diff options
-rw-r--r-- | Documentation/ABI/testing/sysfs-devices-mmc | 21 | ||||
-rw-r--r-- | drivers/mmc/core/mmc.c | 74 | ||||
-rw-r--r-- | include/linux/mmc/card.h | 3 | ||||
-rw-r--r-- | include/linux/mmc/mmc.h | 3 |
4 files changed, 101 insertions, 0 deletions
diff --git a/Documentation/ABI/testing/sysfs-devices-mmc b/Documentation/ABI/testing/sysfs-devices-mmc new file mode 100644 index 00000000000..5a50ab65584 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-devices-mmc | |||
@@ -0,0 +1,21 @@ | |||
1 | What: /sys/devices/.../mmc_host/mmcX/mmcX:XXXX/enhanced_area_offset | ||
2 | Date: January 2011 | ||
3 | Contact: Chuanxiao Dong <chuanxiao.dong@intel.com> | ||
4 | Description: | ||
5 | Enhanced area is a new feature defined in eMMC4.4 standard. | ||
6 | eMMC4.4 or later card can support such feature. This kind of | ||
7 | area can help to improve the card performance. If the feature | ||
8 | is enabled, this attribute will indicate the start address of | ||
9 | enhanced data area. If not, this attribute will be -EINVAL. | ||
10 | Unit Byte. Format decimal. | ||
11 | |||
12 | What: /sys/devices/.../mmc_host/mmcX/mmcX:XXXX/enhanced_area_size | ||
13 | Date: January 2011 | ||
14 | Contact: Chuanxiao Dong <chuanxiao.dong@intel.com> | ||
15 | Description: | ||
16 | Enhanced area is a new feature defined in eMMC4.4 standard. | ||
17 | eMMC4.4 or later card can support such feature. This kind of | ||
18 | area can help to improve the card performance. If the feature | ||
19 | is enabled, this attribute will indicate the size of enhanced | ||
20 | data area. If not, this attribute will be -EINVAL. | ||
21 | Unit KByte. Format decimal. | ||
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); | |||
336 | MMC_DEV_ATTR(name, "%s\n", card->cid.prod_name); | 374 | MMC_DEV_ATTR(name, "%s\n", card->cid.prod_name); |
337 | MMC_DEV_ATTR(oemid, "0x%04x\n", card->cid.oemid); | 375 | MMC_DEV_ATTR(oemid, "0x%04x\n", card->cid.oemid); |
338 | MMC_DEV_ATTR(serial, "0x%08x\n", card->cid.serial); | 376 | MMC_DEV_ATTR(serial, "0x%08x\n", card->cid.serial); |
377 | MMC_DEV_ATTR(enhanced_area_offset, "%llu\n", | ||
378 | card->ext_csd.enhanced_area_offset); | ||
379 | MMC_DEV_ATTR(enhanced_area_size, "%u\n", card->ext_csd.enhanced_area_size); | ||
339 | 380 | ||
340 | static struct attribute *mmc_std_attrs[] = { | 381 | static 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) && |
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 8ce082781cc..4652cf9c544 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h | |||
@@ -54,6 +54,9 @@ struct mmc_ext_csd { | |||
54 | unsigned int sec_trim_mult; /* Secure trim multiplier */ | 54 | unsigned int sec_trim_mult; /* Secure trim multiplier */ |
55 | unsigned int sec_erase_mult; /* Secure erase multiplier */ | 55 | unsigned int sec_erase_mult; /* Secure erase multiplier */ |
56 | unsigned int trim_timeout; /* In milliseconds */ | 56 | unsigned int trim_timeout; /* In milliseconds */ |
57 | bool enhanced_area_en; /* enable bit */ | ||
58 | unsigned long long enhanced_area_offset; /* Units: Byte */ | ||
59 | unsigned int enhanced_area_size; /* Units: KB */ | ||
57 | }; | 60 | }; |
58 | 61 | ||
59 | struct sd_scr { | 62 | struct sd_scr { |
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h index 612301f85d1..264ba5451e3 100644 --- a/include/linux/mmc/mmc.h +++ b/include/linux/mmc/mmc.h | |||
@@ -253,6 +253,8 @@ struct _mmc_csd { | |||
253 | * EXT_CSD fields | 253 | * EXT_CSD fields |
254 | */ | 254 | */ |
255 | 255 | ||
256 | #define EXT_CSD_PARTITION_ATTRIBUTE 156 /* R/W */ | ||
257 | #define EXT_CSD_PARTITION_SUPPORT 160 /* RO */ | ||
256 | #define EXT_CSD_ERASE_GROUP_DEF 175 /* R/W */ | 258 | #define EXT_CSD_ERASE_GROUP_DEF 175 /* R/W */ |
257 | #define EXT_CSD_ERASED_MEM_CONT 181 /* RO */ | 259 | #define EXT_CSD_ERASED_MEM_CONT 181 /* RO */ |
258 | #define EXT_CSD_BUS_WIDTH 183 /* R/W */ | 260 | #define EXT_CSD_BUS_WIDTH 183 /* R/W */ |
@@ -262,6 +264,7 @@ struct _mmc_csd { | |||
262 | #define EXT_CSD_CARD_TYPE 196 /* RO */ | 264 | #define EXT_CSD_CARD_TYPE 196 /* RO */ |
263 | #define EXT_CSD_SEC_CNT 212 /* RO, 4 bytes */ | 265 | #define EXT_CSD_SEC_CNT 212 /* RO, 4 bytes */ |
264 | #define EXT_CSD_S_A_TIMEOUT 217 /* RO */ | 266 | #define EXT_CSD_S_A_TIMEOUT 217 /* RO */ |
267 | #define EXT_CSD_HC_WP_GRP_SIZE 221 /* RO */ | ||
265 | #define EXT_CSD_ERASE_TIMEOUT_MULT 223 /* RO */ | 268 | #define EXT_CSD_ERASE_TIMEOUT_MULT 223 /* RO */ |
266 | #define EXT_CSD_HC_ERASE_GRP_SIZE 224 /* RO */ | 269 | #define EXT_CSD_HC_ERASE_GRP_SIZE 224 /* RO */ |
267 | #define EXT_CSD_SEC_TRIM_MULT 229 /* RO */ | 270 | #define EXT_CSD_SEC_TRIM_MULT 229 /* RO */ |