aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pwm/pwm-imx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pwm/pwm-imx.c')
-rw-r--r--drivers/pwm/pwm-imx.c53
1 files changed, 48 insertions, 5 deletions
diff --git a/drivers/pwm/pwm-imx.c b/drivers/pwm/pwm-imx.c
index 6cd3b72fbbc1..55a3a363d5be 100644
--- a/drivers/pwm/pwm-imx.c
+++ b/drivers/pwm/pwm-imx.c
@@ -87,6 +87,8 @@
87#define MX3_PWMPR_MAX 0xfffe 87#define MX3_PWMPR_MAX 0xfffe
88 88
89struct imx_chip { 89struct imx_chip {
90 struct clk *clk_ipg;
91
90 struct clk *clk_per; 92 struct clk *clk_per;
91 93
92 void __iomem *mmio_base; 94 void __iomem *mmio_base;
@@ -96,6 +98,32 @@ struct imx_chip {
96 98
97#define to_imx_chip(chip) container_of(chip, struct imx_chip, chip) 99#define to_imx_chip(chip) container_of(chip, struct imx_chip, chip)
98 100
101static int imx_pwm_clk_prepare_enable(struct pwm_chip *chip)
102{
103 struct imx_chip *imx = to_imx_chip(chip);
104 int ret;
105
106 ret = clk_prepare_enable(imx->clk_ipg);
107 if (ret)
108 return ret;
109
110 ret = clk_prepare_enable(imx->clk_per);
111 if (ret) {
112 clk_disable_unprepare(imx->clk_ipg);
113 return ret;
114 }
115
116 return 0;
117}
118
119static void imx_pwm_clk_disable_unprepare(struct pwm_chip *chip)
120{
121 struct imx_chip *imx = to_imx_chip(chip);
122
123 clk_disable_unprepare(imx->clk_per);
124 clk_disable_unprepare(imx->clk_ipg);
125}
126
99static void imx_pwm_get_state(struct pwm_chip *chip, 127static void imx_pwm_get_state(struct pwm_chip *chip,
100 struct pwm_device *pwm, struct pwm_state *state) 128 struct pwm_device *pwm, struct pwm_state *state)
101{ 129{
@@ -103,11 +131,15 @@ static void imx_pwm_get_state(struct pwm_chip *chip,
103 u32 period, prescaler, pwm_clk, ret, val; 131 u32 period, prescaler, pwm_clk, ret, val;
104 u64 tmp; 132 u64 tmp;
105 133
134 ret = imx_pwm_clk_prepare_enable(chip);
135 if (ret < 0)
136 return;
137
106 val = readl(imx->mmio_base + MX3_PWMCR); 138 val = readl(imx->mmio_base + MX3_PWMCR);
107 139
108 if (val & MX3_PWMCR_EN) { 140 if (val & MX3_PWMCR_EN) {
109 state->enabled = true; 141 state->enabled = true;
110 ret = clk_prepare_enable(imx->clk_per); 142 ret = imx_pwm_clk_prepare_enable(chip);
111 if (ret) 143 if (ret)
112 return; 144 return;
113 } else { 145 } else {
@@ -143,6 +175,8 @@ static void imx_pwm_get_state(struct pwm_chip *chip,
143 } else { 175 } else {
144 state->duty_cycle = 0; 176 state->duty_cycle = 0;
145 } 177 }
178
179 imx_pwm_clk_disable_unprepare(chip);
146} 180}
147 181
148static int imx_pwm_config_v1(struct pwm_chip *chip, 182static int imx_pwm_config_v1(struct pwm_chip *chip,
@@ -180,7 +214,7 @@ static int imx_pwm_enable_v1(struct pwm_chip *chip, struct pwm_device *pwm)
180 u32 val; 214 u32 val;
181 int ret; 215 int ret;
182 216
183 ret = clk_prepare_enable(imx->clk_per); 217 ret = imx_pwm_clk_prepare_enable(chip);
184 if (ret < 0) 218 if (ret < 0)
185 return ret; 219 return ret;
186 220
@@ -200,7 +234,7 @@ static void imx_pwm_disable_v1(struct pwm_chip *chip, struct pwm_device *pwm)
200 val &= ~MX1_PWMC_EN; 234 val &= ~MX1_PWMC_EN;
201 writel(val, imx->mmio_base + MX1_PWMC); 235 writel(val, imx->mmio_base + MX1_PWMC);
202 236
203 clk_disable_unprepare(imx->clk_per); 237 imx_pwm_clk_disable_unprepare(chip);
204} 238}
205 239
206static void imx_pwm_sw_reset(struct pwm_chip *chip) 240static void imx_pwm_sw_reset(struct pwm_chip *chip)
@@ -286,7 +320,7 @@ static int imx_pwm_apply_v2(struct pwm_chip *chip, struct pwm_device *pwm,
286 if (cstate.enabled) { 320 if (cstate.enabled) {
287 imx_pwm_wait_fifo_slot(chip, pwm); 321 imx_pwm_wait_fifo_slot(chip, pwm);
288 } else { 322 } else {
289 ret = clk_prepare_enable(imx->clk_per); 323 ret = imx_pwm_clk_prepare_enable(chip);
290 if (ret) 324 if (ret)
291 return ret; 325 return ret;
292 326
@@ -309,7 +343,7 @@ static int imx_pwm_apply_v2(struct pwm_chip *chip, struct pwm_device *pwm,
309 } else if (cstate.enabled) { 343 } else if (cstate.enabled) {
310 writel(0, imx->mmio_base + MX3_PWMCR); 344 writel(0, imx->mmio_base + MX3_PWMCR);
311 345
312 clk_disable_unprepare(imx->clk_per); 346 imx_pwm_clk_disable_unprepare(chip);
313 } 347 }
314 348
315 return 0; 349 return 0;
@@ -367,6 +401,13 @@ static int imx_pwm_probe(struct platform_device *pdev)
367 if (imx == NULL) 401 if (imx == NULL)
368 return -ENOMEM; 402 return -ENOMEM;
369 403
404 imx->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
405 if (IS_ERR(imx->clk_ipg)) {
406 dev_err(&pdev->dev, "getting ipg clock failed with %ld\n",
407 PTR_ERR(imx->clk_ipg));
408 return PTR_ERR(imx->clk_ipg);
409 }
410
370 imx->clk_per = devm_clk_get(&pdev->dev, "per"); 411 imx->clk_per = devm_clk_get(&pdev->dev, "per");
371 if (IS_ERR(imx->clk_per)) { 412 if (IS_ERR(imx->clk_per)) {
372 dev_err(&pdev->dev, "getting per clock failed with %ld\n", 413 dev_err(&pdev->dev, "getting per clock failed with %ld\n",
@@ -406,6 +447,8 @@ static int imx_pwm_remove(struct platform_device *pdev)
406 if (imx == NULL) 447 if (imx == NULL)
407 return -ENODEV; 448 return -ENODEV;
408 449
450 imx_pwm_clk_disable_unprepare(&imx->chip);
451
409 return pwmchip_remove(&imx->chip); 452 return pwmchip_remove(&imx->chip);
410} 453}
411 454