dm: usb: tegra: Add driver model support to tegra EHCI
authorSimon Glass <sjg@chromium.org>
Wed, 25 Mar 2015 18:22:48 +0000 (12:22 -0600)
committerSimon Glass <sjg@chromium.org>
Sat, 18 Apr 2015 17:11:27 +0000 (11:11 -0600)
Update this driver with driver model support for USB.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Marek Vasut <marex@denx.de>
drivers/usb/host/ehci-tegra.c

index 7230237..27705d6 100644 (file)
@@ -7,6 +7,7 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <asm/errno.h>
 #include <asm/io.h>
 #include <asm-generic/gpio.h>
@@ -20,6 +21,8 @@
 
 #include "ehci.h"
 
+DECLARE_GLOBAL_DATA_PTR;
+
 #define USB1_ADDR_MASK 0xFFFF0000
 
 #define HOSTPC1_DEVLC  0x84
        #endif
 #endif
 
+#ifndef CONFIG_DM_USB
 enum {
        USB_PORTS_MAX   = 3,            /* Maximum ports we allow */
 };
+#endif
 
 /* Parameters we need for USB */
 enum {
@@ -71,12 +76,15 @@ enum usb_ctlr_type {
 
 /* Information about a USB port */
 struct fdt_usb {
+       struct ehci_ctrl ehci;
        struct usb_ctlr *reg;   /* address of registers in physical memory */
        unsigned utmi:1;        /* 1 if port has external tranceiver, else 0 */
        unsigned ulpi:1;        /* 1 if port has external ULPI transceiver */
        unsigned enabled:1;     /* 1 to enable, 0 to disable */
        unsigned has_legacy_mode:1; /* 1 if this port has legacy mode */
+#ifndef CONFIG_DM_USB
        unsigned initialized:1; /* has this port already been initialized? */
+#endif
        enum usb_ctlr_type type;
        enum usb_init_type init_type;
        enum dr_mode dr_mode;   /* dual role mode */
@@ -85,8 +93,10 @@ struct fdt_usb {
        struct gpio_desc phy_reset_gpio; /* GPIO to reset ULPI phy */
 };
 
+#ifndef CONFIG_DM_USB
 static struct fdt_usb port[USB_PORTS_MAX];     /* List of valid USB ports */
 static unsigned port_count;                    /* Number of available ports */
+#endif
 
 /*
  * This table has USB timing parameters for each Oscillator frequency we
@@ -163,6 +173,7 @@ static const u8 utmip_elastic_limit = 16;
 static const u8 utmip_hs_sync_start_delay = 9;
 
 struct fdt_usb_controller {
+       /* TODO(sjg@chromium.org): Remove when we only use driver model */
        int compat;
        /* flag to determine whether controller supports hostpc register */
        u32 has_hostpc:1;
@@ -785,6 +796,7 @@ static const struct ehci_ops tegra_ehci_ops = {
        .powerup_fixup          = tegra_ehci_powerup_fixup,
 };
 
+#ifndef CONFIG_DM_USB
 /*
  * process_usb_nodes() - Process a list of USB nodes, adding them to our list
  *                     of USB ports.
@@ -905,3 +917,74 @@ int ehci_hcd_stop(int index)
 
        return 0;
 }
+#endif /* !CONFIG_DM_USB */
+
+#ifdef CONFIG_DM_USB
+static int ehci_usb_ofdata_to_platdata(struct udevice *dev)
+{
+       struct fdt_usb *priv = dev_get_priv(dev);
+       int ret;
+
+       ret = fdt_decode_usb(gd->fdt_blob, dev->of_offset, priv);
+       if (ret)
+               return ret;
+
+       priv->type = dev_get_driver_data(dev);
+
+       return 0;
+}
+
+static int ehci_usb_probe(struct udevice *dev)
+{
+       struct usb_platdata *plat = dev_get_platdata(dev);
+       struct fdt_usb *priv = dev_get_priv(dev);
+       struct ehci_hccr *hccr;
+       struct ehci_hcor *hcor;
+       static bool clk_done;
+       int ret;
+
+       ret = usb_common_init(priv, plat->init_type);
+       if (ret)
+               return ret;
+       hccr = (struct ehci_hccr *)&priv->reg->cap_length;
+       hcor = (struct ehci_hcor *)&priv->reg->usb_cmd;
+       if (!clk_done) {
+               config_clock(get_pll_timing(&fdt_usb_controllers[priv->type]));
+               clk_done = true;
+       }
+
+       return ehci_register(dev, hccr, hcor, &tegra_ehci_ops, 0,
+                            plat->init_type);
+}
+
+static int ehci_usb_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 = "nvidia,tegra20-ehci", .data = USB_CTLR_T20 },
+       { .compatible = "nvidia,tegra30-ehci", .data = USB_CTLR_T30 },
+       { .compatible = "nvidia,tegra114-ehci", .data = USB_CTLR_T114 },
+       { }
+};
+
+U_BOOT_DRIVER(usb_ehci) = {
+       .name   = "ehci_tegra",
+       .id     = UCLASS_USB,
+       .of_match = ehci_usb_ids,
+       .ofdata_to_platdata = ehci_usb_ofdata_to_platdata,
+       .probe = ehci_usb_probe,
+       .remove = ehci_usb_remove,
+       .ops    = &ehci_usb_ops,
+       .platdata_auto_alloc_size = sizeof(struct usb_platdata),
+       .priv_auto_alloc_size = sizeof(struct fdt_usb),
+       .flags  = DM_FLAG_ALLOC_PRIV_DMA,
+};
+#endif