aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pwm/pwm-atmel.c
diff options
context:
space:
mode:
authorUwe Kleine-König <[email protected]>2019-08-24 00:10:41 +0000
committerThierry Reding <[email protected]>2020-01-08 12:47:46 +0000
commit651b510a74d4e473281efc4eaf2a83963988de48 (patch)
treef72b2cba2e7325e28b480acf2f1eb8ff8af19a4a /drivers/pwm/pwm-atmel.c
parentpwm: atmel: Use register accessors for channels (diff)
downloadkernel-651b510a74d4e473281efc4eaf2a83963988de48.tar.gz
kernel-651b510a74d4e473281efc4eaf2a83963988de48.zip
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 <[email protected]> Acked-by: Claudiu Beznea <[email protected]> Signed-off-by: Thierry Reding <[email protected]>
Diffstat (limited to 'drivers/pwm/pwm-atmel.c')
-rw-r--r--drivers/pwm/pwm-atmel.c40
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,
};