diff options
author | Tatyana Brokhman <tlinder@codeaurora.org> | 2014-12-04 22:03:42 +0200 |
---|---|---|
committer | Subhash Jadavani <subhashj@codeaurora.org> | 2016-05-31 15:25:49 -0700 |
commit | 15209ec725e499e1e53b6e1104b6249e0430bf94 (patch) | |
tree | 98ff7bdd0f4a8d2f6c58270d0d15ef1e2fbcef53 /drivers | |
parent | 83d95c50fb7c138177290641436a926ed4700e9b (diff) |
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 <tlinder@codeaurora.org>
Signed-off-by: Sujit Reddy Thumma <sthumma@codeaurora.org>
[merez@codeaurora.org: fix conflicts as some of the code was already included]
Signed-off-by: Maya Erez <merez@codeaurora.org>
[venkatg@codeaurora.org: Remove PM related code]
Signed-off-by: Venkat Gopalakrishnan <venkatg@codeaurora.org>
[subhashj@codeaurora.org: fixed trivial merge conflicts]
Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mmc/core/mmc.c | 36 |
1 files changed, 36 insertions, 0 deletions
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 <linux/mmc/host.h> #include <linux/mmc/card.h> #include <linux/mmc/mmc.h> +#include <linux/reboot.h> #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: |