Merge branch 'fixes-s3c-2632-rc6' of git://git.fluff.org/bjdooks/linux
* '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
This commit is contained in:
commit
1ed2374307
@ -58,21 +58,13 @@ enum dma_ch {
|
|||||||
DMACH_MAX /* the end */
|
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
|
return true;
|
||||||
* engine support.
|
|
||||||
*/
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define S3C2410_DMAF_CIRCULAR (1 << 0)
|
#define S3C2410_DMAF_CIRCULAR (1 << 0)
|
||||||
|
|
||||||
static inline bool s3c_dma_has_circular(void)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <plat/dma.h>
|
#include <plat/dma.h>
|
||||||
|
|
||||||
#endif /* __ASM_ARCH_IRQ_H */
|
#endif /* __ASM_ARCH_IRQ_H */
|
||||||
|
@ -77,6 +77,7 @@ config SMDK6410_WM1190_EV1
|
|||||||
depends on MACH_SMDK6410
|
depends on MACH_SMDK6410
|
||||||
select REGULATOR
|
select REGULATOR
|
||||||
select REGULATOR_WM8350
|
select REGULATOR_WM8350
|
||||||
|
select S3C24XX_GPIO_EXTRA64
|
||||||
select MFD_WM8350_I2C
|
select MFD_WM8350_I2C
|
||||||
select MFD_WM8350_CONFIG_MODE_0
|
select MFD_WM8350_CONFIG_MODE_0
|
||||||
select MFD_WM8350_CONFIG_MODE_3
|
select MFD_WM8350_CONFIG_MODE_3
|
||||||
|
@ -320,6 +320,9 @@ static int __init smdk6410_wm8350_init(struct wm8350 *wm8350)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
/* Configure the IRQ line */
|
||||||
|
s3c_gpio_setpull(S3C64XX_GPN(12), S3C_GPIO_PULL_UP);
|
||||||
|
|
||||||
/* Instantiate the regulators */
|
/* Instantiate the regulators */
|
||||||
for (i = 0; i < ARRAY_SIZE(wm1190_regulators); i++)
|
for (i = 0; i < ARRAY_SIZE(wm1190_regulators); i++)
|
||||||
wm8350_register_regulator(wm8350,
|
wm8350_register_regulator(wm8350,
|
||||||
|
@ -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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user