1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright © 2009 Bertrik Sikken
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
25 #include "dma-target.h"
29 /* Driver for the IODMA part of the s5l8700
31 When requesting a DMA transfer the supplied callback is stored and called
32 upon completion of the DMA transfer (callback runs in interrupt context).
36 #define DMAC_BASE 0x38400000
38 #define DMABASE(c) (*(volatile unsigned int*)(DMAC_BASE+0x00+(0x20*c)))
39 #define DMACON(c) (*(volatile unsigned int*)(DMAC_BASE+0x04+(0x20*c)))
40 #define DMATCNT(c) (*(volatile unsigned int*)(DMAC_BASE+0x08+(0x20*c)))
41 #define DMACADDR(c) (*(volatile unsigned int*)(DMAC_BASE+0x0C+(0x20*c)))
42 #define DMACTCNT(c) (*(volatile unsigned int*)(DMAC_BASE+0x10+(0x20*c)))
43 #define DMACOM(c) (*(volatile unsigned int*)(DMAC_BASE+0x14+(0x20*c)))
44 #define DMANOFF(c) (*(volatile unsigned int*)(DMAC_BASE+0x18+(0x20*c)))
46 #define DMACOM_HOLD 2 /* only allowed on channel 0 */
47 #define DMACOM_SKIP 3 /* only allowed on channel 0 */
48 #define DMACOM_CHAN_ON 4
49 #define DMACOM_CHAN_OFF 5
50 #define DMACOM_CLEAR_HCOM 6
51 #define DMACOM_CLEAR_HCOM_WCOM 7
54 /* one completion callback for each channel */
55 static void (*dma_callback
[4])(void);
62 for (i
= 0; i
< 4; i
++) {
63 dma_callback
[i
] = NULL
;
64 dma_disable_channel(i
);
70 /* setup a DMA transfer, but do not start it yet */
71 void dma_setup_channel(int channel
, int sel
, int dir
, int dsize
, int blen
,
72 void *addr
, size_t size
, void (*callback
)(void))
74 dma_callback
[channel
] = callback
;
76 DMACON(channel
) = (sel
<< 30) | /* DEVSEL */
77 (dir
<< 29) | /* DIR */
78 (0 << 24) | /* SCHCNT */
79 (dsize
<< 22) | /* DSIZE */
80 (blen
<< 19) | /* BLEN */
81 (0 << 18) | /* RELOAD */
82 (0 << 17) | /* HCOMINT */
83 (1 << 16) | /* WCOMINT */
84 (0 << 0); /* OFFSET */
85 DMABASE(channel
) = (unsigned int)addr
;
86 DMATCNT(channel
) = size
- 1;
89 void dma_enable_channel(int channel
)
91 DMACOM(channel
) = DMACOM_CHAN_ON
;
94 void dma_disable_channel(int channel
)
96 DMACOM(channel
) = DMACOM_CHAN_OFF
;
99 /* interrupt handler for all DMA channels */
105 mask
= (1 << 0) | /* WCOMx interrupt bit */
106 (1 << 1); /* HCOMx interrupt bit */
107 for (channel
= 0; channel
< 4; channel
++) {
108 if (DMAALLST
& mask
) {
109 /* clear half and whole completion bits */
110 DMACOM(channel
) = DMACOM_CLEAR_HCOM_WCOM
;
112 if (dma_callback
[channel
]) {
113 dma_callback
[channel
]();