summaryrefslogtreecommitdiff
path: root/drivers/usb/host
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host')
-rw-r--r--drivers/usb/host/ehci-hcd.c15
-rw-r--r--drivers/usb/host/ehci-omap.c27
-rw-r--r--drivers/usb/host/ehci.h13
3 files changed, 32 insertions, 23 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 706cf0c..fdad739 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -36,16 +36,7 @@
#define CONFIG_USB_MAX_CONTROLLER_COUNT 1
#endif
-static struct ehci_ctrl {
- struct ehci_hccr *hccr; /* R/O registers, not need for volatile */
- struct ehci_hcor *hcor;
- int rootdev;
- uint16_t portreset;
- struct QH qh_list __aligned(USB_DMA_MINALIGN);
- struct QH periodic_queue __aligned(USB_DMA_MINALIGN);
- uint32_t *periodic_list;
- int ntds;
-} ehcic[CONFIG_USB_MAX_CONTROLLER_COUNT];
+static struct ehci_ctrl ehcic[CONFIG_USB_MAX_CONTROLLER_COUNT];
#define ALIGN_END_ADDR(type, ptr, size) \
((uint32_t)(ptr) + roundup((size) * sizeof(type), USB_DMA_MINALIGN))
@@ -954,7 +945,9 @@ int usb_lowlevel_init(int index, void **controller)
* Split Transactions will be spread across microframes using
* S-mask and C-mask.
*/
- ehcic[index].periodic_list = memalign(4096, 1024*4);
+ if (ehcic[index].periodic_list == NULL)
+ ehcic[index].periodic_list = memalign(4096, 1024 * 4);
+
if (!ehcic[index].periodic_list)
return -ENOMEM;
for (i = 0; i < 1024; i++) {
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index a47e078..032d5e5 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -28,18 +28,21 @@ static struct omap_ehci *const ehci = (struct omap_ehci *)OMAP_EHCI_BASE;
static int omap_uhh_reset(void)
{
- unsigned long init = get_timer(0);
-
- /* perform UHH soft reset, and wait until reset is complete */
- writel(OMAP_UHH_SYSCONFIG_SOFTRESET, &uhh->sysc);
-
- /* Wait for UHH reset to complete */
- while (!(readl(&uhh->syss) & OMAP_UHH_SYSSTATUS_EHCI_RESETDONE))
- if (get_timer(init) > CONFIG_SYS_HZ) {
- debug("OMAP UHH error: timeout resetting ehci\n");
- return -EL3RST;
- }
-
+/*
+ * Soft resetting the UHH module causes instability issues on
+ * all OMAPs so we just avoid it.
+ *
+ * See OMAP36xx Errata
+ * i571: USB host EHCI may stall when entering smart-standby mode
+ * i660: USBHOST Configured In Smart-Idle Can Lead To a Deadlock
+ *
+ * On OMAP4/5, soft-resetting the UHH module will put it into
+ * Smart-Idle mode and lead to a deadlock.
+ *
+ * On OMAP3, this doesn't seem to be the case but still instabilities
+ * are observed on beagle (3530 ES1.0) if soft-reset is used.
+ * e.g. NFS root failures with Linux kernel.
+ */
return 0;
}
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index d090f0a..bd52afe 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -22,6 +22,8 @@
#ifndef USB_EHCI_H
#define USB_EHCI_H
+#include <usb.h>
+
#if !defined(CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS)
#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 2
#endif
@@ -252,6 +254,17 @@ struct QH {
};
};
+struct ehci_ctrl {
+ struct ehci_hccr *hccr; /* R/O registers, not need for volatile */
+ struct ehci_hcor *hcor;
+ int rootdev;
+ uint16_t portreset;
+ struct QH qh_list __aligned(USB_DMA_MINALIGN);
+ struct QH periodic_queue __aligned(USB_DMA_MINALIGN);
+ uint32_t *periodic_list;
+ int ntds;
+};
+
/* Low level init functions */
int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor);
int ehci_hcd_stop(int index);