summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUwe Kleine-König <u.kleine-koenig@pengutronix.de>2022-04-08 17:45:20 +0200
committerThierry Reding <thierry.reding@gmail.com>2022-04-22 18:52:30 +0200
commit4225cd01d30f66b6f35e8f54ba6929db11a9a7af (patch)
treee82cbc2a43c4a1ff5849c6bd3a999edb0e1bd563
parent09f688f0718f57f9cf68ee1aa94490f641e759ba (diff)
downloadlwn-4225cd01d30f66b6f35e8f54ba6929db11a9a7af.tar.gz
lwn-4225cd01d30f66b6f35e8f54ba6929db11a9a7af.zip
pwm: clps71xx: Implement .apply() callback
To eventually get rid of all legacy drivers convert this driver to the modern world implementing .apply(). This fixes a small issue in clps711x_get_duty() en passant: the multiplication v * 0xf might have overflown. Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
-rw-r--r--drivers/pwm/pwm-clps711x.c68
1 files changed, 21 insertions, 47 deletions
diff --git a/drivers/pwm/pwm-clps711x.c b/drivers/pwm/pwm-clps711x.c
index d7ad88685830..b0d91142da8d 100644
--- a/drivers/pwm/pwm-clps711x.c
+++ b/drivers/pwm/pwm-clps711x.c
@@ -23,29 +23,6 @@ static inline struct clps711x_chip *to_clps711x_chip(struct pwm_chip *chip)
return container_of(chip, struct clps711x_chip, chip);
}
-static void clps711x_pwm_update_val(struct clps711x_chip *priv, u32 n, u32 v)
-{
- /* PWM0 - bits 4..7, PWM1 - bits 8..11 */
- u32 shift = (n + 1) * 4;
- unsigned long flags;
- u32 tmp;
-
- spin_lock_irqsave(&priv->lock, flags);
-
- tmp = readl(priv->pmpcon);
- tmp &= ~(0xf << shift);
- tmp |= v << shift;
- writel(tmp, priv->pmpcon);
-
- spin_unlock_irqrestore(&priv->lock, flags);
-}
-
-static unsigned int clps711x_get_duty(struct pwm_device *pwm, unsigned int v)
-{
- /* Duty cycle 0..15 max */
- return DIV64_U64_ROUND_CLOSEST(v * 0xf, pwm->args.period);
-}
-
static int clps711x_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
{
struct clps711x_chip *priv = to_clps711x_chip(chip);
@@ -60,44 +37,41 @@ static int clps711x_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
return 0;
}
-static int clps711x_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
- int duty_ns, int period_ns)
+static int clps711x_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+ const struct pwm_state *state)
{
struct clps711x_chip *priv = to_clps711x_chip(chip);
- unsigned int duty;
+ /* PWM0 - bits 4..7, PWM1 - bits 8..11 */
+ u32 shift = (pwm->hwpwm + 1) * 4;
+ unsigned long flags;
+ u32 pmpcon, val;
- if (period_ns != pwm->args.period)
+ if (state->polarity != PWM_POLARITY_NORMAL)
return -EINVAL;
- duty = clps711x_get_duty(pwm, duty_ns);
- clps711x_pwm_update_val(priv, pwm->hwpwm, duty);
-
- return 0;
-}
+ if (state->period != pwm->args.period)
+ return -EINVAL;
-static int clps711x_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
-{
- struct clps711x_chip *priv = to_clps711x_chip(chip);
- unsigned int duty;
+ if (state->enabled)
+ val = mul_u64_u64_div_u64(state->duty_cycle, 0xf, state->period);
+ else
+ val = 0;
- duty = clps711x_get_duty(pwm, pwm_get_duty_cycle(pwm));
- clps711x_pwm_update_val(priv, pwm->hwpwm, duty);
+ spin_lock_irqsave(&priv->lock, flags);
- return 0;
-}
+ pmpcon = readl(priv->pmpcon);
+ pmpcon &= ~(0xf << shift);
+ pmpcon |= val << shift;
+ writel(pmpcon, priv->pmpcon);
-static void clps711x_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
-{
- struct clps711x_chip *priv = to_clps711x_chip(chip);
+ spin_unlock_irqrestore(&priv->lock, flags);
- clps711x_pwm_update_val(priv, pwm->hwpwm, 0);
+ return 0;
}
static const struct pwm_ops clps711x_pwm_ops = {
.request = clps711x_pwm_request,
- .config = clps711x_pwm_config,
- .enable = clps711x_pwm_enable,
- .disable = clps711x_pwm_disable,
+ .apply = clps711x_pwm_apply,
.owner = THIS_MODULE,
};