[Meego-kernel] [PATCH v1 1/1]mmc: implemented eMMC4.41 enhanced area feature

Chuanxiao Dong chuanxiao.dong at intel.com
Thu Dec 9 18:16:40 PST 2010


Hi,
This patch implemented eMMC4.41 enhanced area feature. It has been sent to
upstream, not accepted yet.

This patch just let host driver read out the enhanced area offs and
size if this feature is enabled. 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 offs and size
to be 0.

Signed-off-by: Chuanxiao Dong <chuanxiao.dong at intel.com>
---
 drivers/mmc/core/mmc.c   |   87 ++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/mmc/card.h |    3 ++
 include/linux/mmc/mmc.h  |    3 ++
 3 files changed, 93 insertions(+), 0 deletions(-)

diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 91c35fd..b7dc1d4 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -302,6 +302,62 @@ 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 offs 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];
+			 /*
+			  * enable the ERASE_GROUP_DEF byte
+			  */
+			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 offs, unit Byte
+			 */
+			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 +392,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 +408,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,
 };
 
@@ -469,6 +531,31 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 		mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
 	}
 
+	/*
+	 * 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.
+	 */
+	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 CSD from card.
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 8ce0827..e850a39 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -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 {
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
index 956fbd8..97ca016 100644
--- a/include/linux/mmc/mmc.h
+++ b/include/linux/mmc/mmc.h
@@ -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 */
-- 
1.6.6.1



More information about the MeeGo-kernel mailing list