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 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) | |||
1956 | goto fail0; | 1956 | goto fail0; |
1957 | } | 1957 | } |
1958 | 1958 | ||
1959 | pm_runtime_use_autosuspend(musb->controller); | ||
1960 | pm_runtime_set_autosuspend_delay(musb->controller, 200); | ||
1961 | pm_runtime_enable(musb->controller); | ||
1962 | |||
1959 | spin_lock_init(&musb->lock); | 1963 | spin_lock_init(&musb->lock); |
1960 | musb->board_mode = plat->mode; | 1964 | musb->board_mode = plat->mode; |
1961 | musb->board_set_power = plat->set_power; | 1965 | musb->board_set_power = plat->set_power; |
@@ -2091,6 +2095,8 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) | |||
2091 | if (status < 0) | 2095 | if (status < 0) |
2092 | goto fail3; | 2096 | goto fail3; |
2093 | 2097 | ||
2098 | pm_runtime_put(musb->controller); | ||
2099 | |||
2094 | status = musb_init_debugfs(musb); | 2100 | status = musb_init_debugfs(musb); |
2095 | if (status < 0) | 2101 | if (status < 0) |
2096 | goto fail4; | 2102 | goto fail4; |
@@ -2190,9 +2196,11 @@ static int __exit musb_remove(struct platform_device *pdev) | |||
2190 | * - Peripheral mode: peripheral is deactivated (or never-activated) | 2196 | * - Peripheral mode: peripheral is deactivated (or never-activated) |
2191 | * - OTG mode: both roles are deactivated (or never-activated) | 2197 | * - OTG mode: both roles are deactivated (or never-activated) |
2192 | */ | 2198 | */ |
2199 | pm_runtime_get_sync(musb->controller); | ||
2193 | musb_exit_debugfs(musb); | 2200 | musb_exit_debugfs(musb); |
2194 | musb_shutdown(pdev); | 2201 | musb_shutdown(pdev); |
2195 | 2202 | ||
2203 | pm_runtime_put(musb->controller); | ||
2196 | musb_free(musb); | 2204 | musb_free(musb); |
2197 | iounmap(ctrl_base); | 2205 | iounmap(ctrl_base); |
2198 | device_init_wakeup(&pdev->dev, 0); | 2206 | device_init_wakeup(&pdev->dev, 0); |
@@ -2378,9 +2386,41 @@ static int musb_resume_noirq(struct device *dev) | |||
2378 | return 0; | 2386 | return 0; |
2379 | } | 2387 | } |
2380 | 2388 | ||
2389 | static int musb_runtime_suspend(struct device *dev) | ||
2390 | { | ||
2391 | struct musb *musb = dev_to_musb(dev); | ||
2392 | |||
2393 | musb_save_context(musb); | ||
2394 | |||
2395 | return 0; | ||
2396 | } | ||
2397 | |||
2398 | static int musb_runtime_resume(struct device *dev) | ||
2399 | { | ||
2400 | struct musb *musb = dev_to_musb(dev); | ||
2401 | static int first = 1; | ||
2402 | |||
2403 | /* | ||
2404 | * When pm_runtime_get_sync called for the first time in driver | ||
2405 | * init, some of the structure is still not initialized which is | ||
2406 | * used in restore function. But clock needs to be | ||
2407 | * enabled before any register access, so | ||
2408 | * pm_runtime_get_sync has to be called. | ||
2409 | * Also context restore without save does not make | ||
2410 | * any sense | ||
2411 | */ | ||
2412 | if (!first) | ||
2413 | musb_restore_context(musb); | ||
2414 | first = 0; | ||
2415 | |||
2416 | return 0; | ||
2417 | } | ||
2418 | |||
2381 | static const struct dev_pm_ops musb_dev_pm_ops = { | 2419 | static const struct dev_pm_ops musb_dev_pm_ops = { |
2382 | .suspend = musb_suspend, | 2420 | .suspend = musb_suspend, |
2383 | .resume_noirq = musb_resume_noirq, | 2421 | .resume_noirq = musb_resume_noirq, |
2422 | .runtime_suspend = musb_runtime_suspend, | ||
2423 | .runtime_resume = musb_runtime_resume, | ||
2384 | }; | 2424 | }; |
2385 | 2425 | ||
2386 | #define MUSB_DEV_PM_OPS (&musb_dev_pm_ops) | 2426 | #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 2a3aee4e108f..5c7b321d3959 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, | |||
1821 | goto err0; | 1821 | goto err0; |
1822 | } | 1822 | } |
1823 | 1823 | ||
1824 | pm_runtime_get_sync(musb->controller); | ||
1825 | |||
1824 | DBG(3, "registering driver %s\n", driver->function); | 1826 | DBG(3, "registering driver %s\n", driver->function); |
1825 | 1827 | ||
1826 | if (musb->gadget_driver) { | 1828 | if (musb->gadget_driver) { |
@@ -1885,6 +1887,10 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, | |||
1885 | } | 1887 | } |
1886 | 1888 | ||
1887 | hcd->self.uses_pio_for_control = 1; | 1889 | hcd->self.uses_pio_for_control = 1; |
1890 | |||
1891 | if (musb->xceiv->last_event == USB_EVENT_NONE) | ||
1892 | pm_runtime_put(musb->controller); | ||
1893 | |||
1888 | } | 1894 | } |
1889 | 1895 | ||
1890 | return 0; | 1896 | return 0; |
@@ -1961,6 +1967,9 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) | |||
1961 | if (!musb->gadget_driver) | 1967 | if (!musb->gadget_driver) |
1962 | return -EINVAL; | 1968 | return -EINVAL; |
1963 | 1969 | ||
1970 | if (musb->xceiv->last_event == USB_EVENT_NONE) | ||
1971 | pm_runtime_get_sync(musb->controller); | ||
1972 | |||
1964 | /* | 1973 | /* |
1965 | * REVISIT always use otg_set_peripheral() here too; | 1974 | * REVISIT always use otg_set_peripheral() here too; |
1966 | * this needs to shut down the OTG engine. | 1975 | * this needs to shut down the OTG engine. |
@@ -2002,6 +2011,8 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) | |||
2002 | if (!is_otg_enabled(musb)) | 2011 | if (!is_otg_enabled(musb)) |
2003 | musb_stop(musb); | 2012 | musb_stop(musb); |
2004 | 2013 | ||
2014 | pm_runtime_put(musb->controller); | ||
2015 | |||
2005 | return 0; | 2016 | return 0; |
2006 | } | 2017 | } |
2007 | EXPORT_SYMBOL(usb_gadget_unregister_driver); | 2018 | EXPORT_SYMBOL(usb_gadget_unregister_driver); |
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index b6dcc7eaa21f..47267987077d 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, | |||
244 | if (is_otg_enabled(musb)) { | 244 | if (is_otg_enabled(musb)) { |
245 | #ifdef CONFIG_USB_GADGET_MUSB_HDRC | 245 | #ifdef CONFIG_USB_GADGET_MUSB_HDRC |
246 | if (musb->gadget_driver) { | 246 | if (musb->gadget_driver) { |
247 | pm_runtime_get_sync(musb->controller); | ||
247 | otg_init(musb->xceiv); | 248 | otg_init(musb->xceiv); |
248 | 249 | ||
249 | if (data->interface_type == | 250 | if (data->interface_type == |
@@ -253,6 +254,7 @@ static int musb_otg_notifications(struct notifier_block *nb, | |||
253 | } | 254 | } |
254 | #endif | 255 | #endif |
255 | } else { | 256 | } else { |
257 | pm_runtime_get_sync(musb->controller); | ||
256 | otg_init(musb->xceiv); | 258 | otg_init(musb->xceiv); |
257 | if (data->interface_type == | 259 | if (data->interface_type == |
258 | MUSB_INTERFACE_UTMI) | 260 | MUSB_INTERFACE_UTMI) |
@@ -263,12 +265,24 @@ static int musb_otg_notifications(struct notifier_block *nb, | |||
263 | case USB_EVENT_VBUS: | 265 | case USB_EVENT_VBUS: |
264 | DBG(4, "VBUS Connect\n"); | 266 | DBG(4, "VBUS Connect\n"); |
265 | 267 | ||
268 | if (musb->gadget_driver) | ||
269 | pm_runtime_get_sync(musb->controller); | ||
270 | |||
266 | otg_init(musb->xceiv); | 271 | otg_init(musb->xceiv); |
267 | break; | 272 | break; |
268 | 273 | ||
269 | case USB_EVENT_NONE: | 274 | case USB_EVENT_NONE: |
270 | DBG(4, "VBUS Disconnect\n"); | 275 | DBG(4, "VBUS Disconnect\n"); |
271 | 276 | ||
277 | #ifdef CONFIG_USB_GADGET_MUSB_HDRC | ||
278 | if (is_otg_enabled(musb)) | ||
279 | if (musb->gadget_driver) | ||
280 | #endif | ||
281 | { | ||
282 | pm_runtime_mark_last_busy(musb->controller); | ||
283 | pm_runtime_put_autosuspend(musb->controller); | ||
284 | } | ||
285 | |||
272 | if (data->interface_type == MUSB_INTERFACE_UTMI) { | 286 | if (data->interface_type == MUSB_INTERFACE_UTMI) { |
273 | if (musb->xceiv->set_vbus) | 287 | if (musb->xceiv->set_vbus) |
274 | otg_set_vbus(musb->xceiv, 0); | 288 | otg_set_vbus(musb->xceiv, 0); |
@@ -300,7 +314,11 @@ static int omap2430_musb_init(struct musb *musb) | |||
300 | return -ENODEV; | 314 | return -ENODEV; |
301 | } | 315 | } |
302 | 316 | ||
303 | omap2430_low_level_init(musb); | 317 | status = pm_runtime_get_sync(dev); |
318 | if (status < 0) { | ||
319 | dev_err(dev, "pm_runtime_get_sync FAILED"); | ||
320 | goto err1; | ||
321 | } | ||
304 | 322 | ||
305 | l = musb_readl(musb->mregs, OTG_INTERFSEL); | 323 | l = musb_readl(musb->mregs, OTG_INTERFSEL); |
306 | 324 | ||
@@ -331,6 +349,10 @@ static int omap2430_musb_init(struct musb *musb) | |||
331 | setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb); | 349 | setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb); |
332 | 350 | ||
333 | return 0; | 351 | return 0; |
352 | |||
353 | err1: | ||
354 | pm_runtime_disable(dev); | ||
355 | return status; | ||
334 | } | 356 | } |
335 | 357 | ||
336 | static void omap2430_musb_enable(struct musb *musb) | 358 | static void omap2430_musb_enable(struct musb *musb) |
@@ -407,8 +429,6 @@ static int __init omap2430_probe(struct platform_device *pdev) | |||
407 | struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; | 429 | struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; |
408 | struct platform_device *musb; | 430 | struct platform_device *musb; |
409 | struct omap2430_glue *glue; | 431 | struct omap2430_glue *glue; |
410 | int status = 0; | ||
411 | |||
412 | int ret = -ENOMEM; | 432 | int ret = -ENOMEM; |
413 | 433 | ||
414 | glue = kzalloc(sizeof(*glue), GFP_KERNEL); | 434 | glue = kzalloc(sizeof(*glue), GFP_KERNEL); |
@@ -454,16 +474,9 @@ static int __init omap2430_probe(struct platform_device *pdev) | |||
454 | } | 474 | } |
455 | 475 | ||
456 | pm_runtime_enable(&pdev->dev); | 476 | pm_runtime_enable(&pdev->dev); |
457 | status = pm_runtime_get_sync(&pdev->dev); | ||
458 | if (status < 0) { | ||
459 | dev_err(&pdev->dev, "pm_runtime_get_sync FAILED"); | ||
460 | goto err3; | ||
461 | } | ||
462 | 477 | ||
463 | return 0; | 478 | return 0; |
464 | 479 | ||
465 | err3: | ||
466 | pm_runtime_disable(&pdev->dev); | ||
467 | err2: | 480 | err2: |
468 | platform_device_put(musb); | 481 | platform_device_put(musb); |
469 | 482 | ||
@@ -489,7 +502,7 @@ static int __exit omap2430_remove(struct platform_device *pdev) | |||
489 | 502 | ||
490 | #ifdef CONFIG_PM | 503 | #ifdef CONFIG_PM |
491 | 504 | ||
492 | static int omap2430_suspend(struct device *dev) | 505 | static int omap2430_runtime_suspend(struct device *dev) |
493 | { | 506 | { |
494 | struct omap2430_glue *glue = dev_get_drvdata(dev); | 507 | struct omap2430_glue *glue = dev_get_drvdata(dev); |
495 | struct musb *musb = glue_to_musb(glue); | 508 | struct musb *musb = glue_to_musb(glue); |
@@ -497,22 +510,14 @@ static int omap2430_suspend(struct device *dev) | |||
497 | omap2430_low_level_exit(musb); | 510 | omap2430_low_level_exit(musb); |
498 | otg_set_suspend(musb->xceiv, 1); | 511 | otg_set_suspend(musb->xceiv, 1); |
499 | 512 | ||
500 | if (!pm_runtime_suspended(dev) && dev->bus && dev->bus->pm && | ||
501 | dev->bus->pm->runtime_suspend) | ||
502 | dev->bus->pm->runtime_suspend(dev); | ||
503 | |||
504 | return 0; | 513 | return 0; |
505 | } | 514 | } |
506 | 515 | ||
507 | static int omap2430_resume(struct device *dev) | 516 | static int omap2430_runtime_resume(struct device *dev) |
508 | { | 517 | { |
509 | struct omap2430_glue *glue = dev_get_drvdata(dev); | 518 | struct omap2430_glue *glue = dev_get_drvdata(dev); |
510 | struct musb *musb = glue_to_musb(glue); | 519 | struct musb *musb = glue_to_musb(glue); |
511 | 520 | ||
512 | if (!pm_runtime_suspended(dev) && dev->bus && dev->bus->pm && | ||
513 | dev->bus->pm->runtime_resume) | ||
514 | dev->bus->pm->runtime_resume(dev); | ||
515 | |||
516 | omap2430_low_level_init(musb); | 521 | omap2430_low_level_init(musb); |
517 | otg_set_suspend(musb->xceiv, 0); | 522 | otg_set_suspend(musb->xceiv, 0); |
518 | 523 | ||
@@ -520,8 +525,8 @@ static int omap2430_resume(struct device *dev) | |||
520 | } | 525 | } |
521 | 526 | ||
522 | static struct dev_pm_ops omap2430_pm_ops = { | 527 | static struct dev_pm_ops omap2430_pm_ops = { |
523 | .suspend = omap2430_suspend, | 528 | .runtime_suspend = omap2430_runtime_suspend, |
524 | .resume = omap2430_resume, | 529 | .runtime_resume = omap2430_runtime_resume, |
525 | }; | 530 | }; |
526 | 531 | ||
527 | #define DEV_PM_OPS (&omap2430_pm_ops) | 532 | #define DEV_PM_OPS (&omap2430_pm_ops) |