[PATCH] mmc: Optimize eMMC erase speed

Peng Fan (OSS) peng.fan at oss.nxp.com
Mon Jan 20 05:30:09 CET 2025


From: Peng Fan <peng.fan at nxp.com>

Per JESD84-B51 6.6.9 Erase:
The host can erase a contiguous range of Erase Groups. Starting the erase
process is a three steps sequence. First the host defines the start address
of the range using the ERASE_GROUP_START (CMD35) command, next it defines
the last address of the range using the ERASE_GROUP_END (CMD36) command and
finally it starts the erase process by issuing the ERASE (CMD38) command
with argument bits set to zero. See Table 11 for the arguments supported by
CMD38.  The address field in the erase commands is an Erase Group address,
in byte units for densities up to 2GB, and in sector units for densities
greater than 2GB. The Device will ignore all LSB's below the Erase Group
size, effectively rounding the address down to the Erase Group boundary.

So choose 2GB bytes as check condition.

If the erase size is larger that 2GB, use 2GB to avoid breaking non high
capacity cards. If erase size is less than 2GB and larger than a grp, use
'grpcnt * mmc->erase_grp_size' to cover all the sectors, else use
the number of sectors.

With test erasing 20GB eMMC

board:  Evk_8ulp Evk_8mm   Evk_8mn             Evk_8mp   Mek_8qxpc0 Mek_8qm
			   kingston  sandisk
before: 37.683s   112.738s  129.365s  28.238s   112.605s  500.470s  490.708s
after:  0.093s    0.111s    0.951s    0.080s    0.121s    6.960s    6.915s

Tested-by: Faqiang Zhu <faqiang.zhu at nxp.com>
Signed-off-by: Peng Fan <peng.fan at nxp.com>
---
 drivers/mmc/mmc_write.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/mmc/mmc_write.c b/drivers/mmc/mmc_write.c
index c023d15e52a..90fcf2679bb 100644
--- a/drivers/mmc/mmc_write.c
+++ b/drivers/mmc/mmc_write.c
@@ -80,6 +80,8 @@ ulong mmc_berase(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt)
 	struct mmc *mmc = find_mmc_device(dev_num);
 	lbaint_t blk = 0, blk_r = 0;
 	int timeout_ms = 1000;
+	u32 grpcnt;
+
 
 	if (!mmc)
 		return -1;
@@ -123,6 +125,15 @@ ulong mmc_berase(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt)
 		} else {
 			blk_r = ((blkcnt - blk) > mmc->erase_grp_size) ?
 				mmc->erase_grp_size : (blkcnt - blk);
+
+			grpcnt = (blkcnt - blk) / mmc->erase_grp_size;
+			/* Max 2GB per spec */
+			if ((blkcnt - blk) > 0x400000)
+				blk_r = 0x400000;
+			else if (grpcnt)
+				blk_r = grpcnt * mmc->erase_grp_size;
+			else
+				blk_r = blkcnt - blk;
 		}
 		err = mmc_erase_t(mmc, start + blk, blk_r, erase_args);
 		if (err)
-- 
2.35.3



More information about the U-Boot mailing list