diff mbox

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

Message ID 1351693612-23314-6-git-send-email-keshava_mgowda@ti.com (mailing list archive)
State New, archived
Headers show

Commit Message

Munegowda, Keshava Oct. 31, 2012, 2:26 p.m. UTC
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@ti.com>
---
 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(-)

Comments

Tony Lindgren Oct. 31, 2012, 6:29 p.m. UTC | #1
* Keshava Munegowda <keshava_mgowda@ti.com> [121031 07:29]:
> 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@ti.com>
> ---
>  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);

Just checking.. Have you tested that these patches also
still work without device tree?

Regards,

Tony
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Munegowda, Keshava Nov. 1, 2012, 8:19 a.m. UTC | #2

Felipe Balbi Nov. 1, 2012, 10:21 a.m. UTC | #3
On Thu, Nov 01, 2012 at 09:19:48AM +0100, Munegowda, Keshava wrote:
> 
> ________________________________________
> From: Tony Lindgren [tony@atomide.com]
> Sent: Wednesday, October 31, 2012 11:59 PM
> To: Munegowda, Keshava
> Cc: linux-omap@vger.kernel.org; devicetree-discuss@lists.ozlabs.org; linux-doc@vger.kernel.org; linux-usb@vger.kernel.org; Balbi, Felipe; sameo@linux.intel.com; Cousson, Benoit
> Subject: Re: [RESEND PATCH 05/11] ARM: OMAP: USB: Host: usb host Device tree node Adaptation
> 
> * Keshava Munegowda <keshava_mgowda@ti.com> [121031 07:29]:
> > 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@ti.com>
> > ---
> >  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);
> 
> Just checking.. Have you tested that these patches also
> still work without device tree?
> 
> Regards,
> 
> Tony
> 
> 
> No ! with out device tree enabled , these patches does not work.
> do I need to make a code such way that it works with and without
> device tree..?

yes. OMAP3/4 still have lots of legacy platform_data-only board support
;-)
Munegowda, Keshava Nov. 1, 2012, 3:12 p.m. UTC | #4

diff mbox

Patch

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;
 };
 
 /*-------------------------------------------------------------------------*/