ARM: mach-shmobile: Run-time IRQ handler for INTCA
authorMagnus Damm <damm@opensource.se>
Tue, 28 Dec 2010 08:27:01 +0000 (08:27 +0000)
committerPaul Mundt <lethal@linux-sh.org>
Fri, 7 Jan 2011 01:42:50 +0000 (10:42 +0900)
Break-out INTC specific IRQ demux code from the file
entry-macro-intc.S and register during run-time.

Covers sh7367, sh7377 and sh7372.

Signed-off-by: Magnus Damm <damm@opensource.se>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
arch/arm/mach-shmobile/Makefile
arch/arm/mach-shmobile/board-ap4evb.c
arch/arm/mach-shmobile/board-g3evm.c
arch/arm/mach-shmobile/board-g4evm.c
arch/arm/mach-shmobile/board-mackerel.c
arch/arm/mach-shmobile/entry-intc.S [new file with mode: 0644]
arch/arm/mach-shmobile/include/mach/common.h

index ab100e4bddd603bee92556425da917ca32ca34fe..e385ef03d5bd8b08ac1fddbcf82f6a8661682b2b 100644 (file)
@@ -18,6 +18,11 @@ pfc-$(CONFIG_ARCH_SH7377)    += pfc-sh7377.o
 pfc-$(CONFIG_ARCH_SH7372)      += pfc-sh7372.o
 pfc-$(CONFIG_ARCH_SH73A0)      += pfc-sh73a0.o
 
+# IRQ objects
+obj-$(CONFIG_ARCH_SH7367)      += entry-intc.o
+obj-$(CONFIG_ARCH_SH7377)      += entry-intc.o
+obj-$(CONFIG_ARCH_SH7372)      += entry-intc.o
+
 # Board objects
 obj-$(CONFIG_MACH_G3EVM)       += board-g3evm.o
 obj-$(CONFIG_MACH_G4EVM)       += board-g4evm.o
index 86edc772f82a7b3549f0b7ebcad7900826c0d192..cd79d7c1ba0d9e5cf58b655dc6a7d10324575f24 100644 (file)
@@ -1361,6 +1361,7 @@ static struct sys_timer ap4evb_timer = {
 MACHINE_START(AP4EVB, "ap4evb")
        .map_io         = ap4evb_map_io,
        .init_irq       = sh7372_init_irq,
+       .handle_irq     = shmobile_handle_irq_intc,
        .init_machine   = ap4evb_init,
        .timer          = &ap4evb_timer,
 MACHINE_END
index 3b83d6320bec808d5f4259fc4308c307f7e62f2e..686b304a7708793b42084840bd900234cac82f1c 100644 (file)
@@ -367,6 +367,7 @@ static struct sys_timer g3evm_timer = {
 MACHINE_START(G3EVM, "g3evm")
        .map_io         = g3evm_map_io,
        .init_irq       = sh7367_init_irq,
+       .handle_irq     = shmobile_handle_irq_intc,
        .init_machine   = g3evm_init,
        .timer          = &g3evm_timer,
 MACHINE_END
index 5b3b582ef3f25fefd4430c071e89f42355832fb1..c13f01280b7ed85e6a5054d632129dfab85d056d 100644 (file)
@@ -394,6 +394,7 @@ static struct sys_timer g4evm_timer = {
 MACHINE_START(G4EVM, "g4evm")
        .map_io         = g4evm_map_io,
        .init_irq       = sh7377_init_irq,
+       .handle_irq     = shmobile_handle_irq_intc,
        .init_machine   = g4evm_init,
        .timer          = &g4evm_timer,
 MACHINE_END
index 6a5ce9a0dcf353eae9976a7646772c4894c72888..5bcf5c1e139910aa839cba555d92959ee79b4750 100644 (file)
@@ -1194,6 +1194,7 @@ static struct sys_timer mackerel_timer = {
 MACHINE_START(MACKEREL, "mackerel")
        .map_io         = mackerel_map_io,
        .init_irq       = sh7372_init_irq,
+       .handle_irq     = shmobile_handle_irq_intc,
        .init_machine   = mackerel_init,
        .timer          = &mackerel_timer,
 MACHINE_END
diff --git a/arch/arm/mach-shmobile/entry-intc.S b/arch/arm/mach-shmobile/entry-intc.S
new file mode 100644 (file)
index 0000000..cac0a7a
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * ARM Interrupt demux handler using INTC
+ *
+ * Copyright (C) 2010 Magnus Damm
+ * Copyright (C) 2008 Renesas Solutions Corp.
+ *
+ * This file is licensed under  the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <asm/entry-macro-multi.S>
+
+#define INTCA_BASE     0xe6980000
+#define INTFLGA_OFFS   0x00000018 /* accept pending interrupt */
+#define INTEVTA_OFFS   0x00000020 /* vector number of accepted interrupt */
+#define INTLVLA_OFFS   0x00000030 /* priority level of accepted interrupt */
+#define INTLVLB_OFFS   0x00000034 /* previous priority level */
+
+       .macro  get_irqnr_preamble, base, tmp
+       ldr     \base, =INTCA_BASE
+       .endm
+
+       .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+       /* The single INTFLGA read access below results in the following:
+        *
+        * 1. INTLVLB is updated with old priority value from INTLVLA
+        * 2. Highest priority interrupt is accepted
+        * 3. INTLVLA is updated to contain priority of accepted interrupt
+        * 4. Accepted interrupt vector is stored in INTFLGA and INTEVTA
+        */
+       ldr     \irqnr, [\base, #INTFLGA_OFFS]
+
+       /* Restore INTLVLA with the value saved in INTLVLB.
+        * This is required to support interrupt priorities properly.
+        */
+       ldrb    \tmp, [\base, #INTLVLB_OFFS]
+       strb    \tmp, [\base, #INTLVLA_OFFS]
+
+       /* Handle invalid vector number case */
+       cmp     \irqnr, #0
+       beq     1000f
+
+       /* Convert vector to irq number, same as the evt2irq() macro */
+       lsr     \irqnr, \irqnr, #0x5
+       subs    \irqnr, \irqnr, #16
+
+1000:
+       .endm
+
+       .macro  test_for_ipi, irqnr, irqstat, base, tmp
+       .endm
+
+       .macro  test_for_ltirq, irqnr, irqstat, base, tmp
+       .endm
+
+       arch_irq_handler shmobile_handle_irq_intc
index 49ac8ebdc184e8cf31576cd8f25970271a164b37..ab75183bfd76037a1438574916c36ee9fd14c738 100644 (file)
@@ -5,6 +5,7 @@ extern struct sys_timer shmobile_timer;
 extern void shmobile_setup_console(void);
 struct clk;
 extern int clk_init(void);
+extern void shmobile_handle_irq_intc(struct pt_regs *);
 
 extern void sh7367_init_irq(void);
 extern void sh7367_add_early_devices(void);