diff options
author | Peter Chen <peter.chen@freescale.com> | 2012-02-22 11:14:01 +0800 |
---|---|---|
committer | Jason Liu <r64343@freescale.com> | 2012-07-20 13:23:48 +0800 |
commit | 416ef3cc9f84e20218a228f801aa45e9a2617cfc (patch) | |
tree | 30032856ca8bb4361d747d1201c986c62fb83f55 /drivers/usb/host | |
parent | 0620bfa4b059c78700e41d368e3deadf496ef0a0 (diff) |
ENGR00176147-1: usb: fix some wakeup problems
- Do not call hcd core adjust wakeup flag code. It may change
wakeup flag, and cause port change detect(PCD) enable setting change.
- For ID wakeup, it should not call host's fsl_usb_recover_hcd at ID interrupt.
The coming ID switch event will resume host.
- Do not need enable wakeup interrupt for host at platform driver resume
routine, it may introduce unnessary wakeup interrupt during bus resume.
The wakeup will be enabled again when usb host goes to controller again
due to autosuspend.
- When there is no gadget enabled, the otg port is still at host mode with
interrupt enabled, so when male Micro-B to female A-type cable with
usb device plugs in, there will be PCD interrupt before hcd core leaves
suspend mode.
Signed-off-by: Peter Chen <peter.chen@freescale.com>
Diffstat (limited to 'drivers/usb/host')
-rwxr-xr-x | drivers/usb/host/ehci-arc.c | 30 |
1 files changed, 6 insertions, 24 deletions
diff --git a/drivers/usb/host/ehci-arc.c b/drivers/usb/host/ehci-arc.c index 99ba497f5f5a..93ef469c39fb 100755 --- a/drivers/usb/host/ehci-arc.c +++ b/drivers/usb/host/ehci-arc.c @@ -28,7 +28,6 @@ #include "../core/usb.h" #include "ehci-fsl.h" #include <mach/fsl_usb.h> - extern void usb_host_set_wakeup(struct device *wkup_dev, bool para); static void fsl_usb_lowpower_mode(struct fsl_usb2_platform_data *pdata, bool enable) { @@ -148,11 +147,11 @@ static irqreturn_t ehci_fsl_pre_irq(int irq, void *dev) pdata = hcd->self.controller->platform_data; if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { - if (pdata->irq_delay || !pdata->wakeup_event) + if (pdata->irq_delay || pdata->wakeup_event != WAKEUP_EVENT_DPDM) return IRQ_NONE; pr_debug("%s\n", __func__); - pdata->wakeup_event = 0; + pdata->wakeup_event = WAKEUP_EVENT_INVALID; fsl_usb_recover_hcd(pdev); return IRQ_HANDLED; } else { @@ -674,17 +673,9 @@ static int ehci_fsl_drv_suspend(struct platform_device *pdev, if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) fsl_usb_clk_gate(hcd->self.controller->platform_data, true); - ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd), - device_may_wakeup(&(pdev->dev))); - if (!host_can_wakeup_system(pdev)) { - int mask; - - mask = ehci_readl(ehci, &ehci->regs->intr_enable); - mask &= ~STS_PCD; - ehci_writel(ehci, mask, &ehci->regs->intr_enable); - + if (!host_can_wakeup_system(pdev)) usb_host_set_wakeup(hcd->self.controller, false); - } + fsl_usb_clk_gate(hcd->self.controller->platform_data, false); printk(KERN_DEBUG "host suspend ends\n"); return 0; @@ -772,17 +763,6 @@ static int ehci_fsl_drv_resume(struct platform_device *pdev) 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); - if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { - fsl_usb_clk_gate(hcd->self.controller->platform_data, true); - } - if (!host_can_wakeup_system(pdev)) { - usb_host_set_wakeup(hcd->self.controller, true); - - } - ehci_prepare_ports_for_controller_resume(hcd_to_ehci(hcd)); - if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { - fsl_usb_clk_gate(hcd->self.controller->platform_data, false); - } return 0; } if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { @@ -794,6 +774,7 @@ static int ehci_fsl_drv_resume(struct platform_device *pdev) spin_unlock_irqrestore(&ehci->lock, flags); } + spin_lock_irqsave(&ehci->lock, flags); /* set host mode */ fsl_platform_set_host_mode(hcd); @@ -812,6 +793,7 @@ static int ehci_fsl_drv_resume(struct platform_device *pdev) tmp = ehci_readl(ehci, &ehci->regs->command); tmp |= CMD_RUN; ehci_writel(ehci, tmp, &ehci->regs->command); + spin_unlock_irqrestore(&ehci->lock, flags); if ((hcd->state & HC_STATE_SUSPENDED)) { printk(KERN_DEBUG "will resume roothub and its children\n"); |