Re: [PATCH v3 2/2] pwm: sifive: change the PWM controlled LED algorithm

From: Emil Renner Berthing
Date: Thu Apr 20 2023 - 06:04:54 EST


On Thu, 20 Apr 2023 at 11:35, Nylon Chen <nylon.chen@xxxxxxxxxx> wrote:
>
> The `frac` variable represents the pulse inactive time, and the result of
> this algorithm is the pulse active time. Therefore, we must reverse the
> result.
>
> The reference is SiFive FU740-C000 Manual[0]
>
> Link: https://sifive.cdn.prismic.io/sifive/1a82e600-1f93-4f41-b2d8-86ed8b16acba_fu740-c000-manual-v1p6.pdf [0]
>
> Acked-by: Conor Dooley <conor.dooley@xxxxxxxxxxxxx>
> Reviewed-by: Conor Dooley <conor.dooley@xxxxxxxxxxxxx>
> Signed-off-by: Nylon Chen <nylon.chen@xxxxxxxxxx>
> Signed-off-by: Vincent Chen <vincent.chen@xxxxxxxxxx>
> ---
> drivers/pwm/pwm-sifive.c | 9 ++++++---
> 1 file changed, 6 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/pwm/pwm-sifive.c b/drivers/pwm/pwm-sifive.c
> index 393a4b97fc19..d5d5f36da297 100644
> --- a/drivers/pwm/pwm-sifive.c
> +++ b/drivers/pwm/pwm-sifive.c
> @@ -132,13 +132,13 @@ static int pwm_sifive_apply(struct pwm_chip *chip, struct pwm_device *pwm,
> {
> struct pwm_sifive_ddata *ddata = pwm_sifive_chip_to_ddata(chip);
> struct pwm_state cur_state;
> - unsigned int duty_cycle;
> + unsigned int duty_cycle, period;
> unsigned long long num;
> bool enabled;
> int ret = 0;
> u32 frac;
>
> - if (state->polarity != PWM_POLARITY_INVERSED)
> + if (state->polarity != PWM_POLARITY_NORMAL && state->polarity != PWM_POLARITY_INVERSED)
> return -EINVAL;
>
> cur_state = pwm->state;
> @@ -154,10 +154,13 @@ static int pwm_sifive_apply(struct pwm_chip *chip, struct pwm_device *pwm,
> * calculating the register values first and then writing them
> * consecutively
> */
> + period = max(state->period, ddata->approx_period);

Hi Nylon,

I don't understand this patch. You introduce this new variable,
period, and set it here but you never seem to use it. If you planned
to use it instead of state->period below, why should it be the max of
the old period and what is requested? What happens if the consumer
wants to lower the period?

Also above you now allow both PWM_POLARITY_NORMAL and
PWM_POLARITY_INVERSED but you treat both cases the same.

/Emil

> num = (u64)duty_cycle * (1U << PWM_SIFIVE_CMPWIDTH);
> frac = DIV64_U64_ROUND_CLOSEST(num, state->period);
> - /* The hardware cannot generate a 100% duty cycle */
> frac = min(frac, (1U << PWM_SIFIVE_CMPWIDTH) - 1);
> + /* The hardware cannot generate a 100% duty cycle */
> + frac = (1U << PWM_SIFIVE_CMPWIDTH) - 1 - frac;
> +
>
> mutex_lock(&ddata->lock);
> if (state->period != ddata->approx_period) {
> --
> 2.40.0
>