aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2008-12-08 11:33:30 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2008-12-11 09:32:43 -0500
commit2f757f2ab7411cf0e2779012d8cda0cbf2f80d26 (patch)
tree880e0c661948132d54ce238eb45cba9bb71314d4 /arch/arm
parent3afb6e9c635f735c751148beddc195daec0e35ec (diff)
[ARM] dma: rejig DMA initialization
Rather than having the central DMA multiplexer call the architecture specific DMA initialization function, have each architecture DMA initialization function use core_initcall(), and register each DMA channel separately with the multiplexer. This removes the array of dma structures in the central multiplexer, replacing it with an array of pointers instead; this is more flexible since it allows the drivers to wrap the DMA structure (eventually allowing us to transition non-ISA DMA drivers away.) Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/include/asm/mach/dma.h12
-rw-r--r--arch/arm/kernel/dma-isa.c18
-rw-r--r--arch/arm/kernel/dma.c25
-rw-r--r--arch/arm/mach-footbridge/dma.c6
-rw-r--r--arch/arm/mach-rpc/dma.c68
-rw-r--r--arch/arm/mach-shark/dma.c6
6 files changed, 88 insertions, 47 deletions
diff --git a/arch/arm/include/asm/mach/dma.h b/arch/arm/include/asm/mach/dma.h
index 281ae7e40a90..38a3693f1258 100644
--- a/arch/arm/include/asm/mach/dma.h
+++ b/arch/arm/include/asm/mach/dma.h
@@ -48,10 +48,12 @@ struct dma_struct {
48 struct dma_ops *d_ops; 48 struct dma_ops *d_ops;
49}; 49};
50 50
51/* Prototype: void arch_dma_init(dma) 51/*
52 * Purpose : Initialise architecture specific DMA 52 * isa_dma_add - add an ISA-style DMA channel
53 * Params : dma - pointer to array of DMA structures
54 */ 53 */
55extern void arch_dma_init(dma_t *dma); 54extern int isa_dma_add(unsigned int, dma_t *dma);
56 55
57extern void isa_init_dma(dma_t *dma); 56/*
57 * Add the ISA DMA controller. Always takes channels 0-7.
58 */
59extern void isa_init_dma(void);
diff --git a/arch/arm/kernel/dma-isa.c b/arch/arm/kernel/dma-isa.c
index 29eca48925d8..da02a7ff3419 100644
--- a/arch/arm/kernel/dma-isa.c
+++ b/arch/arm/kernel/dma-isa.c
@@ -160,7 +160,12 @@ static struct resource dma_resources[] = { {
160 .end = 0x048f 160 .end = 0x048f
161} }; 161} };
162 162
163void __init isa_init_dma(dma_t *dma) 163static dma_t isa_dma[8];
164
165/*
166 * ISA DMA always starts at channel 0
167 */
168void __init isa_init_dma(void)
164{ 169{
165 /* 170 /*
166 * Try to autodetect presence of an ISA DMA controller. 171 * Try to autodetect presence of an ISA DMA controller.
@@ -178,10 +183,10 @@ void __init isa_init_dma(dma_t *dma)
178 outb(0xaa, 0x00); 183 outb(0xaa, 0x00);
179 184
180 if (inb(0) == 0x55 && inb(0) == 0xaa) { 185 if (inb(0) == 0x55 && inb(0) == 0xaa) {
181 int chan, i; 186 unsigned int chan, i;
182 187
183 for (chan = 0; chan < 8; chan++) { 188 for (chan = 0; chan < 8; chan++) {
184 dma[chan].d_ops = &isa_dma_ops; 189 isa_dma[chan].d_ops = &isa_dma_ops;
185 isa_disable_dma(chan, NULL); 190 isa_disable_dma(chan, NULL);
186 } 191 }
187 192
@@ -217,5 +222,12 @@ void __init isa_init_dma(dma_t *dma)
217 222
218 for (i = 0; i < ARRAY_SIZE(dma_resources); i++) 223 for (i = 0; i < ARRAY_SIZE(dma_resources); i++)
219 request_resource(&ioport_resource, dma_resources + i); 224 request_resource(&ioport_resource, dma_resources + i);
225
226 for (chan = 0; chan < 8; chan++) {
227 int ret = isa_dma_add(chan, &isa_dma[chan]);
228 if (ret)
229 printk(KERN_ERR "ISADMA%u: unable to register: %d\n",
230 chan, ret);
231 }
220 } 232 }
221} 233}
diff --git a/arch/arm/kernel/dma.c b/arch/arm/kernel/dma.c
index 0ffea3fc22db..aab24f03ea14 100644
--- a/arch/arm/kernel/dma.c
+++ b/arch/arm/kernel/dma.c
@@ -23,16 +23,24 @@
23DEFINE_SPINLOCK(dma_spin_lock); 23DEFINE_SPINLOCK(dma_spin_lock);
24EXPORT_SYMBOL(dma_spin_lock); 24EXPORT_SYMBOL(dma_spin_lock);
25 25
26static dma_t dma_chan[MAX_DMA_CHANNELS]; 26static dma_t *dma_chan[MAX_DMA_CHANNELS];
27 27
28static inline dma_t *dma_channel(unsigned int chan) 28static inline dma_t *dma_channel(unsigned int chan)
29{ 29{
30 dma_t *dma = dma_chan + chan; 30 if (chan >= MAX_DMA_CHANNELS)
31
32 if (chan >= MAX_DMA_CHANNELS || !dma->d_ops)
33 return NULL; 31 return NULL;
34 32
35 return dma; 33 return dma_chan[chan];
34}
35
36int __init isa_dma_add(unsigned int chan, dma_t *dma)
37{
38 if (!dma->d_ops)
39 return -EINVAL;
40 if (dma_chan[chan])
41 return -EBUSY;
42 dma_chan[chan] = dma;
43 return 0;
36} 44}
37 45
38/* 46/*
@@ -252,10 +260,3 @@ int get_dma_residue(unsigned int chan)
252 return ret; 260 return ret;
253} 261}
254EXPORT_SYMBOL(get_dma_residue); 262EXPORT_SYMBOL(get_dma_residue);
255
256static int __init init_dma(void)
257{
258 arch_dma_init(dma_chan);
259 return 0;
260}
261core_initcall(init_dma);
diff --git a/arch/arm/mach-footbridge/dma.c b/arch/arm/mach-footbridge/dma.c
index e7b8a6adaf7a..fdd94b182d78 100644
--- a/arch/arm/mach-footbridge/dma.c
+++ b/arch/arm/mach-footbridge/dma.c
@@ -41,7 +41,7 @@ static struct dma_ops fb_dma_ops = {
41}; 41};
42#endif 42#endif
43 43
44void __init arch_dma_init(dma_t *dma) 44static int __init fb_dma_init(void)
45{ 45{
46#if 0 46#if 0
47 dma[_DC21285_DMA(0)].d_ops = &fb_dma_ops; 47 dma[_DC21285_DMA(0)].d_ops = &fb_dma_ops;
@@ -49,6 +49,8 @@ void __init arch_dma_init(dma_t *dma)
49#endif 49#endif
50#ifdef CONFIG_ISA_DMA 50#ifdef CONFIG_ISA_DMA
51 if (footbridge_cfn_mode()) 51 if (footbridge_cfn_mode())
52 isa_init_dma(dma + _ISA_DMA(0)); 52 isa_init_dma();
53#endif 53#endif
54 return 0;
54} 55}
56core_initcall(fb_dma_init);
diff --git a/arch/arm/mach-rpc/dma.c b/arch/arm/mach-rpc/dma.c
index a86d3ed859a7..efcf6718d1d0 100644
--- a/arch/arm/mach-rpc/dma.c
+++ b/arch/arm/mach-rpc/dma.c
@@ -302,8 +302,22 @@ static struct dma_ops sound_dma_ops = {
302 .disable = sound_enable_disable_dma, 302 .disable = sound_enable_disable_dma,
303}; 303};
304 304
305void __init arch_dma_init(dma_t *dma) 305static dma_t iomd_dma[6];
306
307static dma_t floppy_dma = {
308 .dma_irq = FIQ_FLOPPYDATA,
309 .d_ops = &floppy_dma_ops,
310};
311
312static dma_t sound_dma = {
313 .d_ops = &sound_dma_ops,
314};
315
316static int __init rpc_dma_init(void)
306{ 317{
318 unsigned int i;
319 int ret;
320
307 iomd_writeb(0, IOMD_IO0CR); 321 iomd_writeb(0, IOMD_IO0CR);
308 iomd_writeb(0, IOMD_IO1CR); 322 iomd_writeb(0, IOMD_IO1CR);
309 iomd_writeb(0, IOMD_IO2CR); 323 iomd_writeb(0, IOMD_IO2CR);
@@ -311,31 +325,39 @@ void __init arch_dma_init(dma_t *dma)
311 325
312 iomd_writeb(0xa0, IOMD_DMATCR); 326 iomd_writeb(0xa0, IOMD_DMATCR);
313 327
314 dma[DMA_0].dma_base = IOMD_IO0CURA;
315 dma[DMA_0].dma_irq = IRQ_DMA0;
316 dma[DMA_0].d_ops = &iomd_dma_ops;
317 dma[DMA_1].dma_base = IOMD_IO1CURA;
318 dma[DMA_1].dma_irq = IRQ_DMA1;
319 dma[DMA_1].d_ops = &iomd_dma_ops;
320 dma[DMA_2].dma_base = IOMD_IO2CURA;
321 dma[DMA_2].dma_irq = IRQ_DMA2;
322 dma[DMA_2].d_ops = &iomd_dma_ops;
323 dma[DMA_3].dma_base = IOMD_IO3CURA;
324 dma[DMA_3].dma_irq = IRQ_DMA3;
325 dma[DMA_3].d_ops = &iomd_dma_ops;
326 dma[DMA_S0].dma_base = IOMD_SD0CURA;
327 dma[DMA_S0].dma_irq = IRQ_DMAS0;
328 dma[DMA_S0].d_ops = &iomd_dma_ops;
329 dma[DMA_S1].dma_base = IOMD_SD1CURA;
330 dma[DMA_S1].dma_irq = IRQ_DMAS1;
331 dma[DMA_S1].d_ops = &iomd_dma_ops;
332 dma[DMA_VIRTUAL_FLOPPY].dma_irq = FIQ_FLOPPYDATA;
333 dma[DMA_VIRTUAL_FLOPPY].d_ops = &floppy_dma_ops;
334 dma[DMA_VIRTUAL_SOUND].d_ops = &sound_dma_ops;
335
336 /* 328 /*
337 * Setup DMA channels 2,3 to be for podules 329 * Setup DMA channels 2,3 to be for podules
338 * and channels 0,1 for internal devices 330 * and channels 0,1 for internal devices
339 */ 331 */
340 iomd_writeb(DMA_EXT_IO3|DMA_EXT_IO2, IOMD_DMAEXT); 332 iomd_writeb(DMA_EXT_IO3|DMA_EXT_IO2, IOMD_DMAEXT);
333
334 iomd_dma[DMA_0].dma_base = IOMD_IO0CURA;
335 iomd_dma[DMA_0].dma_irq = IRQ_DMA0;
336 iomd_dma[DMA_1].dma_base = IOMD_IO1CURA;
337 iomd_dma[DMA_1].dma_irq = IRQ_DMA1;
338 iomd_dma[DMA_2].dma_base = IOMD_IO2CURA;
339 iomd_dma[DMA_2].dma_irq = IRQ_DMA2;
340 iomd_dma[DMA_3].dma_base = IOMD_IO3CURA;
341 iomd_dma[DMA_3].dma_irq = IRQ_DMA3;
342 iomd_dma[DMA_S0].dma_base = IOMD_SD0CURA;
343 iomd_dma[DMA_S0].dma_irq = IRQ_DMAS0;
344 iomd_dma[DMA_S1].dma_base = IOMD_SD1CURA;
345 iomd_dma[DMA_S1].dma_irq = IRQ_DMAS1;
346
347 for (i = DMA_0; i <= DMA_S1; i++) {
348 iomd_dma[i].d_ops = &iomd_dma_ops;
349
350 ret = isa_dma_add(i, &iomd_dma[i]);
351 if (ret)
352 printk("IOMDDMA%u: unable to register: %d\n", i, ret);
353 }
354
355 ret = isa_dma_add(DMA_VIRTUAL_FLOPPY, &floppy_dma);
356 if (ret)
357 printk("IOMDFLOPPY: unable to register: %d\n", ret);
358 ret = isa_dma_add(DMA_VIRTUAL_SOUND, &sound_dma);
359 if (ret)
360 printk("IOMDSOUND: unable to register: %d\n", ret);
361 return 0;
341} 362}
363core_initcall(rpc_dma_init);
diff --git a/arch/arm/mach-shark/dma.c b/arch/arm/mach-shark/dma.c
index 6774b8d5d13d..10b5b8b3272a 100644
--- a/arch/arm/mach-shark/dma.c
+++ b/arch/arm/mach-shark/dma.c
@@ -13,9 +13,11 @@
13#include <asm/dma.h> 13#include <asm/dma.h>
14#include <asm/mach/dma.h> 14#include <asm/mach/dma.h>
15 15
16void __init arch_dma_init(dma_t *dma) 16static int __init shark_dma_init(void)
17{ 17{
18#ifdef CONFIG_ISA_DMA 18#ifdef CONFIG_ISA_DMA
19 isa_init_dma(dma); 19 isa_init_dma();
20#endif 20#endif
21 return 0;
21} 22}
23core_initcall(shark_dma_init);