]> git.sur5r.net Git - u-boot/commitdiff
usb: ehci-marvell.c: Add DM support
authorStefan Roese <sr@denx.de>
Tue, 1 Sep 2015 09:39:44 +0000 (11:39 +0200)
committerLuka Perkov <luka.perkov@sartura.hr>
Wed, 21 Oct 2015 00:25:01 +0000 (02:25 +0200)
This patch adds driver model (DM) support to the Marvell EHCI driver.
This will be used by the MVEBU SoC's, currently Armada XP and 38x.

Tested on Marvell Armada XP and 38x eval boards.

Signed-off-by: Stefan Roese <sr@denx.de>
Acked-by: Marek Vasut <marex@denx.de>
Cc: Simon Glass <sjg@chromium.org>
Cc: Luka Perkov <luka.perkov@sartura.hr>
drivers/usb/host/Kconfig
drivers/usb/host/ehci-marvell.c

index b30b43da3b566dbd9782041770f45b43813ff1b8..2a2bffe06fe0ec8c311b4b2e7b8f2a2687691581 100644 (file)
@@ -52,6 +52,13 @@ config USB_EHCI
 
 if USB_EHCI_HCD
 
+config USB_EHCI_MARVELL
+       bool "Support for MVEBU (AXP / A38x) on-chip EHCI USB controller"
+       depends on ARCH_MVEBU
+       default y
+       ---help---
+         Enables support for the on-chip EHCI controller on MVEBU SoCs.
+
 config USB_EHCI_MX6
        bool "Support for i.MX6 on-chip EHCI USB controller"
        depends on ARCH_MX6
index 50fa01c07989779650264d872bd6954d246222d6..5b0f46aaef878a4e8e80effcf26762d1b4a6d3ab 100644 (file)
@@ -12,6 +12,7 @@
 #include "ehci.h"
 #include <linux/mbus.h>
 #include <asm/arch/cpu.h>
+#include <dm.h>
 
 #if defined(CONFIG_KIRKWOOD)
 #include <asm/arch/soc.h>
@@ -28,24 +29,19 @@ DECLARE_GLOBAL_DATA_PTR;
 /*
  * USB 2.0 Bridge Address Decoding registers setup
  */
-#ifdef CONFIG_ARMADA_XP
+#ifdef CONFIG_DM_USB
 
-/*
- * Armada XP and Armada 38x have different base addresses for
- * the USB 2.0 EHCI host controller. So we need to provide
- * a mechnism to support both here.
- */
-#define MVUSB0_BASE                                    \
-       (mvebu_soc_family() == MVEBU_SOC_A38X ?         \
-        MVEBU_USB20_BASE : MVEBU_AXP_USB_BASE)
-#define MVUSB_BASE(port)       MVUSB0_BASE + ((port) << 12)
+struct ehci_mvebu_priv {
+       struct ehci_ctrl ehci;
+       fdt_addr_t hcd_base;
+};
 
 /*
  * 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(int index)
+static void usb_brg_adrdec_setup(u32 base)
 {
        const struct mbus_dram_target_info *dram;
        int i;
@@ -53,8 +49,8 @@ static void usb_brg_adrdec_setup(int index)
        dram = mvebu_mbus_dram_info();
 
        for (i = 0; i < 4; i++) {
-               writel(0, MVUSB_BASE(index) + USB_WINDOW_CTRL(i));
-               writel(0, MVUSB_BASE(index) + USB_WINDOW_BASE(i));
+               writel(0, base + USB_WINDOW_CTRL(i));
+               writel(0, base + USB_WINDOW_BASE(i));
        }
 
        for (i = 0; i < dram->num_cs; i++) {
@@ -63,12 +59,69 @@ static void usb_brg_adrdec_setup(int index)
                /* 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,
-                      MVUSB_BASE(index) + USB_WINDOW_CTRL(i));
+                      base + USB_WINDOW_CTRL(i));
 
                /* Write base address to base register */
-               writel(cs->base, MVUSB_BASE(index) + USB_WINDOW_BASE(i));
+               writel(cs->base, base + USB_WINDOW_BASE(i));
        }
 }
+
+static int ehci_mvebu_probe(struct udevice *dev)
+{
+       struct ehci_mvebu_priv *priv = dev_get_priv(dev);
+       struct ehci_hccr *hccr;
+       struct ehci_hcor *hcor;
+
+       /*
+        * Get the base address for EHCI controller from the device node
+        */
+       priv->hcd_base = dev_get_addr(dev);
+       if (priv->hcd_base == FDT_ADDR_T_NONE) {
+               debug("Can't get the EHCI register base address\n");
+               return -ENXIO;
+       }
+
+       usb_brg_adrdec_setup(priv->hcd_base);
+
+       hccr = (struct ehci_hccr *)(priv->hcd_base + 0x100);
+       hcor = (struct ehci_hcor *)
+               ((u32)hccr + HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+
+       debug("ehci-marvell: init hccr %x and hcor %x hc_length %d\n",
+             (u32)hccr, (u32)hcor,
+             (u32)HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+
+       return ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST);
+}
+
+static int ehci_mvebu_remove(struct udevice *dev)
+{
+       int ret;
+
+       ret = ehci_deregister(dev);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static const struct udevice_id ehci_usb_ids[] = {
+       { .compatible = "marvell,orion-ehci", },
+       { }
+};
+
+U_BOOT_DRIVER(ehci_mvebu) = {
+       .name   = "ehci_mvebu",
+       .id     = UCLASS_USB,
+       .of_match = ehci_usb_ids,
+       .probe = ehci_mvebu_probe,
+       .remove = ehci_mvebu_remove,
+       .ops    = &ehci_usb_ops,
+       .platdata_auto_alloc_size = sizeof(struct usb_platdata),
+       .priv_auto_alloc_size = sizeof(struct ehci_mvebu_priv),
+       .flags  = DM_FLAG_ALLOC_PRIV_DMA,
+};
+
 #else
 #define MVUSB_BASE(port)       MVUSB0_BASE
 
@@ -112,7 +165,6 @@ static void usb_brg_adrdec_setup(int index)
                writel(base, MVUSB0_BASE + USB_WINDOW_BASE(i));
        }
 }
-#endif
 
 /*
  * Create the appropriate control structures to manage
@@ -142,3 +194,5 @@ int ehci_hcd_stop(int index)
 {
        return 0;
 }
+
+#endif /* CONFIG_DM_USB */