| From 3d2813fb17e5fd0d73c1d1442ca0192bde4af10e Mon Sep 17 00:00:00 2001 |
| From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= <u.kleine-koenig@pengutronix.de> |
| Date: Wed, 7 Jul 2021 18:27:49 +0200 |
| Subject: pwm: lpc32xx: Don't modify HW state in .probe() after the PWM chip was registered |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> |
| |
| commit 3d2813fb17e5fd0d73c1d1442ca0192bde4af10e upstream. |
| |
| This fixes a race condition: After pwmchip_add() is called there might |
| already be a consumer and then modifying the hardware behind the |
| consumer's back is bad. So set the default before. |
| |
| (Side-note: I don't know what this register setting actually does, if |
| this modifies the polarity there is an inconsistency because the |
| inversed polarity isn't considered if the PWM is already running during |
| .probe().) |
| |
| Fixes: acfd92fdfb93 ("pwm: lpc32xx: Set PWM_PIN_LEVEL bit to default value") |
| Cc: Sylvain Lemieux <slemieux@tycoint.com> |
| Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> |
| Signed-off-by: Thierry Reding <thierry.reding@gmail.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/pwm/pwm-lpc32xx.c | 10 +++++----- |
| 1 file changed, 5 insertions(+), 5 deletions(-) |
| |
| --- a/drivers/pwm/pwm-lpc32xx.c |
| +++ b/drivers/pwm/pwm-lpc32xx.c |
| @@ -117,17 +117,17 @@ static int lpc32xx_pwm_probe(struct plat |
| lpc32xx->chip.ops = &lpc32xx_pwm_ops; |
| lpc32xx->chip.npwm = 1; |
| |
| + /* If PWM is disabled, configure the output to the default value */ |
| + val = readl(lpc32xx->base + (lpc32xx->chip.pwms[0].hwpwm << 2)); |
| + val &= ~PWM_PIN_LEVEL; |
| + writel(val, lpc32xx->base + (lpc32xx->chip.pwms[0].hwpwm << 2)); |
| + |
| ret = pwmchip_add(&lpc32xx->chip); |
| if (ret < 0) { |
| dev_err(&pdev->dev, "failed to add PWM chip, error %d\n", ret); |
| return ret; |
| } |
| |
| - /* When PWM is disable, configure the output to the default value */ |
| - val = readl(lpc32xx->base + (lpc32xx->chip.pwms[0].hwpwm << 2)); |
| - val &= ~PWM_PIN_LEVEL; |
| - writel(val, lpc32xx->base + (lpc32xx->chip.pwms[0].hwpwm << 2)); |
| - |
| platform_set_drvdata(pdev, lpc32xx); |
| |
| return 0; |