diff options
author | Jingchang Lu <b35083@freescale.com> | 2012-08-08 09:55:46 +0800 |
---|---|---|
committer | Justin Waters <justin.waters@timesys.com> | 2012-09-12 16:50:05 -0400 |
commit | f4400c213ae4736e965cf86a33dc1c69f8cbb8c6 (patch) | |
tree | ab21bf4935e1c62754c6a1253f5ae304b3f434a2 /drivers | |
parent | 0403e7a68819f629b9a9cc1fd32de8ae01494924 (diff) |
ENGR00219354: Fix USB host driver compiled as module fail problem
Signed-off-by: Jingchang Lu <b35083@freescale.com>
Diffstat (limited to 'drivers')
-rwxr-xr-x | drivers/usb/host/ehci-arc.c | 54 |
1 files changed, 50 insertions, 4 deletions
diff --git a/drivers/usb/host/ehci-arc.c b/drivers/usb/host/ehci-arc.c index 93ef469c39fb..81ab1cffe374 100755 --- a/drivers/usb/host/ehci-arc.c +++ b/drivers/usb/host/ehci-arc.c @@ -336,6 +336,7 @@ static void usb_hcd_fsl_remove(struct usb_hcd *hcd, struct ehci_hcd *ehci = hcd_to_ehci(hcd); struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; u32 tmp; + struct resource *res; if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { /* Need open clock for register access */ @@ -366,6 +367,9 @@ static void usb_hcd_fsl_remove(struct usb_hcd *hcd, usb_remove_hcd(hcd); usb_put_hcd(hcd); + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (res) + free_irq(res->start, (void *)pdev); /* * do platform specific un-initialization: * release iomux pins, etc. @@ -662,13 +666,35 @@ static int ehci_fsl_drv_suspend(struct platform_device *pdev, struct ehci_hcd *ehci = hcd_to_ehci(hcd); struct usb_device *roothub = hcd->self.root_hub; unsigned long flags; - u32 port_status; + u32 port_status, tmp; struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; printk(KERN_DEBUG "USB Host suspend begins\n"); +#ifdef CONFIG_ARCH_MVF + if (pdata->suspended) { + pr_debug("%s: already suspended, leaving early\n", __func__); + pdata->already_suspended = 1; + return 0; + } + + pr_debug("%s: suspending...\n", __func__); + + hcd->state = HC_STATE_SUSPENDED; + pdev->dev.power.power_state = PMSG_SUSPEND; + + /* ignore non-host interrupts */ + clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + + /* stop the controller */ + tmp = ehci_readl(ehci, &ehci->regs->command); + tmp &= ~CMD_RUN; + ehci_writel(ehci, tmp, &ehci->regs->command); + + pdata->suspended = 1; +#else /* Only handles OTG mode switch event, system suspend event will be done in bus suspend */ if (pdata->pmflags == 0) { - printk(KERN_DEBUG "%s, pm event \n", __func__); + printk(KERN_DEBUG "%s, pm event\n", __func__); /* Need open clock for register access */ if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) fsl_usb_clk_gate(hcd->self.controller->platform_data, true); @@ -714,7 +740,7 @@ static int ehci_fsl_drv_suspend(struct platform_device *pdev, fsl_usb_clk_gate(hcd->self.controller->platform_data, true); set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); } - +#endif port_status = ehci_readl(ehci, &ehci->regs->port_status[0]); /* save EHCI registers */ pdata->pm_command = ehci_readl(ehci, &ehci->regs->command); @@ -760,6 +786,22 @@ static int ehci_fsl_drv_resume(struct platform_device *pdev) struct fsl_usb2_wakeup_platform_data *wake_up_pdata = pdata->wakeup_pdata; /* Only handles OTG mode switch event */ printk(KERN_DEBUG "ehci fsl drv resume begins: %s\n", pdata->name); +#ifdef CONFIG_ARCH_MVF + if (pdata->already_suspended) { + pr_debug("already suspended, leaving early\n"); + pdata->already_suspended = 0; + return 0; + } + + if (!pdata->suspended) { + pr_debug("not suspended, leaving early\n"); + return 0; + } + + pdata->suspended = 0; + + pr_debug("%s resuming...\n", __func__); +#else if (pdata->pmflags == 0) { printk(KERN_DEBUG "%s,pm event, wait for wakeup irq if needed\n", __func__); wait_event_interruptible(wake_up_pdata->wq, !wake_up_pdata->usb_wakeup_is_pending); @@ -773,7 +815,7 @@ static int ehci_fsl_drv_resume(struct platform_device *pdev) fsl_usb_lowpower_mode(pdata, false); spin_unlock_irqrestore(&ehci->lock, flags); } - +#endif spin_lock_irqsave(&ehci->lock, flags); /* set host mode */ fsl_platform_set_host_mode(hcd); @@ -795,12 +837,16 @@ static int ehci_fsl_drv_resume(struct platform_device *pdev) ehci_writel(ehci, tmp, &ehci->regs->command); spin_unlock_irqrestore(&ehci->lock, flags); +#ifdef CONFIG_ARCH_MVF + usb_hcd_resume_root_hub(hcd); +#else if ((hcd->state & HC_STATE_SUSPENDED)) { printk(KERN_DEBUG "will resume roothub and its children\n"); usb_lock_device(roothub); usb_resume(&roothub->dev, PMSG_USER_RESUME); usb_unlock_device(roothub); } +#endif pdata->pmflags = 0; printk(KERN_DEBUG "ehci fsl drv resume ends: %s\n", pdata->name); |