]> git.hungrycats.org Git - linux/commitdiff
[MMC] Make MMC card initialisation more reliable.
authorRussell King <rmk@flint.arm.linux.org.uk>
Wed, 29 Sep 2004 16:55:38 +0000 (17:55 +0100)
committerRussell King <rmk@flint.arm.linux.org.uk>
Wed, 29 Sep 2004 16:55:38 +0000 (17:55 +0100)
Pierre Ossman reported a problem where his cards do not correctly
initialise with the current MMC implementation.  However, if we
tell the card to go back to the idle state between probing the
supply voltage and telling the card about the chosen voltage, his
cards work - and we don't seem to upset existing cards.

drivers/mmc/mmc.c

index 38fb1b8e433b7001bbf319ecf5c263c8ff77d3ad..a73bdc5d7b3255307d663a37374b0a289369664d 100644 (file)
@@ -449,12 +449,27 @@ mmc_alloc_card(struct mmc_host *host, u32 *raw_cid, unsigned int *frca)
        return card;
 }
 
+/*
+ * Tell attached cards to go to IDLE state
+ */
+static void mmc_idle_cards(struct mmc_host *host)
+{
+       struct mmc_command cmd;
+
+       cmd.opcode = MMC_GO_IDLE_STATE;
+       cmd.arg = 0;
+       cmd.flags = MMC_RSP_NONE;
+
+       mmc_wait_for_cmd(host, &cmd, 0);
+
+       mmc_delay(1);
+}
+
 /*
  * Apply power to the MMC stack.
  */
 static void mmc_power_up(struct mmc_host *host)
 {
-       struct mmc_command cmd;
        int bit = fls(host->ocr_avail) - 1;
 
        host->ios.vdd = bit;
@@ -469,12 +484,6 @@ static void mmc_power_up(struct mmc_host *host)
        host->ops->set_ios(host, &host->ios);
 
        mmc_delay(2);
-
-       cmd.opcode = MMC_GO_IDLE_STATE;
-       cmd.arg = 0;
-       cmd.flags = MMC_RSP_NONE;
-
-       mmc_wait_for_cmd(host, &cmd, 0);
 }
 
 static void mmc_power_off(struct mmc_host *host)
@@ -646,12 +655,22 @@ static void mmc_setup(struct mmc_host *host)
                u32 ocr;
 
                mmc_power_up(host);
+               mmc_idle_cards(host);
 
                err = mmc_send_op_cond(host, 0, &ocr);
                if (err != MMC_ERR_NONE)
                        return;
 
                host->ocr = mmc_select_voltage(host, ocr);
+
+               /*
+                * Since we're changing the OCR value, we seem to
+                * need to tell some cards to go back to the idle
+                * state.  We wait 1ms to give cards time to
+                * respond.
+                */
+               if (host->ocr)
+                       mmc_idle_cards(host);
        } else {
                host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
                host->ios.clock = host->f_min;