diff options
author | Aisheng.Dong <b29396@freescale.com> | 2010-08-30 14:38:33 +0800 |
---|---|---|
committer | Aisheng.Dong <b29396@freescale.com> | 2010-08-30 14:48:56 +0800 |
commit | a5a62255fd11a6aaa3e843f564307682fa1a6645 (patch) | |
tree | 477766b8659111ae6b55f7016711aa725226ad89 | |
parent | 06a918654992aab5435af4c8195ea43abcc89826 (diff) |
ENGR00126800 esdhc: fix sdio interrupt may be lost issue
Due to the SDIO interrupt of esdhc is implemented in edge trigger
mode, the interrupt may be lost in some critical cases.
This may cause SDIO cards such as WiFi has the possiblity to hang
during a long-term transferring.
Using D3CD to manually driver the HW to re-sample the SDIO interrupt
on bus one more time to guarantee the SDIO interrupt signal sent
from card during the interrupt signal disabled period will not
be lost.
Signed-off-by: Aisheng.Dong <b29396@freescale.com>
-rw-r--r-- | drivers/mmc/host/mx_sdhci.c | 17 | ||||
-rw-r--r-- | drivers/mmc/host/mx_sdhci.h | 1 |
2 files changed, 16 insertions, 2 deletions
diff --git a/drivers/mmc/host/mx_sdhci.c b/drivers/mmc/host/mx_sdhci.c index 788965b42fc6..0a4970504463 100644 --- a/drivers/mmc/host/mx_sdhci.c +++ b/drivers/mmc/host/mx_sdhci.c @@ -1106,12 +1106,11 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable) goto exit_unlock; } - ier = readl(host->ioaddr + SDHCI_SIGNAL_ENABLE); + ier = readl(host->ioaddr + SDHCI_INT_ENABLE); prot = readl(host->ioaddr + SDHCI_HOST_CONTROL); if (enable) { ier |= SDHCI_INT_CARD_INT; - prot |= SDHCI_CTRL_D3CD; present = readl(host->ioaddr + SDHCI_PRESENT_STATE); if ((present & SDHCI_CARD_INT_MASK) != SDHCI_CARD_INT_ID) writel(SDHCI_INT_CARD_INT, @@ -1122,8 +1121,22 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable) } writel(prot, host->ioaddr + SDHCI_HOST_CONTROL); + writel(ier, host->ioaddr + SDHCI_INT_ENABLE); writel(ier, host->ioaddr + SDHCI_SIGNAL_ENABLE); + /* + * Using D3CD to manually driver the HW to re-sample the SDIO interrupt + * on bus one more time to guarantee the SDIO interrupt signal sent + * from card during the interrupt signal disabled period will not + * be lost. + */ + prot |= SDHCI_CTRL_CDSS; + writel(prot, host->ioaddr + SDHCI_HOST_CONTROL); + prot &= ~SDHCI_CTRL_D3CD; + writel(prot, host->ioaddr + SDHCI_HOST_CONTROL); + prot |= SDHCI_CTRL_D3CD; + writel(prot, host->ioaddr + SDHCI_HOST_CONTROL); + mmiowb(); exit_unlock: spin_unlock_irqrestore(&host->lock, flags); diff --git a/drivers/mmc/host/mx_sdhci.h b/drivers/mmc/host/mx_sdhci.h index a212cb2bb03a..83d02975ecd1 100644 --- a/drivers/mmc/host/mx_sdhci.h +++ b/drivers/mmc/host/mx_sdhci.h @@ -69,6 +69,7 @@ #define SDHCI_CTRL_4BITBUS 0x00000002 #define SDHCI_CTRL_8BITBUS 0x00000004 #define SDHCI_CTRL_HISPD 0x00000004 +#define SDHCI_CTRL_CDSS 0x80 #define SDHCI_CTRL_DMA_MASK 0x18 #define SDHCI_CTRL_SDMA 0x00 #define SDHCI_CTRL_ADMA1 0x08 |