diff options
author | Eric Miao <eric.y.miao@gmail.com> | 2007-06-22 06:40:17 +0200 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2007-07-12 15:28:16 +0200 |
commit | f53f066c25036210036730d64c876ea586114425 (patch) | |
tree | e680deb53ff12ec09f5c64421a3f13eecb7aed41 /arch/arm/mach-pxa/dma.c | |
parent | [ARM] 4450/1: pxa: add pxa25x_init_irq() and pxa27x_init_irq() (diff) | |
download | linux-f53f066c25036210036730d64c876ea586114425.tar.xz linux-f53f066c25036210036730d64c876ea586114425.zip |
[ARM] 4451/1: pxa: make dma.c generic and remove cpu specific dma code
Since the number of dma channels varies between pxa25x and pxa27x, it
introduces some specific code in dma.c. This patch moves the specific
code to pxa25x.c and pxa27x.c and makes dma.c more generic.
1. add pxa_init_dma() for dma initialization, the number of channels
are passed in by the argument
2. add a "prio" field to the "struct pxa_dma_channel" for the channel
priority, and is initialized in pxa_init_dma()
3. use a general priority comparison with the channels "prio" field so
to remove the processor specific pxa_for_each_dma_prio macro, this
is not lightning fast as the original one, but it is acceptable as
it happens when requesting dma, which is usually not so performance
critical
Signed-off-by: eric miao <eric.miao@marvell.com>
Acked-by: Nicolas Pitre <nico@cam.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mach-pxa/dma.c')
-rw-r--r-- | arch/arm/mach-pxa/dma.c | 44 |
1 files changed, 31 insertions, 13 deletions
diff --git a/arch/arm/mach-pxa/dma.c b/arch/arm/mach-pxa/dma.c index 4440babe7b97..93c4f31f127f 100644 --- a/arch/arm/mach-pxa/dma.c +++ b/arch/arm/mach-pxa/dma.c @@ -25,12 +25,15 @@ #include <asm/arch/pxa-regs.h> -static struct dma_channel { +struct dma_channel { char *name; + pxa_dma_prio prio; void (*irq_handler)(int, void *); void *data; -} dma_channels[PXA_DMA_CHANNELS]; +}; +static struct dma_channel *dma_channels; +static int num_dma_channels; int pxa_request_dma (char *name, pxa_dma_prio prio, void (*irq_handler)(int, void *), @@ -47,8 +50,9 @@ int pxa_request_dma (char *name, pxa_dma_prio prio, do { /* try grabbing a DMA channel with the requested priority */ - pxa_for_each_dma_prio (i, prio) { - if (!dma_channels[i].name) { + for (i = 0; i < num_dma_channels; i++) { + if ((dma_channels[i].prio == prio) && + !dma_channels[i].name) { found = 1; break; } @@ -91,7 +95,7 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id) { int i, dint = DINT; - for (i = 0; i < PXA_DMA_CHANNELS; i++) { + for (i = 0; i < num_dma_channels; i++) { if (dint & (1 << i)) { struct dma_channel *channel = &dma_channels[i]; if (channel->name && channel->irq_handler) { @@ -109,18 +113,32 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id) return IRQ_HANDLED; } -static int __init pxa_dma_init (void) +int __init pxa_init_dma(int num_ch) { - int ret; + int i, ret; - ret = request_irq (IRQ_DMA, dma_irq_handler, 0, "DMA", NULL); - if (ret) + dma_channels = kzalloc(sizeof(struct dma_channel) * num_ch, GFP_KERNEL); + if (dma_channels == NULL) + return -ENOMEM; + + ret = request_irq(IRQ_DMA, dma_irq_handler, IRQF_DISABLED, "DMA", NULL); + if (ret) { printk (KERN_CRIT "Wow! Can't register IRQ for DMA\n"); - return ret; -} + kfree(dma_channels); + return ret; + } -arch_initcall(pxa_dma_init); + /* dma channel priorities on pxa2xx processors: + * ch 0 - 3, 16 - 19 <--> (0) DMA_PRIO_HIGH + * ch 4 - 7, 20 - 23 <--> (1) DMA_PRIO_MEDIUM + * ch 8 - 15, 24 - 31 <--> (2) DMA_PRIO_LOW + */ + for (i = 0; i < num_ch; i++) + dma_channels[i].prio = min((i & 0xf) >> 2, DMA_PRIO_LOW); + + num_dma_channels = num_ch; + return 0; +} EXPORT_SYMBOL(pxa_request_dma); EXPORT_SYMBOL(pxa_free_dma); - |