diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 5dbf839a1c4..44228a66d0e 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -1625,6 +1625,11 @@ static const struct mmc_fixup blk_fixups[] = MMC_QUIRK_BLK_NO_CMD23), MMC_FIXUP("MMC32G", 0x11, CID_OEMID_ANY, add_quirk_mmc, MMC_QUIRK_BLK_NO_CMD23), + + /* Some INAND MCP devices advertise incorrect timeout values */ + MMC_FIXUP("SEM04G", 0x45, CID_OEMID_ANY, add_quirk_mmc, + MMC_QUIRK_INAND_DATA_TIMEOUT), + END_FIXUP }; diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index ca86323d1db..843a70760b2 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -523,6 +523,11 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card) data->timeout_ns = 100000000; /* 100ms */ } } + /* Increase the timeout values for some bad INAND MCP devices */ + if (card->quirks & MMC_QUIRK_INAND_DATA_TIMEOUT) { + data->timeout_ns = 4000000000u; /* 4s */ + data->timeout_clks = 0; + } } EXPORT_SYMBOL(mmc_set_data_timeout); diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 0fcae7c3a41..8a0c4d5b434 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -202,6 +202,7 @@ struct mmc_card { #define MMC_QUIRK_DISABLE_CD (1<<5) /* disconnect CD/DAT[3] resistor */ #define MMC_QUIRK_INAND_CMD38 (1<<6) /* iNAND devices have broken CMD38 */ #define MMC_QUIRK_BLK_NO_CMD23 (1<<7) /* Avoid CMD23 for regular multiblock */ +#define MMC_QUIRK_INAND_DATA_TIMEOUT (1<<8) /* For incorrect data timeout */ unsigned int poweroff_notify_state; /* eMMC4.5 notify feature */ #define MMC_NO_POWER_NOTIFICATION 0 #define MMC_POWERED_ON 1