[PATCH 5/6] ARM: OMAP3: Modify omap_hsmmc_late_init to handle deleting mmc devices

Rajendra Nayak rnayak at ti.com
Fri Feb 24 04:58:56 EST 2012


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

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

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




More information about the linux-arm-kernel mailing list