diff options
Diffstat (limited to 'arch/arm/plat-s3c24xx/dma.c')
-rw-r--r-- | arch/arm/plat-s3c24xx/dma.c | 77 |
1 files changed, 53 insertions, 24 deletions
diff --git a/arch/arm/plat-s3c24xx/dma.c b/arch/arm/plat-s3c24xx/dma.c index 929265aab7dd..4540a806f522 100644 --- a/arch/arm/plat-s3c24xx/dma.c +++ b/arch/arm/plat-s3c24xx/dma.c @@ -42,6 +42,8 @@ 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 */ @@ -1278,7 +1280,42 @@ static void s3c2410_dma_cache_ctor(void *p, struct kmem_cache *c, unsigned long /* 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; @@ -1286,21 +1323,16 @@ static int __init s3c2410_init_dma(void) 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); @@ -1310,15 +1342,15 @@ static int __init s3c2410_init_dma(void) 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; @@ -1328,12 +1360,6 @@ static int __init s3c2410_init_dma(void) 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); } @@ -1347,7 +1373,10 @@ static int __init s3c2410_init_dma(void) 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) { @@ -1384,7 +1413,7 @@ struct s3c2410_dma_chan *s3c2410_dma_map_channel(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; @@ -1400,7 +1429,7 @@ struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel) /* 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; @@ -1410,7 +1439,7 @@ struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel) } } - if (ch >= S3C2410_DMA_CHANNELS) + if (ch >= dma_channels) return NULL; /* update our channel mapping */ |