Skip to content

Commit

Permalink
pwm: ab8500: Fix register offset calculation to not depend on probe o…
Browse files Browse the repository at this point in the history
…rder

commit eb41f33 upstream.

The assumption that lead to commit 5e5da1e ("pwm: ab8500:
Explicitly allocate pwm chip base dynamically") was wrong: The
pwm-ab8500 devices are not directly instantiated from device tree, but
from the ab8500 mfd driver. So the pdev->id isn't -1, but a number
between 1 and 3. Now that pwmchip ids are always allocated dynamically,
this cannot easily be reverted.

Introduce a new member in the driver data struct that tracks the
hardware id and use this to calculate the register offset.

Side-note: Using chip->base to calculate the offset was never robust
because if there was already a PWM with id 1 at the time ab8500-pwm.1
was probed, the associated pwmchip would get assigned chip->base = 2 (or
something bigger).

Fixes: 5e5da1e ("pwm: ab8500: Explicitly allocate pwm chip base dynamically")
Fixes: 6173f8f ("pwm: Move AB8500 PWM driver to PWM framework")
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
ukleinek authored and gregkh committed Sep 26, 2021
1 parent bc013a3 commit 861006f
Showing 1 changed file with 14 additions and 3 deletions.
17 changes: 14 additions & 3 deletions drivers/pwm/pwm-ab8500.c
Expand Up @@ -22,22 +22,29 @@

struct ab8500_pwm_chip {
struct pwm_chip chip;
unsigned int hwid;
};

static struct ab8500_pwm_chip *ab8500_pwm_from_chip(struct pwm_chip *chip)
{
return container_of(chip, struct ab8500_pwm_chip, chip);
}

static int ab8500_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
const struct pwm_state *state)
{
int ret;
u8 reg;
unsigned int higher_val, lower_val;
struct ab8500_pwm_chip *ab8500 = ab8500_pwm_from_chip(chip);

if (state->polarity != PWM_POLARITY_NORMAL)
return -EINVAL;

if (!state->enabled) {
ret = abx500_mask_and_set_register_interruptible(chip->dev,
AB8500_MISC, AB8500_PWM_OUT_CTRL7_REG,
1 << (chip->base - 1), 0);
1 << ab8500->hwid, 0);

if (ret < 0)
dev_err(chip->dev, "%s: Failed to disable PWM, Error %d\n",
Expand All @@ -56,7 +63,7 @@ static int ab8500_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
*/
higher_val = ((state->duty_cycle & 0x0300) >> 8);

reg = AB8500_PWM_OUT_CTRL1_REG + ((chip->base - 1) * 2);
reg = AB8500_PWM_OUT_CTRL1_REG + (ab8500->hwid * 2);

ret = abx500_set_register_interruptible(chip->dev, AB8500_MISC,
reg, (u8)lower_val);
Expand All @@ -70,7 +77,7 @@ static int ab8500_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,

ret = abx500_mask_and_set_register_interruptible(chip->dev,
AB8500_MISC, AB8500_PWM_OUT_CTRL7_REG,
1 << (chip->base - 1), 1 << (chip->base - 1));
1 << ab8500->hwid, 1 << ab8500->hwid);
if (ret < 0)
dev_err(chip->dev, "%s: Failed to enable PWM, Error %d\n",
pwm->label, ret);
Expand All @@ -88,6 +95,9 @@ static int ab8500_pwm_probe(struct platform_device *pdev)
struct ab8500_pwm_chip *ab8500;
int err;

if (pdev->id < 1 || pdev->id > 31)
return dev_err_probe(&pdev->dev, EINVAL, "Invalid device id %d\n", pdev->id);

/*
* Nothing to be done in probe, this is required to get the
* device which is required for ab8500 read and write
Expand All @@ -99,6 +109,7 @@ static int ab8500_pwm_probe(struct platform_device *pdev)
ab8500->chip.dev = &pdev->dev;
ab8500->chip.ops = &ab8500_pwm_ops;
ab8500->chip.npwm = 1;
ab8500->hwid = pdev->id - 1;

err = pwmchip_add(&ab8500->chip);
if (err < 0)
Expand Down

0 comments on commit 861006f

Please sign in to comment.