diff options
author | Uwe Kleine-König <uwe@kleine-koenig.org> | 2019-08-24 03:10:41 +0300 |
---|---|---|
committer | Thierry Reding <thierry.reding@gmail.com> | 2020-01-08 15:47:46 +0300 |
commit | 651b510a74d4e473281efc4eaf2a83963988de48 (patch) | |
tree | f72b2cba2e7325e28b480acf2f1eb8ff8af19a4a /drivers/pwm/pwm-atmel.c | |
parent | 02afb811e0cf96958ac69c4b3372088180c829a7 (diff) |
pwm: atmel: Implement .get_state()
This function reads back the configured parameters from the hardware. As
.apply() rounds down (mostly) I'm rounding up in .get_state() to achieve
that applying a state just read from hardware is a no-op.
Signed-off-by: Uwe Kleine-König <uwe@kleine-koenig.org>
Acked-by: Claudiu Beznea <claudiu.beznea@microchip.com>
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
Diffstat (limited to 'drivers/pwm/pwm-atmel.c')
-rw-r--r-- | drivers/pwm/pwm-atmel.c | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/drivers/pwm/pwm-atmel.c b/drivers/pwm/pwm-atmel.c index b8b47c315ac0..6161e7e3e9ac 100644 --- a/drivers/pwm/pwm-atmel.c +++ b/drivers/pwm/pwm-atmel.c @@ -295,8 +295,48 @@ static int atmel_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, return 0; } +static void atmel_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + struct pwm_state *state) +{ + struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip); + u32 sr, cmr; + + sr = atmel_pwm_readl(atmel_pwm, PWM_SR); + cmr = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm, PWM_CMR); + + if (sr & (1 << pwm->hwpwm)) { + unsigned long rate = clk_get_rate(atmel_pwm->clk); + u32 cdty, cprd, pres; + u64 tmp; + + pres = cmr & PWM_CMR_CPRE_MSK; + + cprd = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm, + atmel_pwm->data->regs.period); + tmp = (u64)cprd * NSEC_PER_SEC; + tmp <<= pres; + state->period = DIV64_U64_ROUND_UP(tmp, rate); + + cdty = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm, + atmel_pwm->data->regs.duty); + tmp = (u64)cdty * NSEC_PER_SEC; + tmp <<= pres; + state->duty_cycle = DIV64_U64_ROUND_UP(tmp, rate); + + state->enabled = true; + } else { + state->enabled = false; + } + + if (cmr & PWM_CMR_CPOL) + state->polarity = PWM_POLARITY_INVERSED; + else + state->polarity = PWM_POLARITY_NORMAL; +} + static const struct pwm_ops atmel_pwm_ops = { .apply = atmel_pwm_apply, + .get_state = atmel_pwm_get_state, .owner = THIS_MODULE, }; |