[PATCH v4 1/3] pwm: mtk-disp: adjust the clocks to avoid them mismatch
From: Jitao Shi <hidden>
Date: 2021-06-03 10:05:50
Also in:
linux-mediatek, linux-pwm, lkml
Subsystem:
pwm subsystem, the rest · Maintainers:
Uwe Kleine-König, Linus Torvalds
The clk_main and clk_mm clocks are still on when system enter suspend. That will casue the power consumption. The clocks call the clk_prepare() in probe(), but the clk_unprepare() is called in remove(), it isn't called when system suspend. Remove the clcok opterations from probe() and remove. Add the clk_prepare_enable() in config(). Add the clk_disable_unprepare() in disable(). Signed-off-by: Jitao Shi <redacted> --- drivers/pwm/pwm-mtk-disp.c | 81 ++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 48 deletions(-)
diff --git a/drivers/pwm/pwm-mtk-disp.c b/drivers/pwm/pwm-mtk-disp.c
index 9b3ba401a3db..b5771e2c54b8 100644
--- a/drivers/pwm/pwm-mtk-disp.c
+++ b/drivers/pwm/pwm-mtk-disp.c@@ -47,6 +47,7 @@ struct mtk_disp_pwm { struct clk *clk_main; struct clk *clk_mm; void __iomem *base; + bool enabled; }; static inline struct mtk_disp_pwm *to_mtk_disp_pwm(struct pwm_chip *chip)
@@ -74,6 +75,22 @@ static int mtk_disp_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, u64 div, rate; int err; + if (!mdp->enabled) { + err = clk_prepare_enable(mdp->clk_main); + if (err < 0) { + dev_err(chip->dev, "Can't enable mdp->clk_main: %d\n", + err); + return err; + } + err = clk_prepare_enable(mdp->clk_mm); + if (err < 0) { + dev_err(chip->dev, "Can't enable mdp->clk_mm: %d\n", + err); + clk_disable_unprepare(mdp->clk_main); + return err; + } + } + /* * Find period, high_width and clk_div to suit duty_ns and period_ns. * Calculate proper div value to keep period value in the bound.
@@ -87,9 +104,15 @@ static int mtk_disp_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, rate = clk_get_rate(mdp->clk_main); clk_div = div_u64(rate * period_ns, NSEC_PER_SEC) >> PWM_PERIOD_BIT_WIDTH; - if (clk_div > PWM_CLKDIV_MAX) + if (clk_div > PWM_CLKDIV_MAX) { + dev_err(chip->dev, "clock rate is too high: rate = %d Hz\n", + rate); + if (!mdp->enabled) { + clk_disable_unprepare(mdp->clk_mm); + clk_disable_unprepare(mdp->clk_main); + } return -EINVAL; - + } div = NSEC_PER_SEC * (clk_div + 1); period = div64_u64(rate * period_ns, div); if (period > 0)
@@ -98,16 +121,6 @@ static int mtk_disp_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, high_width = div64_u64(rate * duty_ns, div); value = period | (high_width << PWM_HIGH_WIDTH_SHIFT); - err = clk_enable(mdp->clk_main); - if (err < 0) - return err; - - err = clk_enable(mdp->clk_mm); - if (err < 0) { - clk_disable(mdp->clk_main); - return err; - } - mtk_disp_pwm_update_bits(mdp, mdp->data->con0, PWM_CLKDIV_MASK, clk_div << PWM_CLKDIV_SHIFT);
@@ -124,9 +137,6 @@ static int mtk_disp_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, 0x0); } - clk_disable(mdp->clk_mm); - clk_disable(mdp->clk_main); - return 0; }
@@ -135,18 +145,9 @@ static int mtk_disp_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) struct mtk_disp_pwm *mdp = to_mtk_disp_pwm(chip); int err; - err = clk_enable(mdp->clk_main); - if (err < 0) - return err; - - err = clk_enable(mdp->clk_mm); - if (err < 0) { - clk_disable(mdp->clk_main); - return err; - } - mtk_disp_pwm_update_bits(mdp, DISP_PWM_EN, mdp->data->enable_mask, mdp->data->enable_mask); + mdp->enabled = true; return 0; }
@@ -158,8 +159,11 @@ static void mtk_disp_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) mtk_disp_pwm_update_bits(mdp, DISP_PWM_EN, mdp->data->enable_mask, 0x0); - clk_disable(mdp->clk_mm); - clk_disable(mdp->clk_main); + if (mdp->enabled) { + clk_disable_unprepare(mdp->clk_mm); + clk_disable_unprepare(mdp->clk_main); + } + mdp->enabled = false; } static const struct pwm_ops mtk_disp_pwm_ops = {
@@ -192,14 +196,6 @@ static int mtk_disp_pwm_probe(struct platform_device *pdev) if (IS_ERR(mdp->clk_mm)) return PTR_ERR(mdp->clk_mm); - ret = clk_prepare(mdp->clk_main); - if (ret < 0) - return ret; - - ret = clk_prepare(mdp->clk_mm); - if (ret < 0) - goto disable_clk_main; - mdp->chip.dev = &pdev->dev; mdp->chip.ops = &mtk_disp_pwm_ops; mdp->chip.npwm = 1;
@@ -207,7 +203,7 @@ static int mtk_disp_pwm_probe(struct platform_device *pdev) ret = pwmchip_add(&mdp->chip); if (ret < 0) { dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); - goto disable_clk_mm; + return ret; } platform_set_drvdata(pdev, mdp);
@@ -226,24 +222,13 @@ static int mtk_disp_pwm_probe(struct platform_device *pdev) } return 0; - -disable_clk_mm: - clk_unprepare(mdp->clk_mm); -disable_clk_main: - clk_unprepare(mdp->clk_main); - return ret; } static int mtk_disp_pwm_remove(struct platform_device *pdev) { struct mtk_disp_pwm *mdp = platform_get_drvdata(pdev); - int ret; - - ret = pwmchip_remove(&mdp->chip); - clk_unprepare(mdp->clk_mm); - clk_unprepare(mdp->clk_main); - return ret; + return pwmchip_remove(&mdp->chip); } static const struct mtk_pwm_data mt2701_pwm_data = {
--
2.25.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel