diff options
author | Magnus Damm <damm@opensource.se> | 2011-10-12 03:21:42 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2011-11-04 12:02:51 -0400 |
commit | a1993055efcc14fd6d213b936d28a41ea52e1d3d (patch) | |
tree | 5284a00f273605d79cc9367594605a44ac1729ed /arch/arm/mach-shmobile | |
parent | da5713ef03aba15761eeeade4f4938e5db98b1e2 (diff) |
ARM: mach-shmobile: Use common INTC IRQ code on sh73a0
Improve IRQ triggering support by making use of the macro
INTC_IRQ_PINS_32() for INTCA on sh73a0. Unfortunately it
is not as easy as just using the macro as-is, we need to
do mask and unmaks in the GIC but configure other bits
and ack in INTCA. Update GPIO IRQ mappings while at it.
Signed-off-by: Magnus Damm <damm@opensource.se>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/arm/mach-shmobile')
-rw-r--r-- | arch/arm/mach-shmobile/intc-sh73a0.c | 122 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/pfc-sh73a0.c | 68 |
2 files changed, 157 insertions, 33 deletions
diff --git a/arch/arm/mach-shmobile/intc-sh73a0.c b/arch/arm/mach-shmobile/intc-sh73a0.c index a911a60e7719..836e81557986 100644 --- a/arch/arm/mach-shmobile/intc-sh73a0.c +++ b/arch/arm/mach-shmobile/intc-sh73a0.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/irq.h> | 22 | #include <linux/irq.h> |
23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | #include <linux/sh_intc.h> | 24 | #include <linux/sh_intc.h> |
25 | #include <mach/intc.h> | ||
25 | #include <asm/hardware/gic.h> | 26 | #include <asm/hardware/gic.h> |
26 | #include <asm/mach-types.h> | 27 | #include <asm/mach-types.h> |
27 | #include <asm/mach/arch.h> | 28 | #include <asm/mach/arch.h> |
@@ -255,20 +256,141 @@ static int sh73a0_set_wake(struct irq_data *data, unsigned int on) | |||
255 | return 0; /* always allow wakeup */ | 256 | return 0; /* always allow wakeup */ |
256 | } | 257 | } |
257 | 258 | ||
259 | #define RELOC_BASE 0x1000 | ||
260 | |||
261 | /* INTCA IRQ pins at INTCS + 0x1000 to make space for GIC+INTC handling */ | ||
262 | #define INTCS_VECT_RELOC(n, vect) INTCS_VECT((n), (vect) + RELOC_BASE) | ||
263 | |||
264 | INTC_IRQ_PINS_32(intca_irq_pins, 0xe6900000, | ||
265 | INTCS_VECT_RELOC, "sh73a0-intca-irq-pins"); | ||
266 | |||
267 | static int to_gic_irq(struct irq_data *data) | ||
268 | { | ||
269 | unsigned int vect = irq2evt(data->irq) - INTCS_VECT_BASE; | ||
270 | |||
271 | if (vect >= 0x3200) | ||
272 | vect -= 0x3000; | ||
273 | else | ||
274 | vect -= 0x0200; | ||
275 | |||
276 | return gic_spi((vect >> 5) + 1); | ||
277 | } | ||
278 | |||
279 | static int to_intca_reloc_irq(struct irq_data *data) | ||
280 | { | ||
281 | return data->irq + (RELOC_BASE >> 5); | ||
282 | } | ||
283 | |||
284 | #define irq_cb(cb, irq) irq_get_chip(irq)->cb(irq_get_irq_data(irq)) | ||
285 | #define irq_cbp(cb, irq, p...) irq_get_chip(irq)->cb(irq_get_irq_data(irq), p) | ||
286 | |||
287 | static void intca_gic_enable(struct irq_data *data) | ||
288 | { | ||
289 | irq_cb(irq_unmask, to_intca_reloc_irq(data)); | ||
290 | irq_cb(irq_unmask, to_gic_irq(data)); | ||
291 | } | ||
292 | |||
293 | static void intca_gic_disable(struct irq_data *data) | ||
294 | { | ||
295 | irq_cb(irq_mask, to_gic_irq(data)); | ||
296 | irq_cb(irq_mask, to_intca_reloc_irq(data)); | ||
297 | } | ||
298 | |||
299 | static void intca_gic_mask_ack(struct irq_data *data) | ||
300 | { | ||
301 | irq_cb(irq_mask, to_gic_irq(data)); | ||
302 | irq_cb(irq_mask_ack, to_intca_reloc_irq(data)); | ||
303 | } | ||
304 | |||
305 | static void intca_gic_eoi(struct irq_data *data) | ||
306 | { | ||
307 | irq_cb(irq_eoi, to_gic_irq(data)); | ||
308 | } | ||
309 | |||
310 | static int intca_gic_set_type(struct irq_data *data, unsigned int type) | ||
311 | { | ||
312 | return irq_cbp(irq_set_type, to_intca_reloc_irq(data), type); | ||
313 | } | ||
314 | |||
315 | static int intca_gic_set_wake(struct irq_data *data, unsigned int on) | ||
316 | { | ||
317 | return irq_cbp(irq_set_wake, to_intca_reloc_irq(data), on); | ||
318 | } | ||
319 | |||
320 | #ifdef CONFIG_SMP | ||
321 | static int intca_gic_set_affinity(struct irq_data *data, | ||
322 | const struct cpumask *cpumask, | ||
323 | bool force) | ||
324 | { | ||
325 | return irq_cbp(irq_set_affinity, to_gic_irq(data), cpumask, force); | ||
326 | } | ||
327 | #endif | ||
328 | |||
329 | struct irq_chip intca_gic_irq_chip = { | ||
330 | .name = "INTCA-GIC", | ||
331 | .irq_mask = intca_gic_disable, | ||
332 | .irq_unmask = intca_gic_enable, | ||
333 | .irq_mask_ack = intca_gic_mask_ack, | ||
334 | .irq_eoi = intca_gic_eoi, | ||
335 | .irq_enable = intca_gic_enable, | ||
336 | .irq_disable = intca_gic_disable, | ||
337 | .irq_shutdown = intca_gic_disable, | ||
338 | .irq_set_type = intca_gic_set_type, | ||
339 | .irq_set_wake = intca_gic_set_wake, | ||
340 | #ifdef CONFIG_SMP | ||
341 | .irq_set_affinity = intca_gic_set_affinity, | ||
342 | #endif | ||
343 | }; | ||
344 | |||
345 | static int to_intc_vect(int irq) | ||
346 | { | ||
347 | unsigned int irq_pin = irq - gic_spi(1); | ||
348 | unsigned int offs; | ||
349 | |||
350 | if (irq_pin < 16) | ||
351 | offs = 0x0200; | ||
352 | else | ||
353 | offs = 0x3000; | ||
354 | |||
355 | return offs + (irq_pin << 5); | ||
356 | } | ||
357 | |||
358 | static irqreturn_t sh73a0_irq_pin_demux(int irq, void *dev_id) | ||
359 | { | ||
360 | generic_handle_irq(intcs_evt2irq(to_intc_vect(irq))); | ||
361 | return IRQ_HANDLED; | ||
362 | } | ||
363 | |||
364 | static struct irqaction sh73a0_irq_pin_cascade[32]; | ||
365 | |||
258 | void __init sh73a0_init_irq(void) | 366 | void __init sh73a0_init_irq(void) |
259 | { | 367 | { |
260 | void __iomem *gic_dist_base = __io(0xf0001000); | 368 | void __iomem *gic_dist_base = __io(0xf0001000); |
261 | void __iomem *gic_cpu_base = __io(0xf0000100); | 369 | void __iomem *gic_cpu_base = __io(0xf0000100); |
262 | void __iomem *intevtsa = ioremap_nocache(0xffd20100, PAGE_SIZE); | 370 | void __iomem *intevtsa = ioremap_nocache(0xffd20100, PAGE_SIZE); |
371 | int k, n; | ||
263 | 372 | ||
264 | gic_init(0, 29, gic_dist_base, gic_cpu_base); | 373 | gic_init(0, 29, gic_dist_base, gic_cpu_base); |
265 | gic_arch_extn.irq_set_wake = sh73a0_set_wake; | 374 | gic_arch_extn.irq_set_wake = sh73a0_set_wake; |
266 | 375 | ||
267 | register_intc_controller(&intcs_desc); | 376 | register_intc_controller(&intcs_desc); |
377 | register_intc_controller(&intca_irq_pins_desc); | ||
268 | 378 | ||
269 | /* demux using INTEVTSA */ | 379 | /* demux using INTEVTSA */ |
270 | sh73a0_intcs_cascade.name = "INTCS cascade"; | 380 | sh73a0_intcs_cascade.name = "INTCS cascade"; |
271 | sh73a0_intcs_cascade.handler = sh73a0_intcs_demux; | 381 | sh73a0_intcs_cascade.handler = sh73a0_intcs_demux; |
272 | sh73a0_intcs_cascade.dev_id = intevtsa; | 382 | sh73a0_intcs_cascade.dev_id = intevtsa; |
273 | setup_irq(gic_spi(50), &sh73a0_intcs_cascade); | 383 | setup_irq(gic_spi(50), &sh73a0_intcs_cascade); |
384 | |||
385 | /* IRQ pins require special handling through INTCA and GIC */ | ||
386 | for (k = 0; k < 32; k++) { | ||
387 | sh73a0_irq_pin_cascade[k].name = "INTCA-GIC cascade"; | ||
388 | sh73a0_irq_pin_cascade[k].handler = sh73a0_irq_pin_demux; | ||
389 | setup_irq(gic_spi(1 + k), &sh73a0_irq_pin_cascade[k]); | ||
390 | |||
391 | n = intcs_evt2irq(to_intc_vect(gic_spi(1 + k))); | ||
392 | irq_set_chip_and_handler_name(n, &intca_gic_irq_chip, | ||
393 | handle_level_irq, "level"); | ||
394 | set_irq_flags(n, IRQF_VALID); /* yuck */ | ||
395 | } | ||
274 | } | 396 | } |
diff --git a/arch/arm/mach-shmobile/pfc-sh73a0.c b/arch/arm/mach-shmobile/pfc-sh73a0.c index 57322c9fd9b6..5abe02fbd6b9 100644 --- a/arch/arm/mach-shmobile/pfc-sh73a0.c +++ b/arch/arm/mach-shmobile/pfc-sh73a0.c | |||
@@ -2766,41 +2766,43 @@ static struct pinmux_data_reg pinmux_data_regs[] = { | |||
2766 | { }, | 2766 | { }, |
2767 | }; | 2767 | }; |
2768 | 2768 | ||
2769 | #define EXT_IRQ(n) gic_spi((n) + 1) /* GIC SPI starting from 1 for IRQ0 */ | 2769 | /* IRQ pins through INTCS with IRQ0->15 from 0x200 and IRQ16-31 from 0x3200 */ |
2770 | #define EXT_IRQ16L(n) intcs_evt2irq(0x200 + ((n) << 5)) | ||
2771 | #define EXT_IRQ16H(n) intcs_evt2irq(0x3200 + ((n - 16) << 5)) | ||
2770 | 2772 | ||
2771 | static struct pinmux_irq pinmux_irqs[] = { | 2773 | static struct pinmux_irq pinmux_irqs[] = { |
2772 | PINMUX_IRQ(EXT_IRQ(19), PORT9_FN0), | 2774 | PINMUX_IRQ(EXT_IRQ16H(19), PORT9_FN0), |
2773 | PINMUX_IRQ(EXT_IRQ(1), PORT10_FN0), | 2775 | PINMUX_IRQ(EXT_IRQ16L(1), PORT10_FN0), |
2774 | PINMUX_IRQ(EXT_IRQ(0), PORT11_FN0), | 2776 | PINMUX_IRQ(EXT_IRQ16L(0), PORT11_FN0), |
2775 | PINMUX_IRQ(EXT_IRQ(18), PORT13_FN0), | 2777 | PINMUX_IRQ(EXT_IRQ16H(18), PORT13_FN0), |
2776 | PINMUX_IRQ(EXT_IRQ(20), PORT14_FN0), | 2778 | PINMUX_IRQ(EXT_IRQ16H(20), PORT14_FN0), |
2777 | PINMUX_IRQ(EXT_IRQ(21), PORT15_FN0), | 2779 | PINMUX_IRQ(EXT_IRQ16H(21), PORT15_FN0), |
2778 | PINMUX_IRQ(EXT_IRQ(31), PORT26_FN0), | 2780 | PINMUX_IRQ(EXT_IRQ16H(31), PORT26_FN0), |
2779 | PINMUX_IRQ(EXT_IRQ(30), PORT27_FN0), | 2781 | PINMUX_IRQ(EXT_IRQ16H(30), PORT27_FN0), |
2780 | PINMUX_IRQ(EXT_IRQ(29), PORT28_FN0), | 2782 | PINMUX_IRQ(EXT_IRQ16H(29), PORT28_FN0), |
2781 | PINMUX_IRQ(EXT_IRQ(22), PORT40_FN0), | 2783 | PINMUX_IRQ(EXT_IRQ16H(22), PORT40_FN0), |
2782 | PINMUX_IRQ(EXT_IRQ(23), PORT53_FN0), | 2784 | PINMUX_IRQ(EXT_IRQ16H(23), PORT53_FN0), |
2783 | PINMUX_IRQ(EXT_IRQ(10), PORT54_FN0), | 2785 | PINMUX_IRQ(EXT_IRQ16L(10), PORT54_FN0), |
2784 | PINMUX_IRQ(EXT_IRQ(9), PORT56_FN0), | 2786 | PINMUX_IRQ(EXT_IRQ16L(9), PORT56_FN0), |
2785 | PINMUX_IRQ(EXT_IRQ(26), PORT115_FN0), | 2787 | PINMUX_IRQ(EXT_IRQ16H(26), PORT115_FN0), |
2786 | PINMUX_IRQ(EXT_IRQ(27), PORT116_FN0), | 2788 | PINMUX_IRQ(EXT_IRQ16H(27), PORT116_FN0), |
2787 | PINMUX_IRQ(EXT_IRQ(28), PORT117_FN0), | 2789 | PINMUX_IRQ(EXT_IRQ16H(28), PORT117_FN0), |
2788 | PINMUX_IRQ(EXT_IRQ(24), PORT118_FN0), | 2790 | PINMUX_IRQ(EXT_IRQ16H(24), PORT118_FN0), |
2789 | PINMUX_IRQ(EXT_IRQ(6), PORT147_FN0), | 2791 | PINMUX_IRQ(EXT_IRQ16L(6), PORT147_FN0), |
2790 | PINMUX_IRQ(EXT_IRQ(2), PORT149_FN0), | 2792 | PINMUX_IRQ(EXT_IRQ16L(2), PORT149_FN0), |
2791 | PINMUX_IRQ(EXT_IRQ(7), PORT150_FN0), | 2793 | PINMUX_IRQ(EXT_IRQ16L(7), PORT150_FN0), |
2792 | PINMUX_IRQ(EXT_IRQ(12), PORT156_FN0), | 2794 | PINMUX_IRQ(EXT_IRQ16L(12), PORT156_FN0), |
2793 | PINMUX_IRQ(EXT_IRQ(4), PORT159_FN0), | 2795 | PINMUX_IRQ(EXT_IRQ16L(4), PORT159_FN0), |
2794 | PINMUX_IRQ(EXT_IRQ(25), PORT164_FN0), | 2796 | PINMUX_IRQ(EXT_IRQ16H(25), PORT164_FN0), |
2795 | PINMUX_IRQ(EXT_IRQ(8), PORT223_FN0), | 2797 | PINMUX_IRQ(EXT_IRQ16L(8), PORT223_FN0), |
2796 | PINMUX_IRQ(EXT_IRQ(3), PORT224_FN0), | 2798 | PINMUX_IRQ(EXT_IRQ16L(3), PORT224_FN0), |
2797 | PINMUX_IRQ(EXT_IRQ(5), PORT227_FN0), | 2799 | PINMUX_IRQ(EXT_IRQ16L(5), PORT227_FN0), |
2798 | PINMUX_IRQ(EXT_IRQ(17), PORT234_FN0), | 2800 | PINMUX_IRQ(EXT_IRQ16H(17), PORT234_FN0), |
2799 | PINMUX_IRQ(EXT_IRQ(11), PORT238_FN0), | 2801 | PINMUX_IRQ(EXT_IRQ16L(11), PORT238_FN0), |
2800 | PINMUX_IRQ(EXT_IRQ(13), PORT239_FN0), | 2802 | PINMUX_IRQ(EXT_IRQ16L(13), PORT239_FN0), |
2801 | PINMUX_IRQ(EXT_IRQ(16), PORT249_FN0), | 2803 | PINMUX_IRQ(EXT_IRQ16H(16), PORT249_FN0), |
2802 | PINMUX_IRQ(EXT_IRQ(14), PORT251_FN0), | 2804 | PINMUX_IRQ(EXT_IRQ16L(14), PORT251_FN0), |
2803 | PINMUX_IRQ(EXT_IRQ(9), PORT308_FN0), | 2805 | PINMUX_IRQ(EXT_IRQ16L(9), PORT308_FN0), |
2804 | }; | 2806 | }; |
2805 | 2807 | ||
2806 | static struct pinmux_info sh73a0_pinmux_info = { | 2808 | static struct pinmux_info sh73a0_pinmux_info = { |