aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-shmobile
diff options
context:
space:
mode:
authorMagnus Damm <damm@opensource.se>2011-10-12 03:21:42 -0400
committerPaul Mundt <lethal@linux-sh.org>2011-11-04 12:02:51 -0400
commita1993055efcc14fd6d213b936d28a41ea52e1d3d (patch)
tree5284a00f273605d79cc9367594605a44ac1729ed /arch/arm/mach-shmobile
parentda5713ef03aba15761eeeade4f4938e5db98b1e2 (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.c122
-rw-r--r--arch/arm/mach-shmobile/pfc-sh73a0.c68
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
264INTC_IRQ_PINS_32(intca_irq_pins, 0xe6900000,
265 INTCS_VECT_RELOC, "sh73a0-intca-irq-pins");
266
267static 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
279static 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
287static 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
293static 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
299static 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
305static void intca_gic_eoi(struct irq_data *data)
306{
307 irq_cb(irq_eoi, to_gic_irq(data));
308}
309
310static 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
315static 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
321static 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
329struct 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
345static 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
358static 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
364static struct irqaction sh73a0_irq_pin_cascade[32];
365
258void __init sh73a0_init_irq(void) 366void __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
2771static struct pinmux_irq pinmux_irqs[] = { 2773static 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
2806static struct pinmux_info sh73a0_pinmux_info = { 2808static struct pinmux_info sh73a0_pinmux_info = {