]> git.sur5r.net Git - u-boot/blobdiff - drivers/usb/host/ehci-fsl.c
usb: ehci-mx6: allow board_ehci_hcd_init to fail
[u-boot] / drivers / usb / host / ehci-fsl.c
index 1d012db92e6ff2cb2618321c550e70f6aa9f7177..a43d37de0bc9ee507b5de5bcb2cc0bd882ca5d55 100644 (file)
 #include <pci.h>
 #include <usb.h>
 #include <asm/io.h>
-#include <usb/ehci-fsl.h>
+#include <usb/ehci-ci.h>
 #include <hwconfig.h>
-#include <asm/fsl_errata.h>
+#include <fsl_usb.h>
+#include <fdt_support.h>
 
 #include "ehci.h"
 
+#ifndef CONFIG_USB_MAX_CONTROLLER_COUNT
+#define CONFIG_USB_MAX_CONTROLLER_COUNT 1
+#endif
+
+static void set_txfifothresh(struct usb_ehci *, u32);
+
 /* Check USB PHY clock valid */
 static int usb_phy_clk_valid(struct usb_ehci *ehci)
 {
@@ -69,7 +76,7 @@ int ehci_hcd_init(int index, enum usb_init_type init,
                break;
        default:
                printf("ERROR: wrong controller index!!\n");
-               break;
+               return -EINVAL;
        };
 
        *hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength);
@@ -102,15 +109,20 @@ int ehci_hcd_init(int index, enum usb_init_type init,
 
        if (!strncmp(phy_type, "utmi", 4)) {
 #if defined(CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY)
-               setbits_be32(&ehci->control, PHY_CLK_SEL_UTMI);
-               setbits_be32(&ehci->control, UTMI_PHY_EN);
+               clrsetbits_be32(&ehci->control, CONTROL_REGISTER_W1C_MASK,
+                               PHY_CLK_SEL_UTMI);
+               clrsetbits_be32(&ehci->control, CONTROL_REGISTER_W1C_MASK,
+                               UTMI_PHY_EN);
                udelay(1000); /* delay required for PHY Clk to appear */
 #endif
                out_le32(&(*hcor)->or_portsc[0], PORT_PTS_UTMI);
-               setbits_be32(&ehci->control, USB_EN);
+               clrsetbits_be32(&ehci->control, CONTROL_REGISTER_W1C_MASK,
+                               USB_EN);
        } else {
-               setbits_be32(&ehci->control, PHY_CLK_SEL_ULPI);
-               clrsetbits_be32(&ehci->control, UTMI_PHY_EN, USB_EN);
+               clrsetbits_be32(&ehci->control, CONTROL_REGISTER_W1C_MASK,
+                               PHY_CLK_SEL_ULPI);
+               clrsetbits_be32(&ehci->control, UTMI_PHY_EN |
+                               CONTROL_REGISTER_W1C_MASK, USB_EN);
                udelay(1000); /* delay required for PHY Clk to appear */
                if (!usb_phy_clk_valid(ehci))
                        return -EINVAL;
@@ -123,6 +135,19 @@ int ehci_hcd_init(int index, enum usb_init_type init,
 
        in_le32(&ehci->usbmode);
 
+       if (has_erratum_a007798())
+               set_txfifothresh(ehci, TXFIFOTHRESH);
+
+       if (has_erratum_a004477()) {
+               /*
+                * When reset is issued while any ULPI transaction is ongoing
+                * then it may result to corruption of ULPI Function Control
+                * Register which eventually causes phy clock to enter low
+                * power mode which stops the clock. Thus delay is required
+                * before reset to let ongoing ULPI transaction complete.
+                */
+               udelay(1);
+       }
        return 0;
 }
 
@@ -134,3 +159,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);
+}