| /* |
| * linux/arch/h8300/platform/h8s/ints_h8s.c |
| * Interrupt handling CPU variants |
| * |
| * Yoshinori Sato <ysato@users.sourceforge.jp> |
| * |
| */ |
| |
| #include <linux/init.h> |
| #include <linux/errno.h> |
| #include <linux/kernel.h> |
| |
| #include <asm/ptrace.h> |
| #include <asm/traps.h> |
| #include <asm/irq.h> |
| #include <asm/io.h> |
| #include <asm/gpio-internal.h> |
| #include <asm/regs267x.h> |
| |
| /* saved vector list */ |
| const int __initdata h8300_saved_vectors[]={ |
| #if defined(CONFIG_GDB_DEBUG) |
| TRACE_VEC, |
| TRAP3_VEC, |
| #endif |
| -1 |
| }; |
| |
| /* trap entry table */ |
| const H8300_VECTOR __initdata h8300_trap_table[] = { |
| 0,0,0,0,0, |
| trace_break, /* TRACE */ |
| 0,0, |
| system_call, /* TRAPA #0 */ |
| 0,0,0,0,0,0,0 |
| }; |
| |
| /* IRQ pin assignment */ |
| struct irq_pins { |
| unsigned char port_no; |
| unsigned char bit_no; |
| } __attribute__((aligned(1),packed)); |
| /* ISTR = 0 */ |
| static const struct irq_pins irq_assign_table0[16]={ |
| {H8300_GPIO_P5,H8300_GPIO_B0},{H8300_GPIO_P5,H8300_GPIO_B1}, |
| {H8300_GPIO_P5,H8300_GPIO_B2},{H8300_GPIO_P5,H8300_GPIO_B3}, |
| {H8300_GPIO_P5,H8300_GPIO_B4},{H8300_GPIO_P5,H8300_GPIO_B5}, |
| {H8300_GPIO_P5,H8300_GPIO_B6},{H8300_GPIO_P5,H8300_GPIO_B7}, |
| {H8300_GPIO_P6,H8300_GPIO_B0},{H8300_GPIO_P6,H8300_GPIO_B1}, |
| {H8300_GPIO_P6,H8300_GPIO_B2},{H8300_GPIO_P6,H8300_GPIO_B3}, |
| {H8300_GPIO_P6,H8300_GPIO_B4},{H8300_GPIO_P6,H8300_GPIO_B5}, |
| {H8300_GPIO_PF,H8300_GPIO_B1},{H8300_GPIO_PF,H8300_GPIO_B2}, |
| }; |
| /* ISTR = 1 */ |
| static const struct irq_pins irq_assign_table1[16]={ |
| {H8300_GPIO_P8,H8300_GPIO_B0},{H8300_GPIO_P8,H8300_GPIO_B1}, |
| {H8300_GPIO_P8,H8300_GPIO_B2},{H8300_GPIO_P8,H8300_GPIO_B3}, |
| {H8300_GPIO_P8,H8300_GPIO_B4},{H8300_GPIO_P8,H8300_GPIO_B5}, |
| {H8300_GPIO_PH,H8300_GPIO_B2},{H8300_GPIO_PH,H8300_GPIO_B3}, |
| {H8300_GPIO_P2,H8300_GPIO_B0},{H8300_GPIO_P2,H8300_GPIO_B1}, |
| {H8300_GPIO_P2,H8300_GPIO_B2},{H8300_GPIO_P2,H8300_GPIO_B3}, |
| {H8300_GPIO_P2,H8300_GPIO_B4},{H8300_GPIO_P2,H8300_GPIO_B5}, |
| {H8300_GPIO_P2,H8300_GPIO_B6},{H8300_GPIO_P2,H8300_GPIO_B7}, |
| }; |
| |
| /* IRQ to GPIO pin translation */ |
| #define IRQ_GPIO_MAP(irqbit,irq,port,bit) \ |
| do { \ |
| if (*(volatile unsigned short *)ITSR & irqbit) { \ |
| port = irq_assign_table1[irq - EXT_IRQ0].port_no; \ |
| bit = irq_assign_table1[irq - EXT_IRQ0].bit_no; \ |
| } else { \ |
| port = irq_assign_table0[irq - EXT_IRQ0].port_no; \ |
| bit = irq_assign_table0[irq - EXT_IRQ0].bit_no; \ |
| } \ |
| } while(0) |
| |
| int h8300_enable_irq_pin(unsigned int irq) |
| { |
| if (irq >= EXT_IRQ0 && irq <= EXT_IRQ15) { |
| unsigned short ptn = 1 << (irq - EXT_IRQ0); |
| unsigned int port_no,bit_no; |
| IRQ_GPIO_MAP(ptn, irq, port_no, bit_no); |
| if (H8300_GPIO_RESERVE(port_no, bit_no) == 0) |
| return -EBUSY; /* pin already use */ |
| H8300_GPIO_DDR(port_no, bit_no, H8300_GPIO_INPUT); |
| *(volatile unsigned short *)ISR &= ~ptn; /* ISR clear */ |
| } |
| |
| return 0; |
| } |
| |
| void h8300_disable_irq_pin(unsigned int irq) |
| { |
| if (irq >= EXT_IRQ0 && irq <= EXT_IRQ15) { |
| /* disable interrupt & release IRQ pin */ |
| unsigned short ptn = 1 << (irq - EXT_IRQ0); |
| unsigned short port_no,bit_no; |
| *(volatile unsigned short *)ISR &= ~ptn; |
| *(volatile unsigned short *)IER &= ~ptn; |
| IRQ_GPIO_MAP(ptn, irq, port_no, bit_no); |
| H8300_GPIO_FREE(port_no, bit_no); |
| } |
| } |