aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPratibhasagar V <pratibha@codeaurora.org>2016-06-09 18:09:31 -0400
committerUlf Hansson <ulf.hansson@linaro.org>2016-07-25 04:34:12 -0400
commit5320226a051248b50cc2d80f2cb9599dfb56d422 (patch)
tree49b15538c654f6babac1b576d4a671826f179bf3
parent8b7be8f2e7fe6c037fc7c89029a4a568ad2c60b1 (diff)
mmc: core: Disable HPI for certain Hynix eMMC cards
Certain Hynix eMMC 4.41 cards might get broken when HPI feature is used and hence this patch disables the HPI feature for such buggy cards. As some of the other features like BKOPs/Cache/Sanitize are dependent on HPI feature, those features would also get disabled if HPI is disabled. Signed-off-by: Pratibhasagar V <pratibha@codeaurora.org> Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org> [gdavis: Forward port and cleanup] Signed-off-by: George G. Davis <george_davis@mentor.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
-rw-r--r--drivers/mmc/card/block.c6
-rw-r--r--drivers/mmc/core/mmc.c23
-rw-r--r--drivers/mmc/core/quirks.c2
-rw-r--r--include/linux/mmc/card.h35
4 files changed, 52 insertions, 14 deletions
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 636843a90b7e..abfe3942a42d 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -2499,12 +2499,6 @@ force_ro_fail:
2499 return ret; 2499 return ret;
2500} 2500}
2501 2501
2502#define CID_MANFID_SANDISK 0x2
2503#define CID_MANFID_TOSHIBA 0x11
2504#define CID_MANFID_MICRON 0x13
2505#define CID_MANFID_SAMSUNG 0x15
2506#define CID_MANFID_KINGSTON 0x70
2507
2508static const struct mmc_fixup blk_fixups[] = 2502static const struct mmc_fixup blk_fixups[] =
2509{ 2503{
2510 MMC_FIXUP("SEM02G", CID_MANFID_SANDISK, 0x100, add_quirk, 2504 MMC_FIXUP("SEM02G", CID_MANFID_SANDISK, 0x100, add_quirk,
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index ccab9bb8c45a..548504024587 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -45,6 +45,17 @@ static const unsigned int tacc_mant[] = {
45 35, 40, 45, 50, 55, 60, 70, 80, 45 35, 40, 45, 50, 55, 60, 70, 80,
46}; 46};
47 47
48static const struct mmc_fixup mmc_ext_csd_fixups[] = {
49 /*
50 * Certain Hynix eMMC 4.41 cards might get broken when HPI feature
51 * is used so disable the HPI feature for such buggy cards.
52 */
53 MMC_FIXUP_EXT_CSD_REV(CID_NAME_ANY, CID_MANFID_HYNIX,
54 0x014a, add_quirk, MMC_QUIRK_BROKEN_HPI, 5),
55
56 END_FIXUP
57};
58
48#define UNSTUFF_BITS(resp,start,size) \ 59#define UNSTUFF_BITS(resp,start,size) \
49 ({ \ 60 ({ \
50 const int __size = size; \ 61 const int __size = size; \
@@ -375,6 +386,9 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd)
375 */ 386 */
376 card->ext_csd.rev = ext_csd[EXT_CSD_REV]; 387 card->ext_csd.rev = ext_csd[EXT_CSD_REV];
377 388
389 /* fixup device after ext_csd revision field is updated */
390 mmc_fixup_device(card, mmc_ext_csd_fixups);
391
378 card->ext_csd.raw_sectors[0] = ext_csd[EXT_CSD_SEC_CNT + 0]; 392 card->ext_csd.raw_sectors[0] = ext_csd[EXT_CSD_SEC_CNT + 0];
379 card->ext_csd.raw_sectors[1] = ext_csd[EXT_CSD_SEC_CNT + 1]; 393 card->ext_csd.raw_sectors[1] = ext_csd[EXT_CSD_SEC_CNT + 1];
380 card->ext_csd.raw_sectors[2] = ext_csd[EXT_CSD_SEC_CNT + 2]; 394 card->ext_csd.raw_sectors[2] = ext_csd[EXT_CSD_SEC_CNT + 2];
@@ -506,7 +520,8 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd)
506 card->cid.year += 16; 520 card->cid.year += 16;
507 521
508 /* check whether the eMMC card supports BKOPS */ 522 /* check whether the eMMC card supports BKOPS */
509 if (ext_csd[EXT_CSD_BKOPS_SUPPORT] & 0x1) { 523 if (!mmc_card_broken_hpi(card) &&
524 ext_csd[EXT_CSD_BKOPS_SUPPORT] & 0x1) {
510 card->ext_csd.bkops = 1; 525 card->ext_csd.bkops = 1;
511 card->ext_csd.man_bkops_en = 526 card->ext_csd.man_bkops_en =
512 (ext_csd[EXT_CSD_BKOPS_EN] & 527 (ext_csd[EXT_CSD_BKOPS_EN] &
@@ -519,7 +534,8 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd)
519 } 534 }
520 535
521 /* check whether the eMMC card supports HPI */ 536 /* check whether the eMMC card supports HPI */
522 if (!broken_hpi && (ext_csd[EXT_CSD_HPI_FEATURES] & 0x1)) { 537 if (!mmc_card_broken_hpi(card) &&
538 !broken_hpi && (ext_csd[EXT_CSD_HPI_FEATURES] & 0x1)) {
523 card->ext_csd.hpi = 1; 539 card->ext_csd.hpi = 1;
524 if (ext_csd[EXT_CSD_HPI_FEATURES] & 0x2) 540 if (ext_csd[EXT_CSD_HPI_FEATURES] & 0x2)
525 card->ext_csd.hpi_cmd = MMC_STOP_TRANSMISSION; 541 card->ext_csd.hpi_cmd = MMC_STOP_TRANSMISSION;
@@ -1675,7 +1691,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
1675 * If cache size is higher than 0, this indicates 1691 * If cache size is higher than 0, this indicates
1676 * the existence of cache and it can be turned on. 1692 * the existence of cache and it can be turned on.
1677 */ 1693 */
1678 if (card->ext_csd.cache_size > 0) { 1694 if (!mmc_card_broken_hpi(card) &&
1695 card->ext_csd.cache_size > 0) {
1679 err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, 1696 err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
1680 EXT_CSD_CACHE_CTRL, 1, 1697 EXT_CSD_CACHE_CTRL, 1,
1681 card->ext_csd.generic_cmd6_time); 1698 card->ext_csd.generic_cmd6_time);
diff --git a/drivers/mmc/core/quirks.c b/drivers/mmc/core/quirks.c
index fad660b95809..ca9cade317c7 100644
--- a/drivers/mmc/core/quirks.c
+++ b/drivers/mmc/core/quirks.c
@@ -72,6 +72,8 @@ void mmc_fixup_device(struct mmc_card *card, const struct mmc_fixup *table)
72 f->cis_vendor == (u16) SDIO_ANY_ID) && 72 f->cis_vendor == (u16) SDIO_ANY_ID) &&
73 (f->cis_device == card->cis.device || 73 (f->cis_device == card->cis.device ||
74 f->cis_device == (u16) SDIO_ANY_ID) && 74 f->cis_device == (u16) SDIO_ANY_ID) &&
75 (f->ext_csd_rev == EXT_CSD_REV_ANY ||
76 f->ext_csd_rev == card->ext_csd.rev) &&
75 rev >= f->rev_start && rev <= f->rev_end) { 77 rev >= f->rev_start && rev <= f->rev_end) {
76 dev_dbg(&card->dev, "calling %pf\n", f->vendor_fixup); 78 dev_dbg(&card->dev, "calling %pf\n", f->vendor_fixup);
77 f->vendor_fixup(card, f->data); 79 f->vendor_fixup(card, f->data);
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 22defc2a83b7..d8673ca968ba 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -280,6 +280,7 @@ struct mmc_card {
280#define MMC_QUIRK_SEC_ERASE_TRIM_BROKEN (1<<10) /* Skip secure for erase/trim */ 280#define MMC_QUIRK_SEC_ERASE_TRIM_BROKEN (1<<10) /* Skip secure for erase/trim */
281#define MMC_QUIRK_BROKEN_IRQ_POLLING (1<<11) /* Polling SDIO_CCCR_INTx could create a fake interrupt */ 281#define MMC_QUIRK_BROKEN_IRQ_POLLING (1<<11) /* Polling SDIO_CCCR_INTx could create a fake interrupt */
282#define MMC_QUIRK_TRIM_BROKEN (1<<12) /* Skip trim */ 282#define MMC_QUIRK_TRIM_BROKEN (1<<12) /* Skip trim */
283#define MMC_QUIRK_BROKEN_HPI (1<<13) /* Disable broken HPI support */
283 284
284 285
285 unsigned int erase_size; /* erase size in sectors */ 286 unsigned int erase_size; /* erase size in sectors */
@@ -354,6 +355,9 @@ struct mmc_fixup {
354 /* SDIO-specfic fields. You can use SDIO_ANY_ID here of course */ 355 /* SDIO-specfic fields. You can use SDIO_ANY_ID here of course */
355 u16 cis_vendor, cis_device; 356 u16 cis_vendor, cis_device;
356 357
358 /* for MMC cards */
359 unsigned int ext_csd_rev;
360
357 void (*vendor_fixup)(struct mmc_card *card, int data); 361 void (*vendor_fixup)(struct mmc_card *card, int data);
358 int data; 362 int data;
359}; 363};
@@ -362,11 +366,20 @@ struct mmc_fixup {
362#define CID_OEMID_ANY ((unsigned short) -1) 366#define CID_OEMID_ANY ((unsigned short) -1)
363#define CID_NAME_ANY (NULL) 367#define CID_NAME_ANY (NULL)
364 368
369#define EXT_CSD_REV_ANY (-1u)
370
371#define CID_MANFID_SANDISK 0x2
372#define CID_MANFID_TOSHIBA 0x11
373#define CID_MANFID_MICRON 0x13
374#define CID_MANFID_SAMSUNG 0x15
375#define CID_MANFID_KINGSTON 0x70
376#define CID_MANFID_HYNIX 0x90
377
365#define END_FIXUP { NULL } 378#define END_FIXUP { NULL }
366 379
367#define _FIXUP_EXT(_name, _manfid, _oemid, _rev_start, _rev_end, \ 380#define _FIXUP_EXT(_name, _manfid, _oemid, _rev_start, _rev_end, \
368 _cis_vendor, _cis_device, \ 381 _cis_vendor, _cis_device, \
369 _fixup, _data) \ 382 _fixup, _data, _ext_csd_rev) \
370 { \ 383 { \
371 .name = (_name), \ 384 .name = (_name), \
372 .manfid = (_manfid), \ 385 .manfid = (_manfid), \
@@ -377,23 +390,30 @@ struct mmc_fixup {
377 .cis_device = (_cis_device), \ 390 .cis_device = (_cis_device), \
378 .vendor_fixup = (_fixup), \ 391 .vendor_fixup = (_fixup), \
379 .data = (_data), \ 392 .data = (_data), \
393 .ext_csd_rev = (_ext_csd_rev), \
380 } 394 }
381 395
382#define MMC_FIXUP_REV(_name, _manfid, _oemid, _rev_start, _rev_end, \ 396#define MMC_FIXUP_REV(_name, _manfid, _oemid, _rev_start, _rev_end, \
383 _fixup, _data) \ 397 _fixup, _data, _ext_csd_rev) \
384 _FIXUP_EXT(_name, _manfid, \ 398 _FIXUP_EXT(_name, _manfid, \
385 _oemid, _rev_start, _rev_end, \ 399 _oemid, _rev_start, _rev_end, \
386 SDIO_ANY_ID, SDIO_ANY_ID, \ 400 SDIO_ANY_ID, SDIO_ANY_ID, \
387 _fixup, _data) \ 401 _fixup, _data, _ext_csd_rev) \
388 402
389#define MMC_FIXUP(_name, _manfid, _oemid, _fixup, _data) \ 403#define MMC_FIXUP(_name, _manfid, _oemid, _fixup, _data) \
390 MMC_FIXUP_REV(_name, _manfid, _oemid, 0, -1ull, _fixup, _data) 404 MMC_FIXUP_REV(_name, _manfid, _oemid, 0, -1ull, _fixup, _data, \
405 EXT_CSD_REV_ANY)
406
407#define MMC_FIXUP_EXT_CSD_REV(_name, _manfid, _oemid, _fixup, _data, \
408 _ext_csd_rev) \
409 MMC_FIXUP_REV(_name, _manfid, _oemid, 0, -1ull, _fixup, _data, \
410 _ext_csd_rev)
391 411
392#define SDIO_FIXUP(_vendor, _device, _fixup, _data) \ 412#define SDIO_FIXUP(_vendor, _device, _fixup, _data) \
393 _FIXUP_EXT(CID_NAME_ANY, CID_MANFID_ANY, \ 413 _FIXUP_EXT(CID_NAME_ANY, CID_MANFID_ANY, \
394 CID_OEMID_ANY, 0, -1ull, \ 414 CID_OEMID_ANY, 0, -1ull, \
395 _vendor, _device, \ 415 _vendor, _device, \
396 _fixup, _data) \ 416 _fixup, _data, EXT_CSD_REV_ANY) \
397 417
398#define cid_rev(hwrev, fwrev, year, month) \ 418#define cid_rev(hwrev, fwrev, year, month) \
399 (((u64) hwrev) << 40 | \ 419 (((u64) hwrev) << 40 | \
@@ -512,6 +532,11 @@ static inline int mmc_card_broken_irq_polling(const struct mmc_card *c)
512 return c->quirks & MMC_QUIRK_BROKEN_IRQ_POLLING; 532 return c->quirks & MMC_QUIRK_BROKEN_IRQ_POLLING;
513} 533}
514 534
535static inline int mmc_card_broken_hpi(const struct mmc_card *c)
536{
537 return c->quirks & MMC_QUIRK_BROKEN_HPI;
538}
539
515#define mmc_card_name(c) ((c)->cid.prod_name) 540#define mmc_card_name(c) ((c)->cid.prod_name)
516#define mmc_card_id(c) (dev_name(&(c)->dev)) 541#define mmc_card_id(c) (dev_name(&(c)->dev))
517 542