
Hi Lin,
On 3 December 2015 at 01:34, Lin Huang hl@rock-chips.com wrote:
set the mmc specific addresss and range as power on write protection, and can't earse and write this range if you enable it after mmc power on.
Signed-off-by: Lin Huang hl@rock-chips.com
drivers/mmc/mmc.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/mmc.h | 10 ++++++- 2 files changed, 98 insertions(+), 1 deletion(-)
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 2a58702..60ff5be 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -1819,6 +1819,95 @@ int mmc_initialize(bd_t *bis) return 0; }
+int mmc_get_wp_status(struct mmc *mmc, lbaint_t addr, char *status) +{
struct mmc_cmd cmd;
struct mmc_data data;
int err;
cmd.cmdidx = MMC_CMD_WRITE_PROT_TYPE;
cmd.resp_type = MMC_RSP_R1;
cmd.cmdarg = addr;
data.dest = status;
data.blocksize = 8;
data.blocks = 1;
data.flags = MMC_DATA_READ;
err = mmc_send_cmd(mmc, &cmd, &data);
if (err)
return err;
return err;
return 0 I think
Unless you just want to always return err.
+}
+int mmc_usr_power_on_wp(struct mmc *mmc, lbaint_t addr, unsigned int size) +{
int err;
unsigned int wp_group_size, wp_grp_num, i;
struct mmc_cmd cmd;
unsigned int timeout = 1000;
drop blank line
ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN);
size = size / MMC_MAX_BLOCK_LEN;
err = mmc_send_ext_csd(mmc, ext_csd);
if (err)
return err;
if ((ext_csd[EXT_CSD_USER_WP] & EXT_CSD_USER_PERM_WP_EN) ||
(ext_csd[EXT_CSD_USER_WP] & EXT_CSD_USER_PWR_WP_DIS)) {
printf("Power on protection is disabled\n");
return -1;
Can you run a real error in errno.h to return?
}
if (ext_csd[EXT_CSD_ERASE_GROUP_DEF])
wp_group_size = ext_csd[EXT_CSD_HC_WP_GRP_SIZE] *
ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] * 1024;
else {
int erase_gsz, erase_gmul, wp_grp_size;
erase_gsz = (mmc->csd[2] & 0x00007c00) >> 10;
erase_gmul = (mmc->csd[2] & 0x000003e0) >> 5;
wp_grp_size = (mmc->csd[2] & 0x0000001f);
wp_group_size = (erase_gsz + 1) * (erase_gmul + 1) *
(wp_grp_size + 1);
}
if (size < wp_group_size) {
printf("wrong size, fail to set power on wp\n");
return -1;
Can you run a real error in errno.h to return?
}
err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_USER_WP, EXT_CSD_USER_PWR_WP_EN);
if (err)
return err;
wp_grp_num = DIV_ROUND_UP(size, wp_group_size);
cmd.cmdidx = MMC_CMD_WRITE_PROT;
cmd.resp_type = MMC_RSP_R1b;
for (i = 0; i < wp_grp_num; i++) {
cmd.cmdarg = addr + i * wp_group_size;
err = mmc_send_cmd(mmc, &cmd, NULL);
if (err)
return err;
/* CMD28/CMD29 ON failure returns address out of range error */
if ((cmd.response[0] >> 31) & 0x01) {
printf("address for CMD28/29 out of range\n");
return -1;
-EINVAL?
}
err = mmc_send_status(mmc, timeout);
if (err)
return err;
}
return 0;
+}
#ifdef CONFIG_SUPPORT_EMMC_BOOT /*
- This function changes the size of boot partition and the size of rpmb
diff --git a/include/mmc.h b/include/mmc.h index cda9a19..448d5a8 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -89,6 +89,8 @@ #define MMC_CMD_SET_BLOCK_COUNT 23 #define MMC_CMD_WRITE_SINGLE_BLOCK 24 #define MMC_CMD_WRITE_MULTIPLE_BLOCK 25 +#define MMC_CMD_WRITE_PROT 28 +#define MMC_CMD_WRITE_PROT_TYPE 31 #define MMC_CMD_ERASE_GROUP_START 35 #define MMC_CMD_ERASE_GROUP_END 36 #define MMC_CMD_ERASE 38 @@ -175,6 +177,7 @@ #define EXT_CSD_WR_REL_PARAM 166 /* R */ #define EXT_CSD_WR_REL_SET 167 /* R/W */ #define EXT_CSD_RPMB_MULT 168 /* RO */ +#define EXT_CSD_USER_WP 171 #define EXT_CSD_ERASE_GROUP_DEF 175 /* R/W */ #define EXT_CSD_BOOT_BUS_WIDTH 177 #define EXT_CSD_PART_CONF 179 /* R/W */ @@ -231,6 +234,10 @@ #define EXT_CSD_WR_DATA_REL_USR (1 << 0) /* user data area WR_REL */ #define EXT_CSD_WR_DATA_REL_GP(x) (1 << ((x)+1)) /* GP part (x+1) WR_REL */
+#define EXT_CSD_USER_PWR_WP_DIS (1 << 3) /* disable power-on write protect*/ +#define EXT_CSD_USER_PERM_WP_EN (1 << 2) /* enable permanent write protect */ +#define EXT_CSD_USER_PWR_WP_EN (1 << 0) /* enable power-on write protect */
#define R1_ILLEGAL_COMMAND (1 << 22) #define R1_APP_CMD (1 << 5)
@@ -477,7 +484,8 @@ int cpu_mmc_init(bd_t *bis); int mmc_get_env_addr(struct mmc *mmc, int copy, u32 *env_addr);
struct pci_device_id;
+int mmc_usr_power_on_wp(struct mmc *mmc, lbaint_t addr, unsigned int size); +int mmc_get_wp_status(struct mmc *mmc, lbaint_t addr, char *status);
Can you please add full function comments for these?
/**
- pci_mmc_init() - set up PCI MMC devices
-- 1.9.1
Regards, Simon