diff options
Diffstat (limited to 'drivers/mmc/host/sdhci.c')
-rw-r--r-- | drivers/mmc/host/sdhci.c | 35 |
1 files changed, 34 insertions, 1 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index b2910dc97121..66604499c3cb 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
@@ -57,6 +57,8 @@ static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable); | |||
57 | #ifdef CONFIG_PM_RUNTIME | 57 | #ifdef CONFIG_PM_RUNTIME |
58 | static int sdhci_runtime_pm_get(struct sdhci_host *host); | 58 | static int sdhci_runtime_pm_get(struct sdhci_host *host); |
59 | static int sdhci_runtime_pm_put(struct sdhci_host *host); | 59 | static int sdhci_runtime_pm_put(struct sdhci_host *host); |
60 | static void sdhci_runtime_pm_bus_on(struct sdhci_host *host); | ||
61 | static void sdhci_runtime_pm_bus_off(struct sdhci_host *host); | ||
60 | #else | 62 | #else |
61 | static inline int sdhci_runtime_pm_get(struct sdhci_host *host) | 63 | static inline int sdhci_runtime_pm_get(struct sdhci_host *host) |
62 | { | 64 | { |
@@ -66,6 +68,12 @@ static inline int sdhci_runtime_pm_put(struct sdhci_host *host) | |||
66 | { | 68 | { |
67 | return 0; | 69 | return 0; |
68 | } | 70 | } |
71 | static void sdhci_runtime_pm_bus_on(struct sdhci_host *host) | ||
72 | { | ||
73 | } | ||
74 | static void sdhci_runtime_pm_bus_off(struct sdhci_host *host) | ||
75 | { | ||
76 | } | ||
69 | #endif | 77 | #endif |
70 | 78 | ||
71 | static void sdhci_dumpregs(struct sdhci_host *host) | 79 | static void sdhci_dumpregs(struct sdhci_host *host) |
@@ -191,8 +199,12 @@ static void sdhci_reset(struct sdhci_host *host, u8 mask) | |||
191 | 199 | ||
192 | sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET); | 200 | sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET); |
193 | 201 | ||
194 | if (mask & SDHCI_RESET_ALL) | 202 | if (mask & SDHCI_RESET_ALL) { |
195 | host->clock = 0; | 203 | host->clock = 0; |
204 | /* Reset-all turns off SD Bus Power */ | ||
205 | if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON) | ||
206 | sdhci_runtime_pm_bus_off(host); | ||
207 | } | ||
196 | 208 | ||
197 | /* Wait max 100 ms */ | 209 | /* Wait max 100 ms */ |
198 | timeout = 100; | 210 | timeout = 100; |
@@ -1273,6 +1285,8 @@ static int sdhci_set_power(struct sdhci_host *host, unsigned short power) | |||
1273 | 1285 | ||
1274 | if (pwr == 0) { | 1286 | if (pwr == 0) { |
1275 | sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); | 1287 | sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); |
1288 | if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON) | ||
1289 | sdhci_runtime_pm_bus_off(host); | ||
1276 | return 0; | 1290 | return 0; |
1277 | } | 1291 | } |
1278 | 1292 | ||
@@ -1294,6 +1308,9 @@ static int sdhci_set_power(struct sdhci_host *host, unsigned short power) | |||
1294 | 1308 | ||
1295 | sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); | 1309 | sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); |
1296 | 1310 | ||
1311 | if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON) | ||
1312 | sdhci_runtime_pm_bus_on(host); | ||
1313 | |||
1297 | /* | 1314 | /* |
1298 | * Some controllers need an extra 10ms delay of 10ms before they | 1315 | * Some controllers need an extra 10ms delay of 10ms before they |
1299 | * can apply clock after applying power | 1316 | * can apply clock after applying power |
@@ -2647,6 +2664,22 @@ static int sdhci_runtime_pm_put(struct sdhci_host *host) | |||
2647 | return pm_runtime_put_autosuspend(host->mmc->parent); | 2664 | return pm_runtime_put_autosuspend(host->mmc->parent); |
2648 | } | 2665 | } |
2649 | 2666 | ||
2667 | static void sdhci_runtime_pm_bus_on(struct sdhci_host *host) | ||
2668 | { | ||
2669 | if (host->runtime_suspended || host->bus_on) | ||
2670 | return; | ||
2671 | host->bus_on = true; | ||
2672 | pm_runtime_get_noresume(host->mmc->parent); | ||
2673 | } | ||
2674 | |||
2675 | static void sdhci_runtime_pm_bus_off(struct sdhci_host *host) | ||
2676 | { | ||
2677 | if (host->runtime_suspended || !host->bus_on) | ||
2678 | return; | ||
2679 | host->bus_on = false; | ||
2680 | pm_runtime_put_noidle(host->mmc->parent); | ||
2681 | } | ||
2682 | |||
2650 | int sdhci_runtime_suspend_host(struct sdhci_host *host) | 2683 | int sdhci_runtime_suspend_host(struct sdhci_host *host) |
2651 | { | 2684 | { |
2652 | unsigned long flags; | 2685 | unsigned long flags; |