2 * linux/arch/arm26/kernel/dma.c
4 * Copyright (C) 1995-2000 Russell King
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * Front-end to the DMA handling. This handles the allocation/freeing
12 * of DMA channels, and provides a unified interface to the machines
15 #include <linux/module.h>
16 #include <linux/slab.h>
17 #include <linux/sched.h>
18 #include <linux/mman.h>
19 #include <linux/init.h>
20 #include <linux/spinlock.h>
21 #include <linux/errno.h>
25 DEFINE_SPINLOCK(dma_spin_lock
);
27 static dma_t dma_chan
[MAX_DMA_CHANNELS
];
30 * Get dma list for /proc/dma
32 int get_dma_list(char *buf
)
38 for (i
= 0, dma
= dma_chan
; i
< MAX_DMA_CHANNELS
; i
++, dma
++)
40 p
+= sprintf(p
, "%2d: %14s %s\n", i
,
41 dma
->d_ops
->type
, dma
->device_id
);
49 * On certain platforms, we have to allocate an interrupt as well...
51 int request_dma(dmach_t channel
, const char *device_id
)
53 dma_t
*dma
= dma_chan
+ channel
;
56 if (channel
>= MAX_DMA_CHANNELS
|| !dma
->d_ops
)
59 if (xchg(&dma
->lock
, 1) != 0)
62 dma
->device_id
= device_id
;
67 if (dma
->d_ops
->request
)
68 ret
= dma
->d_ops
->request(channel
, dma
);
76 printk(KERN_ERR
"dma: trying to allocate DMA%d\n", channel
);
86 * On certain platforms, we have to free interrupt as well...
88 void free_dma(dmach_t channel
)
90 dma_t
*dma
= dma_chan
+ channel
;
92 if (channel
>= MAX_DMA_CHANNELS
|| !dma
->d_ops
)
96 printk(KERN_ERR
"dma%d: freeing active DMA\n", channel
);
97 dma
->d_ops
->disable(channel
, dma
);
101 if (xchg(&dma
->lock
, 0) != 0) {
102 if (dma
->d_ops
->free
)
103 dma
->d_ops
->free(channel
, dma
);
107 printk(KERN_ERR
"dma%d: trying to free free DMA\n", channel
);
111 printk(KERN_ERR
"dma: trying to free DMA%d\n", channel
);
114 /* Set DMA Scatter-Gather list
116 void set_dma_sg (dmach_t channel
, struct scatterlist
*sg
, int nr_sg
)
118 dma_t
*dma
= dma_chan
+ channel
;
121 printk(KERN_ERR
"dma%d: altering DMA SG while "
122 "DMA active\n", channel
);
125 dma
->sgcount
= nr_sg
;
132 * Copy address to the structure, and set the invalid bit
134 void set_dma_addr (dmach_t channel
, unsigned long physaddr
)
136 dma_t
*dma
= dma_chan
+ channel
;
139 printk(KERN_ERR
"dma%d: altering DMA address while "
140 "DMA active\n", channel
);
144 dma
->buf
.__address
= (char *)physaddr
;//FIXME - not pretty
149 /* Set DMA byte count
151 * Copy address to the structure, and set the invalid bit
153 void set_dma_count (dmach_t channel
, unsigned long count
)
155 dma_t
*dma
= dma_chan
+ channel
;
158 printk(KERN_ERR
"dma%d: altering DMA count while "
159 "DMA active\n", channel
);
163 dma
->buf
.length
= count
;
168 /* Set DMA direction mode
170 void set_dma_mode (dmach_t channel
, dmamode_t mode
)
172 dma_t
*dma
= dma_chan
+ channel
;
175 printk(KERN_ERR
"dma%d: altering DMA mode while "
176 "DMA active\n", channel
);
178 dma
->dma_mode
= mode
;
182 /* Enable DMA channel
184 void enable_dma (dmach_t channel
)
186 dma_t
*dma
= dma_chan
+ channel
;
191 if (dma
->active
== 0) {
193 dma
->d_ops
->enable(channel
, dma
);
198 printk(KERN_ERR
"dma%d: trying to enable free DMA\n", channel
);
202 /* Disable DMA channel
204 void disable_dma (dmach_t channel
)
206 dma_t
*dma
= dma_chan
+ channel
;
211 if (dma
->active
== 1) {
213 dma
->d_ops
->disable(channel
, dma
);
218 printk(KERN_ERR
"dma%d: trying to disable free DMA\n", channel
);
223 * Is the specified DMA channel active?
225 int dma_channel_active(dmach_t channel
)
227 return dma_chan
[channel
].active
;
230 void set_dma_page(dmach_t channel
, char pagenr
)
232 printk(KERN_ERR
"dma%d: trying to set_dma_page\n", channel
);
235 void set_dma_speed(dmach_t channel
, int cycle_ns
)
237 dma_t
*dma
= dma_chan
+ channel
;
240 if (dma
->d_ops
->setspeed
)
241 ret
= dma
->d_ops
->setspeed(channel
, dma
, cycle_ns
);
245 int get_dma_residue(dmach_t channel
)
247 dma_t
*dma
= dma_chan
+ channel
;
250 if (dma
->d_ops
->residue
)
251 ret
= dma
->d_ops
->residue(channel
, dma
);
256 void __init
init_dma(void)
258 arch_dma_init(dma_chan
);
261 EXPORT_SYMBOL(request_dma
);
262 EXPORT_SYMBOL(free_dma
);
263 EXPORT_SYMBOL(enable_dma
);
264 EXPORT_SYMBOL(disable_dma
);
265 EXPORT_SYMBOL(set_dma_addr
);
266 EXPORT_SYMBOL(set_dma_count
);
267 EXPORT_SYMBOL(set_dma_mode
);
268 EXPORT_SYMBOL(set_dma_page
);
269 EXPORT_SYMBOL(get_dma_residue
);
270 EXPORT_SYMBOL(set_dma_sg
);
271 EXPORT_SYMBOL(set_dma_speed
);
273 EXPORT_SYMBOL(dma_spin_lock
);