From 00537de90cbc24e7555c1cb98e1992a5f9649714 Mon Sep 17 00:00:00 2001 From: "david.wu" Date: Tue, 28 Feb 2017 11:23:34 +0800 Subject: [PATCH] pwm: rockchip: State of pwm clock should synchronize with pwm enabled state If the pwm was not enabled at uboot loader, pwm could not work for clock always disabled at pwm driver. The pwm clock is enabled at beginning of pwm_apply(), but disabled at end of pwm_apply(). If the pwm was enabled at uboot loader, pwm clock is always enabled unless closed by ATF. The pwm-backlight might turn off the power at early suspend, should disable pwm clock for saving power consume. It is important to provide opportunity to enable/disable clock at pwm driver, the pwm consumer should ensure correct order to call pwm enable/disable, and pwm driver ensure state of pwm clock synchronized with pwm enabled state. Change-Id: I545db81eb638957567abacb93fd06fff9dd7181b Fixes: 2bf1c98aa5a4 ("pwm: rockchip: Add support for atomic update") Signed-off-by: David Wu --- drivers/pwm/pwm-rockchip.c | 63 ++++++++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 23 deletions(-) diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c index 186019318738..004514a255b9 100644 --- a/drivers/pwm/pwm-rockchip.c +++ b/drivers/pwm/pwm-rockchip.c @@ -148,7 +148,7 @@ static void rockchip_pwm_get_state(struct pwm_chip *chip, u64 tmp; int ret; - ret = clk_enable(pc->clk); + ret = clk_enable(pc->pclk); if (ret) return; @@ -164,7 +164,7 @@ static void rockchip_pwm_get_state(struct pwm_chip *chip, pc->data->get_state(chip, pwm, state); - clk_disable(pc->clk); + clk_disable(pc->pclk); } static int rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, @@ -203,6 +203,28 @@ static int rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, return 0; } +static int rockchip_pwm_enable(struct pwm_chip *chip, + struct pwm_device *pwm, + bool enable, + enum pwm_polarity polarity) +{ + struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); + int ret; + + if (enable) { + ret = clk_enable(pc->clk); + if (ret) + return ret; + } + + pc->data->set_enable(chip, pwm, enable, polarity); + + if (!enable) + clk_disable(pc->clk); + + return 0; +} + static int rockchip_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, struct pwm_state *state) { @@ -218,27 +240,27 @@ static int rockchip_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, if (ret) return ret; - ret = clk_enable(pc->clk); - if (ret) - return ret; - if (state->polarity != curstate.polarity && enabled) { - pc->data->set_enable(chip, pwm, false, state->polarity); + ret = rockchip_pwm_enable(chip, pwm, false, state->polarity); + if (ret) + goto out; enabled = false; } ret = rockchip_pwm_config(chip, pwm, state->duty_cycle, state->period); if (ret) { if (enabled != curstate.enabled) - pc->data->set_enable(chip, pwm, !enabled, - state->polarity); - + rockchip_pwm_enable(chip, pwm, !enabled, + state->polarity); goto out; } - if (state->enabled != enabled) - pc->data->set_enable(chip, pwm, state->enabled, - state->polarity); + if (state->enabled != enabled) { + ret = rockchip_pwm_enable(chip, pwm, state->enabled, + state->polarity); + if (ret) + goto out; + } /* * Update the state with the real hardware, which can differ a bit @@ -247,7 +269,6 @@ static int rockchip_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, rockchip_pwm_get_state(chip, pwm, state); out: - clk_disable(pc->clk); clk_disable(pc->pclk); return ret; @@ -360,11 +381,11 @@ static int rockchip_pwm_probe(struct platform_device *pdev) ret = clk_prepare_enable(pc->clk); if (ret) { - dev_err(&pdev->dev, "Can't prepare bus clk: %d\n", ret); + dev_err(&pdev->dev, "Can't prepare enable bus clk: %d\n", ret); return ret; } - ret = clk_prepare_enable(pc->pclk); + ret = clk_prepare(pc->pclk); if (ret) { dev_err(&pdev->dev, "Can't prepare periph clk: %d\n", ret); goto err_clk; @@ -391,17 +412,15 @@ static int rockchip_pwm_probe(struct platform_device *pdev) } /* Keep the PWM clk enabled if the PWM appears to be up and running. */ - if (!pwm_is_enabled(pc->chip.pwms)) { - clk_disable(pc->pclk); + if (!pwm_is_enabled(pc->chip.pwms)) clk_disable(pc->clk); - } return 0; err_pclk: clk_unprepare(pc->pclk); err_clk: - clk_unprepare(pc->clk); + clk_disable_unprepare(pc->clk); return ret; } @@ -421,10 +440,8 @@ static int rockchip_pwm_remove(struct platform_device *pdev) * clk_unprepare() after pwmchip_remove(). * */ - if (pwm_is_enabled(pc->chip.pwms)) { - clk_disable(pc->pclk); + if (pwm_is_enabled(pc->chip.pwms)) clk_disable(pc->clk); - } clk_unprepare(pc->pclk); clk_unprepare(pc->clk); -- 2.34.1