Skip to content

Commit

Permalink
mmc: sdhci: add standard hw auto retuning support
Browse files Browse the repository at this point in the history
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 <[email protected]>
Acked-by: Adrian Hunter <[email protected]>
Signed-off-by: Ulf Hansson <[email protected]>
  • Loading branch information
Dong Aisheng authored and storulf committed Jul 25, 2016
1 parent 152f05c commit f37b20e
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 3 deletions.
15 changes: 12 additions & 3 deletions drivers/mmc/host/sdhci.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -2787,7 +2794,8 @@ 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_3)
mmc_retune_needed(host->mmc);

if (!device_may_wakeup(mmc_dev(host->mmc))) {
host->ier = 0;
Expand Down Expand Up @@ -2848,7 +2856,8 @@ 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_3)
mmc_retune_needed(host->mmc);

spin_lock_irqsave(&host->lock, flags);
host->ier &= SDHCI_INT_CARD_INT;
Expand Down
3 changes: 3 additions & 0 deletions drivers/mmc/host/sdhci.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
};
Expand Down

0 comments on commit f37b20e

Please sign in to comment.