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.

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 d78f86f..2eadfa5 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(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(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

Reply via email to