aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mmc/host/sdhci.c35
-rw-r--r--include/linux/mmc/sdhci.h2
2 files changed, 36 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;
diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h
index b838ffc49e4a..ba35bdb87d99 100644
--- a/include/linux/mmc/sdhci.h
+++ b/include/linux/mmc/sdhci.h
@@ -95,6 +95,7 @@ struct sdhci_host {
95/* The system physically doesn't support 1.8v, even if the host does */ 95/* The system physically doesn't support 1.8v, even if the host does */
96#define SDHCI_QUIRK2_NO_1_8_V (1<<2) 96#define SDHCI_QUIRK2_NO_1_8_V (1<<2)
97#define SDHCI_QUIRK2_PRESET_VALUE_BROKEN (1<<3) 97#define SDHCI_QUIRK2_PRESET_VALUE_BROKEN (1<<3)
98#define SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON (1<<4)
98 99
99 int irq; /* Device IRQ */ 100 int irq; /* Device IRQ */
100 void __iomem *ioaddr; /* Mapped address */ 101 void __iomem *ioaddr; /* Mapped address */
@@ -139,6 +140,7 @@ struct sdhci_host {
139 u8 pwr; /* Current voltage */ 140 u8 pwr; /* Current voltage */
140 141
141 bool runtime_suspended; /* Host is runtime suspended */ 142 bool runtime_suspended; /* Host is runtime suspended */
143 bool bus_on; /* Bus power prevents runtime suspend */
142 144
143 struct mmc_request *mrq; /* Current request */ 145 struct mmc_request *mrq; /* Current request */
144 struct mmc_command *cmd; /* Current command */ 146 struct mmc_command *cmd; /* Current command */