diff options
Diffstat (limited to 'drivers/mmc/host/sdhci.c')
-rw-r--r-- | drivers/mmc/host/sdhci.c | 49 |
1 files changed, 46 insertions, 3 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index de0bcb9149d2..f9f22a2fe0dd 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1430,15 +1430,55 @@ static int sdhci_disable(struct mmc_host *mmc) { struct sdhci_host *host = mmc_priv(mmc); - if (host->cpu_dma_latency_us) - pm_qos_update_request(&host->pm_qos_req_dma, + if (host->cpu_dma_latency_us) { + /* + * In performance mode, release QoS vote after a timeout to + * make sure back-to-back requests don't suffer from latencies + * that are involved to wake CPU from low power modes in cases + * where the CPU goes into low power mode as soon as QoS vote is + * released. + */ + if (host->power_policy == SDHCI_PERFORMANCE_MODE) + pm_qos_update_request_timeout(&host->pm_qos_req_dma, + host->cpu_dma_latency_us, + host->pm_qos_timeout_us); + else + pm_qos_update_request(&host->pm_qos_req_dma, PM_QOS_DEFAULT_VALUE); + } + if (host->ops->platform_bus_voting) host->ops->platform_bus_voting(host, 0); return 0; } +static inline void sdhci_update_power_policy(struct sdhci_host *host, + enum sdhci_power_policy policy) +{ + host->power_policy = policy; +} + +static int sdhci_notify_load(struct mmc_host *mmc, enum mmc_load state) +{ + int err = 0; + struct sdhci_host *host = mmc_priv(mmc); + + switch (state) { + case MMC_LOAD_HIGH: + sdhci_update_power_policy(host, SDHCI_PERFORMANCE_MODE); + break; + case MMC_LOAD_LOW: + sdhci_update_power_policy(host, SDHCI_POWER_SAVE_MODE); + break; + default: + err = -EINVAL; + break; + } + + return err; +} + static bool sdhci_check_state(struct sdhci_host *host) { if (!host->clock || !host->pwr) @@ -2345,6 +2385,7 @@ static const struct mmc_host_ops sdhci_ops = { .card_busy = sdhci_card_busy, .enable = sdhci_enable, .disable = sdhci_disable, + .notify_load = sdhci_notify_load, }; /*****************************************************************************\ @@ -3588,9 +3629,11 @@ int sdhci_add_host(struct sdhci_host *host) mmiowb(); - if (host->cpu_dma_latency_us) + if (host->cpu_dma_latency_us) { + host->pm_qos_timeout_us = 10000; /* default value */ pm_qos_add_request(&host->pm_qos_req_dma, PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE); + } mmc_add_host(mmc); pr_info("%s: SDHCI controller on %s [%s] using %s\n", |