diff options
-rw-r--r-- | arch/arm/mach-pxa/dma.c | 44 | ||||
-rw-r--r-- | arch/arm/mach-pxa/pxa25x.c | 5 | ||||
-rw-r--r-- | arch/arm/mach-pxa/pxa27x.c | 3 | ||||
-rw-r--r-- | include/asm-arm/arch-pxa/dma.h | 22 |
4 files changed, 41 insertions, 33 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 | |||
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c index a8796aea8353..13437582342d 100644 --- a/arch/arm/mach-pxa/pxa25x.c +++ b/arch/arm/mach-pxa/pxa25x.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <asm/arch/irqs.h> | 25 | #include <asm/arch/irqs.h> |
26 | #include <asm/arch/pxa-regs.h> | 26 | #include <asm/arch/pxa-regs.h> |
27 | #include <asm/arch/pm.h> | 27 | #include <asm/arch/pm.h> |
28 | #include <asm/arch/dma.h> | ||
28 | 29 | ||
29 | #include "generic.h" | 30 | #include "generic.h" |
30 | 31 | ||
@@ -137,7 +138,11 @@ void __init pxa25x_init_irq(void) | |||
137 | 138 | ||
138 | static int __init pxa25x_init(void) | 139 | static int __init pxa25x_init(void) |
139 | { | 140 | { |
141 | int ret = 0; | ||
142 | |||
140 | if (cpu_is_pxa21x() || cpu_is_pxa25x()) { | 143 | if (cpu_is_pxa21x() || cpu_is_pxa25x()) { |
144 | if ((ret = pxa_init_dma(16))) | ||
145 | return ret; | ||
141 | #ifdef CONFIG_PM | 146 | #ifdef CONFIG_PM |
142 | pm_set_ops(&pxa25x_pm_ops); | 147 | pm_set_ops(&pxa25x_pm_ops); |
143 | #endif | 148 | #endif |
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index 1407985c8ab0..5b819e2c5563 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <asm/arch/pxa-regs.h> | 23 | #include <asm/arch/pxa-regs.h> |
24 | #include <asm/arch/ohci.h> | 24 | #include <asm/arch/ohci.h> |
25 | #include <asm/arch/pm.h> | 25 | #include <asm/arch/pm.h> |
26 | #include <asm/arch/dma.h> | ||
26 | 27 | ||
27 | #include "generic.h" | 28 | #include "generic.h" |
28 | 29 | ||
@@ -214,6 +215,8 @@ static int __init pxa27x_init(void) | |||
214 | { | 215 | { |
215 | int ret = 0; | 216 | int ret = 0; |
216 | if (cpu_is_pxa27x()) { | 217 | if (cpu_is_pxa27x()) { |
218 | if ((ret = pxa_init_dma(32))) | ||
219 | return ret; | ||
217 | #ifdef CONFIG_PM | 220 | #ifdef CONFIG_PM |
218 | pm_set_ops(&pxa27x_pm_ops); | 221 | pm_set_ops(&pxa27x_pm_ops); |
219 | #endif | 222 | #endif |
diff --git a/include/asm-arm/arch-pxa/dma.h b/include/asm-arm/arch-pxa/dma.h index bed042d71d68..3280ee2ddfa5 100644 --- a/include/asm-arm/arch-pxa/dma.h +++ b/include/asm-arm/arch-pxa/dma.h | |||
@@ -30,30 +30,12 @@ typedef enum { | |||
30 | DMA_PRIO_LOW = 2 | 30 | DMA_PRIO_LOW = 2 |
31 | } pxa_dma_prio; | 31 | } pxa_dma_prio; |
32 | 32 | ||
33 | #if defined(CONFIG_PXA27x) | ||
34 | |||
35 | #define PXA_DMA_CHANNELS 32 | ||
36 | |||
37 | #define pxa_for_each_dma_prio(ch, prio) \ | ||
38 | for ( \ | ||
39 | ch = prio * 4; \ | ||
40 | ch != (4 << prio) + 16; \ | ||
41 | ch = (ch + 1 == (4 << prio)) ? (prio * 4 + 16) : (ch + 1) \ | ||
42 | ) | ||
43 | |||
44 | #elif defined(CONFIG_PXA25x) | ||
45 | |||
46 | #define PXA_DMA_CHANNELS 16 | ||
47 | |||
48 | #define pxa_for_each_dma_prio(ch, prio) \ | ||
49 | for (ch = prio * 4; ch != (4 << prio); ch++) | ||
50 | |||
51 | #endif | ||
52 | |||
53 | /* | 33 | /* |
54 | * DMA registration | 34 | * DMA registration |
55 | */ | 35 | */ |
56 | 36 | ||
37 | int __init pxa_init_dma(int num_ch); | ||
38 | |||
57 | int pxa_request_dma (char *name, | 39 | int pxa_request_dma (char *name, |
58 | pxa_dma_prio prio, | 40 | pxa_dma_prio prio, |
59 | void (*irq_handler)(int, void *), | 41 | void (*irq_handler)(int, void *), |