summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorDong Aisheng <aisheng.dong@nxp.com>2016-02-05 19:55:28 +0800
committerDong Aisheng <aisheng.dong@nxp.com>2016-02-16 18:02:45 +0800
commit7e9b6c386bf2ba9b39305ae982742936e886cdf7 (patch)
treea8b76329ce2439a8ead98b59a376bea8a5c2b60f /drivers
parente0011f5cbf4ec856c9b8bb47fdf1099be5af8758 (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> (cherry picked from commit 89c224b34d3a63797d956969c2fdf4ccb7ff25bf)
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mmc/host/sdhci.c18
-rw-r--r--drivers/mmc/host/sdhci.h3
2 files changed, 17 insertions, 4 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 529d9edc3b0b..04861ba0ed21 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;
@@ -2788,8 +2796,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;
};