diff options
author | Jitao Shi <jitao.shi@mediatek.com> | 2021-08-08 16:24:29 +0300 |
---|---|---|
committer | Thierry Reding <thierry.reding@gmail.com> | 2021-09-02 23:03:43 +0300 |
commit | d7a4e582587d97a586b1f7709e3bddcf35928e96 (patch) | |
tree | 61f469a2f36d4e975bed64d5084743ff3a6c991b /drivers/pwm | |
parent | dd8f6b299a2b86c4839de4a60a28ce2399453bc0 (diff) | |
download | linux-d7a4e582587d97a586b1f7709e3bddcf35928e96.tar.xz |
pwm: mtk-disp: Adjust the clocks to avoid them mismatch
The clks "main" and "mm" are prepared in .probe() (and unprepared in
.remove()). This results in the clocks being on during suspend which
results in unnecessarily increased power consumption.
Remove the clock operations from .probe() and .remove(). Add the
clk_prepare_enable() in .enable() and the clk_disable_unprepare() in
.disable().
Signed-off-by: Jitao Shi <jitao.shi@mediatek.com>
[thierry.reding@gmail.com: squashed in fixup patch]
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
Diffstat (limited to 'drivers/pwm')
-rw-r--r-- | drivers/pwm/pwm-mtk-disp.c | 91 |
1 files changed, 41 insertions, 50 deletions
diff --git a/drivers/pwm/pwm-mtk-disp.c b/drivers/pwm/pwm-mtk-disp.c index 7b4a2b8c2aeb..5817ac184fa3 100644 --- a/drivers/pwm/pwm-mtk-disp.c +++ b/drivers/pwm/pwm-mtk-disp.c @@ -74,6 +74,19 @@ static int mtk_disp_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, u64 div, rate; int err; + err = clk_prepare_enable(mdp->clk_main); + if (err < 0) { + dev_err(chip->dev, "Can't enable mdp->clk_main: %pe\n", ERR_PTR(err)); + return err; + } + + err = clk_prepare_enable(mdp->clk_mm); + if (err < 0) { + dev_err(chip->dev, "Can't enable mdp->clk_mm: %pe\n", ERR_PTR(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,8 +100,11 @@ 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) { + 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); @@ -98,16 +114,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); @@ -122,10 +128,21 @@ static int mtk_disp_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, mtk_disp_pwm_update_bits(mdp, mdp->data->commit, mdp->data->commit_mask, 0x0); + } else { + /* + * For MT2701, disable double buffer before writing register + * and select manual mode and use PWM_PERIOD/PWM_HIGH_WIDTH. + */ + mtk_disp_pwm_update_bits(mdp, mdp->data->bls_debug, + mdp->data->bls_debug_mask, + mdp->data->bls_debug_mask); + mtk_disp_pwm_update_bits(mdp, mdp->data->con0, + mdp->data->con0_sel, + mdp->data->con0_sel); } - clk_disable(mdp->clk_mm); - clk_disable(mdp->clk_main); + clk_disable_unprepare(mdp->clk_mm); + clk_disable_unprepare(mdp->clk_main); return 0; } @@ -135,13 +152,16 @@ 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) + err = clk_prepare_enable(mdp->clk_main); + if (err < 0) { + dev_err(chip->dev, "Can't enable mdp->clk_main: %pe\n", ERR_PTR(err)); return err; + } - err = clk_enable(mdp->clk_mm); + err = clk_prepare_enable(mdp->clk_mm); if (err < 0) { - clk_disable(mdp->clk_main); + dev_err(chip->dev, "Can't enable mdp->clk_mm: %pe\n", ERR_PTR(err)); + clk_disable_unprepare(mdp->clk_main); return err; } @@ -158,8 +178,8 @@ 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); + clk_disable_unprepare(mdp->clk_mm); + clk_disable_unprepare(mdp->clk_main); } static const struct pwm_ops mtk_disp_pwm_ops = { @@ -192,46 +212,19 @@ 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; ret = pwmchip_add(&mdp->chip); if (ret < 0) { - dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); - goto disable_clk_mm; + dev_err(&pdev->dev, "pwmchip_add() failed: %pe\n", ERR_PTR(ret)); + return ret; } platform_set_drvdata(pdev, mdp); - /* - * For MT2701, disable double buffer before writing register - * and select manual mode and use PWM_PERIOD/PWM_HIGH_WIDTH. - */ - if (!mdp->data->has_commit) { - mtk_disp_pwm_update_bits(mdp, mdp->data->bls_debug, - mdp->data->bls_debug_mask, - mdp->data->bls_debug_mask); - mtk_disp_pwm_update_bits(mdp, mdp->data->con0, - mdp->data->con0_sel, - mdp->data->con0_sel); - } - 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) @@ -239,8 +232,6 @@ static int mtk_disp_pwm_remove(struct platform_device *pdev) struct mtk_disp_pwm *mdp = platform_get_drvdata(pdev); pwmchip_remove(&mdp->chip); - clk_unprepare(mdp->clk_mm); - clk_unprepare(mdp->clk_main); return 0; } |