Thread (10 messages) 10 messages, 2 authors, 2012-10-31
STALE4970d
Revisions (2)
  1. v1 current
  2. resend [diff vs current]

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

From: Keshava Munegowda <hidden>
Date: 2012-10-31 12:16:43
Also in: linux-omap
Subsystem: arm port, multifunction devices (mfd), omap usb support, omap2+ support, the rest · Maintainers: Russell King, Lee Jones, Aaro Koskinen, Andreas Kemnade, Kevin Hilman, Roger Quadros, Tony Lindgren, Linus Torvalds

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 <redacted>
---
 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
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help