Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 709de99d authored by Chuanxiao Dong's avatar Chuanxiao Dong Committed by Chris Ball
Browse files

mmc: export eMMC4.4 enhanced area details to sysfs



Enhanced area feature is a new feature defined in eMMC4.4 standard. This
user data area provides higher performance/reliability, at the expense
of using twice the effective media space due to the area using SLC.

The MMC driver now reads out the enhanced area offset and size and adds
them to the device attributes in sysfs. Enabling the enhanced area can
only be done once, and should be done in manufacturing. To use this
feature, bit ERASE_GRP_DEF should also be set.

Documentation/ABI/testing/sysfs-devices-mmc describes the two new
attributes.

Signed-off-by: default avatarChuanxiao Dong <chuanxiao.dong@intel.com>
Reviewed-by: default avatarChris Ball <cjb@laptop.org>
Signed-off-by: default avatarChris Ball <cjb@laptop.org>
parent cfd80652
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
What:		/sys/devices/.../mmc_host/mmcX/mmcX:XXXX/enhanced_area_offset
Date:		January 2011
Contact:	Chuanxiao Dong <chuanxiao.dong@intel.com>
Description:
		Enhanced area is a new feature defined in eMMC4.4 standard.
		eMMC4.4 or later card can support such feature. This kind of
		area can help to improve the card performance. If the feature
		is enabled, this attribute will indicate the start address of
		enhanced data area. If not, this attribute will be -EINVAL.
		Unit Byte. Format decimal.

What:		/sys/devices/.../mmc_host/mmcX/mmcX:XXXX/enhanced_area_size
Date:		January 2011
Contact:	Chuanxiao Dong <chuanxiao.dong@intel.com>
Description:
		Enhanced area is a new feature defined in eMMC4.4 standard.
		eMMC4.4 or later card can support such feature. This kind of
		area can help to improve the card performance. If the feature
		is enabled, this attribute will indicate the size of enhanced
		data area. If not, this attribute will be -EINVAL.
		Unit KByte. Format decimal.
+74 −0
Original line number Diff line number Diff line
@@ -302,6 +302,44 @@ static int mmc_read_ext_csd(struct mmc_card *card)
	}

	if (card->ext_csd.rev >= 4) {
		/*
		 * Enhanced area feature support -- check whether the eMMC
		 * card has the Enhanced area enabled.  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];

			card->ext_csd.enhanced_area_en = 1;
			/*
			 * calculate the enhanced data area offset, in bytes
			 */
			card->ext_csd.enhanced_area_offset =
				(ext_csd[139] << 24) + (ext_csd[138] << 16) +
				(ext_csd[137] << 8) + ext_csd[136];
			if (mmc_card_blockaddr(card))
				card->ext_csd.enhanced_area_offset <<= 9;
			/*
			 * calculate the enhanced data area size, in kilobytes
			 */
			card->ext_csd.enhanced_area_size =
				(ext_csd[142] << 16) + (ext_csd[141] << 8) +
				ext_csd[140];
			card->ext_csd.enhanced_area_size *=
				(size_t)(hc_erase_grp_sz * hc_wp_grp_sz);
			card->ext_csd.enhanced_area_size <<= 9;
		} else {
			/*
			 * If the enhanced area is not enabled, disable these
			 * device attributes.
			 */
			card->ext_csd.enhanced_area_offset = -EINVAL;
			card->ext_csd.enhanced_area_size = -EINVAL;
		}
		card->ext_csd.sec_trim_mult =
			ext_csd[EXT_CSD_SEC_TRIM_MULT];
		card->ext_csd.sec_erase_mult =
@@ -336,6 +374,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(enhanced_area_offset, "%llu\n",
		card->ext_csd.enhanced_area_offset);
MMC_DEV_ATTR(enhanced_area_size, "%u\n", card->ext_csd.enhanced_area_size);

static struct attribute *mmc_std_attrs[] = {
	&dev_attr_cid.attr,
@@ -349,6 +390,8 @@ static struct attribute *mmc_std_attrs[] = {
	&dev_attr_name.attr,
	&dev_attr_oemid.attr,
	&dev_attr_serial.attr,
	&dev_attr_enhanced_area_offset.attr,
	&dev_attr_enhanced_area_size.attr,
	NULL,
};

@@ -483,6 +526,37 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
		mmc_set_erase_size(card);
	}

	/*
	 * If enhanced_area_en is TRUE, host needs to enable ERASE_GRP_DEF
	 * bit.  This bit will be lost everytime after a reset or power off.
	 */
	if (card->ext_csd.enhanced_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.enhanced_area_offset = -EINVAL;
			card->ext_csd.enhanced_area_size = -EINVAL;
		} else {
			card->ext_csd.erase_group_def = 1;
			/*
			 * enable ERASE_GRP_DEF successfully.
			 * This will affect the erase size, so
			 * here need to reset erase size
			 */
			mmc_set_erase_size(card);
		}
	}

	/*
	 * Activate high speed (if supported)
	 */
+3 −0
Original line number Diff line number Diff line
@@ -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 */
	bool			enhanced_area_en;	/* enable bit */
	unsigned long long	enhanced_area_offset;	/* Units: Byte */
	unsigned int		enhanced_area_size;	/* Units: KB */
};

struct sd_scr {
+3 −0
Original line number Diff line number Diff line
@@ -253,6 +253,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 */
@@ -262,6 +264,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 */