Skip to content

Commit

Permalink
gpio: mvebu: fix pwm .get_state period calculation
Browse files Browse the repository at this point in the history
commit e73b010 upstream.

The period is the sum of on and off values. That is, calculate period as

  ($on + $off) / clkrate

instead of

  $off / clkrate - $on / clkrate

that makes no sense.

Reported-by: Russell King <linux@armlinux.org.uk>
Reviewed-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Fixes: 757642f ("gpio: mvebu: Add limited PWM support")
Signed-off-by: Baruch Siach <baruch@tkos.co.il>
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
[baruch: backport to kernels <= v5.10]
Reviewed-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: Baruch Siach <baruch@tkos.co.il>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
baruchsiach authored and gregkh committed Jan 30, 2021
1 parent b97134d commit 43f2e60
Showing 1 changed file with 10 additions and 15 deletions.
25 changes: 10 additions & 15 deletions drivers/gpio/gpio-mvebu.c
Expand Up @@ -660,9 +660,8 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip,

spin_lock_irqsave(&mvpwm->lock, flags);

val = (unsigned long long)
readl_relaxed(mvebu_pwmreg_blink_on_duration(mvpwm));
val *= NSEC_PER_SEC;
u = readl_relaxed(mvebu_pwmreg_blink_on_duration(mvpwm));
val = (unsigned long long) u * NSEC_PER_SEC;
do_div(val, mvpwm->clk_rate);
if (val > UINT_MAX)
state->duty_cycle = UINT_MAX;
Expand All @@ -671,21 +670,17 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip,
else
state->duty_cycle = 1;

val = (unsigned long long)
readl_relaxed(mvebu_pwmreg_blink_off_duration(mvpwm));
val = (unsigned long long) u; /* on duration */
/* period = on + off duration */
val += readl_relaxed(mvebu_pwmreg_blink_off_duration(mvpwm));
val *= NSEC_PER_SEC;
do_div(val, mvpwm->clk_rate);
if (val < state->duty_cycle) {
if (val > UINT_MAX)
state->period = UINT_MAX;
else if (val)
state->period = val;
else
state->period = 1;
} else {
val -= state->duty_cycle;
if (val > UINT_MAX)
state->period = UINT_MAX;
else if (val)
state->period = val;
else
state->period = 1;
}

regmap_read(mvchip->regs, GPIO_BLINK_EN_OFF + mvchip->offset, &u);
if (u)
Expand Down

0 comments on commit 43f2e60

Please sign in to comment.