aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/sdhci.c
diff options
context:
space:
mode:
authorAdrian Hunter <adrian.hunter@intel.com>2013-05-06 05:17:32 -0400
committerChris Ball <cjb@laptop.org>2013-05-26 14:23:23 -0400
commitf0710a557cb17746b09234f01073a2cdafe4f4a5 (patch)
treef56e5fdd5ba030c74e4a0a73959537cf8254c865 /drivers/mmc/host/sdhci.c
parent113a87f868b2f2e086790a68e8b9e41d8f0c3295 (diff)
mmc: sdhci: add ability to stay runtime-resumed if the card is powered up
If card power is dependent on SD bus power then the host controller must not be runtime suspended while the card is powered up. Add the ability to stay runtime-resumed in that case and enable it with a new quirk SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON. Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc/host/sdhci.c')
-rw-r--r--drivers/mmc/host/sdhci.c35
1 files changed, 34 insertions, 1 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 2ea429c27714..c81c2a289dbd 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -58,6 +58,8 @@ static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable);
58#ifdef CONFIG_PM_RUNTIME 58#ifdef CONFIG_PM_RUNTIME
59static int sdhci_runtime_pm_get(struct sdhci_host *host); 59static int sdhci_runtime_pm_get(struct sdhci_host *host);
60static int sdhci_runtime_pm_put(struct sdhci_host *host); 60static int sdhci_runtime_pm_put(struct sdhci_host *host);
61static void sdhci_runtime_pm_bus_on(struct sdhci_host *host);
62static void sdhci_runtime_pm_bus_off(struct sdhci_host *host);
61#else 63#else
62static inline int sdhci_runtime_pm_get(struct sdhci_host *host) 64static inline int sdhci_runtime_pm_get(struct sdhci_host *host)
63{ 65{
@@ -67,6 +69,12 @@ static inline int sdhci_runtime_pm_put(struct sdhci_host *host)
67{ 69{
68 return 0; 70 return 0;
69} 71}
72static void sdhci_runtime_pm_bus_on(struct sdhci_host *host)
73{
74}
75static void sdhci_runtime_pm_bus_off(struct sdhci_host *host)
76{
77}
70#endif 78#endif
71 79
72static void sdhci_dumpregs(struct sdhci_host *host) 80static void sdhci_dumpregs(struct sdhci_host *host)
@@ -192,8 +200,12 @@ static void sdhci_reset(struct sdhci_host *host, u8 mask)
192 200
193 sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET); 201 sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET);
194 202
195 if (mask & SDHCI_RESET_ALL) 203 if (mask & SDHCI_RESET_ALL) {
196 host->clock = 0; 204 host->clock = 0;
205 /* Reset-all turns off SD Bus Power */
206 if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON)
207 sdhci_runtime_pm_bus_off(host);
208 }
197 209
198 /* Wait max 100 ms */ 210 /* Wait max 100 ms */
199 timeout = 100; 211 timeout = 100;
@@ -1268,6 +1280,8 @@ static int sdhci_set_power(struct sdhci_host *host, unsigned short power)
1268 1280
1269 if (pwr == 0) { 1281 if (pwr == 0) {
1270 sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); 1282 sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
1283 if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON)
1284 sdhci_runtime_pm_bus_off(host);
1271 return 0; 1285 return 0;
1272 } 1286 }
1273 1287
@@ -1289,6 +1303,9 @@ static int sdhci_set_power(struct sdhci_host *host, unsigned short power)
1289 1303
1290 sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); 1304 sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
1291 1305
1306 if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON)
1307 sdhci_runtime_pm_bus_on(host);
1308
1292 /* 1309 /*
1293 * Some controllers need an extra 10ms delay of 10ms before they 1310 * Some controllers need an extra 10ms delay of 10ms before they
1294 * can apply clock after applying power 1311 * can apply clock after applying power
@@ -2625,6 +2642,22 @@ static int sdhci_runtime_pm_put(struct sdhci_host *host)
2625 return pm_runtime_put_autosuspend(host->mmc->parent); 2642 return pm_runtime_put_autosuspend(host->mmc->parent);
2626} 2643}
2627 2644
2645static void sdhci_runtime_pm_bus_on(struct sdhci_host *host)
2646{
2647 if (host->runtime_suspended || host->bus_on)
2648 return;
2649 host->bus_on = true;
2650 pm_runtime_get_noresume(host->mmc->parent);
2651}
2652
2653static void sdhci_runtime_pm_bus_off(struct sdhci_host *host)
2654{
2655 if (host->runtime_suspended || !host->bus_on)
2656 return;
2657 host->bus_on = false;
2658 pm_runtime_put_noidle(host->mmc->parent);
2659}
2660
2628int sdhci_runtime_suspend_host(struct sdhci_host *host) 2661int sdhci_runtime_suspend_host(struct sdhci_host *host)
2629{ 2662{
2630 unsigned long flags; 2663 unsigned long flags;