cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

pwm.c (7705B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * PWM Greybus driver.
      4 *
      5 * Copyright 2014 Google Inc.
      6 * Copyright 2014 Linaro Ltd.
      7 */
      8
      9#include <linux/kernel.h>
     10#include <linux/module.h>
     11#include <linux/slab.h>
     12#include <linux/pwm.h>
     13#include <linux/greybus.h>
     14
     15#include "gbphy.h"
     16
     17struct gb_pwm_chip {
     18	struct gb_connection	*connection;
     19	u8			pwm_max;	/* max pwm number */
     20
     21	struct pwm_chip		chip;
     22	struct pwm_chip		*pwm;
     23};
     24#define pwm_chip_to_gb_pwm_chip(chip) \
     25	container_of(chip, struct gb_pwm_chip, chip)
     26
     27
     28static int gb_pwm_count_operation(struct gb_pwm_chip *pwmc)
     29{
     30	struct gb_pwm_count_response response;
     31	int ret;
     32
     33	ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_PWM_COUNT,
     34				NULL, 0, &response, sizeof(response));
     35	if (ret)
     36		return ret;
     37	pwmc->pwm_max = response.count;
     38	return 0;
     39}
     40
     41static int gb_pwm_activate_operation(struct gb_pwm_chip *pwmc,
     42				     u8 which)
     43{
     44	struct gb_pwm_activate_request request;
     45	struct gbphy_device *gbphy_dev;
     46	int ret;
     47
     48	if (which > pwmc->pwm_max)
     49		return -EINVAL;
     50
     51	request.which = which;
     52
     53	gbphy_dev = to_gbphy_dev(pwmc->chip.dev);
     54	ret = gbphy_runtime_get_sync(gbphy_dev);
     55	if (ret)
     56		return ret;
     57
     58	ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_ACTIVATE,
     59				&request, sizeof(request), NULL, 0);
     60
     61	gbphy_runtime_put_autosuspend(gbphy_dev);
     62
     63	return ret;
     64}
     65
     66static int gb_pwm_deactivate_operation(struct gb_pwm_chip *pwmc,
     67				       u8 which)
     68{
     69	struct gb_pwm_deactivate_request request;
     70	struct gbphy_device *gbphy_dev;
     71	int ret;
     72
     73	if (which > pwmc->pwm_max)
     74		return -EINVAL;
     75
     76	request.which = which;
     77
     78	gbphy_dev = to_gbphy_dev(pwmc->chip.dev);
     79	ret = gbphy_runtime_get_sync(gbphy_dev);
     80	if (ret)
     81		return ret;
     82
     83	ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_DEACTIVATE,
     84				&request, sizeof(request), NULL, 0);
     85
     86	gbphy_runtime_put_autosuspend(gbphy_dev);
     87
     88	return ret;
     89}
     90
     91static int gb_pwm_config_operation(struct gb_pwm_chip *pwmc,
     92				   u8 which, u32 duty, u32 period)
     93{
     94	struct gb_pwm_config_request request;
     95	struct gbphy_device *gbphy_dev;
     96	int ret;
     97
     98	if (which > pwmc->pwm_max)
     99		return -EINVAL;
    100
    101	request.which = which;
    102	request.duty = cpu_to_le32(duty);
    103	request.period = cpu_to_le32(period);
    104
    105	gbphy_dev = to_gbphy_dev(pwmc->chip.dev);
    106	ret = gbphy_runtime_get_sync(gbphy_dev);
    107	if (ret)
    108		return ret;
    109
    110	ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_CONFIG,
    111				&request, sizeof(request), NULL, 0);
    112
    113	gbphy_runtime_put_autosuspend(gbphy_dev);
    114
    115	return ret;
    116}
    117
    118static int gb_pwm_set_polarity_operation(struct gb_pwm_chip *pwmc,
    119					 u8 which, u8 polarity)
    120{
    121	struct gb_pwm_polarity_request request;
    122	struct gbphy_device *gbphy_dev;
    123	int ret;
    124
    125	if (which > pwmc->pwm_max)
    126		return -EINVAL;
    127
    128	request.which = which;
    129	request.polarity = polarity;
    130
    131	gbphy_dev = to_gbphy_dev(pwmc->chip.dev);
    132	ret = gbphy_runtime_get_sync(gbphy_dev);
    133	if (ret)
    134		return ret;
    135
    136	ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_POLARITY,
    137				&request, sizeof(request), NULL, 0);
    138
    139	gbphy_runtime_put_autosuspend(gbphy_dev);
    140
    141	return ret;
    142}
    143
    144static int gb_pwm_enable_operation(struct gb_pwm_chip *pwmc,
    145				   u8 which)
    146{
    147	struct gb_pwm_enable_request request;
    148	struct gbphy_device *gbphy_dev;
    149	int ret;
    150
    151	if (which > pwmc->pwm_max)
    152		return -EINVAL;
    153
    154	request.which = which;
    155
    156	gbphy_dev = to_gbphy_dev(pwmc->chip.dev);
    157	ret = gbphy_runtime_get_sync(gbphy_dev);
    158	if (ret)
    159		return ret;
    160
    161	ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_ENABLE,
    162				&request, sizeof(request), NULL, 0);
    163	if (ret)
    164		gbphy_runtime_put_autosuspend(gbphy_dev);
    165
    166	return ret;
    167}
    168
    169static int gb_pwm_disable_operation(struct gb_pwm_chip *pwmc,
    170				    u8 which)
    171{
    172	struct gb_pwm_disable_request request;
    173	struct gbphy_device *gbphy_dev;
    174	int ret;
    175
    176	if (which > pwmc->pwm_max)
    177		return -EINVAL;
    178
    179	request.which = which;
    180
    181	ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_DISABLE,
    182				&request, sizeof(request), NULL, 0);
    183
    184	gbphy_dev = to_gbphy_dev(pwmc->chip.dev);
    185	gbphy_runtime_put_autosuspend(gbphy_dev);
    186
    187	return ret;
    188}
    189
    190static int gb_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
    191{
    192	struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip);
    193
    194	return gb_pwm_activate_operation(pwmc, pwm->hwpwm);
    195};
    196
    197static void gb_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
    198{
    199	struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip);
    200
    201	if (pwm_is_enabled(pwm))
    202		dev_warn(chip->dev, "freeing PWM device without disabling\n");
    203
    204	gb_pwm_deactivate_operation(pwmc, pwm->hwpwm);
    205}
    206
    207static int gb_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
    208			const struct pwm_state *state)
    209{
    210	int err;
    211	bool enabled = pwm->state.enabled;
    212	u64 period = state->period;
    213	u64 duty_cycle = state->duty_cycle;
    214	struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip);
    215
    216	/* Set polarity */
    217	if (state->polarity != pwm->state.polarity) {
    218		if (enabled) {
    219			gb_pwm_disable_operation(pwmc, pwm->hwpwm);
    220			enabled = false;
    221		}
    222		err = gb_pwm_set_polarity_operation(pwmc, pwm->hwpwm, state->polarity);
    223		if (err)
    224			return err;
    225	}
    226
    227	if (!state->enabled) {
    228		if (enabled)
    229			gb_pwm_disable_operation(pwmc, pwm->hwpwm);
    230		return 0;
    231	}
    232
    233	/*
    234	 * Set period and duty cycle
    235	 *
    236	 * PWM privodes 64-bit period and duty_cycle, but greybus only accepts
    237	 * 32-bit, so their values have to be limited to U32_MAX.
    238	 */
    239	if (period > U32_MAX)
    240		period = U32_MAX;
    241
    242	if (duty_cycle > period)
    243		duty_cycle = period;
    244
    245	err = gb_pwm_config_operation(pwmc, pwm->hwpwm, duty_cycle, period);
    246	if (err)
    247		return err;
    248
    249	/* enable/disable */
    250	if (!enabled)
    251		return gb_pwm_enable_operation(pwmc, pwm->hwpwm);
    252
    253	return 0;
    254}
    255
    256static const struct pwm_ops gb_pwm_ops = {
    257	.request = gb_pwm_request,
    258	.free = gb_pwm_free,
    259	.apply = gb_pwm_apply,
    260	.owner = THIS_MODULE,
    261};
    262
    263static int gb_pwm_probe(struct gbphy_device *gbphy_dev,
    264			const struct gbphy_device_id *id)
    265{
    266	struct gb_connection *connection;
    267	struct gb_pwm_chip *pwmc;
    268	struct pwm_chip *pwm;
    269	int ret;
    270
    271	pwmc = kzalloc(sizeof(*pwmc), GFP_KERNEL);
    272	if (!pwmc)
    273		return -ENOMEM;
    274
    275	connection = gb_connection_create(gbphy_dev->bundle,
    276					  le16_to_cpu(gbphy_dev->cport_desc->id),
    277					  NULL);
    278	if (IS_ERR(connection)) {
    279		ret = PTR_ERR(connection);
    280		goto exit_pwmc_free;
    281	}
    282
    283	pwmc->connection = connection;
    284	gb_connection_set_data(connection, pwmc);
    285	gb_gbphy_set_data(gbphy_dev, pwmc);
    286
    287	ret = gb_connection_enable(connection);
    288	if (ret)
    289		goto exit_connection_destroy;
    290
    291	/* Query number of pwms present */
    292	ret = gb_pwm_count_operation(pwmc);
    293	if (ret)
    294		goto exit_connection_disable;
    295
    296	pwm = &pwmc->chip;
    297
    298	pwm->dev = &gbphy_dev->dev;
    299	pwm->ops = &gb_pwm_ops;
    300	pwm->npwm = pwmc->pwm_max + 1;
    301
    302	ret = pwmchip_add(pwm);
    303	if (ret) {
    304		dev_err(&gbphy_dev->dev,
    305			"failed to register PWM: %d\n", ret);
    306		goto exit_connection_disable;
    307	}
    308
    309	gbphy_runtime_put_autosuspend(gbphy_dev);
    310	return 0;
    311
    312exit_connection_disable:
    313	gb_connection_disable(connection);
    314exit_connection_destroy:
    315	gb_connection_destroy(connection);
    316exit_pwmc_free:
    317	kfree(pwmc);
    318	return ret;
    319}
    320
    321static void gb_pwm_remove(struct gbphy_device *gbphy_dev)
    322{
    323	struct gb_pwm_chip *pwmc = gb_gbphy_get_data(gbphy_dev);
    324	struct gb_connection *connection = pwmc->connection;
    325	int ret;
    326
    327	ret = gbphy_runtime_get_sync(gbphy_dev);
    328	if (ret)
    329		gbphy_runtime_get_noresume(gbphy_dev);
    330
    331	pwmchip_remove(&pwmc->chip);
    332	gb_connection_disable(connection);
    333	gb_connection_destroy(connection);
    334	kfree(pwmc);
    335}
    336
    337static const struct gbphy_device_id gb_pwm_id_table[] = {
    338	{ GBPHY_PROTOCOL(GREYBUS_PROTOCOL_PWM) },
    339	{ },
    340};
    341MODULE_DEVICE_TABLE(gbphy, gb_pwm_id_table);
    342
    343static struct gbphy_driver pwm_driver = {
    344	.name		= "pwm",
    345	.probe		= gb_pwm_probe,
    346	.remove		= gb_pwm_remove,
    347	.id_table	= gb_pwm_id_table,
    348};
    349
    350module_gbphy_driver(pwm_driver);
    351MODULE_LICENSE("GPL v2");