Re: [PATCH v5 2/2] pwm: Add Loongson PWM controller support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Uwe:

Thanks for your review.

On Tue, Sep 10, 2024 at 1:00 PM Uwe Kleine-König
<u.kleine-koenig@xxxxxxxxxxxx> wrote:
>
> Hello,
>
> On Wed, Jul 10, 2024 at 10:04:07AM +0800, Binbin Zhou wrote:
> > diff --git a/drivers/pwm/pwm-loongson.c b/drivers/pwm/pwm-loongson.c
> > new file mode 100644
> > index 000000000000..17ab2a2f48ad
> > --- /dev/null
> > +++ b/drivers/pwm/pwm-loongson.c
> > @@ -0,0 +1,285 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +/*
> > + * Loongson PWM driver
> > + *
> > + * Author: Juxin Gao <gaojuxin@xxxxxxxxxxx>
> > + * Further cleanup and restructuring by:
> > + *         Binbin Zhou <zhoubinbin@xxxxxxxxxxx>
> > + *
> > + * Copyright (C) 2017-2024 Loongson Technology Corporation Limited.
> > + *
> > + * Limitations:
> > + * - The buffer register value should be written before the CTRL register.
> > + * - When disabled the output is driven to 0 independent of the configured
> > + *   polarity.
>
> An info about possible glitches and if a period is completed on
> reconfiguration or when the PWM is disabled would be great.
>
> Also if there is a publically available manual, please add a link here.

The descriptions related to our PWM controllers are in the CPU
manuals, e.g. for the Loongson-2K series CPUs. but unfortunately we
only have the Chinese manuals right now, so I don't have a link to
them here.
>
> > + */
> > +
> > [...]
> > +static int pwm_loongson_apply(struct pwm_chip *chip, struct pwm_device *pwm,
> > +                           const struct pwm_state *state)
> > +{
> > +     int ret;
> > +     u64 period, duty_cycle;
> > +     bool enabled = pwm->state.enabled;
> > +
> > +     if (enabled && !state->enabled) {
> > +             pwm_loongson_disable(chip, pwm);
> > +             return 0;
> > +     }
>
> You can also shortcut if !pwm->state.enabled. Something like:
>
>         if (!state->enabled) {
>                 if (enabled)
>                         pwm_loongson_disable(chip, pwm);
>                 return 0;
>         }
>
> > +     if (state->polarity != pwm->state.polarity) {
> > +             ret = pwm_loongson_set_polarity(chip, pwm, state->polarity);
> > +             if (ret)
> > +                     return ret;
> > +     }
>
> Together with the shortcut above this is buggy. Consider:
>
>         pwm_apply_might_sleep(mypwm, &(struct pwm_state){
>                         .period = A,
>                         .duty_cycle = B,
>                         .polarity = PWM_POLARITY_NORMAL,
>                         .enabled = true});
>         pwm_apply_might_sleep(mypwm, &(struct pwm_state){
>                         .period = A,
>                         .duty_cycle = B,
>                         .polarity = PWM_POLARITY_INVERSED,
>                         .enabled = false});
>         pwm_apply_might_sleep(mypwm, &(struct pwm_state){
>                         .period = A,
>                         .duty_cycle = B,
>                         .polarity = PWM_POLARITY_INVERSED,
>                         .enabled = true});
>
> After the 2nd call you left pwm_loongson_apply() early without writing
> the inversed polarity to the register space. In the 3rd call you have
> state->polarity == pwm->state.polarity and so skip configuring the
> polarity again.
>
> I suggest to just do pwm_loongson_set_polarity() unconditionally if
> state->enabled = true.

I check code and try to do it like:

        if (!state->enabled) {
                if (enabled)
                        pwm_loongson_disable(chip, pwm);
                return 0;
        }

        ret = pwm_loongson_set_polarity(chip, pwm, state->polarity);
        if (ret)
                return ret;

Thanks.
Binbin
>
> > +     period = min(state->period, NANOHZ_PER_HZ);
> > +     duty_cycle = min(state->duty_cycle, NANOHZ_PER_HZ);
> > +
> > +     ret = pwm_loongson_config(chip, pwm, duty_cycle, period);
> > +     if (ret)
> > +             return ret;
> > +
> > +     if (!enabled && state->enabled)
> > +             ret = pwm_loongson_enable(chip, pwm);
> > +
> > +     return ret;
> > +}
>
> Best regards
> Uwe





[Index of Archives]     [Device Tree Compilter]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux PCI Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Yosemite Backpacking]


  Powered by Linux