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