From: Iulian Banaga Date: Mon, 21 Jul 2025 12:35:00 +0000 (+0300) Subject: Fix emmc error state after mmc write timeout X-Git-Tag: v2025.10-rc1~20^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1080815650a00257929f645bedf4e1795bf188bf;p=thirdparty%2Fu-boot.git Fix emmc error state after mmc write timeout 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 Acked-by: Jimmy Durand Wesolowski Reviewed-by: Peng Fan Signed-off-by: Peng Fan --- diff --git a/drivers/mmc/mmc_write.c b/drivers/mmc/mmc_write.c index 90fcf2679bb..928c05872ca 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,13 @@ 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; + /* + * Don't 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 +208,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; }