summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJingchang Lu <b35083@freescale.com>2012-08-08 09:55:46 +0800
committerJason Jin <Jason.jin@freescale.com>2012-08-10 18:19:13 +0800
commitad1cda1655494797e8a22addb080bc4aebaeb335 (patch)
treeab21bf4935e1c62754c6a1253f5ae304b3f434a2
parent3cf4987d5cab9060eab0fabf4b91af92515f5677 (diff)
ENGR00219354: Fix USB host driver compiled as module fail problem
Signed-off-by: Jingchang Lu <b35083@freescale.com>
-rwxr-xr-xdrivers/usb/host/ehci-arc.c54
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);