diff options
Diffstat (limited to 'drivers/usb/musb/musb_core.c')
-rw-r--r-- | drivers/usb/musb/musb_core.c | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index bc296557dc1b..36376d2b1a7c 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1956,6 +1956,10 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) goto fail0; } + pm_runtime_use_autosuspend(musb->controller); + pm_runtime_set_autosuspend_delay(musb->controller, 200); + pm_runtime_enable(musb->controller); + spin_lock_init(&musb->lock); musb->board_mode = plat->mode; musb->board_set_power = plat->set_power; @@ -2091,6 +2095,8 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) if (status < 0) goto fail3; + pm_runtime_put(musb->controller); + status = musb_init_debugfs(musb); if (status < 0) goto fail4; @@ -2190,9 +2196,11 @@ static int __exit musb_remove(struct platform_device *pdev) * - Peripheral mode: peripheral is deactivated (or never-activated) * - OTG mode: both roles are deactivated (or never-activated) */ + pm_runtime_get_sync(musb->controller); musb_exit_debugfs(musb); musb_shutdown(pdev); + pm_runtime_put(musb->controller); musb_free(musb); iounmap(ctrl_base); device_init_wakeup(&pdev->dev, 0); @@ -2378,9 +2386,41 @@ static int musb_resume_noirq(struct device *dev) return 0; } +static int musb_runtime_suspend(struct device *dev) +{ + struct musb *musb = dev_to_musb(dev); + + musb_save_context(musb); + + return 0; +} + +static int musb_runtime_resume(struct device *dev) +{ + struct musb *musb = dev_to_musb(dev); + static int first = 1; + + /* + * When pm_runtime_get_sync called for the first time in driver + * init, some of the structure is still not initialized which is + * used in restore function. But clock needs to be + * enabled before any register access, so + * pm_runtime_get_sync has to be called. + * Also context restore without save does not make + * any sense + */ + if (!first) + musb_restore_context(musb); + first = 0; + + return 0; +} + static const struct dev_pm_ops musb_dev_pm_ops = { .suspend = musb_suspend, .resume_noirq = musb_resume_noirq, + .runtime_suspend = musb_runtime_suspend, + .runtime_resume = musb_runtime_resume, }; #define MUSB_DEV_PM_OPS (&musb_dev_pm_ops) |