summaryrefslogtreecommitdiffstats
path: root/drivers/pwm
diff options
context:
space:
mode:
authorAnson Huang <anson.huang@nxp.com>2018-12-19 00:24:58 -0500
committerThierry Reding <thierry.reding@gmail.com>2018-12-24 06:06:56 -0500
commit9f4c8f9607c3147d291b70c13dd01c738ed41faf (patch)
tree6fc107417a425b3a0f55f516ee12c0017daa2198 /drivers/pwm
parentf236d188683667274824de662d124720198730b7 (diff)
pwm: imx: Add ipg clock operation
i.MX PWM module's ipg_clk_s is for PWM register access, on most of i.MX SoCs, this ipg_clk_s is from system ipg clock or perclk which is always enabled, but on i.MX7D, the ipg_clk_s is from PWM1_CLK_ROOT which is controlled by CCGR132, that means the CCGR132 MUST be enabled first before accessing PWM registers on i.MX7D. This patch adds ipg clock operation to make sure register access successfully on i.MX7D and it fixes Linux kernel boot up hang during PWM driver probe. Fixes: 4a23e6ee9f69 ("ARM: dts: imx7d-sdb: Restore pwm backlight support") Signed-off-by: Anson Huang <Anson.Huang@nxp.com> Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
Diffstat (limited to 'drivers/pwm')
-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