summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2010-06-24 10:34:27 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2010-06-24 11:42:20 +0200
commit2f64aa66abc67be70b0e963bdfd70a2b72f4a942 (patch)
tree2512c4ba057b0d412e60fb2f70f5be9eaf3bbc23
parent0b863c83d0908a1524eed1e55f0efc3397badd2e (diff)
downloadbarebox-2f64aa66abc67be70b0e963bdfd70a2b72f4a942.tar.gz
barebox-2f64aa66abc67be70b0e963bdfd70a2b72f4a942.tar.xz
ehci: Force a ehci_halt before trying to reset
As observed on OMAP some controllers do not like being resetted when running. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
-rw-r--r--drivers/usb/usb_ehci_core.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/drivers/usb/usb_ehci_core.c b/drivers/usb/usb_ehci_core.c
index e70e8718a7..fe988c3b87 100644
--- a/drivers/usb/usb_ehci_core.c
+++ b/drivers/usb/usb_ehci_core.c
@@ -770,12 +770,33 @@ unknown:
return -1;
}
+/* force HC to halt state from unknown (EHCI spec section 2.3) */
+static int ehci_halt(struct ehci_priv *ehci)
+{
+ u32 temp = ehci_readl(&ehci->hcor->or_usbsts);
+
+ /* disable any irqs left enabled by previous code */
+ ehci_writel(&ehci->hcor->or_usbintr, 0);
+
+ if (temp & STS_HALT)
+ return 0;
+
+ temp = ehci_readl(&ehci->hcor->or_usbcmd);
+ temp &= ~CMD_RUN;
+ ehci_writel(&ehci->hcor->or_usbcmd, temp);
+
+ return handshake(&ehci->hcor->or_usbsts,
+ STS_HALT, STS_HALT, 16 * 125);
+}
+
static int ehci_init(struct usb_host *host)
{
struct ehci_priv *ehci = to_ehci(host);
uint32_t reg;
uint32_t cmd;
+ ehci_halt(ehci);
+
/* EHCI spec section 4.1 */
if (ehci_reset(ehci) != 0)
return -1;