Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Uwe Kleine-König and committed by
Thierry Reding
4225cd01 09f688f0

+24 -50
+24 -50
drivers/pwm/pwm-clps711x.c
··· 23 23 return container_of(chip, struct clps711x_chip, chip); 24 24 } 25 25 26 - static void clps711x_pwm_update_val(struct clps711x_chip *priv, u32 n, u32 v) 27 - { 28 - /* PWM0 - bits 4..7, PWM1 - bits 8..11 */ 29 - u32 shift = (n + 1) * 4; 30 - unsigned long flags; 31 - u32 tmp; 32 - 33 - spin_lock_irqsave(&priv->lock, flags); 34 - 35 - tmp = readl(priv->pmpcon); 36 - tmp &= ~(0xf << shift); 37 - tmp |= v << shift; 38 - writel(tmp, priv->pmpcon); 39 - 40 - spin_unlock_irqrestore(&priv->lock, flags); 41 - } 42 - 43 - static unsigned int clps711x_get_duty(struct pwm_device *pwm, unsigned int v) 44 - { 45 - /* Duty cycle 0..15 max */ 46 - return DIV64_U64_ROUND_CLOSEST(v * 0xf, pwm->args.period); 47 - } 48 - 49 26 static int clps711x_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) 50 27 { 51 28 struct clps711x_chip *priv = to_clps711x_chip(chip); ··· 37 60 return 0; 38 61 } 39 62 40 - static int clps711x_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, 41 - int duty_ns, int period_ns) 63 + static int clps711x_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, 64 + const struct pwm_state *state) 42 65 { 43 66 struct clps711x_chip *priv = to_clps711x_chip(chip); 44 - unsigned int duty; 67 + /* PWM0 - bits 4..7, PWM1 - bits 8..11 */ 68 + u32 shift = (pwm->hwpwm + 1) * 4; 69 + unsigned long flags; 70 + u32 pmpcon, val; 45 71 46 - if (period_ns != pwm->args.period) 72 + if (state->polarity != PWM_POLARITY_NORMAL) 47 73 return -EINVAL; 48 74 49 - duty = clps711x_get_duty(pwm, duty_ns); 50 - clps711x_pwm_update_val(priv, pwm->hwpwm, duty); 75 + if (state->period != pwm->args.period) 76 + return -EINVAL; 77 + 78 + if (state->enabled) 79 + val = mul_u64_u64_div_u64(state->duty_cycle, 0xf, state->period); 80 + else 81 + val = 0; 82 + 83 + spin_lock_irqsave(&priv->lock, flags); 84 + 85 + pmpcon = readl(priv->pmpcon); 86 + pmpcon &= ~(0xf << shift); 87 + pmpcon |= val << shift; 88 + writel(pmpcon, priv->pmpcon); 89 + 90 + spin_unlock_irqrestore(&priv->lock, flags); 51 91 52 92 return 0; 53 - } 54 - 55 - static int clps711x_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) 56 - { 57 - struct clps711x_chip *priv = to_clps711x_chip(chip); 58 - unsigned int duty; 59 - 60 - duty = clps711x_get_duty(pwm, pwm_get_duty_cycle(pwm)); 61 - clps711x_pwm_update_val(priv, pwm->hwpwm, duty); 62 - 63 - return 0; 64 - } 65 - 66 - static void clps711x_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) 67 - { 68 - struct clps711x_chip *priv = to_clps711x_chip(chip); 69 - 70 - clps711x_pwm_update_val(priv, pwm->hwpwm, 0); 71 93 } 72 94 73 95 static const struct pwm_ops clps711x_pwm_ops = { 74 96 .request = clps711x_pwm_request, 75 - .config = clps711x_pwm_config, 76 - .enable = clps711x_pwm_enable, 77 - .disable = clps711x_pwm_disable, 97 + .apply = clps711x_pwm_apply, 78 98 .owner = THIS_MODULE, 79 99 }; 80 100