Message ID | 1449131661-9139-1-git-send-email-hl@rock-chips.com |
---|---|
State | Changes Requested |
Delegated to: | Simon Glass |
Headers | show |
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
Hi Simon, Thanks for reviewing, i have upload a new patch to fix your comment. On 11/12/15 11:20, Simon Glass wrote: > 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 > > >
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; +} + +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; + + 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; + } + + 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; + } + + 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; + } + + 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); /** * pci_mmc_init() - set up PCI MMC devices *
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(-)