[PATCH 44/133] [Jaunty SRU] ARM.imx51 Freescale:ENGR00110257 unifi_fs: re-initialize chip every time insert module

Brad Figg brad.figg at canonical.com
Thu Jul 9 16:48:34 UTC 2009


When rmmod, driver will try to poweroff wifi chip, so it may be in a wrong
state when insmod it again.
When insert unifi_sdio module, it will first pull down reset pin to remove
sdio device if it exists and add sdio device, init it again.

Signed-off-by: Richard Zhao <b20223 at freescale.com>
Signed-off-by: Brad Figg <brad.figg at canonical.com>
---
 arch/arm/mach-mx51/mx51_3stack.c     |   13 +-----
 arch/arm/plat-mxc/include/mach/mxc.h |    2 +-
 drivers/mmc/card/unifi_fs/fs_lx.c    |   69 ++++++++++++++-------------------
 drivers/mmc/host/mx_sdhci.c          |    2 -
 4 files changed, 32 insertions(+), 54 deletions(-)

diff --git a/arch/arm/mach-mx51/mx51_3stack.c b/arch/arm/mach-mx51/mx51_3stack.c
index 452b6f9..7e4d887 100644
--- a/arch/arm/mach-mx51/mx51_3stack.c
+++ b/arch/arm/mach-mx51/mx51_3stack.c
@@ -952,12 +952,9 @@ static void mxc_init_bluetooth(void)
 	(void)platform_device_register(&mxc_bt_device);
 }
 
-#if defined(CONFIG_SDIO_UNIFI_FS) || defined(CONFIG_SDIO_UNIFI_FS_MODULE)
-static void mxc_unifi_hardreset(void)
+static void mxc_unifi_hardreset(int pin_level)
 {
-	mxc_set_gpio_dataout(MX51_PIN_EIM_D19, 0);
-	msleep(100);
-	mxc_set_gpio_dataout(MX51_PIN_EIM_D19, 1);
+	mxc_set_gpio_dataout(MX51_PIN_EIM_D19, pin_level & 0x01);
 }
 
 static struct mxc_unifi_platform_data unifi_data = {
@@ -971,12 +968,6 @@ struct mxc_unifi_platform_data *get_unifi_plat_data(void)
 {
 	return &unifi_data;
 }
-#else
-struct mxc_unifi_platform_data *get_unifi_plat_data(void)
-{
-	return NULL;
-}
-#endif
 
 EXPORT_SYMBOL(get_unifi_plat_data);
 
diff --git a/arch/arm/plat-mxc/include/mach/mxc.h b/arch/arm/plat-mxc/include/mach/mxc.h
index 1b1ce12..b8d738e 100644
--- a/arch/arm/plat-mxc/include/mach/mxc.h
+++ b/arch/arm/plat-mxc/include/mach/mxc.h
@@ -293,7 +293,7 @@ struct mxc_keyp_platform_data {
 };
 
 struct mxc_unifi_platform_data {
-	void (*hardreset) (void);
+	void (*hardreset) (int pin_level);
 	void (*enable) (int en);
 	/* power parameters */
 	char *reg_gpo1;
diff --git a/drivers/mmc/card/unifi_fs/fs_lx.c b/drivers/mmc/card/unifi_fs/fs_lx.c
index 37b7bba..a33b6ce 100644
--- a/drivers/mmc/card/unifi_fs/fs_lx.c
+++ b/drivers/mmc/card/unifi_fs/fs_lx.c
@@ -245,7 +245,7 @@ EXPORT_SYMBOL(fs_sdio_set_block_size);
  *
  * ---------------------------------------------------------------------------
  */
-static void fs_unifi_power_on(int check_card)
+static void fs_unifi_power_on(void)
 {
 	struct regulator_unifi *reg_unifi;
 	unsigned int tmp;
@@ -284,11 +284,6 @@ static void fs_unifi_power_on(int check_card)
 		regulator_enable(reg_unifi->reg_1v5_dd);
 	}
 	msleep(10);
-	if (check_card) {
-		do_sdio_hard_reset(NULL);
-		msleep(500);
-		mxc_mmc_force_detect(plat_data->host_id);
-	}
 }
 
 /*
@@ -298,7 +293,7 @@ static void fs_unifi_power_on(int check_card)
  *
  * ---------------------------------------------------------------------------
  */
-static void fs_unifi_power_off(int check_card)
+static void fs_unifi_power_off(void)
 {
 	struct regulator_unifi *reg_unifi;
 
@@ -319,10 +314,6 @@ static void fs_unifi_power_off(int check_card)
 
 	if (reg_unifi->reg_gpo1)
 		regulator_disable(reg_unifi->reg_gpo1);
-
-	if (check_card)
-		mxc_mmc_force_detect(plat_data->host_id);
-
 }
 
 /* This should be made conditional on being slot 2 too - so we can
@@ -334,12 +325,6 @@ int fs_sdio_hard_reset(struct sdio_dev *fdev)
 }
 EXPORT_SYMBOL(fs_sdio_hard_reset);
 
-static int do_sdio_hard_reset(struct sdio_dev *fdev)
-{
-	plat_data->hardreset();
-	return 0;
-}
-
 static const struct sdio_device_id fs_sdio_ids[] = {
 	{SDIO_DEVICE(0x032a, 0x0001)},
 	{ /* end: all zeroes */	},
@@ -358,11 +343,32 @@ static struct sdio_driver sdio_unifi_driver = {
 
 int fs_sdio_register_driver(struct fs_driver *driver)
 {
-	int ret;
+	int ret, retry;
 
 	/* Switch us on, sdio device may exist if power is on by default. */
-	fs_unifi_power_on(available_sdio_dev ? 0 : 1);
-
+	plat_data->hardreset(0);
+	mxc_mmc_force_detect(plat_data->host_id);
+	/* Wait for card removed */
+	for (retry = 0; retry < 100; retry++) {
+		if (!available_sdio_dev)
+			break;
+		msleep(100);
+	}
+	if (retry == 100)
+		printk(KERN_ERR "fs_sdio_register_driver: sdio device exists, "
+				"timeout for card removed");
+	fs_unifi_power_on();
+	plat_data->hardreset(1);
+	msleep(500);
+	mxc_mmc_force_detect(plat_data->host_id);
+	for (retry = 0; retry < 100; retry++) {
+		if (available_sdio_dev)
+			break;
+		msleep(50);
+	}
+	if (retry == 1000)
+		printk(KERN_ERR "fs_sdio_register_driver: Timeout waiting"
+				" for card added\n");
 	/* Store the context to the device driver to the global */
 	available_driver = driver;
 
@@ -392,6 +398,7 @@ EXPORT_SYMBOL(fs_sdio_register_driver);
 
 void fs_sdio_unregister_driver(struct fs_driver *driver)
 {
+	int retry;
 	/*
 	 * If available_sdio_dev is not NULL, probe has been called,
 	 * so pass the remove to the registered driver to clean up.
@@ -421,9 +428,8 @@ void fs_sdio_unregister_driver(struct fs_driver *driver)
 	/* invalidate the context to the device driver to the global */
 	available_driver = NULL;
 	/* Power down the UniFi */
-	fs_unifi_power_off(-1);
-	/* Wait for card removed */
-	msleep(100);
+	fs_unifi_power_off();
+
 }
 EXPORT_SYMBOL(fs_sdio_unregister_driver);
 
@@ -488,23 +494,6 @@ static int fs_sdio_probe(struct sdio_func *func,
 	printk(KERN_INFO "fs_sdio_probe: Add glue driver\n");
 	sdio_set_drvdata(func, fdev);
 
-	/* TODO: If a device driver is registered, call it's probe here */
-	if (available_driver) {
-		/* Store the context to the device driver */
-		fdev->driver = available_driver;
-
-		printk(KERN_INFO "fs_sdio_probe: Add device driver and "
-		       "register IRQ\n");
-		available_driver->probe(fdev);
-
-		/* Register the IRQ handler to the SDIO IRQ. */
-		sdio_claim_host(fdev->func);
-		ret = sdio_claim_irq(func, fs_sdio_irq);
-		sdio_release_host(fdev->func);
-		if (ret)
-			return ret;
-	}
-
 	return 0;
 }
 
diff --git a/drivers/mmc/host/mx_sdhci.c b/drivers/mmc/host/mx_sdhci.c
index f4c51b5..986338f 100644
--- a/drivers/mmc/host/mx_sdhci.c
+++ b/drivers/mmc/host/mx_sdhci.c
@@ -129,8 +129,6 @@ void mxc_mmc_force_detect(int id)
 	if (!mxc_fix_chips[id])
 		return;
 	host = mxc_fix_chips[id]->hosts[0];
-	if (host->flags & SDHCI_CD_PRESENT)
-		return;
 	if (host->detect_irq)
 		return;
 
-- 
1.6.0.4





More information about the kernel-team mailing list