diff mbox series

[6/6] mmc_spi: generate R1b response for erase and stop transmission command

Message ID 20200629094730.10051-7-pragnesh.patel@sifive.com
State Accepted
Commit ed4a11cb7d19a26dd0625bc468ef930c035a71b2
Headers show
Series mmc_spi: mmc erase resolve | expand

Commit Message

Pragnesh Patel June 29, 2020, 9:47 a.m. UTC
As per the SD physical layer specification version 7.10, erase
command (CMD38) and stop transmission command (CMD12) will generate
R1b response.

R1b = R1 + busy signal

A non-zero value after the R1 response indicates card is ready for
next command.

Signed-off-by: Pragnesh Patel <pragnesh.patel at sifive.com>
---
 drivers/mmc/mmc_spi.c | 32 ++++++++++++++++++++++++++++----
 1 file changed, 28 insertions(+), 4 deletions(-)
diff mbox series

Patch

diff --git a/drivers/mmc/mmc_spi.c b/drivers/mmc/mmc_spi.c
index 96a41076dc..50fcd32674 100644
--- a/drivers/mmc/mmc_spi.c
+++ b/drivers/mmc/mmc_spi.c
@@ -59,6 +59,7 @@ 
 #define CMD_TIMEOUT			8
 #define READ_TIMEOUT			3000000 /* 1 sec */
 #define WRITE_TIMEOUT			3000000 /* 1 sec */
+#define R1B_TIMEOUT			3000000 /* 1 sec */
 
 struct mmc_spi_plat {
 	struct mmc_config cfg;
@@ -72,7 +73,7 @@  struct mmc_spi_priv {
 static int mmc_spi_sendcmd(struct udevice *dev,
 			   ushort cmdidx, u32 cmdarg, u32 resp_type,
 			   u8 *resp, u32 resp_size,
-			   bool resp_match, u8 resp_match_value)
+			   bool resp_match, u8 resp_match_value, bool r1b)
 {
 	int i, rpos = 0, ret = 0;
 	u8 cmdo[7], r;
@@ -133,6 +134,24 @@  static int mmc_spi_sendcmd(struct udevice *dev,
 		resp[i] = r;
 	}
 
+	if (r1b == true) {
+		i = R1B_TIMEOUT;
+		while (i) {
+			ret = dm_spi_xfer(dev, 1 * 8, NULL, &r, 0);
+			if (ret)
+				return ret;
+
+			debug(" resp%d=0x%x", rpos, r);
+			rpos++;
+			i--;
+
+			if (r)
+				break;
+		}
+		if (!i)
+			return -ETIMEDOUT;
+	}
+
 	debug("\n");
 
 	return 0;
@@ -265,7 +284,7 @@  static int dm_mmc_spi_request(struct udevice *dev, struct mmc_cmd *cmd,
 	int i, multi, ret = 0;
 	u8 *resp = NULL;
 	u32 resp_size = 0;
-	bool resp_match = false;
+	bool resp_match = false, r1b = false;
 	u8 resp8 = 0, resp16[2] = { 0 }, resp40[5] = { 0 }, resp_match_value = 0;
 
 	dm_spi_claim_bus(dev);
@@ -296,12 +315,17 @@  static int dm_mmc_spi_request(struct udevice *dev, struct mmc_cmd *cmd,
 		break;
 	case MMC_CMD_SET_BLOCKLEN:
 	case MMC_CMD_SPI_CRC_ON_OFF:
-	case MMC_CMD_STOP_TRANSMISSION:
 		resp = &resp8;
 		resp_size = sizeof(resp8);
 		resp_match = true;
 		resp_match_value = 0x0;
 		break;
+	case MMC_CMD_STOP_TRANSMISSION:
+	case MMC_CMD_ERASE:
+		resp = &resp8;
+		resp_size = sizeof(resp8);
+		r1b = true;
+		break;
 	case MMC_CMD_SEND_CSD:
 	case MMC_CMD_SEND_CID:
 	case MMC_CMD_READ_SINGLE_BLOCK:
@@ -323,7 +347,7 @@  static int dm_mmc_spi_request(struct udevice *dev, struct mmc_cmd *cmd,
 	};
 
 	ret = mmc_spi_sendcmd(dev, cmd->cmdidx, cmd->cmdarg, cmd->resp_type,
-			      resp, resp_size, resp_match, resp_match_value);
+			      resp, resp_size, resp_match, resp_match_value, r1b);
 	if (ret)
 		goto done;