diff options
author | Uwe Kleine-König <u.kleine-koenig@pengutronix.de> | 2021-05-01 18:01:39 +0200 |
---|---|---|
committer | Thierry Reding <thierry.reding@gmail.com> | 2021-06-28 13:28:24 +0200 |
commit | 0ca7acd847665f4554ef133c532b3bd855b7bb7f (patch) | |
tree | c0d8d275353d6357158d63484259947be9c9b380 | |
parent | ec67fba92ebf6249b8155613063e403c695696c6 (diff) |
pwm: tiecap: Implement .apply() callback
To eventually get rid of all legacy drivers convert this driver to the
modern world implementing .apply(). This just pushes down a slightly
optimized variant of how legacy drivers are handled in the core.
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
-rw-r--r-- | drivers/pwm/pwm-tiecap.c | 55 |
1 files changed, 45 insertions, 10 deletions
diff --git a/drivers/pwm/pwm-tiecap.c b/drivers/pwm/pwm-tiecap.c index 027dd0142558..dec3f1fb150c 100644 --- a/drivers/pwm/pwm-tiecap.c +++ b/drivers/pwm/pwm-tiecap.c @@ -48,16 +48,13 @@ static inline struct ecap_pwm_chip *to_ecap_pwm_chip(struct pwm_chip *chip) * duty_ns = 10^9 * duty_cycles / PWM_CLK_RATE */ static int ecap_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, - int duty_ns, int period_ns) + int duty_ns, int period_ns, int enabled) { struct ecap_pwm_chip *pc = to_ecap_pwm_chip(chip); u32 period_cycles, duty_cycles; unsigned long long c; u16 value; - if (period_ns > NSEC_PER_SEC) - return -ERANGE; - c = pc->clk_rate; c = c * period_ns; do_div(c, NSEC_PER_SEC); @@ -82,7 +79,7 @@ static int ecap_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, writew(value, pc->mmio_base + ECCTL2); - if (!pwm_is_enabled(pwm)) { + if (!enabled) { /* Update active registers if not running */ writel(duty_cycles, pc->mmio_base + CAP2); writel(period_cycles, pc->mmio_base + CAP1); @@ -96,7 +93,7 @@ static int ecap_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, writel(period_cycles, pc->mmio_base + CAP3); } - if (!pwm_is_enabled(pwm)) { + if (!enabled) { value = readw(pc->mmio_base + ECCTL2); /* Disable APWM mode to put APWM output Low */ value &= ~ECCTL2_APWM_MODE; @@ -168,11 +165,49 @@ static void ecap_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) pm_runtime_put_sync(pc->chip.dev); } +static int ecap_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + const struct pwm_state *state) +{ + int err; + int enabled = pwm->state.enabled; + + if (state->polarity != pwm->state.polarity) { + + if (enabled) { + ecap_pwm_disable(chip, pwm); + enabled = false; + } + + err = ecap_pwm_set_polarity(chip, pwm, state->polarity); + if (err) + return err; + } + + if (!state->enabled) { + if (enabled) + ecap_pwm_disable(chip, pwm); + return 0; + } + + if (state->period != pwm->state.period || + state->duty_cycle != pwm->state.duty_cycle) { + if (state->period > NSEC_PER_SEC) + return -ERANGE; + + err = ecap_pwm_config(chip, pwm, state->duty_cycle, + state->period, enabled); + if (err) + return err; + } + + if (!enabled) + return ecap_pwm_enable(chip, pwm); + + return 0; +} + static const struct pwm_ops ecap_pwm_ops = { - .config = ecap_pwm_config, - .set_polarity = ecap_pwm_set_polarity, - .enable = ecap_pwm_enable, - .disable = ecap_pwm_disable, + .apply = ecap_pwm_apply, .owner = THIS_MODULE, }; |