All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] omap hsmmc init cleanup and section warning fixes for v3.4 merge window
@ 2012-02-15 18:28 ` Tony Lindgren
  0 siblings, 0 replies; 66+ messages in thread
From: Tony Lindgren @ 2012-02-15 18:28 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: linux-omap

Hi all,

This series fixes up the issues noted by Russell on omap2_hsmmc_init()
where if TWL PMIC is compiled as a module we can't keep a bunch of
functions marked as __init like they should be. This series fixes
the issues by splitting omap2_hsmmc_init() into two functions.

One more patch is needed to sort out the remaining issue with
omap4 that has yet another luck based initialization for the
same issue..

Regards,

Tony

---

Ohad Ben-Cohen (1):
      ARM: OMAP: omap_device: Expose omap_device_{alloc, delete, register}

Tony Lindgren (2):
      ARM: OMAP2+: Split omap2_hsmmc_init() to properly support I2C GPIO pins
      ARM: OMAP2+: Mark omap_hsmmc_init and omap_mux related functions as __init


 arch/arm/mach-omap2/board-2430sdp.c           |    2 
 arch/arm/mach-omap2/board-3430sdp.c           |    5 +
 arch/arm/mach-omap2/board-4430sdp.c           |    6 +
 arch/arm/mach-omap2/board-am3517evm.c         |    2 
 arch/arm/mach-omap2/board-cm-t35.c            |    6 +
 arch/arm/mach-omap2/board-devkit8000.c        |    4 +
 arch/arm/mach-omap2/board-flash.c             |    2 
 arch/arm/mach-omap2/board-igep0020.c          |    7 +-
 arch/arm/mach-omap2/board-ldp.c               |    2 
 arch/arm/mach-omap2/board-omap3beagle.c       |   10 ++
 arch/arm/mach-omap2/board-omap3evm.c          |    8 +-
 arch/arm/mach-omap2/board-omap3logic.c        |    2 
 arch/arm/mach-omap2/board-omap3pandora.c      |    6 +
 arch/arm/mach-omap2/board-omap3stalker.c      |   15 ++-
 arch/arm/mach-omap2/board-omap3touchbook.c    |   17 ++--
 arch/arm/mach-omap2/board-omap4panda.c        |    6 +
 arch/arm/mach-omap2/board-overo.c             |    5 +
 arch/arm/mach-omap2/board-rm680.c             |    2 
 arch/arm/mach-omap2/board-rx51-peripherals.c  |    2 
 arch/arm/mach-omap2/board-zoom-peripherals.c  |    6 +
 arch/arm/mach-omap2/display.c                 |    8 +-
 arch/arm/mach-omap2/hsmmc.c                   |  111 ++++++++++++++++++-------
 arch/arm/mach-omap2/hsmmc.h                   |   12 ++-
 arch/arm/mach-omap2/mux.c                     |   22 ++---
 arch/arm/plat-omap/include/plat/omap_device.h |    7 ++
 arch/arm/plat-omap/omap_device.c              |   13 +--
 26 files changed, 192 insertions(+), 96 deletions(-)

-- 
Signature

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

* [PATCH 0/3] omap hsmmc init cleanup and section warning fixes for v3.4 merge window
@ 2012-02-15 18:28 ` Tony Lindgren
  0 siblings, 0 replies; 66+ messages in thread
From: Tony Lindgren @ 2012-02-15 18:28 UTC (permalink / raw)
  To: linux-arm-kernel

Hi all,

This series fixes up the issues noted by Russell on omap2_hsmmc_init()
where if TWL PMIC is compiled as a module we can't keep a bunch of
functions marked as __init like they should be. This series fixes
the issues by splitting omap2_hsmmc_init() into two functions.

One more patch is needed to sort out the remaining issue with
omap4 that has yet another luck based initialization for the
same issue..

Regards,

Tony

---

Ohad Ben-Cohen (1):
      ARM: OMAP: omap_device: Expose omap_device_{alloc, delete, register}

Tony Lindgren (2):
      ARM: OMAP2+: Split omap2_hsmmc_init() to properly support I2C GPIO pins
      ARM: OMAP2+: Mark omap_hsmmc_init and omap_mux related functions as __init


 arch/arm/mach-omap2/board-2430sdp.c           |    2 
 arch/arm/mach-omap2/board-3430sdp.c           |    5 +
 arch/arm/mach-omap2/board-4430sdp.c           |    6 +
 arch/arm/mach-omap2/board-am3517evm.c         |    2 
 arch/arm/mach-omap2/board-cm-t35.c            |    6 +
 arch/arm/mach-omap2/board-devkit8000.c        |    4 +
 arch/arm/mach-omap2/board-flash.c             |    2 
 arch/arm/mach-omap2/board-igep0020.c          |    7 +-
 arch/arm/mach-omap2/board-ldp.c               |    2 
 arch/arm/mach-omap2/board-omap3beagle.c       |   10 ++
 arch/arm/mach-omap2/board-omap3evm.c          |    8 +-
 arch/arm/mach-omap2/board-omap3logic.c        |    2 
 arch/arm/mach-omap2/board-omap3pandora.c      |    6 +
 arch/arm/mach-omap2/board-omap3stalker.c      |   15 ++-
 arch/arm/mach-omap2/board-omap3touchbook.c    |   17 ++--
 arch/arm/mach-omap2/board-omap4panda.c        |    6 +
 arch/arm/mach-omap2/board-overo.c             |    5 +
 arch/arm/mach-omap2/board-rm680.c             |    2 
 arch/arm/mach-omap2/board-rx51-peripherals.c  |    2 
 arch/arm/mach-omap2/board-zoom-peripherals.c  |    6 +
 arch/arm/mach-omap2/display.c                 |    8 +-
 arch/arm/mach-omap2/hsmmc.c                   |  111 ++++++++++++++++++-------
 arch/arm/mach-omap2/hsmmc.h                   |   12 ++-
 arch/arm/mach-omap2/mux.c                     |   22 ++---
 arch/arm/plat-omap/include/plat/omap_device.h |    7 ++
 arch/arm/plat-omap/omap_device.c              |   13 +--
 26 files changed, 192 insertions(+), 96 deletions(-)

-- 
Signature

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

* [PATCH 1/3] ARM: OMAP: omap_device: Expose omap_device_{alloc, delete, register}
  2012-02-15 18:28 ` Tony Lindgren
@ 2012-02-15 18:28   ` Tony Lindgren
  -1 siblings, 0 replies; 66+ messages in thread
From: Tony Lindgren @ 2012-02-15 18:28 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: Ohad Ben-Cohen, Kevin Hilman, linux-omap

From: Ohad Ben-Cohen <ohad@wizery.com>

Expose omap_device_{alloc, delete, register} so we can use them outside
of omap_device.c.

This approach allows users, which need to manipulate an archdata member
of a device before it is registered, to do so. This is also useful
for users who have their devices created very early so they can be used
at ->reserve() time to reserve CMA memory.

The immediate use case for this is to set the private iommu archdata
member, which binds a device to its associated iommu controller.
This way, generic code will be able to attach omap devices to their
iommus, without calling any omap-specific API.

With this in hand, we can further clean the existing mainline OMAP iommu
driver and its mainline users, and focus on generic IOMMU approaches
for future users (rpmsg/remoteproc and the upcoming generic DMA API).

This patch is still considered an interim solution until DT fully materializes
for omap; at that point, this functionality will be removed as DT will
take care of creating the devices and configuring them correctly.

Tested on OMAP4 with a generic rpmsg/remoteproc that doesn't use any
omap-specific IOMMU API anymore.

Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com>
Signed-off-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 arch/arm/plat-omap/include/plat/omap_device.h |    7 +++++++
 arch/arm/plat-omap/omap_device.c              |   13 +++----------
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/arch/arm/plat-omap/include/plat/omap_device.h b/arch/arm/plat-omap/include/plat/omap_device.h
index 51423d2..05f7615 100644
--- a/arch/arm/plat-omap/include/plat/omap_device.h
+++ b/arch/arm/plat-omap/include/plat/omap_device.h
@@ -100,6 +100,13 @@ struct platform_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
 					 struct omap_device_pm_latency *pm_lats,
 					 int pm_lats_cnt, int is_early_device);
 
+struct omap_device *omap_device_alloc(struct platform_device *pdev,
+				      struct omap_hwmod **ohs, int oh_cnt,
+				      struct omap_device_pm_latency *pm_lats,
+				      int pm_lats_cnt);
+void omap_device_delete(struct omap_device *od);
+int omap_device_register(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 e8d9869..f72fafc 100644
--- a/arch/arm/plat-omap/omap_device.c
+++ b/arch/arm/plat-omap/omap_device.c
@@ -97,14 +97,7 @@
 #define USE_WAKEUP_LAT			0
 #define IGNORE_WAKEUP_LAT		1
 
-static int omap_device_register(struct platform_device *pdev);
 static int omap_early_device_register(struct platform_device *pdev);
-static struct omap_device *omap_device_alloc(struct platform_device *pdev,
-				      struct omap_hwmod **ohs, int oh_cnt,
-				      struct omap_device_pm_latency *pm_lats,
-				      int pm_lats_cnt);
-static void omap_device_delete(struct omap_device *od);
-
 
 static struct omap_device_pm_latency omap_default_latency[] = {
 	{
@@ -509,7 +502,7 @@ static int omap_device_fill_resources(struct omap_device *od,
  *
  * Returns an struct omap_device pointer or ERR_PTR() on error;
  */
-static struct omap_device *omap_device_alloc(struct platform_device *pdev,
+struct omap_device *omap_device_alloc(struct platform_device *pdev,
 					struct omap_hwmod **ohs, int oh_cnt,
 					struct omap_device_pm_latency *pm_lats,
 					int pm_lats_cnt)
@@ -591,7 +584,7 @@ oda_exit1:
 	return ERR_PTR(ret);
 }
 
-static void omap_device_delete(struct omap_device *od)
+void omap_device_delete(struct omap_device *od)
 {
 	if (!od)
 		return;
@@ -817,7 +810,7 @@ static struct dev_pm_domain omap_device_pm_domain = {
  * platform_device_register() on the underlying platform_device.
  * Returns the return value of platform_device_register().
  */
-static int omap_device_register(struct platform_device *pdev)
+int omap_device_register(struct platform_device *pdev)
 {
 	pr_debug("omap_device: %s: registering\n", pdev->name);

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

* [PATCH 1/3] ARM: OMAP: omap_device: Expose omap_device_{alloc, delete, register}
@ 2012-02-15 18:28   ` Tony Lindgren
  0 siblings, 0 replies; 66+ messages in thread
From: Tony Lindgren @ 2012-02-15 18:28 UTC (permalink / raw)
  To: linux-arm-kernel

From: Ohad Ben-Cohen <ohad@wizery.com>

Expose omap_device_{alloc, delete, register} so we can use them outside
of omap_device.c.

This approach allows users, which need to manipulate an archdata member
of a device before it is registered, to do so. This is also useful
for users who have their devices created very early so they can be used
at ->reserve() time to reserve CMA memory.

The immediate use case for this is to set the private iommu archdata
member, which binds a device to its associated iommu controller.
This way, generic code will be able to attach omap devices to their
iommus, without calling any omap-specific API.

With this in hand, we can further clean the existing mainline OMAP iommu
driver and its mainline users, and focus on generic IOMMU approaches
for future users (rpmsg/remoteproc and the upcoming generic DMA API).

This patch is still considered an interim solution until DT fully materializes
for omap; at that point, this functionality will be removed as DT will
take care of creating the devices and configuring them correctly.

Tested on OMAP4 with a generic rpmsg/remoteproc that doesn't use any
omap-specific IOMMU API anymore.

Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com>
Signed-off-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 arch/arm/plat-omap/include/plat/omap_device.h |    7 +++++++
 arch/arm/plat-omap/omap_device.c              |   13 +++----------
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/arch/arm/plat-omap/include/plat/omap_device.h b/arch/arm/plat-omap/include/plat/omap_device.h
index 51423d2..05f7615 100644
--- a/arch/arm/plat-omap/include/plat/omap_device.h
+++ b/arch/arm/plat-omap/include/plat/omap_device.h
@@ -100,6 +100,13 @@ struct platform_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
 					 struct omap_device_pm_latency *pm_lats,
 					 int pm_lats_cnt, int is_early_device);
 
+struct omap_device *omap_device_alloc(struct platform_device *pdev,
+				      struct omap_hwmod **ohs, int oh_cnt,
+				      struct omap_device_pm_latency *pm_lats,
+				      int pm_lats_cnt);
+void omap_device_delete(struct omap_device *od);
+int omap_device_register(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 e8d9869..f72fafc 100644
--- a/arch/arm/plat-omap/omap_device.c
+++ b/arch/arm/plat-omap/omap_device.c
@@ -97,14 +97,7 @@
 #define USE_WAKEUP_LAT			0
 #define IGNORE_WAKEUP_LAT		1
 
-static int omap_device_register(struct platform_device *pdev);
 static int omap_early_device_register(struct platform_device *pdev);
-static struct omap_device *omap_device_alloc(struct platform_device *pdev,
-				      struct omap_hwmod **ohs, int oh_cnt,
-				      struct omap_device_pm_latency *pm_lats,
-				      int pm_lats_cnt);
-static void omap_device_delete(struct omap_device *od);
-
 
 static struct omap_device_pm_latency omap_default_latency[] = {
 	{
@@ -509,7 +502,7 @@ static int omap_device_fill_resources(struct omap_device *od,
  *
  * Returns an struct omap_device pointer or ERR_PTR() on error;
  */
-static struct omap_device *omap_device_alloc(struct platform_device *pdev,
+struct omap_device *omap_device_alloc(struct platform_device *pdev,
 					struct omap_hwmod **ohs, int oh_cnt,
 					struct omap_device_pm_latency *pm_lats,
 					int pm_lats_cnt)
@@ -591,7 +584,7 @@ oda_exit1:
 	return ERR_PTR(ret);
 }
 
-static void omap_device_delete(struct omap_device *od)
+void omap_device_delete(struct omap_device *od)
 {
 	if (!od)
 		return;
@@ -817,7 +810,7 @@ static struct dev_pm_domain omap_device_pm_domain = {
  * platform_device_register() on the underlying platform_device.
  * Returns the return value of platform_device_register().
  */
-static int omap_device_register(struct platform_device *pdev)
+int omap_device_register(struct platform_device *pdev)
 {
 	pr_debug("omap_device: %s: registering\n", pdev->name);
 

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

* [PATCH 2/3] ARM: OMAP2+: Split omap2_hsmmc_init() to properly support I2C GPIO pins
  2012-02-15 18:28 ` Tony Lindgren
@ 2012-02-15 18:28   ` Tony Lindgren
  -1 siblings, 0 replies; 66+ messages in thread
From: Tony Lindgren @ 2012-02-15 18:28 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: Russell King, linux-omap

Otherwise omap_device_build() and omap_mux related functions
can't be marked as __init when twl is build as a module.

If a board is using GPIO pins or regulators configured by an
external chip, such as TWL PMIC on I2C bus, the board must
mark those MMC controllers as deferred. Additionally both
omap_hsmmc_init() and omap_hsmmc_late_init() must be called
by the board.

For MMC controllers using internal GPIO pins for card
detect and regulators the slots don't need to be marked
deferred. In this case calling omap_hsmmc_init() is sufficient.

Note that this patch does not change the behaviour for
board-4430sdp.c board-omap4panda.c. These boards wrongly
rely on the omap_hsmmc.c init function callback to configure
the PMIC GPIO interrupt lines on external chip. If the PMIC
interrupt lines are not configured during init, they will
fail.

Reported-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 arch/arm/mach-omap2/board-2430sdp.c          |    2 
 arch/arm/mach-omap2/board-3430sdp.c          |    5 +
 arch/arm/mach-omap2/board-4430sdp.c          |    4 -
 arch/arm/mach-omap2/board-am3517evm.c        |    2 
 arch/arm/mach-omap2/board-cm-t35.c           |    6 +
 arch/arm/mach-omap2/board-devkit8000.c       |    4 +
 arch/arm/mach-omap2/board-igep0020.c         |    7 +-
 arch/arm/mach-omap2/board-ldp.c              |    2 
 arch/arm/mach-omap2/board-omap3beagle.c      |    4 +
 arch/arm/mach-omap2/board-omap3evm.c         |    5 +
 arch/arm/mach-omap2/board-omap3logic.c       |    2 
 arch/arm/mach-omap2/board-omap3pandora.c     |    6 +
 arch/arm/mach-omap2/board-omap3stalker.c     |   12 ++-
 arch/arm/mach-omap2/board-omap3touchbook.c   |    4 +
 arch/arm/mach-omap2/board-omap4panda.c       |    4 -
 arch/arm/mach-omap2/board-overo.c            |    5 +
 arch/arm/mach-omap2/board-rm680.c            |    2 
 arch/arm/mach-omap2/board-rx51-peripherals.c |    2 
 arch/arm/mach-omap2/board-zoom-peripherals.c |    6 +
 arch/arm/mach-omap2/hsmmc.c                  |  107 +++++++++++++++++++-------
 arch/arm/mach-omap2/hsmmc.h                  |   12 ++-
 21 files changed, 147 insertions(+), 56 deletions(-)

diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
index 7370983..c8bda62 100644
--- a/arch/arm/mach-omap2/board-2430sdp.c
+++ b/arch/arm/mach-omap2/board-2430sdp.c
@@ -279,7 +279,7 @@ static void __init omap_2430sdp_init(void)
 	platform_add_devices(sdp2430_devices, ARRAY_SIZE(sdp2430_devices));
 	omap_serial_init();
 	omap_sdrc_init(NULL, NULL);
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_init(mmc);
 	omap2_usbfs_init(&sdp2430_usb_config);
 
 	omap_mux_init_signal("usb0hs_stp", OMAP_PULL_ENA | OMAP_PULL_UP);
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index 383717b..da75f23 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -232,11 +232,13 @@ static struct omap2_hsmmc_info mmc[] = {
 		 */
 		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
 		.gpio_wp	= 4,
+		.deferred	= true,
 	},
 	{
 		.mmc		= 2,
 		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
 		.gpio_wp	= 7,
+		.deferred	= true,
 	},
 	{}	/* Terminator */
 };
@@ -249,7 +251,7 @@ static int sdp3430_twl_gpio_setup(struct device *dev,
 	 */
 	mmc[0].gpio_cd = gpio + 0;
 	mmc[1].gpio_cd = gpio + 1;
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_late_init(mmc);
 
 	/* gpio + 7 is "sub_lcd_en_bkl" (output/PWM1) */
 	gpio_request_one(gpio + 7, GPIOF_OUT_INIT_LOW, "sub_lcd_en_bkl");
@@ -606,6 +608,7 @@ static void __init omap_3430sdp_init(void)
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 	omap_board_config = sdp3430_config;
 	omap_board_config_size = ARRAY_SIZE(sdp3430_config);
+	omap_hsmmc_init(mmc);
 	omap3430_i2c_init();
 	omap_display_init(&sdp3430_dss_data);
 	if (omap_rev() > OMAP3430_REV_ES1_0)
diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c
index 4e90715..09ae257 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -491,9 +491,9 @@ static int __init omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers)
 {
 	struct omap2_hsmmc_info *c;
 
-	omap2_hsmmc_init(controllers);
+	omap_hsmmc_init(controllers);
 	for (c = controllers; c->mmc; c++)
-		omap4_twl6030_hsmmc_set_late_init(c->dev);
+		omap4_twl6030_hsmmc_set_late_init(&c->pdev->dev);
 
 	return 0;
 }
diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c
index 4b1cfe3..71138a1 100644
--- a/arch/arm/mach-omap2/board-am3517evm.c
+++ b/arch/arm/mach-omap2/board-am3517evm.c
@@ -504,7 +504,7 @@ static void __init am3517_evm_init(void)
 	am3517_evm_musb_init();
 
 	/* MMC init function */
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_init(mmc);
 }
 
 MACHINE_START(OMAP3517EVM, "OMAP3517/AM3517 EVM")
diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index e921e3b..60f0501 100644
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -413,7 +413,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.caps		= MMC_CAP_4_BIT_DATA,
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
-
+		.deferred	= true,
 	},
 	{
 		.mmc		= 2,
@@ -422,6 +422,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
 		.ocr_mask	= 0x00100000,	/* 3.3V */
+		.deferred	= true,
 	},
 	{}	/* Terminator */
 };
@@ -471,7 +472,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;
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_late_init(mmc);
 
 	return 0;
 }
@@ -639,6 +640,7 @@ static void __init cm_t3x_common_init(void)
 	omap_serial_init();
 	omap_sdrc_init(mt46h32m32lf6_sdrc_params,
 			     mt46h32m32lf6_sdrc_params);
+	omap_hsmmc_init(mmc);
 	cm_t35_init_i2c();
 	omap_ads7846_init(1, CM_T35_GPIO_PENDOWN, 0, NULL);
 	cm_t35_init_ethernet();
diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
index e873063..11cd2a8 100644
--- a/arch/arm/mach-omap2/board-devkit8000.c
+++ b/arch/arm/mach-omap2/board-devkit8000.c
@@ -100,6 +100,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.mmc		= 1,
 		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
 		.gpio_wp	= 29,
+		.deferred	= true,
 	},
 	{}	/* Terminator */
 };
@@ -228,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;
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_late_init(mmc);
 
 	/* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
 	gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
@@ -636,6 +637,7 @@ static void __init devkit8000_init(void)
 
 	omap_dm9000_init();
 
+	omap_hsmmc_init(mmc);
 	devkit8000_i2c_init();
 	platform_add_devices(devkit8000_devices,
 			ARRAY_SIZE(devkit8000_devices));
diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
index a59ace0..ac1de09 100644
--- a/arch/arm/mach-omap2/board-igep0020.c
+++ b/arch/arm/mach-omap2/board-igep0020.c
@@ -295,6 +295,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.caps		= MMC_CAP_4_BIT_DATA,
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
+		.deferred	= true,
 	},
 #if defined(CONFIG_LIBERTAS_SDIO) || defined(CONFIG_LIBERTAS_SDIO_MODULE)
 	{
@@ -302,6 +303,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.caps		= MMC_CAP_4_BIT_DATA,
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
+		.deferred	= true,
 	},
 #endif
 	{}      /* Terminator */
@@ -402,7 +404,7 @@ static int igep_twl_gpio_setup(struct device *dev,
 
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	mmc[0].gpio_cd = gpio + 0;
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_late_init(mmc);
 
 	/* TWL4030_GPIO_MAX + 1 == ledB (out, active low LED) */
 #if !defined(CONFIG_LEDS_GPIO) && !defined(CONFIG_LEDS_GPIO_MODULE)
@@ -639,6 +641,9 @@ static void __init igep_init(void)
 
 	/* Get IGEP2 hardware revision */
 	igep2_get_revision();
+
+	omap_hsmmc_init(mmc);
+
 	/* Register I2C busses and drivers */
 	igep_i2c_init();
 	platform_add_devices(igep_devices, ARRAY_SIZE(igep_devices));
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index 2d2a61f..b5bc9b2 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -424,7 +424,7 @@ static void __init omap_ldp_init(void)
 	board_nand_init(ldp_nand_partitions,
 		ARRAY_SIZE(ldp_nand_partitions), ZOOM_NAND_CS, 0);
 
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_init(mmc);
 	ldp_display_init();
 }
 
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 7ffcd28..78bfcd5 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -253,6 +253,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.mmc		= 1,
 		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
 		.gpio_wp	= -EINVAL,
+		.deferred	= true,
 	},
 	{}	/* Terminator */
 };
@@ -277,7 +278,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;
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_late_init(mmc);
 
 	/*
 	 * TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, XM active
@@ -521,6 +522,7 @@ static void __init omap3_beagle_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 	omap3_beagle_init_rev();
+	omap_hsmmc_init(mmc);
 	omap3_beagle_i2c_init();
 
 	gpio_buttons[0].gpio = beagle_config.usr_button_gpio;
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index c775bea..db0aa27 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -317,6 +317,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.caps		= MMC_CAP_4_BIT_DATA,
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= 63,
+		.deferred	= true,
 	},
 #ifdef CONFIG_WL12XX_PLATFORM_DATA
 	{
@@ -326,6 +327,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.gpio_wp	= -EINVAL,
 		.gpio_cd	= -EINVAL,
 		.nonremovable	= true,
+		.deferred	= true,
 	},
 #endif
 	{}	/* Terminator */
@@ -363,7 +365,7 @@ static int omap3evm_twl_gpio_setup(struct device *dev,
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	omap_mux_init_gpio(63, OMAP_PIN_INPUT);
 	mmc[0].gpio_cd = gpio + 0;
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_late_init(mmc);
 
 	/*
 	 * Most GPIOs are for USB OTG.  Some are mostly sent to
@@ -644,6 +646,7 @@ static void __init omap3_evm_init(void)
 	omap_board_config = omap3_evm_config;
 	omap_board_config_size = ARRAY_SIZE(omap3_evm_config);
 
+	omap_hsmmc_init(mmc);
 	omap3_evm_i2c_init();
 
 	omap_display_init(&omap3_evm_dss_data);
diff --git a/arch/arm/mach-omap2/board-omap3logic.c b/arch/arm/mach-omap2/board-omap3logic.c
index 4198dd0..2304ba3 100644
--- a/arch/arm/mach-omap2/board-omap3logic.c
+++ b/arch/arm/mach-omap2/board-omap3logic.c
@@ -128,7 +128,7 @@ static void __init board_mmc_init(void)
 		return;
 	}
 
-	omap2_hsmmc_init(board_mmc_info);
+	omap_hsmmc_init(board_mmc_info);
 }
 
 static struct omap_smsc911x_platform_data __initdata board_smsc911x_data = {
diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c
index 1644b73..84c83c8 100644
--- a/arch/arm/mach-omap2/board-omap3pandora.c
+++ b/arch/arm/mach-omap2/board-omap3pandora.c
@@ -273,6 +273,7 @@ static struct omap2_hsmmc_info omap3pandora_mmc[] = {
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= 126,
 		.ext_clock	= 0,
+		.deferred	= true,
 	},
 	{
 		.mmc		= 2,
@@ -281,6 +282,7 @@ static struct omap2_hsmmc_info omap3pandora_mmc[] = {
 		.gpio_wp	= 127,
 		.ext_clock	= 1,
 		.transceiver	= true,
+		.deferred	= true,
 	},
 	{
 		.mmc		= 3,
@@ -288,6 +290,7 @@ static struct omap2_hsmmc_info omap3pandora_mmc[] = {
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
 		.init_card	= pandora_wl1251_init_card,
+		.deferred	= true,
 	},
 	{}	/* Terminator */
 };
@@ -300,7 +303,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;
-	omap2_hsmmc_init(omap3pandora_mmc);
+	omap_hsmmc_late_init(omap3pandora_mmc);
 
 	/* gpio + 13 drives 32kHz buffer for wifi module */
 	gpio_32khz = gpio + 13;
@@ -580,6 +583,7 @@ static struct omap_board_mux board_mux[] __initdata = {
 static void __init omap3pandora_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+	omap_hsmmc_init(omap3pandora_mmc);
 	omap3pandora_i2c_init();
 	pandora_wl1251_init();
 	platform_add_devices(omap3pandora_devices,
diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c
index cb089a4..8eee993 100644
--- a/arch/arm/mach-omap2/board-omap3stalker.c
+++ b/arch/arm/mach-omap2/board-omap3stalker.c
@@ -209,10 +209,11 @@ static struct regulator_init_data omap3stalker_vsim = {
 
 static struct omap2_hsmmc_info mmc[] = {
 	{
-	 .mmc		= 1,
-	 .caps		= MMC_CAP_4_BIT_DATA,
-	 .gpio_cd	= -EINVAL,
-	 .gpio_wp	= 23,
+		.mmc		= 1,
+		.caps		= MMC_CAP_4_BIT_DATA,
+		.gpio_cd	= -EINVAL,
+		.gpio_wp	= 23,
+		.deferred	= true,
 	 },
 	{}			/* Terminator */
 };
@@ -284,7 +285,7 @@ omap3stalker_twl_gpio_setup(struct device *dev,
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	omap_mux_init_gpio(23, OMAP_PIN_INPUT);
 	mmc[0].gpio_cd = gpio + 0;
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_late_init(mmc);
 
 	/*
 	 * Most GPIOs are for USB OTG.  Some are mostly sent to
@@ -425,6 +426,7 @@ static void __init omap3_stalker_init(void)
 	omap_board_config = omap3_stalker_config;
 	omap_board_config_size = ARRAY_SIZE(omap3_stalker_config);
 
+	omap_hsmmc_init(mmc);
 	omap3_stalker_i2c_init();
 
 	platform_add_devices(omap3_stalker_devices,
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index a0b851a..ba9c118 100644
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -100,6 +100,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.mmc		= 1,
 		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
 		.gpio_wp	= 29,
+		.deferred	= true,
 	},
 	{}	/* Terminator */
 };
@@ -125,7 +126,7 @@ static int touchbook_twl_gpio_setup(struct device *dev,
 	}
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	mmc[0].gpio_cd = gpio + 0;
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_late_init(mmc);
 
 	/* REVISIT: need ehci-omap hooks for external VBUS
 	 * power switch and overcurrent detect
@@ -351,6 +352,7 @@ static void __init omap3_touchbook_init(void)
 
 	pm_power_off = omap3_touchbook_poweroff;
 
+	omap_hsmmc_init(mmc);
 	omap3_touchbook_i2c_init();
 	platform_add_devices(omap3_touchbook_devices,
 			ARRAY_SIZE(omap3_touchbook_devices));
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index 28fc271..bcc563c 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -245,9 +245,9 @@ static int __init omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers)
 {
 	struct omap2_hsmmc_info *c;
 
-	omap2_hsmmc_init(controllers);
+	omap_hsmmc_init(controllers);
 	for (c = controllers; c->mmc; c++)
-		omap4_twl6030_hsmmc_set_late_init(c->dev);
+		omap4_twl6030_hsmmc_set_late_init(&c->pdev->dev);
 
 	return 0;
 }
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index 52c0cef..1fc5f7a 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -301,6 +301,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.caps		= MMC_CAP_4_BIT_DATA,
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
+		.deferred	= true,
 	},
 	{
 		.mmc		= 2,
@@ -309,6 +310,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.gpio_wp	= -EINVAL,
 		.transceiver	= true,
 		.ocr_mask	= 0x00100000,	/* 3.3V */
+		.deferred	= true,
 	},
 	{}	/* Terminator */
 };
@@ -407,7 +409,7 @@ static inline void __init overo_init_keys(void) { return; }
 static int overo_twl_gpio_setup(struct device *dev,
 		unsigned gpio, unsigned ngpio)
 {
-	omap2_hsmmc_init(mmc);
+	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) */
@@ -505,6 +507,7 @@ static void __init overo_init(void)
 	int ret;
 
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+	omap_hsmmc_init(mmc);
 	overo_i2c_init();
 	omap_display_init(&overo_dss_data);
 	omap_serial_init();
diff --git a/arch/arm/mach-omap2/board-rm680.c b/arch/arm/mach-omap2/board-rm680.c
index 8678b38..2d24c98 100644
--- a/arch/arm/mach-omap2/board-rm680.c
+++ b/arch/arm/mach-omap2/board-rm680.c
@@ -120,7 +120,7 @@ static void __init rm680_peripherals_init(void)
 				ARRAY_SIZE(rm680_peripherals_devices));
 	rm680_i2c_init();
 	gpmc_onenand_init(board_onenand_data);
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_init(mmc);
 }
 
 #ifdef CONFIG_OMAP_MUX
diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
index acb4e77..0e9d89a 100644
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -1145,7 +1145,7 @@ void __init rx51_peripherals_init(void)
 
 	partition = omap_mux_get("core");
 	if (partition)
-		omap2_hsmmc_init(mmc);
+		omap_hsmmc_init(mmc);
 
 	rx51_charger_init();
 }
diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c
index c126461..82a0f7c 100644
--- a/arch/arm/mach-omap2/board-zoom-peripherals.c
+++ b/arch/arm/mach-omap2/board-zoom-peripherals.c
@@ -205,6 +205,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.caps		= MMC_CAP_4_BIT_DATA,
 		.gpio_wp	= -EINVAL,
 		.power_saving	= true,
+		.deferred	= true,
 	},
 	{
 		.name		= "internal",
@@ -214,6 +215,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.gpio_wp	= -EINVAL,
 		.nonremovable	= true,
 		.power_saving	= true,
+		.deferred	= true,
 	},
 	{
 		.name		= "wl1271",
@@ -222,6 +224,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.gpio_wp	= -EINVAL,
 		.gpio_cd	= -EINVAL,
 		.nonremovable	= true,
+		.deferred	= true,
 	},
 	{}      /* Terminator */
 };
@@ -233,7 +236,7 @@ static int zoom_twl_gpio_setup(struct device *dev,
 
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	mmc[0].gpio_cd = gpio + 0;
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_late_init(mmc);
 
 	ret = gpio_request_one(LCD_PANEL_ENABLE_GPIO, GPIOF_OUT_INIT_LOW,
 			       "lcd enable");
@@ -301,6 +304,7 @@ void __init zoom_peripherals_init(void)
 	if (ret)
 		pr_err("error setting wl12xx data: %d\n", ret);
 
+	omap_hsmmc_init(mmc);
 	omap_i2c_init();
 	platform_device_register(&omap_vwlan_device);
 	usb_musb_init(NULL);
diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
index b40c288..0f774e5 100644
--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -428,66 +428,119 @@ static int omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
 	return 0;
 }
 
+void omap_hsmmc_late_init(struct omap2_hsmmc_info *controllers)
+{
+	struct platform_device *pdev;
+	int res;
+
+	for (; controllers->mmc; controllers++) {
+		if (!controllers->deferred)
+			continue;
+
+		pdev = controllers->pdev;
+		if (!pdev)
+			continue;
+
+		res = omap_device_register(pdev);
+		if (res) {
+			pr_err("Could not late init MMC %s\n",
+			       controllers->name);
+			continue;
+		}
+	}
+}
+
 #define MAX_OMAP_MMC_HWMOD_NAME_LEN		16
 
-void omap_init_hsmmc(struct omap2_hsmmc_info *hsmmcinfo, int ctrl_nr)
+static void omap_hsmmc_init_one(struct omap2_hsmmc_info *hsmmcinfo,
+					int ctrl_nr)
 {
 	struct omap_hwmod *oh;
+	struct omap_hwmod *ohs[1];
+	struct omap_device *od;
 	struct platform_device *pdev;
 	char oh_name[MAX_OMAP_MMC_HWMOD_NAME_LEN];
 	struct omap_mmc_platform_data *mmc_data;
 	struct omap_mmc_dev_attr *mmc_dev_attr;
 	char *name;
-	int l;
+	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");
-		goto done;
+		return;
 	}
 
-	if (omap_hsmmc_pdata_init(hsmmcinfo, mmc_data) < 0) {
-		pr_err("%s fails!\n", __func__);
-		goto done;
-	}
+	res = omap_hsmmc_pdata_init(hsmmcinfo, mmc_data);
+	if (res < 0)
+		goto free_mmc;
+
 	omap_hsmmc_mux(mmc_data, (ctrl_nr - 1));
 
 	name = "omap_hsmmc";
-
-	l = snprintf(oh_name, MAX_OMAP_MMC_HWMOD_NAME_LEN,
+	res = snprintf(oh_name, MAX_OMAP_MMC_HWMOD_NAME_LEN,
 		     "mmc%d", ctrl_nr);
-	WARN(l >= MAX_OMAP_MMC_HWMOD_NAME_LEN,
+	WARN(res >= MAX_OMAP_MMC_HWMOD_NAME_LEN,
 	     "String buffer overflow in MMC%d device setup\n", ctrl_nr);
+
 	oh = omap_hwmod_lookup(oh_name);
 	if (!oh) {
 		pr_err("Could not look up %s\n", oh_name);
-		kfree(mmc_data->slots[0].name);
-		goto done;
+		goto free_name;
 	}
-
+	ohs[0] = oh;
 	if (oh->dev_attr != NULL) {
 		mmc_dev_attr = oh->dev_attr;
 		mmc_data->controller_flags = mmc_dev_attr->flags;
 	}
 
-	pdev = omap_device_build(name, ctrl_nr - 1, oh, mmc_data,
-		sizeof(struct omap_mmc_platform_data), NULL, 0, false);
-	if (IS_ERR(pdev)) {
-		WARN(1, "Can't build omap_device for %s:%s.\n", name, oh->name);
-		kfree(mmc_data->slots[0].name);
-		goto done;
+	pdev = platform_device_alloc(name, ctrl_nr - 1);
+	if (!pdev) {
+		pr_err("Could not allocate pdev for %s\n", name);
+		goto free_mmc;
 	}
-	/*
-	 * return device handle to board setup code
-	 * required to populate for regulator framework structure
-	 */
-	hsmmcinfo->dev = &pdev->dev;
+	dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id);
+
+	od = omap_device_alloc(pdev, ohs, 1, NULL, 0);
+	if (!od) {
+		pr_err("Could not allocate od for %s\n", name);
+		goto put_pdev;
+	}
+
+	res = platform_device_add_data(pdev, mmc_data,
+			      sizeof(struct omap_mmc_platform_data));
+	if (res) {
+		pr_err("Could not add pdata for %s\n", name);
+		goto put_pdev;
+	}
+
+	hsmmcinfo->pdev = pdev;
+
+	if (hsmmcinfo->deferred)
+		return;
+
+	res = omap_device_register(pdev);
+	if (res) {
+		pr_err("Could not register od for %s\n", name);
+		goto free_od;
+	}
+
+	goto free_name;
+
+free_od:
+	omap_device_delete(od);
+
+put_pdev:
+	platform_device_put(pdev);
+
+free_name:
+	kfree(mmc_data->slots[0].name);
 
-done:
+free_mmc:
 	kfree(mmc_data);
 }
 
-void omap2_hsmmc_init(struct omap2_hsmmc_info *controllers)
+void omap_hsmmc_init(struct omap2_hsmmc_info *controllers)
 {
 	u32 reg;
 
@@ -515,7 +568,7 @@ void omap2_hsmmc_init(struct omap2_hsmmc_info *controllers)
 	}
 
 	for (; controllers->mmc; controllers++)
-		omap_init_hsmmc(controllers, controllers->mmc);
+		omap_hsmmc_init_one(controllers, controllers->mmc);
 
 }
 
diff --git a/arch/arm/mach-omap2/hsmmc.h b/arch/arm/mach-omap2/hsmmc.h
index c440973..07831cc 100644
--- a/arch/arm/mach-omap2/hsmmc.h
+++ b/arch/arm/mach-omap2/hsmmc.h
@@ -21,10 +21,11 @@ struct omap2_hsmmc_info {
 	bool	no_off;		/* power_saving and power is not to go off */
 	bool	no_off_init;	/* no power off when not in MMC sleep state */
 	bool	vcc_aux_disable_is_sleep; /* Regulator off remapped to sleep */
+	bool	deferred;	/* mmc needs a deferred probe */
 	int	gpio_cd;	/* or -EINVAL */
 	int	gpio_wp;	/* or -EINVAL */
 	char	*name;		/* or NULL for default */
-	struct device *dev;	/* returned: pointer to mmc adapter */
+	struct platform_device *pdev;	/* mmc controller instance */
 	int	ocr_mask;	/* temporary HACK */
 	/* Remux (pad configuration) when powering on/off */
 	void (*remux)(struct device *dev, int slot, int power_on);
@@ -34,11 +35,16 @@ struct omap2_hsmmc_info {
 
 #if defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
 
-void omap2_hsmmc_init(struct omap2_hsmmc_info *);
+void omap_hsmmc_init(struct omap2_hsmmc_info *);
+void omap_hsmmc_late_init(struct omap2_hsmmc_info *);
 
 #else
 
-static inline void omap2_hsmmc_init(struct omap2_hsmmc_info *info)
+static inline void omap_hsmmc_init(struct omap2_hsmmc_info *info)
+{
+}
+
+static inline void omap_hsmmc_late_init(struct omap2_hsmmc_info *info)
 {
 }

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

* [PATCH 2/3] ARM: OMAP2+: Split omap2_hsmmc_init() to properly support I2C GPIO pins
@ 2012-02-15 18:28   ` Tony Lindgren
  0 siblings, 0 replies; 66+ messages in thread
From: Tony Lindgren @ 2012-02-15 18:28 UTC (permalink / raw)
  To: linux-arm-kernel

Otherwise omap_device_build() and omap_mux related functions
can't be marked as __init when twl is build as a module.

If a board is using GPIO pins or regulators configured by an
external chip, such as TWL PMIC on I2C bus, the board must
mark those MMC controllers as deferred. Additionally both
omap_hsmmc_init() and omap_hsmmc_late_init() must be called
by the board.

For MMC controllers using internal GPIO pins for card
detect and regulators the slots don't need to be marked
deferred. In this case calling omap_hsmmc_init() is sufficient.

Note that this patch does not change the behaviour for
board-4430sdp.c board-omap4panda.c. These boards wrongly
rely on the omap_hsmmc.c init function callback to configure
the PMIC GPIO interrupt lines on external chip. If the PMIC
interrupt lines are not configured during init, they will
fail.

Reported-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 arch/arm/mach-omap2/board-2430sdp.c          |    2 
 arch/arm/mach-omap2/board-3430sdp.c          |    5 +
 arch/arm/mach-omap2/board-4430sdp.c          |    4 -
 arch/arm/mach-omap2/board-am3517evm.c        |    2 
 arch/arm/mach-omap2/board-cm-t35.c           |    6 +
 arch/arm/mach-omap2/board-devkit8000.c       |    4 +
 arch/arm/mach-omap2/board-igep0020.c         |    7 +-
 arch/arm/mach-omap2/board-ldp.c              |    2 
 arch/arm/mach-omap2/board-omap3beagle.c      |    4 +
 arch/arm/mach-omap2/board-omap3evm.c         |    5 +
 arch/arm/mach-omap2/board-omap3logic.c       |    2 
 arch/arm/mach-omap2/board-omap3pandora.c     |    6 +
 arch/arm/mach-omap2/board-omap3stalker.c     |   12 ++-
 arch/arm/mach-omap2/board-omap3touchbook.c   |    4 +
 arch/arm/mach-omap2/board-omap4panda.c       |    4 -
 arch/arm/mach-omap2/board-overo.c            |    5 +
 arch/arm/mach-omap2/board-rm680.c            |    2 
 arch/arm/mach-omap2/board-rx51-peripherals.c |    2 
 arch/arm/mach-omap2/board-zoom-peripherals.c |    6 +
 arch/arm/mach-omap2/hsmmc.c                  |  107 +++++++++++++++++++-------
 arch/arm/mach-omap2/hsmmc.h                  |   12 ++-
 21 files changed, 147 insertions(+), 56 deletions(-)

diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
index 7370983..c8bda62 100644
--- a/arch/arm/mach-omap2/board-2430sdp.c
+++ b/arch/arm/mach-omap2/board-2430sdp.c
@@ -279,7 +279,7 @@ static void __init omap_2430sdp_init(void)
 	platform_add_devices(sdp2430_devices, ARRAY_SIZE(sdp2430_devices));
 	omap_serial_init();
 	omap_sdrc_init(NULL, NULL);
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_init(mmc);
 	omap2_usbfs_init(&sdp2430_usb_config);
 
 	omap_mux_init_signal("usb0hs_stp", OMAP_PULL_ENA | OMAP_PULL_UP);
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index 383717b..da75f23 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -232,11 +232,13 @@ static struct omap2_hsmmc_info mmc[] = {
 		 */
 		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
 		.gpio_wp	= 4,
+		.deferred	= true,
 	},
 	{
 		.mmc		= 2,
 		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
 		.gpio_wp	= 7,
+		.deferred	= true,
 	},
 	{}	/* Terminator */
 };
@@ -249,7 +251,7 @@ static int sdp3430_twl_gpio_setup(struct device *dev,
 	 */
 	mmc[0].gpio_cd = gpio + 0;
 	mmc[1].gpio_cd = gpio + 1;
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_late_init(mmc);
 
 	/* gpio + 7 is "sub_lcd_en_bkl" (output/PWM1) */
 	gpio_request_one(gpio + 7, GPIOF_OUT_INIT_LOW, "sub_lcd_en_bkl");
@@ -606,6 +608,7 @@ static void __init omap_3430sdp_init(void)
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 	omap_board_config = sdp3430_config;
 	omap_board_config_size = ARRAY_SIZE(sdp3430_config);
+	omap_hsmmc_init(mmc);
 	omap3430_i2c_init();
 	omap_display_init(&sdp3430_dss_data);
 	if (omap_rev() > OMAP3430_REV_ES1_0)
diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c
index 4e90715..09ae257 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -491,9 +491,9 @@ static int __init omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers)
 {
 	struct omap2_hsmmc_info *c;
 
-	omap2_hsmmc_init(controllers);
+	omap_hsmmc_init(controllers);
 	for (c = controllers; c->mmc; c++)
-		omap4_twl6030_hsmmc_set_late_init(c->dev);
+		omap4_twl6030_hsmmc_set_late_init(&c->pdev->dev);
 
 	return 0;
 }
diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c
index 4b1cfe3..71138a1 100644
--- a/arch/arm/mach-omap2/board-am3517evm.c
+++ b/arch/arm/mach-omap2/board-am3517evm.c
@@ -504,7 +504,7 @@ static void __init am3517_evm_init(void)
 	am3517_evm_musb_init();
 
 	/* MMC init function */
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_init(mmc);
 }
 
 MACHINE_START(OMAP3517EVM, "OMAP3517/AM3517 EVM")
diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index e921e3b..60f0501 100644
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -413,7 +413,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.caps		= MMC_CAP_4_BIT_DATA,
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
-
+		.deferred	= true,
 	},
 	{
 		.mmc		= 2,
@@ -422,6 +422,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
 		.ocr_mask	= 0x00100000,	/* 3.3V */
+		.deferred	= true,
 	},
 	{}	/* Terminator */
 };
@@ -471,7 +472,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;
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_late_init(mmc);
 
 	return 0;
 }
@@ -639,6 +640,7 @@ static void __init cm_t3x_common_init(void)
 	omap_serial_init();
 	omap_sdrc_init(mt46h32m32lf6_sdrc_params,
 			     mt46h32m32lf6_sdrc_params);
+	omap_hsmmc_init(mmc);
 	cm_t35_init_i2c();
 	omap_ads7846_init(1, CM_T35_GPIO_PENDOWN, 0, NULL);
 	cm_t35_init_ethernet();
diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
index e873063..11cd2a8 100644
--- a/arch/arm/mach-omap2/board-devkit8000.c
+++ b/arch/arm/mach-omap2/board-devkit8000.c
@@ -100,6 +100,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.mmc		= 1,
 		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
 		.gpio_wp	= 29,
+		.deferred	= true,
 	},
 	{}	/* Terminator */
 };
@@ -228,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;
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_late_init(mmc);
 
 	/* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
 	gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
@@ -636,6 +637,7 @@ static void __init devkit8000_init(void)
 
 	omap_dm9000_init();
 
+	omap_hsmmc_init(mmc);
 	devkit8000_i2c_init();
 	platform_add_devices(devkit8000_devices,
 			ARRAY_SIZE(devkit8000_devices));
diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
index a59ace0..ac1de09 100644
--- a/arch/arm/mach-omap2/board-igep0020.c
+++ b/arch/arm/mach-omap2/board-igep0020.c
@@ -295,6 +295,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.caps		= MMC_CAP_4_BIT_DATA,
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
+		.deferred	= true,
 	},
 #if defined(CONFIG_LIBERTAS_SDIO) || defined(CONFIG_LIBERTAS_SDIO_MODULE)
 	{
@@ -302,6 +303,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.caps		= MMC_CAP_4_BIT_DATA,
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
+		.deferred	= true,
 	},
 #endif
 	{}      /* Terminator */
@@ -402,7 +404,7 @@ static int igep_twl_gpio_setup(struct device *dev,
 
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	mmc[0].gpio_cd = gpio + 0;
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_late_init(mmc);
 
 	/* TWL4030_GPIO_MAX + 1 == ledB (out, active low LED) */
 #if !defined(CONFIG_LEDS_GPIO) && !defined(CONFIG_LEDS_GPIO_MODULE)
@@ -639,6 +641,9 @@ static void __init igep_init(void)
 
 	/* Get IGEP2 hardware revision */
 	igep2_get_revision();
+
+	omap_hsmmc_init(mmc);
+
 	/* Register I2C busses and drivers */
 	igep_i2c_init();
 	platform_add_devices(igep_devices, ARRAY_SIZE(igep_devices));
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index 2d2a61f..b5bc9b2 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -424,7 +424,7 @@ static void __init omap_ldp_init(void)
 	board_nand_init(ldp_nand_partitions,
 		ARRAY_SIZE(ldp_nand_partitions), ZOOM_NAND_CS, 0);
 
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_init(mmc);
 	ldp_display_init();
 }
 
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 7ffcd28..78bfcd5 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -253,6 +253,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.mmc		= 1,
 		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
 		.gpio_wp	= -EINVAL,
+		.deferred	= true,
 	},
 	{}	/* Terminator */
 };
@@ -277,7 +278,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;
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_late_init(mmc);
 
 	/*
 	 * TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, XM active
@@ -521,6 +522,7 @@ static void __init omap3_beagle_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 	omap3_beagle_init_rev();
+	omap_hsmmc_init(mmc);
 	omap3_beagle_i2c_init();
 
 	gpio_buttons[0].gpio = beagle_config.usr_button_gpio;
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index c775bea..db0aa27 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -317,6 +317,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.caps		= MMC_CAP_4_BIT_DATA,
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= 63,
+		.deferred	= true,
 	},
 #ifdef CONFIG_WL12XX_PLATFORM_DATA
 	{
@@ -326,6 +327,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.gpio_wp	= -EINVAL,
 		.gpio_cd	= -EINVAL,
 		.nonremovable	= true,
+		.deferred	= true,
 	},
 #endif
 	{}	/* Terminator */
@@ -363,7 +365,7 @@ static int omap3evm_twl_gpio_setup(struct device *dev,
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	omap_mux_init_gpio(63, OMAP_PIN_INPUT);
 	mmc[0].gpio_cd = gpio + 0;
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_late_init(mmc);
 
 	/*
 	 * Most GPIOs are for USB OTG.  Some are mostly sent to
@@ -644,6 +646,7 @@ static void __init omap3_evm_init(void)
 	omap_board_config = omap3_evm_config;
 	omap_board_config_size = ARRAY_SIZE(omap3_evm_config);
 
+	omap_hsmmc_init(mmc);
 	omap3_evm_i2c_init();
 
 	omap_display_init(&omap3_evm_dss_data);
diff --git a/arch/arm/mach-omap2/board-omap3logic.c b/arch/arm/mach-omap2/board-omap3logic.c
index 4198dd0..2304ba3 100644
--- a/arch/arm/mach-omap2/board-omap3logic.c
+++ b/arch/arm/mach-omap2/board-omap3logic.c
@@ -128,7 +128,7 @@ static void __init board_mmc_init(void)
 		return;
 	}
 
-	omap2_hsmmc_init(board_mmc_info);
+	omap_hsmmc_init(board_mmc_info);
 }
 
 static struct omap_smsc911x_platform_data __initdata board_smsc911x_data = {
diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c
index 1644b73..84c83c8 100644
--- a/arch/arm/mach-omap2/board-omap3pandora.c
+++ b/arch/arm/mach-omap2/board-omap3pandora.c
@@ -273,6 +273,7 @@ static struct omap2_hsmmc_info omap3pandora_mmc[] = {
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= 126,
 		.ext_clock	= 0,
+		.deferred	= true,
 	},
 	{
 		.mmc		= 2,
@@ -281,6 +282,7 @@ static struct omap2_hsmmc_info omap3pandora_mmc[] = {
 		.gpio_wp	= 127,
 		.ext_clock	= 1,
 		.transceiver	= true,
+		.deferred	= true,
 	},
 	{
 		.mmc		= 3,
@@ -288,6 +290,7 @@ static struct omap2_hsmmc_info omap3pandora_mmc[] = {
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
 		.init_card	= pandora_wl1251_init_card,
+		.deferred	= true,
 	},
 	{}	/* Terminator */
 };
@@ -300,7 +303,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;
-	omap2_hsmmc_init(omap3pandora_mmc);
+	omap_hsmmc_late_init(omap3pandora_mmc);
 
 	/* gpio + 13 drives 32kHz buffer for wifi module */
 	gpio_32khz = gpio + 13;
@@ -580,6 +583,7 @@ static struct omap_board_mux board_mux[] __initdata = {
 static void __init omap3pandora_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+	omap_hsmmc_init(omap3pandora_mmc);
 	omap3pandora_i2c_init();
 	pandora_wl1251_init();
 	platform_add_devices(omap3pandora_devices,
diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c
index cb089a4..8eee993 100644
--- a/arch/arm/mach-omap2/board-omap3stalker.c
+++ b/arch/arm/mach-omap2/board-omap3stalker.c
@@ -209,10 +209,11 @@ static struct regulator_init_data omap3stalker_vsim = {
 
 static struct omap2_hsmmc_info mmc[] = {
 	{
-	 .mmc		= 1,
-	 .caps		= MMC_CAP_4_BIT_DATA,
-	 .gpio_cd	= -EINVAL,
-	 .gpio_wp	= 23,
+		.mmc		= 1,
+		.caps		= MMC_CAP_4_BIT_DATA,
+		.gpio_cd	= -EINVAL,
+		.gpio_wp	= 23,
+		.deferred	= true,
 	 },
 	{}			/* Terminator */
 };
@@ -284,7 +285,7 @@ omap3stalker_twl_gpio_setup(struct device *dev,
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	omap_mux_init_gpio(23, OMAP_PIN_INPUT);
 	mmc[0].gpio_cd = gpio + 0;
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_late_init(mmc);
 
 	/*
 	 * Most GPIOs are for USB OTG.  Some are mostly sent to
@@ -425,6 +426,7 @@ static void __init omap3_stalker_init(void)
 	omap_board_config = omap3_stalker_config;
 	omap_board_config_size = ARRAY_SIZE(omap3_stalker_config);
 
+	omap_hsmmc_init(mmc);
 	omap3_stalker_i2c_init();
 
 	platform_add_devices(omap3_stalker_devices,
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index a0b851a..ba9c118 100644
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -100,6 +100,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.mmc		= 1,
 		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
 		.gpio_wp	= 29,
+		.deferred	= true,
 	},
 	{}	/* Terminator */
 };
@@ -125,7 +126,7 @@ static int touchbook_twl_gpio_setup(struct device *dev,
 	}
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	mmc[0].gpio_cd = gpio + 0;
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_late_init(mmc);
 
 	/* REVISIT: need ehci-omap hooks for external VBUS
 	 * power switch and overcurrent detect
@@ -351,6 +352,7 @@ static void __init omap3_touchbook_init(void)
 
 	pm_power_off = omap3_touchbook_poweroff;
 
+	omap_hsmmc_init(mmc);
 	omap3_touchbook_i2c_init();
 	platform_add_devices(omap3_touchbook_devices,
 			ARRAY_SIZE(omap3_touchbook_devices));
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index 28fc271..bcc563c 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -245,9 +245,9 @@ static int __init omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers)
 {
 	struct omap2_hsmmc_info *c;
 
-	omap2_hsmmc_init(controllers);
+	omap_hsmmc_init(controllers);
 	for (c = controllers; c->mmc; c++)
-		omap4_twl6030_hsmmc_set_late_init(c->dev);
+		omap4_twl6030_hsmmc_set_late_init(&c->pdev->dev);
 
 	return 0;
 }
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index 52c0cef..1fc5f7a 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -301,6 +301,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.caps		= MMC_CAP_4_BIT_DATA,
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
+		.deferred	= true,
 	},
 	{
 		.mmc		= 2,
@@ -309,6 +310,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.gpio_wp	= -EINVAL,
 		.transceiver	= true,
 		.ocr_mask	= 0x00100000,	/* 3.3V */
+		.deferred	= true,
 	},
 	{}	/* Terminator */
 };
@@ -407,7 +409,7 @@ static inline void __init overo_init_keys(void) { return; }
 static int overo_twl_gpio_setup(struct device *dev,
 		unsigned gpio, unsigned ngpio)
 {
-	omap2_hsmmc_init(mmc);
+	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) */
@@ -505,6 +507,7 @@ static void __init overo_init(void)
 	int ret;
 
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+	omap_hsmmc_init(mmc);
 	overo_i2c_init();
 	omap_display_init(&overo_dss_data);
 	omap_serial_init();
diff --git a/arch/arm/mach-omap2/board-rm680.c b/arch/arm/mach-omap2/board-rm680.c
index 8678b38..2d24c98 100644
--- a/arch/arm/mach-omap2/board-rm680.c
+++ b/arch/arm/mach-omap2/board-rm680.c
@@ -120,7 +120,7 @@ static void __init rm680_peripherals_init(void)
 				ARRAY_SIZE(rm680_peripherals_devices));
 	rm680_i2c_init();
 	gpmc_onenand_init(board_onenand_data);
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_init(mmc);
 }
 
 #ifdef CONFIG_OMAP_MUX
diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
index acb4e77..0e9d89a 100644
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -1145,7 +1145,7 @@ void __init rx51_peripherals_init(void)
 
 	partition = omap_mux_get("core");
 	if (partition)
-		omap2_hsmmc_init(mmc);
+		omap_hsmmc_init(mmc);
 
 	rx51_charger_init();
 }
diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c
index c126461..82a0f7c 100644
--- a/arch/arm/mach-omap2/board-zoom-peripherals.c
+++ b/arch/arm/mach-omap2/board-zoom-peripherals.c
@@ -205,6 +205,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.caps		= MMC_CAP_4_BIT_DATA,
 		.gpio_wp	= -EINVAL,
 		.power_saving	= true,
+		.deferred	= true,
 	},
 	{
 		.name		= "internal",
@@ -214,6 +215,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.gpio_wp	= -EINVAL,
 		.nonremovable	= true,
 		.power_saving	= true,
+		.deferred	= true,
 	},
 	{
 		.name		= "wl1271",
@@ -222,6 +224,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.gpio_wp	= -EINVAL,
 		.gpio_cd	= -EINVAL,
 		.nonremovable	= true,
+		.deferred	= true,
 	},
 	{}      /* Terminator */
 };
@@ -233,7 +236,7 @@ static int zoom_twl_gpio_setup(struct device *dev,
 
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	mmc[0].gpio_cd = gpio + 0;
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_late_init(mmc);
 
 	ret = gpio_request_one(LCD_PANEL_ENABLE_GPIO, GPIOF_OUT_INIT_LOW,
 			       "lcd enable");
@@ -301,6 +304,7 @@ void __init zoom_peripherals_init(void)
 	if (ret)
 		pr_err("error setting wl12xx data: %d\n", ret);
 
+	omap_hsmmc_init(mmc);
 	omap_i2c_init();
 	platform_device_register(&omap_vwlan_device);
 	usb_musb_init(NULL);
diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
index b40c288..0f774e5 100644
--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -428,66 +428,119 @@ static int omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
 	return 0;
 }
 
+void omap_hsmmc_late_init(struct omap2_hsmmc_info *controllers)
+{
+	struct platform_device *pdev;
+	int res;
+
+	for (; controllers->mmc; controllers++) {
+		if (!controllers->deferred)
+			continue;
+
+		pdev = controllers->pdev;
+		if (!pdev)
+			continue;
+
+		res = omap_device_register(pdev);
+		if (res) {
+			pr_err("Could not late init MMC %s\n",
+			       controllers->name);
+			continue;
+		}
+	}
+}
+
 #define MAX_OMAP_MMC_HWMOD_NAME_LEN		16
 
-void omap_init_hsmmc(struct omap2_hsmmc_info *hsmmcinfo, int ctrl_nr)
+static void omap_hsmmc_init_one(struct omap2_hsmmc_info *hsmmcinfo,
+					int ctrl_nr)
 {
 	struct omap_hwmod *oh;
+	struct omap_hwmod *ohs[1];
+	struct omap_device *od;
 	struct platform_device *pdev;
 	char oh_name[MAX_OMAP_MMC_HWMOD_NAME_LEN];
 	struct omap_mmc_platform_data *mmc_data;
 	struct omap_mmc_dev_attr *mmc_dev_attr;
 	char *name;
-	int l;
+	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");
-		goto done;
+		return;
 	}
 
-	if (omap_hsmmc_pdata_init(hsmmcinfo, mmc_data) < 0) {
-		pr_err("%s fails!\n", __func__);
-		goto done;
-	}
+	res = omap_hsmmc_pdata_init(hsmmcinfo, mmc_data);
+	if (res < 0)
+		goto free_mmc;
+
 	omap_hsmmc_mux(mmc_data, (ctrl_nr - 1));
 
 	name = "omap_hsmmc";
-
-	l = snprintf(oh_name, MAX_OMAP_MMC_HWMOD_NAME_LEN,
+	res = snprintf(oh_name, MAX_OMAP_MMC_HWMOD_NAME_LEN,
 		     "mmc%d", ctrl_nr);
-	WARN(l >= MAX_OMAP_MMC_HWMOD_NAME_LEN,
+	WARN(res >= MAX_OMAP_MMC_HWMOD_NAME_LEN,
 	     "String buffer overflow in MMC%d device setup\n", ctrl_nr);
+
 	oh = omap_hwmod_lookup(oh_name);
 	if (!oh) {
 		pr_err("Could not look up %s\n", oh_name);
-		kfree(mmc_data->slots[0].name);
-		goto done;
+		goto free_name;
 	}
-
+	ohs[0] = oh;
 	if (oh->dev_attr != NULL) {
 		mmc_dev_attr = oh->dev_attr;
 		mmc_data->controller_flags = mmc_dev_attr->flags;
 	}
 
-	pdev = omap_device_build(name, ctrl_nr - 1, oh, mmc_data,
-		sizeof(struct omap_mmc_platform_data), NULL, 0, false);
-	if (IS_ERR(pdev)) {
-		WARN(1, "Can't build omap_device for %s:%s.\n", name, oh->name);
-		kfree(mmc_data->slots[0].name);
-		goto done;
+	pdev = platform_device_alloc(name, ctrl_nr - 1);
+	if (!pdev) {
+		pr_err("Could not allocate pdev for %s\n", name);
+		goto free_mmc;
 	}
-	/*
-	 * return device handle to board setup code
-	 * required to populate for regulator framework structure
-	 */
-	hsmmcinfo->dev = &pdev->dev;
+	dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id);
+
+	od = omap_device_alloc(pdev, ohs, 1, NULL, 0);
+	if (!od) {
+		pr_err("Could not allocate od for %s\n", name);
+		goto put_pdev;
+	}
+
+	res = platform_device_add_data(pdev, mmc_data,
+			      sizeof(struct omap_mmc_platform_data));
+	if (res) {
+		pr_err("Could not add pdata for %s\n", name);
+		goto put_pdev;
+	}
+
+	hsmmcinfo->pdev = pdev;
+
+	if (hsmmcinfo->deferred)
+		return;
+
+	res = omap_device_register(pdev);
+	if (res) {
+		pr_err("Could not register od for %s\n", name);
+		goto free_od;
+	}
+
+	goto free_name;
+
+free_od:
+	omap_device_delete(od);
+
+put_pdev:
+	platform_device_put(pdev);
+
+free_name:
+	kfree(mmc_data->slots[0].name);
 
-done:
+free_mmc:
 	kfree(mmc_data);
 }
 
-void omap2_hsmmc_init(struct omap2_hsmmc_info *controllers)
+void omap_hsmmc_init(struct omap2_hsmmc_info *controllers)
 {
 	u32 reg;
 
@@ -515,7 +568,7 @@ void omap2_hsmmc_init(struct omap2_hsmmc_info *controllers)
 	}
 
 	for (; controllers->mmc; controllers++)
-		omap_init_hsmmc(controllers, controllers->mmc);
+		omap_hsmmc_init_one(controllers, controllers->mmc);
 
 }
 
diff --git a/arch/arm/mach-omap2/hsmmc.h b/arch/arm/mach-omap2/hsmmc.h
index c440973..07831cc 100644
--- a/arch/arm/mach-omap2/hsmmc.h
+++ b/arch/arm/mach-omap2/hsmmc.h
@@ -21,10 +21,11 @@ struct omap2_hsmmc_info {
 	bool	no_off;		/* power_saving and power is not to go off */
 	bool	no_off_init;	/* no power off when not in MMC sleep state */
 	bool	vcc_aux_disable_is_sleep; /* Regulator off remapped to sleep */
+	bool	deferred;	/* mmc needs a deferred probe */
 	int	gpio_cd;	/* or -EINVAL */
 	int	gpio_wp;	/* or -EINVAL */
 	char	*name;		/* or NULL for default */
-	struct device *dev;	/* returned: pointer to mmc adapter */
+	struct platform_device *pdev;	/* mmc controller instance */
 	int	ocr_mask;	/* temporary HACK */
 	/* Remux (pad configuration) when powering on/off */
 	void (*remux)(struct device *dev, int slot, int power_on);
@@ -34,11 +35,16 @@ struct omap2_hsmmc_info {
 
 #if defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
 
-void omap2_hsmmc_init(struct omap2_hsmmc_info *);
+void omap_hsmmc_init(struct omap2_hsmmc_info *);
+void omap_hsmmc_late_init(struct omap2_hsmmc_info *);
 
 #else
 
-static inline void omap2_hsmmc_init(struct omap2_hsmmc_info *info)
+static inline void omap_hsmmc_init(struct omap2_hsmmc_info *info)
+{
+}
+
+static inline void omap_hsmmc_late_init(struct omap2_hsmmc_info *info)
 {
 }
 

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

* [PATCH 3/3] ARM: OMAP2+: Mark omap_hsmmc_init and omap_mux related functions as __init
  2012-02-15 18:28 ` Tony Lindgren
@ 2012-02-15 18:28   ` Tony Lindgren
  -1 siblings, 0 replies; 66+ messages in thread
From: Tony Lindgren @ 2012-02-15 18:28 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: Russell King, linux-omap

Now that omap hsmmc init is split into two functions, it's safe
to mark omap_hsmmc_init and omap_mux related functions to __init.

This basically reverts the following fixes for the case where
TWL was compiled as a module:

e3958f (ARM: omap: fix section mismatch error for omap_4430sdp_display_init())
27d8d3 (ARM: omap: fix section mismatch warning in mux.c)
d5de63 (ARM: omap: preemptively fix section mismatch in omap4_sdp4430_wifi_mux_init())
e3958f (ARM: omap: fix section mismatch error for omap_4430sdp_display_init())
a98f77 (ARM: omap: fix section mismatch warning for sdp3430_twl_gpio_setup())
8930b4 (ARM: omap: fix section mismatch warnings in mux.c caused by hsmmc.c)

Additionally it fixes up the remaining section warnings for
all callers of omap_mux functions.

Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 arch/arm/mach-omap2/board-4430sdp.c        |    2 +-
 arch/arm/mach-omap2/board-flash.c          |    2 +-
 arch/arm/mach-omap2/board-omap3beagle.c    |    6 ++++--
 arch/arm/mach-omap2/board-omap3evm.c       |    3 ++-
 arch/arm/mach-omap2/board-omap3stalker.c   |    3 ++-
 arch/arm/mach-omap2/board-omap3touchbook.c |   13 +++++++------
 arch/arm/mach-omap2/board-omap4panda.c     |    2 +-
 arch/arm/mach-omap2/display.c              |    8 ++++----
 arch/arm/mach-omap2/hsmmc.c                |    6 +++---
 arch/arm/mach-omap2/mux.c                  |   22 +++++++++++-----------
 10 files changed, 36 insertions(+), 31 deletions(-)

diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c
index 09ae257..ece9e3a 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -851,7 +851,7 @@ static struct omap_board_mux board_mux[] __initdata = {
 #define board_mux	NULL
  #endif
 
-static void __init omap4_sdp4430_wifi_mux_init(void)
+static void omap4_sdp4430_wifi_mux_init(void)
 {
 	omap_mux_init_gpio(GPIO_WIFI_IRQ, OMAP_PIN_INPUT |
 				OMAP_PIN_OFF_WAKEUPENABLE);
diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c
index 30a6f52..0349fd2 100644
--- a/arch/arm/mach-omap2/board-flash.c
+++ b/arch/arm/mach-omap2/board-flash.c
@@ -189,7 +189,7 @@ unmap:
  *
  * @return - void.
  */
-void board_flash_init(struct flash_partitions partition_info[],
+void __init board_flash_init(struct flash_partitions partition_info[],
 			char chip_sel_board[][GPMC_CS_NUM], int nand_type)
 {
 	u8		cs = 0;
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 78bfcd5..7be8d65 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -273,8 +273,6 @@ static int beagle_twl_gpio_setup(struct device *dev,
 {
 	int r;
 
-	if (beagle_config.mmc1_gpio_wp != -EINVAL)
-		omap_mux_init_gpio(beagle_config.mmc1_gpio_wp, OMAP_PIN_INPUT);
 	mmc[0].gpio_wp = beagle_config.mmc1_gpio_wp;
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	mmc[0].gpio_cd = gpio + 0;
@@ -522,7 +520,11 @@ static void __init omap3_beagle_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 	omap3_beagle_init_rev();
+
+	if (beagle_config.mmc1_gpio_wp != -EINVAL)
+		omap_mux_init_gpio(beagle_config.mmc1_gpio_wp, OMAP_PIN_INPUT);
 	omap_hsmmc_init(mmc);
+
 	omap3_beagle_i2c_init();
 
 	gpio_buttons[0].gpio = beagle_config.usr_button_gpio;
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index db0aa27..0f9a983 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -363,7 +363,6 @@ static int omap3evm_twl_gpio_setup(struct device *dev,
 	int r, lcd_bl_en;
 
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
-	omap_mux_init_gpio(63, OMAP_PIN_INPUT);
 	mmc[0].gpio_cd = gpio + 0;
 	omap_hsmmc_late_init(mmc);
 
@@ -646,7 +645,9 @@ static void __init omap3_evm_init(void)
 	omap_board_config = omap3_evm_config;
 	omap_board_config_size = ARRAY_SIZE(omap3_evm_config);
 
+	omap_mux_init_gpio(63, OMAP_PIN_INPUT);
 	omap_hsmmc_init(mmc);
+
 	omap3_evm_i2c_init();
 
 	omap_display_init(&omap3_evm_dss_data);
diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c
index 8eee993..6410043 100644
--- a/arch/arm/mach-omap2/board-omap3stalker.c
+++ b/arch/arm/mach-omap2/board-omap3stalker.c
@@ -283,7 +283,6 @@ omap3stalker_twl_gpio_setup(struct device *dev,
 			    unsigned gpio, unsigned ngpio)
 {
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
-	omap_mux_init_gpio(23, OMAP_PIN_INPUT);
 	mmc[0].gpio_cd = gpio + 0;
 	omap_hsmmc_late_init(mmc);
 
@@ -426,7 +425,9 @@ static void __init omap3_stalker_init(void)
 	omap_board_config = omap3_stalker_config;
 	omap_board_config_size = ARRAY_SIZE(omap3_stalker_config);
 
+	omap_mux_init_gpio(23, OMAP_PIN_INPUT);
 	omap_hsmmc_init(mmc);
+
 	omap3_stalker_i2c_init();
 
 	platform_add_devices(omap3_stalker_devices,
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index ba9c118..8842e04 100644
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -118,12 +118,6 @@ static struct gpio_led gpio_leds[];
 static int touchbook_twl_gpio_setup(struct device *dev,
 		unsigned gpio, unsigned ngpio)
 {
-	if (system_rev >= 0x20 && system_rev <= 0x34301000) {
-		omap_mux_init_gpio(23, OMAP_PIN_INPUT);
-		mmc[0].gpio_wp = 23;
-	} else {
-		omap_mux_init_gpio(29, OMAP_PIN_INPUT);
-	}
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	mmc[0].gpio_cd = gpio + 0;
 	omap_hsmmc_late_init(mmc);
@@ -352,7 +346,14 @@ static void __init omap3_touchbook_init(void)
 
 	pm_power_off = omap3_touchbook_poweroff;
 
+	if (system_rev >= 0x20 && system_rev <= 0x34301000) {
+		omap_mux_init_gpio(23, OMAP_PIN_INPUT);
+		mmc[0].gpio_wp = 23;
+	} else {
+		omap_mux_init_gpio(29, OMAP_PIN_INPUT);
+	}
 	omap_hsmmc_init(mmc);
+
 	omap3_touchbook_i2c_init();
 	platform_add_devices(omap3_touchbook_devices,
 			ARRAY_SIZE(omap3_touchbook_devices));
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index bcc563c..7ca7a5c 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -461,7 +461,7 @@ static struct omap_dss_board_info omap4_panda_dss_data = {
 	.default_device	= &omap4_panda_dvi_device,
 };
 
-void omap4_panda_display_init(void)
+void __init omap4_panda_display_init(void)
 {
 	int r;
 
diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
index 3677b1f..62e133c 100644
--- a/arch/arm/mach-omap2/display.c
+++ b/arch/arm/mach-omap2/display.c
@@ -124,7 +124,7 @@ static void omap4_hdmi_mux_pads(enum omap_hdmi_flags flags)
 	}
 }
 
-static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
+static int __init omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
 {
 	u32 enable_mask, enable_shift;
 	u32 pipd_mask, pipd_shift;
@@ -157,7 +157,7 @@ static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
 	return 0;
 }
 
-int omap_hdmi_init(enum omap_hdmi_flags flags)
+int __init omap_hdmi_init(enum omap_hdmi_flags flags)
 {
 	if (cpu_is_omap44xx())
 		omap4_hdmi_mux_pads(flags);
@@ -165,7 +165,7 @@ int omap_hdmi_init(enum omap_hdmi_flags flags)
 	return 0;
 }
 
-static int omap_dsi_enable_pads(int dsi_id, unsigned lane_mask)
+static int __init omap_dsi_enable_pads(int dsi_id, unsigned lane_mask)
 {
 	if (cpu_is_omap44xx())
 		return omap4_dsi_mux_pads(dsi_id, lane_mask);
@@ -173,7 +173,7 @@ static int omap_dsi_enable_pads(int dsi_id, unsigned lane_mask)
 	return 0;
 }
 
-static void omap_dsi_disable_pads(int dsi_id, unsigned lane_mask)
+static void __init omap_dsi_disable_pads(int dsi_id, unsigned lane_mask)
 {
 	if (cpu_is_omap44xx())
 		omap4_dsi_mux_pads(dsi_id, 0);
diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
index 0f774e5..59c3ee4 100644
--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -293,8 +293,8 @@ static inline void omap_hsmmc_mux(struct omap_mmc_platform_data *mmc_controller,
 	}
 }
 
-static int omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
-				 struct omap_mmc_platform_data *mmc)
+static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
+					struct omap_mmc_platform_data *mmc)
 {
 	char *hc_name;
 
@@ -540,7 +540,7 @@ free_mmc:
 	kfree(mmc_data);
 }
 
-void omap_hsmmc_init(struct omap2_hsmmc_info *controllers)
+void __init omap_hsmmc_init(struct omap2_hsmmc_info *controllers)
 {
 	u32 reg;
 
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index fb8bc9f..e1cc75d 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -100,8 +100,8 @@ void omap_mux_write_array(struct omap_mux_partition *partition,
 
 static char *omap_mux_options;
 
-static int _omap_mux_init_gpio(struct omap_mux_partition *partition,
-			       int gpio, int val)
+static int __init _omap_mux_init_gpio(struct omap_mux_partition *partition,
+				      int gpio, int val)
 {
 	struct omap_mux_entry *e;
 	struct omap_mux *gpio_mux = NULL;
@@ -145,7 +145,7 @@ static int _omap_mux_init_gpio(struct omap_mux_partition *partition,
 	return 0;
 }
 
-int omap_mux_init_gpio(int gpio, int val)
+int __init omap_mux_init_gpio(int gpio, int val)
 {
 	struct omap_mux_partition *partition;
 	int ret;
@@ -159,9 +159,9 @@ int omap_mux_init_gpio(int gpio, int val)
 	return -ENODEV;
 }
 
-static int _omap_mux_get_by_name(struct omap_mux_partition *partition,
-				 const char *muxname,
-				 struct omap_mux **found_mux)
+static int __init _omap_mux_get_by_name(struct omap_mux_partition *partition,
+					const char *muxname,
+					struct omap_mux **found_mux)
 {
 	struct omap_mux *mux = NULL;
 	struct omap_mux_entry *e;
@@ -240,7 +240,7 @@ omap_mux_get_by_name(const char *muxname,
 	return -ENODEV;
 }
 
-int omap_mux_init_signal(const char *muxname, int val)
+int __init omap_mux_init_signal(const char *muxname, int val)
 {
 	struct omap_mux_partition *partition = NULL;
 	struct omap_mux *mux = NULL;
@@ -1094,8 +1094,8 @@ static void omap_mux_init_package(struct omap_mux *superset,
 		omap_mux_package_init_balls(package_balls, superset);
 }
 
-static void __init omap_mux_init_signals(struct omap_mux_partition *partition,
-					 struct omap_board_mux *board_mux)
+static void omap_mux_init_signals(struct omap_mux_partition *partition,
+				  struct omap_board_mux *board_mux)
 {
 	omap_mux_set_cmdline_signals();
 	omap_mux_write_array(partition, board_mux);
@@ -1109,8 +1109,8 @@ static void omap_mux_init_package(struct omap_mux *superset,
 {
 }
 
-static void __init omap_mux_init_signals(struct omap_mux_partition *partition,
-					 struct omap_board_mux *board_mux)
+static void omap_mux_init_signals(struct omap_mux_partition *partition,
+				  struct omap_board_mux *board_mux)
 {
 }
 


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

* [PATCH 3/3] ARM: OMAP2+: Mark omap_hsmmc_init and omap_mux related functions as __init
@ 2012-02-15 18:28   ` Tony Lindgren
  0 siblings, 0 replies; 66+ messages in thread
From: Tony Lindgren @ 2012-02-15 18:28 UTC (permalink / raw)
  To: linux-arm-kernel

Now that omap hsmmc init is split into two functions, it's safe
to mark omap_hsmmc_init and omap_mux related functions to __init.

This basically reverts the following fixes for the case where
TWL was compiled as a module:

e3958f (ARM: omap: fix section mismatch error for omap_4430sdp_display_init())
27d8d3 (ARM: omap: fix section mismatch warning in mux.c)
d5de63 (ARM: omap: preemptively fix section mismatch in omap4_sdp4430_wifi_mux_init())
e3958f (ARM: omap: fix section mismatch error for omap_4430sdp_display_init())
a98f77 (ARM: omap: fix section mismatch warning for sdp3430_twl_gpio_setup())
8930b4 (ARM: omap: fix section mismatch warnings in mux.c caused by hsmmc.c)

Additionally it fixes up the remaining section warnings for
all callers of omap_mux functions.

Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 arch/arm/mach-omap2/board-4430sdp.c        |    2 +-
 arch/arm/mach-omap2/board-flash.c          |    2 +-
 arch/arm/mach-omap2/board-omap3beagle.c    |    6 ++++--
 arch/arm/mach-omap2/board-omap3evm.c       |    3 ++-
 arch/arm/mach-omap2/board-omap3stalker.c   |    3 ++-
 arch/arm/mach-omap2/board-omap3touchbook.c |   13 +++++++------
 arch/arm/mach-omap2/board-omap4panda.c     |    2 +-
 arch/arm/mach-omap2/display.c              |    8 ++++----
 arch/arm/mach-omap2/hsmmc.c                |    6 +++---
 arch/arm/mach-omap2/mux.c                  |   22 +++++++++++-----------
 10 files changed, 36 insertions(+), 31 deletions(-)

diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c
index 09ae257..ece9e3a 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -851,7 +851,7 @@ static struct omap_board_mux board_mux[] __initdata = {
 #define board_mux	NULL
  #endif
 
-static void __init omap4_sdp4430_wifi_mux_init(void)
+static void omap4_sdp4430_wifi_mux_init(void)
 {
 	omap_mux_init_gpio(GPIO_WIFI_IRQ, OMAP_PIN_INPUT |
 				OMAP_PIN_OFF_WAKEUPENABLE);
diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c
index 30a6f52..0349fd2 100644
--- a/arch/arm/mach-omap2/board-flash.c
+++ b/arch/arm/mach-omap2/board-flash.c
@@ -189,7 +189,7 @@ unmap:
  *
  * @return - void.
  */
-void board_flash_init(struct flash_partitions partition_info[],
+void __init board_flash_init(struct flash_partitions partition_info[],
 			char chip_sel_board[][GPMC_CS_NUM], int nand_type)
 {
 	u8		cs = 0;
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 78bfcd5..7be8d65 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -273,8 +273,6 @@ static int beagle_twl_gpio_setup(struct device *dev,
 {
 	int r;
 
-	if (beagle_config.mmc1_gpio_wp != -EINVAL)
-		omap_mux_init_gpio(beagle_config.mmc1_gpio_wp, OMAP_PIN_INPUT);
 	mmc[0].gpio_wp = beagle_config.mmc1_gpio_wp;
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	mmc[0].gpio_cd = gpio + 0;
@@ -522,7 +520,11 @@ static void __init omap3_beagle_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 	omap3_beagle_init_rev();
+
+	if (beagle_config.mmc1_gpio_wp != -EINVAL)
+		omap_mux_init_gpio(beagle_config.mmc1_gpio_wp, OMAP_PIN_INPUT);
 	omap_hsmmc_init(mmc);
+
 	omap3_beagle_i2c_init();
 
 	gpio_buttons[0].gpio = beagle_config.usr_button_gpio;
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index db0aa27..0f9a983 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -363,7 +363,6 @@ static int omap3evm_twl_gpio_setup(struct device *dev,
 	int r, lcd_bl_en;
 
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
-	omap_mux_init_gpio(63, OMAP_PIN_INPUT);
 	mmc[0].gpio_cd = gpio + 0;
 	omap_hsmmc_late_init(mmc);
 
@@ -646,7 +645,9 @@ static void __init omap3_evm_init(void)
 	omap_board_config = omap3_evm_config;
 	omap_board_config_size = ARRAY_SIZE(omap3_evm_config);
 
+	omap_mux_init_gpio(63, OMAP_PIN_INPUT);
 	omap_hsmmc_init(mmc);
+
 	omap3_evm_i2c_init();
 
 	omap_display_init(&omap3_evm_dss_data);
diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c
index 8eee993..6410043 100644
--- a/arch/arm/mach-omap2/board-omap3stalker.c
+++ b/arch/arm/mach-omap2/board-omap3stalker.c
@@ -283,7 +283,6 @@ omap3stalker_twl_gpio_setup(struct device *dev,
 			    unsigned gpio, unsigned ngpio)
 {
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
-	omap_mux_init_gpio(23, OMAP_PIN_INPUT);
 	mmc[0].gpio_cd = gpio + 0;
 	omap_hsmmc_late_init(mmc);
 
@@ -426,7 +425,9 @@ static void __init omap3_stalker_init(void)
 	omap_board_config = omap3_stalker_config;
 	omap_board_config_size = ARRAY_SIZE(omap3_stalker_config);
 
+	omap_mux_init_gpio(23, OMAP_PIN_INPUT);
 	omap_hsmmc_init(mmc);
+
 	omap3_stalker_i2c_init();
 
 	platform_add_devices(omap3_stalker_devices,
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index ba9c118..8842e04 100644
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -118,12 +118,6 @@ static struct gpio_led gpio_leds[];
 static int touchbook_twl_gpio_setup(struct device *dev,
 		unsigned gpio, unsigned ngpio)
 {
-	if (system_rev >= 0x20 && system_rev <= 0x34301000) {
-		omap_mux_init_gpio(23, OMAP_PIN_INPUT);
-		mmc[0].gpio_wp = 23;
-	} else {
-		omap_mux_init_gpio(29, OMAP_PIN_INPUT);
-	}
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	mmc[0].gpio_cd = gpio + 0;
 	omap_hsmmc_late_init(mmc);
@@ -352,7 +346,14 @@ static void __init omap3_touchbook_init(void)
 
 	pm_power_off = omap3_touchbook_poweroff;
 
+	if (system_rev >= 0x20 && system_rev <= 0x34301000) {
+		omap_mux_init_gpio(23, OMAP_PIN_INPUT);
+		mmc[0].gpio_wp = 23;
+	} else {
+		omap_mux_init_gpio(29, OMAP_PIN_INPUT);
+	}
 	omap_hsmmc_init(mmc);
+
 	omap3_touchbook_i2c_init();
 	platform_add_devices(omap3_touchbook_devices,
 			ARRAY_SIZE(omap3_touchbook_devices));
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index bcc563c..7ca7a5c 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -461,7 +461,7 @@ static struct omap_dss_board_info omap4_panda_dss_data = {
 	.default_device	= &omap4_panda_dvi_device,
 };
 
-void omap4_panda_display_init(void)
+void __init omap4_panda_display_init(void)
 {
 	int r;
 
diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
index 3677b1f..62e133c 100644
--- a/arch/arm/mach-omap2/display.c
+++ b/arch/arm/mach-omap2/display.c
@@ -124,7 +124,7 @@ static void omap4_hdmi_mux_pads(enum omap_hdmi_flags flags)
 	}
 }
 
-static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
+static int __init omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
 {
 	u32 enable_mask, enable_shift;
 	u32 pipd_mask, pipd_shift;
@@ -157,7 +157,7 @@ static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
 	return 0;
 }
 
-int omap_hdmi_init(enum omap_hdmi_flags flags)
+int __init omap_hdmi_init(enum omap_hdmi_flags flags)
 {
 	if (cpu_is_omap44xx())
 		omap4_hdmi_mux_pads(flags);
@@ -165,7 +165,7 @@ int omap_hdmi_init(enum omap_hdmi_flags flags)
 	return 0;
 }
 
-static int omap_dsi_enable_pads(int dsi_id, unsigned lane_mask)
+static int __init omap_dsi_enable_pads(int dsi_id, unsigned lane_mask)
 {
 	if (cpu_is_omap44xx())
 		return omap4_dsi_mux_pads(dsi_id, lane_mask);
@@ -173,7 +173,7 @@ static int omap_dsi_enable_pads(int dsi_id, unsigned lane_mask)
 	return 0;
 }
 
-static void omap_dsi_disable_pads(int dsi_id, unsigned lane_mask)
+static void __init omap_dsi_disable_pads(int dsi_id, unsigned lane_mask)
 {
 	if (cpu_is_omap44xx())
 		omap4_dsi_mux_pads(dsi_id, 0);
diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
index 0f774e5..59c3ee4 100644
--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -293,8 +293,8 @@ static inline void omap_hsmmc_mux(struct omap_mmc_platform_data *mmc_controller,
 	}
 }
 
-static int omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
-				 struct omap_mmc_platform_data *mmc)
+static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
+					struct omap_mmc_platform_data *mmc)
 {
 	char *hc_name;
 
@@ -540,7 +540,7 @@ free_mmc:
 	kfree(mmc_data);
 }
 
-void omap_hsmmc_init(struct omap2_hsmmc_info *controllers)
+void __init omap_hsmmc_init(struct omap2_hsmmc_info *controllers)
 {
 	u32 reg;
 
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index fb8bc9f..e1cc75d 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -100,8 +100,8 @@ void omap_mux_write_array(struct omap_mux_partition *partition,
 
 static char *omap_mux_options;
 
-static int _omap_mux_init_gpio(struct omap_mux_partition *partition,
-			       int gpio, int val)
+static int __init _omap_mux_init_gpio(struct omap_mux_partition *partition,
+				      int gpio, int val)
 {
 	struct omap_mux_entry *e;
 	struct omap_mux *gpio_mux = NULL;
@@ -145,7 +145,7 @@ static int _omap_mux_init_gpio(struct omap_mux_partition *partition,
 	return 0;
 }
 
-int omap_mux_init_gpio(int gpio, int val)
+int __init omap_mux_init_gpio(int gpio, int val)
 {
 	struct omap_mux_partition *partition;
 	int ret;
@@ -159,9 +159,9 @@ int omap_mux_init_gpio(int gpio, int val)
 	return -ENODEV;
 }
 
-static int _omap_mux_get_by_name(struct omap_mux_partition *partition,
-				 const char *muxname,
-				 struct omap_mux **found_mux)
+static int __init _omap_mux_get_by_name(struct omap_mux_partition *partition,
+					const char *muxname,
+					struct omap_mux **found_mux)
 {
 	struct omap_mux *mux = NULL;
 	struct omap_mux_entry *e;
@@ -240,7 +240,7 @@ omap_mux_get_by_name(const char *muxname,
 	return -ENODEV;
 }
 
-int omap_mux_init_signal(const char *muxname, int val)
+int __init omap_mux_init_signal(const char *muxname, int val)
 {
 	struct omap_mux_partition *partition = NULL;
 	struct omap_mux *mux = NULL;
@@ -1094,8 +1094,8 @@ static void omap_mux_init_package(struct omap_mux *superset,
 		omap_mux_package_init_balls(package_balls, superset);
 }
 
-static void __init omap_mux_init_signals(struct omap_mux_partition *partition,
-					 struct omap_board_mux *board_mux)
+static void omap_mux_init_signals(struct omap_mux_partition *partition,
+				  struct omap_board_mux *board_mux)
 {
 	omap_mux_set_cmdline_signals();
 	omap_mux_write_array(partition, board_mux);
@@ -1109,8 +1109,8 @@ static void omap_mux_init_package(struct omap_mux *superset,
 {
 }
 
-static void __init omap_mux_init_signals(struct omap_mux_partition *partition,
-					 struct omap_board_mux *board_mux)
+static void omap_mux_init_signals(struct omap_mux_partition *partition,
+				  struct omap_board_mux *board_mux)
 {
 }
 

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

* Re: [PATCH 2/3] ARM: OMAP2+: Split omap2_hsmmc_init() to properly support I2C GPIO pins
  2012-02-15 18:28   ` Tony Lindgren
@ 2012-02-16 10:03     ` Rajendra Nayak
  -1 siblings, 0 replies; 66+ messages in thread
From: Rajendra Nayak @ 2012-02-16 10:03 UTC (permalink / raw)
  To: Tony Lindgren; +Cc: linux-arm-kernel, Russell King, linux-omap

Hi Tony,

On Wednesday 15 February 2012 11:58 PM, Tony Lindgren wrote:
> Otherwise omap_device_build() and omap_mux related functions
> can't be marked as __init when twl is build as a module.
>
> If a board is using GPIO pins or regulators configured by an
> external chip, such as TWL PMIC on I2C bus, the board must
> mark those MMC controllers as deferred. Additionally both
> omap_hsmmc_init() and omap_hsmmc_late_init() must be called
> by the board.
>
> For MMC controllers using internal GPIO pins for card
> detect and regulators the slots don't need to be marked
> deferred. In this case calling omap_hsmmc_init() is sufficient.
>
> Note that this patch does not change the behaviour for
> board-4430sdp.c board-omap4panda.c. These boards wrongly
> rely on the omap_hsmmc.c init function callback to configure
> the PMIC GPIO interrupt lines on external chip. If the PMIC
> interrupt lines are not configured during init, they will
> fail.

I tested these patches on omap3 beagle and card detect seems
to be broken. See my comment below on why.

>
> Reported-by: Russell King<rmk+kernel@arm.linux.org.uk>
> Signed-off-by: Tony Lindgren<tony@atomide.com>
> ---
>   arch/arm/mach-omap2/board-2430sdp.c          |    2
>   arch/arm/mach-omap2/board-3430sdp.c          |    5 +
>   arch/arm/mach-omap2/board-4430sdp.c          |    4 -
>   arch/arm/mach-omap2/board-am3517evm.c        |    2
>   arch/arm/mach-omap2/board-cm-t35.c           |    6 +
>   arch/arm/mach-omap2/board-devkit8000.c       |    4 +
>   arch/arm/mach-omap2/board-igep0020.c         |    7 +-
>   arch/arm/mach-omap2/board-ldp.c              |    2
>   arch/arm/mach-omap2/board-omap3beagle.c      |    4 +
>   arch/arm/mach-omap2/board-omap3evm.c         |    5 +
>   arch/arm/mach-omap2/board-omap3logic.c       |    2
>   arch/arm/mach-omap2/board-omap3pandora.c     |    6 +
>   arch/arm/mach-omap2/board-omap3stalker.c     |   12 ++-
>   arch/arm/mach-omap2/board-omap3touchbook.c   |    4 +
>   arch/arm/mach-omap2/board-omap4panda.c       |    4 -
>   arch/arm/mach-omap2/board-overo.c            |    5 +
>   arch/arm/mach-omap2/board-rm680.c            |    2
>   arch/arm/mach-omap2/board-rx51-peripherals.c |    2
>   arch/arm/mach-omap2/board-zoom-peripherals.c |    6 +
>   arch/arm/mach-omap2/hsmmc.c                  |  107 +++++++++++++++++++-------
>   arch/arm/mach-omap2/hsmmc.h                  |   12 ++-
>   21 files changed, 147 insertions(+), 56 deletions(-)
>

[]...
> diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
> index e921e3b..60f0501 100644
> --- a/arch/arm/mach-omap2/board-cm-t35.c
> +++ b/arch/arm/mach-omap2/board-cm-t35.c
> @@ -413,7 +413,7 @@ static struct omap2_hsmmc_info mmc[] = {
>   		.caps		= MMC_CAP_4_BIT_DATA,
>   		.gpio_cd	= -EINVAL,
>   		.gpio_wp	= -EINVAL,
> -
> +		.deferred	= true,
>   	},
>   	{
>   		.mmc		= 2,
> @@ -422,6 +422,7 @@ static struct omap2_hsmmc_info mmc[] = {
>   		.gpio_cd	= -EINVAL,
>   		.gpio_wp	= -EINVAL,
>   		.ocr_mask	= 0x00100000,	/* 3.3V */
> +		.deferred	= true,
>   	},
>   	{}	/* Terminator */
>   };
> @@ -471,7 +472,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;
> -	omap2_hsmmc_init(mmc);
> +	omap_hsmmc_late_init(mmc);

omap_hsmmc_late_init() in some way needs to pass on the gpio_cd
value onto the driver via platform_data which its currently not.
better still, I think we should just populate them statically in
omap2_hsmmc_info struct above, so omap_hsmmc_init() takes care
of it already.

[]...
>
> +void omap_hsmmc_late_init(struct omap2_hsmmc_info *controllers)
> +{
> +	struct platform_device *pdev;
> +	int res;
> +
> +	for (; controllers->mmc; controllers++) {
> +		if (!controllers->deferred)
> +			continue;
> +
> +		pdev = controllers->pdev;
> +		if (!pdev)
> +			continue;
> +
> +		res = omap_device_register(pdev);
> +		if (res) {
> +			pr_err("Could not late init MMC %s\n",
> +			       controllers->name);
> +			continue;
> +		}
> +	}
> +}

regards,
Rajendra

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

* [PATCH 2/3] ARM: OMAP2+: Split omap2_hsmmc_init() to properly support I2C GPIO pins
@ 2012-02-16 10:03     ` Rajendra Nayak
  0 siblings, 0 replies; 66+ messages in thread
From: Rajendra Nayak @ 2012-02-16 10:03 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Tony,

On Wednesday 15 February 2012 11:58 PM, Tony Lindgren wrote:
> Otherwise omap_device_build() and omap_mux related functions
> can't be marked as __init when twl is build as a module.
>
> If a board is using GPIO pins or regulators configured by an
> external chip, such as TWL PMIC on I2C bus, the board must
> mark those MMC controllers as deferred. Additionally both
> omap_hsmmc_init() and omap_hsmmc_late_init() must be called
> by the board.
>
> For MMC controllers using internal GPIO pins for card
> detect and regulators the slots don't need to be marked
> deferred. In this case calling omap_hsmmc_init() is sufficient.
>
> Note that this patch does not change the behaviour for
> board-4430sdp.c board-omap4panda.c. These boards wrongly
> rely on the omap_hsmmc.c init function callback to configure
> the PMIC GPIO interrupt lines on external chip. If the PMIC
> interrupt lines are not configured during init, they will
> fail.

I tested these patches on omap3 beagle and card detect seems
to be broken. See my comment below on why.

>
> Reported-by: Russell King<rmk+kernel@arm.linux.org.uk>
> Signed-off-by: Tony Lindgren<tony@atomide.com>
> ---
>   arch/arm/mach-omap2/board-2430sdp.c          |    2
>   arch/arm/mach-omap2/board-3430sdp.c          |    5 +
>   arch/arm/mach-omap2/board-4430sdp.c          |    4 -
>   arch/arm/mach-omap2/board-am3517evm.c        |    2
>   arch/arm/mach-omap2/board-cm-t35.c           |    6 +
>   arch/arm/mach-omap2/board-devkit8000.c       |    4 +
>   arch/arm/mach-omap2/board-igep0020.c         |    7 +-
>   arch/arm/mach-omap2/board-ldp.c              |    2
>   arch/arm/mach-omap2/board-omap3beagle.c      |    4 +
>   arch/arm/mach-omap2/board-omap3evm.c         |    5 +
>   arch/arm/mach-omap2/board-omap3logic.c       |    2
>   arch/arm/mach-omap2/board-omap3pandora.c     |    6 +
>   arch/arm/mach-omap2/board-omap3stalker.c     |   12 ++-
>   arch/arm/mach-omap2/board-omap3touchbook.c   |    4 +
>   arch/arm/mach-omap2/board-omap4panda.c       |    4 -
>   arch/arm/mach-omap2/board-overo.c            |    5 +
>   arch/arm/mach-omap2/board-rm680.c            |    2
>   arch/arm/mach-omap2/board-rx51-peripherals.c |    2
>   arch/arm/mach-omap2/board-zoom-peripherals.c |    6 +
>   arch/arm/mach-omap2/hsmmc.c                  |  107 +++++++++++++++++++-------
>   arch/arm/mach-omap2/hsmmc.h                  |   12 ++-
>   21 files changed, 147 insertions(+), 56 deletions(-)
>

[]...
> diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
> index e921e3b..60f0501 100644
> --- a/arch/arm/mach-omap2/board-cm-t35.c
> +++ b/arch/arm/mach-omap2/board-cm-t35.c
> @@ -413,7 +413,7 @@ static struct omap2_hsmmc_info mmc[] = {
>   		.caps		= MMC_CAP_4_BIT_DATA,
>   		.gpio_cd	= -EINVAL,
>   		.gpio_wp	= -EINVAL,
> -
> +		.deferred	= true,
>   	},
>   	{
>   		.mmc		= 2,
> @@ -422,6 +422,7 @@ static struct omap2_hsmmc_info mmc[] = {
>   		.gpio_cd	= -EINVAL,
>   		.gpio_wp	= -EINVAL,
>   		.ocr_mask	= 0x00100000,	/* 3.3V */
> +		.deferred	= true,
>   	},
>   	{}	/* Terminator */
>   };
> @@ -471,7 +472,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;
> -	omap2_hsmmc_init(mmc);
> +	omap_hsmmc_late_init(mmc);

omap_hsmmc_late_init() in some way needs to pass on the gpio_cd
value onto the driver via platform_data which its currently not.
better still, I think we should just populate them statically in
omap2_hsmmc_info struct above, so omap_hsmmc_init() takes care
of it already.

[]...
>
> +void omap_hsmmc_late_init(struct omap2_hsmmc_info *controllers)
> +{
> +	struct platform_device *pdev;
> +	int res;
> +
> +	for (; controllers->mmc; controllers++) {
> +		if (!controllers->deferred)
> +			continue;
> +
> +		pdev = controllers->pdev;
> +		if (!pdev)
> +			continue;
> +
> +		res = omap_device_register(pdev);
> +		if (res) {
> +			pr_err("Could not late init MMC %s\n",
> +			       controllers->name);
> +			continue;
> +		}
> +	}
> +}

regards,
Rajendra

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

* Re: [PATCH 3/3] ARM: OMAP2+: Mark omap_hsmmc_init and omap_mux related functions as __init
  2012-02-15 18:28   ` Tony Lindgren
@ 2012-02-16 10:11     ` Russell King - ARM Linux
  -1 siblings, 0 replies; 66+ messages in thread
From: Russell King - ARM Linux @ 2012-02-16 10:11 UTC (permalink / raw)
  To: Tony Lindgren; +Cc: linux-arm-kernel, linux-omap

On Wed, Feb 15, 2012 at 10:28:30AM -0800, Tony Lindgren wrote:
> Now that omap hsmmc init is split into two functions, it's safe
> to mark omap_hsmmc_init and omap_mux related functions to __init.
> 
> This basically reverts the following fixes for the case where
> TWL was compiled as a module:
> 
> d5de63 (ARM: omap: preemptively fix section mismatch in omap4_sdp4430_wifi_mux_init())

Why did you include this one?  This is unrelated to the TWL problems.

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

* [PATCH 3/3] ARM: OMAP2+: Mark omap_hsmmc_init and omap_mux related functions as __init
@ 2012-02-16 10:11     ` Russell King - ARM Linux
  0 siblings, 0 replies; 66+ messages in thread
From: Russell King - ARM Linux @ 2012-02-16 10:11 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Feb 15, 2012 at 10:28:30AM -0800, Tony Lindgren wrote:
> Now that omap hsmmc init is split into two functions, it's safe
> to mark omap_hsmmc_init and omap_mux related functions to __init.
> 
> This basically reverts the following fixes for the case where
> TWL was compiled as a module:
> 
> d5de63 (ARM: omap: preemptively fix section mismatch in omap4_sdp4430_wifi_mux_init())

Why did you include this one?  This is unrelated to the TWL problems.

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

* Re: [PATCH 2/3] ARM: OMAP2+: Split omap2_hsmmc_init() to properly support I2C GPIO pins
  2012-02-16 10:03     ` Rajendra Nayak
@ 2012-02-16 10:13       ` Rajendra Nayak
  -1 siblings, 0 replies; 66+ messages in thread
From: Rajendra Nayak @ 2012-02-16 10:13 UTC (permalink / raw)
  To: Tony Lindgren; +Cc: linux-arm-kernel, Russell King, linux-omap

On Thursday 16 February 2012 03:33 PM, Rajendra Nayak wrote:
> better still, I think we should just populate them statically in
> omap2_hsmmc_info struct above, so omap_hsmmc_init() takes care
> of it already.

I just tried this and it seems to work...

---
  arch/arm/mach-omap2/board-omap3beagle.c |    1 +
  1 file changed, 1 insertion(+)

Index: linux-2.6/arch/arm/mach-omap2/board-omap3beagle.c
===================================================================
--- linux-2.6.orig/arch/arm/mach-omap2/board-omap3beagle.c 
2012-02-16 15:38:47.046933403 +0530
+++ linux-2.6/arch/arm/mach-omap2/board-omap3beagle.c   2012-02-16 
15:40:17.355349064 +0530
@@ -253,6 +253,7 @@
                 .mmc            = 1,
                 .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
                 .gpio_wp        = -EINVAL,
+               .gpio_cd        = OMAP_MAX_GPIO_LINES + 0,
                 .deferred       = true,
         },
         {}      /* Terminator */

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

* [PATCH 2/3] ARM: OMAP2+: Split omap2_hsmmc_init() to properly support I2C GPIO pins
@ 2012-02-16 10:13       ` Rajendra Nayak
  0 siblings, 0 replies; 66+ messages in thread
From: Rajendra Nayak @ 2012-02-16 10:13 UTC (permalink / raw)
  To: linux-arm-kernel

On Thursday 16 February 2012 03:33 PM, Rajendra Nayak wrote:
> better still, I think we should just populate them statically in
> omap2_hsmmc_info struct above, so omap_hsmmc_init() takes care
> of it already.

I just tried this and it seems to work...

---
  arch/arm/mach-omap2/board-omap3beagle.c |    1 +
  1 file changed, 1 insertion(+)

Index: linux-2.6/arch/arm/mach-omap2/board-omap3beagle.c
===================================================================
--- linux-2.6.orig/arch/arm/mach-omap2/board-omap3beagle.c 
2012-02-16 15:38:47.046933403 +0530
+++ linux-2.6/arch/arm/mach-omap2/board-omap3beagle.c   2012-02-16 
15:40:17.355349064 +0530
@@ -253,6 +253,7 @@
                 .mmc            = 1,
                 .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
                 .gpio_wp        = -EINVAL,
+               .gpio_cd        = OMAP_MAX_GPIO_LINES + 0,
                 .deferred       = true,
         },
         {}      /* Terminator */

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

* Re: [PATCH 0/3] omap hsmmc init cleanup and section warning fixes for v3.4 merge window
  2012-02-15 18:28 ` Tony Lindgren
@ 2012-02-16 12:00   ` Nayak, Rajendra
  -1 siblings, 0 replies; 66+ messages in thread
From: Nayak, Rajendra @ 2012-02-16 12:00 UTC (permalink / raw)
  To: Tony Lindgren; +Cc: linux-arm-kernel, linux-omap

> One more patch is needed to sort out the remaining issue with
> omap4 that has yet another luck based initialization for the
> same issue..
>

I did this patch on top of your series which should fix the
issue on all omap4 boards too. Tested on omap4panda and
omap4sdp boards.

>From 5a4bbd64fd1e791b922b76ea8f12dac4216c0a0f Mon Sep 17 00:00:00 2001
From: Rajendra Nayak <rnayak@ti.com>
Date: Thu, 16 Feb 2012 17:24:13 +0530
Subject: [PATCH] ARM: OMAP2+: Fix sequencing issues with
omap4_twl6030_hsmmc_late_init

omap4_twl6030_hsmmc_late_init() relies on twl initialization
to happen before the mmc device is probed, which seems to work
today just by luck. Now that we have support for deferred
mmc init using omap_hsmmc_late_init(), make omap4_twl6030_hsmmc_late_init()
to be called only after twl initialization and use omap_hsmmc_late_init()
for deferred mmc init.

This also fixes mmc card detect on omap4panda, which seems to be broken
as card_detect_irq was never passed from omap4panda board file.

Reported-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
---
 arch/arm/mach-omap2/board-4430sdp.c    |   39 +++++-----------------------
 arch/arm/mach-omap2/board-omap4panda.c |   44 ++++++--------------------------
 arch/arm/mach-omap2/hsmmc.c            |    7 +++++
 drivers/mfd/twl-core.c                 |    7 +++++
 include/linux/i2c/twl.h                |    1 +
 5 files changed, 30 insertions(+), 68 deletions(-)

diff --git a/arch/arm/mach-omap2/board-4430sdp.c
b/arch/arm/mach-omap2/board-4430sdp.c
index ece9e3a..966ea8d 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -407,6 +407,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
+		.deferred	= true,
 	},
 	{
 		.mmc		= 5,
@@ -455,46 +456,19 @@ static struct platform_device omap_vwlan_device = {
 	},
 };

-static int omap4_twl6030_hsmmc_late_init(struct device *dev)
+static int omap4_twl6030_hsmmc_late_init(void)
 {
 	int ret = 0;
-	struct platform_device *pdev = container_of(dev,
-				struct platform_device, dev);
-	struct omap_mmc_platform_data *pdata = dev->platform_data;
-
-	/* Setting MMC1 Card detect Irq */
-	if (pdev->id == 0) {
-		ret = twl6030_mmc_card_detect_config();
-		if (ret)
-			pr_err("Failed configuring MMC1 card detect\n");
-		pdata->slots[0].card_detect_irq = TWL6030_IRQ_BASE +
-						MMCDETECT_INTR_OFFSET;
-		pdata->slots[0].card_detect = twl6030_mmc_card_detect;
-	}
+	ret = twl6030_mmc_card_detect_config();
+	if (ret)
+		pr_err("Failed configuring MMC1 card detect\n");
+	omap_hsmmc_late_init(mmc);
 	return ret;
 }

-static __init void omap4_twl6030_hsmmc_set_late_init(struct device *dev)
-{
-	struct omap_mmc_platform_data *pdata;
-
-	/* dev can be null if CONFIG_MMC_OMAP_HS is not set */
-	if (!dev) {
-		pr_err("Failed %s\n", __func__);
-		return;
-	}
-	pdata = dev->platform_data;
-	pdata->init =	omap4_twl6030_hsmmc_late_init;
-}
-
 static int __init omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info
*controllers)
 {
-	struct omap2_hsmmc_info *c;
-
 	omap_hsmmc_init(controllers);
-	for (c = controllers; c->mmc; c++)
-		omap4_twl6030_hsmmc_set_late_init(&c->pdev->dev);
-
 	return 0;
 }

@@ -583,6 +557,7 @@ static int __init omap4_i2c_init(void)
 			TWL_COMMON_REGULATOR_VCXIO |
 			TWL_COMMON_REGULATOR_VUSB |
 			TWL_COMMON_REGULATOR_CLK32KG);
+	sdp4430_twldata.setup = omap4_twl6030_hsmmc_late_init;
 	omap4_pmic_init("twl6030", &sdp4430_twldata);
 	omap_register_i2c_bus(2, 400, NULL, 0);
 	omap_register_i2c_bus(3, 400, sdp4430_i2c_3_boardinfo,
diff --git a/arch/arm/mach-omap2/board-omap4panda.c
b/arch/arm/mach-omap2/board-omap4panda.c
index 7ca7a5c..493aa0a 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -155,6 +155,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
 		.gpio_wp	= -EINVAL,
 		.gpio_cd	= -EINVAL,
+		.deferred	= true,
 	},
 	{
 		.name		= "wl1271",
@@ -204,51 +205,21 @@ struct wl12xx_platform_data omap_panda_wlan_data
 __initdata = {
 	.board_ref_clock = 2,
 };

-static int omap4_twl6030_hsmmc_late_init(struct device *dev)
+static int omap4_twl6030_hsmmc_late_init(void)
 {
 	int ret = 0;
-	struct platform_device *pdev = container_of(dev,
-				struct platform_device, dev);
-	struct omap_mmc_platform_data *pdata = dev->platform_data;

-	if (!pdata) {
-		dev_err(dev, "%s: NULL platform data\n", __func__);
-		return -EINVAL;
-	}
-	/* Setting MMC1 Card detect Irq */
-	if (pdev->id == 0) {
-		ret = twl6030_mmc_card_detect_config();
-		 if (ret)
-			dev_err(dev, "%s: Error card detect config(%d)\n",
-				__func__, ret);
-		 else
-			pdata->slots[0].card_detect = twl6030_mmc_card_detect;
-	}
+	ret = twl6030_mmc_card_detect_config();
+	if (ret)
+		pr_err("%s: Error MMC card detect config(%d)\n",
+			__func__, ret);
+	omap_hsmmc_late_init(mmc);
 	return ret;
 }

-static __init void omap4_twl6030_hsmmc_set_late_init(struct device *dev)
-{
-	struct omap_mmc_platform_data *pdata;
-
-	/* dev can be null if CONFIG_MMC_OMAP_HS is not set */
-	if (!dev) {
-		pr_err("Failed omap4_twl6030_hsmmc_set_late_init\n");
-		return;
-	}
-	pdata = dev->platform_data;
-
-	pdata->init =	omap4_twl6030_hsmmc_late_init;
-}
-
 static int __init omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info
*controllers)
 {
-	struct omap2_hsmmc_info *c;
-
 	omap_hsmmc_init(controllers);
-	for (c = controllers; c->mmc; c++)
-		omap4_twl6030_hsmmc_set_late_init(&c->pdev->dev);
-
 	return 0;
 }

@@ -277,6 +248,7 @@ static int __init omap4_panda_i2c_init(void)
 			TWL_COMMON_REGULATOR_VCXIO |
 			TWL_COMMON_REGULATOR_VUSB |
 			TWL_COMMON_REGULATOR_CLK32KG);
+	omap4_panda_twldata.setup = omap4_twl6030_hsmmc_late_init;
 	omap4_pmic_init("twl6030", &omap4_panda_twldata);
 	omap_register_i2c_bus(2, 400, NULL, 0);
 	/*
diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
index 59c3ee4..ca9192a 100644
--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -14,6 +14,7 @@
 #include <linux/string.h>
 #include <linux/delay.h>
 #include <linux/gpio.h>
+#include <linux/i2c/twl.h>
 #include <mach/hardware.h>
 #include <plat/mmc.h>
 #include <plat/omap-pm.h>
@@ -390,6 +391,12 @@ static int __init omap_hsmmc_pdata_init(struct
omap2_hsmmc_info *c,
 		if (cpu_is_omap3517() || cpu_is_omap3505())
 			mmc->slots[0].set_power = nop_mmc_set_power;

+		if (cpu_is_omap44xx()) {
+			mmc->slots[0].card_detect = twl6030_mmc_card_detect;
+			mmc->slots[0].card_detect_irq = TWL6030_IRQ_BASE +
+						MMCDETECT_INTR_OFFSET;
+		}
+
 		/* OMAP3630 HSMMC1 supports only 4-bit */
 		if (cpu_is_omap3630() &&
 				(c->caps & MMC_CAP_8_BIT_DATA)) {
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index 8ce3959..753a829 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -1322,6 +1322,13 @@ twl_probe(struct i2c_client *client, const
struct i2c_device_id *id)
 #endif
 		status = add_children(pdata, id->driver_data);

+	if (pdata->setup) {
+		int status;
+		status = pdata->setup();
+		if (status)
+			dev_dbg(&client->dev, "setup --> %d\n", status);
+	}
+
 fail:
 	if (status < 0)
 		twl_remove(client);
diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h
index 78d3465..e2d23bc 100644
--- a/include/linux/i2c/twl.h
+++ b/include/linux/i2c/twl.h
@@ -747,6 +747,7 @@ struct twl4030_platform_data {
 	struct regulator_init_data		*smps3;
 	struct regulator_init_data		*smps4;
 	struct regulator_init_data		*vio6025;
+	int					(*setup)(void);
 };

 /*----------------------------------------------------------------------*/
-- 
1.7.1

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

* [PATCH 0/3] omap hsmmc init cleanup and section warning fixes for v3.4 merge window
@ 2012-02-16 12:00   ` Nayak, Rajendra
  0 siblings, 0 replies; 66+ messages in thread
From: Nayak, Rajendra @ 2012-02-16 12:00 UTC (permalink / raw)
  To: linux-arm-kernel

> One more patch is needed to sort out the remaining issue with
> omap4 that has yet another luck based initialization for the
> same issue..
>

I did this patch on top of your series which should fix the
issue on all omap4 boards too. Tested on omap4panda and
omap4sdp boards.

>From 5a4bbd64fd1e791b922b76ea8f12dac4216c0a0f Mon Sep 17 00:00:00 2001
From: Rajendra Nayak <rnayak@ti.com>
Date: Thu, 16 Feb 2012 17:24:13 +0530
Subject: [PATCH] ARM: OMAP2+: Fix sequencing issues with
omap4_twl6030_hsmmc_late_init

omap4_twl6030_hsmmc_late_init() relies on twl initialization
to happen before the mmc device is probed, which seems to work
today just by luck. Now that we have support for deferred
mmc init using omap_hsmmc_late_init(), make omap4_twl6030_hsmmc_late_init()
to be called only after twl initialization and use omap_hsmmc_late_init()
for deferred mmc init.

This also fixes mmc card detect on omap4panda, which seems to be broken
as card_detect_irq was never passed from omap4panda board file.

Reported-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
---
 arch/arm/mach-omap2/board-4430sdp.c    |   39 +++++-----------------------
 arch/arm/mach-omap2/board-omap4panda.c |   44 ++++++--------------------------
 arch/arm/mach-omap2/hsmmc.c            |    7 +++++
 drivers/mfd/twl-core.c                 |    7 +++++
 include/linux/i2c/twl.h                |    1 +
 5 files changed, 30 insertions(+), 68 deletions(-)

diff --git a/arch/arm/mach-omap2/board-4430sdp.c
b/arch/arm/mach-omap2/board-4430sdp.c
index ece9e3a..966ea8d 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -407,6 +407,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
+		.deferred	= true,
 	},
 	{
 		.mmc		= 5,
@@ -455,46 +456,19 @@ static struct platform_device omap_vwlan_device = {
 	},
 };

-static int omap4_twl6030_hsmmc_late_init(struct device *dev)
+static int omap4_twl6030_hsmmc_late_init(void)
 {
 	int ret = 0;
-	struct platform_device *pdev = container_of(dev,
-				struct platform_device, dev);
-	struct omap_mmc_platform_data *pdata = dev->platform_data;
-
-	/* Setting MMC1 Card detect Irq */
-	if (pdev->id == 0) {
-		ret = twl6030_mmc_card_detect_config();
-		if (ret)
-			pr_err("Failed configuring MMC1 card detect\n");
-		pdata->slots[0].card_detect_irq = TWL6030_IRQ_BASE +
-						MMCDETECT_INTR_OFFSET;
-		pdata->slots[0].card_detect = twl6030_mmc_card_detect;
-	}
+	ret = twl6030_mmc_card_detect_config();
+	if (ret)
+		pr_err("Failed configuring MMC1 card detect\n");
+	omap_hsmmc_late_init(mmc);
 	return ret;
 }

-static __init void omap4_twl6030_hsmmc_set_late_init(struct device *dev)
-{
-	struct omap_mmc_platform_data *pdata;
-
-	/* dev can be null if CONFIG_MMC_OMAP_HS is not set */
-	if (!dev) {
-		pr_err("Failed %s\n", __func__);
-		return;
-	}
-	pdata = dev->platform_data;
-	pdata->init =	omap4_twl6030_hsmmc_late_init;
-}
-
 static int __init omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info
*controllers)
 {
-	struct omap2_hsmmc_info *c;
-
 	omap_hsmmc_init(controllers);
-	for (c = controllers; c->mmc; c++)
-		omap4_twl6030_hsmmc_set_late_init(&c->pdev->dev);
-
 	return 0;
 }

@@ -583,6 +557,7 @@ static int __init omap4_i2c_init(void)
 			TWL_COMMON_REGULATOR_VCXIO |
 			TWL_COMMON_REGULATOR_VUSB |
 			TWL_COMMON_REGULATOR_CLK32KG);
+	sdp4430_twldata.setup = omap4_twl6030_hsmmc_late_init;
 	omap4_pmic_init("twl6030", &sdp4430_twldata);
 	omap_register_i2c_bus(2, 400, NULL, 0);
 	omap_register_i2c_bus(3, 400, sdp4430_i2c_3_boardinfo,
diff --git a/arch/arm/mach-omap2/board-omap4panda.c
b/arch/arm/mach-omap2/board-omap4panda.c
index 7ca7a5c..493aa0a 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -155,6 +155,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
 		.gpio_wp	= -EINVAL,
 		.gpio_cd	= -EINVAL,
+		.deferred	= true,
 	},
 	{
 		.name		= "wl1271",
@@ -204,51 +205,21 @@ struct wl12xx_platform_data omap_panda_wlan_data
 __initdata = {
 	.board_ref_clock = 2,
 };

-static int omap4_twl6030_hsmmc_late_init(struct device *dev)
+static int omap4_twl6030_hsmmc_late_init(void)
 {
 	int ret = 0;
-	struct platform_device *pdev = container_of(dev,
-				struct platform_device, dev);
-	struct omap_mmc_platform_data *pdata = dev->platform_data;

-	if (!pdata) {
-		dev_err(dev, "%s: NULL platform data\n", __func__);
-		return -EINVAL;
-	}
-	/* Setting MMC1 Card detect Irq */
-	if (pdev->id == 0) {
-		ret = twl6030_mmc_card_detect_config();
-		 if (ret)
-			dev_err(dev, "%s: Error card detect config(%d)\n",
-				__func__, ret);
-		 else
-			pdata->slots[0].card_detect = twl6030_mmc_card_detect;
-	}
+	ret = twl6030_mmc_card_detect_config();
+	if (ret)
+		pr_err("%s: Error MMC card detect config(%d)\n",
+			__func__, ret);
+	omap_hsmmc_late_init(mmc);
 	return ret;
 }

-static __init void omap4_twl6030_hsmmc_set_late_init(struct device *dev)
-{
-	struct omap_mmc_platform_data *pdata;
-
-	/* dev can be null if CONFIG_MMC_OMAP_HS is not set */
-	if (!dev) {
-		pr_err("Failed omap4_twl6030_hsmmc_set_late_init\n");
-		return;
-	}
-	pdata = dev->platform_data;
-
-	pdata->init =	omap4_twl6030_hsmmc_late_init;
-}
-
 static int __init omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info
*controllers)
 {
-	struct omap2_hsmmc_info *c;
-
 	omap_hsmmc_init(controllers);
-	for (c = controllers; c->mmc; c++)
-		omap4_twl6030_hsmmc_set_late_init(&c->pdev->dev);
-
 	return 0;
 }

@@ -277,6 +248,7 @@ static int __init omap4_panda_i2c_init(void)
 			TWL_COMMON_REGULATOR_VCXIO |
 			TWL_COMMON_REGULATOR_VUSB |
 			TWL_COMMON_REGULATOR_CLK32KG);
+	omap4_panda_twldata.setup = omap4_twl6030_hsmmc_late_init;
 	omap4_pmic_init("twl6030", &omap4_panda_twldata);
 	omap_register_i2c_bus(2, 400, NULL, 0);
 	/*
diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
index 59c3ee4..ca9192a 100644
--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -14,6 +14,7 @@
 #include <linux/string.h>
 #include <linux/delay.h>
 #include <linux/gpio.h>
+#include <linux/i2c/twl.h>
 #include <mach/hardware.h>
 #include <plat/mmc.h>
 #include <plat/omap-pm.h>
@@ -390,6 +391,12 @@ static int __init omap_hsmmc_pdata_init(struct
omap2_hsmmc_info *c,
 		if (cpu_is_omap3517() || cpu_is_omap3505())
 			mmc->slots[0].set_power = nop_mmc_set_power;

+		if (cpu_is_omap44xx()) {
+			mmc->slots[0].card_detect = twl6030_mmc_card_detect;
+			mmc->slots[0].card_detect_irq = TWL6030_IRQ_BASE +
+						MMCDETECT_INTR_OFFSET;
+		}
+
 		/* OMAP3630 HSMMC1 supports only 4-bit */
 		if (cpu_is_omap3630() &&
 				(c->caps & MMC_CAP_8_BIT_DATA)) {
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index 8ce3959..753a829 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -1322,6 +1322,13 @@ twl_probe(struct i2c_client *client, const
struct i2c_device_id *id)
 #endif
 		status = add_children(pdata, id->driver_data);

+	if (pdata->setup) {
+		int status;
+		status = pdata->setup();
+		if (status)
+			dev_dbg(&client->dev, "setup --> %d\n", status);
+	}
+
 fail:
 	if (status < 0)
 		twl_remove(client);
diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h
index 78d3465..e2d23bc 100644
--- a/include/linux/i2c/twl.h
+++ b/include/linux/i2c/twl.h
@@ -747,6 +747,7 @@ struct twl4030_platform_data {
 	struct regulator_init_data		*smps3;
 	struct regulator_init_data		*smps4;
 	struct regulator_init_data		*vio6025;
+	int					(*setup)(void);
 };

 /*----------------------------------------------------------------------*/
-- 
1.7.1

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

* Re: [PATCH 0/3] omap hsmmc init cleanup and section warning fixes for v3.4 merge window
  2012-02-16 12:00   ` Nayak, Rajendra
@ 2012-02-16 12:12     ` Russell King - ARM Linux
  -1 siblings, 0 replies; 66+ messages in thread
From: Russell King - ARM Linux @ 2012-02-16 12:12 UTC (permalink / raw)
  To: Nayak, Rajendra; +Cc: Tony Lindgren, linux-omap, linux-arm-kernel

On Thu, Feb 16, 2012 at 05:30:59PM +0530, Nayak, Rajendra wrote:
> > One more patch is needed to sort out the remaining issue with
> > omap4 that has yet another luck based initialization for the
> > same issue..
> >
> 
> I did this patch on top of your series which should fix the
> issue on all omap4 boards too. Tested on omap4panda and
> omap4sdp boards.

Can you test something with these patches?

1. Build the gpio-twl4030.c as a module, but with HSMMC support built in
2. Boot on the 4430SDP
3. Load the gpio-twl4030 module
4. Remove the gpio-twl4030 module
5. Re-load the gpio-twl4030.ko module

and report back what you get.  Thanks.

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

* [PATCH 0/3] omap hsmmc init cleanup and section warning fixes for v3.4 merge window
@ 2012-02-16 12:12     ` Russell King - ARM Linux
  0 siblings, 0 replies; 66+ messages in thread
From: Russell King - ARM Linux @ 2012-02-16 12:12 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Feb 16, 2012 at 05:30:59PM +0530, Nayak, Rajendra wrote:
> > One more patch is needed to sort out the remaining issue with
> > omap4 that has yet another luck based initialization for the
> > same issue..
> >
> 
> I did this patch on top of your series which should fix the
> issue on all omap4 boards too. Tested on omap4panda and
> omap4sdp boards.

Can you test something with these patches?

1. Build the gpio-twl4030.c as a module, but with HSMMC support built in
2. Boot on the 4430SDP
3. Load the gpio-twl4030 module
4. Remove the gpio-twl4030 module
5. Re-load the gpio-twl4030.ko module

and report back what you get.  Thanks.

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

* Re: [PATCH 0/3] omap hsmmc init cleanup and section warning fixes for v3.4 merge window
  2012-02-16 12:12     ` Russell King - ARM Linux
@ 2012-02-16 12:34       ` Rajendra Nayak
  -1 siblings, 0 replies; 66+ messages in thread
From: Rajendra Nayak @ 2012-02-16 12:34 UTC (permalink / raw)
  To: Russell King - ARM Linux; +Cc: Tony Lindgren, linux-omap, linux-arm-kernel

On Thursday 16 February 2012 05:42 PM, Russell King - ARM Linux wrote:
> On Thu, Feb 16, 2012 at 05:30:59PM +0530, Nayak, Rajendra wrote:
>>> One more patch is needed to sort out the remaining issue with
>>> omap4 that has yet another luck based initialization for the
>>> same issue..
>>>
>>
>> I did this patch on top of your series which should fix the
>> issue on all omap4 boards too. Tested on omap4panda and
>> omap4sdp boards.
>
> Can you test something with these patches?
>
> 1. Build the gpio-twl4030.c as a module, but with HSMMC support built in
> 2. Boot on the 4430SDP

twl4030 gpio is used for card detect on OMAP3, so I tried this
on my Beagle instead of 4430SDP.
The kernel boots up but does not detect/enumerate the mmc card.

> 3. Load the gpio-twl4030 module

I was expecting this to now detect the card, but I instead got
this error which seems to tell gpio-twl4030 has problems
when built/used as a module, outside of the mmc issues.

# insmod gpio-twl4030.ko
[   16.217864] twl4030_gpio twl4030_gpio: can't dispatch IRQs from modules
[   16.242004] gpiochip_add: registered GPIOs 192 to 211 on device: twl4030


> 4. Remove the gpio-twl4030 module
> 5. Re-load the gpio-twl4030.ko module
>
> and report back what you get.  Thanks.


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

* [PATCH 0/3] omap hsmmc init cleanup and section warning fixes for v3.4 merge window
@ 2012-02-16 12:34       ` Rajendra Nayak
  0 siblings, 0 replies; 66+ messages in thread
From: Rajendra Nayak @ 2012-02-16 12:34 UTC (permalink / raw)
  To: linux-arm-kernel

On Thursday 16 February 2012 05:42 PM, Russell King - ARM Linux wrote:
> On Thu, Feb 16, 2012 at 05:30:59PM +0530, Nayak, Rajendra wrote:
>>> One more patch is needed to sort out the remaining issue with
>>> omap4 that has yet another luck based initialization for the
>>> same issue..
>>>
>>
>> I did this patch on top of your series which should fix the
>> issue on all omap4 boards too. Tested on omap4panda and
>> omap4sdp boards.
>
> Can you test something with these patches?
>
> 1. Build the gpio-twl4030.c as a module, but with HSMMC support built in
> 2. Boot on the 4430SDP

twl4030 gpio is used for card detect on OMAP3, so I tried this
on my Beagle instead of 4430SDP.
The kernel boots up but does not detect/enumerate the mmc card.

> 3. Load the gpio-twl4030 module

I was expecting this to now detect the card, but I instead got
this error which seems to tell gpio-twl4030 has problems
when built/used as a module, outside of the mmc issues.

# insmod gpio-twl4030.ko
[   16.217864] twl4030_gpio twl4030_gpio: can't dispatch IRQs from modules
[   16.242004] gpiochip_add: registered GPIOs 192 to 211 on device: twl4030


> 4. Remove the gpio-twl4030 module
> 5. Re-load the gpio-twl4030.ko module
>
> and report back what you get.  Thanks.

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

* Re: [PATCH 0/3] omap hsmmc init cleanup and section warning fixes for v3.4 merge window
  2012-02-16 12:34       ` Rajendra Nayak
@ 2012-02-16 13:15         ` Rajendra Nayak
  -1 siblings, 0 replies; 66+ messages in thread
From: Rajendra Nayak @ 2012-02-16 13:15 UTC (permalink / raw)
  To: Russell King - ARM Linux; +Cc: Tony Lindgren, linux-omap, linux-arm-kernel

On Thursday 16 February 2012 06:04 PM, Rajendra Nayak wrote:
>> Can you test something with these patches?
>>
>> 1. Build the gpio-twl4030.c as a module, but with HSMMC support built in
>> 2. Boot on the 4430SDP
>
> twl4030 gpio is used for card detect on OMAP3, so I tried this
> on my Beagle instead of 4430SDP.
> The kernel boots up but does not detect/enumerate the mmc card.
>
>> 3. Load the gpio-twl4030 module
>
> I was expecting this to now detect the card, but I instead got
> this error which seems to tell gpio-twl4030 has problems
> when built/used as a module, outside of the mmc issues.

Looks like I was mislead with the errors and though the twl4030
gpio probe was bailing out with errors, which its not.
It does seem to go ahead, does a mmc late init which registers
the mmc omap_device and hence does a platform_device_add, but the
device never seem to get probed. mmc driver is built in and
registered.

>
> # insmod gpio-twl4030.ko
> [   16.217864] twl4030_gpio twl4030_gpio: can't dispatch IRQs from modules
> [   16.242004] gpiochip_add: registered GPIOs 192 to 211 on device: twl4030
>
>
>> 4. Remove the gpio-twl4030 module
>> 5. Re-load the gpio-twl4030.ko module
>>
>> and report back what you get.  Thanks.


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

* [PATCH 0/3] omap hsmmc init cleanup and section warning fixes for v3.4 merge window
@ 2012-02-16 13:15         ` Rajendra Nayak
  0 siblings, 0 replies; 66+ messages in thread
From: Rajendra Nayak @ 2012-02-16 13:15 UTC (permalink / raw)
  To: linux-arm-kernel

On Thursday 16 February 2012 06:04 PM, Rajendra Nayak wrote:
>> Can you test something with these patches?
>>
>> 1. Build the gpio-twl4030.c as a module, but with HSMMC support built in
>> 2. Boot on the 4430SDP
>
> twl4030 gpio is used for card detect on OMAP3, so I tried this
> on my Beagle instead of 4430SDP.
> The kernel boots up but does not detect/enumerate the mmc card.
>
>> 3. Load the gpio-twl4030 module
>
> I was expecting this to now detect the card, but I instead got
> this error which seems to tell gpio-twl4030 has problems
> when built/used as a module, outside of the mmc issues.

Looks like I was mislead with the errors and though the twl4030
gpio probe was bailing out with errors, which its not.
It does seem to go ahead, does a mmc late init which registers
the mmc omap_device and hence does a platform_device_add, but the
device never seem to get probed. mmc driver is built in and
registered.

>
> # insmod gpio-twl4030.ko
> [   16.217864] twl4030_gpio twl4030_gpio: can't dispatch IRQs from modules
> [   16.242004] gpiochip_add: registered GPIOs 192 to 211 on device: twl4030
>
>
>> 4. Remove the gpio-twl4030 module
>> 5. Re-load the gpio-twl4030.ko module
>>
>> and report back what you get.  Thanks.

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

* Re: [PATCH 0/3] omap hsmmc init cleanup and section warning fixes for v3.4 merge window
  2012-02-16 13:15         ` Rajendra Nayak
@ 2012-02-16 13:51           ` Russell King - ARM Linux
  -1 siblings, 0 replies; 66+ messages in thread
From: Russell King - ARM Linux @ 2012-02-16 13:51 UTC (permalink / raw)
  To: Rajendra Nayak; +Cc: Tony Lindgren, linux-omap, linux-arm-kernel

On Thu, Feb 16, 2012 at 06:45:50PM +0530, Rajendra Nayak wrote:
> On Thursday 16 February 2012 06:04 PM, Rajendra Nayak wrote:
>>> Can you test something with these patches?
>>>
>>> 1. Build the gpio-twl4030.c as a module, but with HSMMC support built in
>>> 2. Boot on the 4430SDP
>>
>> twl4030 gpio is used for card detect on OMAP3, so I tried this
>> on my Beagle instead of 4430SDP.
>> The kernel boots up but does not detect/enumerate the mmc card.
>>
>>> 3. Load the gpio-twl4030 module
>>
>> I was expecting this to now detect the card, but I instead got
>> this error which seems to tell gpio-twl4030 has problems
>> when built/used as a module, outside of the mmc issues.
>
> Looks like I was mislead with the errors and though the twl4030
> gpio probe was bailing out with errors, which its not.
> It does seem to go ahead, does a mmc late init which registers
> the mmc omap_device and hence does a platform_device_add, but the
> device never seem to get probed. mmc driver is built in and
> registered.
>
>>
>> # insmod gpio-twl4030.ko
>> [   16.217864] twl4030_gpio twl4030_gpio: can't dispatch IRQs from modules
>> [   16.242004] gpiochip_add: registered GPIOs 192 to 211 on device: twl4030
>>
>>
>>> 4. Remove the gpio-twl4030 module
>>> 5. Re-load the gpio-twl4030.ko module
>>>
>>> and report back what you get.  Thanks.
>

(4) and (5) are the key bits of what I was asking you to do.

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

* [PATCH 0/3] omap hsmmc init cleanup and section warning fixes for v3.4 merge window
@ 2012-02-16 13:51           ` Russell King - ARM Linux
  0 siblings, 0 replies; 66+ messages in thread
From: Russell King - ARM Linux @ 2012-02-16 13:51 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Feb 16, 2012 at 06:45:50PM +0530, Rajendra Nayak wrote:
> On Thursday 16 February 2012 06:04 PM, Rajendra Nayak wrote:
>>> Can you test something with these patches?
>>>
>>> 1. Build the gpio-twl4030.c as a module, but with HSMMC support built in
>>> 2. Boot on the 4430SDP
>>
>> twl4030 gpio is used for card detect on OMAP3, so I tried this
>> on my Beagle instead of 4430SDP.
>> The kernel boots up but does not detect/enumerate the mmc card.
>>
>>> 3. Load the gpio-twl4030 module
>>
>> I was expecting this to now detect the card, but I instead got
>> this error which seems to tell gpio-twl4030 has problems
>> when built/used as a module, outside of the mmc issues.
>
> Looks like I was mislead with the errors and though the twl4030
> gpio probe was bailing out with errors, which its not.
> It does seem to go ahead, does a mmc late init which registers
> the mmc omap_device and hence does a platform_device_add, but the
> device never seem to get probed. mmc driver is built in and
> registered.
>
>>
>> # insmod gpio-twl4030.ko
>> [   16.217864] twl4030_gpio twl4030_gpio: can't dispatch IRQs from modules
>> [   16.242004] gpiochip_add: registered GPIOs 192 to 211 on device: twl4030
>>
>>
>>> 4. Remove the gpio-twl4030 module
>>> 5. Re-load the gpio-twl4030.ko module
>>>
>>> and report back what you get.  Thanks.
>

(4) and (5) are the key bits of what I was asking you to do.

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

* Re: [PATCH 2/3] ARM: OMAP2+: Split omap2_hsmmc_init() to properly support I2C GPIO pins
  2012-02-16 10:13       ` Rajendra Nayak
@ 2012-02-16 16:35         ` Tony Lindgren
  -1 siblings, 0 replies; 66+ messages in thread
From: Tony Lindgren @ 2012-02-16 16:35 UTC (permalink / raw)
  To: Rajendra Nayak; +Cc: linux-arm-kernel, Russell King, linux-omap

* Rajendra Nayak <rnayak@ti.com> [120216 01:42]:
> On Thursday 16 February 2012 03:33 PM, Rajendra Nayak wrote:
> >better still, I think we should just populate them statically in
> >omap2_hsmmc_info struct above, so omap_hsmmc_init() takes care
> >of it already.
> 
> I just tried this and it seems to work...
> 
> ---
>  arch/arm/mach-omap2/board-omap3beagle.c |    1 +
>  1 file changed, 1 insertion(+)
> 
> Index: linux-2.6/arch/arm/mach-omap2/board-omap3beagle.c
> ===================================================================
> --- linux-2.6.orig/arch/arm/mach-omap2/board-omap3beagle.c
> 2012-02-16 15:38:47.046933403 +0530
> +++ linux-2.6/arch/arm/mach-omap2/board-omap3beagle.c   2012-02-16
> 15:40:17.355349064 +0530
> @@ -253,6 +253,7 @@
>                 .mmc            = 1,
>                 .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
>                 .gpio_wp        = -EINVAL,
> +               .gpio_cd        = OMAP_MAX_GPIO_LINES + 0,
>                 .deferred       = true,
>         },
>         {}      /* Terminator */

Would be nice to avoid the hard coded gpio numbering for the
external chips though..

Tony

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

* [PATCH 2/3] ARM: OMAP2+: Split omap2_hsmmc_init() to properly support I2C GPIO pins
@ 2012-02-16 16:35         ` Tony Lindgren
  0 siblings, 0 replies; 66+ messages in thread
From: Tony Lindgren @ 2012-02-16 16:35 UTC (permalink / raw)
  To: linux-arm-kernel

* Rajendra Nayak <rnayak@ti.com> [120216 01:42]:
> On Thursday 16 February 2012 03:33 PM, Rajendra Nayak wrote:
> >better still, I think we should just populate them statically in
> >omap2_hsmmc_info struct above, so omap_hsmmc_init() takes care
> >of it already.
> 
> I just tried this and it seems to work...
> 
> ---
>  arch/arm/mach-omap2/board-omap3beagle.c |    1 +
>  1 file changed, 1 insertion(+)
> 
> Index: linux-2.6/arch/arm/mach-omap2/board-omap3beagle.c
> ===================================================================
> --- linux-2.6.orig/arch/arm/mach-omap2/board-omap3beagle.c
> 2012-02-16 15:38:47.046933403 +0530
> +++ linux-2.6/arch/arm/mach-omap2/board-omap3beagle.c   2012-02-16
> 15:40:17.355349064 +0530
> @@ -253,6 +253,7 @@
>                 .mmc            = 1,
>                 .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
>                 .gpio_wp        = -EINVAL,
> +               .gpio_cd        = OMAP_MAX_GPIO_LINES + 0,
>                 .deferred       = true,
>         },
>         {}      /* Terminator */

Would be nice to avoid the hard coded gpio numbering for the
external chips though..

Tony

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

* Re: [PATCH 3/3] ARM: OMAP2+: Mark omap_hsmmc_init and omap_mux related functions as __init
  2012-02-16 10:11     ` Russell King - ARM Linux
@ 2012-02-16 16:41       ` Tony Lindgren
  -1 siblings, 0 replies; 66+ messages in thread
From: Tony Lindgren @ 2012-02-16 16:41 UTC (permalink / raw)
  To: Russell King - ARM Linux; +Cc: linux-arm-kernel, linux-omap

* Russell King - ARM Linux <linux@arm.linux.org.uk> [120216 01:40]:
> On Wed, Feb 15, 2012 at 10:28:30AM -0800, Tony Lindgren wrote:
> > Now that omap hsmmc init is split into two functions, it's safe
> > to mark omap_hsmmc_init and omap_mux related functions to __init.
> > 
> > This basically reverts the following fixes for the case where
> > TWL was compiled as a module:
> > 
> > d5de63 (ARM: omap: preemptively fix section mismatch in omap4_sdp4430_wifi_mux_init())
> 
> Why did you include this one?  This is unrelated to the TWL problems.

Oops sorry, thanks for noticing. Your patch makes it __init,
I was reading the patch wrong way around. Your patch should
stay and my patch now changes it the wrong way.

Regards,

Tony

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

* [PATCH 3/3] ARM: OMAP2+: Mark omap_hsmmc_init and omap_mux related functions as __init
@ 2012-02-16 16:41       ` Tony Lindgren
  0 siblings, 0 replies; 66+ messages in thread
From: Tony Lindgren @ 2012-02-16 16:41 UTC (permalink / raw)
  To: linux-arm-kernel

* Russell King - ARM Linux <linux@arm.linux.org.uk> [120216 01:40]:
> On Wed, Feb 15, 2012 at 10:28:30AM -0800, Tony Lindgren wrote:
> > Now that omap hsmmc init is split into two functions, it's safe
> > to mark omap_hsmmc_init and omap_mux related functions to __init.
> > 
> > This basically reverts the following fixes for the case where
> > TWL was compiled as a module:
> > 
> > d5de63 (ARM: omap: preemptively fix section mismatch in omap4_sdp4430_wifi_mux_init())
> 
> Why did you include this one?  This is unrelated to the TWL problems.

Oops sorry, thanks for noticing. Your patch makes it __init,
I was reading the patch wrong way around. Your patch should
stay and my patch now changes it the wrong way.

Regards,

Tony

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

* Re: [PATCH 2/3] ARM: OMAP2+: Split omap2_hsmmc_init() to properly support I2C GPIO pins
  2012-02-15 18:28   ` Tony Lindgren
@ 2012-02-16 16:45     ` Tony Lindgren
  -1 siblings, 0 replies; 66+ messages in thread
From: Tony Lindgren @ 2012-02-16 16:45 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: Russell King, linux-omap

* Tony Lindgren <tony@atomide.com> [120215 09:57]:
>  
> +void omap_hsmmc_late_init(struct omap2_hsmmc_info *controllers)
> +{
> +	struct platform_device *pdev;
> +	int res;
> +
> +	for (; controllers->mmc; controllers++) {
> +		if (!controllers->deferred)
> +			continue;
> +
> +		pdev = controllers->pdev;
> +		if (!pdev)
> +			continue;
> +
> +		res = omap_device_register(pdev);
> +		if (res) {
> +			pr_err("Could not late init MMC %s\n",
> +			       controllers->name);
> +			continue;
> +		}
> +	}
> +}

Most likely there's no need to pass struct omap2_hsmmc_info *controllers
to omap_hsmmc_late_init() here. And I'll also take a look at making
it a completion to make it more generic across various PMICs.

Tony

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

* [PATCH 2/3] ARM: OMAP2+: Split omap2_hsmmc_init() to properly support I2C GPIO pins
@ 2012-02-16 16:45     ` Tony Lindgren
  0 siblings, 0 replies; 66+ messages in thread
From: Tony Lindgren @ 2012-02-16 16:45 UTC (permalink / raw)
  To: linux-arm-kernel

* Tony Lindgren <tony@atomide.com> [120215 09:57]:
>  
> +void omap_hsmmc_late_init(struct omap2_hsmmc_info *controllers)
> +{
> +	struct platform_device *pdev;
> +	int res;
> +
> +	for (; controllers->mmc; controllers++) {
> +		if (!controllers->deferred)
> +			continue;
> +
> +		pdev = controllers->pdev;
> +		if (!pdev)
> +			continue;
> +
> +		res = omap_device_register(pdev);
> +		if (res) {
> +			pr_err("Could not late init MMC %s\n",
> +			       controllers->name);
> +			continue;
> +		}
> +	}
> +}

Most likely there's no need to pass struct omap2_hsmmc_info *controllers
to omap_hsmmc_late_init() here. And I'll also take a look at making
it a completion to make it more generic across various PMICs.

Tony

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

* Re: [PATCH 2/3] ARM: OMAP2+: Split omap2_hsmmc_init() to properly support I2C GPIO pins
  2012-02-16 16:35         ` Tony Lindgren
@ 2012-02-16 16:46           ` Cousson, Benoit
  -1 siblings, 0 replies; 66+ messages in thread
From: Cousson, Benoit @ 2012-02-16 16:46 UTC (permalink / raw)
  To: Tony Lindgren; +Cc: Rajendra Nayak, linux-arm-kernel, Russell King, linux-omap

On 2/16/2012 5:35 PM, Tony Lindgren wrote:
> * Rajendra Nayak<rnayak@ti.com>  [120216 01:42]:
>> On Thursday 16 February 2012 03:33 PM, Rajendra Nayak wrote:
>>> better still, I think we should just populate them statically in
>>> omap2_hsmmc_info struct above, so omap_hsmmc_init() takes care
>>> of it already.
>>
>> I just tried this and it seems to work...
>>
>> ---
>>   arch/arm/mach-omap2/board-omap3beagle.c |    1 +
>>   1 file changed, 1 insertion(+)
>>
>> Index: linux-2.6/arch/arm/mach-omap2/board-omap3beagle.c
>> ===================================================================
>> --- linux-2.6.orig/arch/arm/mach-omap2/board-omap3beagle.c
>> 2012-02-16 15:38:47.046933403 +0530
>> +++ linux-2.6/arch/arm/mach-omap2/board-omap3beagle.c   2012-02-16
>> 15:40:17.355349064 +0530
>> @@ -253,6 +253,7 @@
>>                  .mmc            = 1,
>>                  .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
>>                  .gpio_wp        = -EINVAL,
>> +               .gpio_cd        = OMAP_MAX_GPIO_LINES + 0,
>>                  .deferred       = true,
>>          },
>>          {}      /* Terminator */
>
> Would be nice to avoid the hard coded gpio numbering for the
> external chips though..

DT will fix that properly, but I think that any non-DT approach will 
anyway be hacky and require centralized hard coded global GPIO number 
like it is done for the IRQ so far.

Regards,
Benoit

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

* [PATCH 2/3] ARM: OMAP2+: Split omap2_hsmmc_init() to properly support I2C GPIO pins
@ 2012-02-16 16:46           ` Cousson, Benoit
  0 siblings, 0 replies; 66+ messages in thread
From: Cousson, Benoit @ 2012-02-16 16:46 UTC (permalink / raw)
  To: linux-arm-kernel

On 2/16/2012 5:35 PM, Tony Lindgren wrote:
> * Rajendra Nayak<rnayak@ti.com>  [120216 01:42]:
>> On Thursday 16 February 2012 03:33 PM, Rajendra Nayak wrote:
>>> better still, I think we should just populate them statically in
>>> omap2_hsmmc_info struct above, so omap_hsmmc_init() takes care
>>> of it already.
>>
>> I just tried this and it seems to work...
>>
>> ---
>>   arch/arm/mach-omap2/board-omap3beagle.c |    1 +
>>   1 file changed, 1 insertion(+)
>>
>> Index: linux-2.6/arch/arm/mach-omap2/board-omap3beagle.c
>> ===================================================================
>> --- linux-2.6.orig/arch/arm/mach-omap2/board-omap3beagle.c
>> 2012-02-16 15:38:47.046933403 +0530
>> +++ linux-2.6/arch/arm/mach-omap2/board-omap3beagle.c   2012-02-16
>> 15:40:17.355349064 +0530
>> @@ -253,6 +253,7 @@
>>                  .mmc            = 1,
>>                  .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
>>                  .gpio_wp        = -EINVAL,
>> +               .gpio_cd        = OMAP_MAX_GPIO_LINES + 0,
>>                  .deferred       = true,
>>          },
>>          {}      /* Terminator */
>
> Would be nice to avoid the hard coded gpio numbering for the
> external chips though..

DT will fix that properly, but I think that any non-DT approach will 
anyway be hacky and require centralized hard coded global GPIO number 
like it is done for the IRQ so far.

Regards,
Benoit

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

* Re: [PATCH 2/3] ARM: OMAP2+: Split omap2_hsmmc_init() to properly support I2C GPIO pins
  2012-02-16 16:35         ` Tony Lindgren
@ 2012-02-16 16:51           ` Rajendra Nayak
  -1 siblings, 0 replies; 66+ messages in thread
From: Rajendra Nayak @ 2012-02-16 16:51 UTC (permalink / raw)
  To: Tony Lindgren; +Cc: linux-arm-kernel, Russell King, linux-omap

On Thursday 16 February 2012 10:05 PM, Tony Lindgren wrote:
>> On Thursday 16 February 2012 03:33 PM, Rajendra Nayak wrote:
>>> >  >better still, I think we should just populate them statically in
>>> >  >omap2_hsmmc_info struct above, so omap_hsmmc_init() takes care
>>> >  >of it already.
>> >
>> >  I just tried this and it seems to work...
>> >
>> >  ---
>> >    arch/arm/mach-omap2/board-omap3beagle.c |    1 +
>> >    1 file changed, 1 insertion(+)
>> >
>> >  Index: linux-2.6/arch/arm/mach-omap2/board-omap3beagle.c
>> >  ===================================================================
>> >  --- linux-2.6.orig/arch/arm/mach-omap2/board-omap3beagle.c
>> >  2012-02-16 15:38:47.046933403 +0530
>> >  +++ linux-2.6/arch/arm/mach-omap2/board-omap3beagle.c   2012-02-16
>> >  15:40:17.355349064 +0530
>> >  @@ -253,6 +253,7 @@
>> >                   .mmc            = 1,
>> >                   .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
>> >                   .gpio_wp        = -EINVAL,
>> >  +               .gpio_cd        = OMAP_MAX_GPIO_LINES + 0,
>> >                   .deferred       = true,
>> >           },
>> >           {}      /* Terminator */
> Would be nice to avoid the hard coded gpio numbering for the
> external chips though..

But if you look closely, thats exactly how its handled today.
All board files hardcode gpio_base to OMAP_MAX_GPIO_LINES in
twl4030_gpio_platform_data. And thats what gets passed back
when the driver calls pdata->setup() from within probe.

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

* [PATCH 2/3] ARM: OMAP2+: Split omap2_hsmmc_init() to properly support I2C GPIO pins
@ 2012-02-16 16:51           ` Rajendra Nayak
  0 siblings, 0 replies; 66+ messages in thread
From: Rajendra Nayak @ 2012-02-16 16:51 UTC (permalink / raw)
  To: linux-arm-kernel

On Thursday 16 February 2012 10:05 PM, Tony Lindgren wrote:
>> On Thursday 16 February 2012 03:33 PM, Rajendra Nayak wrote:
>>> >  >better still, I think we should just populate them statically in
>>> >  >omap2_hsmmc_info struct above, so omap_hsmmc_init() takes care
>>> >  >of it already.
>> >
>> >  I just tried this and it seems to work...
>> >
>> >  ---
>> >    arch/arm/mach-omap2/board-omap3beagle.c |    1 +
>> >    1 file changed, 1 insertion(+)
>> >
>> >  Index: linux-2.6/arch/arm/mach-omap2/board-omap3beagle.c
>> >  ===================================================================
>> >  --- linux-2.6.orig/arch/arm/mach-omap2/board-omap3beagle.c
>> >  2012-02-16 15:38:47.046933403 +0530
>> >  +++ linux-2.6/arch/arm/mach-omap2/board-omap3beagle.c   2012-02-16
>> >  15:40:17.355349064 +0530
>> >  @@ -253,6 +253,7 @@
>> >                   .mmc            = 1,
>> >                   .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
>> >                   .gpio_wp        = -EINVAL,
>> >  +               .gpio_cd        = OMAP_MAX_GPIO_LINES + 0,
>> >                   .deferred       = true,
>> >           },
>> >           {}      /* Terminator */
> Would be nice to avoid the hard coded gpio numbering for the
> external chips though..

But if you look closely, thats exactly how its handled today.
All board files hardcode gpio_base to OMAP_MAX_GPIO_LINES in
twl4030_gpio_platform_data. And thats what gets passed back
when the driver calls pdata->setup() from within probe.

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

* Re: [PATCH 2/3] ARM: OMAP2+: Split omap2_hsmmc_init() to properly support I2C GPIO pins
  2012-02-16 16:51           ` Rajendra Nayak
@ 2012-02-16 17:06             ` Tony Lindgren
  -1 siblings, 0 replies; 66+ messages in thread
From: Tony Lindgren @ 2012-02-16 17:06 UTC (permalink / raw)
  To: Rajendra Nayak; +Cc: linux-arm-kernel, Russell King, linux-omap

* Rajendra Nayak <rnayak@ti.com> [120216 08:19]:
> On Thursday 16 February 2012 10:05 PM, Tony Lindgren wrote:
> >>On Thursday 16 February 2012 03:33 PM, Rajendra Nayak wrote:
> >>>>  >better still, I think we should just populate them statically in
> >>>>  >omap2_hsmmc_info struct above, so omap_hsmmc_init() takes care
> >>>>  >of it already.
> >>>
> >>>  I just tried this and it seems to work...
> >>>
> >>>  ---
> >>>    arch/arm/mach-omap2/board-omap3beagle.c |    1 +
> >>>    1 file changed, 1 insertion(+)
> >>>
> >>>  Index: linux-2.6/arch/arm/mach-omap2/board-omap3beagle.c
> >>>  ===================================================================
> >>>  --- linux-2.6.orig/arch/arm/mach-omap2/board-omap3beagle.c
> >>>  2012-02-16 15:38:47.046933403 +0530
> >>>  +++ linux-2.6/arch/arm/mach-omap2/board-omap3beagle.c   2012-02-16
> >>>  15:40:17.355349064 +0530
> >>>  @@ -253,6 +253,7 @@
> >>>                   .mmc            = 1,
> >>>                   .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
> >>>                   .gpio_wp        = -EINVAL,
> >>>  +               .gpio_cd        = OMAP_MAX_GPIO_LINES + 0,
> >>>                   .deferred       = true,
> >>>           },
> >>>           {}      /* Terminator */
> >Would be nice to avoid the hard coded gpio numbering for the
> >external chips though..
> 
> But if you look closely, thats exactly how its handled today.
> All board files hardcode gpio_base to OMAP_MAX_GPIO_LINES in
> twl4030_gpio_platform_data. And thats what gets passed back
> when the driver calls pdata->setup() from within probe.

Hmm that's not necessarily safe to do as you might have multiple
external GPIO connected, such as a PMIC and FPGA..

Anyways, it seems OK to me for now, as the DT solves that issue
properly and I don't think we currently have any boards with
multiple external GPIO chips.

Regards,

Tony

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

* [PATCH 2/3] ARM: OMAP2+: Split omap2_hsmmc_init() to properly support I2C GPIO pins
@ 2012-02-16 17:06             ` Tony Lindgren
  0 siblings, 0 replies; 66+ messages in thread
From: Tony Lindgren @ 2012-02-16 17:06 UTC (permalink / raw)
  To: linux-arm-kernel

* Rajendra Nayak <rnayak@ti.com> [120216 08:19]:
> On Thursday 16 February 2012 10:05 PM, Tony Lindgren wrote:
> >>On Thursday 16 February 2012 03:33 PM, Rajendra Nayak wrote:
> >>>>  >better still, I think we should just populate them statically in
> >>>>  >omap2_hsmmc_info struct above, so omap_hsmmc_init() takes care
> >>>>  >of it already.
> >>>
> >>>  I just tried this and it seems to work...
> >>>
> >>>  ---
> >>>    arch/arm/mach-omap2/board-omap3beagle.c |    1 +
> >>>    1 file changed, 1 insertion(+)
> >>>
> >>>  Index: linux-2.6/arch/arm/mach-omap2/board-omap3beagle.c
> >>>  ===================================================================
> >>>  --- linux-2.6.orig/arch/arm/mach-omap2/board-omap3beagle.c
> >>>  2012-02-16 15:38:47.046933403 +0530
> >>>  +++ linux-2.6/arch/arm/mach-omap2/board-omap3beagle.c   2012-02-16
> >>>  15:40:17.355349064 +0530
> >>>  @@ -253,6 +253,7 @@
> >>>                   .mmc            = 1,
> >>>                   .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
> >>>                   .gpio_wp        = -EINVAL,
> >>>  +               .gpio_cd        = OMAP_MAX_GPIO_LINES + 0,
> >>>                   .deferred       = true,
> >>>           },
> >>>           {}      /* Terminator */
> >Would be nice to avoid the hard coded gpio numbering for the
> >external chips though..
> 
> But if you look closely, thats exactly how its handled today.
> All board files hardcode gpio_base to OMAP_MAX_GPIO_LINES in
> twl4030_gpio_platform_data. And thats what gets passed back
> when the driver calls pdata->setup() from within probe.

Hmm that's not necessarily safe to do as you might have multiple
external GPIO connected, such as a PMIC and FPGA..

Anyways, it seems OK to me for now, as the DT solves that issue
properly and I don't think we currently have any boards with
multiple external GPIO chips.

Regards,

Tony

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

* Re: [PATCH 0/3] omap hsmmc init cleanup and section warning fixes for v3.4 merge window
  2012-02-16 13:51           ` Russell King - ARM Linux
@ 2012-02-17  9:14             ` Russell King - ARM Linux
  -1 siblings, 0 replies; 66+ messages in thread
From: Russell King - ARM Linux @ 2012-02-17  9:14 UTC (permalink / raw)
  To: Rajendra Nayak; +Cc: Tony Lindgren, linux-omap, linux-arm-kernel

On Thu, Feb 16, 2012 at 01:51:51PM +0000, Russell King - ARM Linux wrote:
> On Thu, Feb 16, 2012 at 06:45:50PM +0530, Rajendra Nayak wrote:
> > On Thursday 16 February 2012 06:04 PM, Rajendra Nayak wrote:
> >>> Can you test something with these patches?
> >>>
> >>> 1. Build the gpio-twl4030.c as a module, but with HSMMC support built in
> >>> 2. Boot on the 4430SDP
> >>
> >> twl4030 gpio is used for card detect on OMAP3, so I tried this
> >> on my Beagle instead of 4430SDP.
> >> The kernel boots up but does not detect/enumerate the mmc card.
> >>
> >>> 3. Load the gpio-twl4030 module
> >>
> >> I was expecting this to now detect the card, but I instead got
> >> this error which seems to tell gpio-twl4030 has problems
> >> when built/used as a module, outside of the mmc issues.
> >
> > Looks like I was mislead with the errors and though the twl4030
> > gpio probe was bailing out with errors, which its not.
> > It does seem to go ahead, does a mmc late init which registers
> > the mmc omap_device and hence does a platform_device_add, but the
> > device never seem to get probed. mmc driver is built in and
> > registered.
> >
> >>
> >> # insmod gpio-twl4030.ko
> >> [   16.217864] twl4030_gpio twl4030_gpio: can't dispatch IRQs from modules
> >> [   16.242004] gpiochip_add: registered GPIOs 192 to 211 on device: twl4030
> >>
> >>
> >>> 4. Remove the gpio-twl4030 module
> >>> 5. Re-load the gpio-twl4030.ko module
> >>>
> >>> and report back what you get.  Thanks.
> >
> 
> (4) and (5) are the key bits of what I was asking you to do.

Okay, so that was a total waste of time and effort, because you didn't do
what I asked.

Tony: I think there's a bug here - if the gpio-twl4030 module is inserted,
removed and re-inserted, I think we'll end up creating the devices for MMC
twice with the same name, resulting in sysfs complaining very loudly.

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

* [PATCH 0/3] omap hsmmc init cleanup and section warning fixes for v3.4 merge window
@ 2012-02-17  9:14             ` Russell King - ARM Linux
  0 siblings, 0 replies; 66+ messages in thread
From: Russell King - ARM Linux @ 2012-02-17  9:14 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Feb 16, 2012 at 01:51:51PM +0000, Russell King - ARM Linux wrote:
> On Thu, Feb 16, 2012 at 06:45:50PM +0530, Rajendra Nayak wrote:
> > On Thursday 16 February 2012 06:04 PM, Rajendra Nayak wrote:
> >>> Can you test something with these patches?
> >>>
> >>> 1. Build the gpio-twl4030.c as a module, but with HSMMC support built in
> >>> 2. Boot on the 4430SDP
> >>
> >> twl4030 gpio is used for card detect on OMAP3, so I tried this
> >> on my Beagle instead of 4430SDP.
> >> The kernel boots up but does not detect/enumerate the mmc card.
> >>
> >>> 3. Load the gpio-twl4030 module
> >>
> >> I was expecting this to now detect the card, but I instead got
> >> this error which seems to tell gpio-twl4030 has problems
> >> when built/used as a module, outside of the mmc issues.
> >
> > Looks like I was mislead with the errors and though the twl4030
> > gpio probe was bailing out with errors, which its not.
> > It does seem to go ahead, does a mmc late init which registers
> > the mmc omap_device and hence does a platform_device_add, but the
> > device never seem to get probed. mmc driver is built in and
> > registered.
> >
> >>
> >> # insmod gpio-twl4030.ko
> >> [   16.217864] twl4030_gpio twl4030_gpio: can't dispatch IRQs from modules
> >> [   16.242004] gpiochip_add: registered GPIOs 192 to 211 on device: twl4030
> >>
> >>
> >>> 4. Remove the gpio-twl4030 module
> >>> 5. Re-load the gpio-twl4030.ko module
> >>>
> >>> and report back what you get.  Thanks.
> >
> 
> (4) and (5) are the key bits of what I was asking you to do.

Okay, so that was a total waste of time and effort, because you didn't do
what I asked.

Tony: I think there's a bug here - if the gpio-twl4030 module is inserted,
removed and re-inserted, I think we'll end up creating the devices for MMC
twice with the same name, resulting in sysfs complaining very loudly.

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

* Re: [PATCH 0/3] omap hsmmc init cleanup and section warning fixes for v3.4 merge window
  2012-02-17  9:14             ` Russell King - ARM Linux
@ 2012-02-17  9:33               ` Rajendra Nayak
  -1 siblings, 0 replies; 66+ messages in thread
From: Rajendra Nayak @ 2012-02-17  9:33 UTC (permalink / raw)
  To: Russell King - ARM Linux; +Cc: Tony Lindgren, linux-omap, linux-arm-kernel

[]...
>>>>> 3. Load the gpio-twl4030 module
>>>>
>>>> I was expecting this to now detect the card, but I instead got
>>>> this error which seems to tell gpio-twl4030 has problems
>>>> when built/used as a module, outside of the mmc issues.
>>>
>>> Looks like I was mislead with the errors and though the twl4030
>>> gpio probe was bailing out with errors, which its not.
>>> It does seem to go ahead, does a mmc late init which registers
>>> the mmc omap_device and hence does a platform_device_add, but the
>>> device never seem to get probed. mmc driver is built in and
>>> registered.
>>>
>>>>
>>>> # insmod gpio-twl4030.ko
>>>> [   16.217864] twl4030_gpio twl4030_gpio: can't dispatch IRQs from modules
>>>> [   16.242004] gpiochip_add: registered GPIOs 192 to 211 on device: twl4030
>>>>
>>>>
>>>>> 4. Remove the gpio-twl4030 module
>>>>> 5. Re-load the gpio-twl4030.ko module
>>>>>
>>>>> and report back what you get.  Thanks.
>>>
>>
>> (4) and (5) are the key bits of what I was asking you to do.
>
> Okay, so that was a total waste of time and effort, because you didn't do
> what I asked.

Sorry, I did'nt repond back because I wanted to get this resolved
completely before I did.

(3) did not probe the inserted mmc device because the driver was
doing a platform_driver_probe() and not a platform_driver_register().

Once I fixed that and removed the __init from probe, I then hit a
failure with gpio_to_irq() call in the mmc driver probe.

This was beacuse the twl gpio driver does not register irqs as said by 
this error at driver load...
 >>>> [   16.217864] twl4030_gpio twl4030_gpio: can't dispatch IRQs from 
modules
... apparently because there is no way to unregister a irq once the
module is unloaded.

That makes sdmmc pretty much unusable if twl gpio is built as a module.

>
> Tony: I think there's a bug here - if the gpio-twl4030 module is inserted,
> removed and re-inserted, I think we'll end up creating the devices for MMC
> twice with the same name, resulting in sysfs complaining very loudly.

I still went ahead and tried (4) becasue I knew I would hit the above
issue. However I end up with a rmmod complaining 'resource temporarily
unavailable' because I see there are 3 gpio_requests, which I found
were from the .setup callback in the board file (I am using beagle).
The beagle board file does not seem to however register a .teardown
hook provided by twl4030 gpio platform_data structure to do a gpio_free.
So I am now trying to get the teardown function clean stuff up including
unregister the mmc device, which should also fix the problem with
multiple mmc device register that you reported with insmod/rmmod/insmod
  sequence.

I will post patches on top of Tony's series to fix all these issues.



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

* [PATCH 0/3] omap hsmmc init cleanup and section warning fixes for v3.4 merge window
@ 2012-02-17  9:33               ` Rajendra Nayak
  0 siblings, 0 replies; 66+ messages in thread
From: Rajendra Nayak @ 2012-02-17  9:33 UTC (permalink / raw)
  To: linux-arm-kernel

[]...
>>>>> 3. Load the gpio-twl4030 module
>>>>
>>>> I was expecting this to now detect the card, but I instead got
>>>> this error which seems to tell gpio-twl4030 has problems
>>>> when built/used as a module, outside of the mmc issues.
>>>
>>> Looks like I was mislead with the errors and though the twl4030
>>> gpio probe was bailing out with errors, which its not.
>>> It does seem to go ahead, does a mmc late init which registers
>>> the mmc omap_device and hence does a platform_device_add, but the
>>> device never seem to get probed. mmc driver is built in and
>>> registered.
>>>
>>>>
>>>> # insmod gpio-twl4030.ko
>>>> [   16.217864] twl4030_gpio twl4030_gpio: can't dispatch IRQs from modules
>>>> [   16.242004] gpiochip_add: registered GPIOs 192 to 211 on device: twl4030
>>>>
>>>>
>>>>> 4. Remove the gpio-twl4030 module
>>>>> 5. Re-load the gpio-twl4030.ko module
>>>>>
>>>>> and report back what you get.  Thanks.
>>>
>>
>> (4) and (5) are the key bits of what I was asking you to do.
>
> Okay, so that was a total waste of time and effort, because you didn't do
> what I asked.

Sorry, I did'nt repond back because I wanted to get this resolved
completely before I did.

(3) did not probe the inserted mmc device because the driver was
doing a platform_driver_probe() and not a platform_driver_register().

Once I fixed that and removed the __init from probe, I then hit a
failure with gpio_to_irq() call in the mmc driver probe.

This was beacuse the twl gpio driver does not register irqs as said by 
this error at driver load...
 >>>> [   16.217864] twl4030_gpio twl4030_gpio: can't dispatch IRQs from 
modules
... apparently because there is no way to unregister a irq once the
module is unloaded.

That makes sdmmc pretty much unusable if twl gpio is built as a module.

>
> Tony: I think there's a bug here - if the gpio-twl4030 module is inserted,
> removed and re-inserted, I think we'll end up creating the devices for MMC
> twice with the same name, resulting in sysfs complaining very loudly.

I still went ahead and tried (4) becasue I knew I would hit the above
issue. However I end up with a rmmod complaining 'resource temporarily
unavailable' because I see there are 3 gpio_requests, which I found
were from the .setup callback in the board file (I am using beagle).
The beagle board file does not seem to however register a .teardown
hook provided by twl4030 gpio platform_data structure to do a gpio_free.
So I am now trying to get the teardown function clean stuff up including
unregister the mmc device, which should also fix the problem with
multiple mmc device register that you reported with insmod/rmmod/insmod
  sequence.

I will post patches on top of Tony's series to fix all these issues.

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

* Re: [PATCH 0/3] omap hsmmc init cleanup and section warning fixes for v3.4 merge window
  2012-02-17  9:33               ` Rajendra Nayak
@ 2012-02-17  9:37                 ` Rajendra Nayak
  -1 siblings, 0 replies; 66+ messages in thread
From: Rajendra Nayak @ 2012-02-17  9:37 UTC (permalink / raw)
  To: Russell King - ARM Linux; +Cc: Tony Lindgren, linux-omap, linux-arm-kernel

On Friday 17 February 2012 03:03 PM, Rajendra Nayak wrote:
> []...
>>>>>> 3. Load the gpio-twl4030 module
>>>>>
>>>>> I was expecting this to now detect the card, but I instead got
>>>>> this error which seems to tell gpio-twl4030 has problems
>>>>> when built/used as a module, outside of the mmc issues.
>>>>
>>>> Looks like I was mislead with the errors and though the twl4030
>>>> gpio probe was bailing out with errors, which its not.
>>>> It does seem to go ahead, does a mmc late init which registers
>>>> the mmc omap_device and hence does a platform_device_add, but the
>>>> device never seem to get probed. mmc driver is built in and
>>>> registered.
>>>>
>>>>>
>>>>> # insmod gpio-twl4030.ko
>>>>> [ 16.217864] twl4030_gpio twl4030_gpio: can't dispatch IRQs from
>>>>> modules
>>>>> [ 16.242004] gpiochip_add: registered GPIOs 192 to 211 on device:
>>>>> twl4030
>>>>>
>>>>>
>>>>>> 4. Remove the gpio-twl4030 module
>>>>>> 5. Re-load the gpio-twl4030.ko module
>>>>>>
>>>>>> and report back what you get. Thanks.
>>>>
>>>
>>> (4) and (5) are the key bits of what I was asking you to do.
>>
>> Okay, so that was a total waste of time and effort, because you didn't do
>> what I asked.
>
> Sorry, I did'nt repond back because I wanted to get this resolved
> completely before I did.
>
> (3) did not probe the inserted mmc device because the driver was
> doing a platform_driver_probe() and not a platform_driver_register().
>
> Once I fixed that and removed the __init from probe, I then hit a
> failure with gpio_to_irq() call in the mmc driver probe.
>
> This was beacuse the twl gpio driver does not register irqs as said by
> this error at driver load...
>  >>>> [ 16.217864] twl4030_gpio twl4030_gpio: can't dispatch IRQs from
> modules
> ... apparently because there is no way to unregister a irq once the
> module is unloaded.
>
> That makes sdmmc pretty much unusable if twl gpio is built as a module.
>
>>
>> Tony: I think there's a bug here - if the gpio-twl4030 module is
>> inserted,
>> removed and re-inserted, I think we'll end up creating the devices for
>> MMC
>> twice with the same name, resulting in sysfs complaining very loudly.
>
> I still went ahead and tried (4) becasue I knew I would hit the above
> issue. However I end up with a rmmod complaining 'resource temporarily
> unavailable' because I see there are 3 gpio_requests, which I found
> were from the .setup callback in the board file (I am using beagle).
> The beagle board file does not seem to however register a .teardown
> hook provided by twl4030 gpio platform_data structure to do a gpio_free.

Forgot to mention, its not just the beagle but *all* omap3 board files
with .teardown missing.

> So I am now trying to get the teardown function clean stuff up including
> unregister the mmc device, which should also fix the problem with
> multiple mmc device register that you reported with insmod/rmmod/insmod
> sequence.
>
> I will post patches on top of Tony's series to fix all these issues.
>
>


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

* [PATCH 0/3] omap hsmmc init cleanup and section warning fixes for v3.4 merge window
@ 2012-02-17  9:37                 ` Rajendra Nayak
  0 siblings, 0 replies; 66+ messages in thread
From: Rajendra Nayak @ 2012-02-17  9:37 UTC (permalink / raw)
  To: linux-arm-kernel

On Friday 17 February 2012 03:03 PM, Rajendra Nayak wrote:
> []...
>>>>>> 3. Load the gpio-twl4030 module
>>>>>
>>>>> I was expecting this to now detect the card, but I instead got
>>>>> this error which seems to tell gpio-twl4030 has problems
>>>>> when built/used as a module, outside of the mmc issues.
>>>>
>>>> Looks like I was mislead with the errors and though the twl4030
>>>> gpio probe was bailing out with errors, which its not.
>>>> It does seem to go ahead, does a mmc late init which registers
>>>> the mmc omap_device and hence does a platform_device_add, but the
>>>> device never seem to get probed. mmc driver is built in and
>>>> registered.
>>>>
>>>>>
>>>>> # insmod gpio-twl4030.ko
>>>>> [ 16.217864] twl4030_gpio twl4030_gpio: can't dispatch IRQs from
>>>>> modules
>>>>> [ 16.242004] gpiochip_add: registered GPIOs 192 to 211 on device:
>>>>> twl4030
>>>>>
>>>>>
>>>>>> 4. Remove the gpio-twl4030 module
>>>>>> 5. Re-load the gpio-twl4030.ko module
>>>>>>
>>>>>> and report back what you get. Thanks.
>>>>
>>>
>>> (4) and (5) are the key bits of what I was asking you to do.
>>
>> Okay, so that was a total waste of time and effort, because you didn't do
>> what I asked.
>
> Sorry, I did'nt repond back because I wanted to get this resolved
> completely before I did.
>
> (3) did not probe the inserted mmc device because the driver was
> doing a platform_driver_probe() and not a platform_driver_register().
>
> Once I fixed that and removed the __init from probe, I then hit a
> failure with gpio_to_irq() call in the mmc driver probe.
>
> This was beacuse the twl gpio driver does not register irqs as said by
> this error at driver load...
>  >>>> [ 16.217864] twl4030_gpio twl4030_gpio: can't dispatch IRQs from
> modules
> ... apparently because there is no way to unregister a irq once the
> module is unloaded.
>
> That makes sdmmc pretty much unusable if twl gpio is built as a module.
>
>>
>> Tony: I think there's a bug here - if the gpio-twl4030 module is
>> inserted,
>> removed and re-inserted, I think we'll end up creating the devices for
>> MMC
>> twice with the same name, resulting in sysfs complaining very loudly.
>
> I still went ahead and tried (4) becasue I knew I would hit the above
> issue. However I end up with a rmmod complaining 'resource temporarily
> unavailable' because I see there are 3 gpio_requests, which I found
> were from the .setup callback in the board file (I am using beagle).
> The beagle board file does not seem to however register a .teardown
> hook provided by twl4030 gpio platform_data structure to do a gpio_free.

Forgot to mention, its not just the beagle but *all* omap3 board files
with .teardown missing.

> So I am now trying to get the teardown function clean stuff up including
> unregister the mmc device, which should also fix the problem with
> multiple mmc device register that you reported with insmod/rmmod/insmod
> sequence.
>
> I will post patches on top of Tony's series to fix all these issues.
>
>

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

* Re: [PATCH 0/3] omap hsmmc init cleanup and section warning fixes for v3.4 merge window
  2012-02-17  9:33               ` Rajendra Nayak
@ 2012-02-17  9:59                 ` Rajendra Nayak
  -1 siblings, 0 replies; 66+ messages in thread
From: Rajendra Nayak @ 2012-02-17  9:59 UTC (permalink / raw)
  To: Russell King - ARM Linux; +Cc: Tony Lindgren, linux-omap, linux-arm-kernel

On Friday 17 February 2012 03:03 PM, Rajendra Nayak wrote:
> Sorry, I did'nt repond back because I wanted to get this resolved
> completely before I did.
>
> (3) did not probe the inserted mmc device because the driver was
> doing a platform_driver_probe() and not a platform_driver_register().
>
> Once I fixed that and removed the __init from probe, I then hit a
> failure with gpio_to_irq() call in the mmc driver probe.
>
> This was beacuse the twl gpio driver does not register irqs as said by
> this error at driver load...
>  >>>> [   16.217864] twl4030_gpio twl4030_gpio: can't dispatch IRQs from
> modules
> ... apparently because there is no way to unregister a irq once the
> module is unloaded.
>
> That makes sdmmc pretty much unusable if twl gpio is built as a module.
>
>>
>> Tony: I think there's a bug here - if the gpio-twl4030 module is
>> inserted,
>> removed and re-inserted, I think we'll end up creating the devices for
>> MMC
>> twice with the same name, resulting in sysfs complaining very loudly.
>
> I still went ahead and tried (4) becasue I knew I would hit the above
> issue. However I end up with a rmmod complaining 'resource temporarily
> unavailable' because I see there are 3 gpio_requests, which I found
> were from the .setup callback in the board file (I am using beagle).
> The beagle board file does not seem to however register a .teardown
> hook provided by twl4030 gpio platform_data structure to do a gpio_free.
> So I am now trying to get the teardown function clean stuff up including
> unregister the mmc device, which should also fix the problem with
> multiple mmc device register that you reported with insmod/rmmod/insmod
>   sequence.

hmm, rmmod does not even seem to trigger the drivers .remove if there
are outstanding requests on the module, so a pdata->teardown called
from within the .remove does not help to get the gpio_requests done
from the board file cleaned.


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

* [PATCH 0/3] omap hsmmc init cleanup and section warning fixes for v3.4 merge window
@ 2012-02-17  9:59                 ` Rajendra Nayak
  0 siblings, 0 replies; 66+ messages in thread
From: Rajendra Nayak @ 2012-02-17  9:59 UTC (permalink / raw)
  To: linux-arm-kernel

On Friday 17 February 2012 03:03 PM, Rajendra Nayak wrote:
> Sorry, I did'nt repond back because I wanted to get this resolved
> completely before I did.
>
> (3) did not probe the inserted mmc device because the driver was
> doing a platform_driver_probe() and not a platform_driver_register().
>
> Once I fixed that and removed the __init from probe, I then hit a
> failure with gpio_to_irq() call in the mmc driver probe.
>
> This was beacuse the twl gpio driver does not register irqs as said by
> this error at driver load...
>  >>>> [   16.217864] twl4030_gpio twl4030_gpio: can't dispatch IRQs from
> modules
> ... apparently because there is no way to unregister a irq once the
> module is unloaded.
>
> That makes sdmmc pretty much unusable if twl gpio is built as a module.
>
>>
>> Tony: I think there's a bug here - if the gpio-twl4030 module is
>> inserted,
>> removed and re-inserted, I think we'll end up creating the devices for
>> MMC
>> twice with the same name, resulting in sysfs complaining very loudly.
>
> I still went ahead and tried (4) becasue I knew I would hit the above
> issue. However I end up with a rmmod complaining 'resource temporarily
> unavailable' because I see there are 3 gpio_requests, which I found
> were from the .setup callback in the board file (I am using beagle).
> The beagle board file does not seem to however register a .teardown
> hook provided by twl4030 gpio platform_data structure to do a gpio_free.
> So I am now trying to get the teardown function clean stuff up including
> unregister the mmc device, which should also fix the problem with
> multiple mmc device register that you reported with insmod/rmmod/insmod
>   sequence.

hmm, rmmod does not even seem to trigger the drivers .remove if there
are outstanding requests on the module, so a pdata->teardown called
from within the .remove does not help to get the gpio_requests done
from the board file cleaned.

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

* Re: [PATCH 0/3] omap hsmmc init cleanup and section warning fixes for v3.4 merge window
  2012-02-17  9:59                 ` Rajendra Nayak
@ 2012-02-17 10:06                   ` Russell King - ARM Linux
  -1 siblings, 0 replies; 66+ messages in thread
From: Russell King - ARM Linux @ 2012-02-17 10:06 UTC (permalink / raw)
  To: Rajendra Nayak; +Cc: Tony Lindgren, linux-omap, linux-arm-kernel

On Fri, Feb 17, 2012 at 03:29:55PM +0530, Rajendra Nayak wrote:
> hmm, rmmod does not even seem to trigger the drivers .remove if there
> are outstanding requests on the module, so a pdata->teardown called
> from within the .remove does not help to get the gpio_requests done
> from the board file cleaned.

If the module use count is non-zero, then it's only right that it won't
let you remove the module.  So as far as that goes, that's fine.

However, it's still possible to unbind the device:

	echo twl4030_gpio > /sys/bus/platform/driver/twl4030_gpio/unbind

and rebind it:

	echo twl4030_gpio > /sys/bus/platform/driver/twl4030_gpio/bind

assuming that the gpios device name is twl4030_gpio and not twl4030_gpio.0.
This would be equivalent to my steps (4) and (5).

As you point out, the there's no teardown function, which suggests that
the gpios won't be able to be requested at step (5).  You'll probably
also get a WARN_ON() dump too when the hsmmc device is registered for a
second time, or maybe an oops (as it'll be a device which has already
been registered being registered for a second time).

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

* [PATCH 0/3] omap hsmmc init cleanup and section warning fixes for v3.4 merge window
@ 2012-02-17 10:06                   ` Russell King - ARM Linux
  0 siblings, 0 replies; 66+ messages in thread
From: Russell King - ARM Linux @ 2012-02-17 10:06 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Feb 17, 2012 at 03:29:55PM +0530, Rajendra Nayak wrote:
> hmm, rmmod does not even seem to trigger the drivers .remove if there
> are outstanding requests on the module, so a pdata->teardown called
> from within the .remove does not help to get the gpio_requests done
> from the board file cleaned.

If the module use count is non-zero, then it's only right that it won't
let you remove the module.  So as far as that goes, that's fine.

However, it's still possible to unbind the device:

	echo twl4030_gpio > /sys/bus/platform/driver/twl4030_gpio/unbind

and rebind it:

	echo twl4030_gpio > /sys/bus/platform/driver/twl4030_gpio/bind

assuming that the gpios device name is twl4030_gpio and not twl4030_gpio.0.
This would be equivalent to my steps (4) and (5).

As you point out, the there's no teardown function, which suggests that
the gpios won't be able to be requested at step (5).  You'll probably
also get a WARN_ON() dump too when the hsmmc device is registered for a
second time, or maybe an oops (as it'll be a device which has already
been registered being registered for a second time).

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

* Re: [PATCH 0/3] omap hsmmc init cleanup and section warning fixes for v3.4 merge window
  2012-02-17 10:06                   ` Russell King - ARM Linux
@ 2012-02-17 10:18                     ` Rajendra Nayak
  -1 siblings, 0 replies; 66+ messages in thread
From: Rajendra Nayak @ 2012-02-17 10:18 UTC (permalink / raw)
  To: Russell King - ARM Linux; +Cc: Tony Lindgren, linux-omap, linux-arm-kernel

On Friday 17 February 2012 03:36 PM, Russell King - ARM Linux wrote:
> On Fri, Feb 17, 2012 at 03:29:55PM +0530, Rajendra Nayak wrote:
>> hmm, rmmod does not even seem to trigger the drivers .remove if there
>> are outstanding requests on the module, so a pdata->teardown called
>> from within the .remove does not help to get the gpio_requests done
>> from the board file cleaned.
>
> If the module use count is non-zero, then it's only right that it won't
> let you remove the module.  So as far as that goes, that's fine.
>
> However, it's still possible to unbind the device:
>
> 	echo twl4030_gpio>  /sys/bus/platform/driver/twl4030_gpio/unbind
>
> and rebind it:
>
> 	echo twl4030_gpio>  /sys/bus/platform/driver/twl4030_gpio/bind
>
> assuming that the gpios device name is twl4030_gpio and not twl4030_gpio.0.
> This would be equivalent to my steps (4) and (5).
>
> As you point out, the there's no teardown function, which suggests that
> the gpios won't be able to be requested at step (5).  You'll probably

I now have a teardown for beagle which does free the gpios.

> also get a WARN_ON() dump too when the hsmmc device is registered for a
> second time, or maybe an oops (as it'll be a device which has already
> been registered being registered for a second time).

Yes, I did get a WARN saying the device is already registered. An 
unregister in my teardown should fix that too.

Thanks for recommending the tests.

# echo twl4030_gpio > unbind
# echo twl4030_gpio > bind
[ 1202.119354] twl4030_gpio twl4030_gpio: can't dispatch IRQs from modules
[ 1202.129913] gpiochip_add: registered GPIOs 192 to 211 on device: twl4030
[ 1202.137145] ------------[ cut here ]------------
[ 1202.142120] WARNING: at kernel/resource.c:597 
__insert_resource+0x168/0x17c()
[ 1202.149658] Modules linked in: gpio_twl4030
[ 1202.154113] [<c001bcd0>] (unwind_backtrace+0x0/0xf4) from 
[<c0042040>] (warn_slowpath_common+0x4c/0x64)
[ 1202.164062] [<c0042040>] (warn_slowpath_common+0x4c/0x64) from 
[<c0042074>] (warn_slowpath_null+0x1c/0x24)
[ 1202.174285] [<c0042074>] (warn_slowpath_null+0x1c/0x24) from 
[<c004a5c0>] (__insert_resource+0x168/0x17c)
[ 1202.184387] [<c004a5c0>] (__insert_resource+0x168/0x17c) from 
[<c004a75c>] (insert_resource_conflict+0x24/0x3c)
[ 1202.195037] [<c004a75c>] (insert_resource_conflict+0x24/0x3c) from 
[<c004a77c>] (insert_resource+0x8/0x14)
[ 1202.205261] [<c004a7ncsert_resource+0x8/0x14) from [<c02be0a4>] 
(platform_device_add+0x70/0x20c)
[ 1202.215118] [<c02be0a4>] (platform_device_add+0x70/0x20c) from 
[<c003628c>] (omap_hsmmc_late_init+0x30/0x5c)
[ 1202.225524] [<c003628c>] (omap_hsmmc_late_init+0x30/0x5c) from 
[<c0034828>] (beagle_twl_gpio_setup+0x20/0xf4)
[ 1202.235992] [<c0034828>] (beagle_twl_gpio_setup+0x20/0xf4) from 
[<bf0005e4>] (gpio_twl4030_probe+0x1ac/0x1ec [gpio_twl4030])
[ 1202.247924] [<bf0005e4>] (gpio_twl4030_probe+0x1ac/0x1ec 
[gpio_twl4030]) from [<c02bdb50>] (platform_drv_probe+0x18/0x1c)
[ 1202.259521] [<c02bdb50>] (platform_drv_probe+0x18/0x1c) from 
[<c02bc6b4>] (driver_probe_device+0x98/0x1a0)
[ 1202.269744] [<c02bc6b4>] (driver_probe_device+0x98/0x1a0) from 
[<c02bb73c>] (driver_bind+0xac/0xe0)
[ 1202.279296] [<c02bb73c>] (driver_bind+0xac/0xe0) from [<c02bad20>] 
(drv_attr_store+0x24/0x28)
[ 1202.288360] [<c02bad20>] (drv_attr_store+0x24/0x28) from [<c0166ca4>] 
(sysfs_write_file+0xfc/0x180)
[ 1202.297943] [<c0166ca4>] (sysfs_write_file+0xfc/0x180) from 
[<c0106d80>] (vfs_write+0xb0/0x134)
[ 1202.307128] [<c0106d80>] /v0x134) from [<c0106ed4>] (sys_write+0x40/0x70)
[ 1202.315612] [<c0106ed4>] (sys_write+0x40/0x70) from [<c0014160>] 
(ret_fast_syscall+0x0/0x3c)
[ 1202.324554] ---[ end trace b395a818cb06b1ff ]---
[ 1202.329467] omap_hsmmc.0: failed to claim resource 3
[ 1202.334747] Could not late init MMC (null)


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

* [PATCH 0/3] omap hsmmc init cleanup and section warning fixes for v3.4 merge window
@ 2012-02-17 10:18                     ` Rajendra Nayak
  0 siblings, 0 replies; 66+ messages in thread
From: Rajendra Nayak @ 2012-02-17 10:18 UTC (permalink / raw)
  To: linux-arm-kernel

On Friday 17 February 2012 03:36 PM, Russell King - ARM Linux wrote:
> On Fri, Feb 17, 2012 at 03:29:55PM +0530, Rajendra Nayak wrote:
>> hmm, rmmod does not even seem to trigger the drivers .remove if there
>> are outstanding requests on the module, so a pdata->teardown called
>> from within the .remove does not help to get the gpio_requests done
>> from the board file cleaned.
>
> If the module use count is non-zero, then it's only right that it won't
> let you remove the module.  So as far as that goes, that's fine.
>
> However, it's still possible to unbind the device:
>
> 	echo twl4030_gpio>  /sys/bus/platform/driver/twl4030_gpio/unbind
>
> and rebind it:
>
> 	echo twl4030_gpio>  /sys/bus/platform/driver/twl4030_gpio/bind
>
> assuming that the gpios device name is twl4030_gpio and not twl4030_gpio.0.
> This would be equivalent to my steps (4) and (5).
>
> As you point out, the there's no teardown function, which suggests that
> the gpios won't be able to be requested at step (5).  You'll probably

I now have a teardown for beagle which does free the gpios.

> also get a WARN_ON() dump too when the hsmmc device is registered for a
> second time, or maybe an oops (as it'll be a device which has already
> been registered being registered for a second time).

Yes, I did get a WARN saying the device is already registered. An 
unregister in my teardown should fix that too.

Thanks for recommending the tests.

# echo twl4030_gpio > unbind
# echo twl4030_gpio > bind
[ 1202.119354] twl4030_gpio twl4030_gpio: can't dispatch IRQs from modules
[ 1202.129913] gpiochip_add: registered GPIOs 192 to 211 on device: twl4030
[ 1202.137145] ------------[ cut here ]------------
[ 1202.142120] WARNING: at kernel/resource.c:597 
__insert_resource+0x168/0x17c()
[ 1202.149658] Modules linked in: gpio_twl4030
[ 1202.154113] [<c001bcd0>] (unwind_backtrace+0x0/0xf4) from 
[<c0042040>] (warn_slowpath_common+0x4c/0x64)
[ 1202.164062] [<c0042040>] (warn_slowpath_common+0x4c/0x64) from 
[<c0042074>] (warn_slowpath_null+0x1c/0x24)
[ 1202.174285] [<c0042074>] (warn_slowpath_null+0x1c/0x24) from 
[<c004a5c0>] (__insert_resource+0x168/0x17c)
[ 1202.184387] [<c004a5c0>] (__insert_resource+0x168/0x17c) from 
[<c004a75c>] (insert_resource_conflict+0x24/0x3c)
[ 1202.195037] [<c004a75c>] (insert_resource_conflict+0x24/0x3c) from 
[<c004a77c>] (insert_resource+0x8/0x14)
[ 1202.205261] [<c004a7ncsert_resource+0x8/0x14) from [<c02be0a4>] 
(platform_device_add+0x70/0x20c)
[ 1202.215118] [<c02be0a4>] (platform_device_add+0x70/0x20c) from 
[<c003628c>] (omap_hsmmc_late_init+0x30/0x5c)
[ 1202.225524] [<c003628c>] (omap_hsmmc_late_init+0x30/0x5c) from 
[<c0034828>] (beagle_twl_gpio_setup+0x20/0xf4)
[ 1202.235992] [<c0034828>] (beagle_twl_gpio_setup+0x20/0xf4) from 
[<bf0005e4>] (gpio_twl4030_probe+0x1ac/0x1ec [gpio_twl4030])
[ 1202.247924] [<bf0005e4>] (gpio_twl4030_probe+0x1ac/0x1ec 
[gpio_twl4030]) from [<c02bdb50>] (platform_drv_probe+0x18/0x1c)
[ 1202.259521] [<c02bdb50>] (platform_drv_probe+0x18/0x1c) from 
[<c02bc6b4>] (driver_probe_device+0x98/0x1a0)
[ 1202.269744] [<c02bc6b4>] (driver_probe_device+0x98/0x1a0) from 
[<c02bb73c>] (driver_bind+0xac/0xe0)
[ 1202.279296] [<c02bb73c>] (driver_bind+0xac/0xe0) from [<c02bad20>] 
(drv_attr_store+0x24/0x28)
[ 1202.288360] [<c02bad20>] (drv_attr_store+0x24/0x28) from [<c0166ca4>] 
(sysfs_write_file+0xfc/0x180)
[ 1202.297943] [<c0166ca4>] (sysfs_write_file+0xfc/0x180) from 
[<c0106d80>] (vfs_write+0xb0/0x134)
[ 1202.307128] [<c0106d80>] /v0x134) from [<c0106ed4>] (sys_write+0x40/0x70)
[ 1202.315612] [<c0106ed4>] (sys_write+0x40/0x70) from [<c0014160>] 
(ret_fast_syscall+0x0/0x3c)
[ 1202.324554] ---[ end trace b395a818cb06b1ff ]---
[ 1202.329467] omap_hsmmc.0: failed to claim resource 3
[ 1202.334747] Could not late init MMC (null)

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

* Re: [PATCH 0/3] omap hsmmc init cleanup and section warning fixes for v3.4 merge window
  2012-02-17 10:18                     ` Rajendra Nayak
@ 2012-02-17 10:26                       ` Rajendra Nayak
  -1 siblings, 0 replies; 66+ messages in thread
From: Rajendra Nayak @ 2012-02-17 10:26 UTC (permalink / raw)
  To: Russell King - ARM Linux; +Cc: Tony Lindgren, linux-omap, linux-arm-kernel

On Friday 17 February 2012 03:48 PM, Rajendra Nayak wrote:
>>
>
> Yes, I did get a WARN saying the device is already registered. An
> unregister in my teardown should fix that too.

And now I see there is no way to unregister an omap_device :-)
which needs to be added.

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

* [PATCH 0/3] omap hsmmc init cleanup and section warning fixes for v3.4 merge window
@ 2012-02-17 10:26                       ` Rajendra Nayak
  0 siblings, 0 replies; 66+ messages in thread
From: Rajendra Nayak @ 2012-02-17 10:26 UTC (permalink / raw)
  To: linux-arm-kernel

On Friday 17 February 2012 03:48 PM, Rajendra Nayak wrote:
>>
>
> Yes, I did get a WARN saying the device is already registered. An
> unregister in my teardown should fix that too.

And now I see there is no way to unregister an omap_device :-)
which needs to be added.

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

* Re: [PATCH 0/3] omap hsmmc init cleanup and section warning fixes for v3.4 merge window
  2012-02-15 18:28 ` Tony Lindgren
@ 2012-02-17 14:24   ` Rajendra Nayak
  -1 siblings, 0 replies; 66+ messages in thread
From: Rajendra Nayak @ 2012-02-17 14:24 UTC (permalink / raw)
  To: Tony Lindgren; +Cc: linux-omap, linux-arm-kernel

Tony,

On Wednesday 15 February 2012 11:58 PM, Tony Lindgren wrote:
> Hi all,
>
> This series fixes up the issues noted by Russell on omap2_hsmmc_init()
> where if TWL PMIC is compiled as a module we can't keep a bunch of
> functions marked as __init like they should be. This series fixes
> the issues by splitting omap2_hsmmc_init() into two functions.

I have a re-spin of this series ready with all the fixes I did
while testing the insmod/unbind/bind test suggested by Russell.
I could not figure out what branch your original patches were
based on. So let me know what branch of your tree you want me
to post this series on.

regards,
Rajendra

>
> One more patch is needed to sort out the remaining issue with
> omap4 that has yet another luck based initialization for the
> same issue..
>
> Regards,
>
> Tony
>
> ---
>
> Ohad Ben-Cohen (1):
>        ARM: OMAP: omap_device: Expose omap_device_{alloc, delete, register}
>
> Tony Lindgren (2):
>        ARM: OMAP2+: Split omap2_hsmmc_init() to properly support I2C GPIO pins
>        ARM: OMAP2+: Mark omap_hsmmc_init and omap_mux related functions as __init
>
>
>   arch/arm/mach-omap2/board-2430sdp.c           |    2
>   arch/arm/mach-omap2/board-3430sdp.c           |    5 +
>   arch/arm/mach-omap2/board-4430sdp.c           |    6 +
>   arch/arm/mach-omap2/board-am3517evm.c         |    2
>   arch/arm/mach-omap2/board-cm-t35.c            |    6 +
>   arch/arm/mach-omap2/board-devkit8000.c        |    4 +
>   arch/arm/mach-omap2/board-flash.c             |    2
>   arch/arm/mach-omap2/board-igep0020.c          |    7 +-
>   arch/arm/mach-omap2/board-ldp.c               |    2
>   arch/arm/mach-omap2/board-omap3beagle.c       |   10 ++
>   arch/arm/mach-omap2/board-omap3evm.c          |    8 +-
>   arch/arm/mach-omap2/board-omap3logic.c        |    2
>   arch/arm/mach-omap2/board-omap3pandora.c      |    6 +
>   arch/arm/mach-omap2/board-omap3stalker.c      |   15 ++-
>   arch/arm/mach-omap2/board-omap3touchbook.c    |   17 ++--
>   arch/arm/mach-omap2/board-omap4panda.c        |    6 +
>   arch/arm/mach-omap2/board-overo.c             |    5 +
>   arch/arm/mach-omap2/board-rm680.c             |    2
>   arch/arm/mach-omap2/board-rx51-peripherals.c  |    2
>   arch/arm/mach-omap2/board-zoom-peripherals.c  |    6 +
>   arch/arm/mach-omap2/display.c                 |    8 +-
>   arch/arm/mach-omap2/hsmmc.c                   |  111 ++++++++++++++++++-------
>   arch/arm/mach-omap2/hsmmc.h                   |   12 ++-
>   arch/arm/mach-omap2/mux.c                     |   22 ++---
>   arch/arm/plat-omap/include/plat/omap_device.h |    7 ++
>   arch/arm/plat-omap/omap_device.c              |   13 +--
>   26 files changed, 192 insertions(+), 96 deletions(-)
>

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

* [PATCH 0/3] omap hsmmc init cleanup and section warning fixes for v3.4 merge window
@ 2012-02-17 14:24   ` Rajendra Nayak
  0 siblings, 0 replies; 66+ messages in thread
From: Rajendra Nayak @ 2012-02-17 14:24 UTC (permalink / raw)
  To: linux-arm-kernel

Tony,

On Wednesday 15 February 2012 11:58 PM, Tony Lindgren wrote:
> Hi all,
>
> This series fixes up the issues noted by Russell on omap2_hsmmc_init()
> where if TWL PMIC is compiled as a module we can't keep a bunch of
> functions marked as __init like they should be. This series fixes
> the issues by splitting omap2_hsmmc_init() into two functions.

I have a re-spin of this series ready with all the fixes I did
while testing the insmod/unbind/bind test suggested by Russell.
I could not figure out what branch your original patches were
based on. So let me know what branch of your tree you want me
to post this series on.

regards,
Rajendra

>
> One more patch is needed to sort out the remaining issue with
> omap4 that has yet another luck based initialization for the
> same issue..
>
> Regards,
>
> Tony
>
> ---
>
> Ohad Ben-Cohen (1):
>        ARM: OMAP: omap_device: Expose omap_device_{alloc, delete, register}
>
> Tony Lindgren (2):
>        ARM: OMAP2+: Split omap2_hsmmc_init() to properly support I2C GPIO pins
>        ARM: OMAP2+: Mark omap_hsmmc_init and omap_mux related functions as __init
>
>
>   arch/arm/mach-omap2/board-2430sdp.c           |    2
>   arch/arm/mach-omap2/board-3430sdp.c           |    5 +
>   arch/arm/mach-omap2/board-4430sdp.c           |    6 +
>   arch/arm/mach-omap2/board-am3517evm.c         |    2
>   arch/arm/mach-omap2/board-cm-t35.c            |    6 +
>   arch/arm/mach-omap2/board-devkit8000.c        |    4 +
>   arch/arm/mach-omap2/board-flash.c             |    2
>   arch/arm/mach-omap2/board-igep0020.c          |    7 +-
>   arch/arm/mach-omap2/board-ldp.c               |    2
>   arch/arm/mach-omap2/board-omap3beagle.c       |   10 ++
>   arch/arm/mach-omap2/board-omap3evm.c          |    8 +-
>   arch/arm/mach-omap2/board-omap3logic.c        |    2
>   arch/arm/mach-omap2/board-omap3pandora.c      |    6 +
>   arch/arm/mach-omap2/board-omap3stalker.c      |   15 ++-
>   arch/arm/mach-omap2/board-omap3touchbook.c    |   17 ++--
>   arch/arm/mach-omap2/board-omap4panda.c        |    6 +
>   arch/arm/mach-omap2/board-overo.c             |    5 +
>   arch/arm/mach-omap2/board-rm680.c             |    2
>   arch/arm/mach-omap2/board-rx51-peripherals.c  |    2
>   arch/arm/mach-omap2/board-zoom-peripherals.c  |    6 +
>   arch/arm/mach-omap2/display.c                 |    8 +-
>   arch/arm/mach-omap2/hsmmc.c                   |  111 ++++++++++++++++++-------
>   arch/arm/mach-omap2/hsmmc.h                   |   12 ++-
>   arch/arm/mach-omap2/mux.c                     |   22 ++---
>   arch/arm/plat-omap/include/plat/omap_device.h |    7 ++
>   arch/arm/plat-omap/omap_device.c              |   13 +--
>   26 files changed, 192 insertions(+), 96 deletions(-)
>

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

* Re: [PATCH 2/3] ARM: OMAP2+: Split omap2_hsmmc_init() to properly support I2C GPIO pins
  2012-02-16 17:06             ` Tony Lindgren
@ 2012-02-17 18:10               ` Tony Lindgren
  -1 siblings, 0 replies; 66+ messages in thread
From: Tony Lindgren @ 2012-02-17 18:10 UTC (permalink / raw)
  To: Rajendra Nayak; +Cc: linux-arm-kernel, Russell King, linux-omap

* Tony Lindgren <tony@atomide.com> [120216 08:35]:
> * Rajendra Nayak <rnayak@ti.com> [120216 08:19]:
> > On Thursday 16 February 2012 10:05 PM, Tony Lindgren wrote:
> > >>On Thursday 16 February 2012 03:33 PM, Rajendra Nayak wrote:
> > >>>>  >better still, I think we should just populate them statically in
> > >>>>  >omap2_hsmmc_info struct above, so omap_hsmmc_init() takes care
> > >>>>  >of it already.
> > >>>
> > >>>  I just tried this and it seems to work...
> > >>>
> > >>>  ---
> > >>>    arch/arm/mach-omap2/board-omap3beagle.c |    1 +
> > >>>    1 file changed, 1 insertion(+)
> > >>>
> > >>>  Index: linux-2.6/arch/arm/mach-omap2/board-omap3beagle.c
> > >>>  ===================================================================
> > >>>  --- linux-2.6.orig/arch/arm/mach-omap2/board-omap3beagle.c
> > >>>  2012-02-16 15:38:47.046933403 +0530
> > >>>  +++ linux-2.6/arch/arm/mach-omap2/board-omap3beagle.c   2012-02-16
> > >>>  15:40:17.355349064 +0530
> > >>>  @@ -253,6 +253,7 @@
> > >>>                   .mmc            = 1,
> > >>>                   .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
> > >>>                   .gpio_wp        = -EINVAL,
> > >>>  +               .gpio_cd        = OMAP_MAX_GPIO_LINES + 0,
> > >>>                   .deferred       = true,
> > >>>           },
> > >>>           {}      /* Terminator */
> > >Would be nice to avoid the hard coded gpio numbering for the
> > >external chips though..
> > 
> > But if you look closely, thats exactly how its handled today.
> > All board files hardcode gpio_base to OMAP_MAX_GPIO_LINES in
> > twl4030_gpio_platform_data. And thats what gets passed back
> > when the driver calls pdata->setup() from within probe.
> 
> Hmm that's not necessarily safe to do as you might have multiple
> external GPIO connected, such as a PMIC and FPGA..
> 
> Anyways, it seems OK to me for now, as the DT solves that issue
> properly and I don't think we currently have any boards with
> multiple external GPIO chips.

Found the reason for this, omap_hsmmc_late_init needs to copy
gpio_cd and gpio_wp into the pdata. Or platform_device_add_data
needs to be called a bit later. Will update my patch for that.

Tony

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

* [PATCH 2/3] ARM: OMAP2+: Split omap2_hsmmc_init() to properly support I2C GPIO pins
@ 2012-02-17 18:10               ` Tony Lindgren
  0 siblings, 0 replies; 66+ messages in thread
From: Tony Lindgren @ 2012-02-17 18:10 UTC (permalink / raw)
  To: linux-arm-kernel

* Tony Lindgren <tony@atomide.com> [120216 08:35]:
> * Rajendra Nayak <rnayak@ti.com> [120216 08:19]:
> > On Thursday 16 February 2012 10:05 PM, Tony Lindgren wrote:
> > >>On Thursday 16 February 2012 03:33 PM, Rajendra Nayak wrote:
> > >>>>  >better still, I think we should just populate them statically in
> > >>>>  >omap2_hsmmc_info struct above, so omap_hsmmc_init() takes care
> > >>>>  >of it already.
> > >>>
> > >>>  I just tried this and it seems to work...
> > >>>
> > >>>  ---
> > >>>    arch/arm/mach-omap2/board-omap3beagle.c |    1 +
> > >>>    1 file changed, 1 insertion(+)
> > >>>
> > >>>  Index: linux-2.6/arch/arm/mach-omap2/board-omap3beagle.c
> > >>>  ===================================================================
> > >>>  --- linux-2.6.orig/arch/arm/mach-omap2/board-omap3beagle.c
> > >>>  2012-02-16 15:38:47.046933403 +0530
> > >>>  +++ linux-2.6/arch/arm/mach-omap2/board-omap3beagle.c   2012-02-16
> > >>>  15:40:17.355349064 +0530
> > >>>  @@ -253,6 +253,7 @@
> > >>>                   .mmc            = 1,
> > >>>                   .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
> > >>>                   .gpio_wp        = -EINVAL,
> > >>>  +               .gpio_cd        = OMAP_MAX_GPIO_LINES + 0,
> > >>>                   .deferred       = true,
> > >>>           },
> > >>>           {}      /* Terminator */
> > >Would be nice to avoid the hard coded gpio numbering for the
> > >external chips though..
> > 
> > But if you look closely, thats exactly how its handled today.
> > All board files hardcode gpio_base to OMAP_MAX_GPIO_LINES in
> > twl4030_gpio_platform_data. And thats what gets passed back
> > when the driver calls pdata->setup() from within probe.
> 
> Hmm that's not necessarily safe to do as you might have multiple
> external GPIO connected, such as a PMIC and FPGA..
> 
> Anyways, it seems OK to me for now, as the DT solves that issue
> properly and I don't think we currently have any boards with
> multiple external GPIO chips.

Found the reason for this, omap_hsmmc_late_init needs to copy
gpio_cd and gpio_wp into the pdata. Or platform_device_add_data
needs to be called a bit later. Will update my patch for that.

Tony

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

* Re: [PATCH 2/3] ARM: OMAP2+: Split omap2_hsmmc_init() to properly support I2C GPIO pins
  2012-02-16 16:45     ` Tony Lindgren
@ 2012-02-17 19:05       ` Tony Lindgren
  -1 siblings, 0 replies; 66+ messages in thread
From: Tony Lindgren @ 2012-02-17 19:05 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: Russell King, linux-omap

* Tony Lindgren <tony@atomide.com> [120216 08:13]:
> * Tony Lindgren <tony@atomide.com> [120215 09:57]:
> >  
> > +void omap_hsmmc_late_init(struct omap2_hsmmc_info *controllers)
> > +{
> > +	struct platform_device *pdev;
> > +	int res;
> > +
> > +	for (; controllers->mmc; controllers++) {
> > +		if (!controllers->deferred)
> > +			continue;
> > +
> > +		pdev = controllers->pdev;
> > +		if (!pdev)
> > +			continue;
> > +
> > +		res = omap_device_register(pdev);
> > +		if (res) {
> > +			pr_err("Could not late init MMC %s\n",
> > +			       controllers->name);
> > +			continue;
> > +		}
> > +	}
> > +}
> 
> Most likely there's no need to pass struct omap2_hsmmc_info *controllers
> to omap_hsmmc_late_init() here. And I'll also take a look at making
> it a completion to make it more generic across various PMICs.

Well looks like it does not make sense to try to do this from the
drivers directly as this is platform_data. And we need to pass the
gpio_cd and gpio_wp anyways to the omap_hsmmc_late_init(), so
might as well keep on using the existing data structure for it.

Updated patch below with the issue noted by Rajendra fixed by
copying gpio_cd and gpio_wp into the pdata in omap_hsmmc_late_init().
Also fixed up the freeing of the controller name that I messed
up in my patch. The name should only get freed on errors, only
pdata gets copied when the platform_device gets registered.

Regards,

Tony


From: Tony Lindgren <tony@atomide.com>
Date: Tue, 14 Feb 2012 16:05:23 -0800
Subject: [PATCH] ARM: OMAP2+: Split omap2_hsmmc_init() to properly support I2C GPIO pins

Otherwise omap_device_build() and omap_mux related functions
can't be marked as __init when twl is build as a module.

If a board is using GPIO pins or regulators configured by an
external chip, such as TWL PMIC on I2C bus, the board must
mark those MMC controllers as deferred. Additionally both
omap_hsmmc_init() and omap_hsmmc_late_init() must be called
by the board.

For MMC controllers using internal GPIO pins for card
detect and regulators the slots don't need to be marked
deferred. In this case calling omap_hsmmc_init() is sufficient.

Note that this patch does not change the behaviour for
board-4430sdp.c board-omap4panda.c. These boards wrongly
rely on the omap_hsmmc.c init function callback to configure
the PMIC GPIO interrupt lines on external chip. If the PMIC
interrupt lines are not configured during init, they will
fail.

Reported-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Tony Lindgren <tony@atomide.com>

diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
index 7370983..c8bda62 100644
--- a/arch/arm/mach-omap2/board-2430sdp.c
+++ b/arch/arm/mach-omap2/board-2430sdp.c
@@ -279,7 +279,7 @@ static void __init omap_2430sdp_init(void)
 	platform_add_devices(sdp2430_devices, ARRAY_SIZE(sdp2430_devices));
 	omap_serial_init();
 	omap_sdrc_init(NULL, NULL);
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_init(mmc);
 	omap2_usbfs_init(&sdp2430_usb_config);
 
 	omap_mux_init_signal("usb0hs_stp", OMAP_PULL_ENA | OMAP_PULL_UP);
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index 383717b..da75f23 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -232,11 +232,13 @@ static struct omap2_hsmmc_info mmc[] = {
 		 */
 		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
 		.gpio_wp	= 4,
+		.deferred	= true,
 	},
 	{
 		.mmc		= 2,
 		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
 		.gpio_wp	= 7,
+		.deferred	= true,
 	},
 	{}	/* Terminator */
 };
@@ -249,7 +251,7 @@ static int sdp3430_twl_gpio_setup(struct device *dev,
 	 */
 	mmc[0].gpio_cd = gpio + 0;
 	mmc[1].gpio_cd = gpio + 1;
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_late_init(mmc);
 
 	/* gpio + 7 is "sub_lcd_en_bkl" (output/PWM1) */
 	gpio_request_one(gpio + 7, GPIOF_OUT_INIT_LOW, "sub_lcd_en_bkl");
@@ -606,6 +608,7 @@ static void __init omap_3430sdp_init(void)
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 	omap_board_config = sdp3430_config;
 	omap_board_config_size = ARRAY_SIZE(sdp3430_config);
+	omap_hsmmc_init(mmc);
 	omap3430_i2c_init();
 	omap_display_init(&sdp3430_dss_data);
 	if (omap_rev() > OMAP3430_REV_ES1_0)
diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c
index 4e90715..09ae257 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -491,9 +491,9 @@ static int __init omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers)
 {
 	struct omap2_hsmmc_info *c;
 
-	omap2_hsmmc_init(controllers);
+	omap_hsmmc_init(controllers);
 	for (c = controllers; c->mmc; c++)
-		omap4_twl6030_hsmmc_set_late_init(c->dev);
+		omap4_twl6030_hsmmc_set_late_init(&c->pdev->dev);
 
 	return 0;
 }
diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c
index 4b1cfe3..71138a1 100644
--- a/arch/arm/mach-omap2/board-am3517evm.c
+++ b/arch/arm/mach-omap2/board-am3517evm.c
@@ -504,7 +504,7 @@ static void __init am3517_evm_init(void)
 	am3517_evm_musb_init();
 
 	/* MMC init function */
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_init(mmc);
 }
 
 MACHINE_START(OMAP3517EVM, "OMAP3517/AM3517 EVM")
diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index e921e3b..60f0501 100644
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -413,7 +413,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.caps		= MMC_CAP_4_BIT_DATA,
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
-
+		.deferred	= true,
 	},
 	{
 		.mmc		= 2,
@@ -422,6 +422,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
 		.ocr_mask	= 0x00100000,	/* 3.3V */
+		.deferred	= true,
 	},
 	{}	/* Terminator */
 };
@@ -471,7 +472,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;
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_late_init(mmc);
 
 	return 0;
 }
@@ -639,6 +640,7 @@ static void __init cm_t3x_common_init(void)
 	omap_serial_init();
 	omap_sdrc_init(mt46h32m32lf6_sdrc_params,
 			     mt46h32m32lf6_sdrc_params);
+	omap_hsmmc_init(mmc);
 	cm_t35_init_i2c();
 	omap_ads7846_init(1, CM_T35_GPIO_PENDOWN, 0, NULL);
 	cm_t35_init_ethernet();
diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
index e873063..11cd2a8 100644
--- a/arch/arm/mach-omap2/board-devkit8000.c
+++ b/arch/arm/mach-omap2/board-devkit8000.c
@@ -100,6 +100,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.mmc		= 1,
 		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
 		.gpio_wp	= 29,
+		.deferred	= true,
 	},
 	{}	/* Terminator */
 };
@@ -228,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;
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_late_init(mmc);
 
 	/* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
 	gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
@@ -636,6 +637,7 @@ static void __init devkit8000_init(void)
 
 	omap_dm9000_init();
 
+	omap_hsmmc_init(mmc);
 	devkit8000_i2c_init();
 	platform_add_devices(devkit8000_devices,
 			ARRAY_SIZE(devkit8000_devices));
diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
index a59ace0..ac1de09 100644
--- a/arch/arm/mach-omap2/board-igep0020.c
+++ b/arch/arm/mach-omap2/board-igep0020.c
@@ -295,6 +295,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.caps		= MMC_CAP_4_BIT_DATA,
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
+		.deferred	= true,
 	},
 #if defined(CONFIG_LIBERTAS_SDIO) || defined(CONFIG_LIBERTAS_SDIO_MODULE)
 	{
@@ -302,6 +303,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.caps		= MMC_CAP_4_BIT_DATA,
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
+		.deferred	= true,
 	},
 #endif
 	{}      /* Terminator */
@@ -402,7 +404,7 @@ static int igep_twl_gpio_setup(struct device *dev,
 
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	mmc[0].gpio_cd = gpio + 0;
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_late_init(mmc);
 
 	/* TWL4030_GPIO_MAX + 1 == ledB (out, active low LED) */
 #if !defined(CONFIG_LEDS_GPIO) && !defined(CONFIG_LEDS_GPIO_MODULE)
@@ -639,6 +641,9 @@ static void __init igep_init(void)
 
 	/* Get IGEP2 hardware revision */
 	igep2_get_revision();
+
+	omap_hsmmc_init(mmc);
+
 	/* Register I2C busses and drivers */
 	igep_i2c_init();
 	platform_add_devices(igep_devices, ARRAY_SIZE(igep_devices));
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index 2d2a61f..b5bc9b2 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -424,7 +424,7 @@ static void __init omap_ldp_init(void)
 	board_nand_init(ldp_nand_partitions,
 		ARRAY_SIZE(ldp_nand_partitions), ZOOM_NAND_CS, 0);
 
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_init(mmc);
 	ldp_display_init();
 }
 
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 7ffcd28..78bfcd5 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -253,6 +253,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.mmc		= 1,
 		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
 		.gpio_wp	= -EINVAL,
+		.deferred	= true,
 	},
 	{}	/* Terminator */
 };
@@ -277,7 +278,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;
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_late_init(mmc);
 
 	/*
 	 * TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, XM active
@@ -521,6 +522,7 @@ static void __init omap3_beagle_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 	omap3_beagle_init_rev();
+	omap_hsmmc_init(mmc);
 	omap3_beagle_i2c_init();
 
 	gpio_buttons[0].gpio = beagle_config.usr_button_gpio;
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index c775bea..db0aa27 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -317,6 +317,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.caps		= MMC_CAP_4_BIT_DATA,
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= 63,
+		.deferred	= true,
 	},
 #ifdef CONFIG_WL12XX_PLATFORM_DATA
 	{
@@ -326,6 +327,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.gpio_wp	= -EINVAL,
 		.gpio_cd	= -EINVAL,
 		.nonremovable	= true,
+		.deferred	= true,
 	},
 #endif
 	{}	/* Terminator */
@@ -363,7 +365,7 @@ static int omap3evm_twl_gpio_setup(struct device *dev,
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	omap_mux_init_gpio(63, OMAP_PIN_INPUT);
 	mmc[0].gpio_cd = gpio + 0;
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_late_init(mmc);
 
 	/*
 	 * Most GPIOs are for USB OTG.  Some are mostly sent to
@@ -644,6 +646,7 @@ static void __init omap3_evm_init(void)
 	omap_board_config = omap3_evm_config;
 	omap_board_config_size = ARRAY_SIZE(omap3_evm_config);
 
+	omap_hsmmc_init(mmc);
 	omap3_evm_i2c_init();
 
 	omap_display_init(&omap3_evm_dss_data);
diff --git a/arch/arm/mach-omap2/board-omap3logic.c b/arch/arm/mach-omap2/board-omap3logic.c
index 4198dd0..2304ba3 100644
--- a/arch/arm/mach-omap2/board-omap3logic.c
+++ b/arch/arm/mach-omap2/board-omap3logic.c
@@ -128,7 +128,7 @@ static void __init board_mmc_init(void)
 		return;
 	}
 
-	omap2_hsmmc_init(board_mmc_info);
+	omap_hsmmc_init(board_mmc_info);
 }
 
 static struct omap_smsc911x_platform_data __initdata board_smsc911x_data = {
diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c
index 1644b73..84c83c8 100644
--- a/arch/arm/mach-omap2/board-omap3pandora.c
+++ b/arch/arm/mach-omap2/board-omap3pandora.c
@@ -273,6 +273,7 @@ static struct omap2_hsmmc_info omap3pandora_mmc[] = {
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= 126,
 		.ext_clock	= 0,
+		.deferred	= true,
 	},
 	{
 		.mmc		= 2,
@@ -281,6 +282,7 @@ static struct omap2_hsmmc_info omap3pandora_mmc[] = {
 		.gpio_wp	= 127,
 		.ext_clock	= 1,
 		.transceiver	= true,
+		.deferred	= true,
 	},
 	{
 		.mmc		= 3,
@@ -288,6 +290,7 @@ static struct omap2_hsmmc_info omap3pandora_mmc[] = {
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
 		.init_card	= pandora_wl1251_init_card,
+		.deferred	= true,
 	},
 	{}	/* Terminator */
 };
@@ -300,7 +303,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;
-	omap2_hsmmc_init(omap3pandora_mmc);
+	omap_hsmmc_late_init(omap3pandora_mmc);
 
 	/* gpio + 13 drives 32kHz buffer for wifi module */
 	gpio_32khz = gpio + 13;
@@ -580,6 +583,7 @@ static struct omap_board_mux board_mux[] __initdata = {
 static void __init omap3pandora_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+	omap_hsmmc_init(omap3pandora_mmc);
 	omap3pandora_i2c_init();
 	pandora_wl1251_init();
 	platform_add_devices(omap3pandora_devices,
diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c
index cb089a4..8eee993 100644
--- a/arch/arm/mach-omap2/board-omap3stalker.c
+++ b/arch/arm/mach-omap2/board-omap3stalker.c
@@ -209,10 +209,11 @@ static struct regulator_init_data omap3stalker_vsim = {
 
 static struct omap2_hsmmc_info mmc[] = {
 	{
-	 .mmc		= 1,
-	 .caps		= MMC_CAP_4_BIT_DATA,
-	 .gpio_cd	= -EINVAL,
-	 .gpio_wp	= 23,
+		.mmc		= 1,
+		.caps		= MMC_CAP_4_BIT_DATA,
+		.gpio_cd	= -EINVAL,
+		.gpio_wp	= 23,
+		.deferred	= true,
 	 },
 	{}			/* Terminator */
 };
@@ -284,7 +285,7 @@ omap3stalker_twl_gpio_setup(struct device *dev,
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	omap_mux_init_gpio(23, OMAP_PIN_INPUT);
 	mmc[0].gpio_cd = gpio + 0;
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_late_init(mmc);
 
 	/*
 	 * Most GPIOs are for USB OTG.  Some are mostly sent to
@@ -425,6 +426,7 @@ static void __init omap3_stalker_init(void)
 	omap_board_config = omap3_stalker_config;
 	omap_board_config_size = ARRAY_SIZE(omap3_stalker_config);
 
+	omap_hsmmc_init(mmc);
 	omap3_stalker_i2c_init();
 
 	platform_add_devices(omap3_stalker_devices,
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index a0b851a..ba9c118 100644
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -100,6 +100,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.mmc		= 1,
 		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
 		.gpio_wp	= 29,
+		.deferred	= true,
 	},
 	{}	/* Terminator */
 };
@@ -125,7 +126,7 @@ static int touchbook_twl_gpio_setup(struct device *dev,
 	}
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	mmc[0].gpio_cd = gpio + 0;
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_late_init(mmc);
 
 	/* REVISIT: need ehci-omap hooks for external VBUS
 	 * power switch and overcurrent detect
@@ -351,6 +352,7 @@ static void __init omap3_touchbook_init(void)
 
 	pm_power_off = omap3_touchbook_poweroff;
 
+	omap_hsmmc_init(mmc);
 	omap3_touchbook_i2c_init();
 	platform_add_devices(omap3_touchbook_devices,
 			ARRAY_SIZE(omap3_touchbook_devices));
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index 28fc271..bcc563c 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -245,9 +245,9 @@ static int __init omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers)
 {
 	struct omap2_hsmmc_info *c;
 
-	omap2_hsmmc_init(controllers);
+	omap_hsmmc_init(controllers);
 	for (c = controllers; c->mmc; c++)
-		omap4_twl6030_hsmmc_set_late_init(c->dev);
+		omap4_twl6030_hsmmc_set_late_init(&c->pdev->dev);
 
 	return 0;
 }
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index 52c0cef..1fc5f7a 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -301,6 +301,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.caps		= MMC_CAP_4_BIT_DATA,
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
+		.deferred	= true,
 	},
 	{
 		.mmc		= 2,
@@ -309,6 +310,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.gpio_wp	= -EINVAL,
 		.transceiver	= true,
 		.ocr_mask	= 0x00100000,	/* 3.3V */
+		.deferred	= true,
 	},
 	{}	/* Terminator */
 };
@@ -407,7 +409,7 @@ static inline void __init overo_init_keys(void) { return; }
 static int overo_twl_gpio_setup(struct device *dev,
 		unsigned gpio, unsigned ngpio)
 {
-	omap2_hsmmc_init(mmc);
+	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) */
@@ -505,6 +507,7 @@ static void __init overo_init(void)
 	int ret;
 
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+	omap_hsmmc_init(mmc);
 	overo_i2c_init();
 	omap_display_init(&overo_dss_data);
 	omap_serial_init();
diff --git a/arch/arm/mach-omap2/board-rm680.c b/arch/arm/mach-omap2/board-rm680.c
index 8678b38..2d24c98 100644
--- a/arch/arm/mach-omap2/board-rm680.c
+++ b/arch/arm/mach-omap2/board-rm680.c
@@ -120,7 +120,7 @@ static void __init rm680_peripherals_init(void)
 				ARRAY_SIZE(rm680_peripherals_devices));
 	rm680_i2c_init();
 	gpmc_onenand_init(board_onenand_data);
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_init(mmc);
 }
 
 #ifdef CONFIG_OMAP_MUX
diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
index acb4e77..0e9d89a 100644
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -1145,7 +1145,7 @@ void __init rx51_peripherals_init(void)
 
 	partition = omap_mux_get("core");
 	if (partition)
-		omap2_hsmmc_init(mmc);
+		omap_hsmmc_init(mmc);
 
 	rx51_charger_init();
 }
diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c
index c126461..82a0f7c 100644
--- a/arch/arm/mach-omap2/board-zoom-peripherals.c
+++ b/arch/arm/mach-omap2/board-zoom-peripherals.c
@@ -205,6 +205,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.caps		= MMC_CAP_4_BIT_DATA,
 		.gpio_wp	= -EINVAL,
 		.power_saving	= true,
+		.deferred	= true,
 	},
 	{
 		.name		= "internal",
@@ -214,6 +215,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.gpio_wp	= -EINVAL,
 		.nonremovable	= true,
 		.power_saving	= true,
+		.deferred	= true,
 	},
 	{
 		.name		= "wl1271",
@@ -222,6 +224,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.gpio_wp	= -EINVAL,
 		.gpio_cd	= -EINVAL,
 		.nonremovable	= true,
+		.deferred	= true,
 	},
 	{}      /* Terminator */
 };
@@ -233,7 +236,7 @@ static int zoom_twl_gpio_setup(struct device *dev,
 
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	mmc[0].gpio_cd = gpio + 0;
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_late_init(mmc);
 
 	ret = gpio_request_one(LCD_PANEL_ENABLE_GPIO, GPIOF_OUT_INIT_LOW,
 			       "lcd enable");
@@ -301,6 +304,7 @@ void __init zoom_peripherals_init(void)
 	if (ret)
 		pr_err("error setting wl12xx data: %d\n", ret);
 
+	omap_hsmmc_init(mmc);
 	omap_i2c_init();
 	platform_device_register(&omap_vwlan_device);
 	usb_musb_init(NULL);
diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
index b40c288..f904766 100644
--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -428,66 +428,132 @@ static int 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)
+{
+	struct platform_device *pdev;
+	struct omap_mmc_platform_data *mmc_pdata;
+	int res;
+
+	if (omap_hsmmc_done)
+		return;
+
+	omap_hsmmc_done = 1;
+
+	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;
+
+		res = omap_device_register(pdev);
+		if (res)
+			pr_err("Could not late init MMC %s\n",
+			       c->name);
+	}
+}
+
 #define MAX_OMAP_MMC_HWMOD_NAME_LEN		16
 
-void omap_init_hsmmc(struct omap2_hsmmc_info *hsmmcinfo, int ctrl_nr)
+static void omap_hsmmc_init_one(struct omap2_hsmmc_info *hsmmcinfo,
+					int ctrl_nr)
 {
 	struct omap_hwmod *oh;
+	struct omap_hwmod *ohs[1];
+	struct omap_device *od;
 	struct platform_device *pdev;
 	char oh_name[MAX_OMAP_MMC_HWMOD_NAME_LEN];
 	struct omap_mmc_platform_data *mmc_data;
 	struct omap_mmc_dev_attr *mmc_dev_attr;
 	char *name;
-	int l;
+	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");
-		goto done;
+		return;
 	}
 
-	if (omap_hsmmc_pdata_init(hsmmcinfo, mmc_data) < 0) {
-		pr_err("%s fails!\n", __func__);
-		goto done;
-	}
+	res = omap_hsmmc_pdata_init(hsmmcinfo, mmc_data);
+	if (res < 0)
+		goto free_mmc;
+
 	omap_hsmmc_mux(mmc_data, (ctrl_nr - 1));
 
 	name = "omap_hsmmc";
-
-	l = snprintf(oh_name, MAX_OMAP_MMC_HWMOD_NAME_LEN,
+	res = snprintf(oh_name, MAX_OMAP_MMC_HWMOD_NAME_LEN,
 		     "mmc%d", ctrl_nr);
-	WARN(l >= MAX_OMAP_MMC_HWMOD_NAME_LEN,
+	WARN(res >= MAX_OMAP_MMC_HWMOD_NAME_LEN,
 	     "String buffer overflow in MMC%d device setup\n", ctrl_nr);
+
 	oh = omap_hwmod_lookup(oh_name);
 	if (!oh) {
 		pr_err("Could not look up %s\n", oh_name);
-		kfree(mmc_data->slots[0].name);
-		goto done;
+		goto free_name;
 	}
-
+	ohs[0] = oh;
 	if (oh->dev_attr != NULL) {
 		mmc_dev_attr = oh->dev_attr;
 		mmc_data->controller_flags = mmc_dev_attr->flags;
 	}
 
-	pdev = omap_device_build(name, ctrl_nr - 1, oh, mmc_data,
-		sizeof(struct omap_mmc_platform_data), NULL, 0, false);
-	if (IS_ERR(pdev)) {
-		WARN(1, "Can't build omap_device for %s:%s.\n", name, oh->name);
-		kfree(mmc_data->slots[0].name);
-		goto done;
+	pdev = platform_device_alloc(name, ctrl_nr - 1);
+	if (!pdev) {
+		pr_err("Could not allocate pdev for %s\n", name);
+		goto free_name;
 	}
-	/*
-	 * return device handle to board setup code
-	 * required to populate for regulator framework structure
-	 */
-	hsmmcinfo->dev = &pdev->dev;
+	dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id);
+
+	od = omap_device_alloc(pdev, ohs, 1, NULL, 0);
+	if (!od) {
+		pr_err("Could not allocate od for %s\n", name);
+		goto put_pdev;
+	}
+
+	res = platform_device_add_data(pdev, mmc_data,
+			      sizeof(struct omap_mmc_platform_data));
+	if (res) {
+		pr_err("Could not add pdata for %s\n", name);
+		goto put_pdev;
+	}
+
+	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);
+		goto free_od;
+	}
+
+	goto free_mmc;
+
+free_od:
+	omap_device_delete(od);
+
+put_pdev:
+	platform_device_put(pdev);
+
+free_name:
+	kfree(mmc_data->slots[0].name);
 
-done:
+free_mmc:
 	kfree(mmc_data);
 }
 
-void omap2_hsmmc_init(struct omap2_hsmmc_info *controllers)
+void omap_hsmmc_init(struct omap2_hsmmc_info *controllers)
 {
 	u32 reg;
 
@@ -515,7 +581,7 @@ void omap2_hsmmc_init(struct omap2_hsmmc_info *controllers)
 	}
 
 	for (; controllers->mmc; controllers++)
-		omap_init_hsmmc(controllers, controllers->mmc);
+		omap_hsmmc_init_one(controllers, controllers->mmc);
 
 }
 
diff --git a/arch/arm/mach-omap2/hsmmc.h b/arch/arm/mach-omap2/hsmmc.h
index c440973..07831cc 100644
--- a/arch/arm/mach-omap2/hsmmc.h
+++ b/arch/arm/mach-omap2/hsmmc.h
@@ -21,10 +21,11 @@ struct omap2_hsmmc_info {
 	bool	no_off;		/* power_saving and power is not to go off */
 	bool	no_off_init;	/* no power off when not in MMC sleep state */
 	bool	vcc_aux_disable_is_sleep; /* Regulator off remapped to sleep */
+	bool	deferred;	/* mmc needs a deferred probe */
 	int	gpio_cd;	/* or -EINVAL */
 	int	gpio_wp;	/* or -EINVAL */
 	char	*name;		/* or NULL for default */
-	struct device *dev;	/* returned: pointer to mmc adapter */
+	struct platform_device *pdev;	/* mmc controller instance */
 	int	ocr_mask;	/* temporary HACK */
 	/* Remux (pad configuration) when powering on/off */
 	void (*remux)(struct device *dev, int slot, int power_on);
@@ -34,11 +35,16 @@ struct omap2_hsmmc_info {
 
 #if defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
 
-void omap2_hsmmc_init(struct omap2_hsmmc_info *);
+void omap_hsmmc_init(struct omap2_hsmmc_info *);
+void omap_hsmmc_late_init(struct omap2_hsmmc_info *);
 
 #else
 
-static inline void omap2_hsmmc_init(struct omap2_hsmmc_info *info)
+static inline void omap_hsmmc_init(struct omap2_hsmmc_info *info)
+{
+}
+
+static inline void omap_hsmmc_late_init(struct omap2_hsmmc_info *info)
 {
 }
 

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

* [PATCH 2/3] ARM: OMAP2+: Split omap2_hsmmc_init() to properly support I2C GPIO pins
@ 2012-02-17 19:05       ` Tony Lindgren
  0 siblings, 0 replies; 66+ messages in thread
From: Tony Lindgren @ 2012-02-17 19:05 UTC (permalink / raw)
  To: linux-arm-kernel

* Tony Lindgren <tony@atomide.com> [120216 08:13]:
> * Tony Lindgren <tony@atomide.com> [120215 09:57]:
> >  
> > +void omap_hsmmc_late_init(struct omap2_hsmmc_info *controllers)
> > +{
> > +	struct platform_device *pdev;
> > +	int res;
> > +
> > +	for (; controllers->mmc; controllers++) {
> > +		if (!controllers->deferred)
> > +			continue;
> > +
> > +		pdev = controllers->pdev;
> > +		if (!pdev)
> > +			continue;
> > +
> > +		res = omap_device_register(pdev);
> > +		if (res) {
> > +			pr_err("Could not late init MMC %s\n",
> > +			       controllers->name);
> > +			continue;
> > +		}
> > +	}
> > +}
> 
> Most likely there's no need to pass struct omap2_hsmmc_info *controllers
> to omap_hsmmc_late_init() here. And I'll also take a look at making
> it a completion to make it more generic across various PMICs.

Well looks like it does not make sense to try to do this from the
drivers directly as this is platform_data. And we need to pass the
gpio_cd and gpio_wp anyways to the omap_hsmmc_late_init(), so
might as well keep on using the existing data structure for it.

Updated patch below with the issue noted by Rajendra fixed by
copying gpio_cd and gpio_wp into the pdata in omap_hsmmc_late_init().
Also fixed up the freeing of the controller name that I messed
up in my patch. The name should only get freed on errors, only
pdata gets copied when the platform_device gets registered.

Regards,

Tony


From: Tony Lindgren <tony@atomide.com>
Date: Tue, 14 Feb 2012 16:05:23 -0800
Subject: [PATCH] ARM: OMAP2+: Split omap2_hsmmc_init() to properly support I2C GPIO pins

Otherwise omap_device_build() and omap_mux related functions
can't be marked as __init when twl is build as a module.

If a board is using GPIO pins or regulators configured by an
external chip, such as TWL PMIC on I2C bus, the board must
mark those MMC controllers as deferred. Additionally both
omap_hsmmc_init() and omap_hsmmc_late_init() must be called
by the board.

For MMC controllers using internal GPIO pins for card
detect and regulators the slots don't need to be marked
deferred. In this case calling omap_hsmmc_init() is sufficient.

Note that this patch does not change the behaviour for
board-4430sdp.c board-omap4panda.c. These boards wrongly
rely on the omap_hsmmc.c init function callback to configure
the PMIC GPIO interrupt lines on external chip. If the PMIC
interrupt lines are not configured during init, they will
fail.

Reported-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Tony Lindgren <tony@atomide.com>

diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
index 7370983..c8bda62 100644
--- a/arch/arm/mach-omap2/board-2430sdp.c
+++ b/arch/arm/mach-omap2/board-2430sdp.c
@@ -279,7 +279,7 @@ static void __init omap_2430sdp_init(void)
 	platform_add_devices(sdp2430_devices, ARRAY_SIZE(sdp2430_devices));
 	omap_serial_init();
 	omap_sdrc_init(NULL, NULL);
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_init(mmc);
 	omap2_usbfs_init(&sdp2430_usb_config);
 
 	omap_mux_init_signal("usb0hs_stp", OMAP_PULL_ENA | OMAP_PULL_UP);
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index 383717b..da75f23 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -232,11 +232,13 @@ static struct omap2_hsmmc_info mmc[] = {
 		 */
 		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
 		.gpio_wp	= 4,
+		.deferred	= true,
 	},
 	{
 		.mmc		= 2,
 		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
 		.gpio_wp	= 7,
+		.deferred	= true,
 	},
 	{}	/* Terminator */
 };
@@ -249,7 +251,7 @@ static int sdp3430_twl_gpio_setup(struct device *dev,
 	 */
 	mmc[0].gpio_cd = gpio + 0;
 	mmc[1].gpio_cd = gpio + 1;
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_late_init(mmc);
 
 	/* gpio + 7 is "sub_lcd_en_bkl" (output/PWM1) */
 	gpio_request_one(gpio + 7, GPIOF_OUT_INIT_LOW, "sub_lcd_en_bkl");
@@ -606,6 +608,7 @@ static void __init omap_3430sdp_init(void)
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 	omap_board_config = sdp3430_config;
 	omap_board_config_size = ARRAY_SIZE(sdp3430_config);
+	omap_hsmmc_init(mmc);
 	omap3430_i2c_init();
 	omap_display_init(&sdp3430_dss_data);
 	if (omap_rev() > OMAP3430_REV_ES1_0)
diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c
index 4e90715..09ae257 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -491,9 +491,9 @@ static int __init omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers)
 {
 	struct omap2_hsmmc_info *c;
 
-	omap2_hsmmc_init(controllers);
+	omap_hsmmc_init(controllers);
 	for (c = controllers; c->mmc; c++)
-		omap4_twl6030_hsmmc_set_late_init(c->dev);
+		omap4_twl6030_hsmmc_set_late_init(&c->pdev->dev);
 
 	return 0;
 }
diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c
index 4b1cfe3..71138a1 100644
--- a/arch/arm/mach-omap2/board-am3517evm.c
+++ b/arch/arm/mach-omap2/board-am3517evm.c
@@ -504,7 +504,7 @@ static void __init am3517_evm_init(void)
 	am3517_evm_musb_init();
 
 	/* MMC init function */
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_init(mmc);
 }
 
 MACHINE_START(OMAP3517EVM, "OMAP3517/AM3517 EVM")
diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index e921e3b..60f0501 100644
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -413,7 +413,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.caps		= MMC_CAP_4_BIT_DATA,
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
-
+		.deferred	= true,
 	},
 	{
 		.mmc		= 2,
@@ -422,6 +422,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
 		.ocr_mask	= 0x00100000,	/* 3.3V */
+		.deferred	= true,
 	},
 	{}	/* Terminator */
 };
@@ -471,7 +472,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;
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_late_init(mmc);
 
 	return 0;
 }
@@ -639,6 +640,7 @@ static void __init cm_t3x_common_init(void)
 	omap_serial_init();
 	omap_sdrc_init(mt46h32m32lf6_sdrc_params,
 			     mt46h32m32lf6_sdrc_params);
+	omap_hsmmc_init(mmc);
 	cm_t35_init_i2c();
 	omap_ads7846_init(1, CM_T35_GPIO_PENDOWN, 0, NULL);
 	cm_t35_init_ethernet();
diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
index e873063..11cd2a8 100644
--- a/arch/arm/mach-omap2/board-devkit8000.c
+++ b/arch/arm/mach-omap2/board-devkit8000.c
@@ -100,6 +100,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.mmc		= 1,
 		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
 		.gpio_wp	= 29,
+		.deferred	= true,
 	},
 	{}	/* Terminator */
 };
@@ -228,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;
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_late_init(mmc);
 
 	/* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
 	gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
@@ -636,6 +637,7 @@ static void __init devkit8000_init(void)
 
 	omap_dm9000_init();
 
+	omap_hsmmc_init(mmc);
 	devkit8000_i2c_init();
 	platform_add_devices(devkit8000_devices,
 			ARRAY_SIZE(devkit8000_devices));
diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
index a59ace0..ac1de09 100644
--- a/arch/arm/mach-omap2/board-igep0020.c
+++ b/arch/arm/mach-omap2/board-igep0020.c
@@ -295,6 +295,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.caps		= MMC_CAP_4_BIT_DATA,
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
+		.deferred	= true,
 	},
 #if defined(CONFIG_LIBERTAS_SDIO) || defined(CONFIG_LIBERTAS_SDIO_MODULE)
 	{
@@ -302,6 +303,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.caps		= MMC_CAP_4_BIT_DATA,
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
+		.deferred	= true,
 	},
 #endif
 	{}      /* Terminator */
@@ -402,7 +404,7 @@ static int igep_twl_gpio_setup(struct device *dev,
 
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	mmc[0].gpio_cd = gpio + 0;
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_late_init(mmc);
 
 	/* TWL4030_GPIO_MAX + 1 == ledB (out, active low LED) */
 #if !defined(CONFIG_LEDS_GPIO) && !defined(CONFIG_LEDS_GPIO_MODULE)
@@ -639,6 +641,9 @@ static void __init igep_init(void)
 
 	/* Get IGEP2 hardware revision */
 	igep2_get_revision();
+
+	omap_hsmmc_init(mmc);
+
 	/* Register I2C busses and drivers */
 	igep_i2c_init();
 	platform_add_devices(igep_devices, ARRAY_SIZE(igep_devices));
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index 2d2a61f..b5bc9b2 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -424,7 +424,7 @@ static void __init omap_ldp_init(void)
 	board_nand_init(ldp_nand_partitions,
 		ARRAY_SIZE(ldp_nand_partitions), ZOOM_NAND_CS, 0);
 
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_init(mmc);
 	ldp_display_init();
 }
 
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 7ffcd28..78bfcd5 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -253,6 +253,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.mmc		= 1,
 		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
 		.gpio_wp	= -EINVAL,
+		.deferred	= true,
 	},
 	{}	/* Terminator */
 };
@@ -277,7 +278,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;
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_late_init(mmc);
 
 	/*
 	 * TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, XM active
@@ -521,6 +522,7 @@ static void __init omap3_beagle_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 	omap3_beagle_init_rev();
+	omap_hsmmc_init(mmc);
 	omap3_beagle_i2c_init();
 
 	gpio_buttons[0].gpio = beagle_config.usr_button_gpio;
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index c775bea..db0aa27 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -317,6 +317,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.caps		= MMC_CAP_4_BIT_DATA,
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= 63,
+		.deferred	= true,
 	},
 #ifdef CONFIG_WL12XX_PLATFORM_DATA
 	{
@@ -326,6 +327,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.gpio_wp	= -EINVAL,
 		.gpio_cd	= -EINVAL,
 		.nonremovable	= true,
+		.deferred	= true,
 	},
 #endif
 	{}	/* Terminator */
@@ -363,7 +365,7 @@ static int omap3evm_twl_gpio_setup(struct device *dev,
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	omap_mux_init_gpio(63, OMAP_PIN_INPUT);
 	mmc[0].gpio_cd = gpio + 0;
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_late_init(mmc);
 
 	/*
 	 * Most GPIOs are for USB OTG.  Some are mostly sent to
@@ -644,6 +646,7 @@ static void __init omap3_evm_init(void)
 	omap_board_config = omap3_evm_config;
 	omap_board_config_size = ARRAY_SIZE(omap3_evm_config);
 
+	omap_hsmmc_init(mmc);
 	omap3_evm_i2c_init();
 
 	omap_display_init(&omap3_evm_dss_data);
diff --git a/arch/arm/mach-omap2/board-omap3logic.c b/arch/arm/mach-omap2/board-omap3logic.c
index 4198dd0..2304ba3 100644
--- a/arch/arm/mach-omap2/board-omap3logic.c
+++ b/arch/arm/mach-omap2/board-omap3logic.c
@@ -128,7 +128,7 @@ static void __init board_mmc_init(void)
 		return;
 	}
 
-	omap2_hsmmc_init(board_mmc_info);
+	omap_hsmmc_init(board_mmc_info);
 }
 
 static struct omap_smsc911x_platform_data __initdata board_smsc911x_data = {
diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c
index 1644b73..84c83c8 100644
--- a/arch/arm/mach-omap2/board-omap3pandora.c
+++ b/arch/arm/mach-omap2/board-omap3pandora.c
@@ -273,6 +273,7 @@ static struct omap2_hsmmc_info omap3pandora_mmc[] = {
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= 126,
 		.ext_clock	= 0,
+		.deferred	= true,
 	},
 	{
 		.mmc		= 2,
@@ -281,6 +282,7 @@ static struct omap2_hsmmc_info omap3pandora_mmc[] = {
 		.gpio_wp	= 127,
 		.ext_clock	= 1,
 		.transceiver	= true,
+		.deferred	= true,
 	},
 	{
 		.mmc		= 3,
@@ -288,6 +290,7 @@ static struct omap2_hsmmc_info omap3pandora_mmc[] = {
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
 		.init_card	= pandora_wl1251_init_card,
+		.deferred	= true,
 	},
 	{}	/* Terminator */
 };
@@ -300,7 +303,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;
-	omap2_hsmmc_init(omap3pandora_mmc);
+	omap_hsmmc_late_init(omap3pandora_mmc);
 
 	/* gpio + 13 drives 32kHz buffer for wifi module */
 	gpio_32khz = gpio + 13;
@@ -580,6 +583,7 @@ static struct omap_board_mux board_mux[] __initdata = {
 static void __init omap3pandora_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+	omap_hsmmc_init(omap3pandora_mmc);
 	omap3pandora_i2c_init();
 	pandora_wl1251_init();
 	platform_add_devices(omap3pandora_devices,
diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c
index cb089a4..8eee993 100644
--- a/arch/arm/mach-omap2/board-omap3stalker.c
+++ b/arch/arm/mach-omap2/board-omap3stalker.c
@@ -209,10 +209,11 @@ static struct regulator_init_data omap3stalker_vsim = {
 
 static struct omap2_hsmmc_info mmc[] = {
 	{
-	 .mmc		= 1,
-	 .caps		= MMC_CAP_4_BIT_DATA,
-	 .gpio_cd	= -EINVAL,
-	 .gpio_wp	= 23,
+		.mmc		= 1,
+		.caps		= MMC_CAP_4_BIT_DATA,
+		.gpio_cd	= -EINVAL,
+		.gpio_wp	= 23,
+		.deferred	= true,
 	 },
 	{}			/* Terminator */
 };
@@ -284,7 +285,7 @@ omap3stalker_twl_gpio_setup(struct device *dev,
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	omap_mux_init_gpio(23, OMAP_PIN_INPUT);
 	mmc[0].gpio_cd = gpio + 0;
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_late_init(mmc);
 
 	/*
 	 * Most GPIOs are for USB OTG.  Some are mostly sent to
@@ -425,6 +426,7 @@ static void __init omap3_stalker_init(void)
 	omap_board_config = omap3_stalker_config;
 	omap_board_config_size = ARRAY_SIZE(omap3_stalker_config);
 
+	omap_hsmmc_init(mmc);
 	omap3_stalker_i2c_init();
 
 	platform_add_devices(omap3_stalker_devices,
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index a0b851a..ba9c118 100644
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -100,6 +100,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.mmc		= 1,
 		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
 		.gpio_wp	= 29,
+		.deferred	= true,
 	},
 	{}	/* Terminator */
 };
@@ -125,7 +126,7 @@ static int touchbook_twl_gpio_setup(struct device *dev,
 	}
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	mmc[0].gpio_cd = gpio + 0;
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_late_init(mmc);
 
 	/* REVISIT: need ehci-omap hooks for external VBUS
 	 * power switch and overcurrent detect
@@ -351,6 +352,7 @@ static void __init omap3_touchbook_init(void)
 
 	pm_power_off = omap3_touchbook_poweroff;
 
+	omap_hsmmc_init(mmc);
 	omap3_touchbook_i2c_init();
 	platform_add_devices(omap3_touchbook_devices,
 			ARRAY_SIZE(omap3_touchbook_devices));
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index 28fc271..bcc563c 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -245,9 +245,9 @@ static int __init omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers)
 {
 	struct omap2_hsmmc_info *c;
 
-	omap2_hsmmc_init(controllers);
+	omap_hsmmc_init(controllers);
 	for (c = controllers; c->mmc; c++)
-		omap4_twl6030_hsmmc_set_late_init(c->dev);
+		omap4_twl6030_hsmmc_set_late_init(&c->pdev->dev);
 
 	return 0;
 }
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index 52c0cef..1fc5f7a 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -301,6 +301,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.caps		= MMC_CAP_4_BIT_DATA,
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
+		.deferred	= true,
 	},
 	{
 		.mmc		= 2,
@@ -309,6 +310,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.gpio_wp	= -EINVAL,
 		.transceiver	= true,
 		.ocr_mask	= 0x00100000,	/* 3.3V */
+		.deferred	= true,
 	},
 	{}	/* Terminator */
 };
@@ -407,7 +409,7 @@ static inline void __init overo_init_keys(void) { return; }
 static int overo_twl_gpio_setup(struct device *dev,
 		unsigned gpio, unsigned ngpio)
 {
-	omap2_hsmmc_init(mmc);
+	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) */
@@ -505,6 +507,7 @@ static void __init overo_init(void)
 	int ret;
 
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+	omap_hsmmc_init(mmc);
 	overo_i2c_init();
 	omap_display_init(&overo_dss_data);
 	omap_serial_init();
diff --git a/arch/arm/mach-omap2/board-rm680.c b/arch/arm/mach-omap2/board-rm680.c
index 8678b38..2d24c98 100644
--- a/arch/arm/mach-omap2/board-rm680.c
+++ b/arch/arm/mach-omap2/board-rm680.c
@@ -120,7 +120,7 @@ static void __init rm680_peripherals_init(void)
 				ARRAY_SIZE(rm680_peripherals_devices));
 	rm680_i2c_init();
 	gpmc_onenand_init(board_onenand_data);
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_init(mmc);
 }
 
 #ifdef CONFIG_OMAP_MUX
diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
index acb4e77..0e9d89a 100644
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -1145,7 +1145,7 @@ void __init rx51_peripherals_init(void)
 
 	partition = omap_mux_get("core");
 	if (partition)
-		omap2_hsmmc_init(mmc);
+		omap_hsmmc_init(mmc);
 
 	rx51_charger_init();
 }
diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c
index c126461..82a0f7c 100644
--- a/arch/arm/mach-omap2/board-zoom-peripherals.c
+++ b/arch/arm/mach-omap2/board-zoom-peripherals.c
@@ -205,6 +205,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.caps		= MMC_CAP_4_BIT_DATA,
 		.gpio_wp	= -EINVAL,
 		.power_saving	= true,
+		.deferred	= true,
 	},
 	{
 		.name		= "internal",
@@ -214,6 +215,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.gpio_wp	= -EINVAL,
 		.nonremovable	= true,
 		.power_saving	= true,
+		.deferred	= true,
 	},
 	{
 		.name		= "wl1271",
@@ -222,6 +224,7 @@ static struct omap2_hsmmc_info mmc[] = {
 		.gpio_wp	= -EINVAL,
 		.gpio_cd	= -EINVAL,
 		.nonremovable	= true,
+		.deferred	= true,
 	},
 	{}      /* Terminator */
 };
@@ -233,7 +236,7 @@ static int zoom_twl_gpio_setup(struct device *dev,
 
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	mmc[0].gpio_cd = gpio + 0;
-	omap2_hsmmc_init(mmc);
+	omap_hsmmc_late_init(mmc);
 
 	ret = gpio_request_one(LCD_PANEL_ENABLE_GPIO, GPIOF_OUT_INIT_LOW,
 			       "lcd enable");
@@ -301,6 +304,7 @@ void __init zoom_peripherals_init(void)
 	if (ret)
 		pr_err("error setting wl12xx data: %d\n", ret);
 
+	omap_hsmmc_init(mmc);
 	omap_i2c_init();
 	platform_device_register(&omap_vwlan_device);
 	usb_musb_init(NULL);
diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
index b40c288..f904766 100644
--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -428,66 +428,132 @@ static int 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)
+{
+	struct platform_device *pdev;
+	struct omap_mmc_platform_data *mmc_pdata;
+	int res;
+
+	if (omap_hsmmc_done)
+		return;
+
+	omap_hsmmc_done = 1;
+
+	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;
+
+		res = omap_device_register(pdev);
+		if (res)
+			pr_err("Could not late init MMC %s\n",
+			       c->name);
+	}
+}
+
 #define MAX_OMAP_MMC_HWMOD_NAME_LEN		16
 
-void omap_init_hsmmc(struct omap2_hsmmc_info *hsmmcinfo, int ctrl_nr)
+static void omap_hsmmc_init_one(struct omap2_hsmmc_info *hsmmcinfo,
+					int ctrl_nr)
 {
 	struct omap_hwmod *oh;
+	struct omap_hwmod *ohs[1];
+	struct omap_device *od;
 	struct platform_device *pdev;
 	char oh_name[MAX_OMAP_MMC_HWMOD_NAME_LEN];
 	struct omap_mmc_platform_data *mmc_data;
 	struct omap_mmc_dev_attr *mmc_dev_attr;
 	char *name;
-	int l;
+	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");
-		goto done;
+		return;
 	}
 
-	if (omap_hsmmc_pdata_init(hsmmcinfo, mmc_data) < 0) {
-		pr_err("%s fails!\n", __func__);
-		goto done;
-	}
+	res = omap_hsmmc_pdata_init(hsmmcinfo, mmc_data);
+	if (res < 0)
+		goto free_mmc;
+
 	omap_hsmmc_mux(mmc_data, (ctrl_nr - 1));
 
 	name = "omap_hsmmc";
-
-	l = snprintf(oh_name, MAX_OMAP_MMC_HWMOD_NAME_LEN,
+	res = snprintf(oh_name, MAX_OMAP_MMC_HWMOD_NAME_LEN,
 		     "mmc%d", ctrl_nr);
-	WARN(l >= MAX_OMAP_MMC_HWMOD_NAME_LEN,
+	WARN(res >= MAX_OMAP_MMC_HWMOD_NAME_LEN,
 	     "String buffer overflow in MMC%d device setup\n", ctrl_nr);
+
 	oh = omap_hwmod_lookup(oh_name);
 	if (!oh) {
 		pr_err("Could not look up %s\n", oh_name);
-		kfree(mmc_data->slots[0].name);
-		goto done;
+		goto free_name;
 	}
-
+	ohs[0] = oh;
 	if (oh->dev_attr != NULL) {
 		mmc_dev_attr = oh->dev_attr;
 		mmc_data->controller_flags = mmc_dev_attr->flags;
 	}
 
-	pdev = omap_device_build(name, ctrl_nr - 1, oh, mmc_data,
-		sizeof(struct omap_mmc_platform_data), NULL, 0, false);
-	if (IS_ERR(pdev)) {
-		WARN(1, "Can't build omap_device for %s:%s.\n", name, oh->name);
-		kfree(mmc_data->slots[0].name);
-		goto done;
+	pdev = platform_device_alloc(name, ctrl_nr - 1);
+	if (!pdev) {
+		pr_err("Could not allocate pdev for %s\n", name);
+		goto free_name;
 	}
-	/*
-	 * return device handle to board setup code
-	 * required to populate for regulator framework structure
-	 */
-	hsmmcinfo->dev = &pdev->dev;
+	dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id);
+
+	od = omap_device_alloc(pdev, ohs, 1, NULL, 0);
+	if (!od) {
+		pr_err("Could not allocate od for %s\n", name);
+		goto put_pdev;
+	}
+
+	res = platform_device_add_data(pdev, mmc_data,
+			      sizeof(struct omap_mmc_platform_data));
+	if (res) {
+		pr_err("Could not add pdata for %s\n", name);
+		goto put_pdev;
+	}
+
+	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);
+		goto free_od;
+	}
+
+	goto free_mmc;
+
+free_od:
+	omap_device_delete(od);
+
+put_pdev:
+	platform_device_put(pdev);
+
+free_name:
+	kfree(mmc_data->slots[0].name);
 
-done:
+free_mmc:
 	kfree(mmc_data);
 }
 
-void omap2_hsmmc_init(struct omap2_hsmmc_info *controllers)
+void omap_hsmmc_init(struct omap2_hsmmc_info *controllers)
 {
 	u32 reg;
 
@@ -515,7 +581,7 @@ void omap2_hsmmc_init(struct omap2_hsmmc_info *controllers)
 	}
 
 	for (; controllers->mmc; controllers++)
-		omap_init_hsmmc(controllers, controllers->mmc);
+		omap_hsmmc_init_one(controllers, controllers->mmc);
 
 }
 
diff --git a/arch/arm/mach-omap2/hsmmc.h b/arch/arm/mach-omap2/hsmmc.h
index c440973..07831cc 100644
--- a/arch/arm/mach-omap2/hsmmc.h
+++ b/arch/arm/mach-omap2/hsmmc.h
@@ -21,10 +21,11 @@ struct omap2_hsmmc_info {
 	bool	no_off;		/* power_saving and power is not to go off */
 	bool	no_off_init;	/* no power off when not in MMC sleep state */
 	bool	vcc_aux_disable_is_sleep; /* Regulator off remapped to sleep */
+	bool	deferred;	/* mmc needs a deferred probe */
 	int	gpio_cd;	/* or -EINVAL */
 	int	gpio_wp;	/* or -EINVAL */
 	char	*name;		/* or NULL for default */
-	struct device *dev;	/* returned: pointer to mmc adapter */
+	struct platform_device *pdev;	/* mmc controller instance */
 	int	ocr_mask;	/* temporary HACK */
 	/* Remux (pad configuration) when powering on/off */
 	void (*remux)(struct device *dev, int slot, int power_on);
@@ -34,11 +35,16 @@ struct omap2_hsmmc_info {
 
 #if defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
 
-void omap2_hsmmc_init(struct omap2_hsmmc_info *);
+void omap_hsmmc_init(struct omap2_hsmmc_info *);
+void omap_hsmmc_late_init(struct omap2_hsmmc_info *);
 
 #else
 
-static inline void omap2_hsmmc_init(struct omap2_hsmmc_info *info)
+static inline void omap_hsmmc_init(struct omap2_hsmmc_info *info)
+{
+}
+
+static inline void omap_hsmmc_late_init(struct omap2_hsmmc_info *info)
 {
 }
 

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

* Re: [PATCH 3/3] ARM: OMAP2+: Mark omap_hsmmc_init and omap_mux related functions as __init
  2012-02-16 16:41       ` Tony Lindgren
@ 2012-02-17 19:17         ` Tony Lindgren
  -1 siblings, 0 replies; 66+ messages in thread
From: Tony Lindgren @ 2012-02-17 19:17 UTC (permalink / raw)
  To: Russell King - ARM Linux; +Cc: linux-arm-kernel, linux-omap

* Tony Lindgren <tony@atomide.com> [120216 08:10]:
> * Russell King - ARM Linux <linux@arm.linux.org.uk> [120216 01:40]:
> > On Wed, Feb 15, 2012 at 10:28:30AM -0800, Tony Lindgren wrote:
> > > Now that omap hsmmc init is split into two functions, it's safe
> > > to mark omap_hsmmc_init and omap_mux related functions to __init.
> > > 
> > > This basically reverts the following fixes for the case where
> > > TWL was compiled as a module:
> > > 
> > > d5de63 (ARM: omap: preemptively fix section mismatch in omap4_sdp4430_wifi_mux_init())
> > 
> > Why did you include this one?  This is unrelated to the TWL problems.
> 
> Oops sorry, thanks for noticing. Your patch makes it __init,
> I was reading the patch wrong way around. Your patch should
> stay and my patch now changes it the wrong way.

Here's the updated patch, looks I had two bad reverts there,
only two are needed.

Regards,

Tony


From: Tony Lindgren <tony@atomide.com>
Date: Tue, 14 Feb 2012 18:17:54 -0800
Subject: [PATCH] ARM: OMAP2+: Mark omap_hsmmc_init and omap_mux related functions as __init

Now that omap hsmmc init is split into two functions, it's safe
to mark omap_hsmmc_init and omap_mux related functions to __init.

This basically reverts the following fixes for the case where
TWL was compiled as a module:

a98f77b (ARM: omap: fix section mismatch warning for sdp3430_twl_gpio_setup())
8930b4e (ARM: omap: fix section mismatch warnings in mux.c caused by hsmmc.c)

Additionally it fixes up the remaining section warnings for
all callers of omap_mux functions.

Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Tony Lindgren <tony@atomide.com>

diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c
index 30a6f52..0349fd2 100644
--- a/arch/arm/mach-omap2/board-flash.c
+++ b/arch/arm/mach-omap2/board-flash.c
@@ -189,7 +189,7 @@ unmap:
  *
  * @return - void.
  */
-void board_flash_init(struct flash_partitions partition_info[],
+void __init board_flash_init(struct flash_partitions partition_info[],
 			char chip_sel_board[][GPMC_CS_NUM], int nand_type)
 {
 	u8		cs = 0;
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 78bfcd5..7be8d65 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -273,8 +273,6 @@ static int beagle_twl_gpio_setup(struct device *dev,
 {
 	int r;
 
-	if (beagle_config.mmc1_gpio_wp != -EINVAL)
-		omap_mux_init_gpio(beagle_config.mmc1_gpio_wp, OMAP_PIN_INPUT);
 	mmc[0].gpio_wp = beagle_config.mmc1_gpio_wp;
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	mmc[0].gpio_cd = gpio + 0;
@@ -522,7 +520,11 @@ static void __init omap3_beagle_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 	omap3_beagle_init_rev();
+
+	if (beagle_config.mmc1_gpio_wp != -EINVAL)
+		omap_mux_init_gpio(beagle_config.mmc1_gpio_wp, OMAP_PIN_INPUT);
 	omap_hsmmc_init(mmc);
+
 	omap3_beagle_i2c_init();
 
 	gpio_buttons[0].gpio = beagle_config.usr_button_gpio;
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index db0aa27..0f9a983 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -363,7 +363,6 @@ static int omap3evm_twl_gpio_setup(struct device *dev,
 	int r, lcd_bl_en;
 
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
-	omap_mux_init_gpio(63, OMAP_PIN_INPUT);
 	mmc[0].gpio_cd = gpio + 0;
 	omap_hsmmc_late_init(mmc);
 
@@ -646,7 +645,9 @@ static void __init omap3_evm_init(void)
 	omap_board_config = omap3_evm_config;
 	omap_board_config_size = ARRAY_SIZE(omap3_evm_config);
 
+	omap_mux_init_gpio(63, OMAP_PIN_INPUT);
 	omap_hsmmc_init(mmc);
+
 	omap3_evm_i2c_init();
 
 	omap_display_init(&omap3_evm_dss_data);
diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c
index 8eee993..6410043 100644
--- a/arch/arm/mach-omap2/board-omap3stalker.c
+++ b/arch/arm/mach-omap2/board-omap3stalker.c
@@ -283,7 +283,6 @@ omap3stalker_twl_gpio_setup(struct device *dev,
 			    unsigned gpio, unsigned ngpio)
 {
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
-	omap_mux_init_gpio(23, OMAP_PIN_INPUT);
 	mmc[0].gpio_cd = gpio + 0;
 	omap_hsmmc_late_init(mmc);
 
@@ -426,7 +425,9 @@ static void __init omap3_stalker_init(void)
 	omap_board_config = omap3_stalker_config;
 	omap_board_config_size = ARRAY_SIZE(omap3_stalker_config);
 
+	omap_mux_init_gpio(23, OMAP_PIN_INPUT);
 	omap_hsmmc_init(mmc);
+
 	omap3_stalker_i2c_init();
 
 	platform_add_devices(omap3_stalker_devices,
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index ba9c118..8842e04 100644
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -118,12 +118,6 @@ static struct gpio_led gpio_leds[];
 static int touchbook_twl_gpio_setup(struct device *dev,
 		unsigned gpio, unsigned ngpio)
 {
-	if (system_rev >= 0x20 && system_rev <= 0x34301000) {
-		omap_mux_init_gpio(23, OMAP_PIN_INPUT);
-		mmc[0].gpio_wp = 23;
-	} else {
-		omap_mux_init_gpio(29, OMAP_PIN_INPUT);
-	}
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	mmc[0].gpio_cd = gpio + 0;
 	omap_hsmmc_late_init(mmc);
@@ -352,7 +346,14 @@ static void __init omap3_touchbook_init(void)
 
 	pm_power_off = omap3_touchbook_poweroff;
 
+	if (system_rev >= 0x20 && system_rev <= 0x34301000) {
+		omap_mux_init_gpio(23, OMAP_PIN_INPUT);
+		mmc[0].gpio_wp = 23;
+	} else {
+		omap_mux_init_gpio(29, OMAP_PIN_INPUT);
+	}
 	omap_hsmmc_init(mmc);
+
 	omap3_touchbook_i2c_init();
 	platform_add_devices(omap3_touchbook_devices,
 			ARRAY_SIZE(omap3_touchbook_devices));
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index bcc563c..7ca7a5c 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -461,7 +461,7 @@ static struct omap_dss_board_info omap4_panda_dss_data = {
 	.default_device	= &omap4_panda_dvi_device,
 };
 
-void omap4_panda_display_init(void)
+void __init omap4_panda_display_init(void)
 {
 	int r;
 
diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
index 3677b1f..62e133c 100644
--- a/arch/arm/mach-omap2/display.c
+++ b/arch/arm/mach-omap2/display.c
@@ -124,7 +124,7 @@ static void omap4_hdmi_mux_pads(enum omap_hdmi_flags flags)
 	}
 }
 
-static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
+static int __init omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
 {
 	u32 enable_mask, enable_shift;
 	u32 pipd_mask, pipd_shift;
@@ -157,7 +157,7 @@ static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
 	return 0;
 }
 
-int omap_hdmi_init(enum omap_hdmi_flags flags)
+int __init omap_hdmi_init(enum omap_hdmi_flags flags)
 {
 	if (cpu_is_omap44xx())
 		omap4_hdmi_mux_pads(flags);
@@ -165,7 +165,7 @@ int omap_hdmi_init(enum omap_hdmi_flags flags)
 	return 0;
 }
 
-static int omap_dsi_enable_pads(int dsi_id, unsigned lane_mask)
+static int __init omap_dsi_enable_pads(int dsi_id, unsigned lane_mask)
 {
 	if (cpu_is_omap44xx())
 		return omap4_dsi_mux_pads(dsi_id, lane_mask);
@@ -173,7 +173,7 @@ static int omap_dsi_enable_pads(int dsi_id, unsigned lane_mask)
 	return 0;
 }
 
-static void omap_dsi_disable_pads(int dsi_id, unsigned lane_mask)
+static void __init omap_dsi_disable_pads(int dsi_id, unsigned lane_mask)
 {
 	if (cpu_is_omap44xx())
 		omap4_dsi_mux_pads(dsi_id, 0);
diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
index f904766..a29ce94 100644
--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -293,8 +293,8 @@ static inline void omap_hsmmc_mux(struct omap_mmc_platform_data *mmc_controller,
 	}
 }
 
-static int omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
-				 struct omap_mmc_platform_data *mmc)
+static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
+					struct omap_mmc_platform_data *mmc)
 {
 	char *hc_name;
 
@@ -553,7 +553,7 @@ free_mmc:
 	kfree(mmc_data);
 }
 
-void omap_hsmmc_init(struct omap2_hsmmc_info *controllers)
+void __init omap_hsmmc_init(struct omap2_hsmmc_info *controllers)
 {
 	u32 reg;
 
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index fb8bc9f..f26b2fa 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -100,8 +100,8 @@ void omap_mux_write_array(struct omap_mux_partition *partition,
 
 static char *omap_mux_options;
 
-static int _omap_mux_init_gpio(struct omap_mux_partition *partition,
-			       int gpio, int val)
+static int __init _omap_mux_init_gpio(struct omap_mux_partition *partition,
+				      int gpio, int val)
 {
 	struct omap_mux_entry *e;
 	struct omap_mux *gpio_mux = NULL;
@@ -145,7 +145,7 @@ static int _omap_mux_init_gpio(struct omap_mux_partition *partition,
 	return 0;
 }
 
-int omap_mux_init_gpio(int gpio, int val)
+int __init omap_mux_init_gpio(int gpio, int val)
 {
 	struct omap_mux_partition *partition;
 	int ret;
@@ -159,9 +159,9 @@ int omap_mux_init_gpio(int gpio, int val)
 	return -ENODEV;
 }
 
-static int _omap_mux_get_by_name(struct omap_mux_partition *partition,
-				 const char *muxname,
-				 struct omap_mux **found_mux)
+static int __init _omap_mux_get_by_name(struct omap_mux_partition *partition,
+					const char *muxname,
+					struct omap_mux **found_mux)
 {
 	struct omap_mux *mux = NULL;
 	struct omap_mux_entry *e;
@@ -240,7 +240,7 @@ omap_mux_get_by_name(const char *muxname,
 	return -ENODEV;
 }
 
-int omap_mux_init_signal(const char *muxname, int val)
+int __init omap_mux_init_signal(const char *muxname, int val)
 {
 	struct omap_mux_partition *partition = NULL;
 	struct omap_mux *mux = NULL;

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

* [PATCH 3/3] ARM: OMAP2+: Mark omap_hsmmc_init and omap_mux related functions as __init
@ 2012-02-17 19:17         ` Tony Lindgren
  0 siblings, 0 replies; 66+ messages in thread
From: Tony Lindgren @ 2012-02-17 19:17 UTC (permalink / raw)
  To: linux-arm-kernel

* Tony Lindgren <tony@atomide.com> [120216 08:10]:
> * Russell King - ARM Linux <linux@arm.linux.org.uk> [120216 01:40]:
> > On Wed, Feb 15, 2012 at 10:28:30AM -0800, Tony Lindgren wrote:
> > > Now that omap hsmmc init is split into two functions, it's safe
> > > to mark omap_hsmmc_init and omap_mux related functions to __init.
> > > 
> > > This basically reverts the following fixes for the case where
> > > TWL was compiled as a module:
> > > 
> > > d5de63 (ARM: omap: preemptively fix section mismatch in omap4_sdp4430_wifi_mux_init())
> > 
> > Why did you include this one?  This is unrelated to the TWL problems.
> 
> Oops sorry, thanks for noticing. Your patch makes it __init,
> I was reading the patch wrong way around. Your patch should
> stay and my patch now changes it the wrong way.

Here's the updated patch, looks I had two bad reverts there,
only two are needed.

Regards,

Tony


From: Tony Lindgren <tony@atomide.com>
Date: Tue, 14 Feb 2012 18:17:54 -0800
Subject: [PATCH] ARM: OMAP2+: Mark omap_hsmmc_init and omap_mux related functions as __init

Now that omap hsmmc init is split into two functions, it's safe
to mark omap_hsmmc_init and omap_mux related functions to __init.

This basically reverts the following fixes for the case where
TWL was compiled as a module:

a98f77b (ARM: omap: fix section mismatch warning for sdp3430_twl_gpio_setup())
8930b4e (ARM: omap: fix section mismatch warnings in mux.c caused by hsmmc.c)

Additionally it fixes up the remaining section warnings for
all callers of omap_mux functions.

Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Tony Lindgren <tony@atomide.com>

diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c
index 30a6f52..0349fd2 100644
--- a/arch/arm/mach-omap2/board-flash.c
+++ b/arch/arm/mach-omap2/board-flash.c
@@ -189,7 +189,7 @@ unmap:
  *
  * @return - void.
  */
-void board_flash_init(struct flash_partitions partition_info[],
+void __init board_flash_init(struct flash_partitions partition_info[],
 			char chip_sel_board[][GPMC_CS_NUM], int nand_type)
 {
 	u8		cs = 0;
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 78bfcd5..7be8d65 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -273,8 +273,6 @@ static int beagle_twl_gpio_setup(struct device *dev,
 {
 	int r;
 
-	if (beagle_config.mmc1_gpio_wp != -EINVAL)
-		omap_mux_init_gpio(beagle_config.mmc1_gpio_wp, OMAP_PIN_INPUT);
 	mmc[0].gpio_wp = beagle_config.mmc1_gpio_wp;
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	mmc[0].gpio_cd = gpio + 0;
@@ -522,7 +520,11 @@ static void __init omap3_beagle_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 	omap3_beagle_init_rev();
+
+	if (beagle_config.mmc1_gpio_wp != -EINVAL)
+		omap_mux_init_gpio(beagle_config.mmc1_gpio_wp, OMAP_PIN_INPUT);
 	omap_hsmmc_init(mmc);
+
 	omap3_beagle_i2c_init();
 
 	gpio_buttons[0].gpio = beagle_config.usr_button_gpio;
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index db0aa27..0f9a983 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -363,7 +363,6 @@ static int omap3evm_twl_gpio_setup(struct device *dev,
 	int r, lcd_bl_en;
 
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
-	omap_mux_init_gpio(63, OMAP_PIN_INPUT);
 	mmc[0].gpio_cd = gpio + 0;
 	omap_hsmmc_late_init(mmc);
 
@@ -646,7 +645,9 @@ static void __init omap3_evm_init(void)
 	omap_board_config = omap3_evm_config;
 	omap_board_config_size = ARRAY_SIZE(omap3_evm_config);
 
+	omap_mux_init_gpio(63, OMAP_PIN_INPUT);
 	omap_hsmmc_init(mmc);
+
 	omap3_evm_i2c_init();
 
 	omap_display_init(&omap3_evm_dss_data);
diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c
index 8eee993..6410043 100644
--- a/arch/arm/mach-omap2/board-omap3stalker.c
+++ b/arch/arm/mach-omap2/board-omap3stalker.c
@@ -283,7 +283,6 @@ omap3stalker_twl_gpio_setup(struct device *dev,
 			    unsigned gpio, unsigned ngpio)
 {
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
-	omap_mux_init_gpio(23, OMAP_PIN_INPUT);
 	mmc[0].gpio_cd = gpio + 0;
 	omap_hsmmc_late_init(mmc);
 
@@ -426,7 +425,9 @@ static void __init omap3_stalker_init(void)
 	omap_board_config = omap3_stalker_config;
 	omap_board_config_size = ARRAY_SIZE(omap3_stalker_config);
 
+	omap_mux_init_gpio(23, OMAP_PIN_INPUT);
 	omap_hsmmc_init(mmc);
+
 	omap3_stalker_i2c_init();
 
 	platform_add_devices(omap3_stalker_devices,
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index ba9c118..8842e04 100644
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -118,12 +118,6 @@ static struct gpio_led gpio_leds[];
 static int touchbook_twl_gpio_setup(struct device *dev,
 		unsigned gpio, unsigned ngpio)
 {
-	if (system_rev >= 0x20 && system_rev <= 0x34301000) {
-		omap_mux_init_gpio(23, OMAP_PIN_INPUT);
-		mmc[0].gpio_wp = 23;
-	} else {
-		omap_mux_init_gpio(29, OMAP_PIN_INPUT);
-	}
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	mmc[0].gpio_cd = gpio + 0;
 	omap_hsmmc_late_init(mmc);
@@ -352,7 +346,14 @@ static void __init omap3_touchbook_init(void)
 
 	pm_power_off = omap3_touchbook_poweroff;
 
+	if (system_rev >= 0x20 && system_rev <= 0x34301000) {
+		omap_mux_init_gpio(23, OMAP_PIN_INPUT);
+		mmc[0].gpio_wp = 23;
+	} else {
+		omap_mux_init_gpio(29, OMAP_PIN_INPUT);
+	}
 	omap_hsmmc_init(mmc);
+
 	omap3_touchbook_i2c_init();
 	platform_add_devices(omap3_touchbook_devices,
 			ARRAY_SIZE(omap3_touchbook_devices));
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index bcc563c..7ca7a5c 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -461,7 +461,7 @@ static struct omap_dss_board_info omap4_panda_dss_data = {
 	.default_device	= &omap4_panda_dvi_device,
 };
 
-void omap4_panda_display_init(void)
+void __init omap4_panda_display_init(void)
 {
 	int r;
 
diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
index 3677b1f..62e133c 100644
--- a/arch/arm/mach-omap2/display.c
+++ b/arch/arm/mach-omap2/display.c
@@ -124,7 +124,7 @@ static void omap4_hdmi_mux_pads(enum omap_hdmi_flags flags)
 	}
 }
 
-static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
+static int __init omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
 {
 	u32 enable_mask, enable_shift;
 	u32 pipd_mask, pipd_shift;
@@ -157,7 +157,7 @@ static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
 	return 0;
 }
 
-int omap_hdmi_init(enum omap_hdmi_flags flags)
+int __init omap_hdmi_init(enum omap_hdmi_flags flags)
 {
 	if (cpu_is_omap44xx())
 		omap4_hdmi_mux_pads(flags);
@@ -165,7 +165,7 @@ int omap_hdmi_init(enum omap_hdmi_flags flags)
 	return 0;
 }
 
-static int omap_dsi_enable_pads(int dsi_id, unsigned lane_mask)
+static int __init omap_dsi_enable_pads(int dsi_id, unsigned lane_mask)
 {
 	if (cpu_is_omap44xx())
 		return omap4_dsi_mux_pads(dsi_id, lane_mask);
@@ -173,7 +173,7 @@ static int omap_dsi_enable_pads(int dsi_id, unsigned lane_mask)
 	return 0;
 }
 
-static void omap_dsi_disable_pads(int dsi_id, unsigned lane_mask)
+static void __init omap_dsi_disable_pads(int dsi_id, unsigned lane_mask)
 {
 	if (cpu_is_omap44xx())
 		omap4_dsi_mux_pads(dsi_id, 0);
diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
index f904766..a29ce94 100644
--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -293,8 +293,8 @@ static inline void omap_hsmmc_mux(struct omap_mmc_platform_data *mmc_controller,
 	}
 }
 
-static int omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
-				 struct omap_mmc_platform_data *mmc)
+static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
+					struct omap_mmc_platform_data *mmc)
 {
 	char *hc_name;
 
@@ -553,7 +553,7 @@ free_mmc:
 	kfree(mmc_data);
 }
 
-void omap_hsmmc_init(struct omap2_hsmmc_info *controllers)
+void __init omap_hsmmc_init(struct omap2_hsmmc_info *controllers)
 {
 	u32 reg;
 
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index fb8bc9f..f26b2fa 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -100,8 +100,8 @@ void omap_mux_write_array(struct omap_mux_partition *partition,
 
 static char *omap_mux_options;
 
-static int _omap_mux_init_gpio(struct omap_mux_partition *partition,
-			       int gpio, int val)
+static int __init _omap_mux_init_gpio(struct omap_mux_partition *partition,
+				      int gpio, int val)
 {
 	struct omap_mux_entry *e;
 	struct omap_mux *gpio_mux = NULL;
@@ -145,7 +145,7 @@ static int _omap_mux_init_gpio(struct omap_mux_partition *partition,
 	return 0;
 }
 
-int omap_mux_init_gpio(int gpio, int val)
+int __init omap_mux_init_gpio(int gpio, int val)
 {
 	struct omap_mux_partition *partition;
 	int ret;
@@ -159,9 +159,9 @@ int omap_mux_init_gpio(int gpio, int val)
 	return -ENODEV;
 }
 
-static int _omap_mux_get_by_name(struct omap_mux_partition *partition,
-				 const char *muxname,
-				 struct omap_mux **found_mux)
+static int __init _omap_mux_get_by_name(struct omap_mux_partition *partition,
+					const char *muxname,
+					struct omap_mux **found_mux)
 {
 	struct omap_mux *mux = NULL;
 	struct omap_mux_entry *e;
@@ -240,7 +240,7 @@ omap_mux_get_by_name(const char *muxname,
 	return -ENODEV;
 }
 
-int omap_mux_init_signal(const char *muxname, int val)
+int __init omap_mux_init_signal(const char *muxname, int val)
 {
 	struct omap_mux_partition *partition = NULL;
 	struct omap_mux *mux = NULL;

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

* Re: [PATCH 0/3] omap hsmmc init cleanup and section warning fixes for v3.4 merge window
  2012-02-17 14:24   ` Rajendra Nayak
@ 2012-02-17 20:21     ` Tony Lindgren
  -1 siblings, 0 replies; 66+ messages in thread
From: Tony Lindgren @ 2012-02-17 20:21 UTC (permalink / raw)
  To: Rajendra Nayak; +Cc: linux-arm-kernel, linux-omap

* Rajendra Nayak <rnayak@ti.com> [120217 05:53]:
> Tony,
> 
> On Wednesday 15 February 2012 11:58 PM, Tony Lindgren wrote:
> >Hi all,
> >
> >This series fixes up the issues noted by Russell on omap2_hsmmc_init()
> >where if TWL PMIC is compiled as a module we can't keep a bunch of
> >functions marked as __init like they should be. This series fixes
> >the issues by splitting omap2_hsmmc_init() into two functions.
> 
> I have a re-spin of this series ready with all the fixes I did
> while testing the insmod/unbind/bind test suggested by Russell.
> I could not figure out what branch your original patches were
> based on. So let me know what branch of your tree you want me
> to post this series on.

I have them on mainline commit a269c2f5a5ad2b24a19fdd723363daf18394ec85.

Note that we should fix what Russell noted separately for the -rc
series for the issue where reloading gpio-twl4030.ko calls
omap2_hsmmc_init() twice, maybe something like below for that.

Regards,

Tony

--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -428,6 +428,7 @@ static int omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
 	return 0;
 }
 
+static int omap_hsmmc_done;
 #define MAX_OMAP_MMC_HWMOD_NAME_LEN		16
 
 void omap_init_hsmmc(struct omap2_hsmmc_info *hsmmcinfo, int ctrl_nr)
@@ -491,6 +492,11 @@ void omap2_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;

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

* [PATCH 0/3] omap hsmmc init cleanup and section warning fixes for v3.4 merge window
@ 2012-02-17 20:21     ` Tony Lindgren
  0 siblings, 0 replies; 66+ messages in thread
From: Tony Lindgren @ 2012-02-17 20:21 UTC (permalink / raw)
  To: linux-arm-kernel

* Rajendra Nayak <rnayak@ti.com> [120217 05:53]:
> Tony,
> 
> On Wednesday 15 February 2012 11:58 PM, Tony Lindgren wrote:
> >Hi all,
> >
> >This series fixes up the issues noted by Russell on omap2_hsmmc_init()
> >where if TWL PMIC is compiled as a module we can't keep a bunch of
> >functions marked as __init like they should be. This series fixes
> >the issues by splitting omap2_hsmmc_init() into two functions.
> 
> I have a re-spin of this series ready with all the fixes I did
> while testing the insmod/unbind/bind test suggested by Russell.
> I could not figure out what branch your original patches were
> based on. So let me know what branch of your tree you want me
> to post this series on.

I have them on mainline commit a269c2f5a5ad2b24a19fdd723363daf18394ec85.

Note that we should fix what Russell noted separately for the -rc
series for the issue where reloading gpio-twl4030.ko calls
omap2_hsmmc_init() twice, maybe something like below for that.

Regards,

Tony

--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -428,6 +428,7 @@ static int omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
 	return 0;
 }
 
+static int omap_hsmmc_done;
 #define MAX_OMAP_MMC_HWMOD_NAME_LEN		16
 
 void omap_init_hsmmc(struct omap2_hsmmc_info *hsmmcinfo, int ctrl_nr)
@@ -491,6 +492,11 @@ void omap2_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;

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

* Re: [PATCH 0/3] omap hsmmc init cleanup and section warning fixes for v3.4 merge window
  2012-02-17  9:14             ` Russell King - ARM Linux
@ 2012-02-17 21:23               ` Tony Lindgren
  -1 siblings, 0 replies; 66+ messages in thread
From: Tony Lindgren @ 2012-02-17 21:23 UTC (permalink / raw)
  To: Russell King - ARM Linux; +Cc: Rajendra Nayak, linux-omap, linux-arm-kernel

* Russell King - ARM Linux <linux@arm.linux.org.uk> [120217 00:43]:
> 
> Tony: I think there's a bug here - if the gpio-twl4030 module is inserted,
> removed and re-inserted, I think we'll end up creating the devices for MMC
> twice with the same name, resulting in sysfs complaining very loudly.

I guess you mean without splitting omap2_hsmmc_init() into two functions.
Yup that's a nasty surprise that should be fixed for the -rc series.

Regards,

Tony

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

* [PATCH 0/3] omap hsmmc init cleanup and section warning fixes for v3.4 merge window
@ 2012-02-17 21:23               ` Tony Lindgren
  0 siblings, 0 replies; 66+ messages in thread
From: Tony Lindgren @ 2012-02-17 21:23 UTC (permalink / raw)
  To: linux-arm-kernel

* Russell King - ARM Linux <linux@arm.linux.org.uk> [120217 00:43]:
> 
> Tony: I think there's a bug here - if the gpio-twl4030 module is inserted,
> removed and re-inserted, I think we'll end up creating the devices for MMC
> twice with the same name, resulting in sysfs complaining very loudly.

I guess you mean without splitting omap2_hsmmc_init() into two functions.
Yup that's a nasty surprise that should be fixed for the -rc series.

Regards,

Tony

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

* Re: [PATCH 0/3] omap hsmmc init cleanup and section warning fixes for v3.4 merge window
  2012-02-17 20:21     ` Tony Lindgren
@ 2012-02-17 22:37       ` Tony Lindgren
  -1 siblings, 0 replies; 66+ messages in thread
From: Tony Lindgren @ 2012-02-17 22:37 UTC (permalink / raw)
  To: Rajendra Nayak; +Cc: linux-arm-kernel, linux-omap

* Tony Lindgren <tony@atomide.com> [120217 11:50]:
> * Rajendra Nayak <rnayak@ti.com> [120217 05:53]:
> > Tony,
> > 
> > On Wednesday 15 February 2012 11:58 PM, Tony Lindgren wrote:
> > >Hi all,
> > >
> > >This series fixes up the issues noted by Russell on omap2_hsmmc_init()
> > >where if TWL PMIC is compiled as a module we can't keep a bunch of
> > >functions marked as __init like they should be. This series fixes
> > >the issues by splitting omap2_hsmmc_init() into two functions.
> > 
> > I have a re-spin of this series ready with all the fixes I did
> > while testing the insmod/unbind/bind test suggested by Russell.
> > I could not figure out what branch your original patches were
> > based on. So let me know what branch of your tree you want me
> > to post this series on.
> 
> I have them on mainline commit a269c2f5a5ad2b24a19fdd723363daf18394ec85.
> 
> Note that we should fix what Russell noted separately for the -rc
> series for the issue where reloading gpio-twl4030.ko calls
> omap2_hsmmc_init() twice, maybe something like below for that.

Here's a better fix for -rc series that also fixes a panic that I was
getting on zoom3.

Tony


From: Tony Lindgren <tony@atomide.com>
Date: Fri, 17 Feb 2012 11:33:37 -0800
Subject: [PATCH] ARM: OMAP: Fix kernel panic with HSMMC when twl4030_gpio is a module

On some omaps twl4030_gpio has a callback to try to initialize
the MMC controller. If twl4030_gpio is compiled as a module,
bad things can happen because the callback function starts
calling functions that are supposed to be marked __init:

Kernel panic - not syncing: Attempted to kill the idle task!
twl4030_gpio twl4030_gpio: can't dispatch IRQs from modules
gpiochip_add: registered GPIOs 192 to 209 on device: twl4030
Unable to handle kernel paging request at virtual address b82a4c74
...

Additionally if this does not fail, warnings are produced
about trying to register the MMC multiple times.

Fix this by removing __init from omap_mux_get_by_name,
and add checks if omap2_hsmmc_init() is getting called more
than once.

Note that this will get fixed properly later on by splitting
omap2_hsmmc_init into two functions.

Reported-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Tony Lindgren <tony@atomide.com>

diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
index b40c288..19dd165 100644
--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -428,6 +428,7 @@ static int omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
 	return 0;
 }
 
+static int omap_hsmmc_done;
 #define MAX_OMAP_MMC_HWMOD_NAME_LEN		16
 
 void omap_init_hsmmc(struct omap2_hsmmc_info *hsmmcinfo, int ctrl_nr)
@@ -491,6 +492,11 @@ void omap2_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;
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index fb8bc9f..611a0e3 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -218,7 +218,7 @@ static int _omap_mux_get_by_name(struct omap_mux_partition *partition,
 	return -ENODEV;
 }
 
-static int __init
+static int
 omap_mux_get_by_name(const char *muxname,
 			struct omap_mux_partition **found_partition,
 			struct omap_mux **found_mux)

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

* [PATCH 0/3] omap hsmmc init cleanup and section warning fixes for v3.4 merge window
@ 2012-02-17 22:37       ` Tony Lindgren
  0 siblings, 0 replies; 66+ messages in thread
From: Tony Lindgren @ 2012-02-17 22:37 UTC (permalink / raw)
  To: linux-arm-kernel

* Tony Lindgren <tony@atomide.com> [120217 11:50]:
> * Rajendra Nayak <rnayak@ti.com> [120217 05:53]:
> > Tony,
> > 
> > On Wednesday 15 February 2012 11:58 PM, Tony Lindgren wrote:
> > >Hi all,
> > >
> > >This series fixes up the issues noted by Russell on omap2_hsmmc_init()
> > >where if TWL PMIC is compiled as a module we can't keep a bunch of
> > >functions marked as __init like they should be. This series fixes
> > >the issues by splitting omap2_hsmmc_init() into two functions.
> > 
> > I have a re-spin of this series ready with all the fixes I did
> > while testing the insmod/unbind/bind test suggested by Russell.
> > I could not figure out what branch your original patches were
> > based on. So let me know what branch of your tree you want me
> > to post this series on.
> 
> I have them on mainline commit a269c2f5a5ad2b24a19fdd723363daf18394ec85.
> 
> Note that we should fix what Russell noted separately for the -rc
> series for the issue where reloading gpio-twl4030.ko calls
> omap2_hsmmc_init() twice, maybe something like below for that.

Here's a better fix for -rc series that also fixes a panic that I was
getting on zoom3.

Tony


From: Tony Lindgren <tony@atomide.com>
Date: Fri, 17 Feb 2012 11:33:37 -0800
Subject: [PATCH] ARM: OMAP: Fix kernel panic with HSMMC when twl4030_gpio is a module

On some omaps twl4030_gpio has a callback to try to initialize
the MMC controller. If twl4030_gpio is compiled as a module,
bad things can happen because the callback function starts
calling functions that are supposed to be marked __init:

Kernel panic - not syncing: Attempted to kill the idle task!
twl4030_gpio twl4030_gpio: can't dispatch IRQs from modules
gpiochip_add: registered GPIOs 192 to 209 on device: twl4030
Unable to handle kernel paging request at virtual address b82a4c74
...

Additionally if this does not fail, warnings are produced
about trying to register the MMC multiple times.

Fix this by removing __init from omap_mux_get_by_name,
and add checks if omap2_hsmmc_init() is getting called more
than once.

Note that this will get fixed properly later on by splitting
omap2_hsmmc_init into two functions.

Reported-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Tony Lindgren <tony@atomide.com>

diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
index b40c288..19dd165 100644
--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -428,6 +428,7 @@ static int omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
 	return 0;
 }
 
+static int omap_hsmmc_done;
 #define MAX_OMAP_MMC_HWMOD_NAME_LEN		16
 
 void omap_init_hsmmc(struct omap2_hsmmc_info *hsmmcinfo, int ctrl_nr)
@@ -491,6 +492,11 @@ void omap2_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;
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index fb8bc9f..611a0e3 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -218,7 +218,7 @@ static int _omap_mux_get_by_name(struct omap_mux_partition *partition,
 	return -ENODEV;
 }
 
-static int __init
+static int
 omap_mux_get_by_name(const char *muxname,
 			struct omap_mux_partition **found_partition,
 			struct omap_mux **found_mux)

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

* Re: [PATCH 0/3] omap hsmmc init cleanup and section warning fixes for v3.4 merge window
  2012-02-17 20:21     ` Tony Lindgren
@ 2012-02-21  5:19       ` Rajendra Nayak
  -1 siblings, 0 replies; 66+ messages in thread
From: Rajendra Nayak @ 2012-02-21  5:19 UTC (permalink / raw)
  To: Tony Lindgren; +Cc: linux-arm-kernel, linux-omap

On Saturday 18 February 2012 01:51 AM, Tony Lindgren wrote:
> * Rajendra Nayak<rnayak@ti.com>  [120217 05:53]:
>> Tony,
>>
>> On Wednesday 15 February 2012 11:58 PM, Tony Lindgren wrote:
>>> Hi all,
>>>
>>> This series fixes up the issues noted by Russell on omap2_hsmmc_init()
>>> where if TWL PMIC is compiled as a module we can't keep a bunch of
>>> functions marked as __init like they should be. This series fixes
>>> the issues by splitting omap2_hsmmc_init() into two functions.
>>
>> I have a re-spin of this series ready with all the fixes I did
>> while testing the insmod/unbind/bind test suggested by Russell.
>> I could not figure out what branch your original patches were
>> based on. So let me know what branch of your tree you want me
>> to post this series on.
>
> I have them on mainline commit a269c2f5a5ad2b24a19fdd723363daf18394ec85.

I could not get them to apply on the above commit, but I was able to on
this mainline commit instead '4f8a428dac431e7bd09673b404769d87df948eef'.

Anyways, now that -rc4 is out I based my series on top of that.

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

* [PATCH 0/3] omap hsmmc init cleanup and section warning fixes for v3.4 merge window
@ 2012-02-21  5:19       ` Rajendra Nayak
  0 siblings, 0 replies; 66+ messages in thread
From: Rajendra Nayak @ 2012-02-21  5:19 UTC (permalink / raw)
  To: linux-arm-kernel

On Saturday 18 February 2012 01:51 AM, Tony Lindgren wrote:
> * Rajendra Nayak<rnayak@ti.com>  [120217 05:53]:
>> Tony,
>>
>> On Wednesday 15 February 2012 11:58 PM, Tony Lindgren wrote:
>>> Hi all,
>>>
>>> This series fixes up the issues noted by Russell on omap2_hsmmc_init()
>>> where if TWL PMIC is compiled as a module we can't keep a bunch of
>>> functions marked as __init like they should be. This series fixes
>>> the issues by splitting omap2_hsmmc_init() into two functions.
>>
>> I have a re-spin of this series ready with all the fixes I did
>> while testing the insmod/unbind/bind test suggested by Russell.
>> I could not figure out what branch your original patches were
>> based on. So let me know what branch of your tree you want me
>> to post this series on.
>
> I have them on mainline commit a269c2f5a5ad2b24a19fdd723363daf18394ec85.

I could not get them to apply on the above commit, but I was able to on
this mainline commit instead '4f8a428dac431e7bd09673b404769d87df948eef'.

Anyways, now that -rc4 is out I based my series on top of that.

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

end of thread, other threads:[~2012-02-21  5:19 UTC | newest]

Thread overview: 66+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-02-15 18:28 [PATCH 0/3] omap hsmmc init cleanup and section warning fixes for v3.4 merge window Tony Lindgren
2012-02-15 18:28 ` Tony Lindgren
2012-02-15 18:28 ` [PATCH 1/3] ARM: OMAP: omap_device: Expose omap_device_{alloc, delete, register} Tony Lindgren
2012-02-15 18:28   ` Tony Lindgren
2012-02-15 18:28 ` [PATCH 2/3] ARM: OMAP2+: Split omap2_hsmmc_init() to properly support I2C GPIO pins Tony Lindgren
2012-02-15 18:28   ` Tony Lindgren
2012-02-16 10:03   ` Rajendra Nayak
2012-02-16 10:03     ` Rajendra Nayak
2012-02-16 10:13     ` Rajendra Nayak
2012-02-16 10:13       ` Rajendra Nayak
2012-02-16 16:35       ` Tony Lindgren
2012-02-16 16:35         ` Tony Lindgren
2012-02-16 16:46         ` Cousson, Benoit
2012-02-16 16:46           ` Cousson, Benoit
2012-02-16 16:51         ` Rajendra Nayak
2012-02-16 16:51           ` Rajendra Nayak
2012-02-16 17:06           ` Tony Lindgren
2012-02-16 17:06             ` Tony Lindgren
2012-02-17 18:10             ` Tony Lindgren
2012-02-17 18:10               ` Tony Lindgren
2012-02-16 16:45   ` Tony Lindgren
2012-02-16 16:45     ` Tony Lindgren
2012-02-17 19:05     ` Tony Lindgren
2012-02-17 19:05       ` Tony Lindgren
2012-02-15 18:28 ` [PATCH 3/3] ARM: OMAP2+: Mark omap_hsmmc_init and omap_mux related functions as __init Tony Lindgren
2012-02-15 18:28   ` Tony Lindgren
2012-02-16 10:11   ` Russell King - ARM Linux
2012-02-16 10:11     ` Russell King - ARM Linux
2012-02-16 16:41     ` Tony Lindgren
2012-02-16 16:41       ` Tony Lindgren
2012-02-17 19:17       ` Tony Lindgren
2012-02-17 19:17         ` Tony Lindgren
2012-02-16 12:00 ` [PATCH 0/3] omap hsmmc init cleanup and section warning fixes for v3.4 merge window Nayak, Rajendra
2012-02-16 12:00   ` Nayak, Rajendra
2012-02-16 12:12   ` Russell King - ARM Linux
2012-02-16 12:12     ` Russell King - ARM Linux
2012-02-16 12:34     ` Rajendra Nayak
2012-02-16 12:34       ` Rajendra Nayak
2012-02-16 13:15       ` Rajendra Nayak
2012-02-16 13:15         ` Rajendra Nayak
2012-02-16 13:51         ` Russell King - ARM Linux
2012-02-16 13:51           ` Russell King - ARM Linux
2012-02-17  9:14           ` Russell King - ARM Linux
2012-02-17  9:14             ` Russell King - ARM Linux
2012-02-17  9:33             ` Rajendra Nayak
2012-02-17  9:33               ` Rajendra Nayak
2012-02-17  9:37               ` Rajendra Nayak
2012-02-17  9:37                 ` Rajendra Nayak
2012-02-17  9:59               ` Rajendra Nayak
2012-02-17  9:59                 ` Rajendra Nayak
2012-02-17 10:06                 ` Russell King - ARM Linux
2012-02-17 10:06                   ` Russell King - ARM Linux
2012-02-17 10:18                   ` Rajendra Nayak
2012-02-17 10:18                     ` Rajendra Nayak
2012-02-17 10:26                     ` Rajendra Nayak
2012-02-17 10:26                       ` Rajendra Nayak
2012-02-17 21:23             ` Tony Lindgren
2012-02-17 21:23               ` Tony Lindgren
2012-02-17 14:24 ` Rajendra Nayak
2012-02-17 14:24   ` Rajendra Nayak
2012-02-17 20:21   ` Tony Lindgren
2012-02-17 20:21     ` Tony Lindgren
2012-02-17 22:37     ` Tony Lindgren
2012-02-17 22:37       ` Tony Lindgren
2012-02-21  5:19     ` Rajendra Nayak
2012-02-21  5:19       ` Rajendra Nayak

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.