Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v9 10/20] mfd: omap-usb-tll: Add OMAP5 revision and HSIC support
From: Roger Quadros @ 2013-01-23 10:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1358937492-8129-1-git-send-email-rogerq@ti.com>

The TLL module on OMAP5 has 3 channels.
HSIC mode requires the TLL channel to be in Transparent UTMI mode.

Signed-off-by: Roger Quadros <rogerq@ti.com>
Reviewed-by: Felipe Balbi <balbi@ti.com>
---
 drivers/mfd/omap-usb-tll.c |   14 ++++++++++++++
 1 files changed, 14 insertions(+), 0 deletions(-)

diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c
index 55c85c7..0aef1a7 100644
--- a/drivers/mfd/omap-usb-tll.c
+++ b/drivers/mfd/omap-usb-tll.c
@@ -54,10 +54,13 @@
 
 #define	OMAP_TLL_CHANNEL_CONF(num)			(0x040 + 0x004 * num)
 #define OMAP_TLL_CHANNEL_CONF_FSLSMODE_SHIFT		24
+#define OMAP_TLL_CHANNEL_CONF_DRVVBUS			(1 << 16)
+#define OMAP_TLL_CHANNEL_CONF_CHRGVBUS			(1 << 15)
 #define	OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF		(1 << 11)
 #define	OMAP_TLL_CHANNEL_CONF_ULPI_ULPIAUTOIDLE		(1 << 10)
 #define	OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE		(1 << 9)
 #define	OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE		(1 << 8)
+#define OMAP_TLL_CHANNEL_CONF_MODE_TRANSPARENT_UTMI	(2 << 1)
 #define OMAP_TLL_CHANNEL_CONF_CHANMODE_FSLS		(1 << 1)
 #define	OMAP_TLL_CHANNEL_CONF_CHANEN			(1 << 0)
 
@@ -92,6 +95,7 @@
 #define OMAP_USBTLL_REV1		0x00000015	/* OMAP3 */
 #define OMAP_USBTLL_REV2		0x00000018	/* OMAP 3630 */
 #define OMAP_USBTLL_REV3		0x00000004	/* OMAP4 */
+#define OMAP_USBTLL_REV4		0x00000006	/* OMAP5 */
 
 #define is_ehci_tll_mode(x)	(x == OMAP_EHCI_PORT_MODE_TLL)
 
@@ -245,6 +249,7 @@ static int usbtll_omap_probe(struct platform_device *pdev)
 	ver =  usbtll_read(base, OMAP_USBTLL_REVISION);
 	switch (ver) {
 	case OMAP_USBTLL_REV1:
+	case OMAP_USBTLL_REV4:
 		tll->nch = OMAP_TLL_CHANNEL_COUNT;
 		break;
 	case OMAP_USBTLL_REV2:
@@ -310,6 +315,15 @@ static int usbtll_omap_probe(struct platform_device *pdev)
 				reg &= ~(OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE
 					| OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF
 					| OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE);
+			} else if (pdata->port_mode[i] ==
+					OMAP_EHCI_PORT_MODE_HSIC) {
+				/*
+				 * HSIC Mode requires UTMI port configurations
+				 */
+				reg |= OMAP_TLL_CHANNEL_CONF_DRVVBUS
+				 | OMAP_TLL_CHANNEL_CONF_CHRGVBUS
+				 | OMAP_TLL_CHANNEL_CONF_MODE_TRANSPARENT_UTMI
+				 | OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF;
 			} else {
 				continue;
 			}
-- 
1.7.4.1

^ permalink raw reply related

* [PATCH v9 09/20] mfd: omap-usb-tll: serialize access to TLL device
From: Roger Quadros @ 2013-01-23 10:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1358937492-8129-1-git-send-email-rogerq@ti.com>

Get rid of the unnecessary spin_lock_irqsave/restore() as there is
no interrupt handler for this driver. Instead we serialize access
to tll_dev using a global spinlock.

Signed-off-by: Roger Quadros <rogerq@ti.com>
Reviewed-by: Felipe Balbi <balbi@ti.com>
---
 drivers/mfd/omap-usb-tll.c |   53 ++++++++++++++++++++++---------------------
 1 files changed, 27 insertions(+), 26 deletions(-)

diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c
index eccc65e..55c85c7 100644
--- a/drivers/mfd/omap-usb-tll.c
+++ b/drivers/mfd/omap-usb-tll.c
@@ -103,14 +103,13 @@ struct usbtll_omap {
 	int					nch;	/* num. of channels */
 	struct usbhs_omap_platform_data		*pdata;
 	struct clk				**ch_clk;
-	/* secure the register updates */
-	spinlock_t				lock;
 };
 
 /*-------------------------------------------------------------------------*/
 
 static const char usbtll_driver_name[] = USBTLL_DRIVER_NAME;
 static struct device	*tll_dev;
+static DEFINE_SPINLOCK(tll_lock);	/* serialize access to tll_dev */
 
 /*-------------------------------------------------------------------------*/
 
@@ -212,7 +211,6 @@ static int usbtll_omap_probe(struct platform_device *pdev)
 	struct resource				*res;
 	struct usbtll_omap			*tll;
 	unsigned				reg;
-	unsigned long				flags;
 	int					ret = 0;
 	int					i, ver;
 	bool needs_tll;
@@ -230,8 +228,6 @@ static int usbtll_omap_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	spin_lock_init(&tll->lock);
-
 	tll->pdata = pdata;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -246,8 +242,6 @@ static int usbtll_omap_probe(struct platform_device *pdev)
 	pm_runtime_enable(dev);
 	pm_runtime_get_sync(dev);
 
-	spin_lock_irqsave(&tll->lock, flags);
-
 	ver =  usbtll_read(base, OMAP_USBTLL_REVISION);
 	switch (ver) {
 	case OMAP_USBTLL_REV1:
@@ -265,8 +259,6 @@ static int usbtll_omap_probe(struct platform_device *pdev)
 		break;
 	}
 
-	spin_unlock_irqrestore(&tll->lock, flags);
-
 	tll->ch_clk = devm_kzalloc(dev, sizeof(struct clk * [tll->nch]),
 						GFP_KERNEL);
 	if (!tll->ch_clk) {
@@ -286,8 +278,6 @@ static int usbtll_omap_probe(struct platform_device *pdev)
 			dev_dbg(dev, "can't get clock : %s\n", clkname);
 	}
 
-	spin_lock_irqsave(&tll->lock, flags);
-
 	needs_tll = false;
 	for (i = 0; i < tll->nch; i++)
 		needs_tll |= omap_usb_mode_needs_tll(pdata->port_mode[i]);
@@ -332,10 +322,11 @@ static int usbtll_omap_probe(struct platform_device *pdev)
 		}
 	}
 
-	spin_unlock_irqrestore(&tll->lock, flags);
 	pm_runtime_put_sync(dev);
 	/* only after this can omap_tll_enable/disable work */
+	spin_lock(&tll_lock);
 	tll_dev = dev;
+	spin_unlock(&tll_lock);
 
 	return 0;
 
@@ -357,7 +348,9 @@ static int usbtll_omap_remove(struct platform_device *pdev)
 	struct usbtll_omap *tll = platform_get_drvdata(pdev);
 	int i;
 
+	spin_lock(&tll_lock);
 	tll_dev = NULL;
+	spin_unlock(&tll_lock);
 
 	for (i = 0; i < tll->nch; i++)
 		if (!IS_ERR(tll->ch_clk[i]))
@@ -371,13 +364,10 @@ static int usbtll_runtime_resume(struct device *dev)
 {
 	struct usbtll_omap			*tll = dev_get_drvdata(dev);
 	struct usbhs_omap_platform_data		*pdata = tll->pdata;
-	unsigned long				flags;
 	int i;
 
 	dev_dbg(dev, "usbtll_runtime_resume\n");
 
-	spin_lock_irqsave(&tll->lock, flags);
-
 	for (i = 0; i < tll->nch; i++) {
 		if (omap_usb_mode_needs_tll(pdata->port_mode[i])) {
 			int r;
@@ -393,8 +383,6 @@ static int usbtll_runtime_resume(struct device *dev)
 		}
 	}
 
-	spin_unlock_irqrestore(&tll->lock, flags);
-
 	return 0;
 }
 
@@ -402,13 +390,10 @@ static int usbtll_runtime_suspend(struct device *dev)
 {
 	struct usbtll_omap			*tll = dev_get_drvdata(dev);
 	struct usbhs_omap_platform_data		*pdata = tll->pdata;
-	unsigned long				flags;
 	int i;
 
 	dev_dbg(dev, "usbtll_runtime_suspend\n");
 
-	spin_lock_irqsave(&tll->lock, flags);
-
 	for (i = 0; i < tll->nch; i++) {
 		if (omap_usb_mode_needs_tll(pdata->port_mode[i])) {
 			if (!IS_ERR(tll->ch_clk[i]))
@@ -416,8 +401,6 @@ static int usbtll_runtime_suspend(struct device *dev)
 		}
 	}
 
-	spin_unlock_irqrestore(&tll->lock, flags);
-
 	return 0;
 }
 
@@ -439,21 +422,39 @@ static struct platform_driver usbtll_omap_driver = {
 
 int omap_tll_enable(void)
 {
+	int ret;
+
+	spin_lock(&tll_lock);
+
 	if (!tll_dev) {
 		pr_err("%s: OMAP USB TLL not initialized\n", __func__);
-		return  -ENODEV;
+		ret = -ENODEV;
+	} else {
+		ret = pm_runtime_get_sync(tll_dev);
 	}
-	return pm_runtime_get_sync(tll_dev);
+
+	spin_unlock(&tll_lock);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(omap_tll_enable);
 
 int omap_tll_disable(void)
 {
+	int ret;
+
+	spin_lock(&tll_lock);
+
 	if (!tll_dev) {
 		pr_err("%s: OMAP USB TLL not initialized\n", __func__);
-		return  -ENODEV;
+		ret = -ENODEV;
+	} else {
+		ret = pm_runtime_put_sync(tll_dev);
 	}
-	return pm_runtime_put_sync(tll_dev);
+
+	spin_unlock(&tll_lock);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(omap_tll_disable);
 
-- 
1.7.4.1

^ permalink raw reply related

* [PATCH v9 08/20] mfd: omap-usb-tll: Fix error message
From: Roger Quadros @ 2013-01-23 10:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1358937492-8129-1-git-send-email-rogerq@ti.com>

omap_enable/disable_tll() can fail if TLL device is not
initialized. It could be due to multiple reasons and not only
due to missing platform data.

Also make local variables static and use 'struct device *'
instead of 'struct platform_device *' for global reference.

Signed-off-by: Roger Quadros <rogerq@ti.com>
Reviewed-by: Felipe Balbi <balbi@ti.com>
---
 drivers/mfd/omap-usb-tll.c |   21 ++++++++++++---------
 1 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c
index 3dbbfea..eccc65e 100644
--- a/drivers/mfd/omap-usb-tll.c
+++ b/drivers/mfd/omap-usb-tll.c
@@ -109,8 +109,8 @@ struct usbtll_omap {
 
 /*-------------------------------------------------------------------------*/
 
-const char usbtll_driver_name[] = USBTLL_DRIVER_NAME;
-struct platform_device	*tll_pdev;
+static const char usbtll_driver_name[] = USBTLL_DRIVER_NAME;
+static struct device	*tll_dev;
 
 /*-------------------------------------------------------------------------*/
 
@@ -334,7 +334,8 @@ static int usbtll_omap_probe(struct platform_device *pdev)
 
 	spin_unlock_irqrestore(&tll->lock, flags);
 	pm_runtime_put_sync(dev);
-	tll_pdev = pdev;
+	/* only after this can omap_tll_enable/disable work */
+	tll_dev = dev;
 
 	return 0;
 
@@ -356,6 +357,8 @@ static int usbtll_omap_remove(struct platform_device *pdev)
 	struct usbtll_omap *tll = platform_get_drvdata(pdev);
 	int i;
 
+	tll_dev = NULL;
+
 	for (i = 0; i < tll->nch; i++)
 		if (!IS_ERR(tll->ch_clk[i]))
 			clk_put(tll->ch_clk[i]);
@@ -436,21 +439,21 @@ static struct platform_driver usbtll_omap_driver = {
 
 int omap_tll_enable(void)
 {
-	if (!tll_pdev) {
-		pr_err("missing omap usbhs tll platform_data\n");
+	if (!tll_dev) {
+		pr_err("%s: OMAP USB TLL not initialized\n", __func__);
 		return  -ENODEV;
 	}
-	return pm_runtime_get_sync(&tll_pdev->dev);
+	return pm_runtime_get_sync(tll_dev);
 }
 EXPORT_SYMBOL_GPL(omap_tll_enable);
 
 int omap_tll_disable(void)
 {
-	if (!tll_pdev) {
-		pr_err("missing omap usbhs tll platform_data\n");
+	if (!tll_dev) {
+		pr_err("%s: OMAP USB TLL not initialized\n", __func__);
 		return  -ENODEV;
 	}
-	return pm_runtime_put_sync(&tll_pdev->dev);
+	return pm_runtime_put_sync(tll_dev);
 }
 EXPORT_SYMBOL_GPL(omap_tll_disable);
 
-- 
1.7.4.1

^ permalink raw reply related

* [PATCH v9 07/20] mfd: omap-usb-tll: Check for missing platform data in probe
From: Roger Quadros @ 2013-01-23 10:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1358937492-8129-1-git-send-email-rogerq@ti.com>

No need to check for missing platform data in runtime_suspend/resume
as it makes more sense to do it in the probe function.

Signed-off-by: Roger Quadros <rogerq@ti.com>
Reviewed-by: Felipe Balbi <balbi@ti.com>
---
 drivers/mfd/omap-usb-tll.c |   15 +++++----------
 1 files changed, 5 insertions(+), 10 deletions(-)

diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c
index af67b96..3dbbfea 100644
--- a/drivers/mfd/omap-usb-tll.c
+++ b/drivers/mfd/omap-usb-tll.c
@@ -225,6 +225,11 @@ static int usbtll_omap_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 
+	if (!pdata) {
+		dev_err(dev, "Platform data missing\n");
+		return -ENODEV;
+	}
+
 	spin_lock_init(&tll->lock);
 
 	tll->pdata = pdata;
@@ -368,11 +373,6 @@ static int usbtll_runtime_resume(struct device *dev)
 
 	dev_dbg(dev, "usbtll_runtime_resume\n");
 
-	if (!pdata) {
-		dev_dbg(dev, "missing platform_data\n");
-		return  -ENODEV;
-	}
-
 	spin_lock_irqsave(&tll->lock, flags);
 
 	for (i = 0; i < tll->nch; i++) {
@@ -404,11 +404,6 @@ static int usbtll_runtime_suspend(struct device *dev)
 
 	dev_dbg(dev, "usbtll_runtime_suspend\n");
 
-	if (!pdata) {
-		dev_dbg(dev, "missing platform_data\n");
-		return  -ENODEV;
-	}
-
 	spin_lock_irqsave(&tll->lock, flags);
 
 	for (i = 0; i < tll->nch; i++) {
-- 
1.7.4.1

^ permalink raw reply related

* [PATCH v9 06/20] mfd: omap-usb-tll: introduce and use mode_needs_tll()
From: Roger Quadros @ 2013-01-23 10:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1358937492-8129-1-git-send-email-rogerq@ti.com>

This is a handy macro to check if the port requires the
USB TLL module or not. Use it to Enable the TLL module and manage
the clocks.

Signed-off-by: Roger Quadros <rogerq@ti.com>
Reviewed-by: Felipe Balbi <balbi@ti.com>
---
 drivers/mfd/omap-usb-tll.c |   20 ++++++++++++--------
 1 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c
index bf7355e..af67b96 100644
--- a/drivers/mfd/omap-usb-tll.c
+++ b/drivers/mfd/omap-usb-tll.c
@@ -95,6 +95,10 @@
 
 #define is_ehci_tll_mode(x)	(x == OMAP_EHCI_PORT_MODE_TLL)
 
+/* only PHY and UNUSED modes don't need TLL */
+#define omap_usb_mode_needs_tll(x)	((x) != OMAP_USBHS_PORT_MODE_UNUSED &&\
+					 (x) != OMAP_EHCI_PORT_MODE_PHY)
+
 struct usbtll_omap {
 	int					nch;	/* num. of channels */
 	struct usbhs_omap_platform_data		*pdata;
@@ -211,6 +215,7 @@ static int usbtll_omap_probe(struct platform_device *pdev)
 	unsigned long				flags;
 	int					ret = 0;
 	int					i, ver;
+	bool needs_tll;
 
 	dev_dbg(dev, "starting TI HSUSB TLL Controller\n");
 
@@ -278,12 +283,11 @@ static int usbtll_omap_probe(struct platform_device *pdev)
 
 	spin_lock_irqsave(&tll->lock, flags);
 
-	if (is_ehci_tll_mode(pdata->port_mode[0]) ||
-	    is_ehci_tll_mode(pdata->port_mode[1]) ||
-	    is_ehci_tll_mode(pdata->port_mode[2]) ||
-	    is_ohci_port(pdata->port_mode[0]) ||
-	    is_ohci_port(pdata->port_mode[1]) ||
-	    is_ohci_port(pdata->port_mode[2])) {
+	needs_tll = false;
+	for (i = 0; i < tll->nch; i++)
+		needs_tll |= omap_usb_mode_needs_tll(pdata->port_mode[i]);
+
+	if (needs_tll) {
 
 		/* Program Common TLL register */
 		reg = usbtll_read(base, OMAP_TLL_SHARED_CONF);
@@ -372,7 +376,7 @@ static int usbtll_runtime_resume(struct device *dev)
 	spin_lock_irqsave(&tll->lock, flags);
 
 	for (i = 0; i < tll->nch; i++) {
-		if (is_ehci_tll_mode(pdata->port_mode[i])) {
+		if (omap_usb_mode_needs_tll(pdata->port_mode[i])) {
 			int r;
 
 			if (IS_ERR(tll->ch_clk[i]))
@@ -408,7 +412,7 @@ static int usbtll_runtime_suspend(struct device *dev)
 	spin_lock_irqsave(&tll->lock, flags);
 
 	for (i = 0; i < tll->nch; i++) {
-		if (is_ehci_tll_mode(pdata->port_mode[i])) {
+		if (omap_usb_mode_needs_tll(pdata->port_mode[i])) {
 			if (!IS_ERR(tll->ch_clk[i]))
 				clk_disable(tll->ch_clk[i]);
 		}
-- 
1.7.4.1

^ permalink raw reply related

* [PATCH v9 05/20] mfd: omap-usb-tll: Clean up clock handling
From: Roger Quadros @ 2013-01-23 10:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1358937492-8129-1-git-send-email-rogerq@ti.com>

Every channel has a functional clock that is similarly named.
It makes sense to use a for loop to manage these clocks as OMAPs
can come with up to 3 channels.

Dynamically allocate and get channel clocks depending on the
number of clocks avaiable on the platform.

Signed-off-by: Roger Quadros <rogerq@ti.com>
Reviewed-by: Felipe Balbi <balbi@ti.com>
Acked-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/mfd/omap-usb-tll.c |   87 +++++++++++++++++++++++++++-----------------
 1 files changed, 54 insertions(+), 33 deletions(-)

diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c
index 9a19cc7..bf7355e 100644
--- a/drivers/mfd/omap-usb-tll.c
+++ b/drivers/mfd/omap-usb-tll.c
@@ -96,10 +96,9 @@
 #define is_ehci_tll_mode(x)	(x == OMAP_EHCI_PORT_MODE_TLL)
 
 struct usbtll_omap {
-	struct clk				*usbtll_p1_fck;
-	struct clk				*usbtll_p2_fck;
 	int					nch;	/* num. of channels */
 	struct usbhs_omap_platform_data		*pdata;
+	struct clk				**ch_clk;
 	/* secure the register updates */
 	spinlock_t				lock;
 };
@@ -225,26 +224,12 @@ static int usbtll_omap_probe(struct platform_device *pdev)
 
 	tll->pdata = pdata;
 
-	tll->usbtll_p1_fck = clk_get(dev, "usb_tll_hs_usb_ch0_clk");
-	if (IS_ERR(tll->usbtll_p1_fck)) {
-		ret = PTR_ERR(tll->usbtll_p1_fck);
-		dev_err(dev, "usbtll_p1_fck failed error:%d\n", ret);
-		return ret;
-	}
-
-	tll->usbtll_p2_fck = clk_get(dev, "usb_tll_hs_usb_ch1_clk");
-	if (IS_ERR(tll->usbtll_p2_fck)) {
-		ret = PTR_ERR(tll->usbtll_p2_fck);
-		dev_err(dev, "usbtll_p2_fck failed error:%d\n", ret);
-		goto err_p2_fck;
-	}
-
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	base = devm_request_and_ioremap(dev, res);
 	if (!base) {
 		ret = -EADDRNOTAVAIL;
 		dev_err(dev, "Resource request/ioremap failed:%d\n", ret);
-		goto err_res;
+		return ret;
 	}
 
 	platform_set_drvdata(pdev, tll);
@@ -270,6 +255,29 @@ static int usbtll_omap_probe(struct platform_device *pdev)
 		break;
 	}
 
+	spin_unlock_irqrestore(&tll->lock, flags);
+
+	tll->ch_clk = devm_kzalloc(dev, sizeof(struct clk * [tll->nch]),
+						GFP_KERNEL);
+	if (!tll->ch_clk) {
+		ret = -ENOMEM;
+		dev_err(dev, "Couldn't allocate memory for channel clocks\n");
+		goto err_clk_alloc;
+	}
+
+	for (i = 0; i < tll->nch; i++) {
+		char clkname[] = "usb_tll_hs_usb_chx_clk";
+
+		snprintf(clkname, sizeof(clkname),
+					"usb_tll_hs_usb_ch%d_clk", i);
+		tll->ch_clk[i] = clk_get(dev, clkname);
+
+		if (IS_ERR(tll->ch_clk[i]))
+			dev_dbg(dev, "can't get clock : %s\n", clkname);
+	}
+
+	spin_lock_irqsave(&tll->lock, flags);
+
 	if (is_ehci_tll_mode(pdata->port_mode[0]) ||
 	    is_ehci_tll_mode(pdata->port_mode[1]) ||
 	    is_ehci_tll_mode(pdata->port_mode[2]) ||
@@ -321,11 +329,9 @@ static int usbtll_omap_probe(struct platform_device *pdev)
 
 	return 0;
 
-err_res:
-	clk_put(tll->usbtll_p2_fck);
-
-err_p2_fck:
-	clk_put(tll->usbtll_p1_fck);
+err_clk_alloc:
+	pm_runtime_put_sync(dev);
+	pm_runtime_disable(dev);
 
 	return ret;
 }
@@ -339,9 +345,12 @@ err_p2_fck:
 static int usbtll_omap_remove(struct platform_device *pdev)
 {
 	struct usbtll_omap *tll = platform_get_drvdata(pdev);
+	int i;
+
+	for (i = 0; i < tll->nch; i++)
+		if (!IS_ERR(tll->ch_clk[i]))
+			clk_put(tll->ch_clk[i]);
 
-	clk_put(tll->usbtll_p2_fck);
-	clk_put(tll->usbtll_p1_fck);
 	pm_runtime_disable(&pdev->dev);
 	return 0;
 }
@@ -351,6 +360,7 @@ static int usbtll_runtime_resume(struct device *dev)
 	struct usbtll_omap			*tll = dev_get_drvdata(dev);
 	struct usbhs_omap_platform_data		*pdata = tll->pdata;
 	unsigned long				flags;
+	int i;
 
 	dev_dbg(dev, "usbtll_runtime_resume\n");
 
@@ -361,11 +371,20 @@ static int usbtll_runtime_resume(struct device *dev)
 
 	spin_lock_irqsave(&tll->lock, flags);
 
-	if (is_ehci_tll_mode(pdata->port_mode[0]))
-		clk_enable(tll->usbtll_p1_fck);
+	for (i = 0; i < tll->nch; i++) {
+		if (is_ehci_tll_mode(pdata->port_mode[i])) {
+			int r;
 
-	if (is_ehci_tll_mode(pdata->port_mode[1]))
-		clk_enable(tll->usbtll_p2_fck);
+			if (IS_ERR(tll->ch_clk[i]))
+				continue;
+
+			r = clk_enable(tll->ch_clk[i]);
+			if (r) {
+				dev_err(dev,
+				 "Error enabling ch %d clock: %d\n", i, r);
+			}
+		}
+	}
 
 	spin_unlock_irqrestore(&tll->lock, flags);
 
@@ -377,6 +396,7 @@ static int usbtll_runtime_suspend(struct device *dev)
 	struct usbtll_omap			*tll = dev_get_drvdata(dev);
 	struct usbhs_omap_platform_data		*pdata = tll->pdata;
 	unsigned long				flags;
+	int i;
 
 	dev_dbg(dev, "usbtll_runtime_suspend\n");
 
@@ -387,11 +407,12 @@ static int usbtll_runtime_suspend(struct device *dev)
 
 	spin_lock_irqsave(&tll->lock, flags);
 
-	if (is_ehci_tll_mode(pdata->port_mode[0]))
-		clk_disable(tll->usbtll_p1_fck);
-
-	if (is_ehci_tll_mode(pdata->port_mode[1]))
-		clk_disable(tll->usbtll_p2_fck);
+	for (i = 0; i < tll->nch; i++) {
+		if (is_ehci_tll_mode(pdata->port_mode[i])) {
+			if (!IS_ERR(tll->ch_clk[i]))
+				clk_disable(tll->ch_clk[i]);
+		}
+	}
 
 	spin_unlock_irqrestore(&tll->lock, flags);
 
-- 
1.7.4.1

^ permalink raw reply related

* [PATCH v9 04/20] mfd: omap-usb-tll: Use devm_kzalloc/ioremap and clean up error path
From: Roger Quadros @ 2013-01-23 10:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1358937492-8129-1-git-send-email-rogerq@ti.com>

Use devm_ variants of kzalloc() and ioremap(). Simplify the error path.

Signed-off-by: Roger Quadros <rogerq@ti.com>
Reviewed-by: Felipe Balbi <balbi@ti.com>
---
 drivers/mfd/omap-usb-tll.c |   38 ++++++++++++--------------------------
 1 files changed, 12 insertions(+), 26 deletions(-)

diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c
index 9658e18..9a19cc7 100644
--- a/drivers/mfd/omap-usb-tll.c
+++ b/drivers/mfd/omap-usb-tll.c
@@ -215,11 +215,10 @@ static int usbtll_omap_probe(struct platform_device *pdev)
 
 	dev_dbg(dev, "starting TI HSUSB TLL Controller\n");
 
-	tll = kzalloc(sizeof(struct usbtll_omap), GFP_KERNEL);
+	tll = devm_kzalloc(dev, sizeof(struct usbtll_omap), GFP_KERNEL);
 	if (!tll) {
 		dev_err(dev, "Memory allocation failed\n");
-		ret = -ENOMEM;
-		goto end;
+		return -ENOMEM;
 	}
 
 	spin_lock_init(&tll->lock);
@@ -230,28 +229,22 @@ static int usbtll_omap_probe(struct platform_device *pdev)
 	if (IS_ERR(tll->usbtll_p1_fck)) {
 		ret = PTR_ERR(tll->usbtll_p1_fck);
 		dev_err(dev, "usbtll_p1_fck failed error:%d\n", ret);
-		goto err_tll;
+		return ret;
 	}
 
 	tll->usbtll_p2_fck = clk_get(dev, "usb_tll_hs_usb_ch1_clk");
 	if (IS_ERR(tll->usbtll_p2_fck)) {
 		ret = PTR_ERR(tll->usbtll_p2_fck);
 		dev_err(dev, "usbtll_p2_fck failed error:%d\n", ret);
-		goto err_usbtll_p1_fck;
+		goto err_p2_fck;
 	}
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(dev, "usb tll get resource failed\n");
-		ret = -ENODEV;
-		goto err_usbtll_p2_fck;
-	}
-
-	base = ioremap(res->start, resource_size(res));
+	base = devm_request_and_ioremap(dev, res);
 	if (!base) {
-		dev_err(dev, "TLL ioremap failed\n");
-		ret = -ENOMEM;
-		goto err_usbtll_p2_fck;
+		ret = -EADDRNOTAVAIL;
+		dev_err(dev, "Resource request/ioremap failed:%d\n", ret);
+		goto err_res;
 	}
 
 	platform_set_drvdata(pdev, tll);
@@ -323,23 +316,17 @@ static int usbtll_omap_probe(struct platform_device *pdev)
 	}
 
 	spin_unlock_irqrestore(&tll->lock, flags);
-	iounmap(base);
 	pm_runtime_put_sync(dev);
 	tll_pdev = pdev;
-	if (!ret)
-		goto end;
-	pm_runtime_disable(dev);
 
-err_usbtll_p2_fck:
+	return 0;
+
+err_res:
 	clk_put(tll->usbtll_p2_fck);
 
-err_usbtll_p1_fck:
+err_p2_fck:
 	clk_put(tll->usbtll_p1_fck);
 
-err_tll:
-	kfree(tll);
-
-end:
 	return ret;
 }
 
@@ -356,7 +343,6 @@ static int usbtll_omap_remove(struct platform_device *pdev)
 	clk_put(tll->usbtll_p2_fck);
 	clk_put(tll->usbtll_p1_fck);
 	pm_runtime_disable(&pdev->dev);
-	kfree(tll);
 	return 0;
 }
 
-- 
1.7.4.1

^ permalink raw reply related

* [PATCH v9 03/20] mfd: omap-usb-tll: Fix channel count detection
From: Roger Quadros @ 2013-01-23 10:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1358937492-8129-1-git-send-email-rogerq@ti.com>

Fix channel count detecion for REV2. Also, don't give up
if we don't recognize the IP Revision. We assume the default
number of channels (i.e. 3) for unrecognized IPs.

Signed-off-by: Roger Quadros <rogerq@ti.com>
Reviewed-by: Felipe Balbi <balbi@ti.com>
---
 drivers/mfd/omap-usb-tll.c |   20 +++++++++++---------
 1 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c
index e459489..9658e18 100644
--- a/drivers/mfd/omap-usb-tll.c
+++ b/drivers/mfd/omap-usb-tll.c
@@ -98,6 +98,7 @@
 struct usbtll_omap {
 	struct clk				*usbtll_p1_fck;
 	struct clk				*usbtll_p2_fck;
+	int					nch;	/* num. of channels */
 	struct usbhs_omap_platform_data		*pdata;
 	/* secure the register updates */
 	spinlock_t				lock;
@@ -210,7 +211,7 @@ static int usbtll_omap_probe(struct platform_device *pdev)
 	unsigned				reg;
 	unsigned long				flags;
 	int					ret = 0;
-	int					i, ver, count;
+	int					i, ver;
 
 	dev_dbg(dev, "starting TI HSUSB TLL Controller\n");
 
@@ -262,16 +263,18 @@ static int usbtll_omap_probe(struct platform_device *pdev)
 	ver =  usbtll_read(base, OMAP_USBTLL_REVISION);
 	switch (ver) {
 	case OMAP_USBTLL_REV1:
-	case OMAP_USBTLL_REV2:
-		count = OMAP_TLL_CHANNEL_COUNT;
+		tll->nch = OMAP_TLL_CHANNEL_COUNT;
 		break;
+	case OMAP_USBTLL_REV2:
 	case OMAP_USBTLL_REV3:
-		count = OMAP_REV2_TLL_CHANNEL_COUNT;
+		tll->nch = OMAP_REV2_TLL_CHANNEL_COUNT;
 		break;
 	default:
-		dev_err(dev, "TLL version failed\n");
-		ret = -ENODEV;
-		goto err_ioremap;
+		tll->nch = OMAP_TLL_CHANNEL_COUNT;
+		dev_dbg(dev,
+		 "USB TLL Rev : 0x%x not recognized, assuming %d channels\n",
+			ver, tll->nch);
+		break;
 	}
 
 	if (is_ehci_tll_mode(pdata->port_mode[0]) ||
@@ -291,7 +294,7 @@ static int usbtll_omap_probe(struct platform_device *pdev)
 		usbtll_write(base, OMAP_TLL_SHARED_CONF, reg);
 
 		/* Enable channels now */
-		for (i = 0; i < count; i++) {
+		for (i = 0; i < tll->nch; i++) {
 			reg = usbtll_read(base,	OMAP_TLL_CHANNEL_CONF(i));
 
 			if (is_ohci_port(pdata->port_mode[i])) {
@@ -319,7 +322,6 @@ static int usbtll_omap_probe(struct platform_device *pdev)
 		}
 	}
 
-err_ioremap:
 	spin_unlock_irqrestore(&tll->lock, flags);
 	iounmap(base);
 	pm_runtime_put_sync(dev);
-- 
1.7.4.1

^ permalink raw reply related

* [PATCH v9 02/20] mfd: omap-usb-host: Consolidate OMAP USB-HS platform data
From: Roger Quadros @ 2013-01-23 10:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1358937492-8129-1-git-send-email-rogerq@ti.com>

Let's have a single platform data structure for the OMAP's High-Speed
USB host subsystem instead of having 3 separate ones i.e. one for
board data, one for USB Host (UHH) module and one for USB-TLL module.

This makes the code much simpler and avoids creating multiple copies of
platform data.

CC: Alan Stern <stern@rowland.harvard.edu>

Signed-off-by: Roger Quadros <rogerq@ti.com>
Reviewed-by: Felipe Balbi <balbi@ti.com>
For the ehci-omap.c part:
Acked-by: Alan Stern <stern@rowland.harvard.edu>
---
 arch/arm/mach-omap2/board-3430sdp.c        |    2 +-
 arch/arm/mach-omap2/board-3630sdp.c        |    2 +-
 arch/arm/mach-omap2/board-am3517crane.c    |    2 +-
 arch/arm/mach-omap2/board-am3517evm.c      |    2 +-
 arch/arm/mach-omap2/board-cm-t35.c         |    2 +-
 arch/arm/mach-omap2/board-cm-t3517.c       |    2 +-
 arch/arm/mach-omap2/board-devkit8000.c     |    2 +-
 arch/arm/mach-omap2/board-igep0020.c       |    4 +-
 arch/arm/mach-omap2/board-omap3beagle.c    |    2 +-
 arch/arm/mach-omap2/board-omap3evm.c       |    2 +-
 arch/arm/mach-omap2/board-omap3pandora.c   |    2 +-
 arch/arm/mach-omap2/board-omap3stalker.c   |    2 +-
 arch/arm/mach-omap2/board-omap3touchbook.c |    2 +-
 arch/arm/mach-omap2/board-omap4panda.c     |    2 +-
 arch/arm/mach-omap2/board-overo.c          |    2 +-
 arch/arm/mach-omap2/board-zoom.c           |    2 +-
 arch/arm/mach-omap2/usb-host.c             |   29 ++-----------
 arch/arm/mach-omap2/usb.h                  |   20 +--------
 drivers/mfd/omap-usb-host.c                |   63 +++++++++++----------------
 drivers/mfd/omap-usb-tll.c                 |   11 ++---
 drivers/usb/host/ehci-omap.c               |    6 +-
 include/linux/platform_data/usb-omap.h     |   23 ++--------
 22 files changed, 61 insertions(+), 125 deletions(-)

diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index bb73afc..46147c8 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -424,7 +424,7 @@ static void enable_board_wakeup_source(void)
 		OMAP_WAKEUP_EN | OMAP_PIN_INPUT_PULLUP);
 }
 
-static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
+static struct usbhs_omap_platform_data usbhs_bdata __initdata = {
 
 	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
 	.port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
diff --git a/arch/arm/mach-omap2/board-3630sdp.c b/arch/arm/mach-omap2/board-3630sdp.c
index 050aaa7..78b1724 100644
--- a/arch/arm/mach-omap2/board-3630sdp.c
+++ b/arch/arm/mach-omap2/board-3630sdp.c
@@ -53,7 +53,7 @@ static void enable_board_wakeup_source(void)
 		OMAP_WAKEUP_EN | OMAP_PIN_INPUT_PULLUP);
 }
 
-static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
+static struct usbhs_omap_platform_data usbhs_bdata __initdata = {
 
 	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
 	.port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
diff --git a/arch/arm/mach-omap2/board-am3517crane.c b/arch/arm/mach-omap2/board-am3517crane.c
index 51b96a1..26f1916 100644
--- a/arch/arm/mach-omap2/board-am3517crane.c
+++ b/arch/arm/mach-omap2/board-am3517crane.c
@@ -40,7 +40,7 @@ static struct omap_board_mux board_mux[] __initdata = {
 };
 #endif
 
-static struct usbhs_omap_board_data usbhs_bdata __initdata = {
+static struct usbhs_omap_platform_data usbhs_bdata __initdata = {
 	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
 	.port_mode[1] = OMAP_USBHS_PORT_MODE_UNUSED,
 	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c
index f81a303..c76725d 100644
--- a/arch/arm/mach-omap2/board-am3517evm.c
+++ b/arch/arm/mach-omap2/board-am3517evm.c
@@ -274,7 +274,7 @@ static __init void am3517_evm_mcbsp1_init(void)
 	omap_ctrl_writel(devconf0, OMAP2_CONTROL_DEVCONF0);
 }
 
-static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
+static struct usbhs_omap_platform_data usbhs_bdata __initdata = {
 	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
 #if defined(CONFIG_PANEL_SHARP_LQ043T1DG01) || \
 		defined(CONFIG_PANEL_SHARP_LQ043T1DG01_MODULE)
diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index b3102c2..cdf1d6e 100644
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -418,7 +418,7 @@ static struct omap2_hsmmc_info mmc[] = {
 	{}	/* Terminator */
 };
 
-static struct usbhs_omap_board_data usbhs_bdata __initdata = {
+static struct usbhs_omap_platform_data usbhs_bdata __initdata = {
 	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
 	.port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
 	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
diff --git a/arch/arm/mach-omap2/board-cm-t3517.c b/arch/arm/mach-omap2/board-cm-t3517.c
index ebbc2ad..cfa9098 100644
--- a/arch/arm/mach-omap2/board-cm-t3517.c
+++ b/arch/arm/mach-omap2/board-cm-t3517.c
@@ -166,7 +166,7 @@ static inline void cm_t3517_init_rtc(void) {}
 #define HSUSB2_RESET_GPIO	(147)
 #define USB_HUB_RESET_GPIO	(152)
 
-static struct usbhs_omap_board_data cm_t3517_ehci_pdata __initdata = {
+static struct usbhs_omap_platform_data cm_t3517_ehci_pdata __initdata = {
 	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
 	.port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
 	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
index 12865af..051ec0d 100644
--- a/arch/arm/mach-omap2/board-devkit8000.c
+++ b/arch/arm/mach-omap2/board-devkit8000.c
@@ -435,7 +435,7 @@ static struct platform_device *devkit8000_devices[] __initdata = {
 	&omap_dm9000_dev,
 };
 
-static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
+static struct usbhs_omap_platform_data usbhs_bdata __initdata = {
 
 	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
 	.port_mode[1] = OMAP_USBHS_PORT_MODE_UNUSED,
diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
index 0f24cb8..cfba790 100644
--- a/arch/arm/mach-omap2/board-igep0020.c
+++ b/arch/arm/mach-omap2/board-igep0020.c
@@ -526,7 +526,7 @@ static void __init igep_i2c_init(void)
 	omap3_pmic_init("twl4030", &igep_twldata);
 }
 
-static const struct usbhs_omap_board_data igep2_usbhs_bdata __initconst = {
+static struct usbhs_omap_platform_data igep2_usbhs_bdata __initdata = {
 	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
 	.port_mode[1] = OMAP_USBHS_PORT_MODE_UNUSED,
 	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
@@ -537,7 +537,7 @@ static const struct usbhs_omap_board_data igep2_usbhs_bdata __initconst = {
 	.reset_gpio_port[2] = -EINVAL,
 };
 
-static const struct usbhs_omap_board_data igep3_usbhs_bdata __initconst = {
+static struct usbhs_omap_platform_data igep3_usbhs_bdata __initdata = {
 	.port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED,
 	.port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
 	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 22c483d..1cb114e 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -430,7 +430,7 @@ static struct platform_device *omap3_beagle_devices[] __initdata = {
 	&madc_hwmon,
 };
 
-static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
+static struct usbhs_omap_platform_data usbhs_bdata __initdata = {
 
 	.port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED,
 	.port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index 3985f35..7bdc8a4 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -538,7 +538,7 @@ static int __init omap3_evm_i2c_init(void)
 	return 0;
 }
 
-static struct usbhs_omap_board_data usbhs_bdata __initdata = {
+static struct usbhs_omap_platform_data usbhs_bdata __initdata = {
 
 	.port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED,
 	.port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c
index a53a668..145a6f8 100644
--- a/arch/arm/mach-omap2/board-omap3pandora.c
+++ b/arch/arm/mach-omap2/board-omap3pandora.c
@@ -567,7 +567,7 @@ static struct platform_device *omap3pandora_devices[] __initdata = {
 	&pandora_backlight,
 };
 
-static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
+static struct usbhs_omap_platform_data usbhs_bdata __initdata = {
 
 	.port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED,
 	.port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c
index 53a6cbc..278ae95 100644
--- a/arch/arm/mach-omap2/board-omap3stalker.c
+++ b/arch/arm/mach-omap2/board-omap3stalker.c
@@ -361,7 +361,7 @@ static struct platform_device *omap3_stalker_devices[] __initdata = {
 	&keys_gpio,
 };
 
-static struct usbhs_omap_board_data usbhs_bdata __initconst = {
+static struct usbhs_omap_platform_data usbhs_bdata __initdata = {
 	.port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED,
 	.port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
 	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index 263cb9c..65a285f 100644
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -309,7 +309,7 @@ static struct platform_device *omap3_touchbook_devices[] __initdata = {
 	&keys_gpio,
 };
 
-static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
+static struct usbhs_omap_platform_data usbhs_bdata __initdata = {
 
 	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
 	.port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index 5c8e9ce..ee76830 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -139,7 +139,7 @@ static struct platform_device *panda_devices[] __initdata = {
 	&btwilink_device,
 };
 
-static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
+static struct usbhs_omap_platform_data usbhs_bdata __initdata = {
 	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
 	.port_mode[1] = OMAP_USBHS_PORT_MODE_UNUSED,
 	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index c8fde3e..b1b0f09 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -457,7 +457,7 @@ static int __init overo_spi_init(void)
 	return 0;
 }
 
-static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
+static struct usbhs_omap_platform_data usbhs_bdata __initdata = {
 	.port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED,
 	.port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
 	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
diff --git a/arch/arm/mach-omap2/board-zoom.c b/arch/arm/mach-omap2/board-zoom.c
index d7fa31e..2d7a457 100644
--- a/arch/arm/mach-omap2/board-zoom.c
+++ b/arch/arm/mach-omap2/board-zoom.c
@@ -92,7 +92,7 @@ static struct mtd_partition zoom_nand_partitions[] = {
 	},
 };
 
-static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
+static struct usbhs_omap_platform_data usbhs_bdata __initdata = {
 	.port_mode[0]		= OMAP_USBHS_PORT_MODE_UNUSED,
 	.port_mode[1]		= OMAP_EHCI_PORT_MODE_PHY,
 	.port_mode[2]		= OMAP_USBHS_PORT_MODE_UNUSED,
diff --git a/arch/arm/mach-omap2/usb-host.c b/arch/arm/mach-omap2/usb-host.c
index 2e44e8a..940aad4 100644
--- a/arch/arm/mach-omap2/usb-host.c
+++ b/arch/arm/mach-omap2/usb-host.c
@@ -37,11 +37,6 @@
 #define	USBHS_UHH_HWMODNAME	"usb_host_hs"
 #define USBHS_TLL_HWMODNAME	"usb_tll_hs"
 
-static struct usbhs_omap_platform_data		usbhs_data;
-static struct usbtll_omap_platform_data		usbtll_data;
-static struct ehci_hcd_omap_platform_data	ehci_data;
-static struct ohci_hcd_omap_platform_data	ohci_data;
-
 static struct omap_device_pm_latency omap_uhhtll_latency[] = {
 	  {
 		.deactivate_func = omap_device_idle_hwmods,
@@ -485,32 +480,18 @@ void __init setup_4430ohci_io_mux(const enum usbhs_omap_port_mode *port_mode)
 	}
 }
 
-void __init usbhs_init(const struct usbhs_omap_board_data *pdata)
+void __init usbhs_init(struct usbhs_omap_platform_data *pdata)
 {
 	struct omap_hwmod	*uhh_hwm, *tll_hwm;
 	struct platform_device	*pdev;
 	int			bus_id = -1;
-	int			i;
-
-	for (i = 0; i < OMAP3_HS_USB_PORTS; i++) {
-		usbhs_data.port_mode[i] = pdata->port_mode[i];
-		usbtll_data.port_mode[i] = pdata->port_mode[i];
-		ohci_data.port_mode[i] = pdata->port_mode[i];
-		ehci_data.port_mode[i] = pdata->port_mode[i];
-		ehci_data.reset_gpio_port[i] = pdata->reset_gpio_port[i];
-		ehci_data.regulator[i] = pdata->regulator[i];
-	}
-	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);
 		setup_ohci_io_mux(pdata->port_mode);
 
 		if (omap_rev() <= OMAP3430_REV_ES2_1)
-			usbhs_data.single_ulpi_bypass = true;
+			pdata->single_ulpi_bypass = true;
 
 	} else if (cpu_is_omap44xx()) {
 		setup_4430ehci_io_mux(pdata->port_mode);
@@ -530,7 +511,7 @@ void __init usbhs_init(const struct usbhs_omap_board_data *pdata)
 	}
 
 	pdev = omap_device_build(OMAP_USBTLL_DEVICE, bus_id, tll_hwm,
-				&usbtll_data, sizeof(usbtll_data),
+				pdata, sizeof(*pdata),
 				omap_uhhtll_latency,
 				ARRAY_SIZE(omap_uhhtll_latency), false);
 	if (IS_ERR(pdev)) {
@@ -540,7 +521,7 @@ void __init usbhs_init(const struct usbhs_omap_board_data *pdata)
 	}
 
 	pdev = omap_device_build(OMAP_USBHS_DEVICE, bus_id, uhh_hwm,
-				&usbhs_data, sizeof(usbhs_data),
+				pdata, sizeof(*pdata),
 				omap_uhhtll_latency,
 				ARRAY_SIZE(omap_uhhtll_latency), false);
 	if (IS_ERR(pdev)) {
@@ -552,7 +533,7 @@ void __init usbhs_init(const struct usbhs_omap_board_data *pdata)
 
 #else
 
-void __init usbhs_init(const struct usbhs_omap_board_data *pdata)
+void __init usbhs_init(struct usbhs_omap_platform_data *pdata)
 {
 }
 
diff --git a/arch/arm/mach-omap2/usb.h b/arch/arm/mach-omap2/usb.h
index 9b986ea..3319f5c 100644
--- a/arch/arm/mach-omap2/usb.h
+++ b/arch/arm/mach-omap2/usb.h
@@ -53,26 +53,8 @@
 #define USBPHY_OTGSESSEND_EN	(1 << 20)
 #define USBPHY_DATA_POLARITY	(1 << 23)
 
-struct usbhs_omap_board_data {
-	enum usbhs_omap_port_mode	port_mode[OMAP3_HS_USB_PORTS];
-
-	/* have to be valid if phy_reset is true and portx is in phy mode */
-	int	reset_gpio_port[OMAP3_HS_USB_PORTS];
-
-	/* Set this to true for ES2.x silicon */
-	unsigned			es2_compatibility:1;
-
-	unsigned			phy_reset:1;
-
-	/*
-	 * Regulators for USB PHYs.
-	 * Each PHY can have a separate regulator.
-	 */
-	struct regulator		*regulator[OMAP3_HS_USB_PORTS];
-};
-
 extern void usb_musb_init(struct omap_musb_board_data *board_data);
-extern void usbhs_init(const struct usbhs_omap_board_data *pdata);
+extern void usbhs_init(struct usbhs_omap_platform_data *pdata);
 
 extern void am35x_musb_reset(void);
 extern void am35x_musb_phy_power(u8 on);
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
index 05164d7..d6e6b8c 100644
--- a/drivers/mfd/omap-usb-host.c
+++ b/drivers/mfd/omap-usb-host.c
@@ -102,7 +102,7 @@ struct usbhs_hcd_omap {
 
 	void __iomem			*uhh_base;
 
-	struct usbhs_omap_platform_data	platdata;
+	struct usbhs_omap_platform_data	*pdata;
 
 	u32				usbhs_rev;
 	spinlock_t			lock;
@@ -184,19 +184,13 @@ err_end:
 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 usbhs_omap_platform_data		*pdata = dev->platform_data;
 	struct platform_device			*ehci;
 	struct platform_device			*ohci;
 	struct resource				*res;
 	struct resource				resources[2];
 	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) {
 		dev_err(dev, "EHCI get resource IORESOURCE_MEM failed\n");
@@ -213,8 +207,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, pdata,
+		sizeof(*pdata), dev);
 
 	if (!ehci) {
 		dev_err(dev, "omap_usbhs_alloc_child failed\n");
@@ -238,8 +232,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, pdata,
+		sizeof(*pdata), dev);
 	if (!ohci) {
 		dev_err(dev, "omap_usbhs_alloc_child failed\n");
 		ret = -ENOMEM;
@@ -278,7 +272,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 = omap->pdata;
 	unsigned long			flags;
 
 	dev_dbg(dev, "usbhs_runtime_resume\n");
@@ -310,7 +304,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 = omap->pdata;
 	unsigned long			flags;
 
 	dev_dbg(dev, "usbhs_runtime_suspend\n");
@@ -342,19 +336,19 @@ 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 = omap->pdata;
 	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 (pdata->phy_reset) {
+		if (gpio_is_valid(pdata->reset_gpio_port[0]))
+			gpio_request_one(pdata->reset_gpio_port[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_port[1]))
+			gpio_request_one(pdata->reset_gpio_port[1],
 					 GPIOF_OUT_INIT_LOW, "USB2 PHY reset");
 
 		/* Hold the PHY in RESET for enough time till DIR is high */
@@ -430,33 +424,33 @@ 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_port[0]))
 			gpio_set_value_cansleep
-				(pdata->ehci_data->reset_gpio_port[0], 1);
+				(pdata->reset_gpio_port[0], 1);
 
-		if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
+		if (gpio_is_valid(pdata->reset_gpio_port[1]))
 			gpio_set_value_cansleep
-				(pdata->ehci_data->reset_gpio_port[1], 1);
+				(pdata->reset_gpio_port[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 = omap->pdata;
 
-	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_port[0]))
+			gpio_free(pdata->reset_gpio_port[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_port[1]))
+			gpio_free(pdata->reset_gpio_port[1]);
 	}
 }
 
@@ -490,15 +484,10 @@ static int usbhs_omap_probe(struct platform_device *pdev)
 
 	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;
+	omap->pdata = pdata;
 
 	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)) {
diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c
index eb86915..e459489 100644
--- a/drivers/mfd/omap-usb-tll.c
+++ b/drivers/mfd/omap-usb-tll.c
@@ -98,7 +98,7 @@
 struct usbtll_omap {
 	struct clk				*usbtll_p1_fck;
 	struct clk				*usbtll_p2_fck;
-	struct usbtll_omap_platform_data	platdata;
+	struct usbhs_omap_platform_data		*pdata;
 	/* secure the register updates */
 	spinlock_t				lock;
 };
@@ -203,7 +203,7 @@ static unsigned ohci_omap3_fslsmode(enum usbhs_omap_port_mode mode)
 static int usbtll_omap_probe(struct platform_device *pdev)
 {
 	struct device				*dev =  &pdev->dev;
-	struct usbtll_omap_platform_data	*pdata = dev->platform_data;
+	struct usbhs_omap_platform_data		*pdata = dev->platform_data;
 	void __iomem				*base;
 	struct resource				*res;
 	struct usbtll_omap			*tll;
@@ -223,8 +223,7 @@ static int usbtll_omap_probe(struct platform_device *pdev)
 
 	spin_lock_init(&tll->lock);
 
-	for (i = 0; i < OMAP3_HS_USB_PORTS; i++)
-		tll->platdata.port_mode[i] = pdata->port_mode[i];
+	tll->pdata = pdata;
 
 	tll->usbtll_p1_fck = clk_get(dev, "usb_tll_hs_usb_ch0_clk");
 	if (IS_ERR(tll->usbtll_p1_fck)) {
@@ -362,7 +361,7 @@ static int usbtll_omap_remove(struct platform_device *pdev)
 static int usbtll_runtime_resume(struct device *dev)
 {
 	struct usbtll_omap			*tll = dev_get_drvdata(dev);
-	struct usbtll_omap_platform_data	*pdata = &tll->platdata;
+	struct usbhs_omap_platform_data		*pdata = tll->pdata;
 	unsigned long				flags;
 
 	dev_dbg(dev, "usbtll_runtime_resume\n");
@@ -388,7 +387,7 @@ static int usbtll_runtime_resume(struct device *dev)
 static int usbtll_runtime_suspend(struct device *dev)
 {
 	struct usbtll_omap			*tll = dev_get_drvdata(dev);
-	struct usbtll_omap_platform_data	*pdata = &tll->platdata;
+	struct usbhs_omap_platform_data		*pdata = tll->pdata;
 	unsigned long				flags;
 
 	dev_dbg(dev, "usbtll_runtime_suspend\n");
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index e9d9b09..b96a4bf 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -107,7 +107,7 @@ static int omap_ehci_init(struct usb_hcd *hcd)
 {
 	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
 	int			rc;
-	struct ehci_hcd_omap_platform_data	*pdata;
+	struct usbhs_omap_platform_data	*pdata;
 
 	pdata = hcd->self.controller->platform_data;
 
@@ -151,7 +151,7 @@ static int omap_ehci_init(struct usb_hcd *hcd)
 }
 
 static void disable_put_regulator(
-		struct ehci_hcd_omap_platform_data *pdata)
+		struct usbhs_omap_platform_data *pdata)
 {
 	int i;
 
@@ -176,7 +176,7 @@ static void disable_put_regulator(
 static int ehci_hcd_omap_probe(struct platform_device *pdev)
 {
 	struct device				*dev = &pdev->dev;
-	struct ehci_hcd_omap_platform_data	*pdata = dev->platform_data;
+	struct usbhs_omap_platform_data		*pdata = dev->platform_data;
 	struct resource				*res;
 	struct usb_hcd				*hcd;
 	void __iomem				*regs;
diff --git a/include/linux/platform_data/usb-omap.h b/include/linux/platform_data/usb-omap.h
index ef65b67..04c7537 100644
--- a/include/linux/platform_data/usb-omap.h
+++ b/include/linux/platform_data/usb-omap.h
@@ -38,30 +38,15 @@ enum usbhs_omap_port_mode {
 	OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM
 };
 
-struct usbtll_omap_platform_data {
-	enum usbhs_omap_port_mode		port_mode[OMAP3_HS_USB_PORTS];
-};
-
-struct ehci_hcd_omap_platform_data {
+struct usbhs_omap_platform_data {
 	enum usbhs_omap_port_mode	port_mode[OMAP3_HS_USB_PORTS];
 	int				reset_gpio_port[OMAP3_HS_USB_PORTS];
 	struct regulator		*regulator[OMAP3_HS_USB_PORTS];
-	unsigned			phy_reset:1;
-};
-
-struct ohci_hcd_omap_platform_data {
-	enum usbhs_omap_port_mode	port_mode[OMAP3_HS_USB_PORTS];
-	unsigned			es2_compatibility:1;
-};
-
-struct usbhs_omap_platform_data {
-	enum usbhs_omap_port_mode		port_mode[OMAP3_HS_USB_PORTS];
-
-	struct ehci_hcd_omap_platform_data	*ehci_data;
-	struct ohci_hcd_omap_platform_data	*ohci_data;
 
 	/* OMAP3 <= ES2.1 have a single ulpi bypass control bit */
-	unsigned				single_ulpi_bypass:1;
+	unsigned			single_ulpi_bypass:1;
+	unsigned			es2_compatibility:1;
+	unsigned			phy_reset:1;
 };
 
 /*-------------------------------------------------------------------------*/
-- 
1.7.4.1

^ permalink raw reply related

* [PATCH v9 01/20] USB: ehci-omap: Don't free gpios that we didn't request
From: Roger Quadros @ 2013-01-23 10:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1358937492-8129-1-git-send-email-rogerq@ti.com>

This driver does not request any gpios so don't free them.
Fixes L3 bus error on multiple modprobe/rmmod of ehci_hcd
with ehci-omap in use.

Without this patch, EHCI will break on repeated insmod/rmmod
of ehci_hcd for all OMAP2+ platforms that use EHCI and
set 'phy_reset = true' in usbhs_omap_board_data.
i.e.

board-3430sdp.c:	.phy_reset  = true,
board-3630sdp.c:	.phy_reset  = true,
board-am3517crane.c:	.phy_reset  = true,
board-am3517evm.c:	.phy_reset  = true,
board-cm-t3517.c:	.phy_reset  = true,
board-cm-t35.c:	.phy_reset  = true,
board-devkit8000.c:	.phy_reset  = true,
board-igep0020.c:	.phy_reset = true,
board-igep0020.c:	.phy_reset = true,
board-omap3beagle.c:	.phy_reset  = true,
board-omap3evm.c:	.phy_reset  = true,
board-omap3pandora.c:	.phy_reset  = true,
board-omap3stalker.c:	.phy_reset = true,
board-omap3touchbook.c:	.phy_reset  = true,
board-omap4panda.c:	.phy_reset  = false,
board-overo.c:	.phy_reset  = true,
board-zoom.c:	.phy_reset		= true,

CC: Alan Stern <stern@rowland.harvard.edu>
CC: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
CC: stable at vger.kernel.org

Signed-off-by: Roger Quadros <rogerq@ti.com>
Reviewed-by: Felipe Balbi <balbi@ti.com>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
---
 drivers/usb/host/ehci-omap.c |    8 --------
 1 files changed, 0 insertions(+), 8 deletions(-)

diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index ac17a7c..e9d9b09 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -288,7 +288,6 @@ static int ehci_hcd_omap_remove(struct platform_device *pdev)
 {
 	struct device *dev				= &pdev->dev;
 	struct usb_hcd *hcd				= dev_get_drvdata(dev);
-	struct ehci_hcd_omap_platform_data *pdata	= dev->platform_data;
 
 	usb_remove_hcd(hcd);
 	disable_put_regulator(dev->platform_data);
@@ -298,13 +297,6 @@ static int ehci_hcd_omap_remove(struct platform_device *pdev)
 	pm_runtime_put_sync(dev);
 	pm_runtime_disable(dev);
 
-	if (pdata->phy_reset) {
-		if (gpio_is_valid(pdata->reset_gpio_port[0]))
-			gpio_free(pdata->reset_gpio_port[0]);
-
-		if (gpio_is_valid(pdata->reset_gpio_port[1]))
-			gpio_free(pdata->reset_gpio_port[1]);
-	}
 	return 0;
 }
 
-- 
1.7.4.1

^ permalink raw reply related

* [PATCH v9 00/20] OMAP USB Host cleanup
From: Roger Quadros @ 2013-01-23 10:37 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Samuel,

I think this series is in a pretty good shape to pull now :). I've added
Reviewed-by and Acked-by tags. You can please pull from below.

NOTE: the first patch is a stable fix so Greg KH might want to pick it up for 3.8-rc.

The following changes since commit 7d1f9aeff1ee4a20b1aeb377dd0f579fe9647619:

  Linux 3.8-rc4 (2013-01-17 19:25:45 -0800)

are available in the git repository at:
  git://github.com/rogerq/linux.git linux-usbhost14-part

This patchset addresses the following

- Consolidate USB Host platform data.
- Avoid addressing clocks one by one by name and use a for loop + bunch
  of cleanups.
- Get number of channels/ports dynamically either from revision register
  or from platform data. Avoids getting clocks that are not present.
- Add OMAP5 and HSIC mode (Not tested).

v9:
- Addressed clock framework related comments from Russell King.
- Removed 2 clock data patches from the series as they will be taken care
  of by Paul Walmsey.

v8:
- Re-arranged patch "USB-ehci-omap-Don-t-free-gpios-that-we-didn-t-reques.patch"
  to be the first since it is a candidate for stable.
- Fixed issues raised by Felipe, i.e. indentation and use of switch ()

v7:
- Updated patch 4 to not hold a spinlock when using clk_get().
- Updated patches 3 and 11 to return -EADDRNOTAVAIL on failure of
  demv_request_and_ioremap().

v6:
- Added USB Host platform data consolidation patch as the first patch.
  based on request from Tony.
- Rebased on v3.8-rc3.

v5:
- Rebased on top of todays arm-soc/for-next.
- Removed the clock merging patch from the list.
- Updated patches 14, 19 and 20 to accomodate the above change.
- Added patch 22 to fix a build warning.

v4:
- Added appropriate maintainers in to/cc.
- minor print message fix in patch 23 to maintain consistency.

v3:
- Rebased on arm-soc/for-next commit f979306c4d38d213c6977aaf3b1115e8ded71e3a.
- Rearranged patch that get rids of cpu_is_omap..() macros.
- Coding style fixes.

v2:
- Clocks are allocated dynamically based on number of ports available
  on the platform.
- Reduced console spam if non critical clocks are not found on the platform.
- Get rid of cpu_is_.. macros from USB host driver.

cheers,
-roger

---
Roger Quadros (20):
      USB: ehci-omap: Don't free gpios that we didn't request
      mfd: omap-usb-host: Consolidate OMAP USB-HS platform data
      mfd: omap-usb-tll: Fix channel count detection
      mfd: omap-usb-tll: Use devm_kzalloc/ioremap and clean up error path
      mfd: omap-usb-tll: Clean up clock handling
      mfd: omap-usb-tll: introduce and use mode_needs_tll()
      mfd: omap-usb-tll: Check for missing platform data in probe
      mfd: omap-usb-tll: Fix error message
      mfd: omap-usb-tll: serialize access to TLL device
      mfd: omap-usb-tll: Add OMAP5 revision and HSIC support
      mfd: omap_usb_host: Avoid missing platform data checks in suspend/resume
      mfd: omap-usb-host: Use devm_kzalloc() and devm_request_and_ioremap()
      mfd: omap-usb-host: know about number of ports from revision register
      mfd: omap-usb-host: override number of ports from platform data
      mfd: omap-usb-host: cleanup clock management code
      mfd: omap-usb-host: Manage HSIC clocks for HSIC mode
      mfd: omap-usb-host: Get rid of unnecessary spinlock
      mfd: omap-usb-host: clean up omap_usbhs_init()
      mfd: omap-usb-host: Don't spam console on clk_set_parent failure
      mdf: omap-usb-host: get rid of build warning

 arch/arm/mach-omap2/board-3430sdp.c        |    2 +-
 arch/arm/mach-omap2/board-3630sdp.c        |    2 +-
 arch/arm/mach-omap2/board-am3517crane.c    |    2 +-
 arch/arm/mach-omap2/board-am3517evm.c      |    2 +-
 arch/arm/mach-omap2/board-cm-t35.c         |    2 +-
 arch/arm/mach-omap2/board-cm-t3517.c       |    2 +-
 arch/arm/mach-omap2/board-devkit8000.c     |    2 +-
 arch/arm/mach-omap2/board-igep0020.c       |    4 +-
 arch/arm/mach-omap2/board-omap3beagle.c    |    2 +-
 arch/arm/mach-omap2/board-omap3evm.c       |    2 +-
 arch/arm/mach-omap2/board-omap3pandora.c   |    2 +-
 arch/arm/mach-omap2/board-omap3stalker.c   |    2 +-
 arch/arm/mach-omap2/board-omap3touchbook.c |    2 +-
 arch/arm/mach-omap2/board-omap4panda.c     |    2 +-
 arch/arm/mach-omap2/board-overo.c          |    2 +-
 arch/arm/mach-omap2/board-zoom.c           |    2 +-
 arch/arm/mach-omap2/usb-host.c             |   29 +--
 arch/arm/mach-omap2/usb.h                  |   20 +-
 drivers/mfd/omap-usb-host.c                |  558 +++++++++++++++++-----------
 drivers/mfd/omap-usb-tll.c                 |  243 +++++++------
 drivers/usb/host/ehci-omap.c               |   14 +-
 include/linux/platform_data/usb-omap.h     |   24 +-
 22 files changed, 497 insertions(+), 425 deletions(-)

-- 
1.7.4.1

^ permalink raw reply

* [PATCH] ARM: dts: specify all the per-cpu interrupts of arch timer for exynos5440
From: Mark Rutland @ 2013-01-23 10:36 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <063f01cdf8ec$926cda30$b7468e90$@samsung.com>

On Tue, Jan 22, 2013 at 10:05:18PM +0000, Kukjin Kim wrote:
> Mark Rutland wrote:
> >
> + devicetree-discuss, Grant Likely, Rob Herring and Tony Lindgren
>  
> > On Tue, Jan 22, 2013 at 01:41:27AM +0000, Kukjin Kim wrote:
> > > From: Thomas Abraham <thomas.ab@samsung.com>
> > >
> > > Need to be changed requirements in the 'cpus' node for exynos5440
> > > to specify all the per-cpu interrupts of arch timer.
> > 
> > The node(s) for the arch timer should not be in the cpus/cpu at N nodes.
> > Instead, there should be one node (in the root of the tree).
> > 
> Well, I don't think so. As per my understanding, the local timers are
> attached to every ARM cores (cpus) and it generates certain interrupt to the
> GIC. So the correct representation for this in device tree is to include the
> interrupts in the cpu nodes in dts file. Your comments  refer to a
> limitation in the Linux kernel implementation of the arch_timer and it
> should not result in representing the hardware details incorrectly in the
> dts file.

I disagree. The "correct representation" is whatever the devicetree binding
documentation describes. It does not describe placing timer nodes in the cpu
nodes.

> 
> > If this works currently it's only because the driver picks up one of the
> nodes,
> > and luckily it's the same as the others. This is not guaranteed to work in
> > future, and will likely break.
> > 
> It is up to the Linux kernel implementation of arch_timer to handle the
> hardware details in dts file accordingly.

The binding specification does not specify that there should be multiple timer
nodes, nor does it specify that they should be under cpu nodes. The timers,
being a banked resource, can be described with one node.

It is not up to the Linux kernel to handle undocumented variations of bindings.

> 
> > >
> > > Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
> > > Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
> > > ---
> > >  arch/arm/boot/dts/exynos5440.dtsi |   20 ++++++++++++++++----
> > >  1 file changed, 16 insertions(+), 4 deletions(-)
> > >
> > > diff --git a/arch/arm/boot/dts/exynos5440.dtsi
> > b/arch/arm/boot/dts/exynos5440.dtsi
> > > index 5406689..c5bd8ed 100644
> > > --- a/arch/arm/boot/dts/exynos5440.dtsi
> > > +++ b/arch/arm/boot/dts/exynos5440.dtsi
> > > @@ -28,7 +28,10 @@
> > >  			compatible = "arm,cortex-a15";
> > >  			timer {
> > >  				compatible = "arm,armv7-timer";
> > > -				interrupts = <1 13 0xf08>;
> > > +				interrupts = <1 13 0xf08>,
> > > +					     <1 14 0xf08>,
> > > +					     <1 11 0xf08>,
> > > +					     <1 10 0xf08>;
> > 
> > Also, this interrupts list is updated differently to all the other nodes.
> Typo?
> > 
> Hmm, I think this should be fine. If any concerns, please let me know in
> detail.

Sorry, I misread the diff. Your patch in fact corrects them to be consistent
where they weren't previously.

> 
> [...]
> 
> Thanks.
> 
> - Kukjin
> 
> 

Thanks,
Mark.

^ permalink raw reply

* LPC32xx and MMCI driver
From: Gabriele Mondada @ 2013-01-23 10:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121222212457.GJ14363@n2100.arm.linux.org.uk>

> 
>> +#ifdef CONFIG_ARCH_LPC32XX
>> +/*
>> + * This exported function is used by mmci driver to workaround a bug in the
>> + * LPC32xx CPU.
>> + */
>> +void pl08x_force_dma_burst(struct dma_chan *chan)
>> +{
>> +    struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
>> +    struct pl08x_driver_data *pl08x = plchan->host;
>> +
>> +    dev_dbg(&pl08x->adev->dev,
>> +        "force burst signal=%d chan=%p plchan=%p\n",
>> +        plchan->signal, chan, plchan);
>> +    if (plchan->signal >= 0)
>> +        writel(1 << plchan->signal, pl08x->base + PL080_SOFT_BREQ);
>> +}
>> +
>> +EXPORT_SYMBOL_GPL(pl08x_force_dma_burst);
> 
> Eww.  This is really horrid and totally breaks software layering.

Yes, it is.
There is a silicon bug that prevents the DMA controller to receive the last DMA request. So, I have to generate the last transfer by software.
How can I do that without breaking software layers? Do I add a new entry point in the dmaengine device?

> As for formatting in the patch, that's also horrid.  Extra tab
> indentations, lines over 80 characters, and a hell of a lot of code
> to fix this brokenness.
> 
> At least the first thing that needs to happen is to clean the patch up
> so that it passes checkpatch.pl.

I cleaned up the patch and posted again on the list. See [PATCH] Implements DMA on mmci driver for LPC3250 plateform

^ permalink raw reply

* [PATCH] ARM: mach-ux500: enable 128KB way L2 cache on DB8540
From: Fabio Baltieri @ 2013-01-23 10:27 UTC (permalink / raw)
  To: linux-arm-kernel

From: Maxime Coquelin <maxime.coquelin@stericsson.com>

DB8540 L2 was configured with 64KB way size, but it has 128KB as AP9540.

Fix this by modifying ux500_l2x0_init() to use 128KB way size for all
cpus in the x540 family.

Signed-off-by: Maxime Coquelin <maxime.coquelin@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Fabio Baltieri <fabio.baltieri@linaro.org>
---
 arch/arm/mach-ux500/cache-l2x0.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-ux500/cache-l2x0.c b/arch/arm/mach-ux500/cache-l2x0.c
index 75d5b51..1682dfe 100644
--- a/arch/arm/mach-ux500/cache-l2x0.c
+++ b/arch/arm/mach-ux500/cache-l2x0.c
@@ -46,8 +46,8 @@ static int __init ux500_l2x0_init(void)
 	/* Unlock before init */
 	ux500_l2x0_unlock();
 
-	/* DB9540's L2 has 128KB way size */
-	if (cpu_is_u9540())
+	/* DBx540's L2 has 128KB way size */
+	if (cpu_is_ux540_family())
 		/* 128KB way size */
 		aux_val |= (0x4 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT);
 	else
-- 
1.7.12.1

^ permalink raw reply related

* [PATCH] clk: Add axi-clkgen driver
From: Russell King - ARM Linux @ 2013-01-23 10:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <50FFB4D8.5060801@metafoo.de>

On Wed, Jan 23, 2013 at 11:00:56AM +0100, Lars-Peter Clausen wrote:
> I think I read somewhere at some point that ioread{8,16,32} is preferred
> over write{b,h,l} in new code.

But... there's *no* point using ioread*() if you don't only use the
ioremap() interface.

ioread*() is there to allow PC IO and PC MMIO accesses through one
accessor depending on the cookie.  ioremap() only ever returns cookies
for MMIO accesses.

^ permalink raw reply

* [PATCH 7/9] ARM: at91/at91_dt_defconfig: remove memory specification to cmdline
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-01-23 10:20 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <2e06e92c758b768baaacc061aafa7f710b74ea02.1358934163.git.nicolas.ferre@atmel.com>

On 10:48 Wed 23 Jan     , Nicolas Ferre wrote:
> No need for this cmdline option as we are using DT.
> Moreover this defconfig is targeted to multiple SoC/boards: this option
> was nonsense.
just keep the console the rest is a nonsense too

as on 9g45 the initrd will be at 0x7xxxxxxx

the console too but as the patch serie to support via DT is not yet mainline
we can keep it

Best Regards,
J.
> 
> Reported-by: Josh Wu <josh.wu@atmel.com>
> Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
> ---
>  arch/arm/configs/at91_dt_defconfig | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/arm/configs/at91_dt_defconfig b/arch/arm/configs/at91_dt_defconfig
> index b175577..a353ff6 100644
> --- a/arch/arm/configs/at91_dt_defconfig
> +++ b/arch/arm/configs/at91_dt_defconfig
> @@ -31,7 +31,7 @@ CONFIG_ZBOOT_ROM_TEXT=0x0
>  CONFIG_ZBOOT_ROM_BSS=0x0
>  CONFIG_ARM_APPENDED_DTB=y
>  CONFIG_ARM_ATAG_DTB_COMPAT=y
> -CONFIG_CMDLINE="mem=128M console=ttyS0,115200 initrd=0x21100000,25165824 root=/dev/ram0 rw"
> +CONFIG_CMDLINE="console=ttyS0,115200 initrd=0x21100000,25165824 root=/dev/ram0 rw"
>  CONFIG_KEXEC=y
>  CONFIG_AUTO_ZRELADDR=y
>  # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
> -- 
> 1.8.0
> 

^ permalink raw reply

* OMAP baseline test results for v3.8-rc4
From: Mark Jackson @ 2013-01-23 10:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20130122182331.GO22517@atomide.com>

On 22/01/13 18:23, Tony Lindgren wrote:
> * Mark Jackson <mpfj-list@mimc.co.uk> [130122 05:46]:
>> On 22/01/13 13:32, Bedia, Vaibhav wrote:
>>
>> <snip>
>>
>>> Following works for me:
>>>
>>> Kernel
>>> ===
>>> git checkout next-20130122
>>> make distclean
>>> make omap2plus_defconfig
>>> <Enable the appended DTB related options via menuconfig>
>>> make -j7
>>> cat arch/arm/boot/zImage arch/arm/boot/dts/am335x-bone.dtb > arch/arm/boot/zImage-dtb.am335x-bone
>>> mkimage -A arm -O linux -C none -T kernel -a 0x80008000 -e 0x80008000 -n 'Linux' -d arch/arm/boot/zImage-dtb.am335x-bone arch/arm/boot/uImage-dtb.am335x-bone
>>>
>>> U-Boot
>>> ===
>>> Built from v2013.01
>>
>> <snip>
>>
>>> A dumb question... in your case what's the bootargs set? Note that the mainline
>>> kernel for AM335x doesn't have MMC support yet and the default bootargs is set to
>>> rootfs on MMC.
>>
>> Yes ... I'm trying to boot from a rootfs on MMC:-
>>
>> Kernel command line: console=ttyO0,115200n8 earlyprintk debug root=/dev/mmcblk0p2 ro rootfstype=ext2
>> rootwait
>>
>> But I should get *something* from the kernel before it starts trying to access the rootfs ?
> 
> Here's something Kevin fixed but did not send it out before going to
> a vacation. Can you give it a try with earlyprintk enabled?
> 
> Note that this does not help with no output early on, that sounds
> like a bug configuring the DEBUG_LL port somewhere.
> 
> Regards,
> 
> Tony
> 
> 
> 
> From: Kevin Hilman <khilman@deeprootsystems.com>
> Date: Tue, 15 Jan 2013 14:12:24 -0800
> Subject: [PATCH] Fix omap_serial as module with debug_ll and earlyprintk
> 
> Otherwise we can race with the earlyconsole getting turned off
> which can cause a non-booting system with earlyprintk enabled.
> 
> [tony at atomide.com: updated description]
> Signed-off-by: Tony Lindgren <tony@atomide.com>
> 
> ---
> 
> Kevin, can I add your Signed-off-by to this one?
> 
> --- a/arch/arm/mach-omap2/omap_device.c
> +++ b/arch/arm/mach-omap2/omap_device.c
> @@ -1298,4 +1298,4 @@ static int __init omap_device_late_init(void)
>  	bus_for_each_dev(&platform_bus_type, NULL, NULL, omap_device_late_idle);
>  	return 0;
>  }
> -omap_late_initcall(omap_device_late_init);
> +late_initcall_sync(omap_device_late_init);
> 

Sorry ... still no joy:-

U-Boot# askenv bootargs
Please enter 'bootargs':ttyO0,115200n8 earlyprintk root=/dev/mmcblk0p2 ro rootfstype=ext2 rootwait
U-Boot# dhcp 80000000 10.0.0.100:/nanobone/uImage-dtb;bootm 80000000
link up on port 0, speed 100, full duplex
BOOTP broadcast 1
*** Unhandled DHCP Option in OFFER/ACK: 44
*** Unhandled DHCP Option in OFFER/ACK: 46
*** Unhandled DHCP Option in OFFER/ACK: 44
*** Unhandled DHCP Option in OFFER/ACK: 46
DHCP client bound to address 10.0.0.112
Using cpsw device
TFTP from server 10.0.0.100; our IP address is 10.0.0.112
Filename '/nanobone/uImage-dtb'.
Load address: 0x80000000
Loading: #################################################################
         #################################################################
         #################################################################
         #################################################################
         ###########
         625 KiB/s
done
Bytes transferred = 3972199 (3c9c67 hex)
## Booting kernel from Legacy Image at 80000000 ...
   Image Name:   Linux 3.8.0-rc3-12154-gac00f0e-d
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    3972135 Bytes = 3.8 MiB
   Load Address: 80008000
   Entry Point:  80008000
   Verifying Checksum ... OK
   Loading Kernel Image ... OK
OK

Starting kernel ...

My .config can be found at http://pastebin.com/rj5ptt7W

Cheers
Mark J.

^ permalink raw reply

* [PATCH V2 2/2] mmc: mmci: Move ios_handler functionality into the driver
From: Russell King - ARM Linux @ 2013-01-23 10:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20130123101349.GH15873@gmail.com>

On Wed, Jan 23, 2013 at 10:13:49AM +0000, Lee Jones wrote:
> On Tue, 22 Jan 2013, Lee Jones wrote:
> > Are you saying that you won't do it? :)
> > 
> > Is there anything I can do to make the process easier?
> 
> Thinking about this a little more. Is it easier to remove it from your
> tree altogether? Only I have a small "ARM: ux500: " patch-set which
> directly relies on this patch. I could take it in via ARM-SoC without
> any fear of ordering issues.

Thankfully, the patch doesn't conflict with any of the others I have, so
we can do that (and it's actually easier to do that.)

Done.

^ permalink raw reply

* [PATCH 1/2] clocksource: dbx500-prcmu: use relaxed readl variant
From: Linus Walleij @ 2013-01-23 10:16 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20130121122203.GA30289@balto.lan>

On Mon, Jan 21, 2013 at 1:22 PM, Fabio Baltieri
<fabio.baltieri@linaro.org> wrote:
> On Mon, Jan 21, 2013 at 01:09:31PM +0100, Fabio Baltieri wrote:
>> From: Rabin Vincent <rabin.vincent@stericsson.com>
>>
>> Modify clksrc_dbx500_prcmu_read to replace readl() with readl_relaxed().
>> This speeds up calls to the function by about 40%.
>
> Hello John,
>
> these two patches may go in the existing ux500 clksrc branch
> together with the nomadik-mtu's patches queued up some time ago.
>
> Can I have your Acked-by for that?

Actually now when I look at it these changes are fully orthogonal
to the other stuff, so these two should just go in through John's
timer tree as usual.

John?

Yours,
Linus Walleij

^ permalink raw reply

* [PATCH V2 2/2] mmc: mmci: Move ios_handler functionality into the driver
From: Lee Jones @ 2013-01-23 10:13 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20130122105608.GP6857@gmail.com>

On Tue, 22 Jan 2013, Lee Jones wrote:

> On Tue, 22 Jan 2013, Russell King - ARM Linux wrote:
> 
> > On Tue, Jan 22, 2013 at 10:20:10AM +0000, Lee Jones wrote:
> > > On Tue, 22 Jan 2013, Russell King - ARM Linux wrote:
> > > 
> > > > On Tue, Jan 22, 2013 at 10:53:42AM +0100, Linus Walleij wrote:
> > > > > On Tue, Jan 22, 2013 at 10:00 AM, Lee Jones <lee.jones@linaro.org> wrote:
> > > > > 
> > > > > >> From: Lee Jones <lee.jones@linaro.org>
> > > > > >>
> > > > > >> There are currently two instances of the ios_handler being used.
> > > > > >> Both of which mearly toy with some regulator settings. Now there
> > > > > >> is a GPIO regulator API, we can use that instead, and lessen the
> > > > > >> per platform burden. By doing this, we also become more Device
> > > > > >> Tree compatible.
> > > > > >
> > > > > > Russell,
> > > > > >
> > > > > > Why is this patch in your tree with Ulf as the Author?
> > > > > 
> > > > > This is because of the way Russell's patch tracker works, it sets
> > > > > Author: to the name of the person using the patch tracker and
> > > > > discards the From: field in the beginning of the patch which
> > > > > git am will conversely respect.
> > > > 
> > > > Actually, the reverse.  It does now respect the From: line, but the
> > > > From: line will be ignored for all notifications about the patch
> > > > because the patch system was never built to parse the actual comments
> > > > when sending out the email notifications.
> > > 
> > > So what do I have to do to reaffirm myself as the author?
> > 
> > I'd need to recommit the patch with the right information, which isn't
> > that easy to do.
> 
> Are you saying that you won't do it? :)
> 
> Is there anything I can do to make the process easier?

Thinking about this a little more. Is it easier to remove it from your
tree altogether? Only I have a small "ARM: ux500: " patch-set which
directly relies on this patch. I could take it in via ARM-SoC without
any fear of ordering issues.

The alternative is for me to wait until this hits Mainline, or for you
to take in the remainder of the patch-set via your patch tracker. The
first option would be my preference.

-- 
Lee Jones
Linaro ST-Ericsson Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply

* [PATCH] Implements DMA on mmci driver for LPC3250 plateform
From: Gabriele Mondada @ 2013-01-23 10:11 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Gabriele Mondada <gabriele@precidata.com>

UPDATE: Here is the patch cleaned up and validated with scripts/checkpatch.pl. I also add a check to prevent crashing when DMA is disabled.

ORIGINAL POST:
Hi,
Currently, LPC32xx plateform do not enable DMA on the mmci driver. This makes the driver useless because getting out data from a 64 bytes FIFO by interrupt is not fast enough (at standard SD-card data rate).

DMA is not enabled because LPC32xx has a bug that prevent DMA to work properly with the MMC controller (silicon bug, I guess). NXP did a patch to workaround this, but it has not been commited on the main branch. The patch is for linux 2.6.39.2 and does not use dmaengine.

So, I reworked this patch to make it compatible with the last kernel (3.7). Here it is. Have I any chance to see this patch be commited on the main branch?

Thanks a lot,
Gabriele 

---
drivers/dma/amba-pl08x.c |   20 ++++++
drivers/mmc/host/mmci.c  |  159 +++++++++++++++++++++++++++++++++++++++++-----
drivers/mmc/host/mmci.h  |   12 +++-
3 files changed, 174 insertions(+), 17 deletions(-)

diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index d1cc579..728f65f 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -1758,6 +1758,26 @@ static void pl08x_free_virtual_channels(struct dma_device *dmadev)
	}
}

+#ifdef CONFIG_ARCH_LPC32XX
+/*
+ * This exported function is used by mmci driver to workaround a bug in the
+ * LPC32xx chip, where the last DMA request is missed and must be simulated by
+ * software.
+ */
+void pl08x_force_dma_burst(struct dma_chan *chan)
+{
+	struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
+	struct pl08x_driver_data *pl08x = plchan->host;
+
+	dev_dbg(&pl08x->adev->dev,
+		"force burst signal=%d chan=%p plchan=%p\n",
+		plchan->signal, chan, plchan);
+	if (plchan->signal >= 0)
+		writel(1 << plchan->signal, pl08x->base + PL080_SOFT_BREQ);
+}
+EXPORT_SYMBOL_GPL(pl08x_force_dma_burst);
+#endif
+
#ifdef CONFIG_DEBUG_FS
static const char *pl08x_state_str(enum pl08x_dma_chan_state state)
{
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 1507723..546445b 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -3,6 +3,7 @@
 *
 *  Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved.
 *  Copyright (C) 2010 ST-Ericsson SA
+ *  Copyright (C) 2012 Precidata Sarl, Gabriele Mondada
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
@@ -43,6 +44,16 @@

#define DRIVER_NAME "mmci-pl18x"

+#define COOKIE_PREP	0x00000001
+#define COOKIE_SINGLE	0x00000002
+#define COOKIE_ID_MASK	0xFF000000
+#define COOKIE_ID_SHIFT	24
+#define COOKIE_ID(n)	(COOKIE_ID_MASK & ((n) << COOKIE_ID_SHIFT))
+
+#ifdef CONFIG_ARCH_LPC32XX
+#define DMA_TX_SIZE SZ_64K
+#endif
+
static unsigned int fmax = 515633;

/**
@@ -133,6 +144,10 @@ static struct variant_data variant_ux500v2 = {
	.signal_direction	= true,
};

+#ifdef CONFIG_ARCH_LPC32XX
+void pl08x_force_dma_burst(struct dma_chan *chan);
+#endif
+
/*
 * This must be called with host->lock held
 */
@@ -267,14 +282,39 @@ static void mmci_dma_setup(struct mmci_host *host)
	struct mmci_platform_data *plat = host->plat;
	const char *rxname, *txname;
	dma_cap_mask_t mask;
+#ifdef CONFIG_ARCH_LPC32XX
+	int i;
+#endif

	if (!plat || !plat->dma_filter) {
		dev_info(mmc_dev(host->mmc), "no DMA platform data\n");
		return;
	}

-	/* initialize pre request cookie */
-	host->next_data.cookie = 1;
+#ifdef CONFIG_ARCH_LPC32XX
+	/*
+	 * The LPC32XX do not support sg on TX DMA. So
+	 * a temporary bouncing buffer is used if more than 1 sg segment
+	 * is passed in the data request. The bouncing buffer will get a
+	 * contiguous copy of the TX data and it will be used instead.
+	 */
+	for (i = 0; i < 2; i++) {
+		host->dma_v_tx[i] = dma_alloc_coherent(mmc_dev(host->mmc),
+			DMA_TX_SIZE, &host->dma_p_tx[i], GFP_KERNEL);
+		if (host->dma_v_tx[i] == NULL) {
+			dev_err(mmc_dev(host->mmc),
+				"error getting DMA region\n");
+			return;
+		}
+		dev_info(mmc_dev(host->mmc), "DMA buffer: phy:%p, virt:%p\n",
+			(void *)host->dma_p_tx[i], host->dma_v_tx[i]);
+	}
+
+	host->dma_v_tx_current = host->dma_v_tx[0];
+	host->dma_p_tx_current = host->dma_p_tx[0];
+	host->next_data.dma_v_tx = host->dma_v_tx[1];
+	host->next_data.dma_p_tx = host->dma_p_tx[1];
+#endif

	/* Try to acquire a generic DMA engine slave channel */
	dma_cap_zero(mask);
@@ -344,12 +384,26 @@ static void mmci_dma_setup(struct mmci_host *host)
static inline void mmci_dma_release(struct mmci_host *host)
{
	struct mmci_platform_data *plat = host->plat;
+#ifdef CONFIG_ARCH_LPC32XX
+	int i;
+#endif

	if (host->dma_rx_channel)
		dma_release_channel(host->dma_rx_channel);
	if (host->dma_tx_channel && plat->dma_tx_param)
		dma_release_channel(host->dma_tx_channel);
	host->dma_rx_channel = host->dma_tx_channel = NULL;
+
+#ifdef CONFIG_ARCH_LPC32XX
+	for (i = 0; i < 2; i++) {
+		if (host->dma_v_tx[i] == NULL)
+			continue;
+		dma_free_coherent(mmc_dev(host->mmc), DMA_TX_SIZE,
+			host->dma_v_tx[i], host->dma_p_tx[i]);
+		host->dma_v_tx[i] = NULL;
+		host->dma_p_tx[i] = 0;
+	}
+#endif
}

static void mmci_dma_unmap(struct mmci_host *host, struct mmc_data *data)
@@ -385,8 +439,9 @@ static void mmci_dma_unmap(struct mmci_host *host, struct mmc_data *data)
		dir = DMA_FROM_DEVICE;
	}

-	if (!data->host_cookie)
+	if (data->host_cookie && !(data->host_cookie & COOKIE_SINGLE))
		dma_unmap_sg(chan->device->dev, data->sg, data->sg_len, dir);
+	/* TODO: no data->host_cookie=0 here ? */

	/*
	 * Use of DMA with scatter-gather is impossible.
@@ -422,6 +477,7 @@ static int mmci_dma_prep_data(struct mmci_host *host, struct mmc_data *data,
	struct dma_async_tx_descriptor *desc;
	enum dma_data_direction buffer_dirn;
	int nr_sg;
+	bool single = false;

	/* Check if next job is already prepared */
	if (data->host_cookie && !next &&
@@ -441,6 +497,9 @@ static int mmci_dma_prep_data(struct mmci_host *host, struct mmc_data *data,
		conf.direction = DMA_MEM_TO_DEV;
		buffer_dirn = DMA_TO_DEVICE;
		chan = host->dma_tx_channel;
+#ifdef CONFIG_ARCH_LPC32XX
+		conf.device_fc = true;
+#endif
	}

	/* If there's no DMA channel, fall back to PIO */
@@ -452,13 +511,49 @@ static int mmci_dma_prep_data(struct mmci_host *host, struct mmc_data *data,
		return -EINVAL;

	device = chan->device;
-	nr_sg = dma_map_sg(device->dev, data->sg, data->sg_len, buffer_dirn);
-	if (nr_sg == 0)
-		return -EINVAL;
-
	dmaengine_slave_config(chan, &conf);
-	desc = dmaengine_prep_slave_sg(chan, data->sg, nr_sg,
-					    conf.direction, DMA_CTRL_ACK);
+
+#ifdef CONFIG_ARCH_LPC32XX
+	if ((data->flags & MMC_DATA_WRITE) && (data->sg_len > 1))
+		single = true;
+#endif
+
+	if (single) {
+		int i;
+		unsigned char *dst = next ? next->dma_v_tx
+					  : host->dma_v_tx_current;
+		size_t len = 0;
+
+		dev_dbg(mmc_dev(host->mmc), "use bounce buffer\n");
+		/* Move data to contiguous buffer first, then transfer it */
+		for (i = 0; i < data->sg_len; i++) {
+			unsigned long flags;
+			struct scatterlist *sg = &data->sg[i];
+			void *src;
+
+			/* Map the current scatter buffer, copy data, unmap */
+			local_irq_save(flags);
+			src = (unsigned char *)kmap_atomic(sg_page(sg)) +
+							   sg->offset;
+			memcpy(dst + len, src, sg->length);
+			len += sg->length;
+			kunmap_atomic(src);
+			local_irq_restore(flags);
+		}
+
+		desc = dmaengine_prep_slave_single(chan,
+			next ? next->dma_p_tx : host->dma_p_tx_current,
+			len, buffer_dirn, DMA_CTRL_ACK);
+	} else {
+		nr_sg = dma_map_sg(device->dev, data->sg, data->sg_len,
+				   buffer_dirn);
+		if (nr_sg == 0)
+			return -EINVAL;
+
+		desc = dmaengine_prep_slave_sg(chan, data->sg, nr_sg,
+					       conf.direction, DMA_CTRL_ACK);
+	}
+
	if (!desc)
		goto unmap_exit;

@@ -470,12 +565,20 @@ static int mmci_dma_prep_data(struct mmci_host *host, struct mmc_data *data,
		host->dma_desc_current = desc;
	}

+	data->host_cookie = COOKIE_PREP;
+	if (single)
+		data->host_cookie |= COOKIE_SINGLE;
+	if (next)
+		data->host_cookie |= COOKIE_ID(++next->cookie_cnt);
+
	return 0;

 unmap_exit:
	if (!next)
		dmaengine_terminate_all(chan);
-	dma_unmap_sg(device->dev, data->sg, data->sg_len, buffer_dirn);
+	if (!single)
+		dma_unmap_sg(device->dev, data->sg, data->sg_len, buffer_dirn);
+	data->host_cookie = 0;
	return -ENOMEM;
}

@@ -513,11 +616,16 @@ static int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl)
static void mmci_get_next_data(struct mmci_host *host, struct mmc_data *data)
{
	struct mmci_host_next *next = &host->next_data;
+#ifdef CONFIG_ARCH_LPC32XX
+	void *tmp_v;
+	dma_addr_t tmp_p;
+#endif

-	if (data->host_cookie && data->host_cookie != next->cookie) {
-		pr_warning("[%s] invalid cookie: data->host_cookie %d"
-		       " host->next_data.cookie %d\n",
-		       __func__, data->host_cookie, host->next_data.cookie);
+	if (data->host_cookie && ((data->host_cookie & COOKIE_ID_MASK) !=
+					COOKIE_ID(next->cookie_cnt))) {
+		pr_warn("[%s] invalid cookie: data->host_cookie=0x%08x host->next_data.cookie_cnt=0x%08x\n",
+			__func__, data->host_cookie,
+			host->next_data.cookie_cnt);
		data->host_cookie = 0;
	}

@@ -529,6 +637,15 @@ static void mmci_get_next_data(struct mmci_host *host, struct mmc_data *data)

	next->dma_desc = NULL;
	next->dma_chan = NULL;
+
+#ifdef CONFIG_ARCH_LPC32XX
+	tmp_v = host->next_data.dma_v_tx;
+	host->next_data.dma_v_tx = host->dma_v_tx_current;
+	host->dma_v_tx_current = tmp_v;
+	tmp_p = host->next_data.dma_p_tx;
+	host->next_data.dma_p_tx = host->dma_p_tx_current;
+	host->dma_p_tx_current = tmp_p;
+#endif
}

static void mmci_pre_request(struct mmc_host *mmc, struct mmc_request *mrq,
@@ -552,7 +669,8 @@ static void mmci_pre_request(struct mmc_host *mmc, struct mmc_request *mrq,
		if (mmci_dma_prep_data(host, data, nd))
			data->host_cookie = 0;
		else
-			data->host_cookie = ++nd->cookie < 0 ? 1 : nd->cookie;
+			data->host_cookie = COOKIE_ID(++nd->cookie_cnt) |
+					    COOKIE_PREP;
	}
}

@@ -580,7 +698,7 @@ static void mmci_post_request(struct mmc_host *mmc, struct mmc_request *mrq,
	if (chan) {
		if (err)
			dmaengine_terminate_all(chan);
-		if (data->host_cookie)
+		if (data->host_cookie && !(data->host_cookie & COOKIE_SINGLE))
			dma_unmap_sg(mmc_dev(host->mmc), data->sg,
				     data->sg_len, dir);
		mrq->data->host_cookie = 0;
@@ -790,6 +908,15 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
		dev_err(mmc_dev(host->mmc), "stray MCI_DATABLOCKEND interrupt\n");

	if (status & MCI_DATAEND || data->error) {
+#ifdef CONFIG_ARCH_LPC32XX
+		/*
+		 * On LPC32XX, there is a problem with the DMA flow control and
+		 * the last burst transfer is not performed. So we force the
+		 * transfer programmatically here.
+		 */
+		if ((data->flags & MMC_DATA_READ) && host->dma_rx_channel)
+			pl08x_force_dma_burst(host->dma_rx_channel);
+#endif
		if (dma_inprogress(host))
			mmci_dma_unmap(host, data);
		mmci_stop_data(host);
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index d34d8c0..f2a781b 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -159,7 +159,11 @@ struct dma_chan;
struct mmci_host_next {
	struct dma_async_tx_descriptor	*dma_desc;
	struct dma_chan			*dma_chan;
-	s32				cookie;
+	s32				cookie_cnt;
+#ifdef CONFIG_ARCH_LPC32XX
+	void				*dma_v_tx;
+	dma_addr_t			dma_p_tx;
+#endif
};

struct mmci_host {
@@ -206,6 +210,12 @@ struct mmci_host {
	struct dma_chan		*dma_tx_channel;
	struct dma_async_tx_descriptor	*dma_desc_current;
	struct mmci_host_next	next_data;
+#ifdef CONFIG_ARCH_LPC32XX
+	void			*dma_v_tx[2];
+	dma_addr_t		dma_p_tx[2];
+	void			*dma_v_tx_current;
+	dma_addr_t		dma_p_tx_current;
+#endif

#define dma_inprogress(host)	((host)->dma_current)
#else
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH 8/8] ARM: ux500: Remove traces of the ios_handler from platform code
From: Linus Walleij @ 2013-01-23 10:07 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CACRpkdbwQAEQxWpXHoEieou5rShcZvsGSddKLaOjwGeG-2o=wg@mail.gmail.com>

On Wed, Jan 23, 2013 at 11:04 AM, Linus Walleij
<linus.walleij@linaro.org> wrote:
> On Thu, Dec 13, 2012 at 2:22 PM, Lee Jones <lee.jones@linaro.org> wrote:
>
>> Now MMCI on/off functionality is using the regulator framework
>> from the MMCI driver, there is no need to keep the ios_handler
>> laying around, duplicating functionality. So we're removing it.
>>
>> Acked-by: Linus Walleij <linus.walleij@linaro.org>
>> Signed-off-by: Lee Jones <lee.jones@linaro.org>
>
> Applied to my ux500-cleanups branch.

Or no, wait, that is dependent or Russell's tree so will not
be bisectable.

Either submit sequel patches to [1/8] through Russell's
patch tracker (based on his tree I guess) or wait for these
to hit mainline and push them after that.

Acked-by anway, on all of the cleanups following [1/8].

Yours,
Linus Walleij

^ permalink raw reply

* [PATCH 8/8] ARM: ux500: Remove traces of the ios_handler from platform code
From: Linus Walleij @ 2013-01-23 10:04 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1355404930-5691-9-git-send-email-lee.jones@linaro.org>

On Thu, Dec 13, 2012 at 2:22 PM, Lee Jones <lee.jones@linaro.org> wrote:

> Now MMCI on/off functionality is using the regulator framework
> from the MMCI driver, there is no need to keep the ios_handler
> laying around, duplicating functionality. So we're removing it.
>
> Acked-by: Linus Walleij <linus.walleij@linaro.org>
> Signed-off-by: Lee Jones <lee.jones@linaro.org>

Applied to my ux500-cleanups branch.

Yours,
Linus Walleij

^ permalink raw reply

* [PATCH 1/1] ARM: ux500: Turn on the 'heartbeat' LED trigger
From: Linus Walleij @ 2013-01-23 10:01 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1358775340-8197-1-git-send-email-lee.jones@linaro.org>

On Mon, Jan 21, 2013 at 2:35 PM, Lee Jones <lee.jones@linaro.org> wrote:

> The heartbeat LED trigger provides an excellent debugging tool
> when hacking on development boards. Here we enable it on all
> u8500 based platforms. This will pulse the User LED on the
> Snowball low-cost development board only.
>
> Signed-off-by: Lee Jones <lee.jones@linaro.org>

Applied to my ux500-defconfig branch.

Thanks,
Linus Walleij

^ permalink raw reply

* [PATCH] clk: Add axi-clkgen driver
From: Lars-Peter Clausen @ 2013-01-23 10:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20130122175552.24671.27893@quantum>

On 01/22/2013 06:55 PM, Mike Turquette wrote:
> Quoting Lars-Peter Clausen (2013-01-09 10:12:00)
> <snip>
>> +static void axi_clkgen_write(struct axi_clkgen *axi_clkgen,
>> +       unsigned int reg, unsigned int val)
>> +{
>> +       iowrite32(val, axi_clkgen->base + reg);
> 
> Silly question: any reason to use this over readl()?  This is more for
> my understanding than a real criticism.

I think I read somewhere at some point that ioread{8,16,32} is preferred
over write{b,h,l} in new code.

> 
>> +}
>> +
>> +static void axi_clkgen_read(struct axi_clkgen *axi_clkgen,
>> +       unsigned int reg, unsigned int *val)
>> +{
>> +       *val = ioread32(axi_clkgen->base + reg);
> 
> Same as above, any reason to use this over writel?

Same answer.

> 
> <snip>
>> +static unsigned long axi_clkgen_recalc_rate(struct clk_hw *clk_hw,
>> +       unsigned long parent_rate)
>> +{
>> +       struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw);
>> +       unsigned int d, m, dout;
>> +       unsigned int reg;
>> +
>> +       axi_clkgen_read(axi_clkgen, AXI_CLKGEN_REG_CLK_OUT1, &reg);
>> +       dout = (reg & 0x3f) + ((reg >> 6) & 0x3f);
>> +       axi_clkgen_read(axi_clkgen, AXI_CLKGEN_REG_CLK_DIV, &reg);
>> +       d = (reg & 0x3f) + ((reg >> 6) & 0x3f);
>> +       axi_clkgen_read(axi_clkgen, AXI_CLKGEN_REG_CLK_FB1, &reg);
>> +       m = (reg & 0x3f) + ((reg >> 6) & 0x3f);
>> +
>> +       if (d == 0 || dout == 0)
>> +               return 0;
>> +
>> +       return parent_rate / d * m / dout;
> 
> Any chance of overflow here?  Maybe do_div should be used?

Not if all the parameters are within spec. But since this is on a slowpath I
guess it does not hurt to use do_div.

Will send a v2.

Thanks for the review,
- Lars

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox