From 15209ec725e499e1e53b6e1104b6249e0430bf94 Mon Sep 17 00:00:00 2001 From: Tatyana Brokhman Date: Thu, 4 Dec 2014 22:03:42 +0200 Subject: mmc: Add long power off notification support At the moment only POWER_OFF_SHORT is sent to the device in case the host is suspended. This patch adds the support of sending POWER_OFF_LONG notification in case the device is powered off. According to device vendors the POWER_OFF_LONG notification will shorten the initialization time of the eMMC card during next boot up. Change-Id: I3c6f224398450cf10463cbb316613fd430d1e8d2 Signed-off-by: Tatyana Brokhman Signed-off-by: Sujit Reddy Thumma [merez@codeaurora.org: fix conflicts as some of the code was already included] Signed-off-by: Maya Erez [venkatg@codeaurora.org: Remove PM related code] Signed-off-by: Venkat Gopalakrishnan [subhashj@codeaurora.org: fixed trivial merge conflicts] Signed-off-by: Subhash Jadavani --- drivers/mmc/core/mmc.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'drivers') diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 440d7a0a99be..461a150109fb 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "core.h" #include "host.h" @@ -1364,6 +1365,20 @@ out: return err; } +static int mmc_reboot_notify(struct notifier_block *notify_block, + unsigned long event, void *unused) +{ + 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; + + return NOTIFY_OK; +} + /* * Activate High Speed or HS200 mode if supported. */ @@ -1495,6 +1510,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, card->rca = 1; memcpy(card->raw_cid, cid, sizeof(card->raw_cid)); host->card = card; + card->reboot_notify.notifier_call = mmc_reboot_notify; } /* @@ -1838,6 +1854,22 @@ 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 err = 0; + struct mmc_host *host = card->host; + + mmc_claim_host(host); + if (card->issue_long_pon && mmc_can_poweroff_notify(card)) { + 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); + } + mmc_release_host(host); + return err; +} + /* * Host is being removed. Free up the current card. */ @@ -1846,6 +1878,7 @@ static void mmc_remove(struct mmc_host *host) BUG_ON(!host); BUG_ON(!host->card); + unregister_reboot_notifier(&host->card->reboot_notify); mmc_remove_card(host->card); mmc_claim_host(host); @@ -2166,6 +2199,9 @@ int mmc_attach_mmc(struct mmc_host *host) goto remove_card; mmc_claim_host(host); + + register_reboot_notifier(&host->card->reboot_notify); + return 0; remove_card: -- cgit v1.2.3