pwm: atmel: Implement .get_state()
authorUwe Kleine-König <uwe@kleine-koenig.org>
Sat, 24 Aug 2019 00:10:41 +0000 (02:10 +0200)
committerThierry Reding <thierry.reding@gmail.com>
Wed, 8 Jan 2020 12:47:46 +0000 (13:47 +0100)
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>
drivers/pwm/pwm-atmel.c

index b8b47c3..6161e7e 100644 (file)
@@ -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,
 };