diff options
Diffstat (limited to 'firmware/target/arm/s5l8700/dma-s5l8700.c')
-rwxr-xr-x | firmware/target/arm/s5l8700/dma-s5l8700.c | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/firmware/target/arm/s5l8700/dma-s5l8700.c b/firmware/target/arm/s5l8700/dma-s5l8700.c new file mode 100755 index 0000000000..f766cef98a --- /dev/null +++ b/firmware/target/arm/s5l8700/dma-s5l8700.c | |||
@@ -0,0 +1,119 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright © 2009 Bertrik Sikken | ||
11 | * | ||
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. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #include "config.h" | ||
23 | |||
24 | #include "s5l8700.h" | ||
25 | #include "dma-target.h" | ||
26 | #include "panic.h" | ||
27 | #include "system.h" | ||
28 | |||
29 | /* Driver for the IODMA part of the s5l8700 | ||
30 | |||
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). | ||
33 | */ | ||
34 | |||
35 | |||
36 | #define DMAC_BASE 0x38400000 | ||
37 | |||
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))) | ||
45 | |||
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 | ||
52 | |||
53 | |||
54 | /* one completion callback for each channel */ | ||
55 | static void (*dma_callback[4])(void); | ||
56 | |||
57 | |||
58 | void dma_init(void) | ||
59 | { | ||
60 | int i; | ||
61 | |||
62 | for (i = 0; i < 4; i++) { | ||
63 | dma_callback[i] = NULL; | ||
64 | dma_disable_channel(i); | ||
65 | } | ||
66 | |||
67 | INTMSK |= (1 << 10); | ||
68 | } | ||
69 | |||
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)) | ||
73 | { | ||
74 | dma_callback[channel] = callback; | ||
75 | |||
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; | ||
87 | } | ||
88 | |||
89 | void dma_enable_channel(int channel) | ||
90 | { | ||
91 | DMACOM(channel) = DMACOM_CHAN_ON; | ||
92 | } | ||
93 | |||
94 | void dma_disable_channel(int channel) | ||
95 | { | ||
96 | DMACOM(channel) = DMACOM_CHAN_OFF; | ||
97 | } | ||
98 | |||
99 | /* interrupt handler for all DMA channels */ | ||
100 | void INT_DMA(void) | ||
101 | { | ||
102 | unsigned int mask; | ||
103 | int channel; | ||
104 | |||
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; | ||
111 | |||
112 | if (dma_callback[channel]) { | ||
113 | dma_callback[channel](); | ||
114 | } | ||
115 | } | ||
116 | mask <<= 4; | ||
117 | } | ||
118 | } | ||
119 | |||