From patchwork Mon Jun 29 09:47:24 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pragnesh Patel X-Patchwork-Id: 243071 List-Id: U-Boot discussion From: pragnesh.patel at sifive.com (Pragnesh Patel) Date: Mon, 29 Jun 2020 15:17:24 +0530 Subject: [PATCH 1/6] mmc: mmc_spi: correct the while condition In-Reply-To: <20200629094730.10051-1-pragnesh.patel@sifive.com> References: <20200629094730.10051-1-pragnesh.patel@sifive.com> Message-ID: <20200629094730.10051-2-pragnesh.patel@sifive.com> When variable i will become 0, while(i--) loop breaks but variable i will again decrement to -1 because of i-- and that's why below condition "if (!i && (r != resp_match_value)" will never execute, So doing "i--" inside of while() loop solves this problem. Signed-off-by: Pragnesh Patel Reviewed-by: Bin Meng --- drivers/mmc/mmc_spi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/mmc_spi.c b/drivers/mmc/mmc_spi.c index e76ab54838..86cc932151 100644 --- a/drivers/mmc/mmc_spi.c +++ b/drivers/mmc/mmc_spi.c @@ -105,12 +105,14 @@ static int mmc_spi_sendcmd(struct udevice *dev, if (resp_match) { r = ~resp_match_value; i = CMD_TIMEOUT; - while (i--) { + 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 == resp_match_value) break; } From patchwork Mon Jun 29 09:47:25 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pragnesh Patel X-Patchwork-Id: 243074 List-Id: U-Boot discussion From: pragnesh.patel at sifive.com (Pragnesh Patel) Date: Mon, 29 Jun 2020 15:17:25 +0530 Subject: [PATCH 2/6] mmc: mmc_spi: generate R1 response for different mmc SPI commands In-Reply-To: <20200629094730.10051-1-pragnesh.patel@sifive.com> References: <20200629094730.10051-1-pragnesh.patel@sifive.com> Message-ID: <20200629094730.10051-3-pragnesh.patel@sifive.com> R1 response is 1 byte long for mmc SPI commands as per the updated physical layer specification version 7.10. So correct the resp and resp_size for existing commands Signed-off-by: Pragnesh Patel --- drivers/mmc/mmc_spi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mmc/mmc_spi.c b/drivers/mmc/mmc_spi.c index 86cc932151..ddfebb6ed6 100644 --- a/drivers/mmc/mmc_spi.c +++ b/drivers/mmc/mmc_spi.c @@ -305,6 +305,8 @@ static int dm_mmc_spi_request(struct udevice *dev, struct mmc_cmd *cmd, case MMC_CMD_READ_MULTIPLE_BLOCK: case MMC_CMD_WRITE_SINGLE_BLOCK: case MMC_CMD_WRITE_MULTIPLE_BLOCK: + resp = &resp8; + resp_size = sizeof(resp8); break; default: resp = &resp8; From patchwork Mon Jun 29 09:47:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pragnesh Patel X-Patchwork-Id: 243073 List-Id: U-Boot discussion From: pragnesh.patel at sifive.com (Pragnesh Patel) Date: Mon, 29 Jun 2020 15:17:26 +0530 Subject: [PATCH 3/6] mmc: read ssr for SD spi In-Reply-To: <20200629094730.10051-1-pragnesh.patel@sifive.com> References: <20200629094730.10051-1-pragnesh.patel@sifive.com> Message-ID: <20200629094730.10051-4-pragnesh.patel@sifive.com> The content of ssr is useful only for erase operations. This saves erase time. Signed-off-by: Pragnesh Patel Reviewed-by: Bin Meng --- drivers/mmc/mmc.c | 5 +++++ drivers/mmc/mmc_spi.c | 1 + 2 files changed, 6 insertions(+) diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 620bb93064..6b193d6d70 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -1746,6 +1746,11 @@ static int sd_select_mode_and_width(struct mmc *mmc, uint card_caps) mmc_set_bus_width(mmc, 1); mmc_select_mode(mmc, MMC_LEGACY); mmc_set_clock(mmc, mmc->tran_speed, MMC_CLK_ENABLE); +#if CONFIG_IS_ENABLED(MMC_WRITE) + err = sd_read_ssr(mmc); + if (err) + pr_warn("unable to read ssr\n"); +#endif return 0; } diff --git a/drivers/mmc/mmc_spi.c b/drivers/mmc/mmc_spi.c index ddfebb6ed6..18d36878ef 100644 --- a/drivers/mmc/mmc_spi.c +++ b/drivers/mmc/mmc_spi.c @@ -305,6 +305,7 @@ static int dm_mmc_spi_request(struct udevice *dev, struct mmc_cmd *cmd, case MMC_CMD_READ_MULTIPLE_BLOCK: case MMC_CMD_WRITE_SINGLE_BLOCK: case MMC_CMD_WRITE_MULTIPLE_BLOCK: + case MMC_CMD_APP_CMD: resp = &resp8; resp_size = sizeof(resp8); break; From patchwork Mon Jun 29 09:47:27 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pragnesh Patel X-Patchwork-Id: 243075 List-Id: U-Boot discussion From: pragnesh.patel at sifive.com (Pragnesh Patel) Date: Mon, 29 Jun 2020 15:17:27 +0530 Subject: [PATCH 4/6] mmc: mmc_spi: Read R2 response for send status command - CMD13 In-Reply-To: <20200629094730.10051-1-pragnesh.patel@sifive.com> References: <20200629094730.10051-1-pragnesh.patel@sifive.com> Message-ID: <20200629094730.10051-5-pragnesh.patel@sifive.com> Send status command (CMD13) will send R1 response under SD mode but R2 response under SPI mode. R2 response is 2 bytes long, so read 2 bytes for mmc SPI mode Signed-off-by: Pragnesh Patel --- drivers/mmc/mmc_spi.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/mmc_spi.c b/drivers/mmc/mmc_spi.c index 18d36878ef..ee56de36ec 100644 --- a/drivers/mmc/mmc_spi.c +++ b/drivers/mmc/mmc_spi.c @@ -266,7 +266,7 @@ static int dm_mmc_spi_request(struct udevice *dev, struct mmc_cmd *cmd, u8 *resp = NULL; u32 resp_size = 0; bool resp_match = false; - u8 resp8 = 0, resp40[5] = { 0 }, resp_match_value = 0; + u8 resp8 = 0, resp16[2] = { 0 }, resp40[5] = { 0 }, resp_match_value = 0; dm_spi_claim_bus(dev); @@ -291,6 +291,9 @@ static int dm_mmc_spi_request(struct udevice *dev, struct mmc_cmd *cmd, resp_size = sizeof(resp40); break; case MMC_CMD_SEND_STATUS: + resp = (u8 *)&resp16[0]; + resp_size = sizeof(resp16); + break; case MMC_CMD_SET_BLOCKLEN: case MMC_CMD_SPI_CRC_ON_OFF: case MMC_CMD_STOP_TRANSMISSION: @@ -335,8 +338,10 @@ static int dm_mmc_spi_request(struct udevice *dev, struct mmc_cmd *cmd, cmd->response[0] |= (uint)resp40[1] << 24; break; case MMC_CMD_SEND_STATUS: - cmd->response[0] = (resp8 & 0xff) ? - MMC_STATUS_ERROR : MMC_STATUS_RDY_FOR_DATA; + if (resp16[0] || resp16[1]) + cmd->response[0] = MMC_STATUS_ERROR; + else + cmd->response[0] = MMC_STATUS_RDY_FOR_DATA; break; case MMC_CMD_SEND_CID: case MMC_CMD_SEND_CSD: From patchwork Mon Jun 29 09:47:28 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pragnesh Patel X-Patchwork-Id: 243072 List-Id: U-Boot discussion From: pragnesh.patel at sifive.com (Pragnesh Patel) Date: Mon, 29 Jun 2020 15:17:28 +0530 Subject: [PATCH 5/6] mmc: mmc_spi: Generate R1 response for erase block start and end address In-Reply-To: <20200629094730.10051-1-pragnesh.patel@sifive.com> References: <20200629094730.10051-1-pragnesh.patel@sifive.com> Message-ID: <20200629094730.10051-6-pragnesh.patel@sifive.com> Erase block start address (CMD32) and erase block end address (CMD33) command will generate R1 response for mmc SPI mode. R1 response is 1 byte long for mmc SPI, so assign 1 byte as a response for this commands. Signed-off-by: Pragnesh Patel --- drivers/mmc/mmc_spi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mmc/mmc_spi.c b/drivers/mmc/mmc_spi.c index ee56de36ec..96a41076dc 100644 --- a/drivers/mmc/mmc_spi.c +++ b/drivers/mmc/mmc_spi.c @@ -309,6 +309,8 @@ static int dm_mmc_spi_request(struct udevice *dev, struct mmc_cmd *cmd, case MMC_CMD_WRITE_SINGLE_BLOCK: case MMC_CMD_WRITE_MULTIPLE_BLOCK: case MMC_CMD_APP_CMD: + case SD_CMD_ERASE_WR_BLK_START: + case SD_CMD_ERASE_WR_BLK_END: resp = &resp8; resp_size = sizeof(resp8); break; From patchwork Mon Jun 29 09:47:29 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pragnesh Patel X-Patchwork-Id: 243076 List-Id: U-Boot discussion From: pragnesh.patel at sifive.com (Pragnesh Patel) Date: Mon, 29 Jun 2020 15:17:29 +0530 Subject: [PATCH 6/6] mmc_spi: generate R1b response for erase and stop transmission command In-Reply-To: <20200629094730.10051-1-pragnesh.patel@sifive.com> References: <20200629094730.10051-1-pragnesh.patel@sifive.com> Message-ID: <20200629094730.10051-7-pragnesh.patel@sifive.com> 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 --- drivers/mmc/mmc_spi.c | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) 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;