Use the newer apply function of pwm_ops instead of config, enable, disable and set_polarity.
This guarantees atomic changes of the pwm controller configuration. It also reduces the size of the driver. This has been tested on a Raspberry PI 4. v2: Fixed compiler error Signed-off-by: Lino Sanfilippo <linosanfili...@gmx.de> --- drivers/pwm/pwm-bcm2835.c | 64 ++++++++++++++++------------------------------- 1 file changed, 21 insertions(+), 43 deletions(-) diff --git a/drivers/pwm/pwm-bcm2835.c b/drivers/pwm/pwm-bcm2835.c index 6841dcf..dad7443 100644 --- a/drivers/pwm/pwm-bcm2835.c +++ b/drivers/pwm/pwm-bcm2835.c @@ -58,13 +58,14 @@ static void bcm2835_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) writel(value, pc->base + PWM_CONTROL); } -static int bcm2835_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, - int duty_ns, int period_ns) +static int bcm2835_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + const struct pwm_state *state) { + struct bcm2835_pwm *pc = to_bcm2835_pwm(chip); unsigned long rate = clk_get_rate(pc->clk); unsigned long scaler; - u32 period; + u32 value; if (!rate) { dev_err(pc->dev, "failed to get clock rate\n"); @@ -72,65 +73,42 @@ static int bcm2835_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, } scaler = DIV_ROUND_CLOSEST(NSEC_PER_SEC, rate); - period = DIV_ROUND_CLOSEST(period_ns, scaler); + /* set period */ + value = DIV_ROUND_CLOSEST_ULL(state->period, scaler); - if (period < PERIOD_MIN) + if (value < PERIOD_MIN) return -EINVAL; - writel(DIV_ROUND_CLOSEST(duty_ns, scaler), - pc->base + DUTY(pwm->hwpwm)); - writel(period, pc->base + PERIOD(pwm->hwpwm)); - - return 0; -} + writel(value, pc->base + PERIOD(pwm->hwpwm)); -static int bcm2835_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) -{ - struct bcm2835_pwm *pc = to_bcm2835_pwm(chip); - u32 value; + /* set duty cycle */ + value = DIV_ROUND_CLOSEST_ULL(state->duty_cycle, scaler); + writel(value, pc->base + DUTY(pwm->hwpwm)); + /* set polarity */ value = readl(pc->base + PWM_CONTROL); - value |= PWM_ENABLE << PWM_CONTROL_SHIFT(pwm->hwpwm); - writel(value, pc->base + PWM_CONTROL); - - return 0; -} -static void bcm2835_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) -{ - struct bcm2835_pwm *pc = to_bcm2835_pwm(chip); - u32 value; - - value = readl(pc->base + PWM_CONTROL); - value &= ~(PWM_ENABLE << PWM_CONTROL_SHIFT(pwm->hwpwm)); - writel(value, pc->base + PWM_CONTROL); -} - -static int bcm2835_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm, - enum pwm_polarity polarity) -{ - struct bcm2835_pwm *pc = to_bcm2835_pwm(chip); - u32 value; - - value = readl(pc->base + PWM_CONTROL); - - if (polarity == PWM_POLARITY_NORMAL) + if (state->polarity == PWM_POLARITY_NORMAL) value &= ~(PWM_POLARITY << PWM_CONTROL_SHIFT(pwm->hwpwm)); else value |= PWM_POLARITY << PWM_CONTROL_SHIFT(pwm->hwpwm); + /* enable/disable */ + if (state->enabled) + value |= PWM_ENABLE << PWM_CONTROL_SHIFT(pwm->hwpwm); + else + value &= ~(PWM_ENABLE << PWM_CONTROL_SHIFT(pwm->hwpwm)); + writel(value, pc->base + PWM_CONTROL); return 0; } + static const struct pwm_ops bcm2835_pwm_ops = { .request = bcm2835_pwm_request, .free = bcm2835_pwm_free, - .config = bcm2835_pwm_config, - .enable = bcm2835_pwm_enable, - .disable = bcm2835_pwm_disable, - .set_polarity = bcm2835_set_polarity, + .apply = bcm2835_pwm_apply, .owner = THIS_MODULE, }; -- 2.7.4