summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnuj Aggarwal <anuj.aggarwal@ti.com>2010-03-08 15:05:58 +0530
committerKevin Hilman <khilman@deeprootsystems.com>2010-05-06 15:02:02 -0700
commita7e05065f562ae347db36b0ef644525cd1e89ecd (patch)
tree02a0144064822f45639462b2ba12559dd32032c9
parentd154fed7234331dc29240deb04f92f382000e66b (diff)
davinci: edma: clear interrupt status for interrupt enabled channels only
Currently, the ISR in the EDMA driver clears the pending interrupt for all channels without regard to whether that channel has a registered callback or not. This causes problems for devices like DM355/DM365 where the multimedia accelerator uses EDMA by polling on the interrupt pending bits of some of the EDMA channels. Since these channels are actually allocated through the Linux EDMA driver (by an out-of-kernel module), the same shadow region is used by Linux and accelerator. There a race between the Linux ISR and the polling code running on the accelerator on the IPR (interrupt pending register). This patch fixes the issue by making the ISR clear the interrupts only for those channels which have interrupt enabled. The channels which are allocated for the purpose of being polled on by the accelerator will not have a callback function provided and so will not have IER (interrupt enable register) bits set. Tested on DM365 and OMAP-L137/L138 with audio and MMC/SD (as EDMA users). Signed-off-by: Anuj Aggarwal <anuj.aggarwal@ti.com> Signed-off-by: Sekhar Nori <nsekhar@ti.com> CC: Archith John Bency <archith@ti.com> Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
-rw-r--r--arch/arm/mach-davinci/dma.c11
1 files changed, 7 insertions, 4 deletions
diff --git a/arch/arm/mach-davinci/dma.c b/arch/arm/mach-davinci/dma.c
index 53137387aee1..0bf290befa23 100644
--- a/arch/arm/mach-davinci/dma.c
+++ b/arch/arm/mach-davinci/dma.c
@@ -359,9 +359,11 @@ static irqreturn_t dma_irq_handler(int irq, void *data)
while (1) {
int j;
- if (edma_shadow0_read_array(ctlr, SH_IPR, 0))
+ if (edma_shadow0_read_array(ctlr, SH_IPR, 0) &
+ edma_shadow0_read_array(ctlr, SH_IER, 0))
j = 0;
- else if (edma_shadow0_read_array(ctlr, SH_IPR, 1))
+ else if (edma_shadow0_read_array(ctlr, SH_IPR, 1) &
+ edma_shadow0_read_array(ctlr, SH_IER, 1))
j = 1;
else
break;
@@ -369,8 +371,9 @@ static irqreturn_t dma_irq_handler(int irq, void *data)
edma_shadow0_read_array(ctlr, SH_IPR, j));
for (i = 0; i < 32; i++) {
int k = (j << 5) + i;
- if (edma_shadow0_read_array(ctlr, SH_IPR, j) &
- (1 << i)) {
+ if ((edma_shadow0_read_array(ctlr, SH_IPR, j) & BIT(i))
+ && (edma_shadow0_read_array(ctlr,
+ SH_IER, j) & BIT(i))) {
/* Clear the corresponding IPR bits */
edma_shadow0_write_array(ctlr, SH_ICR, j,
(1 << i));