Skip to contentSkip to conversation

mmc: export enhanced area info to user

PATCH In review Chuanxiao Dong 2 participants 3 messages Dec 8, 2010 – Jan 11, 2011 MMC, SD and SDIO

lore
Share & tools
lore
#0 lore raw

PATCH v2 1/1 mmc: export enhanced area info to user

enhanced area is a new feature of eMMC4.41 card. Since the offsize and size of enhaneced area is one time programmable register, driver will not set them and just read these values out.

So this patch just let host driver read out the enhanced area offsize and size if the eMMC card is enabled this feature. And expose these values to user space through sys fs for use. The feature enabling should be done in manufactory.

Before read out these values, host driver also need set the ERASE_GROUP_DEF byte. If this setting this byte failed, driver will set the offsize and size to be 0. But not sure whether need to do this.

---
 drivers/mmc/core/mmc.c   |   92 ++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/mmc/card.h |    3 +
 include/linux/mmc/mmc.h  |    3 +
 3 files changed, 98 insertions(+), 0 deletions(-)
drivers/mmc/core/mmc.c +92 -0
index 77f93c3..1f49778 100644
@@ -302,6 +302,64 @@ static int mmc_read_ext_csd(struct mmc_card *card)
 	}
 
 	if (card->ext_csd.rev >= 4) {
+		/*
+		 * Enhanced area feature support
+		 * check whether eMMC card is enabled enhanced area,
+		 * if so, export enhanced area offset and size to
+		 * user by adding sysfs interface
+		 */
+		if ((ext_csd[EXT_CSD_PARTITION_SUPPORT] & 0x2) &&
+				(ext_csd[EXT_CSD_PARTITION_ATTRIBUTE] & 0x1)) {
+			u8 hc_erase_grp_sz =
+				ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE];
+			u8 hc_wp_grp_sz =
+				ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
+			 /*
+			  * FIXME
+			  * Not sure whether need to enable the
+			  * ERASE_GROUP_DEF bit
+			  */
+			err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+					EXT_CSD_ERASE_GROUP_DEF, 1);
+
+			if (err && err != -EBADMSG)
+				goto out;
+
+			if (err) {
+				/*
+				 * ignore this err, just disable enhanced area
+				 */
+				err = 0;
+				goto next;
+			}
+			/* update ext_csd ERASE_GRP_DEF bit */
+			ext_csd[EXT_CSD_ERASE_GROUP_DEF] = 1;
+			card->ext_csd.erase_group_def =
+				ext_csd[EXT_CSD_ERASE_GROUP_DEF];
+			/*
+			 * set a flag to identify whether the enhanced
+			 * user data are enabled
+			 */
+			card->ext_csd.enh_data_area_en = 1;
+			/*
+			 * caculate the enhanced data area offset, unit B
+			 */
+			card->ext_csd.enh_data_area_off =
+				(ext_csd[139] << 24) + (ext_csd[138] << 16) +
+				(ext_csd[137] << 8) + ext_csd[136];
+			if (mmc_card_blockaddr(card))
+				card->ext_csd.enh_data_area_off <<= 9;
+			/*
+			 * caculate the enhanced data area size, unit KB
+			 */
+			card->ext_csd.enh_data_area_sz =
+				(ext_csd[142] << 16) + (ext_csd[141] << 8) +
+				ext_csd[140];
+			card->ext_csd.enh_data_area_sz *=
+				(size_t)(hc_erase_grp_sz * hc_wp_grp_sz);
+			card->ext_csd.enh_data_area_sz <<= 9;
+		}
+next:
 		card->ext_csd.sec_trim_mult =
 			ext_csd[EXT_CSD_SEC_TRIM_MULT];
 		card->ext_csd.sec_erase_mult =
@@ -336,6 +394,9 @@ MMC_DEV_ATTR(manfid, "0x%06x\n", card->cid.manfid);
 MMC_DEV_ATTR(name, "%s\n", card->cid.prod_name);
 MMC_DEV_ATTR(oemid, "0x%04x\n", card->cid.oemid);
 MMC_DEV_ATTR(serial, "0x%08x\n", card->cid.serial);
+MMC_DEV_ATTR(enhen, "%d\n", card->ext_csd.enh_data_area_en);
+MMC_DEV_ATTR(enhoff, "0x%llxB\n", card->ext_csd.enh_data_area_off);
+MMC_DEV_ATTR(enhsz, "0x%xKB\n", card->ext_csd.enh_data_area_sz);
 
 static struct attribute *mmc_std_attrs[] = {
 	&dev_attr_cid.attr,
@@ -349,6 +410,9 @@ static struct attribute *mmc_std_attrs[] = {
 	&dev_attr_name.attr,
 	&dev_attr_oemid.attr,
 	&dev_attr_serial.attr,
+	&dev_attr_enhen.attr,
+	&dev_attr_enhoff.attr,
+	&dev_attr_enhsz.attr,
 	NULL,
 };
 
@@ -472,6 +536,34 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 			goto free_card;
 	}
 
+	/*
+	 * If enh_data_are_en is TRUE, means this init card
+	 * operation is used to reinit card after a reset
+	 * ERASE_GRP_DEF register value will be lost everytime
+	 * after a reset or power off.
+	 *
+	 * FIXME
+	 * Not sure whether need to enable ERASE_GRP_DEF bit.
+	 */
+	if (card->ext_csd.enh_data_area_en) {
+		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+				EXT_CSD_ERASE_GROUP_DEF, 1);
+
+		if (err && err != -EBADMSG)
+			goto free_card;
+
+		if (err) {
+			err = 0;
+			/*
+			 * Just disable enhanced area off & sz
+			 * will try to enable ERASE_GROUP_DEF
+			 * during next time reinit
+			 */
+			card->ext_csd.enh_data_area_off = 0;
+			card->ext_csd.enh_data_area_sz = 0;
+		}
+	}
+
 	if (!oldcard) {
 		/*
 		 * Fetch and process extended CSD.
include/linux/mmc/card.h +3 -0
index 8ce0827..e850a39 100644
@@ -54,6 +54,9 @@ struct mmc_ext_csd {
 	unsigned int		sec_trim_mult;	/* Secure trim multiplier  */
 	unsigned int		sec_erase_mult;	/* Secure erase multiplier */
 	unsigned int		trim_timeout;		/* In milliseconds */
+	unsigned int		enh_data_area_en; /* enh area enable bit */
+	loff_t				enh_data_area_off; /* enh area offset */
+	size_t				enh_data_area_sz; /* enh area size */
 };
 
 struct sd_scr {
include/linux/mmc/mmc.h +3 -0
index 956fbd8..97ca016 100644
@@ -251,6 +251,8 @@ struct _mmc_csd {
  * EXT_CSD fields
  */
 
+#define EXT_CSD_PARTITION_ATTRIBUTE 156	/* R/W */
+#define EXT_CSD_PARTITION_SUPPORT	160	/* RO */
 #define EXT_CSD_ERASE_GROUP_DEF		175	/* R/W */
 #define EXT_CSD_ERASED_MEM_CONT		181	/* RO */
 #define EXT_CSD_BUS_WIDTH		183	/* R/W */
@@ -260,6 +262,7 @@ struct _mmc_csd {
 #define EXT_CSD_CARD_TYPE		196	/* RO */
 #define EXT_CSD_SEC_CNT			212	/* RO, 4 bytes */
 #define EXT_CSD_S_A_TIMEOUT		217	/* RO */
+#define EXT_CSD_HC_WP_GRP_SIZE		221	/* RO */
 #define EXT_CSD_ERASE_TIMEOUT_MULT	223	/* RO */
 #define EXT_CSD_HC_ERASE_GRP_SIZE	224	/* RO */
 #define EXT_CSD_SEC_TRIM_MULT		229	/* RO */
Signature · 1 line
1.6.6.1
#1 lore raw

Hi Chuanxiao, sorry for the late review.

Quoted 9 lines · Chuanxiao Dong

enhanced area is a new feature of eMMC4.41 card. Since the offsize and size of enhaneced area is one time programmable register, driver will not set them and just read these values out.

So this patch just let host driver read out the enhanced area offsize and size if the eMMC card is enabled this feature. And expose these values to user space through sys fs for use. The feature enabling should be done in manufactory.

Quoted 5 lines

Before read out these values, host driver also need set the ERASE_GROUP_DEF byte. If this setting this byte failed, driver will set the offsize and size to be 0. But not sure whether need to do this.

Which userspace applications do you imagine will use this feature? If we're talking about a published interface, we should document this in Documentation/ABI. If this is just a tool to aid in debugging pre-production hardware or host controller drivers, it should live in debugfs instead.

Quoted 76 lines
---
 drivers/mmc/core/mmc.c   |   92 ++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/mmc/card.h |    3 +
 include/linux/mmc/mmc.h  |    3 +
 3 files changed, 98 insertions(+), 0 deletions(-)
drivers/mmc/core/mmc.c +58 -0
index 77f93c3..1f49778 100644
@@ -302,6 +302,64 @@ static int mmc_read_ext_csd(struct mmc_card *card)
 	}
 
 	if (card->ext_csd.rev >= 4) {
+		/*
+		 * Enhanced area feature support
+		 * check whether eMMC card is enabled enhanced area,
+		 * if so, export enhanced area offset and size to
+		 * user by adding sysfs interface
+		 */
+		if ((ext_csd[EXT_CSD_PARTITION_SUPPORT] & 0x2) &&
+				(ext_csd[EXT_CSD_PARTITION_ATTRIBUTE] & 0x1)) {
+			u8 hc_erase_grp_sz =
+				ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE];
+			u8 hc_wp_grp_sz =
+				ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
+			 /*
+			  * FIXME
+			  * Not sure whether need to enable the
+			  * ERASE_GROUP_DEF bit
+			  */
+			err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+					EXT_CSD_ERASE_GROUP_DEF, 1);
+
+			if (err && err != -EBADMSG)
+				goto out;
+
+			if (err) {
+				/*
+				 * ignore this err, just disable enhanced area
+				 */
+				err = 0;
+				goto next;
+			}
+			/* update ext_csd ERASE_GRP_DEF bit */
+			ext_csd[EXT_CSD_ERASE_GROUP_DEF] = 1;
+			card->ext_csd.erase_group_def =
+				ext_csd[EXT_CSD_ERASE_GROUP_DEF];
+			/*
+			 * set a flag to identify whether the enhanced
+			 * user data are enabled
+			 */
+			card->ext_csd.enh_data_area_en = 1;
+			/*
+			 * caculate the enhanced data area offset, unit B
+			 */
+			card->ext_csd.enh_data_area_off =
+				(ext_csd[139] << 24) + (ext_csd[138] << 16) +
+				(ext_csd[137] << 8) + ext_csd[136];
+			if (mmc_card_blockaddr(card))
+				card->ext_csd.enh_data_area_off <<= 9;
+			/*
+			 * caculate the enhanced data area size, unit KB
+			 */
+			card->ext_csd.enh_data_area_sz =
+				(ext_csd[142] << 16) + (ext_csd[141] << 8) +
+				ext_csd[140];
+			card->ext_csd.enh_data_area_sz *=
+				(size_t)(hc_erase_grp_sz * hc_wp_grp_sz);
+			card->ext_csd.enh_data_area_sz <<= 9;
+		}
+next:
 		card->ext_csd.sec_trim_mult =
 			ext_csd[EXT_CSD_SEC_TRIM_MULT];
 		card->ext_csd.sec_erase_mult =

drivers/mmc/core/mmc.c MMC_DEV_ATTR(manfid, "0x%06x\n", card->cid.manfid); · line 399

Quoted 6 lines
drivers/mmc/core/mmc.c +3 -0
@@ -336,6 +394,9 @@ MMC_DEV_ATTR(manfid, "0x%06x\n", card->cid.manfid);
 MMC_DEV_ATTR(name, "%s\n", card->cid.prod_name);
 MMC_DEV_ATTR(oemid, "0x%04x\n", card->cid.oemid);
 MMC_DEV_ATTR(serial, "0x%08x\n", card->cid.serial);
+MMC_DEV_ATTR(enhen, "%d\n", card->ext_csd.enh_data_area_en);
+MMC_DEV_ATTR(enhoff, "0x%llxB\n", card->ext_csd.enh_data_area_off);
+MMC_DEV_ATTR(enhsz, "0x%xKB\n", card->ext_csd.enh_data_area_sz);

If enhen == 0 and the user cats enhoff/enhsz, I think you should return something like -EINVAL instead of 0. (You could also instead consider making the appearance of enhoff and enhsz conditional on enhen == 1, and then just not export enhen to userspace at all?)

Regardless of where the files live, we should have much better names for them. It should be possible to work out what each file is for without already knowing! Perhaps enhanced_area_{enable,offset,size}, if that's not too long.

Quoted 16 lines
drivers/mmc/core/mmc.c +3 -0
 static struct attribute *mmc_std_attrs[] = {
 	&dev_attr_cid.attr,
@@ -349,6 +410,9 @@ static struct attribute *mmc_std_attrs[] = {
 	&dev_attr_name.attr,
 	&dev_attr_oemid.attr,
 	&dev_attr_serial.attr,
+	&dev_attr_enhen.attr,
+	&dev_attr_enhoff.attr,
+	&dev_attr_enhsz.attr,
 	NULL,
 };
 
@@ -472,6 +536,34 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 			goto free_card;
 	}

drivers/mmc/core/mmc.c static int mmc_init_card(struct mmc_host *host, u32 ocr, · line 547

Quoted 10 lines
drivers/mmc/core/mmc.c +9 -0
 
+	/*
+	 * If enh_data_are_en is TRUE, means this init card
+	 * operation is used to reinit card after a reset
+	 * ERASE_GRP_DEF register value will be lost everytime
+	 * after a reset or power off.
+	 *
+	 * FIXME
+	 * Not sure whether need to enable ERASE_GRP_DEF bit.
+	 */

Can we find out somehow?

Quoted 50 lines
drivers/mmc/core/mmc.c +19 -0
+	if (card->ext_csd.enh_data_area_en) {
+		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+				EXT_CSD_ERASE_GROUP_DEF, 1);
+
+		if (err && err != -EBADMSG)
+			goto free_card;
+
+		if (err) {
+			err = 0;
+			/*
+			 * Just disable enhanced area off & sz
+			 * will try to enable ERASE_GROUP_DEF
+			 * during next time reinit
+			 */
+			card->ext_csd.enh_data_area_off = 0;
+			card->ext_csd.enh_data_area_sz = 0;
+		}
+	}
+
 	if (!oldcard) {
 		/*
 		 * Fetch and process extended CSD.
include/linux/mmc/card.h +3 -0
index 8ce0827..e850a39 100644
@@ -54,6 +54,9 @@ struct mmc_ext_csd {
 	unsigned int		sec_trim_mult;	/* Secure trim multiplier  */
 	unsigned int		sec_erase_mult;	/* Secure erase multiplier */
 	unsigned int		trim_timeout;		/* In milliseconds */
+	unsigned int		enh_data_area_en; /* enh area enable bit */
+	loff_t				enh_data_area_off; /* enh area offset */
+	size_t				enh_data_area_sz; /* enh area size */
 };
 
 struct sd_scr {
include/linux/mmc/mmc.h +2 -0
index 956fbd8..97ca016 100644
@@ -251,6 +251,8 @@ struct _mmc_csd {
  * EXT_CSD fields
  */
 
+#define EXT_CSD_PARTITION_ATTRIBUTE 156	/* R/W */
+#define EXT_CSD_PARTITION_SUPPORT	160	/* RO */
 #define EXT_CSD_ERASE_GROUP_DEF		175	/* R/W */
 #define EXT_CSD_ERASED_MEM_CONT		181	/* RO */
 #define EXT_CSD_BUS_WIDTH		183	/* R/W */

include/linux/mmc/mmc.h struct _mmc_csd { · line 268

Quoted 7 lines
include/linux/mmc/mmc.h +1 -0
@@ -260,6 +262,7 @@ struct _mmc_csd {
 #define EXT_CSD_CARD_TYPE		196	/* RO */
 #define EXT_CSD_SEC_CNT			212	/* RO, 4 bytes */
 #define EXT_CSD_S_A_TIMEOUT		217	/* RO */
+#define EXT_CSD_HC_WP_GRP_SIZE		221	/* RO */
 #define EXT_CSD_ERASE_TIMEOUT_MULT	223	/* RO */
 #define EXT_CSD_HC_ERASE_GRP_SIZE	224	/* RO */
 #define EXT_CSD_SEC_TRIM_MULT		229	/* RO */

Thanks,

- Chris.

Signature · 2 lines
Chris Ball   <[email protected]>   <http://printf.net/>
One Laptop Per Child
#2 lore raw

Hi Chris,
Thanks for your comments. It is really helpful!

Quoted 24 lines

-----Original Message-----
From: [email protected] [mailto:[email protected]] On Behalf Of Chris Ball
Sent: Monday, January 10, 2011 8:03 AM
To: Dong, Chuanxiao
Cc: [email protected]; [email protected]; Mai, Leonard
Subject: Re: [PATCH v2 1/1]mmc: export enhanced area info to user

Hi Chuanxiao, sorry for the late review.

Quoted 13 lines · Chuanxiao Dong

enhanced area is a new feature of eMMC4.41 card. Since the offsize and size of enhaneced area is one time programmable register, driver will not set them and just read these values out.

So this patch just let host driver read out the enhanced area offsize and size if the eMMC card is enabled this feature. And expose these values to user space through sys fs for use. The feature enabling should be done in manufactory.

Before read out these values, host driver also need set the ERASE_GROUP_DEF byte. If this setting this byte failed, driver will set the offsize and size to be 0. But not sure whether need to do this.

Quoted 7 lines
Quoted 1 line

Which userspace applications do you imagine will use this feature? If we're talking about a published interface, we should document this in Documentation/ABI. If this is just a tool to aid in debugging pre-production hardware or host controller drivers, it should live in debugfs instead.

What we considered is that, if our eMMC card have some area been set to be an enhanced area, MMC driver can export the size and address of this area to user space so that user can use such area for a SWAP partition. Enhanced area has a good performance than the normal area. Chris, I will document this in Documentation/ABI, thanks a lot for making me clear.

Quoted 79 lines
Quoted 3 lines
---
 drivers/mmc/core/mmc.c   |   92

++++++++++++++++++++++++++++++++++++++++++++++

drivers/mmc/core/mmc.c MMC_DEV_ATTR(manfid, "0x%06x\n",

Quoted 74 lines
 include/linux/mmc/card.h |    3 +
 include/linux/mmc/mmc.h  |    3 +
 3 files changed, 98 insertions(+), 0 deletions(-)
drivers/mmc/core/mmc.c +58 -0
index 77f93c3..1f49778 100644
@@ -302,6 +302,64 @@ static int mmc_read_ext_csd(struct mmc_card *card)
 	}
 
 	if (card->ext_csd.rev >= 4) {
+		/*
+		 * Enhanced area feature support
+		 * check whether eMMC card is enabled enhanced area,
+		 * if so, export enhanced area offset and size to
+		 * user by adding sysfs interface
+		 */
+		if ((ext_csd[EXT_CSD_PARTITION_SUPPORT] & 0x2) &&
+				(ext_csd[EXT_CSD_PARTITION_ATTRIBUTE] & 0x1)) {
+			u8 hc_erase_grp_sz =
+				ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE];
+			u8 hc_wp_grp_sz =
+				ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
+			 /*
+			  * FIXME
+			  * Not sure whether need to enable the
+			  * ERASE_GROUP_DEF bit
+			  */
+			err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+					EXT_CSD_ERASE_GROUP_DEF, 1);
+
+			if (err && err != -EBADMSG)
+				goto out;
+
+			if (err) {
+				/*
+				 * ignore this err, just disable enhanced area
+				 */
+				err = 0;
+				goto next;
+			}
+			/* update ext_csd ERASE_GRP_DEF bit */
+			ext_csd[EXT_CSD_ERASE_GROUP_DEF] = 1;
+			card->ext_csd.erase_group_def =
+				ext_csd[EXT_CSD_ERASE_GROUP_DEF];
+			/*
+			 * set a flag to identify whether the enhanced
+			 * user data are enabled
+			 */
+			card->ext_csd.enh_data_area_en = 1;
+			/*
+			 * caculate the enhanced data area offset, unit B
+			 */
+			card->ext_csd.enh_data_area_off =
+				(ext_csd[139] << 24) + (ext_csd[138] << 16) +
+				(ext_csd[137] << 8) + ext_csd[136];
+			if (mmc_card_blockaddr(card))
+				card->ext_csd.enh_data_area_off <<= 9;
+			/*
+			 * caculate the enhanced data area size, unit KB
+			 */
+			card->ext_csd.enh_data_area_sz =
+				(ext_csd[142] << 16) + (ext_csd[141] << 8) +
+				ext_csd[140];
+			card->ext_csd.enh_data_area_sz *=
+				(size_t)(hc_erase_grp_sz * hc_wp_grp_sz);
+			card->ext_csd.enh_data_area_sz <<= 9;
+		}
+next:
 		card->ext_csd.sec_trim_mult =
 			ext_csd[EXT_CSD_SEC_TRIM_MULT];
 		card->ext_csd.sec_erase_mult =
@@ -336,6 +394,9 @@ MMC_DEV_ATTR(manfid, "0x%06x\n",

card->cid.manfid);

Quoted 11 lines

drivers/mmc/core/mmc.c MMC_DEV_ATTR(manfid, "0x%06x\n", card->cid.manfid); · line 399

Quoted 6 lines
drivers/mmc/core/mmc.c +3 -0
 MMC_DEV_ATTR(name, "%s\n", card->cid.prod_name);
 MMC_DEV_ATTR(oemid, "0x%04x\n", card->cid.oemid);
 MMC_DEV_ATTR(serial, "0x%08x\n", card->cid.serial);
+MMC_DEV_ATTR(enhen, "%d\n", card->ext_csd.enh_data_area_en);
+MMC_DEV_ATTR(enhoff, "0x%llxB\n", card->ext_csd.enh_data_area_off);
+MMC_DEV_ATTR(enhsz, "0x%xKB\n", card->ext_csd.enh_data_area_sz);

If enhen == 0 and the user cats enhoff/enhsz, I think you should return something like -EINVAL instead of 0. (You could also instead consider making the appearance of enhoff and enhsz conditional on enhen == 1, and then just not export enhen to userspace at all?)

I will use the second way which makes user much more clearly. :)

Quoted 5 lines

Regardless of where the files live, we should have much better names for them. It should be possible to work out what each file is for without already knowing! Perhaps enhanced_area_{enable,offset,size}, if that's not too long.

Sure, I will give a better name to them in the next submission.

Quoted 19 lines

drivers/mmc/core/mmc.c static int mmc_init_card(struct mmc_host *host, u32

Quoted 15 lines
drivers/mmc/core/mmc.c +3 -0
 static struct attribute *mmc_std_attrs[] = {
 	&dev_attr_cid.attr,
@@ -349,6 +410,9 @@ static struct attribute *mmc_std_attrs[] = {
 	&dev_attr_name.attr,
 	&dev_attr_oemid.attr,
 	&dev_attr_serial.attr,
+	&dev_attr_enhen.attr,
+	&dev_attr_enhoff.attr,
+	&dev_attr_enhsz.attr,
 	NULL,
 };
 
@@ -472,6 +536,34 @@ static int mmc_init_card(struct mmc_host *host, u32

ocr,

Quoted 3 lines
drivers/mmc/core/mmc.c +0 -0
 			goto free_card;
 	}
 
Quoted 11 lines

drivers/mmc/core/mmc.c static int mmc_init_card(struct mmc_host *host, u32 ocr, · line 547

Quoted 9 lines
drivers/mmc/core/mmc.c +9 -0
+	/*
+	 * If enh_data_are_en is TRUE, means this init card
+	 * operation is used to reinit card after a reset
+	 * ERASE_GRP_DEF register value will be lost everytime
+	 * after a reset or power off.
+	 *
+	 * FIXME
+	 * Not sure whether need to enable ERASE_GRP_DEF bit.
+	 */

Can we find out somehow?

Yes. ERASE_GRP_DEF bit needs to be set. Confirmed with our eMMC device vender.

Quoted 70 lines
Quoted 51 lines
drivers/mmc/core/mmc.c +19 -0
+	if (card->ext_csd.enh_data_area_en) {
+		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+				EXT_CSD_ERASE_GROUP_DEF, 1);
+
+		if (err && err != -EBADMSG)
+			goto free_card;
+
+		if (err) {
+			err = 0;
+			/*
+			 * Just disable enhanced area off & sz
+			 * will try to enable ERASE_GROUP_DEF
+			 * during next time reinit
+			 */
+			card->ext_csd.enh_data_area_off = 0;
+			card->ext_csd.enh_data_area_sz = 0;
+		}
+	}
+
 	if (!oldcard) {
 		/*
 		 * Fetch and process extended CSD.
include/linux/mmc/card.h +3 -0
index 8ce0827..e850a39 100644
@@ -54,6 +54,9 @@ struct mmc_ext_csd {
 	unsigned int		sec_trim_mult;	/* Secure trim multiplier  */
 	unsigned int		sec_erase_mult;	/* Secure erase multiplier */
 	unsigned int		trim_timeout;		/* In milliseconds */
+	unsigned int		enh_data_area_en; /* enh area enable bit */
+	loff_t				enh_data_area_off; /* enh area offset */
+	size_t				enh_data_area_sz; /* enh area size */
 };
 
 struct sd_scr {
include/linux/mmc/mmc.h +2 -0
index 956fbd8..97ca016 100644
@@ -251,6 +251,8 @@ struct _mmc_csd {
  * EXT_CSD fields
  */
 
+#define EXT_CSD_PARTITION_ATTRIBUTE 156	/* R/W */
+#define EXT_CSD_PARTITION_SUPPORT	160	/* RO */
 #define EXT_CSD_ERASE_GROUP_DEF		175	/* R/W */
 #define EXT_CSD_ERASED_MEM_CONT		181	/* RO */
 #define EXT_CSD_BUS_WIDTH		183	/* R/W */

include/linux/mmc/mmc.h struct _mmc_csd { · line 268

Quoted 7 lines
include/linux/mmc/mmc.h +1 -0
@@ -260,6 +262,7 @@ struct _mmc_csd {
 #define EXT_CSD_CARD_TYPE		196	/* RO */
 #define EXT_CSD_SEC_CNT			212	/* RO, 4 bytes */
 #define EXT_CSD_S_A_TIMEOUT		217	/* RO */
+#define EXT_CSD_HC_WP_GRP_SIZE		221	/* RO */
 #define EXT_CSD_ERASE_TIMEOUT_MULT	223	/* RO */
 #define EXT_CSD_HC_ERASE_GRP_SIZE	224	/* RO */
 #define EXT_CSD_SEC_TRIM_MULT		229	/* RO */

Thanks,

- Chris.
--
Chris Ball <[email protected]> <http://printf.net/>
One Laptop Per Child
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/