* [U-Boot] [PATCH] mmc: implement mmc power on write protect function
@ 2015-12-03 8:34 Lin Huang
2015-12-11 3:20 ` Simon Glass
0 siblings, 1 reply; 3+ messages in thread
From: Lin Huang @ 2015-12-03 8:34 UTC (permalink / raw)
To: u-boot
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;
+}
+
+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
*
--
1.9.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [U-Boot] [PATCH] mmc: implement mmc power on write protect function
2015-12-03 8:34 [U-Boot] [PATCH] mmc: implement mmc power on write protect function Lin Huang
@ 2015-12-11 3:20 ` Simon Glass
2015-12-14 2:16 ` hl
0 siblings, 1 reply; 3+ messages in thread
From: Simon Glass @ 2015-12-11 3:20 UTC (permalink / raw)
To: u-boot
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
^ permalink raw reply [flat|nested] 3+ messages in thread
* [U-Boot] [PATCH] mmc: implement mmc power on write protect function
2015-12-11 3:20 ` Simon Glass
@ 2015-12-14 2:16 ` hl
0 siblings, 0 replies; 3+ messages in thread
From: hl @ 2015-12-14 2:16 UTC (permalink / raw)
To: u-boot
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
>
>
>
--
Lin Huang
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2015-12-14 2:16 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-12-03 8:34 [U-Boot] [PATCH] mmc: implement mmc power on write protect function Lin Huang
2015-12-11 3:20 ` Simon Glass
2015-12-14 2:16 ` hl
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox