summaryrefslogtreecommitdiff
path: root/drivers/mmc/host
diff options
context:
space:
mode:
authorJames Hogan <james.hogan@imgtec.com>2011-06-29 09:30:47 +0100
committerChris Ball <cjb@laptop.org>2011-07-20 17:21:06 -0400
commit94dd5b3371c989b32685a00a54cba7bb530f864d (patch)
treef25015abe7cc532eab00d48e8292d437903e7927 /drivers/mmc/host
parent55c5efbc0dbcb20b7f0d264d172ab376494d79a1 (diff)
mmc: dw_mmc: reset FIFO after an error
If an error occurs mid way through a transaction (such as a missing CRC status response after the 2nd block written out of 3), then the FIFO may still contain data which will interfere with the next transaction. Therefore after an error has been detected, reset the fifo using the CTRL register. Signed-off-by: James Hogan <james.hogan@imgtec.com> Acked-by: Will Newton <will.newton@imgtec.com> Tested-by: Jaehoon Chung <jh80.chung@samsung.com> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc/host')
-rw-r--r--drivers/mmc/host/dw_mmc.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 0dac397f37fd..0c839d3338db 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -849,7 +849,7 @@ static void dw_mci_tasklet_func(unsigned long priv)
struct mmc_command *cmd;
enum dw_mci_state state;
enum dw_mci_state prev_state;
- u32 status;
+ u32 status, ctrl;
spin_lock(&host->lock);
@@ -929,6 +929,16 @@ static void dw_mci_tasklet_func(unsigned long priv)
status);
data->error = -EIO;
}
+ /*
+ * After an error, there may be data lingering
+ * in the FIFO, so reset it - doing so
+ * generates a block interrupt, hence setting
+ * the scatter-gather pointer to NULL.
+ */
+ host->sg = NULL;
+ ctrl = mci_readl(host, CTRL);
+ ctrl |= SDMMC_CTRL_FIFO_RESET;
+ mci_writel(host, CTRL, ctrl);
} else {
data->bytes_xfered = data->blocks * data->blksz;
data->error = 0;