linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] pwm: imx27: fix clk handling in pwm_imx27_apply()
@ 2020-02-09 21:31 Uwe Kleine-König
  2020-02-10 21:22 ` [PATCH 0/3] pwm: imx27: fix clk handling Uwe Kleine-König
  0 siblings, 1 reply; 5+ messages in thread
From: Uwe Kleine-König @ 2020-02-09 21:31 UTC (permalink / raw)
  To: Thierry Reding
  Cc: linux-pwm, Shawn Guo, NXP Linux Team, Pengutronix Kernel Team,
	Fabio Estevam, linux-arm-kernel

pwm_imx27_apply() enables the clocks if the previous PWM state was
disabled. Given that the clocks are supposed to be left on iff the PWM
is running, the decision to disable the clocks at the end of the
function must not depend on the previous state.

Without this fix the enable count of the two affected clocks increases
by one whenever pwm_apply changes from one disabled state to another.

Fixes: bd88d319abe9 ("pwm: imx27: Unconditionally write state to hardware")
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 drivers/pwm/pwm-imx27.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/pwm/pwm-imx27.c b/drivers/pwm/pwm-imx27.c
index 35a7ac42269c..7e5ed0152977 100644
--- a/drivers/pwm/pwm-imx27.c
+++ b/drivers/pwm/pwm-imx27.c
@@ -289,7 +289,7 @@ static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 
 	writel(cr, imx->mmio_base + MX3_PWMCR);
 
-	if (!state->enabled && cstate.enabled)
+	if (!state->enabled)
 		pwm_imx27_clk_disable_unprepare(chip);
 
 	return 0;
-- 
2.24.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 0/3] pwm: imx27: fix clk handling
  2020-02-09 21:31 [PATCH] pwm: imx27: fix clk handling in pwm_imx27_apply() Uwe Kleine-König
@ 2020-02-10 21:22 ` Uwe Kleine-König
  2020-02-10 21:22   ` [PATCH 1/3] pwm: imx27: Simplify helper function to enable and disable clocks Uwe Kleine-König
                     ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Uwe Kleine-König @ 2020-02-10 21:22 UTC (permalink / raw)
  To: Thierry Reding
  Cc: linux-pwm, Shawn Guo, NXP Linux Team, Pengutronix Kernel Team,
	Fabio Estevam, linux-arm-kernel

Hello,

while looking through the pwm-imx27 driver I found some more broken
clock handling additional to yesterday's patch (pwm: imx27: fix clk
handling in pwm_imx27_apply()). This series is to be applied on top of
this patch.

Uwe Kleine-König (3):
  pwm: imx27: Simplify helper function to enable and disable clocks
  pwm: imx27: Don't disable clks at device remove time
  pwm: imx27: Ensure clocks being on iff the PWM is on

 drivers/pwm/pwm-imx27.c | 29 +++++++++++++++++------------
 1 file changed, 17 insertions(+), 12 deletions(-)

-- 
2.24.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/3] pwm: imx27: Simplify helper function to enable and disable clocks
  2020-02-10 21:22 ` [PATCH 0/3] pwm: imx27: fix clk handling Uwe Kleine-König
@ 2020-02-10 21:22   ` Uwe Kleine-König
  2020-02-10 21:22   ` [PATCH 2/3] pwm: imx27: Don't disable clks at device remove time Uwe Kleine-König
  2020-02-10 21:22   ` [PATCH 3/3] pwm: imx27: Ensure clocks being on iff the PWM is on Uwe Kleine-König
  2 siblings, 0 replies; 5+ messages in thread
From: Uwe Kleine-König @ 2020-02-10 21:22 UTC (permalink / raw)
  To: Thierry Reding
  Cc: linux-pwm, Shawn Guo, NXP Linux Team, Pengutronix Kernel Team,
	Fabio Estevam, linux-arm-kernel

pwm_imx27_clk_prepare_enable() took a pointer to a struct pwm_chip just
to convert it to a struct pwm_imx27_chip pointer while all callers
already have the latter. Ditto for pwm_imx27_clk_disable_unprepare().

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 drivers/pwm/pwm-imx27.c | 17 +++++++----------
 1 file changed, 7 insertions(+), 10 deletions(-)

diff --git a/drivers/pwm/pwm-imx27.c b/drivers/pwm/pwm-imx27.c
index 7e5ed0152977..e04ae566bbf9 100644
--- a/drivers/pwm/pwm-imx27.c
+++ b/drivers/pwm/pwm-imx27.c
@@ -96,9 +96,8 @@ struct pwm_imx27_chip {
 
 #define to_pwm_imx27_chip(chip)	container_of(chip, struct pwm_imx27_chip, chip)
 
-static int pwm_imx27_clk_prepare_enable(struct pwm_chip *chip)
+static int pwm_imx27_clk_prepare_enable(struct pwm_imx27_chip *imx)
 {
-	struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip);
 	int ret;
 
 	ret = clk_prepare_enable(imx->clk_ipg);
@@ -114,10 +113,8 @@ static int pwm_imx27_clk_prepare_enable(struct pwm_chip *chip)
 	return 0;
 }
 
-static void pwm_imx27_clk_disable_unprepare(struct pwm_chip *chip)
+static void pwm_imx27_clk_disable_unprepare(struct pwm_imx27_chip *imx)
 {
-	struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip);
-
 	clk_disable_unprepare(imx->clk_per);
 	clk_disable_unprepare(imx->clk_ipg);
 }
@@ -130,7 +127,7 @@ static void pwm_imx27_get_state(struct pwm_chip *chip,
 	u64 tmp;
 	int ret;
 
-	ret = pwm_imx27_clk_prepare_enable(chip);
+	ret = pwm_imx27_clk_prepare_enable(imx);
 	if (ret < 0)
 		return;
 
@@ -175,7 +172,7 @@ static void pwm_imx27_get_state(struct pwm_chip *chip,
 	state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, pwm_clk);
 
 	if (!state->enabled)
-		pwm_imx27_clk_disable_unprepare(chip);
+		pwm_imx27_clk_disable_unprepare(imx);
 }
 
 static void pwm_imx27_sw_reset(struct pwm_chip *chip)
@@ -259,7 +256,7 @@ static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 	if (cstate.enabled) {
 		pwm_imx27_wait_fifo_slot(chip, pwm);
 	} else {
-		ret = pwm_imx27_clk_prepare_enable(chip);
+		ret = pwm_imx27_clk_prepare_enable(imx);
 		if (ret)
 			return ret;
 
@@ -290,7 +287,7 @@ static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 	writel(cr, imx->mmio_base + MX3_PWMCR);
 
 	if (!state->enabled)
-		pwm_imx27_clk_disable_unprepare(chip);
+		pwm_imx27_clk_disable_unprepare(imx);
 
 	return 0;
 }
@@ -361,7 +358,7 @@ static int pwm_imx27_remove(struct platform_device *pdev)
 
 	imx = platform_get_drvdata(pdev);
 
-	pwm_imx27_clk_disable_unprepare(&imx->chip);
+	pwm_imx27_clk_disable_unprepare(imx);
 
 	return pwmchip_remove(&imx->chip);
 }
-- 
2.24.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/3] pwm: imx27: Don't disable clks at device remove time
  2020-02-10 21:22 ` [PATCH 0/3] pwm: imx27: fix clk handling Uwe Kleine-König
  2020-02-10 21:22   ` [PATCH 1/3] pwm: imx27: Simplify helper function to enable and disable clocks Uwe Kleine-König
@ 2020-02-10 21:22   ` Uwe Kleine-König
  2020-02-10 21:22   ` [PATCH 3/3] pwm: imx27: Ensure clocks being on iff the PWM is on Uwe Kleine-König
  2 siblings, 0 replies; 5+ messages in thread
From: Uwe Kleine-König @ 2020-02-10 21:22 UTC (permalink / raw)
  To: Thierry Reding
  Cc: linux-pwm, Shawn Guo, NXP Linux Team, Pengutronix Kernel Team,
	Fabio Estevam, linux-arm-kernel

The .remove() callback is not supposed to modify hardware state. This is
in the responsibility of the PWM consumer.

After the PWM was disabled the clks are off (apart from a bug that is
fixed in the next patch), so unbinding the driver either stops the PWM
(which it should not) or disables already disabled clks yielding
warnings from the clk core.

So just drop the call to disable the clocks. (Which BTW was also in the
wrong order because the call makes the PWM unfunctional and so should
have come only after pwmchip_remove().

Fixes: 9f4c8f9607c3 ("pwm: imx: Add ipg clock operation")
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 drivers/pwm/pwm-imx27.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/pwm/pwm-imx27.c b/drivers/pwm/pwm-imx27.c
index e04ae566bbf9..fb142813d455 100644
--- a/drivers/pwm/pwm-imx27.c
+++ b/drivers/pwm/pwm-imx27.c
@@ -358,8 +358,6 @@ static int pwm_imx27_remove(struct platform_device *pdev)
 
 	imx = platform_get_drvdata(pdev);
 
-	pwm_imx27_clk_disable_unprepare(imx);
-
 	return pwmchip_remove(&imx->chip);
 }
 
-- 
2.24.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 3/3] pwm: imx27: Ensure clocks being on iff the PWM is on
  2020-02-10 21:22 ` [PATCH 0/3] pwm: imx27: fix clk handling Uwe Kleine-König
  2020-02-10 21:22   ` [PATCH 1/3] pwm: imx27: Simplify helper function to enable and disable clocks Uwe Kleine-König
  2020-02-10 21:22   ` [PATCH 2/3] pwm: imx27: Don't disable clks at device remove time Uwe Kleine-König
@ 2020-02-10 21:22   ` Uwe Kleine-König
  2 siblings, 0 replies; 5+ messages in thread
From: Uwe Kleine-König @ 2020-02-10 21:22 UTC (permalink / raw)
  To: Thierry Reding
  Cc: linux-pwm, Shawn Guo, NXP Linux Team, Pengutronix Kernel Team,
	Fabio Estevam, linux-arm-kernel

Up to now the .probe function didn't enable clks and relied on the core
to call the .get_state() callback to have the clk running. The latter
enabled the needed clocks and kept them running if the PWM is enabled.

This only works correctly if the .get_state() callback is called exactly
once and this single call happens before unused clocks are disabled by
the clk core.

The former wasn't true for a short period while commit 01ccf903edd6
("pwm: Let pwm_get_state() return the last implemented state") applied
and not not reverted yet and might become wrong in the future.

The latter isn't true any more since commit cfc4c189bc70 ("pwm: Read
initial hardware state at request time") which results in a running PWM
being stopped at boot time if for example the consumer lives in a kernel
module that is only loaded after the clk core disabled unused clocks.

So ensure .probe() is left with the clocks on if the PWM is running and
.get_state() disables everything it enabled.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 drivers/pwm/pwm-imx27.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/pwm/pwm-imx27.c b/drivers/pwm/pwm-imx27.c
index fb142813d455..e83c077bb7cc 100644
--- a/drivers/pwm/pwm-imx27.c
+++ b/drivers/pwm/pwm-imx27.c
@@ -171,8 +171,7 @@ static void pwm_imx27_get_state(struct pwm_chip *chip,
 	tmp = NSEC_PER_SEC * (u64)(val);
 	state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, pwm_clk);
 
-	if (!state->enabled)
-		pwm_imx27_clk_disable_unprepare(imx);
+	pwm_imx27_clk_disable_unprepare(imx);
 }
 
 static void pwm_imx27_sw_reset(struct pwm_chip *chip)
@@ -307,6 +306,8 @@ MODULE_DEVICE_TABLE(of, pwm_imx27_dt_ids);
 static int pwm_imx27_probe(struct platform_device *pdev)
 {
 	struct pwm_imx27_chip *imx;
+	int ret;
+	u32 pwmcr;
 
 	imx = devm_kzalloc(&pdev->dev, sizeof(*imx), GFP_KERNEL);
 	if (imx == NULL)
@@ -349,6 +350,15 @@ static int pwm_imx27_probe(struct platform_device *pdev)
 	if (IS_ERR(imx->mmio_base))
 		return PTR_ERR(imx->mmio_base);
 
+	ret = pwm_imx27_clk_prepare_enable(imx);
+	if (ret)
+		return ret;
+
+	/* keep clks on if pwm is running */
+	pwmcr = readl(imx->mmio_base + MX3_PWMCR);
+	if (!(pwmcr & MX3_PWMCR_EN))
+		pwm_imx27_clk_disable_unprepare(imx);
+
 	return pwmchip_add(&imx->chip);
 }
 
-- 
2.24.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2020-02-10 21:23 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-02-09 21:31 [PATCH] pwm: imx27: fix clk handling in pwm_imx27_apply() Uwe Kleine-König
2020-02-10 21:22 ` [PATCH 0/3] pwm: imx27: fix clk handling Uwe Kleine-König
2020-02-10 21:22   ` [PATCH 1/3] pwm: imx27: Simplify helper function to enable and disable clocks Uwe Kleine-König
2020-02-10 21:22   ` [PATCH 2/3] pwm: imx27: Don't disable clks at device remove time Uwe Kleine-König
2020-02-10 21:22   ` [PATCH 3/3] pwm: imx27: Ensure clocks being on iff the PWM is on Uwe Kleine-König

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).