summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTony Lin <tony.lin@freescale.com>2011-08-30 15:09:05 +0800
committerTony Lin <tony.lin@freescale.com>2011-08-31 18:18:06 +0800
commit1c6f014e61a50e14359183621c2f31d25675d605 (patch)
treea35dc9a5c5f97ddc5210014090a247bf58dd257f
parent5a4aeb9f6c445c9cbf1a80c878e38e685d765268 (diff)
ENGR00155562 [eSDHC]fix DDTS ENGcm03648
fix eSDHC errata 'DDTS ENGcm03648' if it's command with busy, we should poll data0 signal until it's high which means bus is idle. Signed-off-by: Tony Lin <tony.lin@freescale.com>
-rw-r--r--drivers/mmc/host/mx_sdhci.c27
1 files changed, 26 insertions, 1 deletions
diff --git a/drivers/mmc/host/mx_sdhci.c b/drivers/mmc/host/mx_sdhci.c
index 6b3ce8d5f92a..4f709db75115 100644
--- a/drivers/mmc/host/mx_sdhci.c
+++ b/drivers/mmc/host/mx_sdhci.c
@@ -1282,7 +1282,7 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
writel(prot, host->ioaddr + SDHCI_HOST_CONTROL);
mmiowb();
- exit_unlock:
+
spin_unlock_irqrestore(&host->lock, flags);
}
@@ -1352,6 +1352,31 @@ static void sdhci_finish_worker(struct work_struct *work)
mrq = host->mrq;
+ if (!mrq->cmd->data && !mrq->cmd->error
+ && (mrq->cmd->flags & MMC_RSP_BUSY)) {
+ int timeout = 250000;
+
+ /* DDTS ENGcm03648.
+ * if it's a cmd with busy, we should disable auto clock
+ * gate and we need to poll dat0 until it's high which means
+ * data bus is idle.
+ * This sdhci driver disable all auto clock gate bits by
+ * default, so we skip changing auto clock gate bits.
+ * Be careful if auto clock gate bits logic is changed!
+ * Poll on DATA0 line for cmd with busy signal for 250 ms
+ */
+ while (timeout > 0 && !(readl(host->ioaddr + \
+ SDHCI_PRESENT_STATE) & SDHCI_DAT0_IDLE)) {
+ udelay(1);
+ timeout--;
+ }
+
+ if (timeout <= 0) {
+ DBG(KERN_ERR "Timeout waiting for DAT0 to go high!\n");
+ mrq->cmd->error = -ETIMEDOUT;
+ }
+ }
+
/*
* The controller needs a reset of internal state machines
* upon error conditions.