aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorAdrian Hunter <adrian.hunter@intel.com>2013-05-06 05:17:32 -0400
committerNitin Garg <nitin.garg@freescale.com>2014-04-16 09:47:08 -0400
commitf2431fdb2f4880e1884bc5a4e5d4b7ab147088b8 (patch)
treee97715df26aae44ae92a1285e51121bb1fb3a34c /drivers/mmc
parent1401d4c84b71ba643fbbdbb17bab4c17aa6aaaf5 (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> (cherry picked from commit f0710a557cb17746b09234f01073a2cdafe4f4a5)
Diffstat (limited to 'drivers/mmc')
-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 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
58static int sdhci_runtime_pm_get(struct sdhci_host *host); 58static int sdhci_runtime_pm_get(struct sdhci_host *host);
59static int sdhci_runtime_pm_put(struct sdhci_host *host); 59static int sdhci_runtime_pm_put(struct sdhci_host *host);
60static void sdhci_runtime_pm_bus_on(struct sdhci_host *host);
61static void sdhci_runtime_pm_bus_off(struct sdhci_host *host);
60#else 62#else
61static inline int sdhci_runtime_pm_get(struct sdhci_host *host) 63static 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}
71static void sdhci_runtime_pm_bus_on(struct sdhci_host *host)
72{
73}
74static void sdhci_runtime_pm_bus_off(struct sdhci_host *host)
75{
76}
69#endif 77#endif
70 78
71static void sdhci_dumpregs(struct sdhci_host *host) 79static 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
2667static 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
2675static 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
2650int sdhci_runtime_suspend_host(struct sdhci_host *host) 2683int sdhci_runtime_suspend_host(struct sdhci_host *host)
2651{ 2684{
2652 unsigned long flags; 2685 unsigned long flags;