summaryrefslogtreecommitdiff
path: root/drivers/usb/host/ehci-fsl.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/ehci-fsl.c')
-rw-r--r--drivers/usb/host/ehci-fsl.c38
1 files changed, 36 insertions, 2 deletions
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 1ca7cf5d9b..6cb4d98668 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -14,9 +14,12 @@
#include <asm/io.h>
#include <usb/ehci-fsl.h>
#include <hwconfig.h>
+#include <asm/fsl_errata.h>
#include "ehci.h"
+static void set_txfifothresh(struct usb_ehci *, u32);
+
/* Check USB PHY clock valid */
static int usb_phy_clk_valid(struct usb_ehci *ehci)
{
@@ -41,11 +44,23 @@ int ehci_hcd_init(int index, enum usb_init_type init,
struct usb_ehci *ehci = NULL;
const char *phy_type = NULL;
size_t len;
+ char current_usb_controller[5];
#ifdef CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY
char usb_phy[5];
usb_phy[0] = '\0';
#endif
+ if (has_erratum_a007075()) {
+ /*
+ * A 5ms delay is needed after applying soft-reset to the
+ * controller to let external ULPI phy come out of reset.
+ * This delay needs to be added before re-initializing
+ * the controller after soft-resetting completes
+ */
+ mdelay(5);
+ }
+ memset(current_usb_controller, '\0', 5);
+ snprintf(current_usb_controller, 4, "usb%d", index+1);
switch (index) {
case 0:
@@ -70,8 +85,9 @@ int ehci_hcd_init(int index, enum usb_init_type init,
out_be32(&ehci->snoop2, 0x80000000 | SNOOP_SIZE_2GB);
/* Init phy */
- if (hwconfig_sub("usb1", "phy_type"))
- phy_type = hwconfig_subarg("usb1", "phy_type", &len);
+ if (hwconfig_sub(current_usb_controller, "phy_type"))
+ phy_type = hwconfig_subarg(current_usb_controller,
+ "phy_type", &len);
else
phy_type = getenv("usb_phy_type");
@@ -109,6 +125,10 @@ int ehci_hcd_init(int index, enum usb_init_type init,
in_le32(&ehci->usbmode);
+ if (SVR_SOC_VER(get_svr()) == SVR_T4240 &&
+ IS_SVR_REV(get_svr(), 2, 0))
+ set_txfifothresh(ehci, TXFIFOTHRESH);
+
return 0;
}
@@ -120,3 +140,17 @@ int ehci_hcd_stop(int index)
{
return 0;
}
+
+/*
+ * Setting the value of TXFIFO_THRESH field in TXFILLTUNING register
+ * to counter DDR latencies in writing data into Tx buffer.
+ * This prevents Tx buffer from getting underrun
+ */
+static void set_txfifothresh(struct usb_ehci *ehci, u32 txfifo_thresh)
+{
+ u32 cmd;
+ cmd = ehci_readl(&ehci->txfilltuning);
+ cmd &= ~TXFIFO_THRESH_MASK;
+ cmd |= TXFIFO_THRESH(txfifo_thresh);
+ ehci_writel(&ehci->txfilltuning, cmd);
+}