aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/dma.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/kernel/dma.c')
-rw-r--r--arch/arm/kernel/dma.c119
1 files changed, 67 insertions, 52 deletions
diff --git a/arch/arm/kernel/dma.c b/arch/arm/kernel/dma.c
index d006085ed7e7..7d5b9fb01e71 100644
--- a/arch/arm/kernel/dma.c
+++ b/arch/arm/kernel/dma.c
@@ -15,6 +15,7 @@
15#include <linux/init.h> 15#include <linux/init.h>
16#include <linux/spinlock.h> 16#include <linux/spinlock.h>
17#include <linux/errno.h> 17#include <linux/errno.h>
18#include <linux/scatterlist.h>
18 19
19#include <asm/dma.h> 20#include <asm/dma.h>
20 21
@@ -23,19 +24,40 @@
23DEFINE_SPINLOCK(dma_spin_lock); 24DEFINE_SPINLOCK(dma_spin_lock);
24EXPORT_SYMBOL(dma_spin_lock); 25EXPORT_SYMBOL(dma_spin_lock);
25 26
26static dma_t dma_chan[MAX_DMA_CHANNELS]; 27static dma_t *dma_chan[MAX_DMA_CHANNELS];
28
29static inline dma_t *dma_channel(unsigned int chan)
30{
31 if (chan >= MAX_DMA_CHANNELS)
32 return NULL;
33
34 return dma_chan[chan];
35}
36
37int __init isa_dma_add(unsigned int chan, dma_t *dma)
38{
39 if (!dma->d_ops)
40 return -EINVAL;
41
42 sg_init_table(&dma->buf, 1);
43
44 if (dma_chan[chan])
45 return -EBUSY;
46 dma_chan[chan] = dma;
47 return 0;
48}
27 49
28/* 50/*
29 * Request DMA channel 51 * Request DMA channel
30 * 52 *
31 * On certain platforms, we have to allocate an interrupt as well... 53 * On certain platforms, we have to allocate an interrupt as well...
32 */ 54 */
33int request_dma(dmach_t channel, const char *device_id) 55int request_dma(unsigned int chan, const char *device_id)
34{ 56{
35 dma_t *dma = dma_chan + channel; 57 dma_t *dma = dma_channel(chan);
36 int ret; 58 int ret;
37 59
38 if (channel >= MAX_DMA_CHANNELS || !dma->d_ops) 60 if (!dma)
39 goto bad_dma; 61 goto bad_dma;
40 62
41 if (xchg(&dma->lock, 1) != 0) 63 if (xchg(&dma->lock, 1) != 0)
@@ -47,7 +69,7 @@ int request_dma(dmach_t channel, const char *device_id)
47 69
48 ret = 0; 70 ret = 0;
49 if (dma->d_ops->request) 71 if (dma->d_ops->request)
50 ret = dma->d_ops->request(channel, dma); 72 ret = dma->d_ops->request(chan, dma);
51 73
52 if (ret) 74 if (ret)
53 xchg(&dma->lock, 0); 75 xchg(&dma->lock, 0);
@@ -55,7 +77,7 @@ int request_dma(dmach_t channel, const char *device_id)
55 return ret; 77 return ret;
56 78
57bad_dma: 79bad_dma:
58 printk(KERN_ERR "dma: trying to allocate DMA%d\n", channel); 80 printk(KERN_ERR "dma: trying to allocate DMA%d\n", chan);
59 return -EINVAL; 81 return -EINVAL;
60 82
61busy: 83busy:
@@ -68,42 +90,42 @@ EXPORT_SYMBOL(request_dma);
68 * 90 *
69 * On certain platforms, we have to free interrupt as well... 91 * On certain platforms, we have to free interrupt as well...
70 */ 92 */
71void free_dma(dmach_t channel) 93void free_dma(unsigned int chan)
72{ 94{
73 dma_t *dma = dma_chan + channel; 95 dma_t *dma = dma_channel(chan);
74 96
75 if (channel >= MAX_DMA_CHANNELS || !dma->d_ops) 97 if (!dma)
76 goto bad_dma; 98 goto bad_dma;
77 99
78 if (dma->active) { 100 if (dma->active) {
79 printk(KERN_ERR "dma%d: freeing active DMA\n", channel); 101 printk(KERN_ERR "dma%d: freeing active DMA\n", chan);
80 dma->d_ops->disable(channel, dma); 102 dma->d_ops->disable(chan, dma);
81 dma->active = 0; 103 dma->active = 0;
82 } 104 }
83 105
84 if (xchg(&dma->lock, 0) != 0) { 106 if (xchg(&dma->lock, 0) != 0) {
85 if (dma->d_ops->free) 107 if (dma->d_ops->free)
86 dma->d_ops->free(channel, dma); 108 dma->d_ops->free(chan, dma);
87 return; 109 return;
88 } 110 }
89 111
90 printk(KERN_ERR "dma%d: trying to free free DMA\n", channel); 112 printk(KERN_ERR "dma%d: trying to free free DMA\n", chan);
91 return; 113 return;
92 114
93bad_dma: 115bad_dma:
94 printk(KERN_ERR "dma: trying to free DMA%d\n", channel); 116 printk(KERN_ERR "dma: trying to free DMA%d\n", chan);
95} 117}
96EXPORT_SYMBOL(free_dma); 118EXPORT_SYMBOL(free_dma);
97 119
98/* Set DMA Scatter-Gather list 120/* Set DMA Scatter-Gather list
99 */ 121 */
100void set_dma_sg (dmach_t channel, struct scatterlist *sg, int nr_sg) 122void set_dma_sg (unsigned int chan, struct scatterlist *sg, int nr_sg)
101{ 123{
102 dma_t *dma = dma_chan + channel; 124 dma_t *dma = dma_channel(chan);
103 125
104 if (dma->active) 126 if (dma->active)
105 printk(KERN_ERR "dma%d: altering DMA SG while " 127 printk(KERN_ERR "dma%d: altering DMA SG while "
106 "DMA active\n", channel); 128 "DMA active\n", chan);
107 129
108 dma->sg = sg; 130 dma->sg = sg;
109 dma->sgcount = nr_sg; 131 dma->sgcount = nr_sg;
@@ -115,13 +137,13 @@ EXPORT_SYMBOL(set_dma_sg);
115 * 137 *
116 * Copy address to the structure, and set the invalid bit 138 * Copy address to the structure, and set the invalid bit
117 */ 139 */
118void __set_dma_addr (dmach_t channel, void *addr) 140void __set_dma_addr (unsigned int chan, void *addr)
119{ 141{
120 dma_t *dma = dma_chan + channel; 142 dma_t *dma = dma_channel(chan);
121 143
122 if (dma->active) 144 if (dma->active)
123 printk(KERN_ERR "dma%d: altering DMA address while " 145 printk(KERN_ERR "dma%d: altering DMA address while "
124 "DMA active\n", channel); 146 "DMA active\n", chan);
125 147
126 dma->sg = NULL; 148 dma->sg = NULL;
127 dma->addr = addr; 149 dma->addr = addr;
@@ -133,13 +155,13 @@ EXPORT_SYMBOL(__set_dma_addr);
133 * 155 *
134 * Copy address to the structure, and set the invalid bit 156 * Copy address to the structure, and set the invalid bit
135 */ 157 */
136void set_dma_count (dmach_t channel, unsigned long count) 158void set_dma_count (unsigned int chan, unsigned long count)
137{ 159{
138 dma_t *dma = dma_chan + channel; 160 dma_t *dma = dma_channel(chan);
139 161
140 if (dma->active) 162 if (dma->active)
141 printk(KERN_ERR "dma%d: altering DMA count while " 163 printk(KERN_ERR "dma%d: altering DMA count while "
142 "DMA active\n", channel); 164 "DMA active\n", chan);
143 165
144 dma->sg = NULL; 166 dma->sg = NULL;
145 dma->count = count; 167 dma->count = count;
@@ -149,13 +171,13 @@ EXPORT_SYMBOL(set_dma_count);
149 171
150/* Set DMA direction mode 172/* Set DMA direction mode
151 */ 173 */
152void set_dma_mode (dmach_t channel, dmamode_t mode) 174void set_dma_mode (unsigned int chan, unsigned int mode)
153{ 175{
154 dma_t *dma = dma_chan + channel; 176 dma_t *dma = dma_channel(chan);
155 177
156 if (dma->active) 178 if (dma->active)
157 printk(KERN_ERR "dma%d: altering DMA mode while " 179 printk(KERN_ERR "dma%d: altering DMA mode while "
158 "DMA active\n", channel); 180 "DMA active\n", chan);
159 181
160 dma->dma_mode = mode; 182 dma->dma_mode = mode;
161 dma->invalid = 1; 183 dma->invalid = 1;
@@ -164,42 +186,42 @@ EXPORT_SYMBOL(set_dma_mode);
164 186
165/* Enable DMA channel 187/* Enable DMA channel
166 */ 188 */
167void enable_dma (dmach_t channel) 189void enable_dma (unsigned int chan)
168{ 190{
169 dma_t *dma = dma_chan + channel; 191 dma_t *dma = dma_channel(chan);
170 192
171 if (!dma->lock) 193 if (!dma->lock)
172 goto free_dma; 194 goto free_dma;
173 195
174 if (dma->active == 0) { 196 if (dma->active == 0) {
175 dma->active = 1; 197 dma->active = 1;
176 dma->d_ops->enable(channel, dma); 198 dma->d_ops->enable(chan, dma);
177 } 199 }
178 return; 200 return;
179 201
180free_dma: 202free_dma:
181 printk(KERN_ERR "dma%d: trying to enable free DMA\n", channel); 203 printk(KERN_ERR "dma%d: trying to enable free DMA\n", chan);
182 BUG(); 204 BUG();
183} 205}
184EXPORT_SYMBOL(enable_dma); 206EXPORT_SYMBOL(enable_dma);
185 207
186/* Disable DMA channel 208/* Disable DMA channel
187 */ 209 */
188void disable_dma (dmach_t channel) 210void disable_dma (unsigned int chan)
189{ 211{
190 dma_t *dma = dma_chan + channel; 212 dma_t *dma = dma_channel(chan);
191 213
192 if (!dma->lock) 214 if (!dma->lock)
193 goto free_dma; 215 goto free_dma;
194 216
195 if (dma->active == 1) { 217 if (dma->active == 1) {
196 dma->active = 0; 218 dma->active = 0;
197 dma->d_ops->disable(channel, dma); 219 dma->d_ops->disable(chan, dma);
198 } 220 }
199 return; 221 return;
200 222
201free_dma: 223free_dma:
202 printk(KERN_ERR "dma%d: trying to disable free DMA\n", channel); 224 printk(KERN_ERR "dma%d: trying to disable free DMA\n", chan);
203 BUG(); 225 BUG();
204} 226}
205EXPORT_SYMBOL(disable_dma); 227EXPORT_SYMBOL(disable_dma);
@@ -207,45 +229,38 @@ EXPORT_SYMBOL(disable_dma);
207/* 229/*
208 * Is the specified DMA channel active? 230 * Is the specified DMA channel active?
209 */ 231 */
210int dma_channel_active(dmach_t channel) 232int dma_channel_active(unsigned int chan)
211{ 233{
212 return dma_chan[channel].active; 234 dma_t *dma = dma_channel(chan);
235 return dma->active;
213} 236}
214EXPORT_SYMBOL(dma_channel_active); 237EXPORT_SYMBOL(dma_channel_active);
215 238
216void set_dma_page(dmach_t channel, char pagenr) 239void set_dma_page(unsigned int chan, char pagenr)
217{ 240{
218 printk(KERN_ERR "dma%d: trying to set_dma_page\n", channel); 241 printk(KERN_ERR "dma%d: trying to set_dma_page\n", chan);
219} 242}
220EXPORT_SYMBOL(set_dma_page); 243EXPORT_SYMBOL(set_dma_page);
221 244
222void set_dma_speed(dmach_t channel, int cycle_ns) 245void set_dma_speed(unsigned int chan, int cycle_ns)
223{ 246{
224 dma_t *dma = dma_chan + channel; 247 dma_t *dma = dma_channel(chan);
225 int ret = 0; 248 int ret = 0;
226 249
227 if (dma->d_ops->setspeed) 250 if (dma->d_ops->setspeed)
228 ret = dma->d_ops->setspeed(channel, dma, cycle_ns); 251 ret = dma->d_ops->setspeed(chan, dma, cycle_ns);
229 dma->speed = ret; 252 dma->speed = ret;
230} 253}
231EXPORT_SYMBOL(set_dma_speed); 254EXPORT_SYMBOL(set_dma_speed);
232 255
233int get_dma_residue(dmach_t channel) 256int get_dma_residue(unsigned int chan)
234{ 257{
235 dma_t *dma = dma_chan + channel; 258 dma_t *dma = dma_channel(chan);
236 int ret = 0; 259 int ret = 0;
237 260
238 if (dma->d_ops->residue) 261 if (dma->d_ops->residue)
239 ret = dma->d_ops->residue(channel, dma); 262 ret = dma->d_ops->residue(chan, dma);
240 263
241 return ret; 264 return ret;
242} 265}
243EXPORT_SYMBOL(get_dma_residue); 266EXPORT_SYMBOL(get_dma_residue);
244
245static int __init init_dma(void)
246{
247 arch_dma_init(dma_chan);
248 return 0;
249}
250
251core_initcall(init_dma);