diff options
author | Rabin Vincent <rabin.vincent@stericsson.com> | 2011-02-07 22:54:37 -0500 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2011-02-17 07:56:12 -0500 |
commit | aa90eb9d9d39d6e312b822cfa1512bb76e0e1df3 (patch) | |
tree | 28f3c2130a296be1644980c8d844b72025ff8f89 /arch/arm/mach-ux500 | |
parent | 0e25a5c98067286fc727cf142fc0dadf95790921 (diff) |
mach-ux500: DB8500 PMU support
DB8500 has irqs from two cores ORed into one. Implement a
workaround to handle this by bouncing the interrupt by setting
the affinity to the other core when the interrupt appears to
be spurious on the current core.
Signed-off-by: Rabin Vincent <rabin.vincent@stericsson.com>
Acked-by: Lee Jones <lee.jones@linaro.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'arch/arm/mach-ux500')
-rw-r--r-- | arch/arm/mach-ux500/cpu-db8500.c | 51 |
1 files changed, 47 insertions, 4 deletions
diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index 1748fbc58530..5c0fabf5fa01 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c | |||
@@ -12,22 +12,20 @@ | |||
12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | #include <linux/device.h> | 13 | #include <linux/device.h> |
14 | #include <linux/amba/bus.h> | 14 | #include <linux/amba/bus.h> |
15 | #include <linux/interrupt.h> | ||
15 | #include <linux/irq.h> | 16 | #include <linux/irq.h> |
16 | #include <linux/gpio.h> | 17 | #include <linux/gpio.h> |
17 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
18 | #include <linux/io.h> | 19 | #include <linux/io.h> |
19 | 20 | ||
20 | #include <asm/mach/map.h> | 21 | #include <asm/mach/map.h> |
22 | #include <asm/pmu.h> | ||
21 | #include <mach/hardware.h> | 23 | #include <mach/hardware.h> |
22 | #include <mach/setup.h> | 24 | #include <mach/setup.h> |
23 | #include <mach/devices.h> | 25 | #include <mach/devices.h> |
24 | 26 | ||
25 | #include "devices-db8500.h" | 27 | #include "devices-db8500.h" |
26 | 28 | ||
27 | static struct platform_device *platform_devs[] __initdata = { | ||
28 | &u8500_dma40_device, | ||
29 | }; | ||
30 | |||
31 | /* minimum static i/o mapping required to boot U8500 platforms */ | 29 | /* minimum static i/o mapping required to boot U8500 platforms */ |
32 | static struct map_desc u8500_uart_io_desc[] __initdata = { | 30 | static struct map_desc u8500_uart_io_desc[] __initdata = { |
33 | __IO_DEV_DESC(U8500_UART0_BASE, SZ_4K), | 31 | __IO_DEV_DESC(U8500_UART0_BASE, SZ_4K), |
@@ -89,6 +87,51 @@ void __init u8500_map_io(void) | |||
89 | iotable_init(u8500_v2_io_desc, ARRAY_SIZE(u8500_v2_io_desc)); | 87 | iotable_init(u8500_v2_io_desc, ARRAY_SIZE(u8500_v2_io_desc)); |
90 | } | 88 | } |
91 | 89 | ||
90 | static struct resource db8500_pmu_resources[] = { | ||
91 | [0] = { | ||
92 | .start = IRQ_DB8500_PMU, | ||
93 | .end = IRQ_DB8500_PMU, | ||
94 | .flags = IORESOURCE_IRQ, | ||
95 | }, | ||
96 | }; | ||
97 | |||
98 | /* | ||
99 | * The PMU IRQ lines of two cores are wired together into a single interrupt. | ||
100 | * Bounce the interrupt to the other core if it's not ours. | ||
101 | */ | ||
102 | static irqreturn_t db8500_pmu_handler(int irq, void *dev, irq_handler_t handler) | ||
103 | { | ||
104 | irqreturn_t ret = handler(irq, dev); | ||
105 | int other = !smp_processor_id(); | ||
106 | |||
107 | if (ret == IRQ_NONE && cpu_online(other)) | ||
108 | irq_set_affinity(irq, cpumask_of(other)); | ||
109 | |||
110 | /* | ||
111 | * We should be able to get away with the amount of IRQ_NONEs we give, | ||
112 | * while still having the spurious IRQ detection code kick in if the | ||
113 | * interrupt really starts hitting spuriously. | ||
114 | */ | ||
115 | return ret; | ||
116 | } | ||
117 | |||
118 | static struct arm_pmu_platdata db8500_pmu_platdata = { | ||
119 | .handle_irq = db8500_pmu_handler, | ||
120 | }; | ||
121 | |||
122 | static struct platform_device db8500_pmu_device = { | ||
123 | .name = "arm-pmu", | ||
124 | .id = ARM_PMU_DEVICE_CPU, | ||
125 | .num_resources = ARRAY_SIZE(db8500_pmu_resources), | ||
126 | .resource = db8500_pmu_resources, | ||
127 | .dev.platform_data = &db8500_pmu_platdata, | ||
128 | }; | ||
129 | |||
130 | static struct platform_device *platform_devs[] __initdata = { | ||
131 | &u8500_dma40_device, | ||
132 | &db8500_pmu_device, | ||
133 | }; | ||
134 | |||
92 | static resource_size_t __initdata db8500_gpio_base[] = { | 135 | static resource_size_t __initdata db8500_gpio_base[] = { |
93 | U8500_GPIOBANK0_BASE, | 136 | U8500_GPIOBANK0_BASE, |
94 | U8500_GPIOBANK1_BASE, | 137 | U8500_GPIOBANK1_BASE, |