[U-Boot] [PATCH v2 1/1] tegra: usb: Fix device enumeration problem of USB1

Jim Lin jilin at nvidia.com
Tue Jun 19 10:47:03 CEST 2012


A known hardware issue of USB1 port where bit 1 (connect status
change) of PORTSC register will be set after issuing Port Reset
(like "usb reset" in u-boot command line).
This will be treated as an error and stops later device enumeration.

Therefore we add a definition in header file and a callback function
to clear that bit after Port Reset in order to proceed later device
enumeration.

CONFIG_USB_EHCI_SUBMIT_ROOT_POST_CALLBACK

Signed-off-by: Jim Lin <jilin at nvidia.com>
---
To reproduce this issue, you can modify board .dts file to set
as the following to build u-boot binary.
"
 usb0 = "/usb at c5000000";
 usb1 = "/usb at c5008000";
"
Install device on USB1 port (address at 0xc5000000).
And run "usb reset" in u-boot console to enumerate device.

Changes in v2:
- Change config name
- Add a callback function at the end of ehci_submit_root() function

 drivers/usb/host/ehci-hcd.c     |    4 ++++
 drivers/usb/host/ehci-tegra.c   |   34 ++++++++++++++++++++++++++++++++++
 drivers/usb/host/ehci.h         |    4 ++++
 include/configs/tegra2-common.h |    8 ++++++++
 4 files changed, 50 insertions(+), 0 deletions(-)

diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 38d6ae0..0b6b656 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -792,7 +792,11 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
 
 	dev->act_len = len;
 	dev->status = 0;
+#ifdef CONFIG_USB_EHCI_SUBMIT_ROOT_POST_CALLBACK
+	return ehci_submit_root_post_callback(dev, pipe, buffer, length, req);
+#else
 	return 0;
+#endif
 
 unknown:
 	debug("requesttype=%x, request=%x, value=%x, index=%x, length=%x\n",
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index a7e105b..3dd18d3 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -29,6 +29,40 @@
 #include <asm/errno.h>
 #include <asm/arch/usb.h>
 
+#ifdef CONFIG_USB_EHCI_SUBMIT_ROOT_POST_CALLBACK
+int
+ehci_submit_root_post_callback(struct usb_device *dev, unsigned long pipe,
+	void *buffer, int length, struct devrequest *req)
+{
+	u16 typeReq;
+	uint32_t reg;
+	uint32_t *status_reg;
+
+	status_reg = (uint32_t *)&hcor->or_portsc[
+						le16_to_cpu(req->index) - 1];
+	if (((u32) status_reg & 0xFFFFC000) != TEGRA_USB1_BASE)
+		return 0;
+	typeReq = req->request | req->requesttype << 8;
+	switch (typeReq) {
+	case USB_REQ_SET_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8):
+		switch (le16_to_cpu(req->value)) {
+		/*
+		 * A known HW issue on USB1 port where bit 1 (Connect Status
+		 * Change) of PORTSC register will be set after issuing Port
+		 * Reset. Clear that bit for later device enumeration.
+		 */
+		case USB_PORT_FEAT_RESET:
+			reg = ehci_readl(status_reg);
+			reg &= ~EHCI_PS_CLEAR;
+			reg |= EHCI_PS_CSC;
+			ehci_writel(status_reg, reg);
+			break;
+		}
+		break;
+	}
+	return 0;
+}
+#endif
 
 /*
  * Create the appropriate control structures to manage
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index cc00ce4..6c5d8f3 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -204,4 +204,8 @@ struct QH {
 int ehci_hcd_init(void);
 int ehci_hcd_stop(void);
 
+#ifdef CONFIG_USB_EHCI_SUBMIT_ROOT_POST_CALLBACK
+int ehci_submit_root_post_callback(struct usb_device *dev, unsigned long pipe,
+	void *buffer, int length, struct devrequest *req);
+#endif
 #endif /* USB_EHCI_H */
diff --git a/include/configs/tegra2-common.h b/include/configs/tegra2-common.h
index 1931179..b4822d4 100644
--- a/include/configs/tegra2-common.h
+++ b/include/configs/tegra2-common.h
@@ -111,6 +111,14 @@
 #define CONFIG_EHCI_IS_TDI
 #define CONFIG_EHCI_DCACHE
 
+/*
+ * A known HW issue on USB1 port where bit 1 (Connect Status Change) of PORTSC
+ * register will be set after issuing Port Reset.
+ * This setting is to add a callback function to clear that bit for later
+ * device enumeration.
+ */
+#define CONFIG_USB_EHCI_SUBMIT_ROOT_POST_CALLBACK
+
 /* Total I2C ports on Tegra2 */
 #define TEGRA_I2C_NUM_CONTROLLERS	4
 
-- 
1.7.3

nvpublic


More information about the U-Boot mailing list