diff mbox series

[v2,2/5] pwm: pxa: Set duty cycle to 0 when disabling PWM

Message ID 20221003015546.202308-3-doug@schmorgal.com
State Superseded
Headers show
Series pwm: pxa: Fixes for enable/disable transitions | expand

Commit Message

Doug Brown Oct. 3, 2022, 1:55 a.m. UTC
When disabling PWM, the duty cycle needs to be set to 0. This prevents
the previous duty cycle from showing up momentarily when the clock is
re-enabled next time, and also prevents the output pin from being stuck
high when the clock is disabled.

Because the clock has to be running in order to configure the duty
cycle, unconditionally enable it early in pxa_pwm_apply and account for
the correct enable count at the end.

Suggested-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: Doug Brown <doug@schmorgal.com>
---
 drivers/pwm/pwm-pxa.c | 25 ++++++++++++++++---------
 1 file changed, 16 insertions(+), 9 deletions(-)

Comments

Uwe Kleine-König Oct. 19, 2022, 7:34 a.m. UTC | #1
On Sun, Oct 02, 2022 at 06:55:43PM -0700, Doug Brown wrote:
> When disabling PWM, the duty cycle needs to be set to 0. This prevents
> the previous duty cycle from showing up momentarily when the clock is
> re-enabled next time, and also prevents the output pin from being stuck
> high when the clock is disabled.
> 
> Because the clock has to be running in order to configure the duty
> cycle, unconditionally enable it early in pxa_pwm_apply and account for
> the correct enable count at the end.
> 
> Suggested-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
> Signed-off-by: Doug Brown <doug@schmorgal.com>
> ---
>  drivers/pwm/pwm-pxa.c | 25 ++++++++++++++++---------
>  1 file changed, 16 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/pwm/pwm-pxa.c b/drivers/pwm/pwm-pxa.c
> index 0ac052652c62..9ee9b41d62b8 100644
> --- a/drivers/pwm/pwm-pxa.c
> +++ b/drivers/pwm/pwm-pxa.c
> @@ -105,24 +105,31 @@ static int pxa_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
>  			 const struct pwm_state *state)
>  {
>  	struct pxa_pwm_chip *pc = to_pxa_pwm_chip(chip);
> +	u64 duty_cycle;
>  	int err;
>  
>  	if (state->polarity != PWM_POLARITY_NORMAL)
>  		return -EINVAL;
>  
> -	if (!state->enabled) {
> -		if (pwm->state.enabled)
> -			clk_disable_unprepare(pc->clk);
> +	err = clk_prepare_enable(pc->clk);
> +	if (err)
> +		return err;
>  
> -		return 0;
> -	}
> +	duty_cycle = state->enabled ? state->duty_cycle : 0;
>  
> -	err = pxa_pwm_config(chip, pwm, state->duty_cycle, state->period);
> -	if (err)
> +	err = pxa_pwm_config(chip, pwm, duty_cycle, state->period);
> +	if (err) {
> +		clk_disable_unprepare(pc->clk);
>  		return err;
> +	}
> +
> +	if (state->enabled && !pwm->state.enabled)
> +		return 0;
> +
> +	clk_disable_unprepare(pc->clk);
>  
> -	if (!pwm->state.enabled)
> -		return clk_prepare_enable(pc->clk);
> +	if (!state->enabled && pwm->state.enabled)
> +		clk_disable_unprepare(pc->clk);

Reviewed-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>

Best regards
Uwe
Doug Brown Nov. 13, 2022, 11:15 p.m. UTC | #2
Hi Uwe,

On 10/19/2022 12:34 AM, Uwe Kleine-König wrote:
> On Sun, Oct 02, 2022 at 06:55:43PM -0700, Doug Brown wrote:
>> When disabling PWM, the duty cycle needs to be set to 0. This prevents
>> the previous duty cycle from showing up momentarily when the clock is
>> re-enabled next time, and also prevents the output pin from being stuck
>> high when the clock is disabled.
> 
> Reviewed-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>

It appears I messed up when writing the commit message for this patch,
because I did some more testing today with raw register writes and the
output pin definitely doesn't get stuck high when I disable the clock --
no matter where we are in the PWM cycle. Either way, it still makes
sense to set the duty cycle to 0 first. Just wanted you to know that I'm
not changing the patch at all -- just the commit message -- on v3, so
I'm not carrying over your Reviewed-by tag on v3 of this patch. Sorry
about that!

Doug
diff mbox series

Patch

diff --git a/drivers/pwm/pwm-pxa.c b/drivers/pwm/pwm-pxa.c
index 0ac052652c62..9ee9b41d62b8 100644
--- a/drivers/pwm/pwm-pxa.c
+++ b/drivers/pwm/pwm-pxa.c
@@ -105,24 +105,31 @@  static int pxa_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 			 const struct pwm_state *state)
 {
 	struct pxa_pwm_chip *pc = to_pxa_pwm_chip(chip);
+	u64 duty_cycle;
 	int err;
 
 	if (state->polarity != PWM_POLARITY_NORMAL)
 		return -EINVAL;
 
-	if (!state->enabled) {
-		if (pwm->state.enabled)
-			clk_disable_unprepare(pc->clk);
+	err = clk_prepare_enable(pc->clk);
+	if (err)
+		return err;
 
-		return 0;
-	}
+	duty_cycle = state->enabled ? state->duty_cycle : 0;
 
-	err = pxa_pwm_config(chip, pwm, state->duty_cycle, state->period);
-	if (err)
+	err = pxa_pwm_config(chip, pwm, duty_cycle, state->period);
+	if (err) {
+		clk_disable_unprepare(pc->clk);
 		return err;
+	}
+
+	if (state->enabled && !pwm->state.enabled)
+		return 0;
+
+	clk_disable_unprepare(pc->clk);
 
-	if (!pwm->state.enabled)
-		return clk_prepare_enable(pc->clk);
+	if (!state->enabled && pwm->state.enabled)
+		clk_disable_unprepare(pc->clk);
 
 	return 0;
 }