[linux-yocto] [PATCH 44/89] drivers/dma: Corrected IRQ line mixup.
Paul Butler
butler.paul at gmail.com
Sun Oct 27 12:33:09 PDT 2013
From: Anders Berg <anders.berg at lsi.com>
Driver was picking up the wrong interrupt line for the error status interrupt.
A mixup between the BUSY (not used) and ERROR interrupts. This commit also
makes the error interupt service routine clear the error before returning.
Signed-off-by: Anders Berg <anders.berg at lsi.com>
---
arch/arm/boot/dts/axm55xx.dts | 1 -
drivers/dma/lsi-dma32.c | 25 ++++++++++++++-----------
drivers/dma/lsi-dma32.h | 5 +++++
3 files changed, 19 insertions(+), 12 deletions(-)
diff --git a/arch/arm/boot/dts/axm55xx.dts b/arch/arm/boot/dts/axm55xx.dts
index 925e3b2..5ba1824 100644
--- a/arch/arm/boot/dts/axm55xx.dts
+++ b/arch/arm/boot/dts/axm55xx.dts
@@ -210,7 +210,6 @@
};
gpdma at 2020141000 {
- status = "disabled";
compatible = "lsi,dma32";
reg = <0x20 0x20141000 0x00 0x1000>;
interrupts = <0 64 4>, /* busy */
diff --git a/drivers/dma/lsi-dma32.c b/drivers/dma/lsi-dma32.c
index b5d25d8..f2ec6c6 100644
--- a/drivers/dma/lsi-dma32.c
+++ b/drivers/dma/lsi-dma32.c
@@ -102,19 +102,14 @@ static void soft_reset(struct gpdma_engine *engine)
wr32(GPDMA_MAGIC, engine->gbase + SOFT_RESET);
wmb();
- /*
- * Set has to be done twice???
- * Yep! According to LSI code it has to be done twice,
- * have no idea why.
- */
cfg = (engine->pool.phys & 0xfff00000) | GEN_CONFIG_EXT_MEM;
+
if (engine->chip->flags & LSIDMA_EDGE_INT) {
for (i = 0; i < engine->chip->num_channels; i++)
cfg |= GEN_CONFIG_INT_EDGE(i);
engine_dbg(engine, "Using edge-triggered interrupts\n");
}
wr32(cfg, engine->gbase + GEN_CONFIG);
- wr32(cfg, engine->gbase + GEN_CONFIG);
engine_dbg(engine, "engine->desc.phys & 0xfff00000 == %llx\n",
(engine->pool.phys & 0xfff00000));
@@ -327,9 +322,18 @@ static irqreturn_t gpdma_isr_err(int irqno, void *_engine)
{
struct gpdma_engine *engine = _engine;
u32 status = rd32(engine->gbase + GEN_STAT);
+ u32 ch = (status & GEN_STAT_CH0_ERROR) ? 0 : 1;
+ struct gpdma_channel *dmac = &engine->channel[ch];
+
+ if (0 == (status & (GEN_STAT_CH0_ERROR | GEN_STAT_CH1_ERROR)))
+ return IRQ_NONE;
+
+ /* Read the channel status bits and dump the error */
+ status = rd32(dmac->base + DMA_STATUS);
+ pr_err("dma: channel%d error %08x\n", dmac->channel, status);
+ /* Clear the error indication */
+ wr32(DMA_STATUS_ERROR, dmac->base+DMA_STATUS);
- (void) status;
- engine_dbg(engine, "ERROR ISR: status=%08x\n", status);
return IRQ_HANDLED;
}
@@ -715,8 +719,7 @@ static struct lsidma_hw lsi_dma32 = {
.chregs_offset = 0x80,
.genregs_offset = 0xF00,
.flags = (LSIDMA_NEXT_FULL |
- LSIDMA_SEG_REGS |
- LSIDMA_EDGE_INT)
+ LSIDMA_SEG_REGS)
};
static struct lsidma_hw lsi_dma31 = {
@@ -800,7 +803,7 @@ static int __devinit gpdma_of_probe(struct platform_device *op)
}
dev_dbg(&op->dev, "mapped base @ %p\n", engine->iobase);
- engine->err_irq = irq_of_parse_and_map(op->dev.of_node, 0);
+ engine->err_irq = irq_of_parse_and_map(op->dev.of_node, 1);
if (engine->err_irq) {
rc = request_irq(engine->err_irq, gpdma_isr_err,
IRQF_SHARED, "lsi-dma-err", engine);
diff --git a/drivers/dma/lsi-dma32.h b/drivers/dma/lsi-dma32.h
index 04504c1..5f10198 100644
--- a/drivers/dma/lsi-dma32.h
+++ b/drivers/dma/lsi-dma32.h
@@ -114,6 +114,11 @@
DMA_CONFIG_CHAN_EN)
#define GEN_STAT 0x0
+#define GEN_STAT_CH0_ACTIVE (1<<0)
+#define GEN_STAT_CH1_ACTIVE (1<<2)
+#define GEN_STAT_CH1_ACTIVE (1<<2)
+#define GEN_STAT_CH0_ERROR (1<<16)
+#define GEN_STAT_CH1_ERROR (1<<17)
#define GEN_CONFIG 0x4
#define GEN_CONFIG_EXT_MEM (1<<19)
#define GEN_CONFIG_INT_EDGE(_ch) (1<<(_ch))
--
1.8.3.4
More information about the linux-yocto
mailing list