dm: usb: tegra: Add driver model support to tegra EHCI

Update this driver with driver model support for USB.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Marek Vasut <marex@denx.de>
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index 7230237..27705d6 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -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
@@ -32,9 +35,11 @@
 	#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 @@
 
 /* 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 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_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 @@
 	.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 @@
 
 	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