After a warm restart, an eMMC which cannot be powered off is
in an unknown state, so reset it to be sure it will initialize.

Signed-off-by: Adrian Hunter <adrian.hun...@nokia.com>
---
 drivers/mmc/host/omap_hsmmc.c |   38 +++++++++++++++++++++++++++++++++++++-
 1 files changed, 37 insertions(+), 1 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 8c5e7d3..c791230 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -542,10 +542,25 @@ static int omap_hsmmc_gpio_init(struct 
omap_mmc_platform_data *pdata)
        } else
                pdata->slots[0].gpio_wp = -EINVAL;
 
+       if (gpio_is_valid(pdata->slots[0].gpio_hw_reset)) {
+               ret = gpio_request(pdata->slots[0].gpio_hw_reset,
+                                  "mmc_hw_reset");
+               if (ret)
+                       goto err_free_wp;
+               ret = gpio_direction_output(pdata->slots[0].gpio_hw_reset, 1);
+               if (ret)
+                       goto err_free_hw_reset;
+       } else
+               pdata->slots[0].gpio_hw_reset = -EINVAL;
+
        return 0;
 
+
+err_free_hw_reset:
+       gpio_free(pdata->slots[0].gpio_hw_reset);
 err_free_wp:
-       gpio_free(pdata->slots[0].gpio_wp);
+       if (gpio_is_valid(pdata->slots[0].gpio_wp))
+               gpio_free(pdata->slots[0].gpio_wp);
 err_free_cd:
        if (gpio_is_valid(pdata->slots[0].switch_pin))
 err_free_sp:
@@ -555,6 +570,8 @@ err_free_sp:
 
 static void omap_hsmmc_gpio_free(struct omap_mmc_platform_data *pdata)
 {
+       if (gpio_is_valid(pdata->slots[0].gpio_hw_reset))
+               gpio_free(pdata->slots[0].gpio_hw_reset);
        if (gpio_is_valid(pdata->slots[0].gpio_wp))
                gpio_free(pdata->slots[0].gpio_wp);
        if (gpio_is_valid(pdata->slots[0].switch_pin))
@@ -815,6 +832,18 @@ static void omap_hsmmc_context_save(struct omap_hsmmc_host 
*host)
 
 #endif
 
+static void omap_hsmmc_do_hw_reset(struct omap_hsmmc_host *host)
+{
+       if (!gpio_is_valid(mmc_slot(host).gpio_hw_reset))
+               return;
+
+       gpio_set_value_cansleep(mmc_slot(host).gpio_hw_reset, 0);
+       udelay(9);
+       gpio_set_value_cansleep(mmc_slot(host).gpio_hw_reset, 1);
+       usleep_range(1000, 2000);
+       printk(KERN_INFO "%s: hardware reset done\n", mmc_hostname(host->mmc));
+}
+
 /*
  * Send init stream sequence to card
  * before sending IDLE command
@@ -827,6 +856,13 @@ static void send_init_stream(struct omap_hsmmc_host *host)
        if (host->protect_card)
                return;
 
+       /*
+        * After a warm restart, an eMMC which cannot be powered off is in an
+        * unknown state so reset it to be sure it will initialize.
+        */
+       if (mmc_slot(host).no_off)
+               omap_hsmmc_do_hw_reset(host);
+
        disable_irq(host->irq);
 
        OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK);
-- 
1.7.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to