From: Anders Berg <anders.b...@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.b...@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@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 _______________________________________________ linux-yocto mailing list linux-yocto@yoctoproject.org https://lists.yoctoproject.org/listinfo/linux-yocto