1 /* linux/arch/arm/mach-bast/dma.c
3 * (c) 2003,2004 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
8 * http://www.simtec.co.uk/products/EB2410ITX/
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
15 * 08-Aug-2004 BJD Apply rmk's suggestions
16 * 21-Jul-2004 BJD Ported to linux 2.6
17 * 12-Jul-2004 BJD Finished re-write and change of API
18 * 06-Jul-2004 BJD Rewrote dma code to try and cope with various problems
19 * 23-May-2003 BJD Created file
20 * 19-Aug-2003 BJD Cleanup, header fix, added URL
22 * This file is based on the Sangwook Lee/Samsung patches, re-written due
23 * to various ommisions from the code (such as flexible dma configuration)
24 * for use with the BAST system board.
26 * The re-write is pretty much complete, and should be good enough for any
27 * possible DMA function
30 #include <linux/config.h>
32 #ifdef CONFIG_S3C2410_DMA_DEBUG
36 #include <linux/module.h>
37 #include <linux/init.h>
38 #include <linux/sched.h>
39 #include <linux/spinlock.h>
40 #include <linux/interrupt.h>
41 #include <linux/slab.h>
42 #include <linux/errno.h>
43 #include <linux/delay.h>
45 #include <asm/system.h>
47 #include <asm/hardware.h>
51 #include <asm/mach/dma.h>
52 #include <asm/arch/map.h>
55 static void *dma_base
;
57 /* dma channel state information */
58 s3c2410_dma_chan_t s3c2410_chans
[S3C2410_DMA_CHANNELS
];
60 /* debugging functions */
62 #define BUF_MAGIC (0xcafebabe)
64 #define dmawarn(fmt...) printk(KERN_DEBUG fmt)
66 #define dma_regaddr(chan, reg) ((chan)->regs + (reg))
69 #define dma_wrreg(chan, reg, val) writel((val), (chan)->regs + (reg))
72 dma_wrreg(s3c2410_dma_chan_t
*chan
, int reg
, unsigned long val
)
74 pr_debug("writing %08x to register %08x\n",(unsigned int)val
,reg
);
75 writel(val
, dma_regaddr(chan
, reg
));
80 #define dma_rdreg(chan, reg) readl((chan)->regs + (reg))
82 /* captured register state for debug */
84 struct s3c2410_dma_regstate
{
89 unsigned long dmsktrig
;
92 #ifdef CONFIG_S3C2410_DMA_DEBUG
96 * simple debug routine to print the current state of the dma registers
100 dmadbg_capture(s3c2410_dma_chan_t
*chan
, struct s3c2410_dma_regstate
*regs
)
102 regs
->dcsrc
= dma_rdreg(chan
, S3C2410_DMA_DCSRC
);
103 regs
->disrc
= dma_rdreg(chan
, S3C2410_DMA_DISRC
);
104 regs
->dstat
= dma_rdreg(chan
, S3C2410_DMA_DSTAT
);
105 regs
->dcon
= dma_rdreg(chan
, S3C2410_DMA_DCON
);
106 regs
->dmsktrig
= dma_rdreg(chan
, S3C2410_DMA_DMASKTRIG
);
110 dmadbg_showregs(const char *fname
, int line
, s3c2410_dma_chan_t
*chan
,
111 struct s3c2410_dma_regstate
*regs
)
113 printk(KERN_DEBUG
"dma%d: %s:%d: DCSRC=%08lx, DISRC=%08lx, DSTAT=%08lx DMT=%02lx, DCON=%08lx\n",
114 chan
->number
, fname
, line
,
115 regs
->dcsrc
, regs
->disrc
, regs
->dstat
, regs
->dmsktrig
,
120 dmadbg_showchan(const char *fname
, int line
, s3c2410_dma_chan_t
*chan
)
122 struct s3c2410_dma_regstate state
;
124 dmadbg_capture(chan
, &state
);
126 printk(KERN_DEBUG
"dma%d: %s:%d: ls=%d, cur=%p, %p %p\n",
127 chan
->number
, fname
, line
, chan
->load_state
,
128 chan
->curr
, chan
->next
, chan
->end
);
130 dmadbg_showregs(fname
, line
, chan
, &state
);
133 #define dbg_showregs(chan) dmadbg_showregs(__FUNCTION__, __LINE__, (chan))
134 #define dbg_showchan(chan) dmadbg_showchan(__FUNCTION__, __LINE__, (chan))
136 #define dbg_showregs(chan) do { } while(0)
137 #define dbg_showchan(chan) do { } while(0)
138 #endif /* CONFIG_S3C2410_DMA_DEBUG */
140 #define check_channel(chan) \
141 do { if ((chan) >= S3C2410_DMA_CHANNELS) { \
142 printk(KERN_ERR "%s: invalid channel %d\n", __FUNCTION__, (chan)); \
147 /* s3c2410_dma_stats_timeout
149 * Update DMA stats from timeout info
153 s3c2410_dma_stats_timeout(s3c2410_dma_stats_t
*stats
, int val
)
158 if (val
> stats
->timeout_longest
)
159 stats
->timeout_longest
= val
;
160 if (val
< stats
->timeout_shortest
)
161 stats
->timeout_shortest
= val
;
163 stats
->timeout_avg
+= val
;
166 /* s3c2410_dma_waitforload
168 * wait for the DMA engine to load a buffer, and update the state accordingly
172 s3c2410_dma_waitforload(s3c2410_dma_chan_t
*chan
, int line
)
174 int timeout
= chan
->load_timeout
;
177 if (chan
->load_state
!= S3C2410_DMALOAD_1LOADED
) {
178 printk(KERN_ERR
"dma%d: s3c2410_dma_waitforload() called in loadstate %d from line %d\n", chan
->number
, chan
->load_state
, line
);
182 if (chan
->stats
!= NULL
)
183 chan
->stats
->loads
++;
185 while (--timeout
> 0) {
186 if ((dma_rdreg(chan
, S3C2410_DMA_DSTAT
) << (32-20)) != 0) {
187 took
= chan
->load_timeout
- timeout
;
189 s3c2410_dma_stats_timeout(chan
->stats
, took
);
191 switch (chan
->load_state
) {
192 case S3C2410_DMALOAD_1LOADED
:
193 chan
->load_state
= S3C2410_DMALOAD_1RUNNING
;
197 printk(KERN_ERR
"dma%d: unknown load_state in s3c2410_dma_waitforload() %d\n", chan
->number
, chan
->load_state
);
204 if (chan
->stats
!= NULL
) {
205 chan
->stats
->timeout_failed
++;
213 /* s3c2410_dma_loadbuffer
215 * load a buffer, and update the channel state
219 s3c2410_dma_loadbuffer(s3c2410_dma_chan_t
*chan
,
220 s3c2410_dma_buf_t
*buf
)
222 unsigned long reload
;
224 pr_debug("s3c2410_chan_loadbuffer: loading buff %p (0x%08lx,0x%06x)\n",
225 buf
, (unsigned long)buf
->data
, buf
->size
);
228 dmawarn("buffer is NULL\n");
232 /* check the state of the channel before we do anything */
234 if (chan
->load_state
== S3C2410_DMALOAD_1LOADED
) {
235 dmawarn("load_state is S3C2410_DMALOAD_1LOADED\n");
238 if (chan
->load_state
== S3C2410_DMALOAD_1LOADED_1RUNNING
) {
239 dmawarn("state is S3C2410_DMALOAD_1LOADED_1RUNNING\n");
242 /* it would seem sensible if we are the last buffer to not bother
243 * with the auto-reload bit, so that the DMA engine will not try
244 * and load another transfer after this one has finished...
246 if (chan
->load_state
== S3C2410_DMALOAD_NONE
) {
247 pr_debug("load_state is none, checking for noreload (next=%p)\n",
249 reload
= (buf
->next
== NULL
) ? S3C2410_DCON_NORELOAD
: 0;
251 pr_debug("load_state is %d => autoreload\n", chan
->load_state
);
252 reload
= S3C2410_DCON_AUTORELOAD
;
255 writel(buf
->data
, chan
->addr_reg
);
257 dma_wrreg(chan
, S3C2410_DMA_DCON
,
258 chan
->dcon
| reload
| (buf
->size
/chan
->xfer_unit
));
260 chan
->next
= buf
->next
;
262 /* update the state of the channel */
264 switch (chan
->load_state
) {
265 case S3C2410_DMALOAD_NONE
:
266 chan
->load_state
= S3C2410_DMALOAD_1LOADED
;
269 case S3C2410_DMALOAD_1RUNNING
:
270 chan
->load_state
= S3C2410_DMALOAD_1LOADED_1RUNNING
;
274 dmawarn("dmaload: unknown state %d in loadbuffer\n",
282 /* s3c2410_dma_call_op
284 * small routine to call the op routine with the given op if it has been
289 s3c2410_dma_call_op(s3c2410_dma_chan_t
*chan
, s3c2410_chan_op_t op
)
291 if (chan
->op_fn
!= NULL
) {
292 (chan
->op_fn
)(chan
, op
);
296 /* s3c2410_dma_buffdone
298 * small wrapper to check if callback routine needs to be called, and
303 s3c2410_dma_buffdone(s3c2410_dma_chan_t
*chan
, s3c2410_dma_buf_t
*buf
,
304 s3c2410_dma_buffresult_t result
)
306 pr_debug("callback_fn=%p, buf=%p, id=%p, size=%d, result=%d\n",
307 chan
->callback_fn
, buf
, buf
->id
, buf
->size
, result
);
309 if (chan
->callback_fn
!= NULL
) {
310 (chan
->callback_fn
)(chan
, buf
->id
, buf
->size
, result
);
316 * start a dma channel going
319 static int s3c2410_dma_start(s3c2410_dma_chan_t
*chan
)
324 pr_debug("s3c2410_start_dma: channel=%d\n", chan
->number
);
326 local_irq_save(flags
);
328 if (chan
->state
== S3C2410_DMA_RUNNING
) {
329 pr_debug("s3c2410_start_dma: already running (%d)\n", chan
->state
);
330 local_irq_restore(flags
);
334 chan
->state
= S3C2410_DMA_RUNNING
;
336 /* check wether there is anything to load, and if not, see
337 * if we can find anything to load
340 if (chan
->load_state
== S3C2410_DMALOAD_NONE
) {
341 if (chan
->next
== NULL
) {
342 printk(KERN_ERR
"dma%d: channel has nothing loaded\n",
344 chan
->state
= S3C2410_DMA_IDLE
;
345 local_irq_restore(flags
);
349 s3c2410_dma_loadbuffer(chan
, chan
->next
);
354 /* enable the channel */
356 if (!chan
->irq_enabled
) {
357 enable_irq(chan
->irq
);
358 chan
->irq_enabled
= 1;
361 /* start the channel going */
363 tmp
= dma_rdreg(chan
, S3C2410_DMA_DMASKTRIG
);
364 tmp
&= ~S3C2410_DMASKTRIG_STOP
;
365 tmp
|= S3C2410_DMASKTRIG_ON
;
366 dma_wrreg(chan
, S3C2410_DMA_DMASKTRIG
, tmp
);
368 pr_debug("wrote %08lx to DMASKTRIG\n", tmp
);
371 /* the dma buffer loads should take care of clearing the AUTO
372 * reloading feature */
373 tmp
= dma_rdreg(chan
, S3C2410_DMA_DCON
);
374 tmp
&= ~S3C2410_DCON_NORELOAD
;
375 dma_wrreg(chan
, S3C2410_DMA_DCON
, tmp
);
378 s3c2410_dma_call_op(chan
, S3C2410_DMAOP_START
);
382 local_irq_restore(flags
);
386 /* s3c2410_dma_canload
388 * work out if we can queue another buffer into the DMA engine
392 s3c2410_dma_canload(s3c2410_dma_chan_t
*chan
)
394 if (chan
->load_state
== S3C2410_DMALOAD_NONE
||
395 chan
->load_state
== S3C2410_DMALOAD_1RUNNING
)
402 /* s3c2410_dma_enqueue
404 * queue an given buffer for dma transfer.
406 * id the device driver's id information for this buffer
407 * data the physical address of the buffer data
408 * size the size of the buffer in bytes
410 * If the channel is not running, then the flag S3C2410_DMAF_AUTOSTART
411 * is checked, and if set, the channel is started. If this flag isn't set,
412 * then an error will be returned.
414 * It is possible to queue more than one DMA buffer onto a channel at
415 * once, and the code will deal with the re-loading of the next buffer
419 int s3c2410_dma_enqueue(unsigned int channel
, void *id
,
420 dma_addr_t data
, int size
)
422 s3c2410_dma_chan_t
*chan
= &s3c2410_chans
[channel
];
423 s3c2410_dma_buf_t
*buf
;
426 check_channel(channel
);
428 pr_debug("%s: id=%p, data=%08x, size=%d\n",
429 __FUNCTION__
, id
, (unsigned int)data
, size
);
431 buf
= (s3c2410_dma_buf_t
*)kmalloc(sizeof(*buf
), GFP_ATOMIC
);
433 pr_debug("%s: out of memory (%d alloc)\n",
434 __FUNCTION__
, sizeof(*buf
));
438 pr_debug("%s: new buffer %p\n", __FUNCTION__
, buf
);
440 //dbg_showchan(chan);
443 buf
->data
= buf
->ptr
= data
;
446 buf
->magic
= BUF_MAGIC
;
448 local_irq_save(flags
);
450 if (chan
->curr
== NULL
) {
451 /* we've got nothing loaded... */
452 pr_debug("%s: buffer %p queued onto empty channel\n",
459 pr_debug("dma%d: %s: buffer %p queued onto non-empty channel\n",
460 chan
->number
, __FUNCTION__
, buf
);
462 if (chan
->end
== NULL
)
463 pr_debug("dma%d: %s: %p not empty, and chan->end==NULL?\n",
464 chan
->number
, __FUNCTION__
, chan
);
466 chan
->end
->next
= buf
;
470 /* if necessary, update the next buffer field */
471 if (chan
->next
== NULL
)
474 /* check to see if we can load a buffer */
475 if (chan
->state
== S3C2410_DMA_RUNNING
) {
476 if (chan
->load_state
== S3C2410_DMALOAD_1LOADED
&& 1) {
477 if (s3c2410_dma_waitforload(chan
, __LINE__
) == 0) {
478 printk(KERN_ERR
"dma%d: loadbuffer:"
479 "timeout loading buffer\n",
482 local_irq_restore(flags
);
487 while (s3c2410_dma_canload(chan
) && chan
->next
!= NULL
) {
488 s3c2410_dma_loadbuffer(chan
, chan
->next
);
490 } else if (chan
->state
== S3C2410_DMA_IDLE
) {
491 if (chan
->flags
& S3C2410_DMAF_AUTOSTART
) {
492 s3c2410_dma_ctrl(chan
->number
, S3C2410_DMAOP_START
);
494 printk(KERN_DEBUG
"dma%d: cannot load onto stopped channel'n", chan
->number
);
495 local_irq_restore(flags
);
500 local_irq_restore(flags
);
505 s3c2410_dma_freebuf(s3c2410_dma_buf_t
*buf
)
507 int magicok
= (buf
->magic
== BUF_MAGIC
);
514 printk("s3c2410_dma_freebuf: buff %p with bad magic\n", buf
);
518 /* s3c2410_dma_lastxfer
520 * called when the system is out of buffers, to ensure that the channel
521 * is prepared for shutdown.
525 s3c2410_dma_lastxfer(s3c2410_dma_chan_t
*chan
)
527 pr_debug("dma%d: s3c2410_dma_lastxfer: load_state %d\n",
528 chan
->number
, chan
->load_state
);
530 switch (chan
->load_state
) {
531 case S3C2410_DMALOAD_NONE
:
534 case S3C2410_DMALOAD_1LOADED
:
535 if (s3c2410_dma_waitforload(chan
, __LINE__
) == 0) {
537 printk(KERN_ERR
"dma%d: timeout waiting for load\n",
544 pr_debug("dma%d: lastxfer: unhandled load_state %d with no next",
545 chan
->number
, chan
->load_state
);
550 /* hopefully this'll shut the damned thing up after the transfer... */
551 dma_wrreg(chan
, S3C2410_DMA_DCON
, chan
->dcon
| S3C2410_DCON_NORELOAD
);
555 #define dmadbg2(x...)
558 s3c2410_dma_irq(int irq
, void *devpw
, struct pt_regs
*regs
)
560 s3c2410_dma_chan_t
*chan
= (s3c2410_dma_chan_t
*)devpw
;
561 s3c2410_dma_buf_t
*buf
;
567 /* modify the channel state */
569 switch (chan
->load_state
) {
570 case S3C2410_DMALOAD_1RUNNING
:
571 /* TODO - if we are running only one buffer, we probably
572 * want to reload here, and then worry about the buffer
575 chan
->load_state
= S3C2410_DMALOAD_NONE
;
578 case S3C2410_DMALOAD_1LOADED
:
579 /* iirc, we should go back to NONE loaded here, we
580 * had a buffer, and it was never verified as being
584 chan
->load_state
= S3C2410_DMALOAD_NONE
;
587 case S3C2410_DMALOAD_1LOADED_1RUNNING
:
588 /* we'll worry about checking to see if another buffer is
589 * ready after we've called back the owner. This should
590 * ensure we do not wait around too long for the DMA
591 * engine to start the next transfer
594 chan
->load_state
= S3C2410_DMALOAD_1LOADED
;
597 case S3C2410_DMALOAD_NONE
:
598 printk(KERN_ERR
"dma%d: IRQ with no loaded buffer?\n",
603 printk(KERN_ERR
"dma%d: IRQ in invalid load_state %d\n",
604 chan
->number
, chan
->load_state
);
609 /* update the chain to make sure that if we load any more
610 * buffers when we call the callback function, things should
613 chan
->curr
= buf
->next
;
616 if (buf
->magic
!= BUF_MAGIC
) {
617 printk(KERN_ERR
"dma%d: %s: buf %p incorrect magic\n",
618 chan
->number
, __FUNCTION__
, buf
);
622 s3c2410_dma_buffdone(chan
, buf
, S3C2410_RES_OK
);
625 s3c2410_dma_freebuf(buf
);
629 if (chan
->next
!= NULL
) {
632 switch (chan
->load_state
) {
633 case S3C2410_DMALOAD_1RUNNING
:
634 /* don't need to do anything for this state */
637 case S3C2410_DMALOAD_NONE
:
638 /* can load buffer immediately */
641 case S3C2410_DMALOAD_1LOADED
:
642 if (s3c2410_dma_waitforload(chan
, __LINE__
) == 0) {
644 printk(KERN_ERR
"dma%d: timeout waiting for load\n",
652 printk(KERN_ERR
"dma%d: unknown load_state in irq, %d\n",
653 chan
->number
, chan
->load_state
);
657 local_irq_save(flags
);
658 s3c2410_dma_loadbuffer(chan
, chan
->next
);
659 local_irq_restore(flags
);
661 s3c2410_dma_lastxfer(chan
);
663 /* see if we can stop this channel.. */
664 if (chan
->load_state
== S3C2410_DMALOAD_NONE
) {
665 pr_debug("dma%d: end of transfer, stopping channel (%ld)\n",
666 chan
->number
, jiffies
);
667 s3c2410_dma_ctrl(chan
->number
, S3C2410_DMAOP_STOP
);
676 /* s3c2410_request_dma
678 * get control of an dma channel
681 int s3c2410_dma_request(unsigned int channel
, s3c2410_dma_client_t
*client
,
684 s3c2410_dma_chan_t
*chan
= &s3c2410_chans
[channel
];
688 pr_debug("dma%d: s3c2410_request_dma: client=%s, dev=%p\n",
689 channel
, client
->name
, dev
);
691 check_channel(channel
);
693 local_irq_save(flags
);
698 if (client
!= chan
->client
) {
699 printk(KERN_ERR
"dma%d: already in use\n", channel
);
700 local_irq_restore(flags
);
703 printk(KERN_ERR
"dma%d: client already has channel\n", channel
);
707 chan
->client
= client
;
710 if (!chan
->irq_claimed
) {
711 pr_debug("dma%d: %s : requesting irq %d\n",
712 channel
, __FUNCTION__
, chan
->irq
);
714 err
= request_irq(chan
->irq
, s3c2410_dma_irq
, SA_INTERRUPT
,
715 client
->name
, (void *)chan
);
719 local_irq_restore(flags
);
721 printk(KERN_ERR
"%s: cannot get IRQ %d for DMA %d\n",
722 client
->name
, chan
->irq
, chan
->number
);
726 chan
->irq_claimed
= 1;
727 chan
->irq_enabled
= 1;
730 local_irq_restore(flags
);
734 pr_debug("%s: channel initialised, %p\n", __FUNCTION__
, chan
);
741 * release the given channel back to the system, will stop and flush
742 * any outstanding transfers, and ensure the channel is ready for the
745 * Note, although a warning is currently printed if the freeing client
746 * info is not the same as the registrant's client info, the free is still
747 * allowed to go through.
750 int s3c2410_dma_free(dmach_t channel
, s3c2410_dma_client_t
*client
)
752 s3c2410_dma_chan_t
*chan
= &s3c2410_chans
[channel
];
755 check_channel(channel
);
757 local_irq_save(flags
);
760 if (chan
->client
!= client
) {
761 printk(KERN_WARNING
"dma%d: possible free from different client (channel %p, passed %p)\n",
762 channel
, chan
->client
, client
);
765 /* sort out stopping and freeing the channel */
767 if (chan
->state
!= S3C2410_DMA_IDLE
) {
768 pr_debug("%s: need to stop dma channel %p\n",
771 /* possibly flush the channel */
772 s3c2410_dma_ctrl(channel
, S3C2410_DMAOP_STOP
);
778 local_irq_restore(flags
);
783 static int s3c2410_dma_dostop(s3c2410_dma_chan_t
*chan
)
788 pr_debug("%s:\n", __FUNCTION__
);
792 local_irq_save(flags
);
794 s3c2410_dma_call_op(chan
, S3C2410_DMAOP_STOP
);
796 tmp
= dma_rdreg(chan
, S3C2410_DMA_DMASKTRIG
);
797 tmp
|= S3C2410_DMASKTRIG_STOP
;
798 dma_wrreg(chan
, S3C2410_DMA_DMASKTRIG
, tmp
);
801 /* should also clear interrupts, according to WinCE BSP */
802 tmp
= dma_rdreg(chan
, S3C2410_DMA_DCON
);
803 tmp
|= S3C2410_DCON_NORELOAD
;
804 dma_wrreg(chan
, S3C2410_DMA_DCON
, tmp
);
807 chan
->state
= S3C2410_DMA_IDLE
;
808 chan
->load_state
= S3C2410_DMALOAD_NONE
;
810 local_irq_restore(flags
);
817 * stop the channel, and remove all current and pending transfers
820 static int s3c2410_dma_flush(s3c2410_dma_chan_t
*chan
)
822 s3c2410_dma_buf_t
*buf
, *next
;
825 pr_debug("%s:\n", __FUNCTION__
);
827 local_irq_save(flags
);
829 if (chan
->state
!= S3C2410_DMA_IDLE
) {
830 pr_debug("%s: stopping channel...\n", __FUNCTION__
);
831 s3c2410_dma_ctrl(chan
->number
, S3C2410_DMAOP_STOP
);
838 chan
->curr
= chan
->next
= chan
->end
= NULL
;
841 for ( ; buf
!= NULL
; buf
= next
) {
844 pr_debug("%s: free buffer %p, next %p\n",
845 __FUNCTION__
, buf
, buf
->next
);
847 s3c2410_dma_buffdone(chan
, buf
, S3C2410_RES_ABORT
);
848 s3c2410_dma_freebuf(buf
);
852 local_irq_restore(flags
);
859 s3c2410_dma_ctrl(dmach_t channel
, s3c2410_chan_op_t op
)
861 s3c2410_dma_chan_t
*chan
= &s3c2410_chans
[channel
];
863 check_channel(channel
);
866 case S3C2410_DMAOP_START
:
867 return s3c2410_dma_start(chan
);
869 case S3C2410_DMAOP_STOP
:
870 return s3c2410_dma_dostop(chan
);
872 case S3C2410_DMAOP_PAUSE
:
875 case S3C2410_DMAOP_RESUME
:
878 case S3C2410_DMAOP_FLUSH
:
879 return s3c2410_dma_flush(chan
);
881 case S3C2410_DMAOP_TIMEOUT
:
886 return -ENOENT
; /* unknown, don't bother */
890 /* DMA configuration for each channel
892 * DISRCC -> source of the DMA (AHB,APB)
893 * DISRC -> source address of the DMA
894 * DIDSTC -> destination of the DMA (AHB,APD)
895 * DIDST -> destination address of the DMA
898 /* s3c2410_dma_config
900 * xfersize: size of unit in bytes (1,2,4)
901 * dcon: base value of the DCONx register
904 int s3c2410_dma_config(dmach_t channel
,
908 s3c2410_dma_chan_t
*chan
= &s3c2410_chans
[channel
];
910 pr_debug("%s: chan=%d, xfer_unit=%d, dcon=%08x\n",
911 __FUNCTION__
, channel
, xferunit
, dcon
);
913 check_channel(channel
);
917 dcon
|= S3C2410_DCON_BYTE
;
921 dcon
|= S3C2410_DCON_HALFWORD
;
925 dcon
|= S3C2410_DCON_WORD
;
929 pr_debug("%s: bad transfer size %d\n", __FUNCTION__
, xferunit
);
933 dcon
|= S3C2410_DCON_HWTRIG
;
934 dcon
|= S3C2410_DCON_INTREQ
;
936 pr_debug("%s: dcon now %08x\n", __FUNCTION__
, dcon
);
939 chan
->xfer_unit
= xferunit
;
945 int s3c2410_dma_setflags(dmach_t channel
, unsigned int flags
)
947 s3c2410_dma_chan_t
*chan
= &s3c2410_chans
[channel
];
949 check_channel(channel
);
951 pr_debug("%s: chan=%p, flags=%08x\n", __FUNCTION__
, chan
, flags
);
958 /* do we need to protect the settings of the fields from
962 int s3c2410_dma_set_opfn(dmach_t channel
, s3c2410_dma_opfn_t rtn
)
964 s3c2410_dma_chan_t
*chan
= &s3c2410_chans
[channel
];
966 check_channel(channel
);
968 pr_debug("%s: chan=%p, op rtn=%p\n", __FUNCTION__
, chan
, rtn
);
975 int s3c2410_dma_set_buffdone_fn(dmach_t channel
, s3c2410_dma_cbfn_t rtn
)
977 s3c2410_dma_chan_t
*chan
= &s3c2410_chans
[channel
];
979 check_channel(channel
);
981 pr_debug("%s: chan=%p, callback rtn=%p\n", __FUNCTION__
, chan
, rtn
);
983 chan
->callback_fn
= rtn
;
988 /* s3c2410_dma_devconfig
990 * configure the dma source/destination hardware type and address
992 * source: S3C2410_DMASRC_HW: source is hardware
993 * S3C2410_DMASRC_MEM: source is memory
995 * hwcfg: the value for xxxSTCn register,
996 * bit 0: 0=increment pointer, 1=leave pointer
997 * bit 1: 0=soucre is AHB, 1=soucre is APB
999 * devaddr: physical address of the source
1002 int s3c2410_dma_devconfig(int channel
,
1003 s3c2410_dmasrc_t source
,
1005 unsigned long devaddr
)
1007 s3c2410_dma_chan_t
*chan
= &s3c2410_chans
[channel
];
1009 check_channel(channel
);
1011 pr_debug("%s: source=%d, hwcfg=%08x, devaddr=%08lx\n",
1012 __FUNCTION__
, (int)source
, hwcfg
, devaddr
);
1014 chan
->source
= source
;
1015 chan
->dev_addr
= devaddr
;
1018 case S3C2410_DMASRC_HW
:
1019 /* source is hardware */
1020 pr_debug("%s: hw source, devaddr=%08lx, hwcfg=%d\n",
1021 __FUNCTION__
, devaddr
, hwcfg
);
1022 dma_wrreg(chan
, S3C2410_DMA_DISRCC
, hwcfg
& 3);
1023 dma_wrreg(chan
, S3C2410_DMA_DISRC
, devaddr
);
1024 dma_wrreg(chan
, S3C2410_DMA_DIDSTC
, (0<<1) | (0<<0));
1026 chan
->addr_reg
= dma_regaddr(chan
, S3C2410_DMA_DIDST
);
1029 case S3C2410_DMASRC_MEM
:
1030 /* source is memory */
1031 pr_debug( "%s: mem source, devaddr=%08lx, hwcfg=%d\n",
1032 __FUNCTION__
, devaddr
, hwcfg
);
1033 dma_wrreg(chan
, S3C2410_DMA_DISRCC
, (0<<1) | (0<<0));
1034 dma_wrreg(chan
, S3C2410_DMA_DIDST
, devaddr
);
1035 dma_wrreg(chan
, S3C2410_DMA_DIDSTC
, hwcfg
& 3);
1037 chan
->addr_reg
= dma_regaddr(chan
, S3C2410_DMA_DISRC
);
1041 printk(KERN_ERR
"dma%d: invalid source type (%d)\n", channel
, source
);
1045 /* initialisation code */
1047 static int __init
s3c2410_init_dma(void)
1050 s3c2410_dma_chan_t
*cp
;
1052 printk("S3C2410 DMA Driver, (c) 2003-2004 Simtec Electronics\n");
1054 dma_base
= ioremap(S3C2410_PA_DMA
, 0x200);
1055 if (dma_base
== NULL
) {
1056 printk(KERN_ERR
"dma failed to remap register block\n");
1060 for (channel
= 0; channel
< S3C2410_DMA_CHANNELS
; channel
++) {
1061 cp
= &s3c2410_chans
[channel
];
1063 memset(cp
, 0, sizeof(s3c2410_dma_chan_t
));
1065 /* dma channel irqs are in order.. */
1066 cp
->number
= channel
;
1067 cp
->irq
= channel
+ IRQ_DMA0
;
1068 cp
->regs
= (unsigned long)dma_base
+ (channel
*0x40);
1070 /* point current stats somewhere */
1071 cp
->stats
= &cp
->stats_store
;
1072 cp
->stats_store
.timeout_shortest
= LONG_MAX
;
1074 /* basic channel configuration */
1076 cp
->load_timeout
= 1<<18;
1078 printk("DMA channel %d at %08lx, irq %d\n",
1079 cp
->number
, cp
->regs
, cp
->irq
);
1085 __initcall(s3c2410_init_dma
);