diff options
author | Dong Aisheng <aisheng.dong@nxp.com> | 2016-02-05 19:55:28 +0800 |
---|---|---|
committer | Dong Aisheng <aisheng.dong@nxp.com> | 2016-02-16 15:49:16 +0800 |
commit | 89c224b34d3a63797d956969c2fdf4ccb7ff25bf (patch) | |
tree | b3fb9596740ab47d13aee1ab3af1cc7a8d47ecb0 | |
parent | cfcd9c369186ddc8c9e25e7c7573f91a4516449d (diff) |
MLK-12391-2 mmc: sdhci: add standard hw auto retuning support
If HW supports SDHCI_TUNING_MODE_3 which is auto retuning, we won't
retune during runtime suspend and resume, instead we use Re-tuning
Request signaled via SDHCI_INT_RETUNE interrupt to do retuning and
hw auto retuning during data transfer to guarantee the signal sample
window correction.
This can avoid a mass of repeatly retuning during small file system
data access and improve the performance.
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
-rw-r--r-- | drivers/mmc/host/sdhci.c | 18 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci.h | 3 |
2 files changed, 17 insertions, 4 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 35cb4535a150..b0c63b92366e 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -240,6 +240,9 @@ static void sdhci_init(struct sdhci_host *host, int soft) SDHCI_INT_TIMEOUT | SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE; + if (host->tuning_mode == SDHCI_TUNING_MODE_3) + host->ier |= SDHCI_INT_RETUNE; + sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); @@ -2599,6 +2602,9 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) pr_err("%s: Card is consuming too much power!\n", mmc_hostname(host->mmc)); + if (intmask & SDHCI_INT_RETUNE) + mmc_retune_needed(host->mmc); + if (intmask & SDHCI_INT_CARD_INT) { if (host->mmc->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD) { sdhci_enable_sdio_irq_nolock(host, false); @@ -2707,8 +2713,10 @@ int sdhci_suspend_host(struct sdhci_host *host) { sdhci_disable_card_detection(host); - mmc_retune_timer_stop(host->mmc); - mmc_retune_needed(host->mmc); + if (host->tuning_mode == SDHCI_TUNING_MODE_1) { + mmc_retune_timer_stop(host->mmc); + mmc_retune_needed(host->mmc); + } if (!device_may_wakeup(mmc_dev(host->mmc))) { host->ier = 0; @@ -2794,8 +2802,10 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host) { unsigned long flags; - mmc_retune_timer_stop(host->mmc); - mmc_retune_needed(host->mmc); + if (host->tuning_mode == SDHCI_TUNING_MODE_1) { + mmc_retune_timer_stop(host->mmc); + mmc_retune_needed(host->mmc); + } spin_lock_irqsave(&host->lock, flags); host->ier &= SDHCI_INT_CARD_INT; diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index e934a599340c..4a3eab6408fb 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -128,6 +128,7 @@ #define SDHCI_INT_CARD_INSERT 0x00000040 #define SDHCI_INT_CARD_REMOVE 0x00000080 #define SDHCI_INT_CARD_INT 0x00000100 +#define SDHCI_INT_RETUNE 0x00001000 #define SDHCI_INT_ERROR 0x00008000 #define SDHCI_INT_TIMEOUT 0x00010000 #define SDHCI_INT_CRC 0x00020000 @@ -508,6 +509,8 @@ struct sdhci_host { unsigned int tuning_count; /* Timer count for re-tuning */ unsigned int tuning_mode; /* Re-tuning mode supported by host */ #define SDHCI_TUNING_MODE_1 0 +#define SDHCI_TUNING_MODE_2 1 +#define SDHCI_TUNING_MODE_3 2 unsigned long private[0] ____cacheline_aligned; }; |