[PATCH] Fix emmc error state after mmc write timeout
Jimmy Durand Wesolowski
jimmy.wesolowski at mobileye.com
Mon Jul 21 14:35:00 CEST 2025
From: Iulian Banaga <iulianeugen.banaga at mobileye.com>
This is a fix for the sporadic mmc write failure:
mmc write failed
0 blocks written: ERROR
After this happens the emmc will remain in an error state
where subsequent read/writes fail with a timeout.
The mmc driver sends CMD25 - WRITE_MULTIPLE_BLOCK which
can sporadically timeout. When this happens, the mmc driver
aborts the transfer and returns the above error messages.
But the emmc still remains in data transfer mode, since
the timeout was decided by uboot, not by the emmc.
Fix this by sending the STOP_TRANSMISSION command (CMD12)
and waiting for the emmc to be in ready state again (CMD13).
Transferring data blocks after a CMD25 can take anywhere
between 5 and +15s on Samsung EMMCs and the current timeout
is not enough. Increase the timeout by 2x to accommodate the
long transfer times observed.
Signed-off-by: Iulian Banaga <iulianeugen.banaga at mobileye.com>
Acked-by: Jimmy Durand Wesolowski <jimmy.wesolowski at mobileye.com>
---
drivers/mmc/mmc_write.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/mmc/mmc_write.c b/drivers/mmc/mmc_write.c
index 90fcf2679bb..37a42887cab 100644
--- a/drivers/mmc/mmc_write.c
+++ b/drivers/mmc/mmc_write.c
@@ -155,6 +155,7 @@ static ulong mmc_write_blocks(struct mmc *mmc, lbaint_t start,
struct mmc_cmd cmd;
struct mmc_data data;
int timeout_ms = 1000;
+ int err;
if ((start + blkcnt) > mmc_get_blk_desc(mmc)->lba) {
printf("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n",
@@ -181,9 +182,11 @@ static ulong mmc_write_blocks(struct mmc *mmc, lbaint_t start,
data.blocksize = mmc->write_bl_len;
data.flags = MMC_DATA_WRITE;
- if (mmc_send_cmd(mmc, &cmd, &data)) {
+ err = mmc_send_cmd(mmc, &cmd, &data);
+ if (err) {
printf("mmc write failed\n");
- return 0;
+ // do not return 0 here since the emmc will still be in data
+ // transfer mode continue to send the STOP_TRANSMISSION command
}
/* SPI multiblock writes terminate using a special
@@ -203,6 +206,9 @@ static ulong mmc_write_blocks(struct mmc *mmc, lbaint_t start,
if (mmc_poll_for_busy(mmc, timeout_ms))
return 0;
+ if (err)
+ return 0;
+
return blkcnt;
}
--
2.47.0
base-commit: 3b4604a40b9fd61b87e9d059fc56f04d36f1a380
branch: master
More information about the U-Boot
mailing list