diff options
Diffstat (limited to 'drivers/mmc/core/mmc.c')
-rw-r--r-- | drivers/mmc/core/mmc.c | 86 |
1 files changed, 85 insertions, 1 deletions
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 16006ef153fe..772d0d0a541b 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 | ||
@@ -378,6 +421,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
378 | int err, ddr = 0; | 421 | int err, ddr = 0; |
379 | u32 cid[4]; | 422 | u32 cid[4]; |
380 | unsigned int max_dtr; | 423 | unsigned int max_dtr; |
424 | u32 rocr; | ||
381 | 425 | ||
382 | BUG_ON(!host); | 426 | BUG_ON(!host); |
383 | WARN_ON(!host->claimed); | 427 | WARN_ON(!host->claimed); |
@@ -391,7 +435,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
391 | mmc_go_idle(host); | 435 | mmc_go_idle(host); |
392 | 436 | ||
393 | /* The extra bit indicates that we support high capacity */ | 437 | /* The extra bit indicates that we support high capacity */ |
394 | err = mmc_send_op_cond(host, ocr | (1 << 30), NULL); | 438 | err = mmc_send_op_cond(host, ocr | (1 << 30), &rocr); |
395 | if (err) | 439 | if (err) |
396 | goto err; | 440 | goto err; |
397 | 441 | ||
@@ -479,11 +523,51 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
479 | err = mmc_read_ext_csd(card); | 523 | err = mmc_read_ext_csd(card); |
480 | if (err) | 524 | if (err) |
481 | goto free_card; | 525 | goto free_card; |
526 | |||
527 | /* If doing byte addressing, check if required to do sector | ||
528 | * addressing. Handle the case of <2GB cards needing sector | ||
529 | * addressing. See section 8.1 JEDEC Standard JED84-A441; | ||
530 | * ocr register has bit 30 set for sector addressing. | ||
531 | */ | ||
532 | if (!(mmc_card_blockaddr(card)) && (rocr & (1<<30))) | ||
533 | mmc_card_set_blockaddr(card); | ||
534 | |||
482 | /* Erase size depends on CSD and Extended CSD */ | 535 | /* Erase size depends on CSD and Extended CSD */ |
483 | mmc_set_erase_size(card); | 536 | mmc_set_erase_size(card); |
484 | } | 537 | } |
485 | 538 | ||
486 | /* | 539 | /* |
540 | * If enhanced_area_en is TRUE, host needs to enable ERASE_GRP_DEF | ||
541 | * bit. This bit will be lost every time after a reset or power off. | ||
542 | */ | ||
543 | if (card->ext_csd.enhanced_area_en) { | ||
544 | err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, | ||
545 | EXT_CSD_ERASE_GROUP_DEF, 1); | ||
546 | |||
547 | if (err && err != -EBADMSG) | ||
548 | goto free_card; | ||
549 | |||
550 | if (err) { | ||
551 | err = 0; | ||
552 | /* | ||
553 | * Just disable enhanced area off & sz | ||
554 | * will try to enable ERASE_GROUP_DEF | ||
555 | * during next time reinit | ||
556 | */ | ||
557 | card->ext_csd.enhanced_area_offset = -EINVAL; | ||
558 | card->ext_csd.enhanced_area_size = -EINVAL; | ||
559 | } else { | ||
560 | card->ext_csd.erase_group_def = 1; | ||
561 | /* | ||
562 | * enable ERASE_GRP_DEF successfully. | ||
563 | * This will affect the erase size, so | ||
564 | * here need to reset erase size | ||
565 | */ | ||
566 | mmc_set_erase_size(card); | ||
567 | } | ||
568 | } | ||
569 | |||
570 | /* | ||
487 | * Activate high speed (if supported) | 571 | * Activate high speed (if supported) |
488 | */ | 572 | */ |
489 | if ((card->ext_csd.hs_max_dtr != 0) && | 573 | if ((card->ext_csd.hs_max_dtr != 0) && |