#include <asm/dma.h>
 #include <asm/arch/dma.h>
-#include <asm/plat-s3c24xx/dma.h>
 
 #include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/dma.h>
 
 #include <asm/arch/regs-serial.h>
 #include <asm/arch/regs-gpio.h>
 
 static int s3c2410_dma_add(struct sys_device *sysdev)
 {
+       s3c2410_dma_init();
        s3c24xx_dma_order_set(&s3c2410_dma_order);
        return s3c24xx_dma_init_map(&s3c2410_dma_sel);
 }
        .add    = s3c2410_dma_add,
 };
 
-static int __init s3c2410_dma_init(void)
+static int __init s3c2410_dma_drvinit(void)
 {
        return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_dma_driver);
 }
 
-arch_initcall(s3c2410_dma_init);
+arch_initcall(s3c2410_dma_drvinit);
 #endif
 
 #if defined(CONFIG_CPU_S3C2442)
        .add    = s3c2410_dma_add,
 };
 
-static int __init s3c2442_dma_init(void)
+static int __init s3c2442_dma_drvinit(void)
 {
        return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_dma_driver);
 }
 
-arch_initcall(s3c2442_dma_init);
+arch_initcall(s3c2442_dma_drvinit);
 #endif
 
 
 static void __iomem *dma_base;
 static struct kmem_cache *dma_kmem;
 
+static int dma_channels;
+
 struct s3c24xx_dma_selection dma_sel;
 
 /* dma channel state information */
 
 /* initialisation code */
 
-static int __init s3c2410_init_dma(void)
+int __init s3c24xx_dma_sysclass_init(void)
+{
+       int ret = sysdev_class_register(&dma_sysclass);
+
+       if (ret != 0)
+               printk(KERN_ERR "dma sysclass registration failed\n");
+
+       return ret;
+}
+
+core_initcall(s3c24xx_dma_sysclass_init);
+
+int __init s3c24xx_dma_sysdev_register(void)
+{
+       struct s3c2410_dma_chan *cp = s3c2410_chans;
+       int channel, ret;
+
+       for (channel = 0; channel < dma_channels; cp++, channel++) {
+               cp->dev.cls = &dma_sysclass;
+               cp->dev.id  = channel;
+               ret = sysdev_register(&cp->dev);
+
+               if (ret) {
+                       printk(KERN_ERR "error registering dev for dma %d\n",
+                              channel);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+late_initcall(s3c24xx_dma_sysdev_register);
+
+int __init s3c24xx_dma_init(unsigned int channels, unsigned int irq,
+                           unsigned int stride)
 {
        struct s3c2410_dma_chan *cp;
        int channel;
 
        printk("S3C24XX DMA Driver, (c) 2003-2004,2006 Simtec Electronics\n");
 
-       dma_base = ioremap(S3C24XX_PA_DMA, 0x200);
+       dma_channels = channels;
+
+       dma_base = ioremap(S3C24XX_PA_DMA, stride * channels);
        if (dma_base == NULL) {
                printk(KERN_ERR "dma failed to remap register block\n");
                return -ENOMEM;
        }
 
-       printk("Registering sysclass\n");
-
-       ret = sysdev_class_register(&dma_sysclass);
-       if (ret != 0) {
-               printk(KERN_ERR "dma sysclass registration failed\n");
-               goto err;
-       }
-
-       dma_kmem = kmem_cache_create("dma_desc", sizeof(struct s3c2410_dma_buf), 0,
+       dma_kmem = kmem_cache_create("dma_desc",
+                                    sizeof(struct s3c2410_dma_buf), 0,
                                     SLAB_HWCACHE_ALIGN,
                                     s3c2410_dma_cache_ctor, NULL);
 
                goto err;
        }
 
-       for (channel = 0; channel < S3C2410_DMA_CHANNELS; channel++) {
+       for (channel = 0; channel < channels;  channel++) {
                cp = &s3c2410_chans[channel];
 
                memset(cp, 0, sizeof(struct s3c2410_dma_chan));
 
                /* dma channel irqs are in order.. */
                cp->number = channel;
-               cp->irq    = channel + IRQ_DMA0;
-               cp->regs   = dma_base + (channel*0x40);
+               cp->irq    = channel + irq;
+               cp->regs   = dma_base + (channel * stride);
 
                /* point current stats somewhere */
                cp->stats  = &cp->stats_store;
 
                cp->load_timeout = 1<<18;
 
-               /* register system device */
-
-               cp->dev.cls = &dma_sysclass;
-               cp->dev.id  = channel;
-               ret = sysdev_register(&cp->dev);
-
                printk("DMA channel %d at %p, irq %d\n",
                       cp->number, cp->regs, cp->irq);
        }
        return ret;
 }
 
-core_initcall(s3c2410_init_dma);
+int s3c2410_dma_init(void)
+{
+       return s3c24xx_dma_init(4, IRQ_DMA0, 0x40);
+}
 
 static inline int is_channel_valid(unsigned int channel)
 {
        if (dma_order) {
                ord = &dma_order->channels[channel];
 
-               for (ch = 0; ch < S3C2410_DMA_CHANNELS; ch++) {
+               for (ch = 0; ch < dma_channels; ch++) {
                        if (!is_channel_valid(ord->list[ch]))
                                continue;
 
 
        /* second, search the channel map for first free */
 
-       for (ch = 0; ch < S3C2410_DMA_CHANNELS; ch++) {
+       for (ch = 0; ch < dma_channels; ch++) {
                if (!is_channel_valid(ch_map->channels[ch]))
                        continue;
 
                }
        }
 
-       if (ch >= S3C2410_DMA_CHANNELS)
+       if (ch >= dma_channels)
                return NULL;
 
        /* update our channel mapping */