From 5320226a051248b50cc2d80f2cb9599dfb56d422 Mon Sep 17 00:00:00 2001 From: Pratibhasagar V Date: Thu, 9 Jun 2016 18:09:31 -0400 Subject: 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 Signed-off-by: Subhash Jadavani [gdavis: Forward port and cleanup] Signed-off-by: George G. Davis Signed-off-by: Ulf Hansson --- drivers/mmc/core/mmc.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) (limited to 'drivers/mmc/core/mmc.c') diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index ccab9bb..5485040 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -45,6 +45,17 @@ static const unsigned int tacc_mant[] = { 35, 40, 45, 50, 55, 60, 70, 80, }; +static const struct mmc_fixup mmc_ext_csd_fixups[] = { + /* + * Certain Hynix eMMC 4.41 cards might get broken when HPI feature + * is used so disable the HPI feature for such buggy cards. + */ + MMC_FIXUP_EXT_CSD_REV(CID_NAME_ANY, CID_MANFID_HYNIX, + 0x014a, add_quirk, MMC_QUIRK_BROKEN_HPI, 5), + + END_FIXUP +}; + #define UNSTUFF_BITS(resp,start,size) \ ({ \ const int __size = size; \ @@ -375,6 +386,9 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd) */ card->ext_csd.rev = ext_csd[EXT_CSD_REV]; + /* fixup device after ext_csd revision field is updated */ + mmc_fixup_device(card, mmc_ext_csd_fixups); + card->ext_csd.raw_sectors[0] = ext_csd[EXT_CSD_SEC_CNT + 0]; card->ext_csd.raw_sectors[1] = ext_csd[EXT_CSD_SEC_CNT + 1]; 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) card->cid.year += 16; /* check whether the eMMC card supports BKOPS */ - if (ext_csd[EXT_CSD_BKOPS_SUPPORT] & 0x1) { + if (!mmc_card_broken_hpi(card) && + ext_csd[EXT_CSD_BKOPS_SUPPORT] & 0x1) { card->ext_csd.bkops = 1; card->ext_csd.man_bkops_en = (ext_csd[EXT_CSD_BKOPS_EN] & @@ -519,7 +534,8 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd) } /* check whether the eMMC card supports HPI */ - if (!broken_hpi && (ext_csd[EXT_CSD_HPI_FEATURES] & 0x1)) { + if (!mmc_card_broken_hpi(card) && + !broken_hpi && (ext_csd[EXT_CSD_HPI_FEATURES] & 0x1)) { card->ext_csd.hpi = 1; if (ext_csd[EXT_CSD_HPI_FEATURES] & 0x2) card->ext_csd.hpi_cmd = MMC_STOP_TRANSMISSION; @@ -1675,7 +1691,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, * If cache size is higher than 0, this indicates * the existence of cache and it can be turned on. */ - if (card->ext_csd.cache_size > 0) { + if (!mmc_card_broken_hpi(card) && + card->ext_csd.cache_size > 0) { err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_CACHE_CTRL, 1, card->ext_csd.generic_cmd6_time); -- cgit v1.1