diff mbox series

pwm: samsung: Implement .apply() callback

Message ID 20220328073434.44848-1-u.kleine-koenig@pengutronix.de (mailing list archive)
State Accepted
Commit daa986d5f8d8871e6691b0fe54375f263c754d04
Headers show
Series pwm: samsung: Implement .apply() callback | expand

Commit Message

Uwe Kleine-König March 28, 2022, 7:34 a.m. UTC
To eventually get rid of all legacy drivers convert this driver to the
modern world implementing .apply().

The size check for state->period is moved to .apply() to make sure that
the values of state->duty_cycle and state->period are passed to
pwm_samsung_config without change while they are discarded to int.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 drivers/pwm/pwm-samsung.c | 54 ++++++++++++++++++++++++++++++---------
 1 file changed, 42 insertions(+), 12 deletions(-)


base-commit: ed14d36498c8d15be098df4af9ca324f96e9de74

Comments

Krzysztof Kozlowski April 22, 2022, 3:11 p.m. UTC | #1
On 28/03/2022 09:34, Uwe Kleine-König wrote:
> To eventually get rid of all legacy drivers convert this driver to the
> modern world implementing .apply().
> 
> The size check for state->period is moved to .apply() to make sure that
> the values of state->duty_cycle and state->period are passed to
> pwm_samsung_config without change while they are discarded to int.
> 
> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
> ---
>  drivers/pwm/pwm-samsung.c | 54 ++++++++++++++++++++++++++++++---------
>  1 file changed, 42 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/pwm/pwm-samsung.c b/drivers/pwm/pwm-samsung.c
> index 0a4ff55fad04..9c5b4f515641 100644
> --- a/drivers/pwm/pwm-samsung.c
> +++ b/drivers/pwm/pwm-samsung.c
> @@ -321,14 +321,6 @@ static int __pwm_samsung_config(struct pwm_chip *chip, struct pwm_device *pwm,
>  	struct samsung_pwm_channel *chan = pwm_get_chip_data(pwm);
>  	u32 tin_ns = chan->tin_ns, tcnt, tcmp, oldtcmp;
>  
> -	/*
> -	 * We currently avoid using 64bit arithmetic by using the
> -	 * fact that anything faster than 1Hz is easily representable
> -	 * by 32bits.
> -	 */
> -	if (period_ns > NSEC_PER_SEC)
> -		return -ERANGE;
> -
>  	tcnt = readl(our_chip->base + REG_TCNTB(pwm->hwpwm));
>  	oldtcmp = readl(our_chip->base + REG_TCMPB(pwm->hwpwm));
>  
> @@ -438,13 +430,51 @@ static int pwm_samsung_set_polarity(struct pwm_chip *chip,
>  	return 0;
>  }
>  
> +static int pwm_samsung_apply(struct pwm_chip *chip, struct pwm_device *pwm,
> +			     const struct pwm_state *state)
> +{
> +	int err, enabled = pwm->state.enabled;
> +
> +	if (state->polarity != pwm->state.polarity) {
> +		if (enabled) {
> +			pwm_samsung_disable(chip, pwm);
> +			enabled = false;
> +		}
> +
> +		err = pwm_samsung_set_polarity(chip, pwm, state->polarity);
> +		if (err)
> +			return err;
> +	}
> +
> +	if (!state->enabled) {
> +		if (enabled)
> +			pwm_samsung_disable(chip, pwm);
> +
> +		return 0;
> +	}
> +
> +	/*
> +	 * We currently avoid using 64bit arithmetic by using the
> +	 * fact that anything faster than 1Hz is easily representable
> +	 * by 32bits.
> +	 */
> +	if (state->period > NSEC_PER_SEC)

Isn't this changing a bit logic in case of setting wrong period and
inverted signal?

Before, the config would return early and do nothing. Now, you disable
the PWM, check the condition here and exit with PWM disabled. I think
this should reverse the tasks done, or the check should be done early.

> +		return -ERANGE;
> +
> +	err = pwm_samsung_config(chip, pwm, state->duty_cycle, state->period);
> +	if (err)
> +		return err;

Best regards,
Krzysztof
Uwe Kleine-König April 25, 2022, 5:16 p.m. UTC | #2
On Fri, Apr 22, 2022 at 05:11:02PM +0200, Krzysztof Kozlowski wrote:
> On 28/03/2022 09:34, Uwe Kleine-König wrote:
> > To eventually get rid of all legacy drivers convert this driver to the
> > modern world implementing .apply().
> > 
> > The size check for state->period is moved to .apply() to make sure that
> > the values of state->duty_cycle and state->period are passed to
> > pwm_samsung_config without change while they are discarded to int.
> > 
> > Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
> > ---
> >  drivers/pwm/pwm-samsung.c | 54 ++++++++++++++++++++++++++++++---------
> >  1 file changed, 42 insertions(+), 12 deletions(-)
> > 
> > diff --git a/drivers/pwm/pwm-samsung.c b/drivers/pwm/pwm-samsung.c
> > index 0a4ff55fad04..9c5b4f515641 100644
> > --- a/drivers/pwm/pwm-samsung.c
> > +++ b/drivers/pwm/pwm-samsung.c
> > @@ -321,14 +321,6 @@ static int __pwm_samsung_config(struct pwm_chip *chip, struct pwm_device *pwm,
> >  	struct samsung_pwm_channel *chan = pwm_get_chip_data(pwm);
> >  	u32 tin_ns = chan->tin_ns, tcnt, tcmp, oldtcmp;
> >  
> > -	/*
> > -	 * We currently avoid using 64bit arithmetic by using the
> > -	 * fact that anything faster than 1Hz is easily representable
> > -	 * by 32bits.
> > -	 */
> > -	if (period_ns > NSEC_PER_SEC)
> > -		return -ERANGE;
> > -
> >  	tcnt = readl(our_chip->base + REG_TCNTB(pwm->hwpwm));
> >  	oldtcmp = readl(our_chip->base + REG_TCMPB(pwm->hwpwm));
> >  
> > @@ -438,13 +430,51 @@ static int pwm_samsung_set_polarity(struct pwm_chip *chip,
> >  	return 0;
> >  }
> >  
> > +static int pwm_samsung_apply(struct pwm_chip *chip, struct pwm_device *pwm,
> > +			     const struct pwm_state *state)
> > +{
> > +	int err, enabled = pwm->state.enabled;
> > +
> > +	if (state->polarity != pwm->state.polarity) {
> > +		if (enabled) {
> > +			pwm_samsung_disable(chip, pwm);
> > +			enabled = false;
> > +		}
> > +
> > +		err = pwm_samsung_set_polarity(chip, pwm, state->polarity);
> > +		if (err)
> > +			return err;
> > +	}
> > +
> > +	if (!state->enabled) {
> > +		if (enabled)
> > +			pwm_samsung_disable(chip, pwm);
> > +
> > +		return 0;
> > +	}
> > +
> > +	/*
> > +	 * We currently avoid using 64bit arithmetic by using the
> > +	 * fact that anything faster than 1Hz is easily representable
> > +	 * by 32bits.
> > +	 */
> > +	if (state->period > NSEC_PER_SEC)
> 
> Isn't this changing a bit logic in case of setting wrong period and
> inverted signal?
> 
> Before, the config would return early and do nothing. Now, you disable
> the PWM, check the condition here and exit with PWM disabled. I think
> this should reverse the tasks done, or the check should be done early.

The intension here is to just push the legacy implementation of .apply()
(i.e.  pwm_apply_legacy()) into the driver, to be able to get rid of the
legacy handing in the core. I think the problem you point out is real,
but it is not introduced by my change which doesn't change behaviour.

The problem is just that it's not possible to "see" that period is
invalid at the time the polarity is changed and so it exists since at
least 5ec803edcb703fe379836f13560b79dfac79b01d, my patch just made it
more obvious.

So yes, there is potential to further improve the driver, but that's out
of scope for this 1:1 conversion patch.

Best regards
Uwe
Krzysztof Kozlowski April 25, 2022, 5:50 p.m. UTC | #3
On 25/04/2022 19:16, Uwe Kleine-König wrote:

>>> +	/*
>>> +	 * We currently avoid using 64bit arithmetic by using the
>>> +	 * fact that anything faster than 1Hz is easily representable
>>> +	 * by 32bits.
>>> +	 */
>>> +	if (state->period > NSEC_PER_SEC)
>>
>> Isn't this changing a bit logic in case of setting wrong period and
>> inverted signal?
>>
>> Before, the config would return early and do nothing. Now, you disable
>> the PWM, check the condition here and exit with PWM disabled. I think
>> this should reverse the tasks done, or the check should be done early.
> 
> The intension here is to just push the legacy implementation of .apply()
> (i.e.  pwm_apply_legacy()) into the driver, to be able to get rid of the
> legacy handing in the core. I think the problem you point out is real,
> but it is not introduced by my change which doesn't change behaviour.
> 
> The problem is just that it's not possible to "see" that period is
> invalid at the time the polarity is changed and so it exists since at
> least 5ec803edcb703fe379836f13560b79dfac79b01d, my patch just made it
> more obvious.
> 
> So yes, there is potential to further improve the driver, but that's out
> of scope for this 1:1 conversion patch.

Sounds reasonable, thanks for explanation. Everything else was looking
good, so:

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>




Best regards,
Krzysztof
Thierry Reding May 20, 2022, 1:59 p.m. UTC | #4
On Mon, Mar 28, 2022 at 09:34:34AM +0200, Uwe Kleine-König wrote:
> To eventually get rid of all legacy drivers convert this driver to the
> modern world implementing .apply().
> 
> The size check for state->period is moved to .apply() to make sure that
> the values of state->duty_cycle and state->period are passed to
> pwm_samsung_config without change while they are discarded to int.
> 
> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
> ---
>  drivers/pwm/pwm-samsung.c | 54 ++++++++++++++++++++++++++++++---------
>  1 file changed, 42 insertions(+), 12 deletions(-)

Applied, thanks.

Thierry
diff mbox series

Patch

diff --git a/drivers/pwm/pwm-samsung.c b/drivers/pwm/pwm-samsung.c
index 0a4ff55fad04..9c5b4f515641 100644
--- a/drivers/pwm/pwm-samsung.c
+++ b/drivers/pwm/pwm-samsung.c
@@ -321,14 +321,6 @@  static int __pwm_samsung_config(struct pwm_chip *chip, struct pwm_device *pwm,
 	struct samsung_pwm_channel *chan = pwm_get_chip_data(pwm);
 	u32 tin_ns = chan->tin_ns, tcnt, tcmp, oldtcmp;
 
-	/*
-	 * We currently avoid using 64bit arithmetic by using the
-	 * fact that anything faster than 1Hz is easily representable
-	 * by 32bits.
-	 */
-	if (period_ns > NSEC_PER_SEC)
-		return -ERANGE;
-
 	tcnt = readl(our_chip->base + REG_TCNTB(pwm->hwpwm));
 	oldtcmp = readl(our_chip->base + REG_TCMPB(pwm->hwpwm));
 
@@ -438,13 +430,51 @@  static int pwm_samsung_set_polarity(struct pwm_chip *chip,
 	return 0;
 }
 
+static int pwm_samsung_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+			     const struct pwm_state *state)
+{
+	int err, enabled = pwm->state.enabled;
+
+	if (state->polarity != pwm->state.polarity) {
+		if (enabled) {
+			pwm_samsung_disable(chip, pwm);
+			enabled = false;
+		}
+
+		err = pwm_samsung_set_polarity(chip, pwm, state->polarity);
+		if (err)
+			return err;
+	}
+
+	if (!state->enabled) {
+		if (enabled)
+			pwm_samsung_disable(chip, pwm);
+
+		return 0;
+	}
+
+	/*
+	 * We currently avoid using 64bit arithmetic by using the
+	 * fact that anything faster than 1Hz is easily representable
+	 * by 32bits.
+	 */
+	if (state->period > NSEC_PER_SEC)
+		return -ERANGE;
+
+	err = pwm_samsung_config(chip, pwm, state->duty_cycle, state->period);
+	if (err)
+		return err;
+
+	if (!pwm->state.enabled)
+		err = pwm_samsung_enable(chip, pwm);
+
+	return err;
+}
+
 static const struct pwm_ops pwm_samsung_ops = {
 	.request	= pwm_samsung_request,
 	.free		= pwm_samsung_free,
-	.enable		= pwm_samsung_enable,
-	.disable	= pwm_samsung_disable,
-	.config		= pwm_samsung_config,
-	.set_polarity	= pwm_samsung_set_polarity,
+	.apply		= pwm_samsung_apply,
 	.owner		= THIS_MODULE,
 };