mmc: core: Update PON based on the system state

As per eMMC specification, the PON (Power Off Notification)
must be sent by host to the card before turning off the power.
This will allow card to prepare itself for the power off and
may even reduce the initialization of eMMC upon next boot-up.

Send long PON during system power off and send short PON during
system reboot to reduce the reboot latency.

Change-Id: If4188b8b80aaa0e6c4e00e1807aa9589d5e7efdb
Signed-off-by: Sahitya Tummala <stummala@codeaurora.org>
Signed-off-by: Krishna Konda <kkonda@codeaurora.org>
[subhashj@codeaurora.org: fixed trivial merge conflicts]
Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
This commit is contained in:
Krishna Konda 2015-06-29 19:20:05 -07:00 committed by Subhash Jadavani
parent b6c1c16680
commit 62c8dce6e1
3 changed files with 23 additions and 12 deletions

View file

@ -4056,6 +4056,10 @@ static int _mmc_blk_suspend(struct mmc_card *card)
static void mmc_blk_shutdown(struct mmc_card *card)
{
_mmc_blk_suspend(card);
/* send power off notification */
if (mmc_card_mmc(card))
mmc_send_pon(card);
}
#ifdef CONFIG_PM_SLEEP

View file

@ -1431,10 +1431,7 @@ static int mmc_reboot_notify(struct notifier_block *notify_block,
struct mmc_card *card = container_of(
notify_block, struct mmc_card, reboot_notify);
if (event != SYS_RESTART)
card->issue_long_pon = true;
else
card->issue_long_pon = false;
card->pon_type = (event != SYS_RESTART) ? MMC_LONG_PON : MMC_SHRT_PON;
return NOTIFY_OK;
}
@ -2255,19 +2252,24 @@ static int mmc_poweroff_notify(struct mmc_card *card, unsigned int notify_type)
return err;
}
int mmc_send_long_pon(struct mmc_card *card)
int mmc_send_pon(struct mmc_card *card)
{
int err = 0;
struct mmc_host *host = card->host;
if (!mmc_can_poweroff_notify(card))
goto out;
mmc_claim_host(host);
if (card->issue_long_pon && mmc_can_poweroff_notify(card)) {
if (card->pon_type & MMC_LONG_PON)
err = mmc_poweroff_notify(host->card, EXT_CSD_POWER_OFF_LONG);
if (err)
pr_warning("%s: error %d sending Long PON",
mmc_hostname(host), err);
}
else if (card->pon_type & MMC_SHRT_PON)
err = mmc_poweroff_notify(host->card, EXT_CSD_POWER_OFF_SHORT);
if (err)
pr_warn("%s: error %d sending PON type %u",
mmc_hostname(host), err, card->pon_type);
mmc_release_host(host);
out:
return err;
}

View file

@ -324,6 +324,11 @@ struct mmc_bkops_info {
bool needs_manual;
};
enum mmc_pon_type {
MMC_LONG_PON = 1,
MMC_SHRT_PON,
};
/*
* MMC device
*/
@ -411,7 +416,7 @@ struct mmc_card {
struct mmc_wr_pack_stats wr_pack_stats; /* packed commands stats*/
struct notifier_block reboot_notify;
bool issue_long_pon;
enum mmc_pon_type pon_type;
u8 *cached_ext_csd;
bool cmdq_init;
struct mmc_bkops_info bkops;
@ -691,6 +696,6 @@ extern void mmc_fixup_device(struct mmc_card *card,
extern struct mmc_wr_pack_stats *mmc_blk_get_packed_statistics(
struct mmc_card *card);
extern void mmc_blk_init_packed_statistics(struct mmc_card *card);
extern int mmc_send_long_pon(struct mmc_card *card);
extern int mmc_send_pon(struct mmc_card *card);
extern void mmc_blk_cmdq_req_done(struct mmc_request *mrq);
#endif /* LINUX_MMC_CARD_H */