mmc: checking status after commands with R1b response

It is recommended to check card status after these kind of commands.
This is done using CMD13 (SEND_STATUS) JEDEC command until
the card is ready.
In case of error the card status field is displayed.

Signed-off-by: Raffaele Recalcati <raffaele.recalcati@bticino.it>
Signed-off-by: Andy Fleming <afleming@freescale.com>
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 41c28d4..3d445c0 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -52,6 +52,42 @@
 	return mmc->send_cmd(mmc, cmd, data);
 }
 
+int mmc_send_status(struct mmc *mmc, int timeout)
+{
+	struct mmc_cmd cmd;
+	int err;
+#ifdef CONFIG_MMC_TRACE
+	int status;
+#endif
+
+	cmd.cmdidx = MMC_CMD_SEND_STATUS;
+	cmd.resp_type = MMC_RSP_R1;
+	cmd.cmdarg = 0;
+	cmd.flags = 0;
+
+	do {
+		err = mmc_send_cmd(mmc, &cmd, NULL);
+		if (err)
+			return err;
+		else if (cmd.response[0] & MMC_STATUS_RDY_FOR_DATA)
+			break;
+
+		udelay(1000);
+
+		if (cmd.response[0] & MMC_STATUS_MASK) {
+			printf("Status Error: 0x%08X\n", cmd.response[0]);
+			return COMM_ERR;
+		}
+	} while (timeout--);
+
+	if (!timeout) {
+		printf("Timeout waiting card ready\n");
+		return TIMEOUT;
+	}
+
+	return 0;
+}
+
 int mmc_set_blocklen(struct mmc *mmc, int len)
 {
 	struct mmc_cmd cmd;
@@ -86,6 +122,7 @@
 {
 	struct mmc_cmd cmd;
 	struct mmc_data data;
+	int timeout = 1000;
 
 	if ((start + blkcnt) > mmc->block_dev.lba) {
 		printf("MMC: block number 0x%lx exceeds max(0x%lx)\n",
@@ -128,6 +165,9 @@
 			printf("mmc fail to send stop cmd\n");
 			return 0;
 		}
+
+		/* Waiting for the ready status */
+		mmc_send_status(mmc, timeout);
 	}
 
 	return blkcnt;
@@ -162,6 +202,7 @@
 {
 	struct mmc_cmd cmd;
 	struct mmc_data data;
+	int timeout = 1000;
 
 	if (blkcnt > 1)
 		cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK;
@@ -193,6 +234,9 @@
 			printf("mmc fail to send stop cmd\n");
 			return 0;
 		}
+
+		/* Waiting for the ready status */
+		mmc_send_status(mmc, timeout);
 	}
 
 	return blkcnt;
@@ -396,15 +440,23 @@
 int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value)
 {
 	struct mmc_cmd cmd;
+	int timeout = 1000;
+	int ret;
 
 	cmd.cmdidx = MMC_CMD_SWITCH;
 	cmd.resp_type = MMC_RSP_R1b;
 	cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
-		(index << 16) |
-		(value << 8);
+				 (index << 16) |
+				 (value << 8);
 	cmd.flags = 0;
 
-	return mmc_send_cmd(mmc, &cmd, NULL);
+	ret = mmc_send_cmd(mmc, &cmd, NULL);
+
+	/* Waiting for the ready status */
+	mmc_send_status(mmc, timeout);
+
+	return ret;
+
 }
 
 int mmc_change_freq(struct mmc *mmc)
@@ -643,6 +695,7 @@
 	u64 cmult, csize;
 	struct mmc_cmd cmd;
 	char ext_csd[512];
+	int timeout = 1000;
 
 #ifdef CONFIG_MMC_SPI_CRC_ON
 	if (mmc_host_is_spi(mmc)) { /* enable CRC check for spi */
@@ -699,6 +752,9 @@
 
 	err = mmc_send_cmd(mmc, &cmd, NULL);
 
+	/* Waiting for the ready status */
+	mmc_send_status(mmc, timeout);
+
 	if (err)
 		return err;