diff options
Diffstat (limited to 'drivers/mmc/core/sdio.c')
-rw-r--r-- | drivers/mmc/core/sdio.c | 54 |
1 files changed, 45 insertions, 9 deletions
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index f332c52968b7..c3ad1058cd31 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -10,6 +10,7 @@ */ #include <linux/err.h> +#include <linux/pm_runtime.h> #include <linux/mmc/host.h> #include <linux/mmc/card.h> @@ -456,7 +457,6 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, return -ENOENT; card = oldcard; - return 0; } if (card->type == MMC_TYPE_SD_COMBO) { @@ -546,6 +546,11 @@ static void mmc_sdio_detect(struct mmc_host *host) BUG_ON(!host); BUG_ON(!host->card); + /* Make sure card is powered before detecting it */ + err = pm_runtime_get_sync(&host->card->dev); + if (err < 0) + goto out; + mmc_claim_host(host); /* @@ -555,6 +560,7 @@ static void mmc_sdio_detect(struct mmc_host *host) mmc_release_host(host); +out: if (err) { mmc_sdio_remove(host); @@ -562,6 +568,9 @@ static void mmc_sdio_detect(struct mmc_host *host) mmc_detach_bus(host); mmc_release_host(host); } + + /* Tell PM core that we're done */ + pm_runtime_put(&host->card->dev); } /* @@ -614,14 +623,6 @@ static int mmc_sdio_resume(struct mmc_host *host) mmc_claim_host(host); err = mmc_sdio_init_card(host, host->ocr, host->card, (host->pm_flags & MMC_PM_KEEP_POWER)); - if (!err) { - /* We may have switched to 1-bit mode during suspend. */ - err = sdio_enable_4bit_bus(host->card); - if (err > 0) { - mmc_set_bus_width(host, MMC_BUS_WIDTH_4); - err = 0; - } - } if (!err && host->sdio_irqs) mmc_signal_sdio_irq(host); mmc_release_host(host); @@ -647,11 +648,29 @@ static int mmc_sdio_resume(struct mmc_host *host) return err; } +static int mmc_sdio_power_restore(struct mmc_host *host) +{ + int ret; + + BUG_ON(!host); + BUG_ON(!host->card); + + mmc_claim_host(host); + ret = mmc_sdio_init_card(host, host->ocr, host->card, + (host->pm_flags & MMC_PM_KEEP_POWER)); + if (!ret && host->sdio_irqs) + mmc_signal_sdio_irq(host); + mmc_release_host(host); + + return ret; +} + static const struct mmc_bus_ops mmc_sdio_ops = { .remove = mmc_sdio_remove, .detect = mmc_sdio_detect, .suspend = mmc_sdio_suspend, .resume = mmc_sdio_resume, + .power_restore = mmc_sdio_power_restore, }; @@ -699,6 +718,18 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr) card = host->card; /* + * Let runtime PM core know our card is active + */ + err = pm_runtime_set_active(&card->dev); + if (err) + goto remove; + + /* + * Enable runtime PM for this card + */ + pm_runtime_enable(&card->dev); + + /* * The number of functions on the card is encoded inside * the ocr. */ @@ -712,6 +743,11 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr) err = sdio_init_func(host->card, i + 1); if (err) goto remove; + + /* + * Enable Runtime PM for this func + */ + pm_runtime_enable(&card->sdio_func[i]->dev); } mmc_release_host(host); |