summaryrefslogtreecommitdiffstats
path: root/drivers/pwm/pwm-img.c
diff options
context:
space:
mode:
authorEd Blake <ed.blake@sondrel.com>2017-10-02 05:51:48 -0400
committerThierry Reding <thierry.reding@gmail.com>2017-11-15 04:38:37 -0500
commite690ae526216b913c61977193eb7e4b803511e75 (patch)
treeadcd6ab6102c737a2593155233558c54798574cc /drivers/pwm/pwm-img.c
parenta18afce522e8c469132e740f840f2b95b2008987 (diff)
pwm: img: Add runtime PM
Add runtime PM to disable the clocks when the h/w is not in use. Signed-off-by: Ed Blake <ed.blake@sondrel.com> Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
Diffstat (limited to 'drivers/pwm/pwm-img.c')
-rw-r--r--drivers/pwm/pwm-img.c132
1 files changed, 95 insertions, 37 deletions
diff --git a/drivers/pwm/pwm-img.c b/drivers/pwm/pwm-img.c
index b54daf2917bf..815f5333bb8f 100644
--- a/drivers/pwm/pwm-img.c
+++ b/drivers/pwm/pwm-img.c
@@ -18,6 +18,7 @@
18#include <linux/of.h> 18#include <linux/of.h>
19#include <linux/of_device.h> 19#include <linux/of_device.h>
20#include <linux/platform_device.h> 20#include <linux/platform_device.h>
21#include <linux/pm_runtime.h>
21#include <linux/pwm.h> 22#include <linux/pwm.h>
22#include <linux/regmap.h> 23#include <linux/regmap.h>
23#include <linux/slab.h> 24#include <linux/slab.h>
@@ -39,6 +40,8 @@
39#define PERIP_PWM_PDM_CONTROL_CH_MASK 0x1 40#define PERIP_PWM_PDM_CONTROL_CH_MASK 0x1
40#define PERIP_PWM_PDM_CONTROL_CH_SHIFT(ch) ((ch) * 4) 41#define PERIP_PWM_PDM_CONTROL_CH_SHIFT(ch) ((ch) * 4)
41 42
43#define IMG_PWM_PM_TIMEOUT 1000 /* ms */
44
42/* 45/*
43 * PWM period is specified with a timebase register, 46 * PWM period is specified with a timebase register,
44 * in number of step periods. The PWM duty cycle is also 47 * in number of step periods. The PWM duty cycle is also
@@ -96,6 +99,7 @@ static int img_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
96 unsigned long mul, output_clk_hz, input_clk_hz; 99 unsigned long mul, output_clk_hz, input_clk_hz;
97 struct img_pwm_chip *pwm_chip = to_img_pwm_chip(chip); 100 struct img_pwm_chip *pwm_chip = to_img_pwm_chip(chip);
98 unsigned int max_timebase = pwm_chip->data->max_timebase; 101 unsigned int max_timebase = pwm_chip->data->max_timebase;
102 int ret;
99 103
100 if (period_ns < pwm_chip->min_period_ns || 104 if (period_ns < pwm_chip->min_period_ns ||
101 period_ns > pwm_chip->max_period_ns) { 105 period_ns > pwm_chip->max_period_ns) {
@@ -127,6 +131,10 @@ static int img_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
127 131
128 duty = DIV_ROUND_UP(timebase * duty_ns, period_ns); 132 duty = DIV_ROUND_UP(timebase * duty_ns, period_ns);
129 133
134 ret = pm_runtime_get_sync(chip->dev);
135 if (ret < 0)
136 return ret;
137
130 val = img_pwm_readl(pwm_chip, PWM_CTRL_CFG); 138 val = img_pwm_readl(pwm_chip, PWM_CTRL_CFG);
131 val &= ~(PWM_CTRL_CFG_DIV_MASK << PWM_CTRL_CFG_DIV_SHIFT(pwm->hwpwm)); 139 val &= ~(PWM_CTRL_CFG_DIV_MASK << PWM_CTRL_CFG_DIV_SHIFT(pwm->hwpwm));
132 val |= (div & PWM_CTRL_CFG_DIV_MASK) << 140 val |= (div & PWM_CTRL_CFG_DIV_MASK) <<
@@ -137,6 +145,9 @@ static int img_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
137 (timebase << PWM_CH_CFG_TMBASE_SHIFT); 145 (timebase << PWM_CH_CFG_TMBASE_SHIFT);
138 img_pwm_writel(pwm_chip, PWM_CH_CFG(pwm->hwpwm), val); 146 img_pwm_writel(pwm_chip, PWM_CH_CFG(pwm->hwpwm), val);
139 147
148 pm_runtime_mark_last_busy(chip->dev);
149 pm_runtime_put_autosuspend(chip->dev);
150
140 return 0; 151 return 0;
141} 152}
142 153
@@ -144,6 +155,11 @@ static int img_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
144{ 155{
145 u32 val; 156 u32 val;
146 struct img_pwm_chip *pwm_chip = to_img_pwm_chip(chip); 157 struct img_pwm_chip *pwm_chip = to_img_pwm_chip(chip);
158 int ret;
159
160 ret = pm_runtime_get_sync(chip->dev);
161 if (ret < 0)
162 return ret;
147 163
148 val = img_pwm_readl(pwm_chip, PWM_CTRL_CFG); 164 val = img_pwm_readl(pwm_chip, PWM_CTRL_CFG);
149 val |= BIT(pwm->hwpwm); 165 val |= BIT(pwm->hwpwm);
@@ -164,6 +180,9 @@ static void img_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
164 val = img_pwm_readl(pwm_chip, PWM_CTRL_CFG); 180 val = img_pwm_readl(pwm_chip, PWM_CTRL_CFG);
165 val &= ~BIT(pwm->hwpwm); 181 val &= ~BIT(pwm->hwpwm);
166 img_pwm_writel(pwm_chip, PWM_CTRL_CFG, val); 182 img_pwm_writel(pwm_chip, PWM_CTRL_CFG, val);
183
184 pm_runtime_mark_last_busy(chip->dev);
185 pm_runtime_put_autosuspend(chip->dev);
167} 186}
168 187
169static const struct pwm_ops img_pwm_ops = { 188static const struct pwm_ops img_pwm_ops = {
@@ -186,6 +205,37 @@ static const struct of_device_id img_pwm_of_match[] = {
186}; 205};
187MODULE_DEVICE_TABLE(of, img_pwm_of_match); 206MODULE_DEVICE_TABLE(of, img_pwm_of_match);
188 207
208static int img_pwm_runtime_suspend(struct device *dev)
209{
210 struct img_pwm_chip *pwm_chip = dev_get_drvdata(dev);
211
212 clk_disable_unprepare(pwm_chip->pwm_clk);
213 clk_disable_unprepare(pwm_chip->sys_clk);
214
215 return 0;
216}
217
218static int img_pwm_runtime_resume(struct device *dev)
219{
220 struct img_pwm_chip *pwm_chip = dev_get_drvdata(dev);
221 int ret;
222
223 ret = clk_prepare_enable(pwm_chip->sys_clk);
224 if (ret < 0) {
225 dev_err(dev, "could not prepare or enable sys clock\n");
226 return ret;
227 }
228
229 ret = clk_prepare_enable(pwm_chip->pwm_clk);
230 if (ret < 0) {
231 dev_err(dev, "could not prepare or enable pwm clock\n");
232 clk_disable_unprepare(pwm_chip->sys_clk);
233 return ret;
234 }
235
236 return 0;
237}
238
189static int img_pwm_probe(struct platform_device *pdev) 239static int img_pwm_probe(struct platform_device *pdev)
190{ 240{
191 int ret; 241 int ret;
@@ -228,23 +278,20 @@ static int img_pwm_probe(struct platform_device *pdev)
228 return PTR_ERR(pwm->pwm_clk); 278 return PTR_ERR(pwm->pwm_clk);
229 } 279 }
230 280
231 ret = clk_prepare_enable(pwm->sys_clk); 281 pm_runtime_set_autosuspend_delay(&pdev->dev, IMG_PWM_PM_TIMEOUT);
232 if (ret < 0) { 282 pm_runtime_use_autosuspend(&pdev->dev);
233 dev_err(&pdev->dev, "could not prepare or enable sys clock\n"); 283 pm_runtime_enable(&pdev->dev);
234 return ret; 284 if (!pm_runtime_enabled(&pdev->dev)) {
235 } 285 ret = img_pwm_runtime_resume(&pdev->dev);
236 286 if (ret)
237 ret = clk_prepare_enable(pwm->pwm_clk); 287 goto err_pm_disable;
238 if (ret < 0) {
239 dev_err(&pdev->dev, "could not prepare or enable pwm clock\n");
240 goto disable_sysclk;
241 } 288 }
242 289
243 clk_rate = clk_get_rate(pwm->pwm_clk); 290 clk_rate = clk_get_rate(pwm->pwm_clk);
244 if (!clk_rate) { 291 if (!clk_rate) {
245 dev_err(&pdev->dev, "pwm clock has no frequency\n"); 292 dev_err(&pdev->dev, "pwm clock has no frequency\n");
246 ret = -EINVAL; 293 ret = -EINVAL;
247 goto disable_pwmclk; 294 goto err_suspend;
248 } 295 }
249 296
250 /* The maximum input clock divider is 512 */ 297 /* The maximum input clock divider is 512 */
@@ -264,16 +311,18 @@ static int img_pwm_probe(struct platform_device *pdev)
264 ret = pwmchip_add(&pwm->chip); 311 ret = pwmchip_add(&pwm->chip);
265 if (ret < 0) { 312 if (ret < 0) {
266 dev_err(&pdev->dev, "pwmchip_add failed: %d\n", ret); 313 dev_err(&pdev->dev, "pwmchip_add failed: %d\n", ret);
267 goto disable_pwmclk; 314 goto err_suspend;
268 } 315 }
269 316
270 platform_set_drvdata(pdev, pwm); 317 platform_set_drvdata(pdev, pwm);
271 return 0; 318 return 0;
272 319
273disable_pwmclk: 320err_suspend:
274 clk_disable_unprepare(pwm->pwm_clk); 321 if (!pm_runtime_enabled(&pdev->dev))
275disable_sysclk: 322 img_pwm_runtime_suspend(&pdev->dev);
276 clk_disable_unprepare(pwm->sys_clk); 323err_pm_disable:
324 pm_runtime_disable(&pdev->dev);
325 pm_runtime_dont_use_autosuspend(&pdev->dev);
277 return ret; 326 return ret;
278} 327}
279 328
@@ -282,6 +331,11 @@ static int img_pwm_remove(struct platform_device *pdev)
282 struct img_pwm_chip *pwm_chip = platform_get_drvdata(pdev); 331 struct img_pwm_chip *pwm_chip = platform_get_drvdata(pdev);
283 u32 val; 332 u32 val;
284 unsigned int i; 333 unsigned int i;
334 int ret;
335
336 ret = pm_runtime_get_sync(&pdev->dev);
337 if (ret < 0)
338 return ret;
285 339
286 for (i = 0; i < pwm_chip->chip.npwm; i++) { 340 for (i = 0; i < pwm_chip->chip.npwm; i++) {
287 val = img_pwm_readl(pwm_chip, PWM_CTRL_CFG); 341 val = img_pwm_readl(pwm_chip, PWM_CTRL_CFG);
@@ -289,8 +343,10 @@ static int img_pwm_remove(struct platform_device *pdev)
289 img_pwm_writel(pwm_chip, PWM_CTRL_CFG, val); 343 img_pwm_writel(pwm_chip, PWM_CTRL_CFG, val);
290 } 344 }
291 345
292 clk_disable_unprepare(pwm_chip->pwm_clk); 346 pm_runtime_put(&pdev->dev);
293 clk_disable_unprepare(pwm_chip->sys_clk); 347 pm_runtime_disable(&pdev->dev);
348 if (!pm_runtime_status_suspended(&pdev->dev))
349 img_pwm_runtime_suspend(&pdev->dev);
294 350
295 return pwmchip_remove(&pwm_chip->chip); 351 return pwmchip_remove(&pwm_chip->chip);
296} 352}
@@ -298,9 +354,14 @@ static int img_pwm_remove(struct platform_device *pdev)
298#ifdef CONFIG_PM_SLEEP 354#ifdef CONFIG_PM_SLEEP
299static int img_pwm_suspend(struct device *dev) 355static int img_pwm_suspend(struct device *dev)
300{ 356{
301 struct platform_device *pdev = to_platform_device(dev); 357 struct img_pwm_chip *pwm_chip = dev_get_drvdata(dev);
302 struct img_pwm_chip *pwm_chip = platform_get_drvdata(pdev); 358 int i, ret;
303 int i; 359
360 if (pm_runtime_status_suspended(dev)) {
361 ret = img_pwm_runtime_resume(dev);
362 if (ret)
363 return ret;
364 }
304 365
305 for (i = 0; i < pwm_chip->chip.npwm; i++) 366 for (i = 0; i < pwm_chip->chip.npwm; i++)
306 pwm_chip->suspend_ch_cfg[i] = img_pwm_readl(pwm_chip, 367 pwm_chip->suspend_ch_cfg[i] = img_pwm_readl(pwm_chip,
@@ -308,31 +369,20 @@ static int img_pwm_suspend(struct device *dev)
308 369
309 pwm_chip->suspend_ctrl_cfg = img_pwm_readl(pwm_chip, PWM_CTRL_CFG); 370 pwm_chip->suspend_ctrl_cfg = img_pwm_readl(pwm_chip, PWM_CTRL_CFG);
310 371
311 clk_disable_unprepare(pwm_chip->pwm_clk); 372 img_pwm_runtime_suspend(dev);
312 clk_disable_unprepare(pwm_chip->sys_clk);
313 373
314 return 0; 374 return 0;
315} 375}
316 376
317static int img_pwm_resume(struct device *dev) 377static int img_pwm_resume(struct device *dev)
318{ 378{
319 struct platform_device *pdev = to_platform_device(dev); 379 struct img_pwm_chip *pwm_chip = dev_get_drvdata(dev);
320 struct img_pwm_chip *pwm_chip = platform_get_drvdata(pdev);
321 int ret; 380 int ret;
322 int i; 381 int i;
323 382
324 ret = clk_prepare_enable(pwm_chip->sys_clk); 383 ret = img_pwm_runtime_resume(dev);
325 if (ret < 0) { 384 if (ret)
326 dev_err(&pdev->dev, "could not prepare or enable sys clock\n");
327 return ret; 385 return ret;
328 }
329
330 ret = clk_prepare_enable(pwm_chip->pwm_clk);
331 if (ret < 0) {
332 dev_err(&pdev->dev, "could not prepare or enable pwm clock\n");
333 clk_disable_unprepare(pwm_chip->sys_clk);
334 return ret;
335 }
336 386
337 for (i = 0; i < pwm_chip->chip.npwm; i++) 387 for (i = 0; i < pwm_chip->chip.npwm; i++)
338 img_pwm_writel(pwm_chip, PWM_CH_CFG(i), 388 img_pwm_writel(pwm_chip, PWM_CH_CFG(i),
@@ -348,11 +398,19 @@ static int img_pwm_resume(struct device *dev)
348 PERIP_PWM_PDM_CONTROL_CH_SHIFT(i), 398 PERIP_PWM_PDM_CONTROL_CH_SHIFT(i),
349 0); 399 0);
350 400
401 if (pm_runtime_status_suspended(dev))
402 img_pwm_runtime_suspend(dev);
403
351 return 0; 404 return 0;
352} 405}
353#endif /* CONFIG_PM */ 406#endif /* CONFIG_PM */
354 407
355SIMPLE_DEV_PM_OPS(img_pwm_pm_ops, img_pwm_suspend, img_pwm_resume); 408static const struct dev_pm_ops img_pwm_pm_ops = {
409 SET_RUNTIME_PM_OPS(img_pwm_runtime_suspend,
410 img_pwm_runtime_resume,
411 NULL)
412 SET_SYSTEM_SLEEP_PM_OPS(img_pwm_suspend, img_pwm_resume)
413};
356 414
357static struct platform_driver img_pwm_driver = { 415static struct platform_driver img_pwm_driver = {
358 .driver = { 416 .driver = {