diff options
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 @@ | |||
25 | 25 | ||
26 | #include <asm/arch/pxa-regs.h> | 26 | #include <asm/arch/pxa-regs.h> |
27 | 27 | ||
28 | static struct dma_channel { | 28 | struct dma_channel { |
29 | char *name; | 29 | char *name; |
30 | pxa_dma_prio prio; | ||
30 | void (*irq_handler)(int, void *); | 31 | void (*irq_handler)(int, void *); |
31 | void *data; | 32 | void *data; |
32 | } dma_channels[PXA_DMA_CHANNELS]; | 33 | }; |
33 | 34 | ||
35 | static struct dma_channel *dma_channels; | ||
36 | static int num_dma_channels; | ||
34 | 37 | ||
35 | int pxa_request_dma (char *name, pxa_dma_prio prio, | 38 | int pxa_request_dma (char *name, pxa_dma_prio prio, |
36 | void (*irq_handler)(int, void *), | 39 | void (*irq_handler)(int, void *), |
@@ -47,8 +50,9 @@ int pxa_request_dma (char *name, pxa_dma_prio prio, | |||
47 | 50 | ||
48 | do { | 51 | do { |
49 | /* try grabbing a DMA channel with the requested priority */ | 52 | /* try grabbing a DMA channel with the requested priority */ |
50 | pxa_for_each_dma_prio (i, prio) { | 53 | for (i = 0; i < num_dma_channels; i++) { |
51 | if (!dma_channels[i].name) { | 54 | if ((dma_channels[i].prio == prio) && |
55 | !dma_channels[i].name) { | ||
52 | found = 1; | 56 | found = 1; |
53 | break; | 57 | break; |
54 | } | 58 | } |
@@ -91,7 +95,7 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id) | |||
91 | { | 95 | { |
92 | int i, dint = DINT; | 96 | int i, dint = DINT; |
93 | 97 | ||
94 | for (i = 0; i < PXA_DMA_CHANNELS; i++) { | 98 | for (i = 0; i < num_dma_channels; i++) { |
95 | if (dint & (1 << i)) { | 99 | if (dint & (1 << i)) { |
96 | struct dma_channel *channel = &dma_channels[i]; | 100 | struct dma_channel *channel = &dma_channels[i]; |
97 | if (channel->name && channel->irq_handler) { | 101 | if (channel->name && channel->irq_handler) { |
@@ -109,18 +113,32 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id) | |||
109 | return IRQ_HANDLED; | 113 | return IRQ_HANDLED; |
110 | } | 114 | } |
111 | 115 | ||
112 | static int __init pxa_dma_init (void) | 116 | int __init pxa_init_dma(int num_ch) |
113 | { | 117 | { |
114 | int ret; | 118 | int i, ret; |
115 | 119 | ||
116 | ret = request_irq (IRQ_DMA, dma_irq_handler, 0, "DMA", NULL); | 120 | dma_channels = kzalloc(sizeof(struct dma_channel) * num_ch, GFP_KERNEL); |
117 | if (ret) | 121 | if (dma_channels == NULL) |
122 | return -ENOMEM; | ||
123 | |||
124 | ret = request_irq(IRQ_DMA, dma_irq_handler, IRQF_DISABLED, "DMA", NULL); | ||
125 | if (ret) { | ||
118 | printk (KERN_CRIT "Wow! Can't register IRQ for DMA\n"); | 126 | printk (KERN_CRIT "Wow! Can't register IRQ for DMA\n"); |
119 | return ret; | 127 | kfree(dma_channels); |
120 | } | 128 | return ret; |
129 | } | ||
121 | 130 | ||
122 | arch_initcall(pxa_dma_init); | 131 | /* dma channel priorities on pxa2xx processors: |
132 | * ch 0 - 3, 16 - 19 <--> (0) DMA_PRIO_HIGH | ||
133 | * ch 4 - 7, 20 - 23 <--> (1) DMA_PRIO_MEDIUM | ||
134 | * ch 8 - 15, 24 - 31 <--> (2) DMA_PRIO_LOW | ||
135 | */ | ||
136 | for (i = 0; i < num_ch; i++) | ||
137 | dma_channels[i].prio = min((i & 0xf) >> 2, DMA_PRIO_LOW); | ||
138 | |||
139 | num_dma_channels = num_ch; | ||
140 | return 0; | ||
141 | } | ||
123 | 142 | ||
124 | EXPORT_SYMBOL(pxa_request_dma); | 143 | EXPORT_SYMBOL(pxa_request_dma); |
125 | EXPORT_SYMBOL(pxa_free_dma); | 144 | EXPORT_SYMBOL(pxa_free_dma); |
126 | |||