[U-Boot] [PATCH 3/7 V4] mmc: Enhance erase handling procedure

Haijun Zhang haijun.zhang at freescale.com
Tue Dec 10 09:20:50 CET 2013


This patch enhances the currently implemented erase procedure in u-boot,
Not all cards support secure erase feature. We should make a difference
between them. For eMMC card that support erase group feature, check the
the command class first, then try to align the erase group size before
we actually sending the command.

Erase sequence after this patch:
1. check if erase command is supported by the card. If not just return.
2. Check the erase range to see if it is group aligned. For mmc card the
   minimum erase size should be one erase group. For SD card it is fixed
   to one block(512),
3. If not, aligned the erase rang according to the erase group size.
4. Send erase command to erase card once one erase group.
5. If it's a SD card, erase with arg 0x00000000 should be send.
   else if secure feature is supported, erase with arg 0x80000000
   (Spec eMMC 4.41).
   else erase with arg 0x00000000.(Trim and discard are ignored here)
6. Check card status after erase operation is completed.

Signed-off-by: Haijun Zhang <haijun.zhang at freescale.com>
---
changes for V4:
        - Update the commit message
changes for V3:
        - update the commit message and secure feature supporting judgment.

 drivers/mmc/mmc_write.c | 68 +++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 58 insertions(+), 10 deletions(-)

diff --git a/drivers/mmc/mmc_write.c b/drivers/mmc/mmc_write.c
index aa2fdef..c2dafa3 100644
--- a/drivers/mmc/mmc_write.c
+++ b/drivers/mmc/mmc_write.c
@@ -17,6 +17,10 @@ static ulong mmc_erase_t(struct mmc *mmc, ulong start, lbaint_t blkcnt)
 	struct mmc_cmd cmd;
 	ulong end;
 	int err, start_cmd, end_cmd;
+	uint arg = 0;
+
+	if (!(mmc->cmdclass & CCC_ERASE))
+		return NOT_SUPPORT;
 
 	if (mmc->high_capacity) {
 		end = start + blkcnt - 1;
@@ -48,8 +52,15 @@ static ulong mmc_erase_t(struct mmc *mmc, ulong start, lbaint_t blkcnt)
 	if (err)
 		goto err_out;
 
+	/* SD card only support %MMC_ERASE_ARG */
+	if (!IS_SD(mmc) &&
+		(mmc->sec_feature_support & EXT_CSD_SEC_ER_EN))
+		arg = MMC_SECURE_ERASE_ARG;
+	else
+		arg = MMC_ERASE_ARG;
+
 	cmd.cmdidx = MMC_CMD_ERASE;
-	cmd.cmdarg = SECURE_ERASE;
+	cmd.cmdarg = arg;
 	cmd.resp_type = MMC_RSP_R1b;
 
 	err = mmc_send_cmd(mmc, &cmd, NULL);
@@ -69,24 +80,61 @@ unsigned long mmc_berase(int dev_num, lbaint_t start, lbaint_t blkcnt)
 	struct mmc *mmc = find_mmc_device(dev_num);
 	lbaint_t blk = 0, blk_r = 0;
 	int timeout = 1000;
+	int res;
+	bool align = true;
 
 	if (!mmc)
 		return -1;
 
+	if (!(mmc->cmdclass & CCC_ERASE)) {
+		printf("\nErase operation is not support by card\n");
+		return NOT_SUPPORT;
+	}
+
 	if ((start % mmc->erase_grp_size) || (blkcnt % mmc->erase_grp_size))
+		align = false;
+
+	res = start % mmc->erase_grp_size;
+	if (res) {
+		res = mmc->erase_grp_size - res;
+		start += res;
+		if (blkcnt > res)
+			blkcnt -= res;
+		else {
+			printf("\nErase size smaller than Erase group "
+				"size [0x%x] is not support by the device.\n",
+				mmc->erase_grp_size);
+			return NOT_SUPPORT;
+		}
+	}
+
+	res = blkcnt % mmc->erase_grp_size;
+	if (res)
+		blkcnt -= res;
+
+	if (!blkcnt) {
+		printf("\nErase size smaller than Erase group size [0x%x] "
+			"is not support by the device.\n",
+			mmc->erase_grp_size);
+		return NOT_SUPPORT;
+	}
+
+	if (!align)
 		printf("\n\nCaution! Your devices Erase group is 0x%x\n"
-		       "The erase range would be change to "
-		       "0x" LBAF "~0x" LBAF "\n\n",
-		       mmc->erase_grp_size, start & ~(mmc->erase_grp_size - 1),
-		       ((start + blkcnt + mmc->erase_grp_size)
-		       & ~(mmc->erase_grp_size - 1)) - 1);
+			"The erase range would be change to "
+			"0x" LBAF "~0x" LBAF "\n\n",
+			mmc->erase_grp_size, start, start + blkcnt);
+
 
 	while (blk < blkcnt) {
-		blk_r = ((blkcnt - blk) > mmc->erase_grp_size) ?
-			mmc->erase_grp_size : (blkcnt - blk);
+		if ((blkcnt - blk) >= mmc->erase_grp_size)
+			blk_r = mmc->erase_grp_size;
 		err = mmc_erase_t(mmc, start + blk, blk_r);
-		if (err)
-			break;
+		if (err) {
+			printf("\nErase range from 0x" LBAF "~0x" LBAF
+				" Failed\n", start + blk, blkcnt);
+			return COMM_ERR;
+		}
 
 		blk += blk_r;
 
-- 
1.8.4.1




More information about the U-Boot mailing list