diff options
Diffstat (limited to 'arch/arm/mach-ixp4xx/common.c')
-rw-r--r-- | arch/arm/mach-ixp4xx/common.c | 107 |
1 files changed, 67 insertions, 40 deletions
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index c7513f6eb50c..2ec9a9e9a04d 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/timex.h> | 28 | #include <linux/timex.h> |
29 | #include <linux/clocksource.h> | 29 | #include <linux/clocksource.h> |
30 | 30 | ||
31 | #include <asm/arch/udc.h> | ||
31 | #include <asm/hardware.h> | 32 | #include <asm/hardware.h> |
32 | #include <asm/uaccess.h> | 33 | #include <asm/uaccess.h> |
33 | #include <asm/io.h> | 34 | #include <asm/io.h> |
@@ -39,6 +40,8 @@ | |||
39 | #include <asm/mach/irq.h> | 40 | #include <asm/mach/irq.h> |
40 | #include <asm/mach/time.h> | 41 | #include <asm/mach/time.h> |
41 | 42 | ||
43 | static int __init ixp4xx_clocksource_init(void); | ||
44 | |||
42 | /************************************************************************* | 45 | /************************************************************************* |
43 | * IXP4xx chipset I/O mapping | 46 | * IXP4xx chipset I/O mapping |
44 | *************************************************************************/ | 47 | *************************************************************************/ |
@@ -86,7 +89,8 @@ enum ixp4xx_irq_type { | |||
86 | IXP4XX_IRQ_LEVEL, IXP4XX_IRQ_EDGE | 89 | IXP4XX_IRQ_LEVEL, IXP4XX_IRQ_EDGE |
87 | }; | 90 | }; |
88 | 91 | ||
89 | static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type); | 92 | /* Each bit represents an IRQ: 1: edge-triggered, 0: level triggered */ |
93 | static unsigned long long ixp4xx_irq_edge = 0; | ||
90 | 94 | ||
91 | /* | 95 | /* |
92 | * IRQ -> GPIO mapping table | 96 | * IRQ -> GPIO mapping table |
@@ -135,7 +139,11 @@ static int ixp4xx_set_irq_type(unsigned int irq, unsigned int type) | |||
135 | default: | 139 | default: |
136 | return -EINVAL; | 140 | return -EINVAL; |
137 | } | 141 | } |
138 | ixp4xx_config_irq(irq, irq_type); | 142 | |
143 | if (irq_type == IXP4XX_IRQ_EDGE) | ||
144 | ixp4xx_irq_edge |= (1 << irq); | ||
145 | else | ||
146 | ixp4xx_irq_edge &= ~(1 << irq); | ||
139 | 147 | ||
140 | if (line >= 8) { /* pins 8-15 */ | 148 | if (line >= 8) { /* pins 8-15 */ |
141 | line -= 8; | 149 | line -= 8; |
@@ -167,14 +175,6 @@ static void ixp4xx_irq_mask(unsigned int irq) | |||
167 | *IXP4XX_ICMR &= ~(1 << irq); | 175 | *IXP4XX_ICMR &= ~(1 << irq); |
168 | } | 176 | } |
169 | 177 | ||
170 | static void ixp4xx_irq_unmask(unsigned int irq) | ||
171 | { | ||
172 | if (cpu_is_ixp46x() && irq >= 32) | ||
173 | *IXP4XX_ICMR2 |= (1 << (irq - 32)); | ||
174 | else | ||
175 | *IXP4XX_ICMR |= (1 << irq); | ||
176 | } | ||
177 | |||
178 | static void ixp4xx_irq_ack(unsigned int irq) | 178 | static void ixp4xx_irq_ack(unsigned int irq) |
179 | { | 179 | { |
180 | int line = (irq < 32) ? irq2gpio[irq] : -1; | 180 | int line = (irq < 32) ? irq2gpio[irq] : -1; |
@@ -187,41 +187,25 @@ static void ixp4xx_irq_ack(unsigned int irq) | |||
187 | * Level triggered interrupts on GPIO lines can only be cleared when the | 187 | * Level triggered interrupts on GPIO lines can only be cleared when the |
188 | * interrupt condition disappears. | 188 | * interrupt condition disappears. |
189 | */ | 189 | */ |
190 | static void ixp4xx_irq_level_unmask(unsigned int irq) | 190 | static void ixp4xx_irq_unmask(unsigned int irq) |
191 | { | 191 | { |
192 | ixp4xx_irq_ack(irq); | 192 | if (!(ixp4xx_irq_edge & (1 << irq))) |
193 | ixp4xx_irq_unmask(irq); | 193 | ixp4xx_irq_ack(irq); |
194 | } | ||
195 | 194 | ||
196 | static struct irqchip ixp4xx_irq_level_chip = { | 195 | if (cpu_is_ixp46x() && irq >= 32) |
197 | .ack = ixp4xx_irq_mask, | 196 | *IXP4XX_ICMR2 |= (1 << (irq - 32)); |
198 | .mask = ixp4xx_irq_mask, | 197 | else |
199 | .unmask = ixp4xx_irq_level_unmask, | 198 | *IXP4XX_ICMR |= (1 << irq); |
200 | .set_type = ixp4xx_set_irq_type, | 199 | } |
201 | }; | ||
202 | 200 | ||
203 | static struct irqchip ixp4xx_irq_edge_chip = { | 201 | static struct irq_chip ixp4xx_irq_chip = { |
202 | .name = "IXP4xx", | ||
204 | .ack = ixp4xx_irq_ack, | 203 | .ack = ixp4xx_irq_ack, |
205 | .mask = ixp4xx_irq_mask, | 204 | .mask = ixp4xx_irq_mask, |
206 | .unmask = ixp4xx_irq_unmask, | 205 | .unmask = ixp4xx_irq_unmask, |
207 | .set_type = ixp4xx_set_irq_type, | 206 | .set_type = ixp4xx_set_irq_type, |
208 | }; | 207 | }; |
209 | 208 | ||
210 | static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type) | ||
211 | { | ||
212 | switch (type) { | ||
213 | case IXP4XX_IRQ_LEVEL: | ||
214 | set_irq_chip(irq, &ixp4xx_irq_level_chip); | ||
215 | set_irq_handler(irq, do_level_IRQ); | ||
216 | break; | ||
217 | case IXP4XX_IRQ_EDGE: | ||
218 | set_irq_chip(irq, &ixp4xx_irq_edge_chip); | ||
219 | set_irq_handler(irq, do_edge_IRQ); | ||
220 | break; | ||
221 | } | ||
222 | set_irq_flags(irq, IRQF_VALID); | ||
223 | } | ||
224 | |||
225 | void __init ixp4xx_init_irq(void) | 209 | void __init ixp4xx_init_irq(void) |
226 | { | 210 | { |
227 | int i = 0; | 211 | int i = 0; |
@@ -241,8 +225,11 @@ void __init ixp4xx_init_irq(void) | |||
241 | } | 225 | } |
242 | 226 | ||
243 | /* Default to all level triggered */ | 227 | /* Default to all level triggered */ |
244 | for(i = 0; i < NR_IRQS; i++) | 228 | for(i = 0; i < NR_IRQS; i++) { |
245 | ixp4xx_config_irq(i, IXP4XX_IRQ_LEVEL); | 229 | set_irq_chip(i, &ixp4xx_irq_chip); |
230 | set_irq_handler(i, handle_level_irq); | ||
231 | set_irq_flags(i, IRQF_VALID); | ||
232 | } | ||
246 | } | 233 | } |
247 | 234 | ||
248 | 235 | ||
@@ -296,12 +283,52 @@ static void __init ixp4xx_timer_init(void) | |||
296 | 283 | ||
297 | /* Connect the interrupt handler and enable the interrupt */ | 284 | /* Connect the interrupt handler and enable the interrupt */ |
298 | setup_irq(IRQ_IXP4XX_TIMER1, &ixp4xx_timer_irq); | 285 | setup_irq(IRQ_IXP4XX_TIMER1, &ixp4xx_timer_irq); |
286 | |||
287 | ixp4xx_clocksource_init(); | ||
299 | } | 288 | } |
300 | 289 | ||
301 | struct sys_timer ixp4xx_timer = { | 290 | struct sys_timer ixp4xx_timer = { |
302 | .init = ixp4xx_timer_init, | 291 | .init = ixp4xx_timer_init, |
303 | }; | 292 | }; |
304 | 293 | ||
294 | static struct pxa2xx_udc_mach_info ixp4xx_udc_info; | ||
295 | |||
296 | void __init ixp4xx_set_udc_info(struct pxa2xx_udc_mach_info *info) | ||
297 | { | ||
298 | memcpy(&ixp4xx_udc_info, info, sizeof *info); | ||
299 | } | ||
300 | |||
301 | static struct resource ixp4xx_udc_resources[] = { | ||
302 | [0] = { | ||
303 | .start = 0xc800b000, | ||
304 | .end = 0xc800bfff, | ||
305 | .flags = IORESOURCE_MEM, | ||
306 | }, | ||
307 | [1] = { | ||
308 | .start = IRQ_IXP4XX_USB, | ||
309 | .end = IRQ_IXP4XX_USB, | ||
310 | .flags = IORESOURCE_IRQ, | ||
311 | }, | ||
312 | }; | ||
313 | |||
314 | /* | ||
315 | * USB device controller. The IXP4xx uses the same controller as PXA2XX, | ||
316 | * so we just use the same device. | ||
317 | */ | ||
318 | static struct platform_device ixp4xx_udc_device = { | ||
319 | .name = "pxa2xx-udc", | ||
320 | .id = -1, | ||
321 | .num_resources = 2, | ||
322 | .resource = ixp4xx_udc_resources, | ||
323 | .dev = { | ||
324 | .platform_data = &ixp4xx_udc_info, | ||
325 | }, | ||
326 | }; | ||
327 | |||
328 | static struct platform_device *ixp4xx_devices[] __initdata = { | ||
329 | &ixp4xx_udc_device, | ||
330 | }; | ||
331 | |||
305 | static struct resource ixp46x_i2c_resources[] = { | 332 | static struct resource ixp46x_i2c_resources[] = { |
306 | [0] = { | 333 | [0] = { |
307 | .start = 0xc8011000, | 334 | .start = 0xc8011000, |
@@ -337,6 +364,8 @@ void __init ixp4xx_sys_init(void) | |||
337 | { | 364 | { |
338 | ixp4xx_exp_bus_size = SZ_16M; | 365 | ixp4xx_exp_bus_size = SZ_16M; |
339 | 366 | ||
367 | platform_add_devices(ixp4xx_devices, ARRAY_SIZE(ixp4xx_devices)); | ||
368 | |||
340 | if (cpu_is_ixp46x()) { | 369 | if (cpu_is_ixp46x()) { |
341 | int region; | 370 | int region; |
342 | 371 | ||
@@ -379,5 +408,3 @@ static int __init ixp4xx_clocksource_init(void) | |||
379 | 408 | ||
380 | return 0; | 409 | return 0; |
381 | } | 410 | } |
382 | |||
383 | device_initcall(ixp4xx_clocksource_init); | ||