diff options
author | Tony Lin <tony.lin@freescale.com> | 2011-08-30 15:09:05 +0800 |
---|---|---|
committer | Tony Lin <tony.lin@freescale.com> | 2011-08-31 18:18:06 +0800 |
commit | 1c6f014e61a50e14359183621c2f31d25675d605 (patch) | |
tree | a35dc9a5c5f97ddc5210014090a247bf58dd257f | |
parent | 5a4aeb9f6c445c9cbf1a80c878e38e685d765268 (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.c | 27 |
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. |