From 8f90734610992221f4793b135db80d87c7189f33 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 5 Aug 2011 15:32:36 +0530 Subject: [PATCH] --- yaml --- r: 273868 b: refs/heads/master c: 28da28365da3f3bea1d4b7212a8a40e4b9ac3229 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/drivers/dma/amba-pl08x.c | 44 ++++++++++++++++++---------------- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/[refs] b/[refs] index 5b1e6cf04933..8da793124552 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 16ca8105040217acf5b4b506d04bb933fb3a76af +refs/heads/master: 28da28365da3f3bea1d4b7212a8a40e4b9ac3229 diff --git a/trunk/drivers/dma/amba-pl08x.c b/trunk/drivers/dma/amba-pl08x.c index 3653961b6088..6bba32e5ddb8 100644 --- a/trunk/drivers/dma/amba-pl08x.c +++ b/trunk/drivers/dma/amba-pl08x.c @@ -1619,38 +1619,40 @@ static void pl08x_tasklet(unsigned long data) static irqreturn_t pl08x_irq(int irq, void *dev) { struct pl08x_driver_data *pl08x = dev; - u32 mask = 0; - u32 val; - int i; - - val = readl(pl08x->base + PL080_ERR_STATUS); - if (val) { - /* An error interrupt (on one or more channels) */ - dev_err(&pl08x->adev->dev, - "%s error interrupt, register value 0x%08x\n", - __func__, val); - /* - * Simply clear ALL PL08X error interrupts, - * regardless of channel and cause - * FIXME: should be 0x00000003 on PL081 really. - */ - writel(0x000000FF, pl08x->base + PL080_ERR_CLEAR); + u32 mask = 0, err, tc, i; + + /* check & clear - ERR & TC interrupts */ + err = readl(pl08x->base + PL080_ERR_STATUS); + if (err) { + dev_err(&pl08x->adev->dev, "%s error interrupt, register value 0x%08x\n", + __func__, err); + writel(err, pl08x->base + PL080_ERR_CLEAR); } - val = readl(pl08x->base + PL080_INT_STATUS); + tc = readl(pl08x->base + PL080_INT_STATUS); + if (tc) + writel(tc, pl08x->base + PL080_TC_CLEAR); + + if (!err && !tc) + return IRQ_NONE; + for (i = 0; i < pl08x->vd->channels; i++) { - if ((1 << i) & val) { + if (((1 << i) & err) || ((1 << i) & tc)) { /* Locate physical channel */ struct pl08x_phy_chan *phychan = &pl08x->phy_chans[i]; struct pl08x_dma_chan *plchan = phychan->serving; + if (!plchan) { + dev_err(&pl08x->adev->dev, + "%s Error TC interrupt on unused channel: 0x%08x\n", + __func__, i); + continue; + } + /* Schedule tasklet on this channel */ tasklet_schedule(&plchan->tasklet); - mask |= (1 << i); } } - /* Clear only the terminal interrupts on channels we processed */ - writel(mask, pl08x->base + PL080_TC_CLEAR); return mask ? IRQ_HANDLED : IRQ_NONE; }