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 c7513f6eb50..2ec9a9e9a04 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c @@ -28,6 +28,7 @@ #include <linux/timex.h> #include <linux/clocksource.h> +#include <asm/arch/udc.h> #include <asm/hardware.h> #include <asm/uaccess.h> #include <asm/io.h> @@ -39,6 +40,8 @@ #include <asm/mach/irq.h> #include <asm/mach/time.h> +static int __init ixp4xx_clocksource_init(void); + /************************************************************************* * IXP4xx chipset I/O mapping *************************************************************************/ @@ -86,7 +89,8 @@ enum ixp4xx_irq_type { IXP4XX_IRQ_LEVEL, IXP4XX_IRQ_EDGE }; -static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type); +/* Each bit represents an IRQ: 1: edge-triggered, 0: level triggered */ +static unsigned long long ixp4xx_irq_edge = 0; /* * IRQ -> GPIO mapping table @@ -135,7 +139,11 @@ static int ixp4xx_set_irq_type(unsigned int irq, unsigned int type) default: return -EINVAL; } - ixp4xx_config_irq(irq, irq_type); + + if (irq_type == IXP4XX_IRQ_EDGE) + ixp4xx_irq_edge |= (1 << irq); + else + ixp4xx_irq_edge &= ~(1 << irq); if (line >= 8) { /* pins 8-15 */ line -= 8; @@ -167,14 +175,6 @@ static void ixp4xx_irq_mask(unsigned int irq) *IXP4XX_ICMR &= ~(1 << irq); } -static void ixp4xx_irq_unmask(unsigned int irq) -{ - if (cpu_is_ixp46x() && irq >= 32) - *IXP4XX_ICMR2 |= (1 << (irq - 32)); - else - *IXP4XX_ICMR |= (1 << irq); -} - static void ixp4xx_irq_ack(unsigned int irq) { int line = (irq < 32) ? irq2gpio[irq] : -1; @@ -187,41 +187,25 @@ static void ixp4xx_irq_ack(unsigned int irq) * Level triggered interrupts on GPIO lines can only be cleared when the * interrupt condition disappears. */ -static void ixp4xx_irq_level_unmask(unsigned int irq) +static void ixp4xx_irq_unmask(unsigned int irq) { - ixp4xx_irq_ack(irq); - ixp4xx_irq_unmask(irq); -} + if (!(ixp4xx_irq_edge & (1 << irq))) + ixp4xx_irq_ack(irq); -static struct irqchip ixp4xx_irq_level_chip = { - .ack = ixp4xx_irq_mask, - .mask = ixp4xx_irq_mask, - .unmask = ixp4xx_irq_level_unmask, - .set_type = ixp4xx_set_irq_type, -}; + if (cpu_is_ixp46x() && irq >= 32) + *IXP4XX_ICMR2 |= (1 << (irq - 32)); + else + *IXP4XX_ICMR |= (1 << irq); +} -static struct irqchip ixp4xx_irq_edge_chip = { +static struct irq_chip ixp4xx_irq_chip = { + .name = "IXP4xx", .ack = ixp4xx_irq_ack, .mask = ixp4xx_irq_mask, .unmask = ixp4xx_irq_unmask, .set_type = ixp4xx_set_irq_type, }; -static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type) -{ - switch (type) { - case IXP4XX_IRQ_LEVEL: - set_irq_chip(irq, &ixp4xx_irq_level_chip); - set_irq_handler(irq, do_level_IRQ); - break; - case IXP4XX_IRQ_EDGE: - set_irq_chip(irq, &ixp4xx_irq_edge_chip); - set_irq_handler(irq, do_edge_IRQ); - break; - } - set_irq_flags(irq, IRQF_VALID); -} - void __init ixp4xx_init_irq(void) { int i = 0; @@ -241,8 +225,11 @@ void __init ixp4xx_init_irq(void) } /* Default to all level triggered */ - for(i = 0; i < NR_IRQS; i++) - ixp4xx_config_irq(i, IXP4XX_IRQ_LEVEL); + for(i = 0; i < NR_IRQS; i++) { + set_irq_chip(i, &ixp4xx_irq_chip); + set_irq_handler(i, handle_level_irq); + set_irq_flags(i, IRQF_VALID); + } } @@ -296,12 +283,52 @@ static void __init ixp4xx_timer_init(void) /* Connect the interrupt handler and enable the interrupt */ setup_irq(IRQ_IXP4XX_TIMER1, &ixp4xx_timer_irq); + + ixp4xx_clocksource_init(); } struct sys_timer ixp4xx_timer = { .init = ixp4xx_timer_init, }; +static struct pxa2xx_udc_mach_info ixp4xx_udc_info; + +void __init ixp4xx_set_udc_info(struct pxa2xx_udc_mach_info *info) +{ + memcpy(&ixp4xx_udc_info, info, sizeof *info); +} + +static struct resource ixp4xx_udc_resources[] = { + [0] = { + .start = 0xc800b000, + .end = 0xc800bfff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_IXP4XX_USB, + .end = IRQ_IXP4XX_USB, + .flags = IORESOURCE_IRQ, + }, +}; + +/* + * USB device controller. The IXP4xx uses the same controller as PXA2XX, + * so we just use the same device. + */ +static struct platform_device ixp4xx_udc_device = { + .name = "pxa2xx-udc", + .id = -1, + .num_resources = 2, + .resource = ixp4xx_udc_resources, + .dev = { + .platform_data = &ixp4xx_udc_info, + }, +}; + +static struct platform_device *ixp4xx_devices[] __initdata = { + &ixp4xx_udc_device, +}; + static struct resource ixp46x_i2c_resources[] = { [0] = { .start = 0xc8011000, @@ -337,6 +364,8 @@ void __init ixp4xx_sys_init(void) { ixp4xx_exp_bus_size = SZ_16M; + platform_add_devices(ixp4xx_devices, ARRAY_SIZE(ixp4xx_devices)); + if (cpu_is_ixp46x()) { int region; @@ -379,5 +408,3 @@ static int __init ixp4xx_clocksource_init(void) return 0; } - -device_initcall(ixp4xx_clocksource_init); |