[linux-yocto] [PATCH 38/78] drivers/dma: Corrected IRQ line mixup.

Paul Butler butler.paul at gmail.com
Tue Nov 19 20:23:14 PST 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.4.3



More information about the linux-yocto mailing list