usb: ehci: fsl: Add code to use CONFIG_DM_USB

Adds code to use driver model for USB EHCI FSL driver

Signed-off-by: Rajesh Bhagat <rajesh.bhagat@nxp.com>
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index df3fa04..f5e3ae7 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -1,5 +1,5 @@
 /*
- * (C) Copyright 2009, 2011 Freescale Semiconductor, Inc.
+ * (C) Copyright 2009, 2011, 2016 Freescale Semiconductor, Inc.
  *
  * (C) Copyright 2008, Excito Elektronik i Sk=E5ne AB
  *
@@ -16,16 +16,32 @@
 #include <hwconfig.h>
 #include <fsl_usb.h>
 #include <fdt_support.h>
+#include <dm.h>
 
 #include "ehci.h"
 
+DECLARE_GLOBAL_DATA_PTR;
+
 #ifndef CONFIG_USB_MAX_CONTROLLER_COUNT
 #define CONFIG_USB_MAX_CONTROLLER_COUNT 1
 #endif
 
+#ifdef CONFIG_DM_USB
+struct ehci_fsl_priv {
+	struct ehci_ctrl ehci;
+	fdt_addr_t hcd_base;
+	char *phy_type;
+};
+#endif
+
 static void set_txfifothresh(struct usb_ehci *, u32);
+#ifdef CONFIG_DM_USB
+static int ehci_fsl_init(struct ehci_fsl_priv *priv, struct usb_ehci *ehci,
+		  struct ehci_hccr *hccr, struct ehci_hcor *hcor);
+#else
 static int ehci_fsl_init(int index, struct usb_ehci *ehci,
 			 struct ehci_hccr *hccr, struct ehci_hcor *hcor);
+#endif
 
 /* Check USB PHY clock valid */
 static int usb_phy_clk_valid(struct usb_ehci *ehci)
@@ -37,8 +53,101 @@
 	} else {
 		return 1;
 	}
+}
+
+#ifdef CONFIG_DM_USB
+static int ehci_fsl_ofdata_to_platdata(struct udevice *dev)
+{
+	struct ehci_fsl_priv *priv = dev_get_priv(dev);
+	const void *prop;
+
+	prop = fdt_getprop(gd->fdt_blob, dev->of_offset, "phy_type",
+			   NULL);
+	if (prop) {
+		priv->phy_type = (char *)prop;
+		debug("phy_type %s\n", priv->phy_type);
+	}
+
+	return 0;
+}
+
+static int ehci_fsl_init_after_reset(struct ehci_ctrl *ctrl)
+{
+	struct usb_ehci *ehci = NULL;
+	struct ehci_fsl_priv *priv = container_of(ctrl, struct ehci_fsl_priv,
+						   ehci);
+
+	ehci = (struct usb_ehci *)priv->hcd_base;
+	if (ehci_fsl_init(priv, ehci, priv->ehci.hccr, priv->ehci.hcor) < 0)
+		return -ENXIO;
+
+	return 0;
+}
+
+static const struct ehci_ops fsl_ehci_ops = {
+	.init_after_reset = ehci_fsl_init_after_reset,
+};
+
+static int ehci_fsl_probe(struct udevice *dev)
+{
+	struct ehci_fsl_priv *priv = dev_get_priv(dev);
+	struct usb_ehci *ehci = NULL;
+	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;
+	}
+	ehci = (struct usb_ehci *)priv->hcd_base;
+	hccr = (struct ehci_hccr *)(&ehci->caplength);
+	hcor = (struct ehci_hcor *)
+		((u32)hccr + HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+
+	if (ehci_fsl_init(priv, ehci, hccr, hcor) < 0)
+		return -ENXIO;
+
+	debug("ehci-fsl: 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, &fsl_ehci_ops, 0, USB_INIT_HOST);
+}
+
+static int ehci_fsl_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 = "fsl-usb2-mph", },
+	{ .compatible = "fsl-usb2-dr", },
+	{ }
+};
+
+U_BOOT_DRIVER(ehci_fsl) = {
+	.name	= "ehci_fsl",
+	.id	= UCLASS_USB,
+	.of_match = ehci_usb_ids,
+	.ofdata_to_platdata = ehci_fsl_ofdata_to_platdata,
+	.probe = ehci_fsl_probe,
+	.remove = ehci_fsl_remove,
+	.ops	= &ehci_usb_ops,
+	.platdata_auto_alloc_size = sizeof(struct usb_platdata),
+	.priv_auto_alloc_size = sizeof(struct ehci_fsl_priv),
+	.flags	= DM_FLAG_ALLOC_PRIV_DMA,
+};
+#else
 /*
  * Create the appropriate control structures to manage
  * a new EHCI host controller.
@@ -77,13 +186,21 @@
 {
 	return 0;
 }
+#endif
 
+#ifdef CONFIG_DM_USB
+static int ehci_fsl_init(struct ehci_fsl_priv *priv, struct usb_ehci *ehci,
+		  struct ehci_hccr *hccr, struct ehci_hcor *hcor)
+#else
 static int ehci_fsl_init(int index, struct usb_ehci *ehci,
 			 struct ehci_hccr *hccr, struct ehci_hcor *hcor)
+#endif
 {
 	const char *phy_type = NULL;
+#ifndef CONFIG_DM_USB
 	size_t len;
 	char current_usb_controller[5];
+#endif
 #ifdef CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY
 	char usb_phy[5];
 
@@ -98,9 +215,6 @@
 		 */
 		mdelay(5);
 	}
-	memset(current_usb_controller, '\0', 5);
-	snprintf(current_usb_controller, sizeof(current_usb_controller),
-		 "usb%d", index+1);
 
 	/* Set to Host mode */
 	setbits_le32(&ehci->usbmode, CM_HOST);
@@ -109,9 +223,18 @@
 	out_be32(&ehci->snoop2, 0x80000000 | SNOOP_SIZE_2GB);
 
 	/* Init phy */
+#ifdef CONFIG_DM_USB
+	if (priv->phy_type)
+		phy_type = priv->phy_type;
+#else
+	memset(current_usb_controller, '\0', 5);
+	snprintf(current_usb_controller, sizeof(current_usb_controller),
+		 "usb%d", index+1);
+
 	if (hwconfig_sub(current_usb_controller, "phy_type"))
 		phy_type = hwconfig_subarg(current_usb_controller,
 				"phy_type", &len);
+#endif
 	else
 		phy_type = getenv("usb_phy_type");