linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/6] Fix issues around twl4030-gpio used as a module
@ 2012-02-24  9:58 Rajendra Nayak
  2012-02-24  9:58 ` [PATCH 1/6] ARM: OMAP: omap_device: Add omap_device_unregister() Rajendra Nayak
                   ` (5 more replies)
  0 siblings, 6 replies; 12+ messages in thread
From: Rajendra Nayak @ 2012-02-24  9:58 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Tony,

This series is based on top of 'hsmmc' branch in linux-omap
on top of commit '0e91c8ddf0e0932da59ec1d116e34049791b0e73' as
requested by you.

This mainly splits omap_hsmmc_late_init() into omap_hsmmc_deferred_add()
and omap_hsmmc_deferred_del() and adds .teardown hooks in all omap3 boards
to handle issues around multiple twl4030-gpio module insmod/unbind/bind
as reported by Russell.

In the process this series adds an api to unregister an
omap_device, makes mmc driver work with hotpluggable devices
and also removes 'deferred' flag for a few mmc devices on some
boards which are not really dependent on twl4030-gpio for card
detect as reported by Igor.

I have tested this series on omap3 beagle, with twl4030-gpio built
in, as well as twl4030-gpio built as a module and by doing multiple
insmod/unbind/bind sequence. I have tested card-detect to work fine
on beagle too.

regards,
Rajendra

Rajendra Nayak (6):
  ARM: OMAP: omap_device: Add omap_device_unregister()
  mmc: omap_hsmmc: Make the driver support hotpluggable devices
  mmc: omap_hsmmc: If probe fails, give our error messages
  ARM: OMAP3: Make only mmc devices using gpio_cd as deferred
  ARM: OMAP3: Modify omap_hsmmc_late_init to handle deleting mmc
    devices
  ARM: OMAP3: Use .teardown of twl4030-gpio to clean board requests

 arch/arm/mach-omap2/board-3430sdp.c           |   15 ++++-
 arch/arm/mach-omap2/board-cm-t35.c            |   15 ++++-
 arch/arm/mach-omap2/board-devkit8000.c        |   15 ++++-
 arch/arm/mach-omap2/board-igep0020.c          |   18 ++++-
 arch/arm/mach-omap2/board-ldp.c               |   13 ++++
 arch/arm/mach-omap2/board-omap3beagle.c       |   17 ++++-
 arch/arm/mach-omap2/board-omap3evm.c          |   16 ++++-
 arch/arm/mach-omap2/board-omap3pandora.c      |   14 +++-
 arch/arm/mach-omap2/board-omap3stalker.c      |   16 ++++-
 arch/arm/mach-omap2/board-omap3touchbook.c    |   15 ++++-
 arch/arm/mach-omap2/board-overo.c             |   11 +++-
 arch/arm/mach-omap2/board-rx51-peripherals.c  |   11 +++
 arch/arm/mach-omap2/board-zoom-peripherals.c  |   14 +++-
 arch/arm/mach-omap2/hsmmc.c                   |   93 ++++++++++++-------------
 arch/arm/mach-omap2/hsmmc.h                   |    9 ++-
 arch/arm/plat-omap/include/plat/omap_device.h |    1 +
 arch/arm/plat-omap/omap_device.c              |   20 +++++-
 drivers/mmc/host/omap_hsmmc.c                 |   11 ++--
 18 files changed, 249 insertions(+), 75 deletions(-)

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 1/6] ARM: OMAP: omap_device: Add omap_device_unregister()
  2012-02-24  9:58 [PATCH 0/6] Fix issues around twl4030-gpio used as a module Rajendra Nayak
@ 2012-02-24  9:58 ` Rajendra Nayak
  2012-02-24  9:58 ` [PATCH 2/6] mmc: omap_hsmmc: Make the driver support hotpluggable devices Rajendra Nayak
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 12+ messages in thread
From: Rajendra Nayak @ 2012-02-24  9:58 UTC (permalink / raw)
  To: linux-arm-kernel

Add support to unregister an omap_device using
omap_device_unregister api.

While here, also fix the kerneldoc comments for
omap_device_register.

Signed-off-by: Rajendra Nayak <rnayak@ti.com>
Cc: Kevin Hilman <khilman@ti.com>
---
 arch/arm/plat-omap/include/plat/omap_device.h |    1 +
 arch/arm/plat-omap/omap_device.c              |   20 ++++++++++++++++++--
 2 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/arch/arm/plat-omap/include/plat/omap_device.h b/arch/arm/plat-omap/include/plat/omap_device.h
index 05f7615..ce0dc86 100644
--- a/arch/arm/plat-omap/include/plat/omap_device.h
+++ b/arch/arm/plat-omap/include/plat/omap_device.h
@@ -106,6 +106,7 @@ struct omap_device *omap_device_alloc(struct platform_device *pdev,
 				      int pm_lats_cnt);
 void omap_device_delete(struct omap_device *od);
 int omap_device_register(struct platform_device *pdev);
+void omap_device_unregister(struct platform_device *pdev);
 
 void __iomem *omap_device_get_rt_va(struct omap_device *od);
 struct device *omap_device_get_by_hwmod_name(const char *oh_name);
diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
index 2d00ab0..27aa02d 100644
--- a/arch/arm/plat-omap/omap_device.c
+++ b/arch/arm/plat-omap/omap_device.c
@@ -808,8 +808,8 @@ static struct dev_pm_domain omap_device_pm_domain = {
  * @od: struct omap_device * to register
  *
  * Register the omap_device structure.  This currently just calls
- * platform_device_register() on the underlying platform_device.
- * Returns the return value of platform_device_register().
+ * platform_device_add() on the underlying platform_device.
+ * Returns the return value of platform_device_add().
  */
 int omap_device_register(struct platform_device *pdev)
 {
@@ -820,6 +820,22 @@ int omap_device_register(struct platform_device *pdev)
 	return platform_device_add(pdev);
 }
 
+/**
+ * omap_device_unregister - unregister an omap_device with one omap_hwmod
+ * @od: struct omap_device * to unregister
+ *
+ * Unregister the omap_device structure.  This currently just calls
+ * platform_device_del() on the underlying platform_device.
+ * No return value.
+ */
+void omap_device_unregister(struct platform_device *pdev)
+{
+	pr_debug("omap_device: %s: unregistering\n", pdev->name);
+
+	pdev->dev.parent = &omap_device_parent;
+	pdev->dev.pm_domain = &omap_device_pm_domain;
+	platform_device_del(pdev);
+}
 
 /* Public functions for use by device drivers through struct platform_data */
 
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 2/6] mmc: omap_hsmmc: Make the driver support hotpluggable devices
  2012-02-24  9:58 [PATCH 0/6] Fix issues around twl4030-gpio used as a module Rajendra Nayak
  2012-02-24  9:58 ` [PATCH 1/6] ARM: OMAP: omap_device: Add omap_device_unregister() Rajendra Nayak
@ 2012-02-24  9:58 ` Rajendra Nayak
  2012-02-24  9:58 ` [PATCH 3/6] mmc: omap_hsmmc: If probe fails, give out error messages Rajendra Nayak
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 12+ messages in thread
From: Rajendra Nayak @ 2012-02-24  9:58 UTC (permalink / raw)
  To: linux-arm-kernel

Make the hsmmc driver register the driver using platform_driver_register()
so it can support hotpluggable devices.

This is needed, for instance, in case of OMAP3, wherein some of the mmc
devices might get added and removed dynamically based on dependent modules
like twl4030-gpio.

Signed-off-by: Rajendra Nayak <rnayak@ti.com>
Cc: Chris Ball <cjb@laptop.org>
Cc: <linux-mmc@vger.kernel.org>
---
 drivers/mmc/host/omap_hsmmc.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index fd0c661..21b8afa 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -1847,7 +1847,7 @@ static void omap_hsmmc_debugfs(struct mmc_host *mmc)
 
 #endif
 
-static int __init omap_hsmmc_probe(struct platform_device *pdev)
+static int omap_hsmmc_probe(struct platform_device *pdev)
 {
 	struct omap_mmc_platform_data *pdata = pdev->dev.platform_data;
 	struct mmc_host *mmc;
@@ -2264,6 +2264,7 @@ static struct dev_pm_ops omap_hsmmc_dev_pm_ops = {
 };
 
 static struct platform_driver omap_hsmmc_driver = {
+	.probe		= omap_hsmmc_probe,
 	.remove		= omap_hsmmc_remove,
 	.driver		= {
 		.name = DRIVER_NAME,
@@ -2275,7 +2276,7 @@ static struct platform_driver omap_hsmmc_driver = {
 static int __init omap_hsmmc_init(void)
 {
 	/* Register the MMC driver */
-	return platform_driver_probe(&omap_hsmmc_driver, omap_hsmmc_probe);
+	return platform_driver_register(&omap_hsmmc_driver);
 }
 
 static void __exit omap_hsmmc_cleanup(void)
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 3/6] mmc: omap_hsmmc: If probe fails, give out error messages
  2012-02-24  9:58 [PATCH 0/6] Fix issues around twl4030-gpio used as a module Rajendra Nayak
  2012-02-24  9:58 ` [PATCH 1/6] ARM: OMAP: omap_device: Add omap_device_unregister() Rajendra Nayak
  2012-02-24  9:58 ` [PATCH 2/6] mmc: omap_hsmmc: Make the driver support hotpluggable devices Rajendra Nayak
@ 2012-02-24  9:58 ` Rajendra Nayak
  2012-02-24  9:58 ` [PATCH 4/6] ARM: OMAP3: Mark only those mmc devices which use gpio_cd, as deferred Rajendra Nayak
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 12+ messages in thread
From: Rajendra Nayak @ 2012-02-24  9:58 UTC (permalink / raw)
  To: linux-arm-kernel

Giving out debug messages even in case of probe failure seems
not very useful. Make them error messages instead.

Signed-off-by: Rajendra Nayak <rnayak@ti.com>
Cc: Chris Ball <cjb@laptop.org>
Cc: <linux-mmc@vger.kernel.org>
---
 drivers/mmc/host/omap_hsmmc.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 21b8afa..653ffee 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -2008,13 +2008,13 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
 	ret = request_irq(host->irq, omap_hsmmc_irq, 0,
 			mmc_hostname(mmc), host);
 	if (ret) {
-		dev_dbg(mmc_dev(host->mmc), "Unable to grab HSMMC IRQ\n");
+		dev_err(mmc_dev(host->mmc), "Unable to grab HSMMC IRQ\n");
 		goto err_irq;
 	}
 
 	if (pdata->init != NULL) {
 		if (pdata->init(&pdev->dev) != 0) {
-			dev_dbg(mmc_dev(host->mmc),
+			dev_err(mmc_dev(host->mmc),
 				"Unable to configure MMC IRQs\n");
 			goto err_irq_cd_init;
 		}
@@ -2037,7 +2037,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
 					   IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
 					   mmc_hostname(mmc), host);
 		if (ret) {
-			dev_dbg(mmc_dev(host->mmc),
+			dev_err(mmc_dev(host->mmc),
 				"Unable to grab MMC CD IRQ\n");
 			goto err_irq_cd;
 		}
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 4/6] ARM: OMAP3: Mark only those mmc devices which use gpio_cd, as deferred
  2012-02-24  9:58 [PATCH 0/6] Fix issues around twl4030-gpio used as a module Rajendra Nayak
                   ` (2 preceding siblings ...)
  2012-02-24  9:58 ` [PATCH 3/6] mmc: omap_hsmmc: If probe fails, give out error messages Rajendra Nayak
@ 2012-02-24  9:58 ` Rajendra Nayak
  2012-02-24 22:21   ` Tony Lindgren
  2012-02-24  9:58 ` [PATCH 5/6] ARM: OMAP3: Modify omap_hsmmc_late_init to handle deleting mmc devices Rajendra Nayak
  2012-02-24  9:58 ` [PATCH 6/6] ARM: OMAP3: Use .teardown of twl4030-gpio to clean board requests Rajendra Nayak
  5 siblings, 1 reply; 12+ messages in thread
From: Rajendra Nayak @ 2012-02-24  9:58 UTC (permalink / raw)
  To: linux-arm-kernel

mmc devices which actually do not depend on twl4030-gpio for
gpio_cd should not be maked as deferred.

Also on overo, since none of the mmc devices need to be deferred,
get rid of omap_hsmmc_late_init() altogether.

Reported-by: Igor Grinberg <grinberg@compulab.co.il>
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
---
 arch/arm/mach-omap2/board-cm-t35.c           |    1 -
 arch/arm/mach-omap2/board-igep0020.c         |    1 -
 arch/arm/mach-omap2/board-omap3evm.c         |    1 -
 arch/arm/mach-omap2/board-omap3pandora.c     |    1 -
 arch/arm/mach-omap2/board-overo.c            |    4 ----
 arch/arm/mach-omap2/board-zoom-peripherals.c |    2 --
 6 files changed, 0 insertions(+), 10 deletions(-)

diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index 8eaed63..49e6405 100644
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -422,7 +422,6 @@ static struct omap2_hsmmc_info mmc[] = {
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
 		.ocr_mask	= 0x00100000,	/* 3.3V */
-		.deferred	= true,
 	},
 	{}	/* Terminator */
 };
diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
index ac1de09..e558800 100644
--- a/arch/arm/mach-omap2/board-igep0020.c
+++ b/arch/arm/mach-omap2/board-igep0020.c
@@ -303,7 +303,6 @@ static struct omap2_hsmmc_info mmc[] = {
 		.caps		= MMC_CAP_4_BIT_DATA,
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
-		.deferred	= true,
 	},
 #endif
 	{}      /* Terminator */
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index 0f9a983..6b77ad9 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -327,7 +327,6 @@ static struct omap2_hsmmc_info mmc[] = {
 		.gpio_wp	= -EINVAL,
 		.gpio_cd	= -EINVAL,
 		.nonremovable	= true,
-		.deferred	= true,
 	},
 #endif
 	{}	/* Terminator */
diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c
index 84c83c8..ace466b 100644
--- a/arch/arm/mach-omap2/board-omap3pandora.c
+++ b/arch/arm/mach-omap2/board-omap3pandora.c
@@ -290,7 +290,6 @@ static struct omap2_hsmmc_info omap3pandora_mmc[] = {
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
 		.init_card	= pandora_wl1251_init_card,
-		.deferred	= true,
 	},
 	{}	/* Terminator */
 };
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index 1fc5f7a..668533e 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -301,7 +301,6 @@ static struct omap2_hsmmc_info mmc[] = {
 		.caps		= MMC_CAP_4_BIT_DATA,
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
-		.deferred	= true,
 	},
 	{
 		.mmc		= 2,
@@ -310,7 +309,6 @@ static struct omap2_hsmmc_info mmc[] = {
 		.gpio_wp	= -EINVAL,
 		.transceiver	= true,
 		.ocr_mask	= 0x00100000,	/* 3.3V */
-		.deferred	= true,
 	},
 	{}	/* Terminator */
 };
@@ -409,8 +407,6 @@ static inline void __init overo_init_keys(void) { return; }
 static int overo_twl_gpio_setup(struct device *dev,
 		unsigned gpio, unsigned ngpio)
 {
-	omap_hsmmc_late_init(mmc);
-
 #if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
 	/* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
 	gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c
index 82a0f7c..3d39cdb 100644
--- a/arch/arm/mach-omap2/board-zoom-peripherals.c
+++ b/arch/arm/mach-omap2/board-zoom-peripherals.c
@@ -215,7 +215,6 @@ static struct omap2_hsmmc_info mmc[] = {
 		.gpio_wp	= -EINVAL,
 		.nonremovable	= true,
 		.power_saving	= true,
-		.deferred	= true,
 	},
 	{
 		.name		= "wl1271",
@@ -224,7 +223,6 @@ static struct omap2_hsmmc_info mmc[] = {
 		.gpio_wp	= -EINVAL,
 		.gpio_cd	= -EINVAL,
 		.nonremovable	= true,
-		.deferred	= true,
 	},
 	{}      /* Terminator */
 };
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 5/6] ARM: OMAP3: Modify omap_hsmmc_late_init to handle deleting mmc devices
  2012-02-24  9:58 [PATCH 0/6] Fix issues around twl4030-gpio used as a module Rajendra Nayak
                   ` (3 preceding siblings ...)
  2012-02-24  9:58 ` [PATCH 4/6] ARM: OMAP3: Mark only those mmc devices which use gpio_cd, as deferred Rajendra Nayak
@ 2012-02-24  9:58 ` Rajendra Nayak
  2012-02-25  0:33   ` Tony Lindgren
  2012-02-24  9:58 ` [PATCH 6/6] ARM: OMAP3: Use .teardown of twl4030-gpio to clean board requests Rajendra Nayak
  5 siblings, 1 reply; 12+ messages in thread
From: Rajendra Nayak @ 2012-02-24  9:58 UTC (permalink / raw)
  To: linux-arm-kernel

omap_hsmmc_late_init() adds deferred (if any) mmc devices which are
dependent on twl4030-gpio device to be available.
If twl4030-gpio is built as a module and inserted and deleted multiple
times, the mmc devices also should be added and deleted accordingly.
Split omap_hsmmc_late_init() into omap_hsmmc_deferred_add() and
omap_hsmmc_deferred_del() to handle this.
The .setup board hook for twl4030-gpio handles the runtime adding
on deferred mmc devices. Similarly a .teardown board hook for twl4030-gpio
should handle the runtime deletion by calling omap_hsmmc_deferred_del().
This is done for all existing omap3 boards in subsequent patches.

Reported-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
---
 arch/arm/mach-omap2/board-3430sdp.c          |    2 +-
 arch/arm/mach-omap2/board-cm-t35.c           |    2 +-
 arch/arm/mach-omap2/board-devkit8000.c       |    2 +-
 arch/arm/mach-omap2/board-igep0020.c         |    2 +-
 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-zoom-peripherals.c |    2 +-
 arch/arm/mach-omap2/hsmmc.c                  |   93 ++++++++++++--------------
 arch/arm/mach-omap2/hsmmc.h                  |    9 ++-
 12 files changed, 61 insertions(+), 61 deletions(-)

diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index da75f23..2eef653 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -251,7 +251,7 @@ static int sdp3430_twl_gpio_setup(struct device *dev,
 	 */
 	mmc[0].gpio_cd = gpio + 0;
 	mmc[1].gpio_cd = gpio + 1;
-	omap_hsmmc_late_init(mmc);
+	omap_hsmmc_deferred_add(mmc);
 
 	/* gpio + 7 is "sub_lcd_en_bkl" (output/PWM1) */
 	gpio_request_one(gpio + 7, GPIOF_OUT_INIT_LOW, "sub_lcd_en_bkl");
diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index 49e6405..28e7117 100644
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -471,7 +471,7 @@ static int cm_t35_twl_gpio_setup(struct device *dev, unsigned gpio,
 
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	mmc[0].gpio_cd = gpio + 0;
-	omap_hsmmc_late_init(mmc);
+	omap_hsmmc_deferred_add(mmc);
 
 	return 0;
 }
diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
index 11cd2a8..373ba75 100644
--- a/arch/arm/mach-omap2/board-devkit8000.c
+++ b/arch/arm/mach-omap2/board-devkit8000.c
@@ -229,7 +229,7 @@ static int devkit8000_twl_gpio_setup(struct device *dev,
 
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	mmc[0].gpio_cd = gpio + 0;
-	omap_hsmmc_late_init(mmc);
+	omap_hsmmc_deferred_add(mmc);
 
 	/* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
 	gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
index e558800..fb94fdc 100644
--- a/arch/arm/mach-omap2/board-igep0020.c
+++ b/arch/arm/mach-omap2/board-igep0020.c
@@ -403,7 +403,7 @@ static int igep_twl_gpio_setup(struct device *dev,
 
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	mmc[0].gpio_cd = gpio + 0;
-	omap_hsmmc_late_init(mmc);
+	omap_hsmmc_deferred_add(mmc);
 
 	/* TWL4030_GPIO_MAX + 1 == ledB (out, active low LED) */
 #if !defined(CONFIG_LEDS_GPIO) && !defined(CONFIG_LEDS_GPIO_MODULE)
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 7be8d65..2ec7bae 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -276,7 +276,7 @@ static int beagle_twl_gpio_setup(struct device *dev,
 	mmc[0].gpio_wp = beagle_config.mmc1_gpio_wp;
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	mmc[0].gpio_cd = gpio + 0;
-	omap_hsmmc_late_init(mmc);
+	omap_hsmmc_deferred_add(mmc);
 
 	/*
 	 * TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, XM active
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index 6b77ad9..47a9159 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -363,7 +363,7 @@ static int omap3evm_twl_gpio_setup(struct device *dev,
 
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	mmc[0].gpio_cd = gpio + 0;
-	omap_hsmmc_late_init(mmc);
+	omap_hsmmc_deferred_add(mmc);
 
 	/*
 	 * Most GPIOs are for USB OTG.  Some are mostly sent to
diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c
index ace466b..faea4c8 100644
--- a/arch/arm/mach-omap2/board-omap3pandora.c
+++ b/arch/arm/mach-omap2/board-omap3pandora.c
@@ -302,7 +302,7 @@ static int omap3pandora_twl_gpio_setup(struct device *dev,
 	/* gpio + {0,1} is "mmc{0,1}_cd" (input/IRQ) */
 	omap3pandora_mmc[0].gpio_cd = gpio + 0;
 	omap3pandora_mmc[1].gpio_cd = gpio + 1;
-	omap_hsmmc_late_init(omap3pandora_mmc);
+	omap_hsmmc_deferred_add(omap3pandora_mmc);
 
 	/* gpio + 13 drives 32kHz buffer for wifi module */
 	gpio_32khz = gpio + 13;
diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c
index 6410043..1cad225 100644
--- a/arch/arm/mach-omap2/board-omap3stalker.c
+++ b/arch/arm/mach-omap2/board-omap3stalker.c
@@ -284,7 +284,7 @@ omap3stalker_twl_gpio_setup(struct device *dev,
 {
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	mmc[0].gpio_cd = gpio + 0;
-	omap_hsmmc_late_init(mmc);
+	omap_hsmmc_deferred_add(mmc);
 
 	/*
 	 * Most GPIOs are for USB OTG.  Some are mostly sent to
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index 8842e04..932ac8e 100644
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -120,7 +120,7 @@ static int touchbook_twl_gpio_setup(struct device *dev,
 {
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	mmc[0].gpio_cd = gpio + 0;
-	omap_hsmmc_late_init(mmc);
+	omap_hsmmc_deferred_add(mmc);
 
 	/* REVISIT: need ehci-omap hooks for external VBUS
 	 * power switch and overcurrent detect
diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c
index 3d39cdb..1c200ee 100644
--- a/arch/arm/mach-omap2/board-zoom-peripherals.c
+++ b/arch/arm/mach-omap2/board-zoom-peripherals.c
@@ -234,7 +234,7 @@ static int zoom_twl_gpio_setup(struct device *dev,
 
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	mmc[0].gpio_cd = gpio + 0;
-	omap_hsmmc_late_init(mmc);
+	omap_hsmmc_deferred_add(mmc);
 
 	ret = gpio_request_one(LCD_PANEL_ENABLE_GPIO, GPIOF_OUT_INIT_LOW,
 			       "lcd enable");
diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
index a97876d..bd47f5c 100644
--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -43,6 +43,9 @@ static int hsmmc_get_context_loss(struct device *dev)
 #define hsmmc_get_context_loss NULL
 #endif
 
+static void omap_hsmmc_init_one(struct omap2_hsmmc_info *hsmmcinfo,
+					int ctrl_nr, int deferred);
+
 static void omap_hsmmc1_before_set_reg(struct device *dev, int slot,
 				  int power_on, int vdd)
 {
@@ -428,45 +431,24 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
 	return 0;
 }
 
-static int omap_hsmmc_done;
-
-void omap_hsmmc_late_init(struct omap2_hsmmc_info *c)
+void omap_hsmmc_deferred_add(struct omap2_hsmmc_info *c)
 {
-	struct platform_device *pdev;
-	struct omap_mmc_platform_data *mmc_pdata;
-	int res;
-
-	if (omap_hsmmc_done != 1)
-		return;
-
-	omap_hsmmc_done++;
-
-	for (; c->mmc; c++) {
-		if (!c->deferred)
-			continue;
-
-		pdev = c->pdev;
-		if (!pdev)
-			continue;
-
-		mmc_pdata = pdev->dev.platform_data;
-		if (!mmc_pdata)
-			continue;
-
-		mmc_pdata->slots[0].switch_pin = c->gpio_cd;
-		mmc_pdata->slots[0].gpio_wp = c->gpio_wp;
+	for (; c->mmc; c++)
+		if (c->deferred)
+			omap_hsmmc_init_one(c, c->mmc, 0);
+}
 
-		res = omap_device_register(pdev);
-		if (res)
-			pr_err("Could not late init MMC %s\n",
-			       c->name);
-	}
+void omap_hsmmc_deferred_del(struct omap2_hsmmc_info *c)
+{
+	for (; c->mmc; c++)
+		if (c->deferred)
+			omap_device_unregister(c->pdev);
 }
 
 #define MAX_OMAP_MMC_HWMOD_NAME_LEN		16
 
 static void omap_hsmmc_init_one(struct omap2_hsmmc_info *hsmmcinfo,
-					int ctrl_nr)
+					int ctrl_nr, int deferred)
 {
 	struct omap_hwmod *oh;
 	struct omap_hwmod *ohs[1];
@@ -478,18 +460,38 @@ static void omap_hsmmc_init_one(struct omap2_hsmmc_info *hsmmcinfo,
 	char *name;
 	int res;
 
-	mmc_data = kzalloc(sizeof(struct omap_mmc_platform_data), GFP_KERNEL);
-	if (!mmc_data) {
-		pr_err("Cannot allocate memory for mmc device!\n");
-		return;
+	if (!hsmmcinfo->mmc_data) {
+		mmc_data = kzalloc(sizeof(*mmc_data), GFP_KERNEL);
+		if (!mmc_data) {
+			pr_err("Cannot allocate memory for mmc device!\n");
+			return;
+		}
+
+		res = omap_hsmmc_pdata_init(hsmmcinfo, mmc_data);
+		if (res < 0)
+			goto free_mmc;
+
+		omap_hsmmc_mux(mmc_data, (ctrl_nr - 1));
+		hsmmcinfo->mmc_data = kmemdup(mmc_data, sizeof(*mmc_data),
+								 GFP_KERNEL);
+		if (!hsmmcinfo->mmc_data) {
+			pr_err("Cannot allocate memory for mmc device!\n");
+			goto free_mmc;
+		}
+	} else	{
+		mmc_data = kmemdup(hsmmcinfo->mmc_data, sizeof(*mmc_data),
+								 GFP_KERNEL);
+		if (!mmc_data) {
+			pr_err("Cannot allocate memory for mmc device!\n");
+			return;
+		}
+		mmc_data->slots[0].switch_pin = hsmmcinfo->gpio_cd;
+		mmc_data->slots[0].gpio_wp = hsmmcinfo->gpio_wp;
 	}
 
-	res = omap_hsmmc_pdata_init(hsmmcinfo, mmc_data);
-	if (res < 0)
+	if (deferred)
 		goto free_mmc;
 
-	omap_hsmmc_mux(mmc_data, (ctrl_nr - 1));
-
 	name = "omap_hsmmc";
 	res = snprintf(oh_name, MAX_OMAP_MMC_HWMOD_NAME_LEN,
 		     "mmc%d", ctrl_nr);
@@ -529,9 +531,6 @@ static void omap_hsmmc_init_one(struct omap2_hsmmc_info *hsmmcinfo,
 
 	hsmmcinfo->pdev = pdev;
 
-	if (hsmmcinfo->deferred)
-		goto free_mmc;
-
 	res = omap_device_register(pdev);
 	if (res) {
 		pr_err("Could not register od for %s\n", name);
@@ -557,11 +556,6 @@ void __init omap_hsmmc_init(struct omap2_hsmmc_info *controllers)
 {
 	u32 reg;
 
-	if (omap_hsmmc_done)
-		return;
-
-	omap_hsmmc_done = 1;
-
 	if (!cpu_is_omap44xx()) {
 		if (cpu_is_omap2430()) {
 			control_pbias_offset = OMAP243X_CONTROL_PBIAS_LITE;
@@ -586,7 +580,8 @@ void __init omap_hsmmc_init(struct omap2_hsmmc_info *controllers)
 	}
 
 	for (; controllers->mmc; controllers++)
-		omap_hsmmc_init_one(controllers, controllers->mmc);
+		omap_hsmmc_init_one(controllers, controllers->mmc,
+						 controllers->deferred);
 
 }
 
diff --git a/arch/arm/mach-omap2/hsmmc.h b/arch/arm/mach-omap2/hsmmc.h
index 07831cc..2c1c580 100644
--- a/arch/arm/mach-omap2/hsmmc.h
+++ b/arch/arm/mach-omap2/hsmmc.h
@@ -31,12 +31,14 @@ struct omap2_hsmmc_info {
 	void (*remux)(struct device *dev, int slot, int power_on);
 	/* init some special card */
 	void (*init_card)(struct mmc_card *card);
+	struct omap_mmc_platform_data *mmc_data;
 };
 
 #if defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
 
 void omap_hsmmc_init(struct omap2_hsmmc_info *);
-void omap_hsmmc_late_init(struct omap2_hsmmc_info *);
+void omap_hsmmc_deferred_add(struct omap2_hsmmc_info *);
+void omap_hsmmc_deferred_del(struct omap2_hsmmc_info *);
 
 #else
 
@@ -44,8 +46,11 @@ static inline void omap_hsmmc_init(struct omap2_hsmmc_info *info)
 {
 }
 
-static inline void omap_hsmmc_late_init(struct omap2_hsmmc_info *info)
+static inline void omap_hsmmc_deferred_add(struct omap2_hsmmc_info *info)
 {
 }
 
+static inline void omap_hsmmc_deferred_del(struct omap2_hsmmc_info *info)
+{
+}
 #endif
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 6/6] ARM: OMAP3: Use .teardown of twl4030-gpio to clean board requests
  2012-02-24  9:58 [PATCH 0/6] Fix issues around twl4030-gpio used as a module Rajendra Nayak
                   ` (4 preceding siblings ...)
  2012-02-24  9:58 ` [PATCH 5/6] ARM: OMAP3: Modify omap_hsmmc_late_init to handle deleting mmc devices Rajendra Nayak
@ 2012-02-24  9:58 ` Rajendra Nayak
  5 siblings, 0 replies; 12+ messages in thread
From: Rajendra Nayak @ 2012-02-24  9:58 UTC (permalink / raw)
  To: linux-arm-kernel

All OMAP3 boards which register a .setup function with twl4030
gpio driver do not seem to have a .teardown hook implemented.
.setup mainly requests a few gpios and also in most cases
does a omap_hsmmc_deferred_add(). Have a .teardown do a gpio_free()
and of the requested gpios and also do a omap_hsmmc_deferred_del().
This helps in case the twl4030 gpio driver is built as a module and
added and removed multiple times. Without the .teardown a multiple
insmod/rmmod can result in gpio request failues and also WARN messages
stating addition of already registered mmc devices.

Reported-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
---
 arch/arm/mach-omap2/board-3430sdp.c          |   13 +++++++++++++
 arch/arm/mach-omap2/board-cm-t35.c           |   12 ++++++++++++
 arch/arm/mach-omap2/board-devkit8000.c       |   13 +++++++++++++
 arch/arm/mach-omap2/board-igep0020.c         |   15 +++++++++++++++
 arch/arm/mach-omap2/board-ldp.c              |   13 +++++++++++++
 arch/arm/mach-omap2/board-omap3beagle.c      |   15 +++++++++++++++
 arch/arm/mach-omap2/board-omap3evm.c         |   13 +++++++++++++
 arch/arm/mach-omap2/board-omap3pandora.c     |   11 +++++++++++
 arch/arm/mach-omap2/board-omap3stalker.c     |   14 ++++++++++++++
 arch/arm/mach-omap2/board-omap3touchbook.c   |   13 +++++++++++++
 arch/arm/mach-omap2/board-rx51-peripherals.c |   11 +++++++++++
 arch/arm/mach-omap2/board-zoom-peripherals.c |   10 ++++++++++
 12 files changed, 153 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index 2eef653..e5afbdd 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -262,6 +262,18 @@ static int sdp3430_twl_gpio_setup(struct device *dev,
 	return 0;
 }
 
+static int sdp3430_twl_gpio_teardown(struct device *dev,
+		unsigned gpio, unsigned ngpio)
+{
+	omap_hsmmc_deferred_del(mmc);
+	/* gpio + 7 is "sub_lcd_en_bkl" (output/PWM1) */
+	gpio_free(gpio + 7);
+	/* gpio + 15 is "sub_lcd_nRST" (output) */
+	gpio_free(gpio + 15);
+
+	return 0;
+}
+
 static struct twl4030_gpio_platform_data sdp3430_gpio_data = {
 	.gpio_base	= OMAP_MAX_GPIO_LINES,
 	.irq_base	= TWL4030_GPIO_IRQ_BASE,
@@ -269,6 +281,7 @@ static struct twl4030_gpio_platform_data sdp3430_gpio_data = {
 	.pulldowns	= BIT(2) | BIT(6) | BIT(8) | BIT(13)
 				| BIT(16) | BIT(17),
 	.setup		= sdp3430_twl_gpio_setup,
+	.teardown	= sdp3430_twl_gpio_teardown,
 };
 
 /* regulator consumer mappings */
diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index 28e7117..953824b 100644
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -476,11 +476,23 @@ static int cm_t35_twl_gpio_setup(struct device *dev, unsigned gpio,
 	return 0;
 }
 
+static int cm_t35_twl_gpio_teardown(struct device *dev, unsigned gpio,
+				 unsigned ngpio)
+{
+	int wlan_rst = gpio + 2;
+
+	omap_hsmmc_deferred_del(mmc);
+	gpio_free(wlan_rst);
+
+	return 0;
+}
+
 static struct twl4030_gpio_platform_data cm_t35_gpio_data = {
 	.gpio_base	= OMAP_MAX_GPIO_LINES,
 	.irq_base	= TWL4030_GPIO_IRQ_BASE,
 	.irq_end	= TWL4030_GPIO_IRQ_END,
 	.setup          = cm_t35_twl_gpio_setup,
+	.teardown	= cm_t35_twl_gpio_teardown,
 };
 
 static struct twl4030_platform_data cm_t35_twldata = {
diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
index 373ba75..fe93cbc 100644
--- a/arch/arm/mach-omap2/board-devkit8000.c
+++ b/arch/arm/mach-omap2/board-devkit8000.c
@@ -255,6 +255,18 @@ static int devkit8000_twl_gpio_setup(struct device *dev,
 	return 0;
 }
 
+static int devkit8000_twl_gpio_teardown(struct device *dev,
+		unsigned gpio, unsigned ngpio)
+{
+	omap_hsmmc_deferred_del(mmc);
+	/* TWL4030_GPIO_MAX + 0 is "LCD_PWREN" (out, active high) */
+	gpio_free(gpio + TWL4030_GPIO_MAX + 0);
+	/* gpio + 7 is "DVI_PD" (out, active low) */
+	gpio_free(gpio + 7);
+
+	return 0;
+}
+
 static struct twl4030_gpio_platform_data devkit8000_gpio_data = {
 	.gpio_base	= OMAP_MAX_GPIO_LINES,
 	.irq_base	= TWL4030_GPIO_IRQ_BASE,
@@ -263,6 +275,7 @@ static struct twl4030_gpio_platform_data devkit8000_gpio_data = {
 	.pulldowns	= BIT(1) | BIT(2) | BIT(6) | BIT(8) | BIT(13)
 				| BIT(15) | BIT(16) | BIT(17),
 	.setup		= devkit8000_twl_gpio_setup,
+	.teardown	= devkit8000_twl_gpio_teardown,
 };
 
 static struct regulator_consumer_supply devkit8000_vpll1_supplies[] = {
diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
index fb94fdc..5d47932 100644
--- a/arch/arm/mach-omap2/board-igep0020.c
+++ b/arch/arm/mach-omap2/board-igep0020.c
@@ -436,12 +436,27 @@ static int igep_twl_gpio_setup(struct device *dev,
 	return 0;
 };
 
+static int igep_twl_gpio_teardown(struct device *dev,
+		unsigned gpio, unsigned ngpio)
+{
+	omap_hsmmc_deferred_del(mmc);
+	/* TWL4030_GPIO_MAX + 1 == ledB (out, active low LED) */
+	gpio_free(gpio + TWL4030_GPIO_MAX + 1);
+	if (machine_is_igep0030())
+		return 0;
+
+	gpio_free_array(igep2_twl_gpios, ARRAY_SIZE(igep2_twl_gpios));
+
+	return 0;
+}
+
 static struct twl4030_gpio_platform_data igep_twl4030_gpio_pdata = {
 	.gpio_base	= OMAP_MAX_GPIO_LINES,
 	.irq_base	= TWL4030_GPIO_IRQ_BASE,
 	.irq_end	= TWL4030_GPIO_IRQ_END,
 	.use_leds	= true,
 	.setup		= igep_twl_gpio_setup,
+	.teardown	= igep_twl_gpio_teardown,
 };
 
 static int igep2_enable_dvi(struct omap_dss_device *dssdev)
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index b5bc9b2..b41add4 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -274,11 +274,24 @@ static int ldp_twl_gpio_setup(struct device *dev, unsigned gpio, unsigned ngpio)
 	return 0;
 }
 
+static int ldp_twl_gpio_teardown(struct device *dev, unsigned gpio,
+							 unsigned ngpio)
+{
+	struct gpio gpios[] = {
+		{gpio + 7 , GPIOF_OUT_INIT_LOW, "LCD ENABLE"},
+		{gpio + 15, GPIOF_OUT_INIT_LOW, "LCD BACKLIGHT"},
+	};
+	gpio_free_array(gpios, ARRAY_SIZE(gpios));
+
+	return 0;
+}
+
 static struct twl4030_gpio_platform_data ldp_gpio_data = {
 	.gpio_base	= OMAP_MAX_GPIO_LINES,
 	.irq_base	= TWL4030_GPIO_IRQ_BASE,
 	.irq_end	= TWL4030_GPIO_IRQ_END,
 	.setup		= ldp_twl_gpio_setup,
+	.teardown	= ldp_twl_gpio_teardown,
 };
 
 static struct regulator_consumer_supply ldp_vmmc1_supply[] = {
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 2ec7bae..cbfe87e 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -320,6 +320,20 @@ static int beagle_twl_gpio_setup(struct device *dev,
 	return 0;
 }
 
+static int beagle_twl_gpio_teardown(struct device *dev,
+		unsigned gpio, unsigned ngpio)
+{
+	omap_hsmmc_deferred_del(mmc);
+	/* gpio + 1 is used for differently on beagle and beagle-Xm boards */
+	gpio_free(gpio + 1);
+	if (cpu_is_omap3630())
+		/* gpio + 2 is used only on Xm */
+		gpio_free(gpio + 2);
+	gpio_free(gpio + TWL4030_GPIO_MAX);
+
+	return 0;
+}
+
 static struct twl4030_gpio_platform_data beagle_gpio_data = {
 	.gpio_base	= OMAP_MAX_GPIO_LINES,
 	.irq_base	= TWL4030_GPIO_IRQ_BASE,
@@ -329,6 +343,7 @@ static struct twl4030_gpio_platform_data beagle_gpio_data = {
 	.pulldowns	= BIT(2) | BIT(6) | BIT(7) | BIT(8) | BIT(13)
 				| BIT(15) | BIT(16) | BIT(17),
 	.setup		= beagle_twl_gpio_setup,
+	.teardown	= beagle_twl_gpio_teardown,
 };
 
 /* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index 47a9159..ae7e921 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -388,12 +388,25 @@ static int omap3evm_twl_gpio_setup(struct device *dev,
 	return 0;
 }
 
+static int omap3evm_twl_gpio_teardown(struct device *dev,
+		unsigned gpio, unsigned ngpio)
+{
+	omap_hsmmc_deferred_del(mmc);
+	/* gpio + TWL4030_GPIO_MAX used for ledA, LCD Backlight control */
+	gpio_free(gpio + TWL4030_GPIO_MAX);
+	/* gpio + 7 used for DVI Enable */
+	gpio_free(gpio + 7);
+
+	return 0;
+}
+
 static struct twl4030_gpio_platform_data omap3evm_gpio_data = {
 	.gpio_base	= OMAP_MAX_GPIO_LINES,
 	.irq_base	= TWL4030_GPIO_IRQ_BASE,
 	.irq_end	= TWL4030_GPIO_IRQ_END,
 	.use_leds	= true,
 	.setup		= omap3evm_twl_gpio_setup,
+	.teardown	= omap3evm_twl_gpio_teardown,
 };
 
 static uint32_t board_keymap[] = {
diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c
index faea4c8..9637bbb 100644
--- a/arch/arm/mach-omap2/board-omap3pandora.c
+++ b/arch/arm/mach-omap2/board-omap3pandora.c
@@ -315,11 +315,22 @@ static int omap3pandora_twl_gpio_setup(struct device *dev,
 	return 0;
 }
 
+static int omap3pandora_twl_gpio_teardown(struct device *dev,
+		unsigned gpio, unsigned ngpio)
+{
+	omap_hsmmc_deferred_del(omap3pandora_mmc);
+	/* gpio + 13 drives 32kHz buffer for wifi module */
+	gpio_free(gpio + 13);
+
+	return 0;
+}
+
 static struct twl4030_gpio_platform_data omap3pandora_gpio_data = {
 	.gpio_base	= OMAP_MAX_GPIO_LINES,
 	.irq_base	= TWL4030_GPIO_IRQ_BASE,
 	.irq_end	= TWL4030_GPIO_IRQ_END,
 	.setup		= omap3pandora_twl_gpio_setup,
+	.teardown	= omap3pandora_twl_gpio_teardown,
 };
 
 static struct regulator_consumer_supply pandora_vmmc1_supply[] = {
diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c
index 1cad225..5c73750 100644
--- a/arch/arm/mach-omap2/board-omap3stalker.c
+++ b/arch/arm/mach-omap2/board-omap3stalker.c
@@ -307,12 +307,26 @@ omap3stalker_twl_gpio_setup(struct device *dev,
 	return 0;
 }
 
+static int
+omap3stalker_twl_gpio_teardown(struct device *dev,
+			    unsigned gpio, unsigned ngpio)
+{
+	omap_hsmmc_deferred_del(mmc);
+	/* gpio + TWL4030_GPIO_MAX used for ledA, LCD Backlight control */
+	gpio_free(gpio + TWL4030_GPIO_MAX);
+	/* gpio + 7 used for DVI Enable */
+	gpio_free(gpio + 7);
+
+	return 0;
+}
+
 static struct twl4030_gpio_platform_data omap3stalker_gpio_data = {
 	.gpio_base	= OMAP_MAX_GPIO_LINES,
 	.irq_base	= TWL4030_GPIO_IRQ_BASE,
 	.irq_end	= TWL4030_GPIO_IRQ_END,
 	.use_leds	= true,
 	.setup		= omap3stalker_twl_gpio_setup,
+	.teardown	= omap3stalker_twl_gpio_teardown,
 };
 
 static uint32_t board_keymap[] = {
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index 932ac8e..d3752f2 100644
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -137,6 +137,18 @@ static int touchbook_twl_gpio_setup(struct device *dev,
 	return 0;
 }
 
+static int touchbook_twl_gpio_teardown(struct device *dev,
+		unsigned gpio, unsigned ngpio)
+{
+	omap_hsmmc_deferred_del(mmc);
+	/* gpio + 1 used for EHCI_nOC */
+	gpio_free(gpio + 1);
+	/* gpio + TWL4030_GPIO_MAX used for ledA, EHCI nEN_USB_PWR */
+	gpio_free(gpio + TWL4030_GPIO_MAX);
+
+	return 0;
+}
+
 static struct twl4030_gpio_platform_data touchbook_gpio_data = {
 	.gpio_base	= OMAP_MAX_GPIO_LINES,
 	.irq_base	= TWL4030_GPIO_IRQ_BASE,
@@ -146,6 +158,7 @@ static struct twl4030_gpio_platform_data touchbook_gpio_data = {
 	.pulldowns	= BIT(2) | BIT(6) | BIT(7) | BIT(8) | BIT(13)
 				| BIT(15) | BIT(16) | BIT(17),
 	.setup		= touchbook_twl_gpio_setup,
+	.teardown	= touchbook_twl_gpio_teardown,
 };
 
 static struct regulator_consumer_supply touchbook_vdac_supply[] = {
diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
index 0e9d89a..e900d40 100644
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -702,6 +702,16 @@ static int rx51_twlgpio_setup(struct device *dev, unsigned gpio, unsigned n)
 	return 0;
 }
 
+static int rx51_twlgpio_teardown(struct device *dev, unsigned gpio, unsigned n)
+{
+	/* gpio + 6 used for backlight_pwm */
+	gpio_free(gpio + 6);
+	/* gpio + 7 used for speaker_en */
+	gpio_free(gpio + 7);
+
+	return 0;
+}
+
 static struct twl4030_gpio_platform_data rx51_gpio_data = {
 	.gpio_base		= OMAP_MAX_GPIO_LINES,
 	.irq_base		= TWL4030_GPIO_IRQ_BASE,
@@ -712,6 +722,7 @@ static struct twl4030_gpio_platform_data rx51_gpio_data = {
 				| BIT(12) | BIT(13) | BIT(14) | BIT(15)
 				| BIT(16) | BIT(17) ,
 	.setup			= rx51_twlgpio_setup,
+	.teardown		= rx51_twlgpio_teardown,
 };
 
 static struct twl4030_ins sleep_on_seq[] __initdata = {
diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c
index 1c200ee..a5fd25a 100644
--- a/arch/arm/mach-omap2/board-zoom-peripherals.c
+++ b/arch/arm/mach-omap2/board-zoom-peripherals.c
@@ -245,6 +245,15 @@ static int zoom_twl_gpio_setup(struct device *dev,
 	return ret;
 }
 
+static int zoom_twl_gpio_teardown(struct device *dev,
+		unsigned gpio, unsigned ngpio)
+{
+	omap_hsmmc_deferred_del(mmc);
+	gpio_free(LCD_PANEL_ENABLE_GPIO);
+
+	return 0;
+}
+
 /* EXTMUTE callback function */
 static void zoom2_set_hs_extmute(int mute)
 {
@@ -256,6 +265,7 @@ static struct twl4030_gpio_platform_data zoom_gpio_data = {
 	.irq_base	= TWL4030_GPIO_IRQ_BASE,
 	.irq_end	= TWL4030_GPIO_IRQ_END,
 	.setup		= zoom_twl_gpio_setup,
+	.teardown	= zoom_twl_gpio_teardown,
 };
 
 static struct twl4030_platform_data zoom_twldata = {
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 4/6] ARM: OMAP3: Mark only those mmc devices which use gpio_cd, as deferred
  2012-02-24  9:58 ` [PATCH 4/6] ARM: OMAP3: Mark only those mmc devices which use gpio_cd, as deferred Rajendra Nayak
@ 2012-02-24 22:21   ` Tony Lindgren
  2012-02-25  4:30     ` Rajendra Nayak
  0 siblings, 1 reply; 12+ messages in thread
From: Tony Lindgren @ 2012-02-24 22:21 UTC (permalink / raw)
  To: linux-arm-kernel

* Rajendra Nayak <rnayak@ti.com> [120224 01:27]:
> mmc devices which actually do not depend on twl4030-gpio for
> gpio_cd should not be maked as deferred.
> 
> Also on overo, since none of the mmc devices need to be deferred,
> get rid of omap_hsmmc_late_init() altogether.
> 
> Reported-by: Igor Grinberg <grinberg@compulab.co.il>
> Signed-off-by: Rajendra Nayak <rnayak@ti.com>

Thanks, I'll fold this into the original patch with your SOB
so we avoid the extra churn.

Regards,

Tony

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 5/6] ARM: OMAP3: Modify omap_hsmmc_late_init to handle deleting mmc devices
  2012-02-24  9:58 ` [PATCH 5/6] ARM: OMAP3: Modify omap_hsmmc_late_init to handle deleting mmc devices Rajendra Nayak
@ 2012-02-25  0:33   ` Tony Lindgren
  2012-02-25  4:45     ` Rajendra Nayak
  0 siblings, 1 reply; 12+ messages in thread
From: Tony Lindgren @ 2012-02-25  0:33 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

* Rajendra Nayak <rnayak@ti.com> [120224 01:27]:
> omap_hsmmc_late_init() adds deferred (if any) mmc devices which are
> dependent on twl4030-gpio device to be available.
> If twl4030-gpio is built as a module and inserted and deleted multiple
> times, the mmc devices also should be added and deleted accordingly.
> Split omap_hsmmc_late_init() into omap_hsmmc_deferred_add() and
> omap_hsmmc_deferred_del() to handle this.
> The .setup board hook for twl4030-gpio handles the runtime adding
> on deferred mmc devices. Similarly a .teardown board hook for twl4030-gpio
> should handle the runtime deletion by calling omap_hsmmc_deferred_del().
> This is done for all existing omap3 boards in subsequent patches.

This gets complex.. But I think I've found a simpler way where we
can use the twl gpio offsets and let the drivers take care of the rest.
I'll post some patches hopefully on Monday.

Regards,

Tony

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 4/6] ARM: OMAP3: Mark only those mmc devices which use gpio_cd, as deferred
  2012-02-24 22:21   ` Tony Lindgren
@ 2012-02-25  4:30     ` Rajendra Nayak
  0 siblings, 0 replies; 12+ messages in thread
From: Rajendra Nayak @ 2012-02-25  4:30 UTC (permalink / raw)
  To: linux-arm-kernel

On Saturday 25 February 2012 03:51 AM, Tony Lindgren wrote:
> * Rajendra Nayak<rnayak@ti.com>  [120224 01:27]:
>> mmc devices which actually do not depend on twl4030-gpio for
>> gpio_cd should not be maked as deferred.
>>
>> Also on overo, since none of the mmc devices need to be deferred,
>> get rid of omap_hsmmc_late_init() altogether.
>>
>> Reported-by: Igor Grinberg<grinberg@compulab.co.il>
>> Signed-off-by: Rajendra Nayak<rnayak@ti.com>
>
> Thanks, I'll fold this into the original patch with your SOB
> so we avoid the extra churn.

okay, thanks.

>
> Regards,
>
> Tony

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 5/6] ARM: OMAP3: Modify omap_hsmmc_late_init to handle deleting mmc devices
  2012-02-25  0:33   ` Tony Lindgren
@ 2012-02-25  4:45     ` Rajendra Nayak
  2012-03-01 18:58       ` Tony Lindgren
  0 siblings, 1 reply; 12+ messages in thread
From: Rajendra Nayak @ 2012-02-25  4:45 UTC (permalink / raw)
  To: linux-arm-kernel

On Saturday 25 February 2012 06:03 AM, Tony Lindgren wrote:
> Hi,
>
> * Rajendra Nayak<rnayak@ti.com>  [120224 01:27]:
>> omap_hsmmc_late_init() adds deferred (if any) mmc devices which are
>> dependent on twl4030-gpio device to be available.
>> If twl4030-gpio is built as a module and inserted and deleted multiple
>> times, the mmc devices also should be added and deleted accordingly.
>> Split omap_hsmmc_late_init() into omap_hsmmc_deferred_add() and
>> omap_hsmmc_deferred_del() to handle this.
>> The .setup board hook for twl4030-gpio handles the runtime adding
>> on deferred mmc devices. Similarly a .teardown board hook for twl4030-gpio
>> should handle the runtime deletion by calling omap_hsmmc_deferred_del().
>> This is done for all existing omap3 boards in subsequent patches.
>
> This gets complex.. But I think I've found a simpler way where we
> can use the twl gpio offsets and let the drivers take care of the rest.
> I'll post some patches hopefully on Monday.

I agree it gets complex. If you have a simpler way to handle this, that
would be great.

regards,
Rajendra
>
> Regards,
>
> Tony

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 5/6] ARM: OMAP3: Modify omap_hsmmc_late_init to handle deleting mmc devices
  2012-02-25  4:45     ` Rajendra Nayak
@ 2012-03-01 18:58       ` Tony Lindgren
  0 siblings, 0 replies; 12+ messages in thread
From: Tony Lindgren @ 2012-03-01 18:58 UTC (permalink / raw)
  To: linux-arm-kernel

* Rajendra Nayak <rnayak@ti.com> [120224 20:14]:
> On Saturday 25 February 2012 06:03 AM, Tony Lindgren wrote:
> >Hi,
> >
> >* Rajendra Nayak<rnayak@ti.com>  [120224 01:27]:
> >>omap_hsmmc_late_init() adds deferred (if any) mmc devices which are
> >>dependent on twl4030-gpio device to be available.
> >>If twl4030-gpio is built as a module and inserted and deleted multiple
> >>times, the mmc devices also should be added and deleted accordingly.
> >>Split omap_hsmmc_late_init() into omap_hsmmc_deferred_add() and
> >>omap_hsmmc_deferred_del() to handle this.
> >>The .setup board hook for twl4030-gpio handles the runtime adding
> >>on deferred mmc devices. Similarly a .teardown board hook for twl4030-gpio
> >>should handle the runtime deletion by calling omap_hsmmc_deferred_del().
> >>This is done for all existing omap3 boards in subsequent patches.
> >
> >This gets complex.. But I think I've found a simpler way where we
> >can use the twl gpio offsets and let the drivers take care of the rest.
> >I'll post some patches hopefully on Monday.
> 
> I agree it gets complex. If you have a simpler way to handle this, that
> would be great.

Posted now, sorry it too a bit longer, I got distracted with other
stuff. The thread is "[PATCH 0/4] Start getting rid of pdata callbacks
with gpio_find_by_chip_name()". Some further testing would be
appreciated.

Regards,

Tony

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2012-03-01 18:58 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-02-24  9:58 [PATCH 0/6] Fix issues around twl4030-gpio used as a module Rajendra Nayak
2012-02-24  9:58 ` [PATCH 1/6] ARM: OMAP: omap_device: Add omap_device_unregister() Rajendra Nayak
2012-02-24  9:58 ` [PATCH 2/6] mmc: omap_hsmmc: Make the driver support hotpluggable devices Rajendra Nayak
2012-02-24  9:58 ` [PATCH 3/6] mmc: omap_hsmmc: If probe fails, give out error messages Rajendra Nayak
2012-02-24  9:58 ` [PATCH 4/6] ARM: OMAP3: Mark only those mmc devices which use gpio_cd, as deferred Rajendra Nayak
2012-02-24 22:21   ` Tony Lindgren
2012-02-25  4:30     ` Rajendra Nayak
2012-02-24  9:58 ` [PATCH 5/6] ARM: OMAP3: Modify omap_hsmmc_late_init to handle deleting mmc devices Rajendra Nayak
2012-02-25  0:33   ` Tony Lindgren
2012-02-25  4:45     ` Rajendra Nayak
2012-03-01 18:58       ` Tony Lindgren
2012-02-24  9:58 ` [PATCH 6/6] ARM: OMAP3: Use .teardown of twl4030-gpio to clean board requests Rajendra Nayak

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).