On Wed, Apr 07, 2021 at 10:41:27PM +0200, Clemens Gruber wrote: > On Wed, Apr 07, 2021 at 08:12:29AM +0200, Uwe Kleine-König wrote: > > On Tue, Apr 06, 2021 at 06:41:39PM +0200, Clemens Gruber wrote: > > > Previously, the last used PWM channel could change the global prescale > > > setting, even if other channels are already in use. > > > > > > Fix it by only allowing the first enabled PWM to change the global > > > chip-wide prescale setting. If there is more than one channel in use, > > > the prescale settings resulting from the chosen periods must match. > > > > > > GPIOs do not count as enabled PWMs as they are not using the prescaler > > > and can't change it. > > > > > > Signed-off-by: Clemens Gruber <clemens.gruber@xxxxxxxxxxxx> > > > --- > > > Changes since v6: > > > - Only allow the first PWM that is enabled to change the prescaler, not > > > the first one that uses the prescaler > > > > > > drivers/pwm/pwm-pca9685.c | 66 +++++++++++++++++++++++++++++++++------ > > > 1 file changed, 56 insertions(+), 10 deletions(-) > > > > > > diff --git a/drivers/pwm/pwm-pca9685.c b/drivers/pwm/pwm-pca9685.c > > > index 24221ee7a77a..cf0c98e4ef44 100644 > > > --- a/drivers/pwm/pwm-pca9685.c > > > +++ b/drivers/pwm/pwm-pca9685.c > > > @@ -23,11 +23,11 @@ > > > #include <linux/bitmap.h> > > > > > > /* > > > - * Because the PCA9685 has only one prescaler per chip, changing the period of > > > - * one channel affects the period of all 16 PWM outputs! > > > - * However, the ratio between each configured duty cycle and the chip-wide > > > - * period remains constant, because the OFF time is set in proportion to the > > > - * counter range. > > > + * Because the PCA9685 has only one prescaler per chip, only the first channel > > > + * that is enabled is allowed to change the prescale register. > > > + * PWM channels requested afterwards must use a period that results in the same > > > + * prescale setting as the one set by the first requested channel. > > > + * GPIOs do not count as enabled PWMs as they are not using the prescaler. > > > */ > > > > > > #define PCA9685_MODE1 0x00 > > > @@ -78,8 +78,9 @@ > > > struct pca9685 { > > > struct pwm_chip chip; > > > struct regmap *regmap; > > > -#if IS_ENABLED(CONFIG_GPIOLIB) > > > struct mutex lock; > > > + DECLARE_BITMAP(pwms_enabled, PCA9685_MAXCHAN + 1); > > > +#if IS_ENABLED(CONFIG_GPIOLIB) > > > struct gpio_chip gpio; > > > DECLARE_BITMAP(pwms_inuse, PCA9685_MAXCHAN + 1); > > > #endif > > > @@ -90,6 +91,22 @@ static inline struct pca9685 *to_pca(struct pwm_chip *chip) > > > return container_of(chip, struct pca9685, chip); > > > } > > > > > > +/* This function is supposed to be called with the lock mutex held */ > > > +static bool pca9685_prescaler_can_change(struct pca9685 *pca, int channel) > > > +{ > > > + /* No PWM enabled: Change allowed */ > > > + if (bitmap_empty(pca->pwms_enabled, PCA9685_MAXCHAN + 1)) > > > + return true; > > > + /* More than one PWM enabled: Change not allowed */ > > > + if (bitmap_weight(pca->pwms_enabled, PCA9685_MAXCHAN + 1) > 1) > > > + return false; > > > + /* > > > + * Only one PWM enabled: Change allowed if the PWM about to > > > + * be changed is the one that is already enabled > > > + */ > > > + return test_bit(channel, pca->pwms_enabled); > > > > Maybe this is a bit more effective?: > > > > DECLARE_BITMAP(blablub, PCA9685_MAXCHAN + 1); > > bitmap_zero(blablub, PCA9685_MAXCHAN + 1); > > bitmap_set(blablub, channel); > > return bitmap_subset(pca->pwms_enabled, blablub); > > But if no PWM is enabled, it should return true, not false. If no PWM is enabled we have pca->pwms_enabled = empty set which is a subset of every set. So I'd expect this case to be handled just fine. > > (but that's a minor issue, the suggested algorithm is correct.) > > I would prefer to keep it explicit because it is a little easier to > follow and probably not worth optimizing. I didn't find it hard to follow, but I'm willing to accept that this isn't representative. I'm ok with keeping the code as is. > I agree that it would be nice to drop the ALL channel support. Maybe deprecate it using a config item? But no hurry. Best regards Uwe -- Pengutronix e.K. | Uwe Kleine-König | Industrial Linux Solutions | https://www.pengutronix.de/ |
Attachment:
signature.asc
Description: PGP signature