aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorMagnus Damm <damm@opensource.se>2011-10-17 05:00:52 -0400
committerPaul Mundt <lethal@linux-sh.org>2011-11-04 12:03:55 -0400
commit566aad39df77211467078e0b3dcd62100f56b5e4 (patch)
treec91d7a06ad1a6f0090d425359d500ba9897d18f7 /arch/arm
parent91c088ae17c62f7741d9563e36935bc7a69a7e9e (diff)
ARM: mach-shmobile: sh73a0 and AG5EVM PINT support
Support PINT on sh73a0 and AG5EVM using INTC PINT macros. With this patch applied the AG5EVM ethernet is handled through one of the chained sh73a0 PINT interrupt controllers. Signed-off-by: Magnus Damm <damm@opensource.se> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/mach-shmobile/board-ag5evm.c17
-rw-r--r--arch/arm/mach-shmobile/include/mach/sh73a0.h4
-rw-r--r--arch/arm/mach-shmobile/intc-sh73a0.c65
3 files changed, 71 insertions, 15 deletions
diff --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c
index d6e46171052..83624e26b88 100644
--- a/arch/arm/mach-shmobile/board-ag5evm.c
+++ b/arch/arm/mach-shmobile/board-ag5evm.c
@@ -59,7 +59,7 @@ static struct resource smsc9220_resources[] = {
59 .flags = IORESOURCE_MEM, 59 .flags = IORESOURCE_MEM,
60 }, 60 },
61 [1] = { 61 [1] = {
62 .start = gic_spi(33), /* PINT1 */ 62 .start = SH73A0_PINT0_IRQ(2), /* PINTA2 */
63 .flags = IORESOURCE_IRQ, 63 .flags = IORESOURCE_IRQ,
64 }, 64 },
65}; 65};
@@ -474,19 +474,6 @@ static void __init ag5evm_map_io(void)
474 shmobile_setup_console(); 474 shmobile_setup_console();
475} 475}
476 476
477#define PINTC_ADDR 0xe6900000
478#define PINTER0A (PINTC_ADDR + 0xa0)
479#define PINTCR0A (PINTC_ADDR + 0xb0)
480
481void __init ag5evm_init_irq(void)
482{
483 sh73a0_init_irq();
484
485 /* setup PINT: enable PINTA2 as active low */
486 __raw_writel(__raw_readl(PINTER0A) | (1<<29), PINTER0A);
487 __raw_writew(__raw_readw(PINTCR0A) | (2<<10), PINTCR0A);
488}
489
490#define DSI0PHYCR 0xe615006c 477#define DSI0PHYCR 0xe615006c
491 478
492static void __init ag5evm_init(void) 479static void __init ag5evm_init(void)
@@ -620,7 +607,7 @@ struct sys_timer ag5evm_timer = {
620 607
621MACHINE_START(AG5EVM, "ag5evm") 608MACHINE_START(AG5EVM, "ag5evm")
622 .map_io = ag5evm_map_io, 609 .map_io = ag5evm_map_io,
623 .init_irq = ag5evm_init_irq, 610 .init_irq = sh73a0_init_irq,
624 .handle_irq = shmobile_handle_irq_gic, 611 .handle_irq = shmobile_handle_irq_gic,
625 .init_machine = ag5evm_init, 612 .init_machine = ag5evm_init,
626 .timer = &ag5evm_timer, 613 .timer = &ag5evm_timer,
diff --git a/arch/arm/mach-shmobile/include/mach/sh73a0.h b/arch/arm/mach-shmobile/include/mach/sh73a0.h
index b385e976797..18ae6a990bc 100644
--- a/arch/arm/mach-shmobile/include/mach/sh73a0.h
+++ b/arch/arm/mach-shmobile/include/mach/sh73a0.h
@@ -507,4 +507,8 @@ enum {
507 SHDMA_SLAVE_MMCIF_RX, 507 SHDMA_SLAVE_MMCIF_RX,
508}; 508};
509 509
510/* PINT interrupts are located at Linux IRQ 768 and up */
511#define SH73A0_PINT0_IRQ(irq) ((irq) + 768)
512#define SH73A0_PINT1_IRQ(irq) ((irq) + 800)
513
510#endif /* __ASM_SH73A0_H__ */ 514#endif /* __ASM_SH73A0_H__ */
diff --git a/arch/arm/mach-shmobile/intc-sh73a0.c b/arch/arm/mach-shmobile/intc-sh73a0.c
index 836e8155798..1eda6b0b69e 100644
--- a/arch/arm/mach-shmobile/intc-sh73a0.c
+++ b/arch/arm/mach-shmobile/intc-sh73a0.c
@@ -23,6 +23,7 @@
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 <mach/intc.h>
26#include <mach/sh73a0.h>
26#include <asm/hardware/gic.h> 27#include <asm/hardware/gic.h>
27#include <asm/mach-types.h> 28#include <asm/mach-types.h>
28#include <asm/mach/arch.h> 29#include <asm/mach/arch.h>
@@ -363,6 +364,59 @@ static irqreturn_t sh73a0_irq_pin_demux(int irq, void *dev_id)
363 364
364static struct irqaction sh73a0_irq_pin_cascade[32]; 365static struct irqaction sh73a0_irq_pin_cascade[32];
365 366
367#define PINTER0 0xe69000a0
368#define PINTER1 0xe69000a4
369#define PINTRR0 0xe69000d0
370#define PINTRR1 0xe69000d4
371
372#define PINT0A_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT0_IRQ(irq))
373#define PINT0B_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT0_IRQ(irq + 8))
374#define PINT0C_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT0_IRQ(irq + 16))
375#define PINT0D_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT0_IRQ(irq + 24))
376#define PINT1E_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT1_IRQ(irq))
377
378INTC_PINT(intc_pint0, PINTER0, 0xe69000b0, "sh73a0-pint0", \
379 INTC_PINT_E(A), INTC_PINT_E(B), INTC_PINT_E(C), INTC_PINT_E(D), \
380 INTC_PINT_V(A, PINT0A_IRQ), INTC_PINT_V(B, PINT0B_IRQ), \
381 INTC_PINT_V(C, PINT0C_IRQ), INTC_PINT_V(D, PINT0D_IRQ), \
382 INTC_PINT_E(A), INTC_PINT_E(B), INTC_PINT_E(C), INTC_PINT_E(D), \
383 INTC_PINT_E(A), INTC_PINT_E(B), INTC_PINT_E(C), INTC_PINT_E(D));
384
385INTC_PINT(intc_pint1, PINTER1, 0xe69000c0, "sh73a0-pint1", \
386 INTC_PINT_E(E), INTC_PINT_E_EMPTY, INTC_PINT_E_EMPTY, INTC_PINT_E_EMPTY, \
387 INTC_PINT_V(E, PINT1E_IRQ), INTC_PINT_V_NONE, \
388 INTC_PINT_V_NONE, INTC_PINT_V_NONE, \
389 INTC_PINT_E_NONE, INTC_PINT_E_NONE, INTC_PINT_E_NONE, INTC_PINT_E(E), \
390 INTC_PINT_E(E), INTC_PINT_E_NONE, INTC_PINT_E_NONE, INTC_PINT_E_NONE);
391
392static struct irqaction sh73a0_pint0_cascade;
393static struct irqaction sh73a0_pint1_cascade;
394
395static void pint_demux(unsigned long rr, unsigned long er, int base_irq)
396{
397 unsigned long value = ioread32(rr) & ioread32(er);
398 int k;
399
400 for (k = 0; k < 32; k++) {
401 if (value & (1 << (31 - k))) {
402 generic_handle_irq(base_irq + k);
403 iowrite32(~(1 << (31 - k)), rr);
404 }
405 }
406}
407
408static irqreturn_t sh73a0_pint0_demux(int irq, void *dev_id)
409{
410 pint_demux(PINTRR0, PINTER0, SH73A0_PINT0_IRQ(0));
411 return IRQ_HANDLED;
412}
413
414static irqreturn_t sh73a0_pint1_demux(int irq, void *dev_id)
415{
416 pint_demux(PINTRR1, PINTER1, SH73A0_PINT1_IRQ(0));
417 return IRQ_HANDLED;
418}
419
366void __init sh73a0_init_irq(void) 420void __init sh73a0_init_irq(void)
367{ 421{
368 void __iomem *gic_dist_base = __io(0xf0001000); 422 void __iomem *gic_dist_base = __io(0xf0001000);
@@ -375,6 +429,8 @@ void __init sh73a0_init_irq(void)
375 429
376 register_intc_controller(&intcs_desc); 430 register_intc_controller(&intcs_desc);
377 register_intc_controller(&intca_irq_pins_desc); 431 register_intc_controller(&intca_irq_pins_desc);
432 register_intc_controller(&intc_pint0_desc);
433 register_intc_controller(&intc_pint1_desc);
378 434
379 /* demux using INTEVTSA */ 435 /* demux using INTEVTSA */
380 sh73a0_intcs_cascade.name = "INTCS cascade"; 436 sh73a0_intcs_cascade.name = "INTCS cascade";
@@ -393,4 +449,13 @@ void __init sh73a0_init_irq(void)
393 handle_level_irq, "level"); 449 handle_level_irq, "level");
394 set_irq_flags(n, IRQF_VALID); /* yuck */ 450 set_irq_flags(n, IRQF_VALID); /* yuck */
395 } 451 }
452
453 /* PINT pins are sanely tied to the GIC as SPI */
454 sh73a0_pint0_cascade.name = "PINT0 cascade";
455 sh73a0_pint0_cascade.handler = sh73a0_pint0_demux;
456 setup_irq(gic_spi(33), &sh73a0_pint0_cascade);
457
458 sh73a0_pint1_cascade.name = "PINT1 cascade";
459 sh73a0_pint1_cascade.handler = sh73a0_pint1_demux;
460 setup_irq(gic_spi(34), &sh73a0_pint1_cascade);
396} 461}