summaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorUlf Hansson <ulf.hansson@linaro.org>2013-06-10 17:03:38 +0200
committerChris Ball <cjb@laptop.org>2013-06-27 18:39:16 +0200
commit74590263384e5d4601de7f0ee2790477578829ea (patch)
treeb6548924c4fdc46244f0663c2adcfd72d22f30c9 /drivers/mmc
parentmmc: core: Validate suspend prerequisites for SDIO at SUSPEND_PREPARE (diff)
downloadlinux-74590263384e5d4601de7f0ee2790477578829ea.tar.xz
linux-74590263384e5d4601de7f0ee2790477578829ea.zip
mmc: core: Push common suspend|resume code into each bus_ops
By moving code from the mmc_suspend|resume_host down into each .suspend|resume bus_ops callback, we get a more flexible solution. Some nice side effects are that we get a better understanding of each bus_ops suspend|resume sequence and the common code don't have to take care of specific corner cases, especially for the SDIO case. Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Tested-by: Jaehoon Chung <jh80.chung@samsung.com> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/core/core.c31
-rw-r--r--drivers/mmc/core/mmc.c4
-rw-r--r--drivers/mmc/core/sd.c4
-rw-r--r--drivers/mmc/core/sdio.c21
4 files changed, 32 insertions, 28 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 7a8a42d3a039..da3b9078ea65 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -2621,9 +2621,6 @@ int mmc_suspend_host(struct mmc_host *host)
{
int err = 0;
- cancel_delayed_work(&host->detect);
- mmc_flush_scheduled_work();
-
mmc_bus_get(host);
if (host->bus_ops && !host->bus_dead) {
if (host->bus_ops->suspend)
@@ -2631,9 +2628,6 @@ int mmc_suspend_host(struct mmc_host *host)
}
mmc_bus_put(host);
- if (!err && !mmc_card_keep_power(host))
- mmc_power_off(host);
-
return err;
}
EXPORT_SYMBOL(mmc_suspend_host);
@@ -2644,39 +2638,20 @@ EXPORT_SYMBOL(mmc_suspend_host);
*/
int mmc_resume_host(struct mmc_host *host)
{
- int err = 0;
+ int err;
mmc_bus_get(host);
if (host->bus_ops && !host->bus_dead) {
- if (!mmc_card_keep_power(host)) {
- mmc_power_up(host);
- mmc_select_voltage(host, host->ocr);
- /*
- * Tell runtime PM core we just powered up the card,
- * since it still believes the card is powered off.
- * Note that currently runtime PM is only enabled
- * for SDIO cards that are MMC_CAP_POWER_OFF_CARD
- */
- if (mmc_card_sdio(host->card) &&
- (host->caps & MMC_CAP_POWER_OFF_CARD)) {
- pm_runtime_disable(&host->card->dev);
- pm_runtime_set_active(&host->card->dev);
- pm_runtime_enable(&host->card->dev);
- }
- }
BUG_ON(!host->bus_ops->resume);
err = host->bus_ops->resume(host);
- if (err) {
+ if (err)
pr_warning("%s: error %d during resume "
"(card was removed?)\n",
mmc_hostname(host), err);
- err = 0;
- }
}
- host->pm_flags &= ~MMC_PM_KEEP_POWER;
mmc_bus_put(host);
- return err;
+ return 0;
}
EXPORT_SYMBOL(mmc_resume_host);
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 913260990829..c8c7135c84b0 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -1494,6 +1494,8 @@ static int mmc_suspend(struct mmc_host *host)
err = mmc_deselect_cards(host);
host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
+ if (!err)
+ mmc_power_off(host);
out:
mmc_release_host(host);
return err;
@@ -1513,6 +1515,8 @@ static int mmc_resume(struct mmc_host *host)
BUG_ON(!host->card);
mmc_claim_host(host);
+ mmc_power_up(host);
+ mmc_select_voltage(host, host->ocr);
err = mmc_init_card(host, host->ocr, host->card);
mmc_release_host(host);
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index aeaae7c3b22b..cacef27b00d1 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -1075,6 +1075,8 @@ static int mmc_sd_suspend(struct mmc_host *host)
if (!mmc_host_is_spi(host))
err = mmc_deselect_cards(host);
host->card->state &= ~MMC_STATE_HIGHSPEED;
+ if (!err)
+ mmc_power_off(host);
mmc_release_host(host);
return err;
@@ -1094,6 +1096,8 @@ static int mmc_sd_resume(struct mmc_host *host)
BUG_ON(!host->card);
mmc_claim_host(host);
+ mmc_power_up(host);
+ mmc_select_voltage(host, host->ocr);
err = mmc_sd_init_card(host, host->ocr, host->card);
mmc_release_host(host);
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index be8cca8d3024..80d89cff7306 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -963,6 +963,9 @@ static int mmc_sdio_suspend(struct mmc_host *host)
mmc_release_host(host);
}
+ if (!err && !mmc_card_keep_power(host))
+ mmc_power_off(host);
+
return err;
}
@@ -976,6 +979,23 @@ static int mmc_sdio_resume(struct mmc_host *host)
/* Basic card reinitialization. */
mmc_claim_host(host);
+ /* Restore power if needed */
+ if (!mmc_card_keep_power(host)) {
+ mmc_power_up(host);
+ mmc_select_voltage(host, host->ocr);
+ /*
+ * Tell runtime PM core we just powered up the card,
+ * since it still believes the card is powered off.
+ * Note that currently runtime PM is only enabled
+ * for SDIO cards that are MMC_CAP_POWER_OFF_CARD
+ */
+ if (host->caps & MMC_CAP_POWER_OFF_CARD) {
+ pm_runtime_disable(&host->card->dev);
+ pm_runtime_set_active(&host->card->dev);
+ pm_runtime_enable(&host->card->dev);
+ }
+ }
+
/* No need to reinitialize powered-resumed nonremovable cards */
if (mmc_card_is_removable(host) || !mmc_card_keep_power(host)) {
sdio_reset(host);
@@ -1013,6 +1033,7 @@ static int mmc_sdio_resume(struct mmc_host *host)
}
}
+ host->pm_flags &= ~MMC_PM_KEEP_POWER;
return err;
}