Hello Miquel, On Sun, May 03, 2020 at 12:54:53PM +0200, Miquel Raynal wrote: > +static u8 max7313_pwm_get_intensity(struct pca953x_chip *pca_chip, > + unsigned int idx) > +{ > + struct device *dev = &pca_chip->client->dev; > + unsigned int reg, shift, val, output; > + u8 intensity; > + bool phase; > + int ret; > + > + /* Retrieve the intensity */ > + reg = MAX7313_INTENSITY + (idx / PWM_PER_REG); > + shift = (idx % PWM_PER_REG) ? PWM_BITS_PER_REG : 0; I would find shift = (idx % PWM_PER_REG) * PWM_BITS_PER_REG more natural here as your formula only works for PWM_PER_REG = 2. > + mutex_lock(&pca_chip->i2c_lock); > + ret = regmap_read(pca_chip->regmap, reg, &val); > + mutex_unlock(&pca_chip->i2c_lock); > + if (ret < 0) { > + dev_err(dev, "Cannot retrieve PWM intensity (%d)\n", ret); Please use %pe for error codes. > + return 0; > + } > + > + val >>= shift; > + val &= PWM_INTENSITY_MASK; > + > + /* Retrieve the phase */ > + reg = pca953x_recalc_addr(pca_chip, pca_chip->regs->output, idx, 0, 0); > + > + mutex_lock(&pca_chip->i2c_lock); > + ret = regmap_read(pca_chip->regmap, reg, &output); > + mutex_unlock(&pca_chip->i2c_lock); > + if (ret < 0) { > + dev_err(dev, "Cannot retrieve PWM phase (%d)\n", ret); > + return 0; > + } > + > + phase = output & BIT(idx % BANK_SZ); Would it make sense to cache the phase value to reduce register access and locking here? > [...] > +static int max7313_pwm_apply(struct pwm_chip *chip, > + struct pwm_device *pwm, > + const struct pwm_state *state) > +{ > + struct max7313_pwm *max_pwm = to_max7313_pwm(chip); > + struct pca953x_chip *pca_chip = to_pca953x(max_pwm); > + unsigned int intensity, active; > + int ret = 0; > + > + if (!state->enabled || > + state->period < PWM_PERIOD_NS || > + state->polarity != PWM_POLARITY_NORMAL) > + return -EINVAL; You could simulate state->enabled = false using duty_cycle = 0. > + /* Convert the duty-cycle to be in the [0;16] range */ > + intensity = max7313_pwm_duty_to_intensity(state->duty_cycle); This might return a value > 16 if state->duty_cycle > PWM_PERIOD_NS. I suggest to do duty_cycle = min(state->duty_cycle, PWM_PERIOD_NS); and use that value instead of state->duty_cycle. > + /* > + * The hardware is supposedly glitch-free when changing the intensity, > + * unless we need to flip the blink phase to reach an extremity or the > + * other of the spectrum (0/16 from phase 1, 16/16 from phase 0). s/other of/other end of/. I don't understand the difference between extremity and "other end of the spectrum". > + */ > + return max7313_pwm_set_state(pca_chip, pwm, intensity); > +} > + > +static void max7313_pwm_get_state(struct pwm_chip *chip, > + struct pwm_device *pwm, > + struct pwm_state *state) > +{ > + struct max7313_pwm *max_pwm = to_max7313_pwm(chip); > + struct pca953x_chip *pca_chip = to_pca953x(max_pwm); > + u8 intensity; > + > + state->enabled = true; > + state->period = PWM_PERIOD_NS; > + state->polarity = PWM_POLARITY_NORMAL; > + > + intensity = max7313_pwm_get_intensity(pca_chip, pwm->hwpwm); > + state->duty_cycle = max7313_pwm_intensity_to_duty(intensity); Please round up the division in max7313_pwm_intensity_to_duty(). (The reasoning is: with rounding down the following can happen: /* this configures for 15/16 */ pwm_apply_state(pwm, { .duty_cycle = 31249, .period = 31250 }); /* assume this called your .get_state callback */ pwm_get_state(pwm, &state); /* * we now have * state.duty_cycle = 29296; * state.period = 31250; * right? */ /* this configures for 14/16 because 29296 * 16 / 31250 < 15 */ pwm_apply_state(pwm, &state); But I want this to be idempotent, i.e. pwm_get_state has to round up and then return .duty_cycle = 29297 in the above example which is enough to let .apply_state() configure 15/16 again. Enabling PWM_DEBUG should catch this.) > +}; Best regards Uwe -- Pengutronix e.K. | Uwe Kleine-König | Industrial Linux Solutions | https://www.pengutronix.de/ |