aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIdo Yariv <ido@wizery.com>2012-03-11 17:39:58 -0400
committerChris Ball <cjb@laptop.org>2012-03-27 12:20:11 -0400
commitbe7b5622e608189894c2c440c3fb0138f122071f (patch)
treea8ebaad47cc471e1c01d66df697d93aa57d8cd54
parent1f84b71b3fa834faa87e14c8dc5d5a7c1fa084e8 (diff)
mmc: davinci: Eliminate spurious interrupts
The davinci mmc interrupt handler fills the fifo, as long as the DXRDY or DRRDY bits are set in the status register. If interrupts fire during this loop, they will be handled by the handler, but the interrupt controller will still buffer these. As a result, the handler will be called again to serve these needlessly. In order to avoid these spurious interrupts, keep interrupts masked while filling the fifo. Signed-off-by: Ido Yariv <ido@wizery.com> Tested-by: Rajashekhara, Sudhakar <sudhakar.raj@ti.com> Signed-off-by: Chris Ball <cjb@laptop.org>
-rw-r--r--drivers/mmc/host/davinci_mmc.c33
1 files changed, 27 insertions, 6 deletions
diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c
index 8de9c9bdba0b..1e076fb06ac3 100644
--- a/drivers/mmc/host/davinci_mmc.c
+++ b/drivers/mmc/host/davinci_mmc.c
@@ -1009,12 +1009,33 @@ static irqreturn_t mmc_davinci_irq(int irq, void *dev_id)
1009 * by read. So, it is not unbouned loop even in the case of 1009 * by read. So, it is not unbouned loop even in the case of
1010 * non-dma. 1010 * non-dma.
1011 */ 1011 */
1012 while (host->bytes_left && (status & (MMCST0_DXRDY | MMCST0_DRRDY))) { 1012 if (host->bytes_left && (status & (MMCST0_DXRDY | MMCST0_DRRDY))) {
1013 davinci_fifo_data_trans(host, rw_threshold); 1013 unsigned long im_val;
1014 status = readl(host->base + DAVINCI_MMCST0); 1014
1015 if (!status) 1015 /*
1016 break; 1016 * If interrupts fire during the following loop, they will be
1017 qstatus |= status; 1017 * handled by the handler, but the PIC will still buffer these.
1018 * As a result, the handler will be called again to serve these
1019 * needlessly. In order to avoid these spurious interrupts,
1020 * keep interrupts masked during the loop.
1021 */
1022 im_val = readl(host->base + DAVINCI_MMCIM);
1023 writel(0, host->base + DAVINCI_MMCIM);
1024
1025 do {
1026 davinci_fifo_data_trans(host, rw_threshold);
1027 status = readl(host->base + DAVINCI_MMCST0);
1028 qstatus |= status;
1029 } while (host->bytes_left &&
1030 (status & (MMCST0_DXRDY | MMCST0_DRRDY)));
1031
1032 /*
1033 * If an interrupt is pending, it is assumed it will fire when
1034 * it is unmasked. This assumption is also taken when the MMCIM
1035 * is first set. Otherwise, writing to MMCIM after reading the
1036 * status is race-prone.
1037 */
1038 writel(im_val, host->base + DAVINCI_MMCIM);
1018 } 1039 }
1019 1040
1020 if (qstatus & MMCST0_DATDNE) { 1041 if (qstatus & MMCST0_DATDNE) {