Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell King <rmk@flint.arm.linux.org.uk>2004-09-29 17:55:38 +0100
committerRussell King <rmk@flint.arm.linux.org.uk>2004-09-29 17:55:38 +0100
commit78b3f6d473a2a972007e951ddffed96c04335835 (patch)
tree7cab1413e51c58a52c9efeda627e26b8ffd3e6c1
parent0931f8a984b0e0db09ca3f75c9d5dedbf334f514 (diff)
[MMC] Make MMC card initialisation more reliable.
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.
-rw-r--r--drivers/mmc/mmc.c33
1 files changed, 26 insertions, 7 deletions
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 38fb1b8e433b..a73bdc5d7b32 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -450,11 +450,26 @@ mmc_alloc_card(struct mmc_host *host, u32 *raw_cid, unsigned int *frca)
}
/*
+ * 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;