summaryrefslogtreecommitdiff
path: root/drivers/usb/host
diff options
context:
space:
mode:
authorPeter Chen <peter.chen@freescale.com>2012-10-18 04:24:43 (GMT)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-10-24 21:40:50 (GMT)
commit6273f1810f95f4deeb2f0d6810f301726ad32308 (patch)
tree202135972f6010f17312103e05642bbbed3cda07 /drivers/usb/host
parente8cebb9cde3716800219ea8473306d431e83154b (diff)
downloadlinux-fsl-qoriq-6273f1810f95f4deeb2f0d6810f301726ad32308.tar.xz
USB: EHCI: add condition for delay during the resume
Without this condition, all controllers will do this delay, and increase the resume time. Only enabled and unsuspended port needs this delay, but Some buggy hardware(like Synopsys usb controller) will clear suspend bit once they receive/send resume signal, so it takes resume bit as consideration. Tested it at Freescale i.mx6q Sabrelite board. Signed-off-by: Peter Chen <peter.chen@freescale.com> Acked-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/host')
-rw-r--r--drivers/usb/host/ehci-hub.c23
1 files changed, 18 insertions, 5 deletions
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 914ce93..a7ec827 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -384,11 +384,24 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
ehci_writel(ehci, ehci->command, &ehci->regs->command);
ehci->rh_state = EHCI_RH_RUNNING;
- /* Some controller/firmware combinations need a delay during which
- * they set up the port statuses. See Bugzilla #8190. */
- spin_unlock_irq(&ehci->lock);
- msleep(8);
- spin_lock_irq(&ehci->lock);
+ /*
+ * According to Bugzilla #8190, the port status for some controllers
+ * will be wrong without a delay. At their wrong status, the port
+ * is enabled, but not suspended neither resumed.
+ */
+ i = HCS_N_PORTS(ehci->hcs_params);
+ while (i--) {
+ temp = ehci_readl(ehci, &ehci->regs->port_status[i]);
+ if ((temp & PORT_PE) &&
+ !(temp & (PORT_SUSPEND | PORT_RESUME))) {
+ ehci_dbg(ehci, "Port status(0x%x) is wrong\n", temp);
+ spin_unlock_irq(&ehci->lock);
+ msleep(8);
+ spin_lock_irq(&ehci->lock);
+ break;
+ }
+ }
+
if (ehci->shutdown)
goto shutdown;