From cad4eba461bdfec394c85a1c5efae9ecf66ce3d9 Mon Sep 17 00:00:00 2001 From: Sham Muthayyan Date: Thu, 9 Mar 2017 19:52:24 +0530 Subject: [PATCH] mmc: eMMC add Secured Trim command support Secured Trim command does eMMC erase for unalligned block size. Change-Id: I4dc7bea15c8fcb57e07d19c398b1c8e2289da100 Signed-off-by: Sham Muthayyan --- drivers/mmc/mmc.c | 3 +++ drivers/mmc/mmc_write.c | 59 +++++++++++++++++++++++++++++++++-------- include/mmc.h | 8 ++++++ 3 files changed, 59 insertions(+), 11 deletions(-) diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 3a34028c91..d928c59d2d 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -1231,6 +1231,9 @@ static int mmc_startup(struct mmc *mmc) if ((ext_csd[EXT_CSD_PARTITIONING_SUPPORT] & PART_SUPPORT) || ext_csd[EXT_CSD_BOOT_MULT]) mmc->part_config = ext_csd[EXT_CSD_PART_CONF]; + + if(ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT]) + mmc->sec_feature_support = ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT]; if (part_completed && (ext_csd[EXT_CSD_PARTITIONING_SUPPORT] & ENHNCD_SUPPORT)) mmc->part_attr = ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE]; diff --git a/drivers/mmc/mmc_write.c b/drivers/mmc/mmc_write.c index 221bf306cc..28fad96fdd 100644 --- a/drivers/mmc/mmc_write.c +++ b/drivers/mmc/mmc_write.c @@ -14,7 +14,7 @@ #include #include "mmc_private.h" -static ulong mmc_erase_t(struct mmc *mmc, ulong start, lbaint_t blkcnt) +static ulong mmc_erase_t(struct mmc *mmc, ulong start, lbaint_t blkcnt, int arg) { struct mmc_cmd cmd; ulong end; @@ -51,7 +51,7 @@ static ulong mmc_erase_t(struct mmc *mmc, ulong start, lbaint_t blkcnt) goto err_out; cmd.cmdidx = MMC_CMD_ERASE; - cmd.cmdarg = MMC_ERASE_ARG; + cmd.cmdarg = arg; cmd.resp_type = MMC_RSP_R1b; err = mmc_send_cmd(mmc, &cmd, NULL); @@ -71,11 +71,15 @@ unsigned long mmc_berase(int dev_num, lbaint_t start, lbaint_t blkcnt) u32 start_rem, blkcnt_rem; struct mmc *mmc = find_mmc_device(dev_num); lbaint_t blk = 0, blk_r = 0; - int timeout = 1000; + int timeout = 2000; + int arg = MMC_ERASE_ARG; if (!mmc) return -1; + if (!(mmc->sec_feature_support & EXT_CSD_SEC_ER_EN)) { + return -1; + } /* * We want to see if the requested start or total block count are * unaligned. We discard the whole numbers and only care about the @@ -83,26 +87,59 @@ unsigned long mmc_berase(int dev_num, lbaint_t start, lbaint_t blkcnt) */ err = div_u64_rem(start, mmc->erase_grp_size, &start_rem); err = div_u64_rem(blkcnt, mmc->erase_grp_size, &blkcnt_rem); - if (start_rem || blkcnt_rem) + if (start_rem || blkcnt_rem) { + if (mmc->sec_feature_support & EXT_CSD_SEC_GB_CL_EN) { + arg = MMC_SECURE_TRIM1_ARG; + } else { 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); + } + } + + if (arg != MMC_SECURE_TRIM1_ARG) { + while (blk < blkcnt) { + + blk_r = ((blkcnt - blk) > mmc->erase_grp_size) ? + mmc->erase_grp_size : (blkcnt - blk); + + err = mmc_erase_t(mmc, start + blk, blk_r, arg); + + if (err) + break; + + blk += blk_r; + + /* Waiting for the ready status */ + if (mmc_send_status(mmc, timeout)) + return 0; + } + + return blk; + } else { + err = mmc_erase_t(mmc, start, blkcnt, arg); - while (blk < blkcnt) { - blk_r = ((blkcnt - blk) > mmc->erase_grp_size) ? - mmc->erase_grp_size : (blkcnt - blk); - err = mmc_erase_t(mmc, start + blk, blk_r); if (err) - break; - - blk += blk_r; + return -1; /* Waiting for the ready status */ if (mmc_send_status(mmc, timeout)) + return -1; + + arg = MMC_SECURE_TRIM2_ARG; + err = mmc_erase_t(mmc, start, blkcnt, arg); + + if (err) + return -1; + + /* Waiting for the ready status */ + if (mmc_send_status(mmc, timeout)) { return 0; + } + return blkcnt; } return blk; diff --git a/include/mmc.h b/include/mmc.h index b89962a562..00d87063a3 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -191,7 +191,10 @@ #define EXT_CSD_HC_WP_GRP_SIZE 221 /* RO */ #define EXT_CSD_HC_ERASE_GRP_SIZE 224 /* RO */ #define EXT_CSD_BOOT_MULT 226 /* RO */ +#define EXT_CSD_SEC_FEATURE_SUPPORT 231 /* RO */ +#define EXT_CSD_SEC_ER_EN (1 << 0) +#define EXT_CSD_SEC_GB_CL_EN (1 << 4) /* * EXT_CSD field definitions */ @@ -293,6 +296,10 @@ struct mmc *mmc_get_mmc_dev(struct udevice *dev); /* End of driver model support */ +#define MMC_SECURE_TRIM1_ARG 0x80000001 +#define MMC_SECURE_TRIM2_ARG 0x80008000 + + struct mmc_cid { unsigned long psn; unsigned short oid; @@ -382,6 +389,7 @@ struct mmc { char init_in_progress; /* 1 if we have done mmc_start_init() */ char preinit; /* start init as early as possible */ int ddr_mode; + uchar sec_feature_support; }; struct mmc_hwpart_conf {