Skip to contentSkip to conversation

MMC compatibility fix - GO_IDLE

PATCH In review Pierre Ossman 2 participants 4 messages Sep 18, 2004 – Sep 22, 2004 MMC, SD and SDIO

lore
Share & tools
lore
#0 lore raw

PATCH 1/3 MMC compatibility fix - GO_IDLE

This patch adds a GO_IDLE before sending a new SEND_OP_COND (as required by MMC standard).

drivers/mmc/mmc.c +12 -0
Index: linux-wbsd/drivers/mmc/mmc.c
===================================================================
@@ -579,6 +579,8 @@
 
 static void mmc_setup(struct mmc_host *host)
 {
+	struct mmc_command cmd;
+	
 	if (host->ios.power_mode != MMC_POWER_ON) {
 		int err;
 		u32 ocr;
@@ -613,6 +615,16 @@
 	if (host->ocr == 0)
 		return;
 
+	/* Put cards in idle before sending new OCR */
+
+	cmd.opcode = MMC_GO_IDLE_STATE;
+	cmd.arg = 0;
+	cmd.flags = MMC_RSP_NONE;
+	
+	mmc_wait_for_cmd(host, &cmd, 0);
+
+	mmc_delay(1);
+	
 	/*
 	 * Send the selected OCR multiple times... until the cards
 	 * all get the idea that they should be ready for CMD2.
#1 lore raw
Quoted 2 lines · Pierre Ossman

This patch adds a GO_IDLE before sending a new SEND_OP_COND (as required by MMC standard).

Thanks; I haven't completely vanished off the face of the planet.

We already have a function using MMC_GO_IDLE_STATE, so I suggest we separate this out. If you need a 1ms delay after sending this, maybe the other case also needs this delay as well?

How about this patch?

Signature · 4 lines
Russell King
 Linux kernel    2.6 ARM Linux   - http://www.arm.linux.org.uk/
 maintainer of:  2.6 PCMCIA      - http://pcmcia.arm.linux.org.uk/
                 2.6 Serial core
drivers/mmc/mmc.c +26 -7
diff -u linux-2.6-mmc/drivers/mmc/mmc.c linux/drivers/mmc/mmc.c
@@ -451,11 +451,26 @@
 }
 
 /*
+ * 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;
@@ -470,12 +485,6 @@
 	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)
@@ -647,12 +656,22 @@
 		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;
#2 lore raw
Quoted 10 lines · Russell King
Quoted 3 lines · Pierre Ossman

This patch adds a GO_IDLE before sending a new SEND_OP_COND (as required by MMC standard).

Thanks; I haven't completely vanished off the face of the planet.

Good to know. You've seemed a bit busy :)

Quoted 6 lines

We already have a function using MMC_GO_IDLE_STATE, so I suggest we separate this out. If you need a 1ms delay after sending this, maybe the other case also needs this delay as well?

The delay was added just in case. The cards I have here work fine without it. I just thought adding a small delay might avoid problematic cards later on. Seems to be a few of those.

Quoted 4 lines

How about this patch?

Looks ok. You sure we don't need to put all cards into an idle state before issuing a new SEND_OP_COND? I haven't studied how the MMC layer is called in detail. Can a rescan be done while a card is in a selected state?

Rgds
Pierre

#3 lore raw
Quoted 5 lines · Pierre Ossman
Quoted 1 line · Russell King

How about this patch?

Looks ok. You sure we don't need to put all cards into an idle state before issuing a new SEND_OP_COND?

We aren't sending that to the existing cards - they are still in whatever state they were when they were previously detected. In addition, we aren't actually changing or detecting the operational conditions, we're merely informing the new cards about the existing setup.

Quoted 1 line

Can a rescan be done while a card is in a selected state?

Yes - any cards not already in idle state will ignore the command as intended.

Signature · 4 lines
Russell King
 Linux kernel    2.6 ARM Linux   - http://www.arm.linux.org.uk/
 maintainer of:  2.6 PCMCIA      - http://pcmcia.arm.linux.org.uk/
                 2.6 Serial core