diff options
author | Yoshinori Sato <ysato@users.sourceforge.jp> | 2015-05-11 02:36:51 +0900 |
---|---|---|
committer | Yoshinori Sato <ysato@users.sourceforge.jp> | 2015-06-23 13:35:50 +0900 |
commit | 883251dd163c551abcb1031803e20e3ccd1f988c (patch) | |
tree | af689584f4ee082cf973df93ca7b2ce216429c19 /arch/h8300/kernel/irq.c | |
parent | 88d1739f54200cecd7b25c9e53ede90309b59526 (diff) | |
download | linux-883251dd163c551abcb1031803e20e3ccd1f988c.tar.bz2 |
h8300: Interrupt and exceptions
Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
Diffstat (limited to 'arch/h8300/kernel/irq.c')
-rw-r--r-- | arch/h8300/kernel/irq.c | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/arch/h8300/kernel/irq.c b/arch/h8300/kernel/irq.c new file mode 100644 index 000000000000..da79f9521699 --- /dev/null +++ b/arch/h8300/kernel/irq.c @@ -0,0 +1,97 @@ +/* + * linux/arch/h8300/kernel/irq.c + * + * Copyright 2014-2015 Yoshinori Sato <ysato@users.sourceforge.jp> + */ + +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/irqdomain.h> +#include <linux/of_irq.h> +#include <asm/traps.h> + +#ifdef CONFIG_RAMKERNEL +typedef void (*h8300_vector)(void); + +static const h8300_vector __initconst trap_table[] = { + 0, 0, 0, 0, + _trace_break, + 0, 0, + _nmi, + _system_call, + 0, 0, + _trace_break, +}; + +static unsigned long __init *get_vector_address(void) +{ + unsigned long *rom_vector = CPU_VECTOR; + unsigned long base, tmp; + int vec_no; + + base = rom_vector[EXT_IRQ0] & ADDR_MASK; + + /* check romvector format */ + for (vec_no = EXT_IRQ0 + 1; vec_no <= EXT_IRQ0+EXT_IRQS; vec_no++) { + if ((base+(vec_no - EXT_IRQ0)*4) != + (rom_vector[vec_no] & ADDR_MASK)) + return NULL; + } + + /* ramvector base address */ + base -= EXT_IRQ0*4; + + /* writerble? */ + tmp = ~(*(volatile unsigned long *)base); + (*(volatile unsigned long *)base) = tmp; + if ((*(volatile unsigned long *)base) != tmp) + return NULL; + return (unsigned long *)base; +} + +static void __init setup_vector(void) +{ + int i; + unsigned long *ramvec, *ramvec_p; + const h8300_vector *trap_entry; + + ramvec = get_vector_address(); + if (ramvec == NULL) + panic("interrupt vector serup failed."); + else + pr_debug("virtual vector at 0x%p\n", ramvec); + + /* create redirect table */ + ramvec_p = ramvec; + trap_entry = trap_table; + for (i = 0; i < NR_IRQS; i++) { + if (i < 12) { + if (*trap_entry) + *ramvec_p = VECTOR(*trap_entry); + ramvec_p++; + trap_entry++; + } else + *ramvec_p++ = REDIRECT(_interrupt_entry); + } + _interrupt_redirect_table = ramvec; +} +#else +void setup_vector(void) +{ + /* noting do */ +} +#endif + +void __init init_IRQ(void) +{ + setup_vector(); + irqchip_init(); +} + +asmlinkage void do_IRQ(int irq) +{ + irq_enter(); + generic_handle_irq(irq); + irq_exit(); +} |