@@ -302,6 +302,35 @@ 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[160] & 0x2) && (ext_csd[156] & 0x1)) {
+ u8 hc_erase_grp_sz = ext_csd[224];
+ u8 hc_wp_grp_sz = ext_csd[221];
+ /* 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;
+ }
+
card->ext_csd.sec_trim_mult =
ext_csd[EXT_CSD_SEC_TRIM_MULT];
card->ext_csd.sec_erase_mult =
@@ -336,6 +365,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 +381,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,
};
@@ -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;
+ loff_t enh_data_area_off;
+ size_t enh_data_area_sz;
};
struct sd_scr {