aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/core/mmc.c
diff options
context:
space:
mode:
authorChuanxiao Dong <chuanxiao.dong@intel.com>2011-01-21 15:09:41 -0500
committerChris Ball <cjb@laptop.org>2011-03-15 13:48:01 -0400
commit709de99df0ecf3102e7728fbd876a3591859f423 (patch)
treef1adaa026531d3dcc93cf33c2e8ede84455ca46a /drivers/mmc/core/mmc.c
parentcfd80652467717ca7346857d6d8c94503d74f3a3 (diff)
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: Chuanxiao Dong <chuanxiao.dong@intel.com> Reviewed-by: Chris Ball <cjb@laptop.org> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc/core/mmc.c')
-rw-r--r--drivers/mmc/core/mmc.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 16006ef153f..6396c5d98e8 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -302,6 +302,44 @@ static int mmc_read_ext_csd(struct mmc_card *card)
302 } 302 }
303 303
304 if (card->ext_csd.rev >= 4) { 304 if (card->ext_csd.rev >= 4) {
305 /*
306 * Enhanced area feature support -- check whether the eMMC
307 * card has the Enhanced area enabled. If so, export enhanced
308 * area offset and size to user by adding sysfs interface.
309 */
310 if ((ext_csd[EXT_CSD_PARTITION_SUPPORT] & 0x2) &&
311 (ext_csd[EXT_CSD_PARTITION_ATTRIBUTE] & 0x1)) {
312 u8 hc_erase_grp_sz =
313 ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE];
314 u8 hc_wp_grp_sz =
315 ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
316
317 card->ext_csd.enhanced_area_en = 1;
318 /*
319 * calculate the enhanced data area offset, in bytes
320 */
321 card->ext_csd.enhanced_area_offset =
322 (ext_csd[139] << 24) + (ext_csd[138] << 16) +
323 (ext_csd[137] << 8) + ext_csd[136];
324 if (mmc_card_blockaddr(card))
325 card->ext_csd.enhanced_area_offset <<= 9;
326 /*
327 * calculate the enhanced data area size, in kilobytes
328 */
329 card->ext_csd.enhanced_area_size =
330 (ext_csd[142] << 16) + (ext_csd[141] << 8) +
331 ext_csd[140];
332 card->ext_csd.enhanced_area_size *=
333 (size_t)(hc_erase_grp_sz * hc_wp_grp_sz);
334 card->ext_csd.enhanced_area_size <<= 9;
335 } else {
336 /*
337 * If the enhanced area is not enabled, disable these
338 * device attributes.
339 */
340 card->ext_csd.enhanced_area_offset = -EINVAL;
341 card->ext_csd.enhanced_area_size = -EINVAL;
342 }
305 card->ext_csd.sec_trim_mult = 343 card->ext_csd.sec_trim_mult =
306 ext_csd[EXT_CSD_SEC_TRIM_MULT]; 344 ext_csd[EXT_CSD_SEC_TRIM_MULT];
307 card->ext_csd.sec_erase_mult = 345 card->ext_csd.sec_erase_mult =
@@ -336,6 +374,9 @@ MMC_DEV_ATTR(manfid, "0x%06x\n", card->cid.manfid);
336MMC_DEV_ATTR(name, "%s\n", card->cid.prod_name); 374MMC_DEV_ATTR(name, "%s\n", card->cid.prod_name);
337MMC_DEV_ATTR(oemid, "0x%04x\n", card->cid.oemid); 375MMC_DEV_ATTR(oemid, "0x%04x\n", card->cid.oemid);
338MMC_DEV_ATTR(serial, "0x%08x\n", card->cid.serial); 376MMC_DEV_ATTR(serial, "0x%08x\n", card->cid.serial);
377MMC_DEV_ATTR(enhanced_area_offset, "%llu\n",
378 card->ext_csd.enhanced_area_offset);
379MMC_DEV_ATTR(enhanced_area_size, "%u\n", card->ext_csd.enhanced_area_size);
339 380
340static struct attribute *mmc_std_attrs[] = { 381static struct attribute *mmc_std_attrs[] = {
341 &dev_attr_cid.attr, 382 &dev_attr_cid.attr,
@@ -349,6 +390,8 @@ static struct attribute *mmc_std_attrs[] = {
349 &dev_attr_name.attr, 390 &dev_attr_name.attr,
350 &dev_attr_oemid.attr, 391 &dev_attr_oemid.attr,
351 &dev_attr_serial.attr, 392 &dev_attr_serial.attr,
393 &dev_attr_enhanced_area_offset.attr,
394 &dev_attr_enhanced_area_size.attr,
352 NULL, 395 NULL,
353}; 396};
354 397
@@ -484,6 +527,37 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
484 } 527 }
485 528
486 /* 529 /*
530 * If enhanced_area_en is TRUE, host needs to enable ERASE_GRP_DEF
531 * bit. This bit will be lost everytime after a reset or power off.
532 */
533 if (card->ext_csd.enhanced_area_en) {
534 err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
535 EXT_CSD_ERASE_GROUP_DEF, 1);
536
537 if (err && err != -EBADMSG)
538 goto free_card;
539
540 if (err) {
541 err = 0;
542 /*
543 * Just disable enhanced area off & sz
544 * will try to enable ERASE_GROUP_DEF
545 * during next time reinit
546 */
547 card->ext_csd.enhanced_area_offset = -EINVAL;
548 card->ext_csd.enhanced_area_size = -EINVAL;
549 } else {
550 card->ext_csd.erase_group_def = 1;
551 /*
552 * enable ERASE_GRP_DEF successfully.
553 * This will affect the erase size, so
554 * here need to reset erase size
555 */
556 mmc_set_erase_size(card);
557 }
558 }
559
560 /*
487 * Activate high speed (if supported) 561 * Activate high speed (if supported)
488 */ 562 */
489 if ((card->ext_csd.hs_max_dtr != 0) && 563 if ((card->ext_csd.hs_max_dtr != 0) &&