Skip to contentSkip to conversation

omap hsmmc init cleanup and section warning fixes for v3.4 merge window

PATCH New Tony Lindgren 4 participants 33 messages Feb 15, 2012 – Feb 21, 2012

Subsystems (4)
lore
Share & tools
lore

Tony Lindgren

author maintainer
#0 lore raw

cover omap hsmmc init cleanup and section warning fixes for v3.4 merge window

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 · 1 line
Signature
author maintainer
#1 lore raw

PATCH 1/3 ARM: OMAP: omap_device: Expose omap_device_{alloc, delete, register}

From: Ohad Ben-Cohen <[email protected]>

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.

---
 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(-)
arch/arm/plat-omap/include/plat/omap_device.h +7 -0
index 51423d2..05f7615 100644
@@ -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);
 
arch/arm/plat-omap/omap_device.c +3 -10
index e8d9869..f72fafc 100644
@@ -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);
 
author maintainer
#2 lore raw

PATCH 2/3 ARM: OMAP2+: Split omap2_hsmmc_init() to properly support I2C GPIO pins

In reply to Tony Lindgren

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.

---
 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(-)
arch/arm/mach-omap2/board-2430sdp.c +1 -1
index 7370983..c8bda62 100644
@@ -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);
arch/arm/mach-omap2/board-3430sdp.c +4 -1
index 383717b..da75f23 100644
@@ -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)
arch/arm/mach-omap2/board-4430sdp.c +2 -2
index 4e90715..09ae257 100644
@@ -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;
 }
arch/arm/mach-omap2/board-am3517evm.c +1 -1
index 4b1cfe3..71138a1 100644
@@ -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")
arch/arm/mach-omap2/board-cm-t35.c +4 -2
index e921e3b..60f0501 100644
@@ -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();
arch/arm/mach-omap2/board-devkit8000.c +3 -1
index e873063..11cd2a8 100644
@@ -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));
arch/arm/mach-omap2/board-igep0020.c +6 -1
index a59ace0..ac1de09 100644
@@ -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));
arch/arm/mach-omap2/board-ldp.c +1 -1
index 2d2a61f..b5bc9b2 100644
@@ -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();
 }
 
arch/arm/mach-omap2/board-omap3beagle.c +3 -1
index 7ffcd28..78bfcd5 100644
@@ -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;
arch/arm/mach-omap2/board-omap3evm.c +4 -1
index c775bea..db0aa27 100644
@@ -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);
arch/arm/mach-omap2/board-omap3logic.c +1 -1
index 4198dd0..2304ba3 100644
@@ -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 = {
arch/arm/mach-omap2/board-omap3pandora.c +5 -1
index 1644b73..84c83c8 100644
@@ -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,
arch/arm/mach-omap2/board-omap3stalker.c +7 -5
index cb089a4..8eee993 100644
@@ -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,
arch/arm/mach-omap2/board-omap3touchbook.c +3 -1
index a0b851a..ba9c118 100644
@@ -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));
arch/arm/mach-omap2/board-omap4panda.c +2 -2
index 28fc271..bcc563c 100644
@@ -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;
 }
arch/arm/mach-omap2/board-overo.c +4 -1
index 52c0cef..1fc5f7a 100644
@@ -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();
arch/arm/mach-omap2/board-rm680.c +1 -1
index 8678b38..2d24c98 100644
@@ -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
arch/arm/mach-omap2/board-rx51-peripherals.c +1 -1
index acb4e77..0e9d89a 100644
@@ -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();
 }
arch/arm/mach-omap2/board-zoom-peripherals.c +5 -1
index c126461..82a0f7c 100644
@@ -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);
arch/arm/mach-omap2/hsmmc.c +80 -27

153 lines not on this page · raw message

arch/arm/mach-omap2/hsmmc.h +9 -3
index c440973..07831cc 100644
@@ -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)
 {
 }
 
#3 lore raw

PATCH 2/3 ARM: OMAP2+: Split omap2_hsmmc_init() to properly support I2C GPIO pins

Hi Tony,

Quoted 13 lines · Tony Lindgren

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.

Quoted 6 lines

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.

Quoted 18 lines
---
  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 +
Quoted 9 lines
  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(-)

[]...

Quoted 22 lines
arch/arm/mach-omap2/board-cm-t35.c +2 -1
index e921e3b..60f0501 100644
@@ -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 */
  };

arch/arm/mach-omap2/board-cm-t35.c static int cm_t35_twl_gpio_setup(struct device *dev, unsigned gpio, · line 475

Quoted 5 lines
arch/arm/mach-omap2/board-cm-t35.c +1 -1
@@ -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.

[]...

Quoted 12 lines
arch/arm/mach-omap2/board-cm-t35.c +11 -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)

arch/arm/mach-omap2/board-cm-t35.c static int cm_t35_twl_gpio_setup(struct device *dev, unsigned gpio,

Quoted 10 lines
arch/arm/mach-omap2/board-cm-t35.c +10 -0
+			continue;
+
+		res = omap_device_register(pdev);
+		if (res) {
+			pr_err("Could not late init MMC %s\n",
+			       controllers->name);
+			continue;
+		}
+	}
+}

regards,
Rajendra

#4 lore raw

PATCH 2/3 ARM: OMAP2+: Split omap2_hsmmc_init() to properly support I2C GPIO pins

Quoted 3 lines · Rajendra Nayak

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

author maintainer
#5 lore raw

PATCH 2/3 ARM: OMAP2+: Split omap2_hsmmc_init() to properly support I2C GPIO pins

Quoted 18 lines · Rajendra Nayak
Quoted 3 lines · Rajendra Nayak

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

arch/arm/mach-omap2/board-omap3beagle.c static struct omap2_hsmmc_info mmc[] = { · line 259

Quoted 7 lines
arch/arm/mach-omap2/board-omap3beagle.c +1 -0
@@ -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

#6 lore raw

PATCH 2/3 ARM: OMAP2+: Split omap2_hsmmc_init() to properly support I2C GPIO pins

Quoted 21 lines · Tony Lindgren
Quoted 20 lines · Rajendra Nayak
Quoted 3 lines · Rajendra Nayak

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

(quoted diff) +0 -0
@@ -253,6 +253,7 @@
                 .mmc            = 1,
                 .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
Quoted 8 lines

arch/arm/mach-omap2/board-cm-t35.c static struct omap2_hsmmc_info mmc[] = { · line 427

Quoted 5 lines
arch/arm/mach-omap2/board-cm-t35.c +1 -0
                 .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

#7 lore raw

PATCH 2/3 ARM: OMAP2+: Split omap2_hsmmc_init() to properly support I2C GPIO pins

In reply to Tony Lindgren
Quoted 25 lines · Tony Lindgren
Quoted 11 lines · Rajendra Nayak
Quoted 10 lines
Quoted 3 lines
Quoted 3 lines

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(+)
Quoted 14 lines
Quoted 14 lines

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 */
Quoted 2 lines

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.

author maintainer
#8 lore raw

PATCH 2/3 ARM: OMAP2+: Split omap2_hsmmc_init() to properly support I2C GPIO pins

Quoted 26 lines · Rajendra Nayak
Quoted 25 lines · Tony Lindgren
Quoted 25 lines · Rajendra Nayak
Quoted 24 lines
Quoted 3 lines
Quoted 3 lines

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 */
Quoted 7 lines
Quoted 2 lines

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

author maintainer
#9 lore raw

PATCH 2/3 ARM: OMAP2+: Split omap2_hsmmc_init() to properly support I2C GPIO pins

Quoted 35 lines · Tony Lindgren
Quoted 26 lines · Rajendra Nayak
Quoted 25 lines · Tony Lindgren
Quoted 25 lines · Rajendra Nayak
Quoted 24 lines
Quoted 3 lines
Quoted 3 lines

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 */
Quoted 7 lines
Quoted 2 lines

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.

Quoted 6 lines

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

author maintainer
#10 lore raw

PATCH 2/3 ARM: OMAP2+: Split omap2_hsmmc_init() to properly support I2C GPIO pins

In reply to Tony Lindgren
Quoted 12 lines · Tony Lindgren
arch/arm/mach-omap2/hsmmc.c +11 -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)

arch/arm/mach-omap2/hsmmc.c static int omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, · line 451

Quoted 10 lines
arch/arm/mach-omap2/hsmmc.c +10 -0
+			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

author maintainer
#11 lore raw

PATCH 2/3 ARM: OMAP2+: Split omap2_hsmmc_init() to properly support I2C GPIO pins

Quoted 19 lines · Tony Lindgren
Quoted 18 lines · Tony Lindgren
(quoted diff) +17 -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);
Quoted 8 lines

Review

Quoted 4 lines
(quoted diff) +4 -0
+			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 <[email protected]>
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.

arch/arm/mach-omap2/board-2430sdp.c +1 -1
index 7370983..c8bda62 100644
@@ -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);
arch/arm/mach-omap2/board-3430sdp.c +4 -1
index 383717b..da75f23 100644
@@ -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)
arch/arm/mach-omap2/board-4430sdp.c +2 -2
index 4e90715..09ae257 100644
@@ -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;
 }
arch/arm/mach-omap2/board-am3517evm.c +1 -1
index 4b1cfe3..71138a1 100644
@@ -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")
arch/arm/mach-omap2/board-cm-t35.c +4 -2
index e921e3b..60f0501 100644
@@ -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();
arch/arm/mach-omap2/board-devkit8000.c +3 -1
index e873063..11cd2a8 100644
@@ -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));
arch/arm/mach-omap2/board-igep0020.c +6 -1
index a59ace0..ac1de09 100644
@@ -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));
arch/arm/mach-omap2/board-ldp.c +1 -1
index 2d2a61f..b5bc9b2 100644
@@ -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();
 }
 
arch/arm/mach-omap2/board-omap3beagle.c +3 -1
index 7ffcd28..78bfcd5 100644
@@ -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;
arch/arm/mach-omap2/board-omap3evm.c +4 -1
index c775bea..db0aa27 100644
@@ -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);
arch/arm/mach-omap2/board-omap3logic.c +1 -1
index 4198dd0..2304ba3 100644
@@ -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 = {
arch/arm/mach-omap2/board-omap3pandora.c +5 -1
index 1644b73..84c83c8 100644
@@ -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,
arch/arm/mach-omap2/board-omap3stalker.c +7 -5
index cb089a4..8eee993 100644
@@ -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,
arch/arm/mach-omap2/board-omap3touchbook.c +3 -1
index a0b851a..ba9c118 100644
@@ -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));
arch/arm/mach-omap2/board-omap4panda.c +2 -2
index 28fc271..bcc563c 100644
@@ -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;
 }
arch/arm/mach-omap2/board-overo.c +4 -1
index 52c0cef..1fc5f7a 100644
@@ -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();
arch/arm/mach-omap2/board-rm680.c +1 -1
index 8678b38..2d24c98 100644
@@ -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
arch/arm/mach-omap2/board-rx51-peripherals.c +1 -1
index acb4e77..0e9d89a 100644
@@ -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();
 }
arch/arm/mach-omap2/board-zoom-peripherals.c +5 -1
index c126461..82a0f7c 100644
@@ -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);
arch/arm/mach-omap2/hsmmc.c +93 -27

166 lines not on this page · raw message

arch/arm/mach-omap2/hsmmc.h +9 -3
index c440973..07831cc 100644
@@ -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)
 {
 }
 
author maintainer
#12 lore raw

PATCH 3/3 ARM: OMAP2+: Mark omap_hsmmc_init and omap_mux related functions as __init

In reply to Tony Lindgren

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.

---
 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(-)
arch/arm/mach-omap2/board-4430sdp.c +1 -1
index 09ae257..ece9e3a 100644
@@ -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);
arch/arm/mach-omap2/board-flash.c +1 -1
index 30a6f52..0349fd2 100644
@@ -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;
arch/arm/mach-omap2/board-omap3beagle.c +4 -2
index 78bfcd5..7be8d65 100644
@@ -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;
arch/arm/mach-omap2/board-omap3evm.c +2 -1
index db0aa27..0f9a983 100644
@@ -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);
arch/arm/mach-omap2/board-omap3stalker.c +2 -1
index 8eee993..6410043 100644
@@ -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,
arch/arm/mach-omap2/board-omap3touchbook.c +7 -6
index ba9c118..8842e04 100644
@@ -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));
arch/arm/mach-omap2/board-omap4panda.c +1 -1
index bcc563c..7ca7a5c 100644
@@ -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;
 
arch/arm/mach-omap2/display.c +4 -4
index 3677b1f..62e133c 100644
@@ -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);
arch/arm/mach-omap2/hsmmc.c +3 -3
index 0f774e5..59c3ee4 100644
@@ -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;
 
arch/arm/mach-omap2/mux.c +11 -11
index fb8bc9f..e1cc75d 100644
@@ -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)
 {
 }
 
#13 lore raw

PATCH 3/3 ARM: OMAP2+: Mark omap_hsmmc_init and omap_mux related functions as __init

Quoted 7 lines · Tony Lindgren

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.

author maintainer
#14 lore raw

PATCH 3/3 ARM: OMAP2+: Mark omap_hsmmc_init and omap_mux related functions as __init

Quoted 10 lines · Russell King - ARM Linux
Quoted 7 lines · Tony Lindgren

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

author maintainer
#15 lore raw

PATCH 3/3 ARM: OMAP2+: Mark omap_hsmmc_init and omap_mux related functions as __init

Quoted 8 lines · Tony Lindgren
Quoted 7 lines · Russell King - ARM Linux
Quoted 6 lines · Tony Lindgren

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:

Quoted 7 lines
Quoted 3 lines
Quoted 1 line

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 <[email protected]>
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.

arch/arm/mach-omap2/board-flash.c +1 -1
index 30a6f52..0349fd2 100644
@@ -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;
arch/arm/mach-omap2/board-omap3beagle.c +4 -2
index 78bfcd5..7be8d65 100644
@@ -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;
arch/arm/mach-omap2/board-omap3evm.c +2 -1
index db0aa27..0f9a983 100644
@@ -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);
arch/arm/mach-omap2/board-omap3stalker.c +2 -1
index 8eee993..6410043 100644
@@ -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,
arch/arm/mach-omap2/board-omap3touchbook.c +7 -6
index ba9c118..8842e04 100644
@@ -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));
arch/arm/mach-omap2/board-omap4panda.c +1 -1
index bcc563c..7ca7a5c 100644
@@ -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;
 
arch/arm/mach-omap2/display.c +4 -4
index 3677b1f..62e133c 100644
@@ -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);
arch/arm/mach-omap2/hsmmc.c +3 -3
index f904766..a29ce94 100644
@@ -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;
 
arch/arm/mach-omap2/mux.c +7 -7
index fb8bc9f..f26b2fa 100644
@@ -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;
#16 lore raw

cover omap hsmmc init cleanup and section warning fixes for v3.4 merge window

In reply to Tony Lindgren
Quoted 4 lines

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.

Quoted 1 line

From 5a4bbd64fd1e791b922b76ea8f12dac4216c0a0f Mon Sep 17 00:00:00 2001

From: Rajendra Nayak <[email protected]>
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.

---
 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(-)
(quoted diff) +0 -0

b/arch/arm/mach-omap2/board-4430sdp.c
index ece9e3a..966ea8d 100644

arch/arm/mach-omap2/board-4430sdp.c +6 -27
@@ -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,

(quoted diff) +0 -0

b/arch/arm/mach-omap2/board-omap4panda.c
index 7ca7a5c..493aa0a 100644

arch/arm/mach-omap2/board-omap4panda.c +7 -31
@@ -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);
/*

arch/arm/mach-omap2/hsmmc.c +1 -0
index 59c3ee4..ca9192a 100644
@@ -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)) {

drivers/mfd/twl-core.c +0 -0
index 8ce3959..753a829 100644
@@ -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);

include/linux/i2c/twl.h +1 -0
index 78d3465..e2d23bc 100644
@@ -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);
 };
 
 /*----------------------------------------------------------------------*/
Signature · 1 line
1.7.1
#17 lore raw

cover omap hsmmc init cleanup and section warning fixes for v3.4 merge window

Quoted 8 lines · Rajendra
Quoted 4 lines

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.

#18 lore raw

cover omap hsmmc init cleanup and section warning fixes for v3.4 merge window

Quoted 6 lines · Russell King - ARM Linux
Quoted 5 lines · Rajendra
Quoted 4 lines

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

Quoted 8 lines
Quoted 3 lines

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.

Quoted 1 line

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
Quoted 4 lines

4. Remove the gpio-twl4030 module
5. Re-load the gpio-twl4030.ko module

and report back what you get. Thanks.

#19 lore raw

cover omap hsmmc init cleanup and section warning fixes for v3.4 merge window

Quoted 9 lines · Rajendra Nayak
Quoted 4 lines

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.

Quoted 5 lines
Quoted 1 line

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.

Quoted 10 lines
# 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
Quoted 4 lines

4. Remove the gpio-twl4030 module
5. Re-load the gpio-twl4030.ko module

and report back what you get. Thanks.

#20 lore raw

cover omap hsmmc init cleanup and section warning fixes for v3.4 merge window

Quoted 16 lines · Rajendra Nayak
Quoted 9 lines · Rajendra Nayak
Quoted 4 lines

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.

Quoted 5 lines
Quoted 1 line

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.

Quoted 18 lines

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.

Quoted 10 lines
# 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
Quoted 4 lines

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.

#21 lore raw

cover omap hsmmc init cleanup and section warning fixes for v3.4 merge window

Quoted 30 lines · Russell King - ARM Linux
Quoted 29 lines · Rajendra Nayak
Quoted 9 lines · Rajendra Nayak
Quoted 4 lines

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.

Quoted 5 lines
Quoted 1 line

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.

Quoted 6 lines
# 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
Quoted 7 lines
Quoted 5 lines
Quoted 4 lines
Quoted 4 lines

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.

#22 lore raw

cover omap hsmmc init cleanup and section warning fixes for v3.4 merge window

[]...

Quoted 22 lines
Quoted 22 lines
Quoted 22 lines
Quoted 5 lines
Quoted 1 line

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.

Quoted 9 lines
# 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
Quoted 3 lines

4. Remove the gpio-twl4030 module
5. Re-load the gpio-twl4030.ko module

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
Quoted 1 line
Quoted 1 line

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...

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
[   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.

Quoted 4 lines

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.

#23 lore raw

cover omap hsmmc init cleanup and section warning fixes for v3.4 merge window

Quoted 58 lines · Rajendra Nayak

[]...

Quoted 24 lines
Quoted 24 lines
Quoted 24 lines
Quoted 5 lines
Quoted 1 line

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.

Quoted 11 lines
# 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
Quoted 3 lines

4. Remove the gpio-twl4030 module
5. Re-load the gpio-twl4030.ko module

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
Quoted 1 line
Quoted 1 line

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...

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
[ 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.

Quoted 6 lines

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.

Quoted 6 lines

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.

Quoted 8 lines

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.

#24 lore raw

cover omap hsmmc init cleanup and section warning fixes for v3.4 merge window

In reply to Rajendra Nayak
Quoted 25 lines · Rajendra Nayak

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...

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
[   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.

Quoted 6 lines

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.

Quoted 10 lines

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.

#25 lore raw

cover omap hsmmc init cleanup and section warning fixes for v3.4 merge window

Quoted 4 lines · Rajendra Nayak

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).

#26 lore raw

cover omap hsmmc init cleanup and section warning fixes for v3.4 merge window

Quoted 15 lines · Russell King - ARM Linux
Quoted 4 lines · Rajendra Nayak

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:

Quoted 7 lines
	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.

Quoted 3 lines

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)
#27 lore raw

cover omap hsmmc init cleanup and section warning fixes for v3.4 merge window

Quoted 4 lines · Rajendra Nayak
Quoted 1 line

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.

author maintainer
#28 lore raw

cover omap hsmmc init cleanup and section warning fixes for v3.4 merge window

In reply to Russell King - ARM Linux
Quoted 4 lines · Russell King - ARM Linux

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

#29 lore raw

cover omap hsmmc init cleanup and section warning fixes for v3.4 merge window

In reply to Tony Lindgren

Tony,

Quoted 6 lines · Tony Lindgren

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

Quoted 47 lines

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(-)
author maintainer
#30 lore raw

cover omap hsmmc init cleanup and section warning fixes for v3.4 merge window

Quoted 10 lines · Rajendra Nayak

Tony,

Quoted 6 lines · Tony Lindgren

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.

Quoted 5 lines

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

arch/arm/mach-omap2/hsmmc.c +6 -0
@@ -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;
author maintainer
#31 lore raw

cover omap hsmmc init cleanup and section warning fixes for v3.4 merge window

Quoted 17 lines · Tony Lindgren
Quoted 10 lines · Rajendra Nayak

Tony,

Quoted 6 lines · Tony Lindgren

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.

Quoted 5 lines

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.

Quoted 5 lines

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 <[email protected]>
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.

arch/arm/mach-omap2/hsmmc.c +6 -0
index b40c288..19dd165 100644
@@ -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;
arch/arm/mach-omap2/mux.c +1 -1
index fb8bc9f..611a0e3 100644
@@ -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)
#32 lore raw

cover omap hsmmc init cleanup and section warning fixes for v3.4 merge window

In reply to Tony Lindgren
Quoted 11 lines · Tony Lindgren
Quoted 10 lines · Rajendra Nayak

Tony,

Quoted 6 lines · Tony Lindgren

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.

Quoted 7 lines
Quoted 5 lines

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.