diff options
Diffstat (limited to 'drivers/usb/musb/omap2430.c')
-rw-r--r-- | drivers/usb/musb/omap2430.c | 63 |
1 files changed, 34 insertions, 29 deletions
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index ba85f273e48..df719eae3b0 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -29,7 +29,6 @@ #include <linux/sched.h> #include <linux/init.h> #include <linux/list.h> -#include <linux/clk.h> #include <linux/io.h> #include <linux/platform_device.h> #include <linux/dma-mapping.h> @@ -223,26 +222,29 @@ static inline void omap2430_low_level_init(struct musb *musb) musb_writel(musb->mregs, OTG_FORCESTDBY, l); } -/* blocking notifier support */ static int musb_otg_notifications(struct notifier_block *nb, unsigned long event, void *unused) { struct musb *musb = container_of(nb, struct musb, nb); + + musb->xceiv_event = event; + schedule_work(&musb->otg_notifier_work); + + return NOTIFY_OK; +} + +static void musb_otg_notifier_work(struct work_struct *data_notifier_work) +{ + struct musb *musb = container_of(data_notifier_work, struct musb, otg_notifier_work); struct device *dev = musb->controller; struct musb_hdrc_platform_data *pdata = dev->platform_data; struct omap_musb_board_data *data = pdata->board_data; - switch (event) { + switch (musb->xceiv_event) { case USB_EVENT_ID: dev_dbg(musb->controller, "ID GND\n"); - if (is_otg_enabled(musb)) { - if (musb->gadget_driver) { - pm_runtime_get_sync(musb->controller); - otg_init(musb->xceiv); - omap2430_musb_set_vbus(musb, 1); - } - } else { + if (!is_otg_enabled(musb) || musb->gadget_driver) { pm_runtime_get_sync(musb->controller); otg_init(musb->xceiv); omap2430_musb_set_vbus(musb, 1); @@ -274,10 +276,7 @@ static int musb_otg_notifications(struct notifier_block *nb, break; default: dev_dbg(musb->controller, "ID float\n"); - return NOTIFY_DONE; } - - return NOTIFY_OK; } static int omap2430_musb_init(struct musb *musb) @@ -297,6 +296,8 @@ static int omap2430_musb_init(struct musb *musb) return -ENODEV; } + INIT_WORK(&musb->otg_notifier_work, musb_otg_notifier_work); + status = pm_runtime_get_sync(dev); if (status < 0) { dev_err(dev, "pm_runtime_get_sync FAILED"); @@ -334,7 +335,6 @@ static int omap2430_musb_init(struct musb *musb) return 0; err1: - pm_runtime_disable(dev); return status; } @@ -350,20 +350,19 @@ static void omap2430_musb_enable(struct musb *musb) case USB_EVENT_ID: otg_init(musb->xceiv); - if (data->interface_type == MUSB_INTERFACE_UTMI) { - devctl = musb_readb(musb->mregs, MUSB_DEVCTL); - /* start the session */ - devctl |= MUSB_DEVCTL_SESSION; - musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); - while (musb_readb(musb->mregs, MUSB_DEVCTL) & - MUSB_DEVCTL_BDEVICE) { - cpu_relax(); - - if (time_after(jiffies, timeout)) { - dev_err(musb->controller, - "configured as A device timeout"); - break; - } + if (data->interface_type != MUSB_INTERFACE_UTMI) + break; + devctl = musb_readb(musb->mregs, MUSB_DEVCTL); + /* start the session */ + devctl |= MUSB_DEVCTL_SESSION; + musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); + while (musb_readb(musb->mregs, MUSB_DEVCTL) & + MUSB_DEVCTL_BDEVICE) { + cpu_relax(); + + if (time_after(jiffies, timeout)) { + dev_err(dev, "configured as A device timeout"); + break; } } break; @@ -386,6 +385,7 @@ static void omap2430_musb_disable(struct musb *musb) static int omap2430_musb_exit(struct musb *musb) { del_timer_sync(&musb_idle_timer); + cancel_work_sync(&musb->otg_notifier_work); omap2430_low_level_exit(musb); otg_put_transceiver(musb->xceiv); @@ -478,7 +478,6 @@ static int __exit omap2430_remove(struct platform_device *pdev) platform_device_del(glue->musb); platform_device_put(glue->musb); pm_runtime_put(&pdev->dev); - pm_runtime_disable(&pdev->dev); kfree(glue); return 0; @@ -491,6 +490,9 @@ static int omap2430_runtime_suspend(struct device *dev) struct omap2430_glue *glue = dev_get_drvdata(dev); struct musb *musb = glue_to_musb(glue); + musb->context.otg_interfsel = musb_readl(musb->mregs, + OTG_INTERFSEL); + omap2430_low_level_exit(musb); otg_set_suspend(musb->xceiv, 1); @@ -503,6 +505,9 @@ static int omap2430_runtime_resume(struct device *dev) struct musb *musb = glue_to_musb(glue); omap2430_low_level_init(musb); + musb_writel(musb->mregs, OTG_INTERFSEL, + musb->context.otg_interfsel); + otg_set_suspend(musb->xceiv, 0); return 0; |