Skip to content

Commit

Permalink
Merge branch 'fixes-s3c-2632-rc6' of git://git.fluff.org/bjdooks/linux
Browse files Browse the repository at this point in the history
* 'fixes-s3c-2632-rc6' of git://git.fluff.org/bjdooks/linux:
  ARM: S3C64XX: DMA: Free node for non-circular queues
  ARM: S3C64XX: DMA: Callback with correct buffer pointer
  ARM: S3C64XX: DMA: Make src and dst transfer size same
  ARM: S3C64XX: DMA: Unify callback functions for success/failure
  ARM: S3C64XX: DMA: Protect buffer pointers while manipulation
  ARM: S3C64XX: Tidy definition and comments in s3c_dma_has_circular()
  ARM: S3C64XX: Remove duplicate s3c_dma_has_circular() definition for S3C64xx.
  ARM: SMDK6410: Allocate more GPIO space for WM1190-EV1
  ARM: SMDK6410: Configure GPIO pull up for WM835x IRQ line
  • Loading branch information
Linus Torvalds committed Nov 11, 2009
2 parents a544de2 + 2ce672e commit 1ed2374
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 34 deletions.
12 changes: 2 additions & 10 deletions arch/arm/mach-s3c6400/include/mach/dma.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,21 +58,13 @@ enum dma_ch {
DMACH_MAX /* the end */
};

static __inline__ int s3c_dma_has_circular(void)
static __inline__ bool s3c_dma_has_circular(void)
{
/* we will be supporting ciruclar buffers as soon as we have DMA
* engine support.
*/
return 1;
return true;
}

#define S3C2410_DMAF_CIRCULAR (1 << 0)

static inline bool s3c_dma_has_circular(void)
{
return false;
}

#include <plat/dma.h>

#endif /* __ASM_ARCH_IRQ_H */
1 change: 1 addition & 0 deletions arch/arm/mach-s3c6410/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ config SMDK6410_WM1190_EV1
depends on MACH_SMDK6410
select REGULATOR
select REGULATOR_WM8350
select S3C24XX_GPIO_EXTRA64
select MFD_WM8350_I2C
select MFD_WM8350_CONFIG_MODE_0
select MFD_WM8350_CONFIG_MODE_3
Expand Down
3 changes: 3 additions & 0 deletions arch/arm/mach-s3c6410/mach-smdk6410.c
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,9 @@ static int __init smdk6410_wm8350_init(struct wm8350 *wm8350)
{
int i;

/* Configure the IRQ line */
s3c_gpio_setpull(S3C64XX_GPN(12), S3C_GPIO_PULL_UP);

/* Instantiate the regulators */
for (i = 0; i < ARRAY_SIZE(wm1190_regulators); i++)
wm8350_register_regulator(wm8350,
Expand Down
76 changes: 52 additions & 24 deletions arch/arm/plat-s3c64xx/dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,17 +151,13 @@ static void s3c64xx_dma_fill_lli(struct s3c2410_dma_chan *chan,
src = chan->dev_addr;
dst = data;
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;
break;

case S3C2410_DMASRC_MEM:
src = data;
dst = chan->dev_addr;
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;
break;
default:
Expand All @@ -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 */
control0 |= PL080_CONTROL_PROT_SYS; /* always in priv. mode */
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->dst_addr = dst;
Expand Down Expand Up @@ -339,6 +337,7 @@ int s3c2410_dma_enqueue(unsigned int channel, void *id,
struct s3c64xx_dma_buff *next;
struct s3c64xx_dma_buff *buff;
struct pl080s_lli *lli;
unsigned long flags;
int ret;

WARN_ON(!chan);
Expand Down Expand Up @@ -366,6 +365,8 @@ int s3c2410_dma_enqueue(unsigned int channel, void *id,

s3c64xx_dma_fill_lli(chan, lli, data, size);

local_irq_save(flags);

if ((next = chan->next) != NULL) {
struct s3c64xx_dma_buff *end = chan->end;
struct pl080s_lli *endlli = end->lli;
Expand Down Expand Up @@ -397,6 +398,8 @@ int s3c2410_dma_enqueue(unsigned int channel, void *id,
s3c64xx_lli_to_regs(chan, lli);
}

local_irq_restore(flags);

show_lli(lli);

dbg_showchan(chan);
Expand Down Expand Up @@ -560,26 +563,11 @@ int s3c2410_dma_free(unsigned int channel, struct s3c2410_dma_client *client)

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)
{
struct s3c64xx_dmac *dmac = pw;
struct s3c2410_dma_chan *chan;
enum s3c2410_dma_buffresult res;
u32 tcstat, errstat;
u32 bit;
int offs;
Expand All @@ -588,14 +576,54 @@ static irqreturn_t s3c64xx_dma_irq(int irq, void *pw)
errstat = readl(dmac->regs + PL080_ERR_STATUS);

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) {
writel(bit, dmac->regs + PL080_TC_CLEAR);
s3c64xx_dma_tcirq(dmac, offs);
res = S3C2410_RES_OK;
}

if (errstat & bit) {
s3c64xx_dma_errirq(dmac, offs);
if (errstat & bit)
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;
}
}

Expand Down

0 comments on commit 1ed2374

Please sign in to comment.