Commit 2ce672e4 authored by Ben Dooks's avatar Ben Dooks

ARM: S3C: Merge fixes-s3c64xx-dma

Merge branch 'fixes-s3c64xx-dma' into fixes-s3c-2632-rc6
parents b3c5496f 336b1a31
...@@ -151,8 +151,6 @@ static void s3c64xx_dma_fill_lli(struct s3c2410_dma_chan *chan, ...@@ -151,8 +151,6 @@ static void s3c64xx_dma_fill_lli(struct s3c2410_dma_chan *chan,
src = chan->dev_addr; src = chan->dev_addr;
dst = data; dst = data;
control0 = PL080_CONTROL_SRC_AHB2; control0 = PL080_CONTROL_SRC_AHB2;
control0 |= (u32)chan->hw_width << PL080_CONTROL_SWIDTH_SHIFT;
control0 |= 2 << PL080_CONTROL_DWIDTH_SHIFT;
control0 |= PL080_CONTROL_DST_INCR; control0 |= PL080_CONTROL_DST_INCR;
break; break;
...@@ -160,8 +158,6 @@ static void s3c64xx_dma_fill_lli(struct s3c2410_dma_chan *chan, ...@@ -160,8 +158,6 @@ static void s3c64xx_dma_fill_lli(struct s3c2410_dma_chan *chan,
src = data; src = data;
dst = chan->dev_addr; dst = chan->dev_addr;
control0 = PL080_CONTROL_DST_AHB2; control0 = PL080_CONTROL_DST_AHB2;
control0 |= (u32)chan->hw_width << PL080_CONTROL_DWIDTH_SHIFT;
control0 |= 2 << PL080_CONTROL_SWIDTH_SHIFT;
control0 |= PL080_CONTROL_SRC_INCR; control0 |= PL080_CONTROL_SRC_INCR;
break; break;
default: default:
...@@ -173,6 +169,8 @@ static void s3c64xx_dma_fill_lli(struct s3c2410_dma_chan *chan, ...@@ -173,6 +169,8 @@ static void s3c64xx_dma_fill_lli(struct s3c2410_dma_chan *chan,
control1 = size >> chan->hw_width; /* size in no of xfers */ control1 = size >> chan->hw_width; /* size in no of xfers */
control0 |= PL080_CONTROL_PROT_SYS; /* always in priv. mode */ control0 |= PL080_CONTROL_PROT_SYS; /* always in priv. mode */
control0 |= PL080_CONTROL_TC_IRQ_EN; /* always fire IRQ */ control0 |= PL080_CONTROL_TC_IRQ_EN; /* always fire IRQ */
control0 |= (u32)chan->hw_width << PL080_CONTROL_DWIDTH_SHIFT;
control0 |= (u32)chan->hw_width << PL080_CONTROL_SWIDTH_SHIFT;
lli->src_addr = src; lli->src_addr = src;
lli->dst_addr = dst; lli->dst_addr = dst;
...@@ -339,6 +337,7 @@ int s3c2410_dma_enqueue(unsigned int channel, void *id, ...@@ -339,6 +337,7 @@ int s3c2410_dma_enqueue(unsigned int channel, void *id,
struct s3c64xx_dma_buff *next; struct s3c64xx_dma_buff *next;
struct s3c64xx_dma_buff *buff; struct s3c64xx_dma_buff *buff;
struct pl080s_lli *lli; struct pl080s_lli *lli;
unsigned long flags;
int ret; int ret;
WARN_ON(!chan); WARN_ON(!chan);
...@@ -366,6 +365,8 @@ int s3c2410_dma_enqueue(unsigned int channel, void *id, ...@@ -366,6 +365,8 @@ int s3c2410_dma_enqueue(unsigned int channel, void *id,
s3c64xx_dma_fill_lli(chan, lli, data, size); s3c64xx_dma_fill_lli(chan, lli, data, size);
local_irq_save(flags);
if ((next = chan->next) != NULL) { if ((next = chan->next) != NULL) {
struct s3c64xx_dma_buff *end = chan->end; struct s3c64xx_dma_buff *end = chan->end;
struct pl080s_lli *endlli = end->lli; struct pl080s_lli *endlli = end->lli;
...@@ -397,6 +398,8 @@ int s3c2410_dma_enqueue(unsigned int channel, void *id, ...@@ -397,6 +398,8 @@ int s3c2410_dma_enqueue(unsigned int channel, void *id,
s3c64xx_lli_to_regs(chan, lli); s3c64xx_lli_to_regs(chan, lli);
} }
local_irq_restore(flags);
show_lli(lli); show_lli(lli);
dbg_showchan(chan); dbg_showchan(chan);
...@@ -560,26 +563,11 @@ int s3c2410_dma_free(unsigned int channel, struct s3c2410_dma_client *client) ...@@ -560,26 +563,11 @@ int s3c2410_dma_free(unsigned int channel, struct s3c2410_dma_client *client)
EXPORT_SYMBOL(s3c2410_dma_free); EXPORT_SYMBOL(s3c2410_dma_free);
static void s3c64xx_dma_tcirq(struct s3c64xx_dmac *dmac, int offs)
{
struct s3c2410_dma_chan *chan = dmac->channels + offs;
/* note, we currently do not bother to work out which buffer
* or buffers have been completed since the last tc-irq. */
if (chan->callback_fn)
(chan->callback_fn)(chan, chan->curr->pw, 0, S3C2410_RES_OK);
}
static void s3c64xx_dma_errirq(struct s3c64xx_dmac *dmac, int offs)
{
printk(KERN_DEBUG "%s: offs %d\n", __func__, offs);
}
static irqreturn_t s3c64xx_dma_irq(int irq, void *pw) static irqreturn_t s3c64xx_dma_irq(int irq, void *pw)
{ {
struct s3c64xx_dmac *dmac = pw; struct s3c64xx_dmac *dmac = pw;
struct s3c2410_dma_chan *chan;
enum s3c2410_dma_buffresult res;
u32 tcstat, errstat; u32 tcstat, errstat;
u32 bit; u32 bit;
int offs; int offs;
...@@ -588,14 +576,54 @@ static irqreturn_t s3c64xx_dma_irq(int irq, void *pw) ...@@ -588,14 +576,54 @@ static irqreturn_t s3c64xx_dma_irq(int irq, void *pw)
errstat = readl(dmac->regs + PL080_ERR_STATUS); errstat = readl(dmac->regs + PL080_ERR_STATUS);
for (offs = 0, bit = 1; offs < 8; offs++, bit <<= 1) { for (offs = 0, bit = 1; offs < 8; offs++, bit <<= 1) {
struct s3c64xx_dma_buff *buff;
if (!(errstat & bit) && !(tcstat & bit))
continue;
chan = dmac->channels + offs;
res = S3C2410_RES_ERR;
if (tcstat & bit) { if (tcstat & bit) {
writel(bit, dmac->regs + PL080_TC_CLEAR); writel(bit, dmac->regs + PL080_TC_CLEAR);
s3c64xx_dma_tcirq(dmac, offs); res = S3C2410_RES_OK;
} }
if (errstat & bit) { if (errstat & bit)
s3c64xx_dma_errirq(dmac, offs);
writel(bit, dmac->regs + PL080_ERR_CLEAR); writel(bit, dmac->regs + PL080_ERR_CLEAR);
/* 'next' points to the buffer that is next to the
* currently active buffer.
* For CIRCULAR queues, 'next' will be same as 'curr'
* when 'end' is the active buffer.
*/
buff = chan->curr;
while (buff && buff != chan->next
&& buff->next != chan->next)
buff = buff->next;
if (!buff)
BUG();
if (buff == chan->next)
buff = chan->end;
s3c64xx_dma_bufffdone(chan, buff, res);
/* Free the node and update curr, if non-circular queue */
if (!(chan->flags & S3C2410_DMAF_CIRCULAR)) {
chan->curr = buff->next;
s3c64xx_dma_freebuff(buff);
}
/* Update 'next' */
buff = chan->next;
if (chan->next == chan->end) {
chan->next = chan->curr;
if (!(chan->flags & S3C2410_DMAF_CIRCULAR))
chan->end = NULL;
} else {
chan->next = buff->next;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment