diff options
author | Ahmad Fatoum <ahmad@a3f.at> | 2020-03-30 16:57:12 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2020-03-31 09:48:34 +0200 |
commit | 91912a0d5576441db1a4c9a03d309258bd49f149 (patch) | |
tree | 8bf435ff2fe7ed945da5a00e94cab123ce50cc22 /drivers/pwm | |
parent | bc2c433d1e52833614b0910c545e8b808407a2f5 (diff) | |
download | barebox-91912a0d5576441db1a4c9a03d309258bd49f149.tar.gz barebox-91912a0d5576441db1a4c9a03d309258bd49f149.tar.xz |
PWM: core: apply initial state in of_pwm_request
This functions prepares a state that can later be tweaked and applied
to the PWM device with pwm_apply_state(). This is a convenient function
that first retrieves the current PWM state and the replaces the period
with the reference values defined in pwm->args.
Once the function returns, you can adjust the ->enabled and ->duty_cycle
fields according to your needs before calling pwm_apply_state().
Signed-off-by: Ahmad Fatoum <ahmad@a3f.at>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/pwm')
-rw-r--r-- | drivers/pwm/core.c | 70 |
1 files changed, 66 insertions, 4 deletions
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index b42b3092a3..9206fc0b9e 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c @@ -20,6 +20,23 @@ #include <linux/list.h> #include <linux/err.h> +/** + * struct pwm_args - board-dependent PWM arguments + * @period_ns: reference period + * + * This structure describes board-dependent arguments attached to a PWM + * device. These arguments are usually retrieved from the PWM lookup table or + * device tree. + * + * Do not confuse this with the PWM state: PWM arguments represent the initial + * configuration that users want to use on this PWM device rather than the + * current PWM hardware state. + */ + +struct pwm_args { + unsigned int period_ns; +}; + struct pwm_device { struct pwm_chip *chip; unsigned long flags; @@ -29,6 +46,7 @@ struct pwm_device { struct device_d dev; struct pwm_state params; + struct pwm_args args; }; static LIST_HEAD(pwm_list); @@ -194,6 +212,7 @@ struct pwm_device *of_pwm_request(struct device_node *np, const char *con_id) struct of_phandle_args args; int index = 0; struct pwm_device *pwm; + struct pwm_state state; int ret; if (con_id) @@ -213,11 +232,17 @@ struct pwm_device *of_pwm_request(struct device_node *np, const char *con_id) } if (args.args_count > 1) - pwm->chip->state.period_ns = args.args[1]; + pwm->args.period_ns = args.args[1]; ret = __pwm_request(pwm); if (ret) - return ERR_PTR(-ret); + return ERR_PTR(ret); + + pwm_init_state(pwm, &state); + + ret = pwm_apply_state(pwm, &state); + if (ret) + return ERR_PTR(ret); return pwm; } @@ -233,13 +258,50 @@ void pwm_free(struct pwm_device *pwm) } EXPORT_SYMBOL_GPL(pwm_free); -void pwm_get_state(const struct pwm_device *pwm, - struct pwm_state *state) +void pwm_get_state(const struct pwm_device *pwm, struct pwm_state *state) { *state = pwm->chip->state; } EXPORT_SYMBOL_GPL(pwm_get_state); +static void pwm_get_args(const struct pwm_device *pwm, struct pwm_args *args) +{ + *args = pwm->args; +} + +/** + * pwm_init_state() - prepare a new state to be applied with pwm_apply_state() + * @pwm: PWM device + * @state: state to fill with the prepared PWM state + * + * This functions prepares a state that can later be tweaked and applied + * to the PWM device with pwm_apply_state(). This is a convenient function + * that first retrieves the current PWM state and the replaces the period + * with the reference values defined in pwm->args. + * Once the function returns, you can adjust the ->enabled and ->duty_cycle + * fields according to your needs before calling pwm_apply_state(). + * + * ->duty_cycle is initially set to zero to avoid cases where the current + * ->duty_cycle value exceed the pwm_args->period one, which would trigger + * an error if the user calls pwm_apply_state() without adjusting ->duty_cycle + * first. + */ +void pwm_init_state(const struct pwm_device *pwm, + struct pwm_state *state) +{ + struct pwm_args args; + + /* First get the current state. */ + pwm_get_state(pwm, state); + + /* Then fill it with the reference config */ + pwm_get_args(pwm, &args); + + state->period_ns = args.period_ns; + state->duty_ns = 0; +} +EXPORT_SYMBOL_GPL(pwm_init_state); + int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state) { struct pwm_chip *chip = pwm->chip; |