summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAisheng.Dong <b29396@freescale.com>2010-08-30 14:38:33 +0800
committerAisheng.Dong <b29396@freescale.com>2010-08-30 14:48:56 +0800
commita5a62255fd11a6aaa3e843f564307682fa1a6645 (patch)
tree477766b8659111ae6b55f7016711aa725226ad89
parent06a918654992aab5435af4c8195ea43abcc89826 (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.c17
-rw-r--r--drivers/mmc/host/mx_sdhci.h1
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