[RESEND PATCH 05/11] ARM: OMAP: USB: Host: usb host Device tree node Adaptation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The USB2 Host device node is extracted and used in the probe
of the driver to initialize the usb ports and controller. The
platform specific initialization is also performed.

Signed-off-by: Keshava Munegowda <keshava_mgowda@xxxxxx>
---
 arch/arm/mach-omap2/usb-host.c         |    2 -
 drivers/mfd/omap-usb-host.c            |  163 +++++++++++++++++++++++---------
 include/linux/platform_data/usb-omap.h |   19 +++-
 3 files changed, 133 insertions(+), 51 deletions(-)

diff --git a/arch/arm/mach-omap2/usb-host.c b/arch/arm/mach-omap2/usb-host.c
index d1dbe12..239c175 100644
--- a/arch/arm/mach-omap2/usb-host.c
+++ b/arch/arm/mach-omap2/usb-host.c
@@ -502,8 +502,6 @@ void __init usbhs_init(const struct usbhs_omap_board_data *pdata)
 	}
 	ehci_data.phy_reset = pdata->phy_reset;
 	ohci_data.es2_compatibility = pdata->es2_compatibility;
-	usbhs_data.ehci_data = &ehci_data;
-	usbhs_data.ohci_data = &ohci_data;
 
 	if (cpu_is_omap34xx()) {
 		setup_ehci_io_mux(pdata->port_mode);
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
index cebfe0a..4b3af16 100644
--- a/drivers/mfd/omap-usb-host.c
+++ b/drivers/mfd/omap-usb-host.c
@@ -24,7 +24,7 @@
 #include <linux/clk.h>
 #include <linux/dma-mapping.h>
 #include <linux/spinlock.h>
-#include <linux/gpio.h>
+#include <linux/of_gpio.h>
 #include <plat/cpu.h>
 #include <linux/platform_device.h>
 #include <linux/platform_data/usb-omap.h>
@@ -103,8 +103,6 @@ struct usbhs_hcd_omap {
 
 	void __iomem			*uhh_base;
 
-	struct usbhs_omap_platform_data	platdata;
-
 	u32				usbhs_rev;
 	spinlock_t			lock;
 };
@@ -186,8 +184,6 @@ static int omap_usbhs_alloc_children(struct platform_device *pdev)
 {
 	struct device				*dev = &pdev->dev;
 	struct usbhs_hcd_omap			*omap;
-	struct ehci_hcd_omap_platform_data	*ehci_data;
-	struct ohci_hcd_omap_platform_data	*ohci_data;
 	struct platform_device			*ehci;
 	struct platform_device			*ohci;
 	struct resource				*res;
@@ -195,8 +191,6 @@ static int omap_usbhs_alloc_children(struct platform_device *pdev)
 	int					ret;
 
 	omap = platform_get_drvdata(pdev);
-	ehci_data = omap->platdata.ehci_data;
-	ohci_data = omap->platdata.ohci_data;
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ehci");
 	if (!res) {
@@ -214,8 +208,8 @@ static int omap_usbhs_alloc_children(struct platform_device *pdev)
 	}
 	resources[1] = *res;
 
-	ehci = omap_usbhs_alloc_child(OMAP_EHCI_DEVICE, resources, 2, ehci_data,
-		sizeof(*ehci_data), dev);
+	ehci = omap_usbhs_alloc_child(OMAP_EHCI_DEVICE, resources, 2, NULL,
+		0, dev);
 
 	if (!ehci) {
 		dev_err(dev, "omap_usbhs_alloc_child failed\n");
@@ -239,8 +233,8 @@ static int omap_usbhs_alloc_children(struct platform_device *pdev)
 	}
 	resources[1] = *res;
 
-	ohci = omap_usbhs_alloc_child(OMAP_OHCI_DEVICE, resources, 2, ohci_data,
-		sizeof(*ohci_data), dev);
+	ohci = omap_usbhs_alloc_child(OMAP_OHCI_DEVICE, resources, 2, NULL,
+		0, dev);
 	if (!ohci) {
 		dev_err(dev, "omap_usbhs_alloc_child failed\n");
 		ret = -ENOMEM;
@@ -279,7 +273,7 @@ static bool is_ohci_port(enum usbhs_omap_port_mode pmode)
 static int usbhs_runtime_resume(struct device *dev)
 {
 	struct usbhs_hcd_omap		*omap = dev_get_drvdata(dev);
-	struct usbhs_omap_platform_data	*pdata = &omap->platdata;
+	struct usbhs_omap_platform_data	*pdata = dev->platform_data;
 	unsigned long			flags;
 
 	dev_dbg(dev, "usbhs_runtime_resume\n");
@@ -295,6 +289,7 @@ static int usbhs_runtime_resume(struct device *dev)
 	if (omap->ehci_logic_fck && !IS_ERR(omap->ehci_logic_fck))
 		clk_enable(omap->ehci_logic_fck);
 
+	clk_enable(pdata->hub_clk);
 	if (is_ehci_tll_mode(pdata->port_mode[0]))
 		clk_enable(omap->usbhost_p1_fck);
 	if (is_ehci_tll_mode(pdata->port_mode[1]))
@@ -311,7 +306,7 @@ static int usbhs_runtime_resume(struct device *dev)
 static int usbhs_runtime_suspend(struct device *dev)
 {
 	struct usbhs_hcd_omap		*omap = dev_get_drvdata(dev);
-	struct usbhs_omap_platform_data	*pdata = &omap->platdata;
+	struct usbhs_omap_platform_data	*pdata = dev->platform_data;
 	unsigned long			flags;
 
 	dev_dbg(dev, "usbhs_runtime_suspend\n");
@@ -331,6 +326,7 @@ static int usbhs_runtime_suspend(struct device *dev)
 	clk_disable(omap->utmi_p2_fck);
 	clk_disable(omap->utmi_p1_fck);
 
+	clk_disable(pdata->hub_clk);
 	if (omap->ehci_logic_fck && !IS_ERR(omap->ehci_logic_fck))
 		clk_disable(omap->ehci_logic_fck);
 
@@ -343,19 +339,29 @@ static int usbhs_runtime_suspend(struct device *dev)
 static void omap_usbhs_init(struct device *dev)
 {
 	struct usbhs_hcd_omap		*omap = dev_get_drvdata(dev);
-	struct usbhs_omap_platform_data	*pdata = &omap->platdata;
+	struct usbhs_omap_platform_data	*pdata = dev->platform_data;
 	unsigned long			flags;
 	unsigned			reg;
 
 	dev_dbg(dev, "starting TI HSUSB Controller\n");
 
-	if (pdata->ehci_data->phy_reset) {
-		if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
-			gpio_request_one(pdata->ehci_data->reset_gpio_port[0],
+	if (gpio_is_valid(pdata->hub_power_gpio))
+		gpio_request_one(pdata->hub_power_gpio, GPIOF_OUT_INIT_HIGH,
+				 "Hub Power");
+	if (gpio_is_valid(pdata->hub_reset_gpio)) {
+		gpio_request_one(pdata->hub_reset_gpio, GPIOF_OUT_INIT_LOW,
+				 "Hub Reset Power");
+		udelay(5);
+		gpio_set_value_cansleep(pdata->hub_reset_gpio, 1);
+	}
+
+	if (pdata->phy_reset) {
+		if (gpio_is_valid(pdata->reset_gpio[0]))
+			gpio_request_one(pdata->reset_gpio[0],
 					 GPIOF_OUT_INIT_LOW, "USB1 PHY reset");
 
-		if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
-			gpio_request_one(pdata->ehci_data->reset_gpio_port[1],
+		if (gpio_is_valid(pdata->reset_gpio[1]))
+			gpio_request_one(pdata->reset_gpio[1],
 					 GPIOF_OUT_INIT_LOW, "USB2 PHY reset");
 
 		/* Hold the PHY in RESET for enough time till DIR is high */
@@ -431,36 +437,85 @@ static void omap_usbhs_init(struct device *dev)
 	spin_unlock_irqrestore(&omap->lock, flags);
 
 	pm_runtime_put_sync(dev);
-	if (pdata->ehci_data->phy_reset) {
+	if (pdata->phy_reset) {
 		/* Hold the PHY in RESET for enough time till
 		 * PHY is settled and ready
 		 */
 		udelay(10);
 
-		if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
+		if (gpio_is_valid(pdata->reset_gpio[0]))
 			gpio_set_value_cansleep
-				(pdata->ehci_data->reset_gpio_port[0], 1);
+				(pdata->reset_gpio[0], 1);
 
-		if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
+		if (gpio_is_valid(pdata->reset_gpio[1]))
 			gpio_set_value_cansleep
-				(pdata->ehci_data->reset_gpio_port[1], 1);
+				(pdata->reset_gpio[1], 1);
 	}
 }
 
 static void omap_usbhs_deinit(struct device *dev)
 {
-	struct usbhs_hcd_omap		*omap = dev_get_drvdata(dev);
-	struct usbhs_omap_platform_data	*pdata = &omap->platdata;
+	struct usbhs_omap_platform_data	*pdata = dev->platform_data;
 
-	if (pdata->ehci_data->phy_reset) {
-		if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
-			gpio_free(pdata->ehci_data->reset_gpio_port[0]);
+	if (pdata->phy_reset) {
+		if (gpio_is_valid(pdata->reset_gpio[0]))
+			gpio_free(pdata->reset_gpio[0]);
 
-		if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
-			gpio_free(pdata->ehci_data->reset_gpio_port[1]);
+		if (gpio_is_valid(pdata->reset_gpio[1]))
+			gpio_free(pdata->reset_gpio[1]);
 	}
 }
 
+static struct usbhs_omap_platform_data *of_get_usbhs_pdata(struct device *dev)
+{
+	struct usbhs_omap_platform_data *pdata;
+	struct device_node *np = dev->of_node;
+	struct property *pp;
+	char hubclk[20];
+
+	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return NULL; /* out of memory */
+
+	of_property_read_u32(np, "port-0", &pdata->port_mode[0]);
+	of_property_read_u32(np, "port-1", &pdata->port_mode[1]);
+	of_property_read_u32(np, "port-2", &pdata->port_mode[2]);
+	pdata->reset_gpio[0] = of_get_named_gpio(np, "reset-gpio-1", 0);
+	pdata->reset_gpio[1] = of_get_named_gpio(np, "reset-gpio-2", 0);
+	pdata->reset_gpio[2] = of_get_named_gpio(np, "reset-gpio-3", 0);
+
+	if (gpio_is_valid(pdata->reset_gpio[0]) ||
+	    gpio_is_valid(pdata->reset_gpio[1]) ||
+	    gpio_is_valid(pdata->reset_gpio[2]))
+		pdata->phy_reset = true;
+
+	pp = of_find_property(np, "hub-clk", NULL);
+	if (pp) {
+		strncpy(hubclk, pp->value, 20);
+		pdata->hub_clk = clk_get(NULL, hubclk);
+		if (IS_ERR(pdata->hub_clk)) {
+			dev_err(dev, "hub clk failed error: %ld\n",
+				PTR_ERR(pdata->hub_clk));
+			goto err_end;
+		}
+	} else {
+		pdata->hub_clk = NULL;
+	}
+	if (pdata->hub_clk) {
+		of_property_read_u32(np, "hub-clkrate", &pdata->hub_clkrate);
+		clk_set_rate(pdata->hub_clk, pdata->hub_clkrate);
+	}
+
+	pdata->hub_power_gpio =	of_get_named_gpio(np, "hub-power-gpio", 0);
+	pdata->hub_reset_gpio =	of_get_named_gpio(np, "hub-reset-gpio", 0);
+
+	return pdata;
+
+err_end:
+	devm_kfree(dev, pdata);
+	return NULL;
+}
+
 
 /**
  * usbhs_omap_probe - initialize TI-based HCDs
@@ -470,14 +525,16 @@ static void omap_usbhs_deinit(struct device *dev)
 static int __devinit usbhs_omap_probe(struct platform_device *pdev)
 {
 	struct device			*dev =  &pdev->dev;
-	struct usbhs_omap_platform_data	*pdata = dev->platform_data;
+	struct usbhs_omap_platform_data	*pdata;
 	struct usbhs_hcd_omap		*omap;
 	struct resource			*res;
 	int				ret = 0;
 	int				i;
 
+
+	pdata = of_get_usbhs_pdata(dev);
 	if (!pdata) {
-		dev_err(dev, "Missing platform data\n");
+		dev_err(dev, "function of_get_usbhs_pdata failed\n");
 		ret = -ENOMEM;
 		goto end_probe;
 	}
@@ -486,20 +543,13 @@ static int __devinit usbhs_omap_probe(struct platform_device *pdev)
 	if (!omap) {
 		dev_err(dev, "Memory allocation failed\n");
 		ret = -ENOMEM;
-		goto end_probe;
+		goto err_pdata;
 	}
 
 	spin_lock_init(&omap->lock);
 
-	for (i = 0; i < OMAP3_HS_USB_PORTS; i++)
-		omap->platdata.port_mode[i] = pdata->port_mode[i];
-
-	omap->platdata.ehci_data = pdata->ehci_data;
-	omap->platdata.ohci_data = pdata->ohci_data;
-
 	pm_runtime_enable(dev);
 
-
 	for (i = 0; i < OMAP3_HS_USB_PORTS; i++)
 		if (is_ehci_phy_mode(i) || is_ehci_tll_mode(i) ||
 			is_ehci_hsic_mode(i)) {
@@ -516,7 +566,7 @@ static int __devinit usbhs_omap_probe(struct platform_device *pdev)
 	if (IS_ERR(omap->utmi_p1_fck)) {
 		ret = PTR_ERR(omap->utmi_p1_fck);
 		dev_err(dev, "utmi_p1_gfclk failed error:%d\n",	ret);
-		goto err_end;
+		goto err_ehci_fck;
 	}
 
 	omap->xclk60mhsp1_ck = clk_get(dev, "xclk60mhsp1_ck");
@@ -605,6 +655,7 @@ static int __devinit usbhs_omap_probe(struct platform_device *pdev)
 	}
 
 	platform_set_drvdata(pdev, omap);
+	dev->platform_data = pdata;
 
 	omap_usbhs_init(dev);
 	ret = omap_usbhs_alloc_children(pdev);
@@ -640,11 +691,15 @@ err_xclk60mhsp1_ck:
 err_utmi_p1_fck:
 	clk_put(omap->utmi_p1_fck);
 
-err_end:
+err_ehci_fck:
 	clk_put(omap->ehci_logic_fck);
 	pm_runtime_disable(dev);
 	kfree(omap);
 
+err_pdata:
+	clk_put(pdata->hub_clk);
+	devm_kfree(dev, pdata);
+
 end_probe:
 	return ret;
 }
@@ -657,9 +712,11 @@ end_probe:
  */
 static int __devexit usbhs_omap_remove(struct platform_device *pdev)
 {
-	struct usbhs_hcd_omap *omap = platform_get_drvdata(pdev);
+	struct device			*dev =  &pdev->dev;
+	struct usbhs_hcd_omap		*omap = platform_get_drvdata(pdev);
+	struct usbhs_omap_platform_data	*pdata = dev->platform_data;
 
-	omap_usbhs_deinit(&pdev->dev);
+	omap_usbhs_deinit(dev);
 	iounmap(omap->uhh_base);
 	clk_put(omap->init_60m_fclk);
 	clk_put(omap->usbhost_p2_fck);
@@ -669,7 +726,9 @@ static int __devexit usbhs_omap_remove(struct platform_device *pdev)
 	clk_put(omap->xclk60mhsp1_ck);
 	clk_put(omap->utmi_p1_fck);
 	clk_put(omap->ehci_logic_fck);
-	pm_runtime_disable(&pdev->dev);
+	pm_runtime_disable(dev);
+	clk_put(pdata->hub_clk);
+	devm_kfree(dev, pdata);
 	kfree(omap);
 
 	return 0;
@@ -680,11 +739,23 @@ static const struct dev_pm_ops usbhsomap_dev_pm_ops = {
 	.runtime_resume		= usbhs_runtime_resume,
 };
 
+#ifdef CONFIG_OF
+static const struct of_device_id omap_usbhs_of_match[] = {
+	{
+		.compatible = "ti,usbhs",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, omap_usbhs_of_match);
+
+#endif
+
 static struct platform_driver usbhs_omap_driver = {
 	.driver = {
 		.name		= (char *)usbhs_driver_name,
 		.owner		= THIS_MODULE,
 		.pm		= &usbhsomap_dev_pm_ops,
+		.of_match_table = of_match_ptr(omap_usbhs_of_match),
 	},
 	.remove		= __exit_p(usbhs_omap_remove),
 };
diff --git a/include/linux/platform_data/usb-omap.h b/include/linux/platform_data/usb-omap.h
index 8570bcf..04dcf67 100644
--- a/include/linux/platform_data/usb-omap.h
+++ b/include/linux/platform_data/usb-omap.h
@@ -55,10 +55,23 @@ struct ohci_hcd_omap_platform_data {
 };
 
 struct usbhs_omap_platform_data {
-	enum usbhs_omap_port_mode		port_mode[OMAP3_HS_USB_PORTS];
+	enum usbhs_omap_port_mode	port_mode[OMAP3_HS_USB_PORTS];
+	int				reset_gpio[OMAP3_HS_USB_PORTS];
+
+	/*
+	 * Regulators for USB PHYs.
+	 * Each PHY can have a separate regulator.
+	 */
+	struct regulator		*regulator[OMAP3_HS_USB_PORTS];
 
-	struct ehci_hcd_omap_platform_data	*ehci_data;
-	struct ohci_hcd_omap_platform_data	*ohci_data;
+	unsigned			phy_reset:1;
+
+	/* Set this to true for ES2.x silicon */
+	unsigned			es2_compatibility:1;
+	struct clk			*hub_clk;
+	int				hub_clkrate;
+	int				hub_power_gpio;
+	int				hub_reset_gpio;
 };
 
 /*-------------------------------------------------------------------------*/
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux