#ifdef CONFIG_PM_RUNTIME
static int sdhci_runtime_pm_get(struct sdhci_host *host);
static int sdhci_runtime_pm_put(struct sdhci_host *host);
+static void sdhci_runtime_pm_bus_on(struct sdhci_host *host);
+static void sdhci_runtime_pm_bus_off(struct sdhci_host *host);
#else
static inline int sdhci_runtime_pm_get(struct sdhci_host *host)
{
{
return 0;
}
+static void sdhci_runtime_pm_bus_on(struct sdhci_host *host)
+{
+}
+static void sdhci_runtime_pm_bus_off(struct sdhci_host *host)
+{
+}
#endif
static void sdhci_dumpregs(struct sdhci_host *host)
sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET);
- if (mask & SDHCI_RESET_ALL)
+ if (mask & SDHCI_RESET_ALL) {
host->clock = 0;
+ /* Reset-all turns off SD Bus Power */
+ if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON)
+ sdhci_runtime_pm_bus_off(host);
+ }
/* Wait max 100 ms */
timeout = 100;
if (pwr == 0) {
sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
+ if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON)
+ sdhci_runtime_pm_bus_off(host);
return 0;
}
sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
+ if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON)
+ sdhci_runtime_pm_bus_on(host);
+
/*
* Some controllers need an extra 10ms delay of 10ms before they
* can apply clock after applying power
return pm_runtime_put_autosuspend(host->mmc->parent);
}
+static void sdhci_runtime_pm_bus_on(struct sdhci_host *host)
+{
+ if (host->runtime_suspended || host->bus_on)
+ return;
+ host->bus_on = true;
+ pm_runtime_get_noresume(host->mmc->parent);
+}
+
+static void sdhci_runtime_pm_bus_off(struct sdhci_host *host)
+{
+ if (host->runtime_suspended || !host->bus_on)
+ return;
+ host->bus_on = false;
+ pm_runtime_put_noidle(host->mmc->parent);
+}
+
int sdhci_runtime_suspend_host(struct sdhci_host *host)
{
unsigned long flags;
/* The system physically doesn't support 1.8v, even if the host does */
#define SDHCI_QUIRK2_NO_1_8_V (1<<2)
#define SDHCI_QUIRK2_PRESET_VALUE_BROKEN (1<<3)
+#define SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON (1<<4)
int irq; /* Device IRQ */
void __iomem *ioaddr; /* Mapped address */
u8 pwr; /* Current voltage */
bool runtime_suspended; /* Host is runtime suspended */
+ bool bus_on; /* Bus power prevents runtime suspend */
struct mmc_request *mrq; /* Current request */
struct mmc_command *cmd; /* Current command */