diff options
Diffstat (limited to 'drivers/usb/musb')
-rw-r--r-- | drivers/usb/musb/musb_core.c | 40 | ||||
-rw-r--r-- | drivers/usb/musb/musb_gadget.c | 11 | ||||
-rw-r--r-- | drivers/usb/musb/omap2430.c | 49 |
3 files changed, 78 insertions, 22 deletions
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index bc296557dc1..36376d2b1a7 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) diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 2a3aee4e108..5c7b321d395 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -1821,6 +1821,8 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, goto err0; } + pm_runtime_get_sync(musb->controller); + DBG(3, "registering driver %s\n", driver->function); if (musb->gadget_driver) { @@ -1885,6 +1887,10 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, } hcd->self.uses_pio_for_control = 1; + + if (musb->xceiv->last_event == USB_EVENT_NONE) + pm_runtime_put(musb->controller); + } return 0; @@ -1961,6 +1967,9 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) if (!musb->gadget_driver) return -EINVAL; + if (musb->xceiv->last_event == USB_EVENT_NONE) + pm_runtime_get_sync(musb->controller); + /* * REVISIT always use otg_set_peripheral() here too; * this needs to shut down the OTG engine. @@ -2002,6 +2011,8 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) if (!is_otg_enabled(musb)) musb_stop(musb); + pm_runtime_put(musb->controller); + return 0; } EXPORT_SYMBOL(usb_gadget_unregister_driver); diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index b6dcc7eaa21..47267987077 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -244,6 +244,7 @@ static int musb_otg_notifications(struct notifier_block *nb, if (is_otg_enabled(musb)) { #ifdef CONFIG_USB_GADGET_MUSB_HDRC if (musb->gadget_driver) { + pm_runtime_get_sync(musb->controller); otg_init(musb->xceiv); if (data->interface_type == @@ -253,6 +254,7 @@ static int musb_otg_notifications(struct notifier_block *nb, } #endif } else { + pm_runtime_get_sync(musb->controller); otg_init(musb->xceiv); if (data->interface_type == MUSB_INTERFACE_UTMI) @@ -263,12 +265,24 @@ static int musb_otg_notifications(struct notifier_block *nb, case USB_EVENT_VBUS: DBG(4, "VBUS Connect\n"); + if (musb->gadget_driver) + pm_runtime_get_sync(musb->controller); + otg_init(musb->xceiv); break; case USB_EVENT_NONE: DBG(4, "VBUS Disconnect\n"); +#ifdef CONFIG_USB_GADGET_MUSB_HDRC + if (is_otg_enabled(musb)) + if (musb->gadget_driver) +#endif + { + pm_runtime_mark_last_busy(musb->controller); + pm_runtime_put_autosuspend(musb->controller); + } + if (data->interface_type == MUSB_INTERFACE_UTMI) { if (musb->xceiv->set_vbus) otg_set_vbus(musb->xceiv, 0); @@ -300,7 +314,11 @@ static int omap2430_musb_init(struct musb *musb) return -ENODEV; } - omap2430_low_level_init(musb); + status = pm_runtime_get_sync(dev); + if (status < 0) { + dev_err(dev, "pm_runtime_get_sync FAILED"); + goto err1; + } l = musb_readl(musb->mregs, OTG_INTERFSEL); @@ -331,6 +349,10 @@ static int omap2430_musb_init(struct musb *musb) setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb); return 0; + +err1: + pm_runtime_disable(dev); + return status; } static void omap2430_musb_enable(struct musb *musb) @@ -407,8 +429,6 @@ static int __init omap2430_probe(struct platform_device *pdev) struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; struct platform_device *musb; struct omap2430_glue *glue; - int status = 0; - int ret = -ENOMEM; glue = kzalloc(sizeof(*glue), GFP_KERNEL); @@ -454,16 +474,9 @@ static int __init omap2430_probe(struct platform_device *pdev) } pm_runtime_enable(&pdev->dev); - status = pm_runtime_get_sync(&pdev->dev); - if (status < 0) { - dev_err(&pdev->dev, "pm_runtime_get_sync FAILED"); - goto err3; - } return 0; -err3: - pm_runtime_disable(&pdev->dev); err2: platform_device_put(musb); @@ -489,7 +502,7 @@ static int __exit omap2430_remove(struct platform_device *pdev) #ifdef CONFIG_PM -static int omap2430_suspend(struct device *dev) +static int omap2430_runtime_suspend(struct device *dev) { struct omap2430_glue *glue = dev_get_drvdata(dev); struct musb *musb = glue_to_musb(glue); @@ -497,22 +510,14 @@ static int omap2430_suspend(struct device *dev) omap2430_low_level_exit(musb); otg_set_suspend(musb->xceiv, 1); - if (!pm_runtime_suspended(dev) && dev->bus && dev->bus->pm && - dev->bus->pm->runtime_suspend) - dev->bus->pm->runtime_suspend(dev); - return 0; } -static int omap2430_resume(struct device *dev) +static int omap2430_runtime_resume(struct device *dev) { struct omap2430_glue *glue = dev_get_drvdata(dev); struct musb *musb = glue_to_musb(glue); - if (!pm_runtime_suspended(dev) && dev->bus && dev->bus->pm && - dev->bus->pm->runtime_resume) - dev->bus->pm->runtime_resume(dev); - omap2430_low_level_init(musb); otg_set_suspend(musb->xceiv, 0); @@ -520,8 +525,8 @@ static int omap2430_resume(struct device *dev) } static struct dev_pm_ops omap2430_pm_ops = { - .suspend = omap2430_suspend, - .resume = omap2430_resume, + .runtime_suspend = omap2430_runtime_suspend, + .runtime_resume = omap2430_runtime_resume, }; #define DEV_PM_OPS (&omap2430_pm_ops) |