diff options
author | Peter Chen <peter.chen@freescale.com> | 2011-08-24 17:05:31 +0800 |
---|---|---|
committer | Peter Chen <peter.chen@freescale.com> | 2011-08-26 15:50:11 +0800 |
commit | c23e1d5d234a1d5bd71bb93f2cb8668cb4f5a6de (patch) | |
tree | 2046248ddc2eee3466aa87c2f56823014a62a796 | |
parent | e8682101f1f73222cf53df77177358b2030cde61 (diff) |
ENGR00155292 usb-host: do not clear RS bit when usb bus goes to suspend
The standard EHCI design will clear RS bit after usb bus goes to
suspend, but it causes some remote wakeup issues, like remote-wakeup
featured device will be reset after resuming.
According to usb 2.0 spec, the SOF need to be sent out within 3ms
after resume signal ends, or device may consider host disconnects
with device. Freescale's USB Controller (Chipidea's core) will ends
up resume signal automatically within 21ms after it recevices remote
wakeup signal. So, if software does not set RS bit within 21ms after
it recevices remote wakeup signal, the problem described above will
be occurred.
Signed-off-by: Peter Chen <peter.chen@freescale.com>
-rw-r--r-- | drivers/usb/host/ehci-arc.c | 12 | ||||
-rw-r--r-- | drivers/usb/host/ehci-fsl.h | 1 |
2 files changed, 12 insertions, 1 deletions
diff --git a/drivers/usb/host/ehci-arc.c b/drivers/usb/host/ehci-arc.c index 068285adc716..ed686e8aac28 100644 --- a/drivers/usb/host/ehci-arc.c +++ b/drivers/usb/host/ehci-arc.c @@ -126,7 +126,7 @@ void fsl_usb_recover_hcd(struct platform_device *pdev) * CMDRUN bit in 20ms to keep port status. */ cmd = ehci_readl(ehci, &ehci->regs->command); - if (!(cmd & CMD_RUN)) { + if (!(cmd & CMD_RUN) || (hcd->state == HC_STATE_SUSPENDED)) { ehci_writel(ehci, ehci->command, &ehci->regs->command); /* Resume root hub here? */ usb_hcd_resume_root_hub(hcd); @@ -404,6 +404,8 @@ static int ehci_fsl_bus_suspend(struct usb_hcd *hcd) { int ret = 0; struct fsl_usb2_platform_data *pdata; + u32 tmp, portsc; + struct ehci_hcd *ehci = hcd_to_ehci(hcd); pdata = hcd->self.controller->platform_data; printk(KERN_DEBUG "%s, %s\n", __func__, pdata->name); @@ -413,10 +415,18 @@ static int ehci_fsl_bus_suspend(struct usb_hcd *hcd) return 0; } + portsc = ehci_readl(ehci, &ehci->regs->port_status[0]); ret = ehci_bus_suspend(hcd); if (ret != 0) return ret; + if (portsc & PORT_CCS) { + printk(KERN_DEBUG "there is a device on the port\n"); + tmp = ehci_readl(ehci, &ehci->regs->command); + tmp |= CMD_RUN; + ehci_writel(ehci, tmp, &ehci->regs->command); + } + if (pdata->platform_suspend) pdata->platform_suspend(pdata); diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h index 8a12eec68a90..448516527df1 100644 --- a/drivers/usb/host/ehci-fsl.h +++ b/drivers/usb/host/ehci-fsl.h @@ -30,6 +30,7 @@ #define PORT_PTS_SERIAL (3<<30) #define PORT_PTS_PTW (1<<28) #define PORT_PTS_PHCD (1<<23) +#define PORT_CCS (1<<0) #define FSL_SOC_USB_PORTSC2 0x188 #define FSL_SOC_USB_USBMODE 0x1a8 #define USBMODE_CM_HOST (3 << 0) /* controller mode: host */ |