From: zhaojohn <john.zhao@xxxxxxxxx> Hynix eMMC devices sometimes take 50% longer to resume from sleep. Based on a recommendation from Hynix, send a Power-Off Notification before going to S3 to restore a resume time consistently within spec. Signed-off-by: zhaojohn <john.zhao@xxxxxxxxx> Signed-off-by: Arindam Roy <arindam.roy@xxxxxxxxx> Tested-by: Freddy Paul <freddy.paul@xxxxxxxxx> Reviewed-by: Icarus W Sparry <icarus.w.sparry@xxxxxxxxx> Reviewed-by: Marc Herbert <marc.herbert@xxxxxxxxx> Reviewed-by: Eric Caruso <ejcaruso@xxxxxxxxxxxx> Signed-off-by: Brian Norris <briannorris@xxxxxxxxxxxx> Signed-off-by: Thierry Escande <thierry.escande@xxxxxxxxxxxxx> --- drivers/mmc/card/block.c | 8 ++++++++ drivers/mmc/core/mmc.c | 8 +++++++- include/linux/mmc/card.h | 2 ++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 2206d44..cbc2d97 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -2572,6 +2572,14 @@ static const struct mmc_fixup blk_fixups[] = MMC_FIXUP("V10016", CID_MANFID_KINGSTON, CID_OEMID_ANY, add_quirk_mmc, MMC_QUIRK_TRIM_BROKEN), + /* + * Hynix eMMC devices sometimes take 50% longer to resume from sleep. + * Based on a recommendation from Hynix, send a Power-Off Notification + * before going to S3 to restore a resume time consistently within spec. + */ + MMC_FIXUP(CID_NAME_ANY, CID_MANFID_HYNIX, CID_OEMID_ANY, add_quirk_mmc, + MMC_QUIRK_NOTIFY_POWEROFF_ON_SLEEP), + END_FIXUP }; diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index f2d185c..46a4562 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1925,8 +1925,14 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend) if (mmc_can_poweroff_notify(host->card) && ((host->caps2 & MMC_CAP2_FULL_PWR_CYCLE) || !is_suspend)) err = mmc_poweroff_notify(host->card, notify_type); - else if (mmc_can_sleep(host->card)) + else if (mmc_can_sleep(host->card)) { + if (host->card->quirks & MMC_QUIRK_NOTIFY_POWEROFF_ON_SLEEP) { + err = mmc_poweroff_notify(host->card, notify_type); + if (err) + goto out; + } err = mmc_sleep(host); + } else if (!mmc_host_is_spi(host)) err = mmc_deselect_cards(host); diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index d8673ca..30e34b0 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -281,6 +281,8 @@ struct mmc_card { #define MMC_QUIRK_BROKEN_IRQ_POLLING (1<<11) /* Polling SDIO_CCCR_INTx could create a fake interrupt */ #define MMC_QUIRK_TRIM_BROKEN (1<<12) /* Skip trim */ #define MMC_QUIRK_BROKEN_HPI (1<<13) /* Disable broken HPI support */ +#define MMC_QUIRK_NOTIFY_POWEROFF_ON_SLEEP \ + (1<<14) /* Poweroff notification*/ unsigned int erase_size; /* erase size in sectors */ -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html