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 repeatedly retuning during small file system data access and improve the performance. Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com> Acked-by: Adrian Hunter <adrian.hunter@intel.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
This commit is contained in:
Родитель
152f05c783
Коммит
f37b20ebc4
|
@ -229,6 +229,10 @@ 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_2 ||
|
||||
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);
|
||||
|
||||
|
@ -2673,6 +2677,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) {
|
||||
sdhci_enable_sdio_irq_nolock(host, false);
|
||||
host->thread_isr |= SDHCI_INT_CARD_INT;
|
||||
|
@ -2682,7 +2689,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
|
|||
intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE |
|
||||
SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK |
|
||||
SDHCI_INT_ERROR | SDHCI_INT_BUS_POWER |
|
||||
SDHCI_INT_CARD_INT);
|
||||
SDHCI_INT_RETUNE | SDHCI_INT_CARD_INT);
|
||||
|
||||
if (intmask) {
|
||||
unexpected |= intmask;
|
||||
|
@ -2787,6 +2794,7 @@ int sdhci_suspend_host(struct sdhci_host *host)
|
|||
sdhci_disable_card_detection(host);
|
||||
|
||||
mmc_retune_timer_stop(host->mmc);
|
||||
if (host->tuning_mode != SDHCI_TUNING_MODE_3)
|
||||
mmc_retune_needed(host->mmc);
|
||||
|
||||
if (!device_may_wakeup(mmc_dev(host->mmc))) {
|
||||
|
@ -2848,6 +2856,7 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host)
|
|||
unsigned long flags;
|
||||
|
||||
mmc_retune_timer_stop(host->mmc);
|
||||
if (host->tuning_mode != SDHCI_TUNING_MODE_3)
|
||||
mmc_retune_needed(host->mmc);
|
||||
|
||||
spin_lock_irqsave(&host->lock, flags);
|
||||
|
|
|
@ -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
|
||||
|
@ -518,6 +519,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;
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче