aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pwm/pwm-imx.c
diff options
context:
space:
mode:
authorPhilipp Zabel <p.zabel@pengutronix.de>2012-06-25 10:15:20 -0400
committerThierry Reding <thierry.reding@avionic-design.de>2012-09-12 08:25:07 -0400
commit7b27c160c68152581c702b9f1fe362338d2a0cad (patch)
tree0fb2f975f42b1aadcbddb2ff25b06f7c525b112e /drivers/pwm/pwm-imx.c
parent8d1c24bfd20829f5943c76b85c4973db264dd666 (diff)
pwm: i.MX: fix clock lookup
The i.MX PWM core has two clocks: The ipg clock and the ipg highfreq (peripheral) clock. The ipg clock has to be enabled for this hardware to work. The actual PWM output can either be driven by the ipg clock or the ipg highfreq. The ipg highfreq has the advantage that it runs even when the SoC is in low power modes. This patch requests both clocks and enables the ipg clock for accessing registers and the peripheral clock to actually turn on the PWM. Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> Reviewed-by: Shawn Guo <shawn.guo@linaro.org> Reviewed-by: Benoît Thébaudeau <benoit.thebaudeau@advansee.com> Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>
Diffstat (limited to 'drivers/pwm/pwm-imx.c')
-rw-r--r--drivers/pwm/pwm-imx.c35
1 files changed, 27 insertions, 8 deletions
diff --git a/drivers/pwm/pwm-imx.c b/drivers/pwm/pwm-imx.c
index 852de6ce6e11..8a5d3ae2946a 100644
--- a/drivers/pwm/pwm-imx.c
+++ b/drivers/pwm/pwm-imx.c
@@ -40,7 +40,8 @@
40#define MX3_PWMCR_EN (1 << 0) 40#define MX3_PWMCR_EN (1 << 0)
41 41
42struct imx_chip { 42struct imx_chip {
43 struct clk *clk; 43 struct clk *clk_per;
44 struct clk *clk_ipg;
44 45
45 int enabled; 46 int enabled;
46 void __iomem *mmio_base; 47 void __iomem *mmio_base;
@@ -106,7 +107,7 @@ static int imx_pwm_config_v2(struct pwm_chip *chip,
106 unsigned long period_cycles, duty_cycles, prescale; 107 unsigned long period_cycles, duty_cycles, prescale;
107 u32 cr; 108 u32 cr;
108 109
109 c = clk_get_rate(imx->clk); 110 c = clk_get_rate(imx->clk_per);
110 c = c * period_ns; 111 c = c * period_ns;
111 do_div(c, 1000000000); 112 do_div(c, 1000000000);
112 period_cycles = c; 113 period_cycles = c;
@@ -161,8 +162,17 @@ static int imx_pwm_config(struct pwm_chip *chip,
161 struct pwm_device *pwm, int duty_ns, int period_ns) 162 struct pwm_device *pwm, int duty_ns, int period_ns)
162{ 163{
163 struct imx_chip *imx = to_imx_chip(chip); 164 struct imx_chip *imx = to_imx_chip(chip);
165 int ret;
166
167 ret = clk_prepare_enable(imx->clk_ipg);
168 if (ret)
169 return ret;
164 170
165 return imx->config(chip, pwm, duty_ns, period_ns); 171 ret = imx->config(chip, pwm, duty_ns, period_ns);
172
173 clk_disable_unprepare(imx->clk_ipg);
174
175 return ret;
166} 176}
167 177
168static int imx_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) 178static int imx_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
@@ -170,7 +180,7 @@ static int imx_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
170 struct imx_chip *imx = to_imx_chip(chip); 180 struct imx_chip *imx = to_imx_chip(chip);
171 int ret; 181 int ret;
172 182
173 ret = clk_prepare_enable(imx->clk); 183 ret = clk_prepare_enable(imx->clk_per);
174 if (ret) 184 if (ret)
175 return ret; 185 return ret;
176 186
@@ -187,7 +197,7 @@ static void imx_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
187 197
188 imx->set_enable(chip, false); 198 imx->set_enable(chip, false);
189 199
190 clk_disable_unprepare(imx->clk); 200 clk_disable_unprepare(imx->clk_per);
191 imx->enabled = 0; 201 imx->enabled = 0;
192} 202}
193 203
@@ -239,10 +249,19 @@ static int __devinit imx_pwm_probe(struct platform_device *pdev)
239 return -ENOMEM; 249 return -ENOMEM;
240 } 250 }
241 251
242 imx->clk = devm_clk_get(&pdev->dev, "pwm"); 252 imx->clk_per = devm_clk_get(&pdev->dev, "per");
253 if (IS_ERR(imx->clk_per)) {
254 dev_err(&pdev->dev, "getting per clock failed with %ld\n",
255 PTR_ERR(imx->clk_per));
256 return PTR_ERR(imx->clk_per);
257 }
243 258
244 if (IS_ERR(imx->clk)) 259 imx->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
245 return PTR_ERR(imx->clk); 260 if (IS_ERR(imx->clk_ipg)) {
261 dev_err(&pdev->dev, "getting ipg clock failed with %ld\n",
262 PTR_ERR(imx->clk_ipg));
263 return PTR_ERR(imx->clk_ipg);
264 }
246 265
247 imx->chip.ops = &imx_pwm_ops; 266 imx->chip.ops = &imx_pwm_ops;
248 imx->chip.dev = &pdev->dev; 267 imx->chip.dev = &pdev->dev;