diff options
author | Rohith Seelaboyina <rseelaboyina@nvidia.com> | 2016-06-22 07:47:19 -0400 |
---|---|---|
committer | Thierry Reding <thierry.reding@gmail.com> | 2016-07-11 06:49:31 -0400 |
commit | 5dfbd2bd5439f1ada5ddaa3883e9e038de5d2abe (patch) | |
tree | 2a7d98e034a4e9d7f1194ad9f379de6597b44d0c /drivers/pwm/pwm-tegra.c | |
parent | 4f57f5a01fcb4ec9d98e274837c0cd853d447da3 (diff) |
pwm: tegra: Add support for reset control
Add reset control of the PWM controller to reset it before
accessing the PWM register.
Signed-off-by: Rohith Seelaboyina <rseelaboyina@nvidia.com>
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
Diffstat (limited to 'drivers/pwm/pwm-tegra.c')
-rw-r--r-- | drivers/pwm/pwm-tegra.c | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c index 3cbb32d8064f..097658e0751b 100644 --- a/drivers/pwm/pwm-tegra.c +++ b/drivers/pwm/pwm-tegra.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/pwm.h> | 29 | #include <linux/pwm.h> |
30 | #include <linux/platform_device.h> | 30 | #include <linux/platform_device.h> |
31 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
32 | #include <linux/reset.h> | ||
32 | 33 | ||
33 | #define PWM_ENABLE (1 << 31) | 34 | #define PWM_ENABLE (1 << 31) |
34 | #define PWM_DUTY_WIDTH 8 | 35 | #define PWM_DUTY_WIDTH 8 |
@@ -41,6 +42,7 @@ struct tegra_pwm_chip { | |||
41 | struct device *dev; | 42 | struct device *dev; |
42 | 43 | ||
43 | struct clk *clk; | 44 | struct clk *clk; |
45 | struct reset_control*rst; | ||
44 | 46 | ||
45 | void __iomem *regs; | 47 | void __iomem *regs; |
46 | }; | 48 | }; |
@@ -187,6 +189,15 @@ static int tegra_pwm_probe(struct platform_device *pdev) | |||
187 | if (IS_ERR(pwm->clk)) | 189 | if (IS_ERR(pwm->clk)) |
188 | return PTR_ERR(pwm->clk); | 190 | return PTR_ERR(pwm->clk); |
189 | 191 | ||
192 | pwm->rst = devm_reset_control_get(&pdev->dev, "pwm"); | ||
193 | if (IS_ERR(pwm->rst)) { | ||
194 | ret = PTR_ERR(pwm->rst); | ||
195 | dev_err(&pdev->dev, "Reset control is not found: %d\n", ret); | ||
196 | return ret; | ||
197 | } | ||
198 | |||
199 | reset_control_deassert(pwm->rst); | ||
200 | |||
190 | pwm->chip.dev = &pdev->dev; | 201 | pwm->chip.dev = &pdev->dev; |
191 | pwm->chip.ops = &tegra_pwm_ops; | 202 | pwm->chip.ops = &tegra_pwm_ops; |
192 | pwm->chip.base = -1; | 203 | pwm->chip.base = -1; |
@@ -195,6 +206,7 @@ static int tegra_pwm_probe(struct platform_device *pdev) | |||
195 | ret = pwmchip_add(&pwm->chip); | 206 | ret = pwmchip_add(&pwm->chip); |
196 | if (ret < 0) { | 207 | if (ret < 0) { |
197 | dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); | 208 | dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); |
209 | reset_control_assert(pwm->rst); | ||
198 | return ret; | 210 | return ret; |
199 | } | 211 | } |
200 | 212 | ||
@@ -205,10 +217,15 @@ static int tegra_pwm_remove(struct platform_device *pdev) | |||
205 | { | 217 | { |
206 | struct tegra_pwm_chip *pc = platform_get_drvdata(pdev); | 218 | struct tegra_pwm_chip *pc = platform_get_drvdata(pdev); |
207 | unsigned int i; | 219 | unsigned int i; |
220 | int err; | ||
208 | 221 | ||
209 | if (WARN_ON(!pc)) | 222 | if (WARN_ON(!pc)) |
210 | return -ENODEV; | 223 | return -ENODEV; |
211 | 224 | ||
225 | err = clk_prepare_enable(pc->clk); | ||
226 | if (err < 0) | ||
227 | return err; | ||
228 | |||
212 | for (i = 0; i < pc->chip.npwm; i++) { | 229 | for (i = 0; i < pc->chip.npwm; i++) { |
213 | struct pwm_device *pwm = &pc->chip.pwms[i]; | 230 | struct pwm_device *pwm = &pc->chip.pwms[i]; |
214 | 231 | ||
@@ -221,6 +238,9 @@ static int tegra_pwm_remove(struct platform_device *pdev) | |||
221 | clk_disable_unprepare(pc->clk); | 238 | clk_disable_unprepare(pc->clk); |
222 | } | 239 | } |
223 | 240 | ||
241 | reset_control_assert(pc->rst); | ||
242 | clk_disable_unprepare(pc->clk); | ||
243 | |||
224 | return pwmchip_remove(&pc->chip); | 244 | return pwmchip_remove(&pc->chip); |
225 | } | 245 | } |
226 | 246 | ||