X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Farm%2Fmach-s3c2410%2Fdma.c;h=4dbd8e758ea6f9691f73e5c06439fa4d2efec2fc;hb=9464c7cf61b9433057924c36e6e02f303a00e768;hp=cc92a7b2db889e7cbc5ec151e61a888718325046;hpb=41689045f6a3cbe0550e1d34e9cc20d2e8c432ba;p=linux-2.6.git diff --git a/arch/arm/mach-s3c2410/dma.c b/arch/arm/mach-s3c2410/dma.c index cc92a7b2d..4dbd8e758 100644 --- a/arch/arm/mach-s3c2410/dma.c +++ b/arch/arm/mach-s3c2410/dma.c @@ -31,6 +31,7 @@ * possible DMA function */ +#include #ifdef CONFIG_S3C2410_DMA_DEBUG #define DEBUG @@ -60,7 +61,7 @@ static void __iomem *dma_base; static kmem_cache_t *dma_kmem; /* dma channel state information */ -struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS]; +s3c2410_dma_chan_t s3c2410_chans[S3C2410_DMA_CHANNELS]; /* debugging functions */ @@ -74,7 +75,7 @@ struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS]; #define dma_wrreg(chan, reg, val) writel((val), (chan)->regs + (reg)) #else static inline void -dma_wrreg(struct s3c2410_dma_chan *chan, int reg, unsigned long val) +dma_wrreg(s3c2410_dma_chan_t *chan, int reg, unsigned long val) { pr_debug("writing %08x to register %08x\n",(unsigned int)val,reg); writel(val, dma_regaddr(chan, reg)); @@ -102,7 +103,7 @@ struct s3c2410_dma_regstate { */ static void -dmadbg_capture(struct s3c2410_dma_chan *chan, struct s3c2410_dma_regstate *regs) +dmadbg_capture(s3c2410_dma_chan_t *chan, struct s3c2410_dma_regstate *regs) { regs->dcsrc = dma_rdreg(chan, S3C2410_DMA_DCSRC); regs->disrc = dma_rdreg(chan, S3C2410_DMA_DISRC); @@ -112,7 +113,7 @@ dmadbg_capture(struct s3c2410_dma_chan *chan, struct s3c2410_dma_regstate *regs) } static void -dmadbg_dumpregs(const char *fname, int line, struct s3c2410_dma_chan *chan, +dmadbg_showregs(const char *fname, int line, s3c2410_dma_chan_t *chan, struct s3c2410_dma_regstate *regs) { printk(KERN_DEBUG "dma%d: %s:%d: DCSRC=%08lx, DISRC=%08lx, DSTAT=%08lx DMT=%02lx, DCON=%08lx\n", @@ -122,7 +123,7 @@ dmadbg_dumpregs(const char *fname, int line, struct s3c2410_dma_chan *chan, } static void -dmadbg_showchan(const char *fname, int line, struct s3c2410_dma_chan *chan) +dmadbg_showchan(const char *fname, int line, s3c2410_dma_chan_t *chan) { struct s3c2410_dma_regstate state; @@ -132,16 +133,7 @@ dmadbg_showchan(const char *fname, int line, struct s3c2410_dma_chan *chan) chan->number, fname, line, chan->load_state, chan->curr, chan->next, chan->end); - dmadbg_dumpregs(fname, line, chan, &state); -} - -static void -dmadbg_showregs(const char *fname, int line, struct s3c2410_dma_chan *chan) -{ - struct s3c2410_dma_regstate state; - - dmadbg_capture(chan, &state); - dmadbg_dumpregs(fname, line, chan, &state); + dmadbg_showregs(fname, line, chan, &state); } #define dbg_showregs(chan) dmadbg_showregs(__FUNCTION__, __LINE__, (chan)) @@ -164,7 +156,7 @@ dmadbg_showregs(const char *fname, int line, struct s3c2410_dma_chan *chan) */ static void -s3c2410_dma_stats_timeout(struct s3c2410_dma_stats *stats, int val) +s3c2410_dma_stats_timeout(s3c2410_dma_stats_t *stats, int val) { if (stats == NULL) return; @@ -183,7 +175,7 @@ s3c2410_dma_stats_timeout(struct s3c2410_dma_stats *stats, int val) */ static int -s3c2410_dma_waitforload(struct s3c2410_dma_chan *chan, int line) +s3c2410_dma_waitforload(s3c2410_dma_chan_t *chan, int line) { int timeout = chan->load_timeout; int took; @@ -230,8 +222,8 @@ s3c2410_dma_waitforload(struct s3c2410_dma_chan *chan, int line) */ static inline int -s3c2410_dma_loadbuffer(struct s3c2410_dma_chan *chan, - struct s3c2410_dma_buf *buf) +s3c2410_dma_loadbuffer(s3c2410_dma_chan_t *chan, + s3c2410_dma_buf_t *buf) { unsigned long reload; @@ -262,14 +254,10 @@ s3c2410_dma_loadbuffer(struct s3c2410_dma_chan *chan, buf->next); reload = (buf->next == NULL) ? S3C2410_DCON_NORELOAD : 0; } else { - //pr_debug("load_state is %d => autoreload\n", chan->load_state); + pr_debug("load_state is %d => autoreload\n", chan->load_state); reload = S3C2410_DCON_AUTORELOAD; } - if ((buf->data & 0xf0000000) != 0x30000000) { - dmawarn("dmaload: buffer is %p\n", (void *)buf->data); - } - writel(buf->data, chan->addr_reg); dma_wrreg(chan, S3C2410_DMA_DCON, @@ -304,7 +292,7 @@ s3c2410_dma_loadbuffer(struct s3c2410_dma_chan *chan, */ static void -s3c2410_dma_call_op(struct s3c2410_dma_chan *chan, enum s3c2410_chan_op op) +s3c2410_dma_call_op(s3c2410_dma_chan_t *chan, s3c2410_chan_op_t op) { if (chan->op_fn != NULL) { (chan->op_fn)(chan, op); @@ -318,8 +306,8 @@ s3c2410_dma_call_op(struct s3c2410_dma_chan *chan, enum s3c2410_chan_op op) */ static inline void -s3c2410_dma_buffdone(struct s3c2410_dma_chan *chan, struct s3c2410_dma_buf *buf, - enum s3c2410_dma_buffresult result) +s3c2410_dma_buffdone(s3c2410_dma_chan_t *chan, s3c2410_dma_buf_t *buf, + s3c2410_dma_buffresult_t result) { pr_debug("callback_fn=%p, buf=%p, id=%p, size=%d, result=%d\n", chan->callback_fn, buf, buf->id, buf->size, result); @@ -334,7 +322,7 @@ s3c2410_dma_buffdone(struct s3c2410_dma_chan *chan, struct s3c2410_dma_buf *buf, * start a dma channel going */ -static int s3c2410_dma_start(struct s3c2410_dma_chan *chan) +static int s3c2410_dma_start(s3c2410_dma_chan_t *chan) { unsigned long tmp; unsigned long flags; @@ -383,7 +371,7 @@ static int s3c2410_dma_start(struct s3c2410_dma_chan *chan) tmp |= S3C2410_DMASKTRIG_ON; dma_wrreg(chan, S3C2410_DMA_DMASKTRIG, tmp); - pr_debug("dma%d: %08lx to DMASKTRIG\n", chan->number, tmp); + pr_debug("wrote %08lx to DMASKTRIG\n", tmp); #if 0 /* the dma buffer loads should take care of clearing the AUTO @@ -397,30 +385,7 @@ static int s3c2410_dma_start(struct s3c2410_dma_chan *chan) dbg_showchan(chan); - /* if we've only loaded one buffer onto the channel, then chec - * to see if we have another, and if so, try and load it so when - * the first buffer is finished, the new one will be loaded onto - * the channel */ - - if (chan->next != NULL) { - if (chan->load_state == S3C2410_DMALOAD_1LOADED) { - - if (s3c2410_dma_waitforload(chan, __LINE__) == 0) { - pr_debug("%s: buff not yet loaded, no more todo\n", - __FUNCTION__); - } else { - chan->load_state = S3C2410_DMALOAD_1RUNNING; - s3c2410_dma_loadbuffer(chan, chan->next); - } - - } else if (chan->load_state == S3C2410_DMALOAD_1RUNNING) { - s3c2410_dma_loadbuffer(chan, chan->next); - } - } - - local_irq_restore(flags); - return 0; } @@ -430,7 +395,7 @@ static int s3c2410_dma_start(struct s3c2410_dma_chan *chan) */ static int -s3c2410_dma_canload(struct s3c2410_dma_chan *chan) +s3c2410_dma_canload(s3c2410_dma_chan_t *chan) { if (chan->load_state == S3C2410_DMALOAD_NONE || chan->load_state == S3C2410_DMALOAD_1RUNNING) @@ -460,8 +425,8 @@ s3c2410_dma_canload(struct s3c2410_dma_chan *chan) int s3c2410_dma_enqueue(unsigned int channel, void *id, dma_addr_t data, int size) { - struct s3c2410_dma_chan *chan = &s3c2410_chans[channel]; - struct s3c2410_dma_buf *buf; + s3c2410_dma_chan_t *chan = &s3c2410_chans[channel]; + s3c2410_dma_buf_t *buf; unsigned long flags; check_channel(channel); @@ -472,11 +437,12 @@ int s3c2410_dma_enqueue(unsigned int channel, void *id, buf = kmem_cache_alloc(dma_kmem, GFP_ATOMIC); if (buf == NULL) { pr_debug("%s: out of memory (%ld alloc)\n", - __FUNCTION__, (long)sizeof(*buf)); + __FUNCTION__, sizeof(*buf)); return -ENOMEM; } - //pr_debug("%s: new buffer %p\n", __FUNCTION__, buf); + pr_debug("%s: new buffer %p\n", __FUNCTION__, buf); + //dbg_showchan(chan); buf->next = NULL; @@ -540,7 +506,7 @@ int s3c2410_dma_enqueue(unsigned int channel, void *id, EXPORT_SYMBOL(s3c2410_dma_enqueue); static inline void -s3c2410_dma_freebuf(struct s3c2410_dma_buf *buf) +s3c2410_dma_freebuf(s3c2410_dma_buf_t *buf) { int magicok = (buf->magic == BUF_MAGIC); @@ -560,7 +526,7 @@ s3c2410_dma_freebuf(struct s3c2410_dma_buf *buf) */ static inline void -s3c2410_dma_lastxfer(struct s3c2410_dma_chan *chan) +s3c2410_dma_lastxfer(s3c2410_dma_chan_t *chan) { pr_debug("dma%d: s3c2410_dma_lastxfer: load_state %d\n", chan->number, chan->load_state); @@ -572,20 +538,14 @@ s3c2410_dma_lastxfer(struct s3c2410_dma_chan *chan) case S3C2410_DMALOAD_1LOADED: if (s3c2410_dma_waitforload(chan, __LINE__) == 0) { /* flag error? */ - printk(KERN_ERR "dma%d: timeout waiting for load (%s)\n", - chan->number, __FUNCTION__); + printk(KERN_ERR "dma%d: timeout waiting for load\n", + chan->number); return; } break; - case S3C2410_DMALOAD_1LOADED_1RUNNING: - /* I belive in this case we do not have anything to do - * until the next buffer comes along, and we turn off the - * reload */ - return; - default: - pr_debug("dma%d: lastxfer: unhandled load_state %d with no next\n", + pr_debug("dma%d: lastxfer: unhandled load_state %d with no next", chan->number, chan->load_state); return; @@ -601,8 +561,8 @@ s3c2410_dma_lastxfer(struct s3c2410_dma_chan *chan) static irqreturn_t s3c2410_dma_irq(int irq, void *devpw, struct pt_regs *regs) { - struct s3c2410_dma_chan *chan = (struct s3c2410_dma_chan *)devpw; - struct s3c2410_dma_buf *buf; + s3c2410_dma_chan_t *chan = (s3c2410_dma_chan_t *)devpw; + s3c2410_dma_buf_t *buf; buf = chan->curr; @@ -670,14 +630,7 @@ s3c2410_dma_irq(int irq, void *devpw, struct pt_regs *regs) } else { } - /* only reload if the channel is still running... our buffer done - * routine may have altered the state by requesting the dma channel - * to stop or shutdown... */ - - /* todo: check that when the channel is shut-down from inside this - * function, we cope with unsetting reload, etc */ - - if (chan->next != NULL && chan->state != S3C2410_DMA_IDLE) { + if (chan->next != NULL) { unsigned long flags; switch (chan->load_state) { @@ -692,8 +645,8 @@ s3c2410_dma_irq(int irq, void *devpw, struct pt_regs *regs) case S3C2410_DMALOAD_1LOADED: if (s3c2410_dma_waitforload(chan, __LINE__) == 0) { /* flag error? */ - printk(KERN_ERR "dma%d: timeout waiting for load (%s)\n", - chan->number, __FUNCTION__); + printk(KERN_ERR "dma%d: timeout waiting for load\n", + chan->number); return IRQ_HANDLED; } @@ -726,15 +679,17 @@ s3c2410_dma_irq(int irq, void *devpw, struct pt_regs *regs) return IRQ_HANDLED; } + + /* s3c2410_request_dma * * get control of an dma channel */ -int s3c2410_dma_request(unsigned int channel, struct s3c2410_dma_client *client, +int s3c2410_dma_request(unsigned int channel, s3c2410_dma_client_t *client, void *dev) { - struct s3c2410_dma_chan *chan = &s3c2410_chans[channel]; + s3c2410_dma_chan_t *chan = &s3c2410_chans[channel]; unsigned long flags; int err; @@ -764,17 +719,11 @@ int s3c2410_dma_request(unsigned int channel, struct s3c2410_dma_client *client, pr_debug("dma%d: %s : requesting irq %d\n", channel, __FUNCTION__, chan->irq); - chan->irq_claimed = 1; - local_irq_restore(flags); - - err = request_irq(chan->irq, s3c2410_dma_irq, IRQF_DISABLED, + err = request_irq(chan->irq, s3c2410_dma_irq, SA_INTERRUPT, client->name, (void *)chan); - local_irq_save(flags); - if (err) { chan->in_use = 0; - chan->irq_claimed = 0; local_irq_restore(flags); printk(KERN_ERR "%s: cannot get IRQ %d for DMA %d\n", @@ -782,6 +731,7 @@ int s3c2410_dma_request(unsigned int channel, struct s3c2410_dma_client *client, return err; } + chan->irq_claimed = 1; chan->irq_enabled = 1; } @@ -807,9 +757,9 @@ EXPORT_SYMBOL(s3c2410_dma_request); * allowed to go through. */ -int s3c2410_dma_free(dmach_t channel, struct s3c2410_dma_client *client) +int s3c2410_dma_free(dmach_t channel, s3c2410_dma_client_t *client) { - struct s3c2410_dma_chan *chan = &s3c2410_chans[channel]; + s3c2410_dma_chan_t *chan = &s3c2410_chans[channel]; unsigned long flags; check_channel(channel); @@ -846,7 +796,7 @@ int s3c2410_dma_free(dmach_t channel, struct s3c2410_dma_client *client) EXPORT_SYMBOL(s3c2410_dma_free); -static int s3c2410_dma_dostop(struct s3c2410_dma_chan *chan) +static int s3c2410_dma_dostop(s3c2410_dma_chan_t *chan) { unsigned long tmp; unsigned long flags; @@ -861,7 +811,6 @@ static int s3c2410_dma_dostop(struct s3c2410_dma_chan *chan) tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG); tmp |= S3C2410_DMASKTRIG_STOP; - //tmp &= ~S3C2410_DMASKTRIG_ON; dma_wrreg(chan, S3C2410_DMA_DMASKTRIG, tmp); #if 0 @@ -871,7 +820,6 @@ static int s3c2410_dma_dostop(struct s3c2410_dma_chan *chan) dma_wrreg(chan, S3C2410_DMA_DCON, tmp); #endif - /* should stop do this, or should we wait for flush? */ chan->state = S3C2410_DMA_IDLE; chan->load_state = S3C2410_DMALOAD_NONE; @@ -880,35 +828,17 @@ static int s3c2410_dma_dostop(struct s3c2410_dma_chan *chan) return 0; } -void s3c2410_dma_waitforstop(struct s3c2410_dma_chan *chan) -{ - unsigned long tmp; - unsigned int timeout = 0x10000; - - while (timeout-- > 0) { - tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG); - - if (!(tmp & S3C2410_DMASKTRIG_ON)) - return; - } - - pr_debug("dma%d: failed to stop?\n", chan->number); -} - - /* s3c2410_dma_flush * * stop the channel, and remove all current and pending transfers */ -static int s3c2410_dma_flush(struct s3c2410_dma_chan *chan) +static int s3c2410_dma_flush(s3c2410_dma_chan_t *chan) { - struct s3c2410_dma_buf *buf, *next; + s3c2410_dma_buf_t *buf, *next; unsigned long flags; - pr_debug("%s: chan %p (%d)\n", __FUNCTION__, chan, chan->number); - - dbg_showchan(chan); + pr_debug("%s:\n", __FUNCTION__); local_irq_save(flags); @@ -935,69 +865,16 @@ static int s3c2410_dma_flush(struct s3c2410_dma_chan *chan) } } - dbg_showregs(chan); - - s3c2410_dma_waitforstop(chan); - -#if 0 - /* should also clear interrupts, according to WinCE BSP */ - { - unsigned long tmp; - - tmp = dma_rdreg(chan, S3C2410_DMA_DCON); - tmp |= S3C2410_DCON_NORELOAD; - dma_wrreg(chan, S3C2410_DMA_DCON, tmp); - } -#endif - - dbg_showregs(chan); - local_irq_restore(flags); return 0; } -int -s3c2410_dma_started(struct s3c2410_dma_chan *chan) -{ - unsigned long flags; - - local_irq_save(flags); - - dbg_showchan(chan); - - /* if we've only loaded one buffer onto the channel, then chec - * to see if we have another, and if so, try and load it so when - * the first buffer is finished, the new one will be loaded onto - * the channel */ - - if (chan->next != NULL) { - if (chan->load_state == S3C2410_DMALOAD_1LOADED) { - - if (s3c2410_dma_waitforload(chan, __LINE__) == 0) { - pr_debug("%s: buff not yet loaded, no more todo\n", - __FUNCTION__); - } else { - chan->load_state = S3C2410_DMALOAD_1RUNNING; - s3c2410_dma_loadbuffer(chan, chan->next); - } - - } else if (chan->load_state == S3C2410_DMALOAD_1RUNNING) { - s3c2410_dma_loadbuffer(chan, chan->next); - } - } - - - local_irq_restore(flags); - - return 0; - -} int -s3c2410_dma_ctrl(dmach_t channel, enum s3c2410_chan_op op) +s3c2410_dma_ctrl(dmach_t channel, s3c2410_chan_op_t op) { - struct s3c2410_dma_chan *chan = &s3c2410_chans[channel]; + s3c2410_dma_chan_t *chan = &s3c2410_chans[channel]; check_channel(channel); @@ -1009,15 +886,14 @@ s3c2410_dma_ctrl(dmach_t channel, enum s3c2410_chan_op op) return s3c2410_dma_dostop(chan); case S3C2410_DMAOP_PAUSE: + return -ENOENT; + case S3C2410_DMAOP_RESUME: return -ENOENT; case S3C2410_DMAOP_FLUSH: return s3c2410_dma_flush(chan); - case S3C2410_DMAOP_STARTED: - return s3c2410_dma_started(chan); - case S3C2410_DMAOP_TIMEOUT: return 0; @@ -1046,7 +922,7 @@ int s3c2410_dma_config(dmach_t channel, int xferunit, int dcon) { - struct s3c2410_dma_chan *chan = &s3c2410_chans[channel]; + s3c2410_dma_chan_t *chan = &s3c2410_chans[channel]; pr_debug("%s: chan=%d, xfer_unit=%d, dcon=%08x\n", __FUNCTION__, channel, xferunit, dcon); @@ -1086,7 +962,7 @@ EXPORT_SYMBOL(s3c2410_dma_config); int s3c2410_dma_setflags(dmach_t channel, unsigned int flags) { - struct s3c2410_dma_chan *chan = &s3c2410_chans[channel]; + s3c2410_dma_chan_t *chan = &s3c2410_chans[channel]; check_channel(channel); @@ -1106,7 +982,7 @@ EXPORT_SYMBOL(s3c2410_dma_setflags); int s3c2410_dma_set_opfn(dmach_t channel, s3c2410_dma_opfn_t rtn) { - struct s3c2410_dma_chan *chan = &s3c2410_chans[channel]; + s3c2410_dma_chan_t *chan = &s3c2410_chans[channel]; check_channel(channel); @@ -1121,7 +997,7 @@ EXPORT_SYMBOL(s3c2410_dma_set_opfn); int s3c2410_dma_set_buffdone_fn(dmach_t channel, s3c2410_dma_cbfn_t rtn) { - struct s3c2410_dma_chan *chan = &s3c2410_chans[channel]; + s3c2410_dma_chan_t *chan = &s3c2410_chans[channel]; check_channel(channel); @@ -1149,11 +1025,11 @@ EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn); */ int s3c2410_dma_devconfig(int channel, - enum s3c2410_dmasrc source, + s3c2410_dmasrc_t source, int hwcfg, unsigned long devaddr) { - struct s3c2410_dma_chan *chan = &s3c2410_chans[channel]; + s3c2410_dma_chan_t *chan = &s3c2410_chans[channel]; check_channel(channel); @@ -1200,7 +1076,7 @@ EXPORT_SYMBOL(s3c2410_dma_devconfig); int s3c2410_dma_getposition(dmach_t channel, dma_addr_t *src, dma_addr_t *dst) { - struct s3c2410_dma_chan *chan = &s3c2410_chans[channel]; + s3c2410_dma_chan_t *chan = &s3c2410_chans[channel]; check_channel(channel); @@ -1222,7 +1098,7 @@ EXPORT_SYMBOL(s3c2410_dma_getposition); static int s3c2410_dma_suspend(struct sys_device *dev, pm_message_t state) { - struct s3c2410_dma_chan *cp = container_of(dev, struct s3c2410_dma_chan, dev); + s3c2410_dma_chan_t *cp = container_of(dev, s3c2410_dma_chan_t, dev); printk(KERN_DEBUG "suspending dma channel %d\n", cp->number); @@ -1262,7 +1138,7 @@ static struct sysdev_class dma_sysclass = { static void s3c2410_dma_cache_ctor(void *p, kmem_cache_t *c, unsigned long f) { - memset(p, 0, sizeof(struct s3c2410_dma_buf)); + memset(p, 0, sizeof(s3c2410_dma_buf_t)); } @@ -1270,7 +1146,7 @@ static void s3c2410_dma_cache_ctor(void *p, kmem_cache_t *c, unsigned long f) static int __init s3c2410_init_dma(void) { - struct s3c2410_dma_chan *cp; + s3c2410_dma_chan_t *cp; int channel; int ret; @@ -1288,7 +1164,7 @@ static int __init s3c2410_init_dma(void) goto err; } - dma_kmem = kmem_cache_create("dma_desc", sizeof(struct s3c2410_dma_buf), 0, + dma_kmem = kmem_cache_create("dma_desc", sizeof(s3c2410_dma_buf_t), 0, SLAB_HWCACHE_ALIGN, s3c2410_dma_cache_ctor, NULL); @@ -1301,7 +1177,7 @@ static int __init s3c2410_init_dma(void) for (channel = 0; channel < S3C2410_DMA_CHANNELS; channel++) { cp = &s3c2410_chans[channel]; - memset(cp, 0, sizeof(struct s3c2410_dma_chan)); + memset(cp, 0, sizeof(s3c2410_dma_chan_t)); /* dma channel irqs are in order.. */ cp->number = channel;