aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/amba/bus.c
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2011-08-14 04:13:48 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2011-09-22 11:21:42 -0400
commit92b97f0aaccbf9de4a29696e6253bf82e8850d1d (patch)
tree0da0f934d8451ca450186c3a77d4fb6de7909f4b /drivers/amba/bus.c
parent93ee7a9340d64f20295aacc3fb6a22b759323280 (diff)
PM: add runtime PM support to core Primecell driver
Add runtime PM support to the core Primecell driver, following the PCI model of how this is done. Rather than having every driver fiddle about with enabling runtime PM, that's dealt with in the core and instead, drivers just do a put() in their probe and a balancing get() in their remove function to activate runtime PM for the device. As we're dealing with enabling runtime PM in the core, fix up spi-pl022 as it must not enable and disable runtime PM itself anymore. Tested-by: Linus Walleij <linus.walleij@linaro.org> Acked-by: Rafael J. Wysocki <rjw@sisk.pl> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'drivers/amba/bus.c')
-rw-r--r--drivers/amba/bus.c57
1 files changed, 54 insertions, 3 deletions
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
index d74926e0939e..84bdaace56c8 100644
--- a/drivers/amba/bus.c
+++ b/drivers/amba/bus.c
@@ -365,6 +365,40 @@ static int amba_pm_restore_noirq(struct device *dev)
365 365
366#endif /* !CONFIG_HIBERNATE_CALLBACKS */ 366#endif /* !CONFIG_HIBERNATE_CALLBACKS */
367 367
368#ifdef CONFIG_PM_RUNTIME
369/*
370 * Hooks to provide runtime PM of the pclk (bus clock). It is safe to
371 * enable/disable the bus clock at runtime PM suspend/resume as this
372 * does not result in loss of context. However, disabling vcore power
373 * would do, so we leave that to the driver.
374 */
375static int amba_pm_runtime_suspend(struct device *dev)
376{
377 struct amba_device *pcdev = to_amba_device(dev);
378 int ret = pm_generic_runtime_suspend(dev);
379
380 if (ret == 0 && dev->driver)
381 clk_disable(pcdev->pclk);
382
383 return ret;
384}
385
386static int amba_pm_runtime_resume(struct device *dev)
387{
388 struct amba_device *pcdev = to_amba_device(dev);
389 int ret;
390
391 if (dev->driver) {
392 ret = clk_enable(pcdev->pclk);
393 /* Failure is probably fatal to the system, but... */
394 if (ret)
395 return ret;
396 }
397
398 return pm_generic_runtime_resume(dev);
399}
400#endif
401
368#ifdef CONFIG_PM 402#ifdef CONFIG_PM
369 403
370static const struct dev_pm_ops amba_pm = { 404static const struct dev_pm_ops amba_pm = {
@@ -383,8 +417,8 @@ static const struct dev_pm_ops amba_pm = {
383 .poweroff_noirq = amba_pm_poweroff_noirq, 417 .poweroff_noirq = amba_pm_poweroff_noirq,
384 .restore_noirq = amba_pm_restore_noirq, 418 .restore_noirq = amba_pm_restore_noirq,
385 SET_RUNTIME_PM_OPS( 419 SET_RUNTIME_PM_OPS(
386 pm_generic_runtime_suspend, 420 amba_pm_runtime_suspend,
387 pm_generic_runtime_resume, 421 amba_pm_runtime_resume,
388 pm_generic_runtime_idle 422 pm_generic_runtime_idle
389 ) 423 )
390}; 424};
@@ -494,10 +528,18 @@ static int amba_probe(struct device *dev)
494 if (ret) 528 if (ret)
495 break; 529 break;
496 530
531 pm_runtime_get_noresume(dev);
532 pm_runtime_set_active(dev);
533 pm_runtime_enable(dev);
534
497 ret = pcdrv->probe(pcdev, id); 535 ret = pcdrv->probe(pcdev, id);
498 if (ret == 0) 536 if (ret == 0)
499 break; 537 break;
500 538
539 pm_runtime_disable(dev);
540 pm_runtime_set_suspended(dev);
541 pm_runtime_put_noidle(dev);
542
501 amba_put_disable_pclk(pcdev); 543 amba_put_disable_pclk(pcdev);
502 amba_put_disable_vcore(pcdev); 544 amba_put_disable_vcore(pcdev);
503 } while (0); 545 } while (0);
@@ -509,7 +551,16 @@ static int amba_remove(struct device *dev)
509{ 551{
510 struct amba_device *pcdev = to_amba_device(dev); 552 struct amba_device *pcdev = to_amba_device(dev);
511 struct amba_driver *drv = to_amba_driver(dev->driver); 553 struct amba_driver *drv = to_amba_driver(dev->driver);
512 int ret = drv->remove(pcdev); 554 int ret;
555
556 pm_runtime_get_sync(dev);
557 ret = drv->remove(pcdev);
558 pm_runtime_put_noidle(dev);
559
560 /* Undo the runtime PM settings in amba_probe() */
561 pm_runtime_disable(dev);
562 pm_runtime_set_suspended(dev);
563 pm_runtime_put_noidle(dev);
513 564
514 amba_put_disable_pclk(pcdev); 565 amba_put_disable_pclk(pcdev);
515 amba_put_disable_vcore(pcdev); 566 amba_put_disable_vcore(pcdev);