Unlike the other 64-bit mvebu SoCs the AlleyCat5 uses the older ehci
block from the 32-bit SoCs. Adapt the ehci-marvell.c driver to cope with
the fact that the ac5 does not have the mbus infrastructure the 32-bit
SoCs have and ensure USB_EHCI_IS_TDI is selected.

Signed-off-by: Chris Packham <judge.pack...@gmail.com>
---

(no changes since v1)

 drivers/usb/host/Kconfig        |  1 +
 drivers/usb/host/ehci-marvell.c | 57 +++++++++++++++++++++++++++------
 2 files changed, 48 insertions(+), 10 deletions(-)

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index a0f48f09a7..628078f495 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -178,6 +178,7 @@ config USB_EHCI_MARVELL
        depends on ARCH_MVEBU || ARCH_KIRKWOOD || ARCH_ORION5X
        default y
        select USB_EHCI_IS_TDI if !ARM64
+       select USB_EHCI_IS_TDI if ALLEYCAT_5
        ---help---
          Enables support for the on-chip EHCI controller on MVEBU SoCs.
 
diff --git a/drivers/usb/host/ehci-marvell.c b/drivers/usb/host/ehci-marvell.c
index b7e60c690a..7d859b9cce 100644
--- a/drivers/usb/host/ehci-marvell.c
+++ b/drivers/usb/host/ehci-marvell.c
@@ -48,12 +48,17 @@ struct ehci_mvebu_priv {
        fdt_addr_t hcd_base;
 };
 
+#define USB_TO_DRAM_TARGET_ID 0x2
+#define USB_TO_DRAM_ATTR_ID 0x0
+#define USB_DRAM_BASE 0x00000000
+#define USB_DRAM_SIZE 0xfff    /* don't overrun u-boot source (was 0xffff) */
+
 /*
  * Once all the older Marvell SoC's (Orion, Kirkwood) are converted
  * to the common mvebu archticture including the mbus setup, this
  * will be the only function needed to configure the access windows
  */
-static void usb_brg_adrdec_setup(void *base)
+static void usb_brg_adrdec_setup(struct udevice *dev, void *base)
 {
        const struct mbus_dram_target_info *dram;
        int i;
@@ -65,16 +70,34 @@ static void usb_brg_adrdec_setup(void *base)
                writel(0, base + USB_WINDOW_BASE(i));
        }
 
-       for (i = 0; i < dram->num_cs; i++) {
-               const struct mbus_dram_window *cs = dram->cs + i;
+       if (device_is_compatible(dev, "marvell,ac5-ehci")) {
+               /*
+                * use decoding window to map dram address seen by usb to 0x0
+                */
 
                /* Write size, attributes and target id to control register */
-               writel(((cs->size - 1) & 0xffff0000) | (cs->mbus_attr << 8) |
-                      (dram->mbus_dram_target_id << 4) | 1,
-                      base + USB_WINDOW_CTRL(i));
+               writel((USB_DRAM_SIZE << 16) | (USB_TO_DRAM_ATTR_ID << 8) |
+                          (USB_TO_DRAM_TARGET_ID << 4) | 1,
+                          base + USB_WINDOW_CTRL(0));
 
                /* Write base address to base register */
-               writel(cs->base, base + USB_WINDOW_BASE(i));
+               writel(USB_DRAM_BASE, base + USB_WINDOW_BASE(0));
+
+               debug("## AC5 decoding windows, ctrl[%p]=0x%x, base[%p]=0x%x\n",
+                     base + USB_WINDOW_CTRL(0), readl(base + 
USB_WINDOW_CTRL(0)),
+                     base + USB_WINDOW_BASE(0), readl(base + 
USB_WINDOW_BASE(0)));
+       } else {
+               for (i = 0; i < dram->num_cs; i++) {
+                       const struct mbus_dram_window *cs = dram->cs + i;
+
+                       /* Write size, attributes and target id to control 
register */
+                       writel(((cs->size - 1) & 0xffff0000) | (cs->mbus_attr 
<< 8) |
+                                  (dram->mbus_dram_target_id << 4) | 1,
+                                  base + USB_WINDOW_CTRL(i));
+
+                       /* Write base address to base register */
+                       writel(cs->base, base + USB_WINDOW_BASE(i));
+               }
        }
 }
 
@@ -126,15 +149,28 @@ static int ehci_mvebu_probe(struct udevice *dev)
        if (device_is_compatible(dev, "marvell,armada-3700-ehci"))
                marvell_ehci_ops.powerup_fixup = marvell_ehci_powerup_fixup;
        else
-               usb_brg_adrdec_setup((void *)priv->hcd_base);
+               usb_brg_adrdec_setup(dev, (void *)priv->hcd_base);
 
        hccr = (struct ehci_hccr *)(priv->hcd_base + 0x100);
        hcor = (struct ehci_hcor *)
                ((uintptr_t)hccr + HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
 
        debug("ehci-marvell: init hccr %lx and hcor %lx hc_length %ld\n",
-             (uintptr_t)hccr, (uintptr_t)hcor,
-             (uintptr_t)HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+                 (uintptr_t)hccr, (uintptr_t)hcor,
+                 (uintptr_t)HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+
+#define PHY_CALIB_OFFSET 0x808
+       /*
+        * Trigger calibration during each usb start/reset:
+        * BIT 13 to 0, and then to 1
+        */
+       if (device_is_compatible(dev, "marvell,ac5-ehci")) {
+               void *phy_calib_reg = (void *)(priv->hcd_base + 
PHY_CALIB_OFFSET);
+               u32 val = readl(phy_calib_reg) & (~BIT(13));
+
+               writel(val, phy_calib_reg);
+               writel(val | BIT(13), phy_calib_reg);
+       }
 
        return ehci_register(dev, hccr, hcor, &marvell_ehci_ops, 0,
                             USB_INIT_HOST);
@@ -143,6 +179,7 @@ static int ehci_mvebu_probe(struct udevice *dev)
 static const struct udevice_id ehci_usb_ids[] = {
        { .compatible = "marvell,orion-ehci", },
        { .compatible = "marvell,armada-3700-ehci", },
+       { .compatible = "marvell,ac5-ehci", },
        { }
 };
 
-- 
2.37.3

Reply via email to