[ARM] dma: rejig DMA initialization
authorRussell King <rmk@dyn-67.arm.linux.org.uk>
Mon, 8 Dec 2008 16:33:30 +0000 (16:33 +0000)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Thu, 11 Dec 2008 14:32:43 +0000 (14:32 +0000)
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>
arch/arm/include/asm/mach/dma.h
arch/arm/kernel/dma-isa.c
arch/arm/kernel/dma.c
arch/arm/mach-footbridge/dma.c
arch/arm/mach-rpc/dma.c
arch/arm/mach-shark/dma.c

index 281ae7e..38a3693 100644 (file)
@@ -48,10 +48,12 @@ struct dma_struct {
        struct dma_ops  *d_ops;
 };
 
-/* Prototype: void arch_dma_init(dma)
- * Purpose  : Initialise architecture specific DMA
- * Params   : dma - pointer to array of DMA structures
+/*
+ * isa_dma_add - add an ISA-style DMA channel
  */
-extern void arch_dma_init(dma_t *dma);
+extern int isa_dma_add(unsigned int, dma_t *dma);
 
-extern void isa_init_dma(dma_t *dma);
+/*
+ * Add the ISA DMA controller.  Always takes channels 0-7.
+ */
+extern void isa_init_dma(void);
index 29eca48..da02a7f 100644 (file)
@@ -160,7 +160,12 @@ static struct resource dma_resources[] = { {
        .end    = 0x048f
 } };
 
-void __init isa_init_dma(dma_t *dma)
+static dma_t isa_dma[8];
+
+/*
+ * ISA DMA always starts at channel 0
+ */
+void __init isa_init_dma(void)
 {
        /*
         * Try to autodetect presence of an ISA DMA controller.
@@ -178,10 +183,10 @@ void __init isa_init_dma(dma_t *dma)
        outb(0xaa, 0x00);
 
        if (inb(0) == 0x55 && inb(0) == 0xaa) {
-               int chan, i;
+               unsigned int chan, i;
 
                for (chan = 0; chan < 8; chan++) {
-                       dma[chan].d_ops = &isa_dma_ops;
+                       isa_dma[chan].d_ops = &isa_dma_ops;
                        isa_disable_dma(chan, NULL);
                }
 
@@ -217,5 +222,12 @@ void __init isa_init_dma(dma_t *dma)
 
                for (i = 0; i < ARRAY_SIZE(dma_resources); i++)
                        request_resource(&ioport_resource, dma_resources + i);
+
+               for (chan = 0; chan < 8; chan++) {
+                       int ret = isa_dma_add(chan, &isa_dma[chan]);
+                       if (ret)
+                               printk(KERN_ERR "ISADMA%u: unable to register: %d\n",
+                                       chan, ret);
+               }
        }
 }
index 0ffea3f..aab24f0 100644 (file)
 DEFINE_SPINLOCK(dma_spin_lock);
 EXPORT_SYMBOL(dma_spin_lock);
 
-static dma_t dma_chan[MAX_DMA_CHANNELS];
+static dma_t *dma_chan[MAX_DMA_CHANNELS];
 
 static inline dma_t *dma_channel(unsigned int chan)
 {
-       dma_t *dma = dma_chan + chan;
-
-       if (chan >= MAX_DMA_CHANNELS || !dma->d_ops)
+       if (chan >= MAX_DMA_CHANNELS)
                return NULL;
 
-       return dma;
+       return dma_chan[chan];
+}
+
+int __init isa_dma_add(unsigned int chan, dma_t *dma)
+{
+       if (!dma->d_ops)
+               return -EINVAL;
+       if (dma_chan[chan])
+               return -EBUSY;
+       dma_chan[chan] = dma;
+       return 0;
 }
 
 /*
@@ -252,10 +260,3 @@ int get_dma_residue(unsigned int chan)
        return ret;
 }
 EXPORT_SYMBOL(get_dma_residue);
-
-static int __init init_dma(void)
-{
-       arch_dma_init(dma_chan);
-       return 0;
-}
-core_initcall(init_dma);
index e7b8a6a..fdd94b1 100644 (file)
@@ -41,7 +41,7 @@ static struct dma_ops fb_dma_ops = {
 };
 #endif
 
-void __init arch_dma_init(dma_t *dma)
+static int __init fb_dma_init(void)
 {
 #if 0
        dma[_DC21285_DMA(0)].d_ops = &fb_dma_ops;
@@ -49,6 +49,8 @@ void __init arch_dma_init(dma_t *dma)
 #endif
 #ifdef CONFIG_ISA_DMA
        if (footbridge_cfn_mode())
-               isa_init_dma(dma + _ISA_DMA(0));
+               isa_init_dma();
 #endif
+       return 0;
 }
+core_initcall(fb_dma_init);
index a86d3ed..efcf671 100644 (file)
@@ -302,8 +302,22 @@ static struct dma_ops sound_dma_ops = {
        .disable        = sound_enable_disable_dma,
 };
 
-void __init arch_dma_init(dma_t *dma)
+static dma_t iomd_dma[6];
+
+static dma_t floppy_dma = {
+       .dma_irq        = FIQ_FLOPPYDATA,
+       .d_ops          = &floppy_dma_ops,
+};
+
+static dma_t sound_dma = {
+       .d_ops          = &sound_dma_ops,
+};
+
+static int __init rpc_dma_init(void)
 {
+       unsigned int i;
+       int ret;
+
        iomd_writeb(0, IOMD_IO0CR);
        iomd_writeb(0, IOMD_IO1CR);
        iomd_writeb(0, IOMD_IO2CR);
@@ -311,31 +325,39 @@ void __init arch_dma_init(dma_t *dma)
 
        iomd_writeb(0xa0, IOMD_DMATCR);
 
-       dma[DMA_0].dma_base             = IOMD_IO0CURA;
-       dma[DMA_0].dma_irq              = IRQ_DMA0;
-       dma[DMA_0].d_ops                = &iomd_dma_ops;
-       dma[DMA_1].dma_base             = IOMD_IO1CURA;
-       dma[DMA_1].dma_irq              = IRQ_DMA1;
-       dma[DMA_1].d_ops                = &iomd_dma_ops;
-       dma[DMA_2].dma_base             = IOMD_IO2CURA;
-       dma[DMA_2].dma_irq              = IRQ_DMA2;
-       dma[DMA_2].d_ops                = &iomd_dma_ops;
-       dma[DMA_3].dma_base             = IOMD_IO3CURA;
-       dma[DMA_3].dma_irq              = IRQ_DMA3;
-       dma[DMA_3].d_ops                = &iomd_dma_ops;
-       dma[DMA_S0].dma_base            = IOMD_SD0CURA;
-       dma[DMA_S0].dma_irq             = IRQ_DMAS0;
-       dma[DMA_S0].d_ops               = &iomd_dma_ops;
-       dma[DMA_S1].dma_base            = IOMD_SD1CURA;
-       dma[DMA_S1].dma_irq             = IRQ_DMAS1;
-       dma[DMA_S1].d_ops               = &iomd_dma_ops;
-       dma[DMA_VIRTUAL_FLOPPY].dma_irq = FIQ_FLOPPYDATA;
-       dma[DMA_VIRTUAL_FLOPPY].d_ops   = &floppy_dma_ops;
-       dma[DMA_VIRTUAL_SOUND].d_ops    = &sound_dma_ops;
-
        /*
         * Setup DMA channels 2,3 to be for podules
         * and channels 0,1 for internal devices
         */
        iomd_writeb(DMA_EXT_IO3|DMA_EXT_IO2, IOMD_DMAEXT);
+
+       iomd_dma[DMA_0].dma_base        = IOMD_IO0CURA;
+       iomd_dma[DMA_0].dma_irq         = IRQ_DMA0;
+       iomd_dma[DMA_1].dma_base        = IOMD_IO1CURA;
+       iomd_dma[DMA_1].dma_irq         = IRQ_DMA1;
+       iomd_dma[DMA_2].dma_base        = IOMD_IO2CURA;
+       iomd_dma[DMA_2].dma_irq         = IRQ_DMA2;
+       iomd_dma[DMA_3].dma_base        = IOMD_IO3CURA;
+       iomd_dma[DMA_3].dma_irq         = IRQ_DMA3;
+       iomd_dma[DMA_S0].dma_base       = IOMD_SD0CURA;
+       iomd_dma[DMA_S0].dma_irq        = IRQ_DMAS0;
+       iomd_dma[DMA_S1].dma_base       = IOMD_SD1CURA;
+       iomd_dma[DMA_S1].dma_irq        = IRQ_DMAS1;
+
+       for (i = DMA_0; i <= DMA_S1; i++) {
+               iomd_dma[i].d_ops = &iomd_dma_ops;
+
+               ret = isa_dma_add(i, &iomd_dma[i]);
+               if (ret)
+                       printk("IOMDDMA%u: unable to register: %d\n", i, ret);
+       }
+
+       ret = isa_dma_add(DMA_VIRTUAL_FLOPPY, &floppy_dma);
+       if (ret)
+               printk("IOMDFLOPPY: unable to register: %d\n", ret);
+       ret = isa_dma_add(DMA_VIRTUAL_SOUND, &sound_dma);
+       if (ret)
+               printk("IOMDSOUND: unable to register: %d\n", ret);
+       return 0;
 }
+core_initcall(rpc_dma_init);
index 6774b8d..10b5b8b 100644 (file)
 #include <asm/dma.h>
 #include <asm/mach/dma.h>
 
-void __init arch_dma_init(dma_t *dma)
+static int __init shark_dma_init(void)
 {
 #ifdef CONFIG_ISA_DMA
-       isa_init_dma(dma);
+       isa_init_dma();
 #endif
+       return 0;
 }
+core_initcall(shark_dma_init);