Linux PWM subsystem development
 help / color / mirror / Atom feed
* [PATCH] pwm: iqs620a: Correct a stale state variable
@ 2021-01-15  5:00 Jeff LaBundy
  2021-01-15  7:45 ` Uwe Kleine-König
  0 siblings, 1 reply; 5+ messages in thread
From: Jeff LaBundy @ 2021-01-15  5:00 UTC (permalink / raw)
  To: thierry.reding; +Cc: u.kleine-koenig, lee.jones, linux-pwm, Jeff LaBundy

If duty cycle is first set to a value that is sufficiently high to
enable the output (e.g. 10000 ns) but then lowered to a value that
is quantized to zero (e.g. 1000 ns), the output is disabled as the
device cannot drive a constant zero (as expected).

However if the device is later re-initialized due to watchdog bite,
the output is re-enabled at the next-to-last duty cycle (10000 ns).
This is because the iqs620_pwm->out_en flag unconditionally tracks
state->enabled instead of what was actually written to the device.

To solve this problem, force the iqs620_pwm->out_en flag to follow
the IQS620_PWR_SETTINGS_PWM_OUT field instead, as was the original
design intent.

Fixes: 6f0841a8197b ("pwm: Add support for Azoteq IQS620A PWM generator")
Signed-off-by: Jeff LaBundy <jeff@labundy.com>
---
 drivers/pwm/pwm-iqs620a.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/pwm/pwm-iqs620a.c b/drivers/pwm/pwm-iqs620a.c
index 5ede825..5eb8fa4 100644
--- a/drivers/pwm/pwm-iqs620a.c
+++ b/drivers/pwm/pwm-iqs620a.c
@@ -79,6 +79,8 @@ static int iqs620_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 					 IQS620_PWR_SETTINGS_PWM_OUT, 0);
 		if (ret)
 			goto err_mutex;
+
+		iqs620_pwm->out_en = false;
 	}
 
 	if (duty_scale) {
@@ -97,9 +99,9 @@ static int iqs620_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 					 IQS620_PWR_SETTINGS_PWM_OUT, 0xff);
 		if (ret)
 			goto err_mutex;
-	}
 
-	iqs620_pwm->out_en = state->enabled;
+		iqs620_pwm->out_en = true;
+	}
 
 err_mutex:
 	mutex_unlock(&iqs620_pwm->lock);
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH] pwm: iqs620a: Correct a stale state variable
  2021-01-15  5:00 [PATCH] pwm: iqs620a: Correct a stale state variable Jeff LaBundy
@ 2021-01-15  7:45 ` Uwe Kleine-König
  2021-01-18  4:30   ` Jeff LaBundy
  0 siblings, 1 reply; 5+ messages in thread
From: Uwe Kleine-König @ 2021-01-15  7:45 UTC (permalink / raw)
  To: Jeff LaBundy; +Cc: thierry.reding, lee.jones, linux-pwm

[-- Attachment #1: Type: text/plain, Size: 2282 bytes --]

On Thu, Jan 14, 2021 at 11:00:34PM -0600, Jeff LaBundy wrote:
> If duty cycle is first set to a value that is sufficiently high to
> enable the output (e.g. 10000 ns) but then lowered to a value that
> is quantized to zero (e.g. 1000 ns), the output is disabled as the
> device cannot drive a constant zero (as expected).
> 
> However if the device is later re-initialized due to watchdog bite,
> the output is re-enabled at the next-to-last duty cycle (10000 ns).
> This is because the iqs620_pwm->out_en flag unconditionally tracks
> state->enabled instead of what was actually written to the device.
> 
> To solve this problem, force the iqs620_pwm->out_en flag to follow
> the IQS620_PWR_SETTINGS_PWM_OUT field instead, as was the original
> design intent.
> 
> Fixes: 6f0841a8197b ("pwm: Add support for Azoteq IQS620A PWM generator")
> Signed-off-by: Jeff LaBundy <jeff@labundy.com>
> ---
>  drivers/pwm/pwm-iqs620a.c | 6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/pwm/pwm-iqs620a.c b/drivers/pwm/pwm-iqs620a.c
> index 5ede825..5eb8fa4 100644
> --- a/drivers/pwm/pwm-iqs620a.c
> +++ b/drivers/pwm/pwm-iqs620a.c
> @@ -79,6 +79,8 @@ static int iqs620_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
>  					 IQS620_PWR_SETTINGS_PWM_OUT, 0);
>  		if (ret)
>  			goto err_mutex;
> +
> +		iqs620_pwm->out_en = false;
>  	}
>  
>  	if (duty_scale) {
> @@ -97,9 +99,9 @@ static int iqs620_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
>  					 IQS620_PWR_SETTINGS_PWM_OUT, 0xff);
>  		if (ret)
>  			goto err_mutex;
> -	}
>  
> -	iqs620_pwm->out_en = state->enabled;
> +		iqs620_pwm->out_en = true;
> +	}

I got the problem and I agree it needs fixing. Are you aware you change
the semantic of out_en here and so the behaviour of .get_state()? IMHO
the change is fine however, and unless I miss something this patch makes
the comment in iqs620_pwm_get_state true.

Other than that I wonder if it would make more sense to track duty_scale
in the driver struct instead of duty_val and out_en.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | https://www.pengutronix.de/ |

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] pwm: iqs620a: Correct a stale state variable
  2021-01-15  7:45 ` Uwe Kleine-König
@ 2021-01-18  4:30   ` Jeff LaBundy
  2021-01-18  8:02     ` Uwe Kleine-König
  0 siblings, 1 reply; 5+ messages in thread
From: Jeff LaBundy @ 2021-01-18  4:30 UTC (permalink / raw)
  To: Uwe Kleine-König; +Cc: thierry.reding, lee.jones, linux-pwm

Hi Uwe,

Thank you for taking a look; actually I came across this problem while
testing your patch, so I owe you even more gratitude :)

On Fri, Jan 15, 2021 at 08:45:09AM +0100, Uwe Kleine-König wrote:
> On Thu, Jan 14, 2021 at 11:00:34PM -0600, Jeff LaBundy wrote:
> > If duty cycle is first set to a value that is sufficiently high to
> > enable the output (e.g. 10000 ns) but then lowered to a value that
> > is quantized to zero (e.g. 1000 ns), the output is disabled as the
> > device cannot drive a constant zero (as expected).
> > 
> > However if the device is later re-initialized due to watchdog bite,
> > the output is re-enabled at the next-to-last duty cycle (10000 ns).
> > This is because the iqs620_pwm->out_en flag unconditionally tracks
> > state->enabled instead of what was actually written to the device.
> > 
> > To solve this problem, force the iqs620_pwm->out_en flag to follow
> > the IQS620_PWR_SETTINGS_PWM_OUT field instead, as was the original
> > design intent.
> > 
> > Fixes: 6f0841a8197b ("pwm: Add support for Azoteq IQS620A PWM generator")
> > Signed-off-by: Jeff LaBundy <jeff@labundy.com>
> > ---
> >  drivers/pwm/pwm-iqs620a.c | 6 ++++--
> >  1 file changed, 4 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/pwm/pwm-iqs620a.c b/drivers/pwm/pwm-iqs620a.c
> > index 5ede825..5eb8fa4 100644
> > --- a/drivers/pwm/pwm-iqs620a.c
> > +++ b/drivers/pwm/pwm-iqs620a.c
> > @@ -79,6 +79,8 @@ static int iqs620_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
> >  					 IQS620_PWR_SETTINGS_PWM_OUT, 0);
> >  		if (ret)
> >  			goto err_mutex;
> > +
> > +		iqs620_pwm->out_en = false;
> >  	}
> >  
> >  	if (duty_scale) {
> > @@ -97,9 +99,9 @@ static int iqs620_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
> >  					 IQS620_PWR_SETTINGS_PWM_OUT, 0xff);
> >  		if (ret)
> >  			goto err_mutex;
> > -	}
> >  
> > -	iqs620_pwm->out_en = state->enabled;
> > +		iqs620_pwm->out_en = true;
> > +	}
> 
> I got the problem and I agree it needs fixing. Are you aware you change
> the semantic of out_en here and so the behaviour of .get_state()? IMHO
> the change is fine however, and unless I miss something this patch makes
> the comment in iqs620_pwm_get_state true.

Agreed on all counts; in fact I saw this as an improvement because the
get_state callback now reflects the actual state of the hardware under
all circumstances.

As you mention, the comment in iqs620_pwm_get_state() is fully correct
now too. Previously it was incorrect in this particular corner case.

> 
> Other than that I wonder if it would make more sense to track duty_scale
> in the driver struct instead of duty_val and out_en.

You would still have to cache state->enabled because it's required for
decoding duty_scale at the time it was cached, so there is not much to
gain. I prefer this solution because the get_state callback is correct
across all cases now, and the change is small.

> 
> Best regards
> Uwe
> 
> -- 
> Pengutronix e.K.                           | Uwe Kleine-König            |
> Industrial Linux Solutions                 | https://www.pengutronix.de/ |

Kind regards,
Jeff LaBundy

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] pwm: iqs620a: Correct a stale state variable
  2021-01-18  4:30   ` Jeff LaBundy
@ 2021-01-18  8:02     ` Uwe Kleine-König
  2021-01-19  2:55       ` Jeff LaBundy
  0 siblings, 1 reply; 5+ messages in thread
From: Uwe Kleine-König @ 2021-01-18  8:02 UTC (permalink / raw)
  To: Jeff LaBundy; +Cc: thierry.reding, lee.jones, linux-pwm, kernel

[-- Attachment #1: Type: text/plain, Size: 3501 bytes --]

Hello Jeff,

On Sun, Jan 17, 2021 at 10:30:05PM -0600, Jeff LaBundy wrote:
> Thank you for taking a look; actually I came across this problem while
> testing your patch, so I owe you even more gratitude :)

:-)

> On Fri, Jan 15, 2021 at 08:45:09AM +0100, Uwe Kleine-König wrote:
> > On Thu, Jan 14, 2021 at 11:00:34PM -0600, Jeff LaBundy wrote:
> > > If duty cycle is first set to a value that is sufficiently high to
> > > enable the output (e.g. 10000 ns) but then lowered to a value that
> > > is quantized to zero (e.g. 1000 ns), the output is disabled as the
> > > device cannot drive a constant zero (as expected).
> > > 
> > > However if the device is later re-initialized due to watchdog bite,
> > > the output is re-enabled at the next-to-last duty cycle (10000 ns).
> > > This is because the iqs620_pwm->out_en flag unconditionally tracks
> > > state->enabled instead of what was actually written to the device.
> > > 
> > > To solve this problem, force the iqs620_pwm->out_en flag to follow
> > > the IQS620_PWR_SETTINGS_PWM_OUT field instead, as was the original
> > > design intent.
> > > 
> > > Fixes: 6f0841a8197b ("pwm: Add support for Azoteq IQS620A PWM generator")
> > > Signed-off-by: Jeff LaBundy <jeff@labundy.com>
> > > ---
> > >  drivers/pwm/pwm-iqs620a.c | 6 ++++--
> > >  1 file changed, 4 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/drivers/pwm/pwm-iqs620a.c b/drivers/pwm/pwm-iqs620a.c
> > > index 5ede825..5eb8fa4 100644
> > > --- a/drivers/pwm/pwm-iqs620a.c
> > > +++ b/drivers/pwm/pwm-iqs620a.c
> > > @@ -79,6 +79,8 @@ static int iqs620_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
> > >  					 IQS620_PWR_SETTINGS_PWM_OUT, 0);
> > >  		if (ret)
> > >  			goto err_mutex;
> > > +
> > > +		iqs620_pwm->out_en = false;
> > >  	}
> > >  
> > >  	if (duty_scale) {
> > > @@ -97,9 +99,9 @@ static int iqs620_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
> > >  					 IQS620_PWR_SETTINGS_PWM_OUT, 0xff);
> > >  		if (ret)
> > >  			goto err_mutex;
> > > -	}
> > >  
> > > -	iqs620_pwm->out_en = state->enabled;
> > > +		iqs620_pwm->out_en = true;
> > > +	}
> > 
> > I got the problem and I agree it needs fixing. Are you aware you change
> > the semantic of out_en here and so the behaviour of .get_state()? IMHO
> > the change is fine however, and unless I miss something this patch makes
> > the comment in iqs620_pwm_get_state true.
> 
> Agreed on all counts; in fact I saw this as an improvement because the
> get_state callback now reflects the actual state of the hardware under
> all circumstances.
> 
> As you mention, the comment in iqs620_pwm_get_state() is fully correct
> now too. Previously it was incorrect in this particular corner case.

ok, I wondered if I missed something.

> > Other than that I wonder if it would make more sense to track duty_scale
> > in the driver struct instead of duty_val and out_en.
> 
> You would still have to cache state->enabled because it's required for
> decoding duty_scale at the time it was cached, so there is not much to
> gain. I prefer this solution because the get_state callback is correct
> across all cases now, and the change is small.

Can't we cope for this by just doing

	if (!state->enabled)
		duty_scale = 0;

?

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | https://www.pengutronix.de/ |

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] pwm: iqs620a: Correct a stale state variable
  2021-01-18  8:02     ` Uwe Kleine-König
@ 2021-01-19  2:55       ` Jeff LaBundy
  0 siblings, 0 replies; 5+ messages in thread
From: Jeff LaBundy @ 2021-01-19  2:55 UTC (permalink / raw)
  To: Uwe Kleine-König; +Cc: thierry.reding, lee.jones, linux-pwm, kernel

Hi Uwe,

On Mon, Jan 18, 2021 at 09:02:19AM +0100, Uwe Kleine-König wrote:
> Hello Jeff,
> 
> On Sun, Jan 17, 2021 at 10:30:05PM -0600, Jeff LaBundy wrote:
> > Thank you for taking a look; actually I came across this problem while
> > testing your patch, so I owe you even more gratitude :)
> 
> :-)
> 
> > On Fri, Jan 15, 2021 at 08:45:09AM +0100, Uwe Kleine-König wrote:
> > > On Thu, Jan 14, 2021 at 11:00:34PM -0600, Jeff LaBundy wrote:
> > > > If duty cycle is first set to a value that is sufficiently high to
> > > > enable the output (e.g. 10000 ns) but then lowered to a value that
> > > > is quantized to zero (e.g. 1000 ns), the output is disabled as the
> > > > device cannot drive a constant zero (as expected).
> > > > 
> > > > However if the device is later re-initialized due to watchdog bite,
> > > > the output is re-enabled at the next-to-last duty cycle (10000 ns).
> > > > This is because the iqs620_pwm->out_en flag unconditionally tracks
> > > > state->enabled instead of what was actually written to the device.
> > > > 
> > > > To solve this problem, force the iqs620_pwm->out_en flag to follow
> > > > the IQS620_PWR_SETTINGS_PWM_OUT field instead, as was the original
> > > > design intent.
> > > > 
> > > > Fixes: 6f0841a8197b ("pwm: Add support for Azoteq IQS620A PWM generator")
> > > > Signed-off-by: Jeff LaBundy <jeff@labundy.com>
> > > > ---
> > > >  drivers/pwm/pwm-iqs620a.c | 6 ++++--
> > > >  1 file changed, 4 insertions(+), 2 deletions(-)
> > > > 
> > > > diff --git a/drivers/pwm/pwm-iqs620a.c b/drivers/pwm/pwm-iqs620a.c
> > > > index 5ede825..5eb8fa4 100644
> > > > --- a/drivers/pwm/pwm-iqs620a.c
> > > > +++ b/drivers/pwm/pwm-iqs620a.c
> > > > @@ -79,6 +79,8 @@ static int iqs620_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
> > > >  					 IQS620_PWR_SETTINGS_PWM_OUT, 0);
> > > >  		if (ret)
> > > >  			goto err_mutex;
> > > > +
> > > > +		iqs620_pwm->out_en = false;
> > > >  	}
> > > >  
> > > >  	if (duty_scale) {
> > > > @@ -97,9 +99,9 @@ static int iqs620_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
> > > >  					 IQS620_PWR_SETTINGS_PWM_OUT, 0xff);
> > > >  		if (ret)
> > > >  			goto err_mutex;
> > > > -	}
> > > >  
> > > > -	iqs620_pwm->out_en = state->enabled;
> > > > +		iqs620_pwm->out_en = true;
> > > > +	}
> > > 
> > > I got the problem and I agree it needs fixing. Are you aware you change
> > > the semantic of out_en here and so the behaviour of .get_state()? IMHO
> > > the change is fine however, and unless I miss something this patch makes
> > > the comment in iqs620_pwm_get_state true.
> > 
> > Agreed on all counts; in fact I saw this as an improvement because the
> > get_state callback now reflects the actual state of the hardware under
> > all circumstances.
> > 
> > As you mention, the comment in iqs620_pwm_get_state() is fully correct
> > now too. Previously it was incorrect in this particular corner case.
> 
> ok, I wondered if I missed something.
> 
> > > Other than that I wonder if it would make more sense to track duty_scale
> > > in the driver struct instead of duty_val and out_en.
> > 
> > You would still have to cache state->enabled because it's required for
> > decoding duty_scale at the time it was cached, so there is not much to
> > gain. I prefer this solution because the get_state callback is correct
> > across all cases now, and the change is small.
> 
> Can't we cope for this by just doing
> 
> 	if (!state->enabled)
> 		duty_scale = 0;
> 
> ?

This is an excellent idea, and simplifies the driver significantly. I'll
send a v2 shortly.

> 
> Best regards
> Uwe
> 
> -- 
> Pengutronix e.K.                           | Uwe Kleine-König            |
> Industrial Linux Solutions                 | https://www.pengutronix.de/ |

Kind regards,
Jeff LaBundy

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2021-01-19  2:56 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-01-15  5:00 [PATCH] pwm: iqs620a: Correct a stale state variable Jeff LaBundy
2021-01-15  7:45 ` Uwe Kleine-König
2021-01-18  4:30   ` Jeff LaBundy
2021-01-18  8:02     ` Uwe Kleine-König
2021-01-19  2:55       ` Jeff LaBundy

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox