From f9a8ee8c8bcd118e800d88772c6457381db45224 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 1 Mar 2021 19:57:19 +0100 Subject: pwm: Always allocate PWM chip base ID dynamically MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit 5e5da1e9fbee ("pwm: ab8500: Explicitly allocate pwm chip base dynamically") all drivers use dynamic ID allocation explicitly. New drivers are supposed to do the same, so remove support for driver specified base IDs and drop all assignments in the low-level drivers. Signed-off-by: Uwe Kleine-König Signed-off-by: Thierry Reding --- drivers/pwm/pwm-atmel.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/pwm/pwm-atmel.c') diff --git a/drivers/pwm/pwm-atmel.c b/drivers/pwm/pwm-atmel.c index 5813339b597b..a4d0be6b265b 100644 --- a/drivers/pwm/pwm-atmel.c +++ b/drivers/pwm/pwm-atmel.c @@ -429,7 +429,6 @@ static int atmel_pwm_probe(struct platform_device *pdev) atmel_pwm->chip.ops = &atmel_pwm_ops; atmel_pwm->chip.of_xlate = of_pwm_xlate_with_flags; atmel_pwm->chip.of_pwm_n_cells = 3; - atmel_pwm->chip.base = -1; atmel_pwm->chip.npwm = 4; ret = pwmchip_add(&atmel_pwm->chip); -- cgit v1.2.3 From 89c6f314602efeecfe8d9093571b3bbfe1029ab5 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 24 Mar 2021 20:56:35 +0100 Subject: pwm: atmel: Free resources only after pwmchip_remove() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before pwmchip_remove() returns the PWM is expected to be functional. So remove the pwmchip before disabling the clock. Signed-off-by: Uwe Kleine-König Acked-by: Claudiu Beznea Signed-off-by: Thierry Reding --- drivers/pwm/pwm-atmel.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/pwm/pwm-atmel.c') diff --git a/drivers/pwm/pwm-atmel.c b/drivers/pwm/pwm-atmel.c index a4d0be6b265b..d49da708337f 100644 --- a/drivers/pwm/pwm-atmel.c +++ b/drivers/pwm/pwm-atmel.c @@ -450,10 +450,12 @@ static int atmel_pwm_remove(struct platform_device *pdev) { struct atmel_pwm_chip *atmel_pwm = platform_get_drvdata(pdev); + pwmchip_remove(&atmel_pwm->chip); + clk_unprepare(atmel_pwm->clk); mutex_destroy(&atmel_pwm->isr_lock); - return pwmchip_remove(&atmel_pwm->chip); + return 0; } static struct platform_driver atmel_pwm_driver = { -- cgit v1.2.3 From 453e8b3d8e36ddcb283b3d1698864a03ea45599a Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Tue, 20 Apr 2021 11:51:17 +0200 Subject: pwm: atmel: Fix duty cycle calculation in .get_state() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The CDTY register contains the number of inactive cycles. .apply() does this correctly, however .get_state() got this wrong. Fixes: 651b510a74d4 ("pwm: atmel: Implement .get_state()") Signed-off-by: Uwe Kleine-König Signed-off-by: Thierry Reding --- drivers/pwm/pwm-atmel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/pwm/pwm-atmel.c') diff --git a/drivers/pwm/pwm-atmel.c b/drivers/pwm/pwm-atmel.c index d49da708337f..ebaeb50dcfde 100644 --- a/drivers/pwm/pwm-atmel.c +++ b/drivers/pwm/pwm-atmel.c @@ -319,7 +319,7 @@ static void atmel_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, cdty = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm, atmel_pwm->data->regs.duty); - tmp = (u64)cdty * NSEC_PER_SEC; + tmp = (u64)(cprd - cdty) * NSEC_PER_SEC; tmp <<= pres; state->duty_cycle = DIV64_U64_ROUND_UP(tmp, rate); -- cgit v1.2.3 From 8035e6c66a5e98f098edf7441667de74affb4e78 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Tue, 20 Apr 2021 11:51:18 +0200 Subject: pwm: atmel: Improve duty cycle calculation in .apply() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the calculation of the register value determining the duty cycle the requested period is used instead of the actually implemented period which results in suboptimal settings. The following example assumes an input clock of 133333333 Hz on one of the SoCs with 16 bit period. When the following state is to be applied: .period = 414727681 .duty_cycle = 652806 the following register values used to be calculated: PRES = 10 CPRD = 54000 CDTY = 53916 which yields an actual duty cycle of a bit more than 645120 ns. The setting PRES = 10 CPRD = 54000 CDTY = 53915 however yields a duty of 652800 ns which is between the current result and the requested value and so is a better approximation. The reason for this error is that for the calculation of CDTY the requested period was used instead of the actually implemented one. Signed-off-by: Uwe Kleine-König Signed-off-by: Thierry Reding --- drivers/pwm/pwm-atmel.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'drivers/pwm/pwm-atmel.c') diff --git a/drivers/pwm/pwm-atmel.c b/drivers/pwm/pwm-atmel.c index ebaeb50dcfde..29b5ad03f715 100644 --- a/drivers/pwm/pwm-atmel.c +++ b/drivers/pwm/pwm-atmel.c @@ -124,6 +124,7 @@ static inline void atmel_pwm_ch_writel(struct atmel_pwm_chip *chip, } static int atmel_pwm_calculate_cprd_and_pres(struct pwm_chip *chip, + unsigned long clkrate, const struct pwm_state *state, unsigned long *cprd, u32 *pres) { @@ -132,7 +133,7 @@ static int atmel_pwm_calculate_cprd_and_pres(struct pwm_chip *chip, int shift; /* Calculate the period cycles and prescale value */ - cycles *= clk_get_rate(atmel_pwm->clk); + cycles *= clkrate; do_div(cycles, NSEC_PER_SEC); /* @@ -158,12 +159,14 @@ static int atmel_pwm_calculate_cprd_and_pres(struct pwm_chip *chip, } static void atmel_pwm_calculate_cdty(const struct pwm_state *state, - unsigned long cprd, unsigned long *cdty) + unsigned long clkrate, unsigned long cprd, + u32 pres, unsigned long *cdty) { unsigned long long cycles = state->duty_cycle; - cycles *= cprd; - do_div(cycles, state->period); + cycles *= clkrate; + do_div(cycles, NSEC_PER_SEC); + cycles >>= pres; *cdty = cprd - cycles; } @@ -244,17 +247,23 @@ static int atmel_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, pwm_get_state(pwm, &cstate); if (state->enabled) { + unsigned long clkrate = clk_get_rate(atmel_pwm->clk); + if (cstate.enabled && cstate.polarity == state->polarity && cstate.period == state->period) { + u32 cmr = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm, PWM_CMR); + cprd = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm, atmel_pwm->data->regs.period); - atmel_pwm_calculate_cdty(state, cprd, &cdty); + pres = cmr & PWM_CMR_CPRE_MSK; + + atmel_pwm_calculate_cdty(state, clkrate, cprd, pres, &cdty); atmel_pwm_update_cdty(chip, pwm, cdty); return 0; } - ret = atmel_pwm_calculate_cprd_and_pres(chip, state, &cprd, + ret = atmel_pwm_calculate_cprd_and_pres(chip, clkrate, state, &cprd, &pres); if (ret) { dev_err(chip->dev, @@ -262,7 +271,7 @@ static int atmel_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, return ret; } - atmel_pwm_calculate_cdty(state, cprd, &cdty); + atmel_pwm_calculate_cdty(state, clkrate, cprd, pres, &cdty); if (cstate.enabled) { atmel_pwm_disable(chip, pwm, false); -- cgit v1.2.3