This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / arch / arm / mach-s3c2410 / dma.c
1 /* linux/arch/arm/mach-bast/dma.c
2  *
3  * (c) 2003,2004 Simtec Electronics
4  * Ben Dooks <ben@simtec.co.uk>
5  *
6  * S3C2410 DMA core
7  *
8  * http://www.simtec.co.uk/products/EB2410ITX/
9  *
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.
13  *
14  * Changelog:
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
21  *
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.
25  *
26  * The re-write is pretty much complete, and should be good enough for any
27  * possible DMA function
28  */
29
30 #include <linux/config.h>
31
32 #ifdef CONFIG_S3C2410_DMA_DEBUG
33 #define DEBUG
34 #endif
35
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>
44
45 #include <asm/system.h>
46 #include <asm/irq.h>
47 #include <asm/hardware.h>
48 #include <asm/io.h>
49 #include <asm/dma.h>
50
51 #include <asm/mach/dma.h>
52 #include <asm/arch/map.h>
53
54 /* io map for dma */
55 static void *dma_base;
56
57 /* dma channel state information */
58 s3c2410_dma_chan_t s3c2410_chans[S3C2410_DMA_CHANNELS];
59
60 /* debugging functions */
61
62 #define BUF_MAGIC (0xcafebabe)
63
64 #define dmawarn(fmt...) printk(KERN_DEBUG fmt)
65
66 #define dma_regaddr(chan, reg) ((chan)->regs + (reg))
67
68 #if 1
69 #define dma_wrreg(chan, reg, val) writel((val), (chan)->regs + (reg))
70 #else
71 static inline void
72 dma_wrreg(s3c2410_dma_chan_t *chan, int reg, unsigned long val)
73 {
74         pr_debug("writing %08x to register %08x\n",(unsigned int)val,reg);
75         writel(val, dma_regaddr(chan, reg));
76 }
77
78 #endif
79
80 #define dma_rdreg(chan, reg) readl((chan)->regs + (reg))
81
82 /* captured register state for debug */
83
84 struct s3c2410_dma_regstate {
85         unsigned long         dcsrc;
86         unsigned long         disrc;
87         unsigned long         dstat;
88         unsigned long         dcon;
89         unsigned long         dmsktrig;
90 };
91
92 #ifdef CONFIG_S3C2410_DMA_DEBUG
93
94 /* dmadbg_showregs
95  *
96  * simple debug routine to print the current state of the dma registers
97 */
98
99 static void
100 dmadbg_capture(s3c2410_dma_chan_t *chan, struct s3c2410_dma_regstate *regs)
101 {
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);
107 }
108
109 static void
110 dmadbg_showregs(const char *fname, int line, s3c2410_dma_chan_t *chan,
111                  struct s3c2410_dma_regstate *regs)
112 {
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,
116                regs->dcon);
117 }
118
119 static void
120 dmadbg_showchan(const char *fname, int line, s3c2410_dma_chan_t *chan)
121 {
122         struct s3c2410_dma_regstate state;
123
124         dmadbg_capture(chan, &state);
125
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);
129
130         dmadbg_showregs(fname, line, chan, &state);
131 }
132
133 #define dbg_showregs(chan) dmadbg_showregs(__FUNCTION__, __LINE__, (chan))
134 #define dbg_showchan(chan) dmadbg_showchan(__FUNCTION__, __LINE__, (chan))
135 #else
136 #define dbg_showregs(chan) do { } while(0)
137 #define dbg_showchan(chan) do { } while(0)
138 #endif /* CONFIG_S3C2410_DMA_DEBUG */
139
140 #define check_channel(chan) \
141   do { if ((chan) >= S3C2410_DMA_CHANNELS) { \
142     printk(KERN_ERR "%s: invalid channel %d\n", __FUNCTION__, (chan)); \
143     return -EINVAL; \
144   } } while(0)
145
146
147 /* s3c2410_dma_stats_timeout
148  *
149  * Update DMA stats from timeout info
150 */
151
152 static void
153 s3c2410_dma_stats_timeout(s3c2410_dma_stats_t *stats, int val)
154 {
155         if (stats == NULL)
156                 return;
157
158         if (val > stats->timeout_longest)
159                 stats->timeout_longest = val;
160         if (val < stats->timeout_shortest)
161                 stats->timeout_shortest = val;
162
163         stats->timeout_avg += val;
164 }
165
166 /* s3c2410_dma_waitforload
167  *
168  * wait for the DMA engine to load a buffer, and update the state accordingly
169 */
170
171 static int
172 s3c2410_dma_waitforload(s3c2410_dma_chan_t *chan, int line)
173 {
174         int timeout = chan->load_timeout;
175         int took;
176
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);
179                 return 0;
180         }
181
182         if (chan->stats != NULL)
183                 chan->stats->loads++;
184
185         while (--timeout > 0) {
186                 if ((dma_rdreg(chan, S3C2410_DMA_DSTAT) << (32-20)) != 0) {
187                         took = chan->load_timeout - timeout;
188
189                         s3c2410_dma_stats_timeout(chan->stats, took);
190
191                         switch (chan->load_state) {
192                         case S3C2410_DMALOAD_1LOADED:
193                                 chan->load_state = S3C2410_DMALOAD_1RUNNING;
194                                 break;
195
196                         default:
197                                 printk(KERN_ERR "dma%d: unknown load_state in s3c2410_dma_waitforload() %d\n", chan->number, chan->load_state);
198                         }
199
200                         return 1;
201                 }
202         }
203
204         if (chan->stats != NULL) {
205                 chan->stats->timeout_failed++;
206         }
207
208         return 0;
209 }
210
211
212
213 /* s3c2410_dma_loadbuffer
214  *
215  * load a buffer, and update the channel state
216 */
217
218 static inline int
219 s3c2410_dma_loadbuffer(s3c2410_dma_chan_t *chan,
220                        s3c2410_dma_buf_t *buf)
221 {
222         unsigned long reload;
223
224         pr_debug("s3c2410_chan_loadbuffer: loading buff %p (0x%08lx,0x%06x)\n",
225                  buf, (unsigned long)buf->data, buf->size);
226
227         if (buf == NULL) {
228                 dmawarn("buffer is NULL\n");
229                 return -EINVAL;
230         }
231
232         /* check the state of the channel before we do anything */
233
234         if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
235                 dmawarn("load_state is S3C2410_DMALOAD_1LOADED\n");
236         }
237
238         if (chan->load_state == S3C2410_DMALOAD_1LOADED_1RUNNING) {
239                 dmawarn("state is S3C2410_DMALOAD_1LOADED_1RUNNING\n");
240         }
241
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...
245          */
246         if (chan->load_state == S3C2410_DMALOAD_NONE) {
247                 pr_debug("load_state is none, checking for noreload (next=%p)\n",
248                          buf->next);
249                 reload = (buf->next == NULL) ? S3C2410_DCON_NORELOAD : 0;
250         } else {
251                 pr_debug("load_state is %d => autoreload\n", chan->load_state);
252                 reload = S3C2410_DCON_AUTORELOAD;
253         }
254
255         writel(buf->data, chan->addr_reg);
256
257         dma_wrreg(chan, S3C2410_DMA_DCON,
258                   chan->dcon | reload | (buf->size/chan->xfer_unit));
259
260         chan->next = buf->next;
261
262         /* update the state of the channel */
263
264         switch (chan->load_state) {
265         case S3C2410_DMALOAD_NONE:
266                 chan->load_state = S3C2410_DMALOAD_1LOADED;
267                 break;
268
269         case S3C2410_DMALOAD_1RUNNING:
270                 chan->load_state = S3C2410_DMALOAD_1LOADED_1RUNNING;
271                 break;
272
273         default:
274                 dmawarn("dmaload: unknown state %d in loadbuffer\n",
275                         chan->load_state);
276                 break;
277         }
278
279         return 0;
280 }
281
282 /* s3c2410_dma_call_op
283  *
284  * small routine to call the op routine with the given op if it has been
285  * registered
286 */
287
288 static void
289 s3c2410_dma_call_op(s3c2410_dma_chan_t *chan, s3c2410_chan_op_t op)
290 {
291         if (chan->op_fn != NULL) {
292                 (chan->op_fn)(chan, op);
293         }
294 }
295
296 /* s3c2410_dma_buffdone
297  *
298  * small wrapper to check if callback routine needs to be called, and
299  * if so, call it
300 */
301
302 static inline void
303 s3c2410_dma_buffdone(s3c2410_dma_chan_t *chan, s3c2410_dma_buf_t *buf,
304                      s3c2410_dma_buffresult_t result)
305 {
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);
308
309         if (chan->callback_fn != NULL) {
310                 (chan->callback_fn)(chan, buf->id, buf->size, result);
311         }
312 }
313
314 /* s3c2410_dma_start
315  *
316  * start a dma channel going
317 */
318
319 static int s3c2410_dma_start(s3c2410_dma_chan_t *chan)
320 {
321         unsigned long tmp;
322         unsigned long flags;
323
324         pr_debug("s3c2410_start_dma: channel=%d\n", chan->number);
325
326         local_irq_save(flags);
327
328         if (chan->state == S3C2410_DMA_RUNNING) {
329                 pr_debug("s3c2410_start_dma: already running (%d)\n", chan->state);
330                 local_irq_restore(flags);
331                 return 0;
332         }
333
334         chan->state = S3C2410_DMA_RUNNING;
335
336         /* check wether there is anything to load, and if not, see
337          * if we can find anything to load
338          */
339
340         if (chan->load_state == S3C2410_DMALOAD_NONE) {
341                 if (chan->next == NULL) {
342                         printk(KERN_ERR "dma%d: channel has nothing loaded\n",
343                                chan->number);
344                         chan->state = S3C2410_DMA_IDLE;
345                         local_irq_restore(flags);
346                         return -EINVAL;
347                 }
348
349                 s3c2410_dma_loadbuffer(chan, chan->next);
350         }
351
352         dbg_showchan(chan);
353
354         /* enable the channel */
355
356         if (!chan->irq_enabled) {
357                 enable_irq(chan->irq);
358                 chan->irq_enabled = 1;
359         }
360
361         /* start the channel going */
362
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);
367
368         pr_debug("wrote %08lx to DMASKTRIG\n", tmp);
369
370 #if 0
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);
376 #endif
377
378         s3c2410_dma_call_op(chan, S3C2410_DMAOP_START);
379
380         dbg_showchan(chan);
381
382         local_irq_restore(flags);
383         return 0;
384 }
385
386 /* s3c2410_dma_canload
387  *
388  * work out if we can queue another buffer into the DMA engine
389 */
390
391 static int
392 s3c2410_dma_canload(s3c2410_dma_chan_t *chan)
393 {
394         if (chan->load_state == S3C2410_DMALOAD_NONE ||
395             chan->load_state == S3C2410_DMALOAD_1RUNNING)
396                 return 1;
397
398         return 0;
399 }
400
401
402 /* s3c2410_dma_enqueue
403  *
404  * queue an given buffer for dma transfer.
405  *
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
409  *
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.
413  *
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
416  * when necessary.
417 */
418
419 int s3c2410_dma_enqueue(unsigned int channel, void *id,
420                         dma_addr_t data, int size)
421 {
422         s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
423         s3c2410_dma_buf_t *buf;
424         unsigned long flags;
425
426         check_channel(channel);
427
428         pr_debug("%s: id=%p, data=%08x, size=%d\n",
429                  __FUNCTION__, id, (unsigned int)data, size);
430
431         buf = (s3c2410_dma_buf_t *)kmalloc(sizeof(*buf), GFP_ATOMIC);
432         if (buf == NULL) {
433                 pr_debug("%s: out of memory (%d alloc)\n",
434                          __FUNCTION__, sizeof(*buf));
435                 return -ENOMEM;
436         }
437
438         pr_debug("%s: new buffer %p\n", __FUNCTION__, buf);
439
440         //dbg_showchan(chan);
441
442         buf->next  = NULL;
443         buf->data  = buf->ptr = data;
444         buf->size  = size;
445         buf->id    = id;
446         buf->magic = BUF_MAGIC;
447
448         local_irq_save(flags);
449
450         if (chan->curr == NULL) {
451                 /* we've got nothing loaded... */
452                 pr_debug("%s: buffer %p queued onto empty channel\n",
453                          __FUNCTION__, buf);
454
455                 chan->curr = buf;
456                 chan->end  = buf;
457                 chan->next = NULL;
458         } else {
459                 pr_debug("dma%d: %s: buffer %p queued onto non-empty channel\n",
460                          chan->number, __FUNCTION__, buf);
461
462                 if (chan->end == NULL)
463                         pr_debug("dma%d: %s: %p not empty, and chan->end==NULL?\n",
464                                  chan->number, __FUNCTION__, chan);
465
466                 chan->end->next = buf;
467                 chan->end = buf;
468         }
469
470         /* if necessary, update the next buffer field */
471         if (chan->next == NULL)
472                 chan->next = buf;
473
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",
480                                        chan->number);
481                                 dbg_showchan(chan);
482                                 local_irq_restore(flags);
483                                 return -EINVAL;
484                         }
485                 }
486
487                 while (s3c2410_dma_canload(chan) && chan->next != NULL) {
488                         s3c2410_dma_loadbuffer(chan, chan->next);
489                 }
490         } else if (chan->state == S3C2410_DMA_IDLE) {
491                 if (chan->flags & S3C2410_DMAF_AUTOSTART) {
492                         s3c2410_dma_ctrl(chan->number, S3C2410_DMAOP_START);
493                 } else {
494                         printk(KERN_DEBUG "dma%d: cannot load onto stopped channel'n", chan->number);
495                         local_irq_restore(flags);
496                         return -EINVAL;
497                 }
498         }
499
500         local_irq_restore(flags);
501         return 0;
502 }
503
504 static inline void
505 s3c2410_dma_freebuf(s3c2410_dma_buf_t *buf)
506 {
507         int magicok = (buf->magic == BUF_MAGIC);
508
509         buf->magic = -1;
510
511         if (magicok) {
512                 kfree(buf);
513         } else {
514                 printk("s3c2410_dma_freebuf: buff %p with bad magic\n", buf);
515         }
516 }
517
518 /* s3c2410_dma_lastxfer
519  *
520  * called when the system is out of buffers, to ensure that the channel
521  * is prepared for shutdown.
522 */
523
524 static inline void
525 s3c2410_dma_lastxfer(s3c2410_dma_chan_t *chan)
526 {
527         pr_debug("dma%d: s3c2410_dma_lastxfer: load_state %d\n",
528                  chan->number, chan->load_state);
529
530         switch (chan->load_state) {
531         case S3C2410_DMALOAD_NONE:
532                 break;
533
534         case S3C2410_DMALOAD_1LOADED:
535                 if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
536                                 /* flag error? */
537                         printk(KERN_ERR "dma%d: timeout waiting for load\n",
538                                chan->number);
539                         return;
540                 }
541                 break;
542
543         default:
544                 pr_debug("dma%d: lastxfer: unhandled load_state %d with no next",
545                          chan->number, chan->load_state);
546                 return;
547
548         }
549
550         /* hopefully this'll shut the damned thing up after the transfer... */
551         dma_wrreg(chan, S3C2410_DMA_DCON, chan->dcon | S3C2410_DCON_NORELOAD);
552 }
553
554
555 #define dmadbg2(x...)
556
557 static irqreturn_t
558 s3c2410_dma_irq(int irq, void *devpw, struct pt_regs *regs)
559 {
560         s3c2410_dma_chan_t *chan = (s3c2410_dma_chan_t *)devpw;
561         s3c2410_dma_buf_t  *buf;
562
563         buf = chan->curr;
564
565         dbg_showchan(chan);
566
567         /* modify the channel state */
568
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
573                  * callback */
574
575                 chan->load_state = S3C2410_DMALOAD_NONE;
576                 break;
577
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
581                  * loaded.
582                  */
583
584                 chan->load_state = S3C2410_DMALOAD_NONE;
585                 break;
586
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
592                  */
593
594                 chan->load_state = S3C2410_DMALOAD_1LOADED;
595                 break;
596
597         case S3C2410_DMALOAD_NONE:
598                 printk(KERN_ERR "dma%d: IRQ with no loaded buffer?\n",
599                        chan->number);
600                 break;
601
602         default:
603                 printk(KERN_ERR "dma%d: IRQ in invalid load_state %d\n",
604                        chan->number, chan->load_state);
605                 break;
606         }
607
608         if (buf != NULL) {
609                 /* update the chain to make sure that if we load any more
610                  * buffers when we call the callback function, things should
611                  * work properly */
612
613                 chan->curr = buf->next;
614                 buf->next  = NULL;
615
616                 if (buf->magic != BUF_MAGIC) {
617                         printk(KERN_ERR "dma%d: %s: buf %p incorrect magic\n",
618                                chan->number, __FUNCTION__, buf);
619                         return IRQ_HANDLED;
620                 }
621
622                 s3c2410_dma_buffdone(chan, buf, S3C2410_RES_OK);
623
624                 /* free resouces */
625                 s3c2410_dma_freebuf(buf);
626         } else {
627         }
628
629         if (chan->next != NULL) {
630                 unsigned long flags;
631
632                 switch (chan->load_state) {
633                 case S3C2410_DMALOAD_1RUNNING:
634                         /* don't need to do anything for this state */
635                         break;
636
637                 case S3C2410_DMALOAD_NONE:
638                         /* can load buffer immediately */
639                         break;
640
641                 case S3C2410_DMALOAD_1LOADED:
642                         if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
643                                 /* flag error? */
644                                 printk(KERN_ERR "dma%d: timeout waiting for load\n",
645                                        chan->number);
646                                 return IRQ_HANDLED;
647                         }
648
649                         break;
650
651                 default:
652                         printk(KERN_ERR "dma%d: unknown load_state in irq, %d\n",
653                                chan->number, chan->load_state);
654                         return IRQ_HANDLED;
655                 }
656
657                 local_irq_save(flags);
658                 s3c2410_dma_loadbuffer(chan, chan->next);
659                 local_irq_restore(flags);
660         } else {
661                 s3c2410_dma_lastxfer(chan);
662
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);
668                 }
669         }
670
671         return IRQ_HANDLED;
672 }
673
674
675
676 /* s3c2410_request_dma
677  *
678  * get control of an dma channel
679 */
680
681 int s3c2410_dma_request(unsigned int channel, s3c2410_dma_client_t *client,
682                         void *dev)
683 {
684         s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
685         unsigned long flags;
686         int err;
687
688         pr_debug("dma%d: s3c2410_request_dma: client=%s, dev=%p\n",
689                  channel, client->name, dev);
690
691         check_channel(channel);
692
693         local_irq_save(flags);
694
695         dbg_showchan(chan);
696
697         if (chan->in_use) {
698                 if (client != chan->client) {
699                         printk(KERN_ERR "dma%d: already in use\n", channel);
700                         local_irq_restore(flags);
701                         return -EBUSY;
702                 } else {
703                         printk(KERN_ERR "dma%d: client already has channel\n", channel);
704                 }
705         }
706
707         chan->client = client;
708         chan->in_use = 1;
709
710         if (!chan->irq_claimed) {
711                 pr_debug("dma%d: %s : requesting irq %d\n",
712                          channel, __FUNCTION__, chan->irq);
713
714                 err = request_irq(chan->irq, s3c2410_dma_irq, SA_INTERRUPT,
715                                   client->name, (void *)chan);
716
717                 if (err) {
718                         chan->in_use = 0;
719                         local_irq_restore(flags);
720
721                         printk(KERN_ERR "%s: cannot get IRQ %d for DMA %d\n",
722                                client->name, chan->irq, chan->number);
723                         return err;
724                 }
725
726                 chan->irq_claimed = 1;
727                 chan->irq_enabled = 1;
728         }
729
730         local_irq_restore(flags);
731
732         /* need to setup */
733
734         pr_debug("%s: channel initialised, %p\n", __FUNCTION__, chan);
735
736         return 0;
737 }
738
739 /* s3c2410_dma_free
740  *
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
743  * next claimant.
744  *
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.
748 */
749
750 int s3c2410_dma_free(dmach_t channel, s3c2410_dma_client_t *client)
751 {
752         s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
753         unsigned long flags;
754
755         check_channel(channel);
756
757         local_irq_save(flags);
758
759
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);
763         }
764
765         /* sort out stopping and freeing the channel */
766
767         if (chan->state != S3C2410_DMA_IDLE) {
768                 pr_debug("%s: need to stop dma channel %p\n",
769                        __FUNCTION__, chan);
770
771                 /* possibly flush the channel */
772                 s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STOP);
773         }
774
775         chan->client = NULL;
776         chan->in_use = 0;
777
778         local_irq_restore(flags);
779
780         return 0;
781 }
782
783 static int s3c2410_dma_dostop(s3c2410_dma_chan_t *chan)
784 {
785         unsigned long tmp;
786         unsigned long flags;
787
788         pr_debug("%s:\n", __FUNCTION__);
789
790         dbg_showchan(chan);
791
792         local_irq_save(flags);
793
794         s3c2410_dma_call_op(chan,  S3C2410_DMAOP_STOP);
795
796         tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
797         tmp |= S3C2410_DMASKTRIG_STOP;
798         dma_wrreg(chan, S3C2410_DMA_DMASKTRIG, tmp);
799
800 #if 0
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);
805 #endif
806
807         chan->state      = S3C2410_DMA_IDLE;
808         chan->load_state = S3C2410_DMALOAD_NONE;
809
810         local_irq_restore(flags);
811
812         return 0;
813 }
814
815 /* s3c2410_dma_flush
816  *
817  * stop the channel, and remove all current and pending transfers
818 */
819
820 static int s3c2410_dma_flush(s3c2410_dma_chan_t *chan)
821 {
822         s3c2410_dma_buf_t *buf, *next;
823         unsigned long flags;
824
825         pr_debug("%s:\n", __FUNCTION__);
826
827         local_irq_save(flags);
828
829         if (chan->state != S3C2410_DMA_IDLE) {
830                 pr_debug("%s: stopping channel...\n", __FUNCTION__ );
831                 s3c2410_dma_ctrl(chan->number, S3C2410_DMAOP_STOP);
832         }
833
834         buf = chan->curr;
835         if (buf == NULL)
836                 buf = chan->next;
837
838         chan->curr = chan->next = chan->end = NULL;
839
840         if (buf != NULL) {
841                 for ( ; buf != NULL; buf = next) {
842                         next = buf->next;
843
844                         pr_debug("%s: free buffer %p, next %p\n",
845                                __FUNCTION__, buf, buf->next);
846
847                         s3c2410_dma_buffdone(chan, buf, S3C2410_RES_ABORT);
848                         s3c2410_dma_freebuf(buf);
849                 }
850         }
851
852         local_irq_restore(flags);
853
854         return 0;
855 }
856
857
858 int
859 s3c2410_dma_ctrl(dmach_t channel, s3c2410_chan_op_t op)
860 {
861         s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
862
863         check_channel(channel);
864
865         switch (op) {
866         case S3C2410_DMAOP_START:
867                 return s3c2410_dma_start(chan);
868
869         case S3C2410_DMAOP_STOP:
870                 return s3c2410_dma_dostop(chan);
871
872         case S3C2410_DMAOP_PAUSE:
873                 return -ENOENT;
874
875         case S3C2410_DMAOP_RESUME:
876                 return -ENOENT;
877
878         case S3C2410_DMAOP_FLUSH:
879                 return s3c2410_dma_flush(chan);
880
881         case S3C2410_DMAOP_TIMEOUT:
882                 return 0;
883
884         }
885
886         return -ENOENT;      /* unknown, don't bother */
887 }
888
889
890 /* DMA configuration for each channel
891  *
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
896 */
897
898 /* s3c2410_dma_config
899  *
900  * xfersize:     size of unit in bytes (1,2,4)
901  * dcon:         base value of the DCONx register
902 */
903
904 int s3c2410_dma_config(dmach_t channel,
905                        int xferunit,
906                        int dcon)
907 {
908         s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
909
910         pr_debug("%s: chan=%d, xfer_unit=%d, dcon=%08x\n",
911                  __FUNCTION__, channel, xferunit, dcon);
912
913         check_channel(channel);
914
915         switch (xferunit) {
916         case 1:
917                 dcon |= S3C2410_DCON_BYTE;
918                 break;
919
920         case 2:
921                 dcon |= S3C2410_DCON_HALFWORD;
922                 break;
923
924         case 4:
925                 dcon |= S3C2410_DCON_WORD;
926                 break;
927
928         default:
929                 pr_debug("%s: bad transfer size %d\n", __FUNCTION__, xferunit);
930                 return -EINVAL;
931         }
932
933         dcon |= S3C2410_DCON_HWTRIG;
934         dcon |= S3C2410_DCON_INTREQ;
935
936         pr_debug("%s: dcon now %08x\n", __FUNCTION__, dcon);
937
938         chan->dcon = dcon;
939         chan->xfer_unit = xferunit;
940
941         return 0;
942 }
943
944
945 int s3c2410_dma_setflags(dmach_t channel, unsigned int flags)
946 {
947         s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
948
949         check_channel(channel);
950
951         pr_debug("%s: chan=%p, flags=%08x\n", __FUNCTION__, chan, flags);
952
953         chan->flags = flags;
954
955         return 0;
956 }
957
958 /* do we need to protect the settings of the fields from
959  * irq?
960 */
961
962 int s3c2410_dma_set_opfn(dmach_t channel, s3c2410_dma_opfn_t rtn)
963 {
964         s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
965
966         check_channel(channel);
967
968         pr_debug("%s: chan=%p, op rtn=%p\n", __FUNCTION__, chan, rtn);
969
970         chan->op_fn = rtn;
971
972         return 0;
973 }
974
975 int s3c2410_dma_set_buffdone_fn(dmach_t channel, s3c2410_dma_cbfn_t rtn)
976 {
977         s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
978
979         check_channel(channel);
980
981         pr_debug("%s: chan=%p, callback rtn=%p\n", __FUNCTION__, chan, rtn);
982
983         chan->callback_fn = rtn;
984
985         return 0;
986 }
987
988 /* s3c2410_dma_devconfig
989  *
990  * configure the dma source/destination hardware type and address
991  *
992  * source:    S3C2410_DMASRC_HW: source is hardware
993  *            S3C2410_DMASRC_MEM: source is memory
994  *
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
998  *
999  * devaddr:   physical address of the source
1000 */
1001
1002 int s3c2410_dma_devconfig(int channel,
1003                           s3c2410_dmasrc_t source,
1004                           int hwcfg,
1005                           unsigned long devaddr)
1006 {
1007         s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
1008
1009         check_channel(channel);
1010
1011         pr_debug("%s: source=%d, hwcfg=%08x, devaddr=%08lx\n",
1012                  __FUNCTION__, (int)source, hwcfg, devaddr);
1013
1014         chan->source = source;
1015         chan->dev_addr = devaddr;
1016
1017         switch (source) {
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));
1025
1026                 chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DIDST);
1027                 return 0;
1028
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);
1036
1037                 chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DISRC);
1038                 return 0;
1039         }
1040
1041         printk(KERN_ERR "dma%d: invalid source type (%d)\n", channel, source);
1042         return -EINVAL;
1043 }
1044
1045 /* initialisation code */
1046
1047 static int __init s3c2410_init_dma(void)
1048 {
1049         int channel;
1050         s3c2410_dma_chan_t *cp;
1051
1052         printk("S3C2410 DMA Driver, (c) 2003-2004 Simtec Electronics\n");
1053
1054         dma_base = ioremap(S3C2410_PA_DMA, 0x200);
1055         if (dma_base == NULL) {
1056                 printk(KERN_ERR "dma failed to remap register block\n");
1057                 return -ENOMEM;
1058         }
1059
1060         for (channel = 0; channel < S3C2410_DMA_CHANNELS; channel++) {
1061                 cp = &s3c2410_chans[channel];
1062
1063                 memset(cp, 0, sizeof(s3c2410_dma_chan_t));
1064
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);
1069
1070                 /* point current stats somewhere */
1071                 cp->stats  = &cp->stats_store;
1072                 cp->stats_store.timeout_shortest = LONG_MAX;
1073
1074                 /* basic channel configuration */
1075
1076                 cp->load_timeout = 1<<18;
1077
1078                 printk("DMA channel %d at %08lx, irq %d\n",
1079                        cp->number, cp->regs, cp->irq);
1080         }
1081
1082         return 0;
1083 }
1084
1085 __initcall(s3c2410_init_dma);