1/* 2 * linux/arch/cris/kernel/irq.c 3 * 4 * Copyright (c) 2000-2002 Axis Communications AB 5 * 6 * Authors: Bjorn Wesen (bjornw@axis.com) 7 * 8 * This file contains the interrupt vectors and some 9 * helper functions 10 * 11 */ 12 13#include <asm/irq.h> 14#include <asm/current.h> 15#include <linux/irq.h> 16#include <linux/interrupt.h> 17#include <linux/kernel.h> 18#include <linux/init.h> 19 20#define crisv10_mask_irq(irq_nr) (*R_VECT_MASK_CLR = 1 << (irq_nr)); 21#define crisv10_unmask_irq(irq_nr) (*R_VECT_MASK_SET = 1 << (irq_nr)); 22 23extern void kgdb_init(void); 24extern void breakpoint(void); 25 26/* don't use set_int_vector, it bypasses the linux interrupt handlers. it is 27 * global just so that the kernel gdb can use it. 28 */ 29 30void 31set_int_vector(int n, irqvectptr addr) 32{ 33 etrax_irv->v[n + 0x20] = (irqvectptr)addr; 34} 35 36/* the breakpoint vector is obviously not made just like the normal irq handlers 37 * but needs to contain _code_ to jump to addr. 38 * 39 * the BREAK n instruction jumps to IBR + n * 8 40 */ 41 42void 43set_break_vector(int n, irqvectptr addr) 44{ 45 unsigned short *jinstr = (unsigned short *)&etrax_irv->v[n*2]; 46 unsigned long *jaddr = (unsigned long *)(jinstr + 1); 47 48 /* if you don't know what this does, do not touch it! */ 49 50 *jinstr = 0x0d3f; 51 *jaddr = (unsigned long)addr; 52 53 /* 00000026 <clrlop+1a> 3f0d82000000 jump 0x82 */ 54} 55 56/* 57 * This builds up the IRQ handler stubs using some ugly macros in irq.h 58 * 59 * These macros create the low-level assembly IRQ routines that do all 60 * the operations that are needed. They are also written to be fast - and to 61 * disable interrupts as little as humanly possible. 62 * 63 */ 64 65/* IRQ0 and 1 are special traps */ 66void hwbreakpoint(void); 67void IRQ1_interrupt(void); 68BUILD_TIMER_IRQ(2, 0x04) /* the timer interrupt is somewhat special */ 69BUILD_IRQ(3, 0x08) 70BUILD_IRQ(4, 0x10) 71BUILD_IRQ(5, 0x20) 72BUILD_IRQ(6, 0x40) 73BUILD_IRQ(7, 0x80) 74BUILD_IRQ(8, 0x100) 75BUILD_IRQ(9, 0x200) 76BUILD_IRQ(10, 0x400) 77BUILD_IRQ(11, 0x800) 78BUILD_IRQ(12, 0x1000) 79BUILD_IRQ(13, 0x2000) 80void mmu_bus_fault(void); /* IRQ 14 is the bus fault interrupt */ 81void multiple_interrupt(void); /* IRQ 15 is the multiple IRQ interrupt */ 82BUILD_IRQ(16, 0x10000 | 0x20000) /* ethernet tx interrupt needs to block rx */ 83BUILD_IRQ(17, 0x20000 | 0x10000) /* ...and vice versa */ 84BUILD_IRQ(18, 0x40000) 85BUILD_IRQ(19, 0x80000) 86BUILD_IRQ(20, 0x100000) 87BUILD_IRQ(21, 0x200000) 88BUILD_IRQ(22, 0x400000) 89BUILD_IRQ(23, 0x800000) 90BUILD_IRQ(24, 0x1000000) 91BUILD_IRQ(25, 0x2000000) 92/* IRQ 26-30 are reserved */ 93BUILD_IRQ(31, 0x80000000) 94 95/* 96 * Pointers to the low-level handlers 97 */ 98 99static void (*interrupt[NR_IRQS])(void) = { 100 NULL, NULL, IRQ2_interrupt, IRQ3_interrupt, 101 IRQ4_interrupt, IRQ5_interrupt, IRQ6_interrupt, IRQ7_interrupt, 102 IRQ8_interrupt, IRQ9_interrupt, IRQ10_interrupt, IRQ11_interrupt, 103 IRQ12_interrupt, IRQ13_interrupt, NULL, NULL, 104 IRQ16_interrupt, IRQ17_interrupt, IRQ18_interrupt, IRQ19_interrupt, 105 IRQ20_interrupt, IRQ21_interrupt, IRQ22_interrupt, IRQ23_interrupt, 106 IRQ24_interrupt, IRQ25_interrupt, NULL, NULL, NULL, NULL, NULL, 107 IRQ31_interrupt 108}; 109 110static void enable_crisv10_irq(struct irq_data *data) 111{ 112 crisv10_unmask_irq(data->irq); 113} 114 115static void disable_crisv10_irq(struct irq_data *data) 116{ 117 crisv10_mask_irq(data->irq); 118} 119 120static struct irq_chip crisv10_irq_type = { 121 .name = "CRISv10", 122 .irq_shutdown = disable_crisv10_irq, 123 .irq_enable = enable_crisv10_irq, 124 .irq_disable = disable_crisv10_irq, 125}; 126 127void weird_irq(void); 128void system_call(void); /* from entry.S */ 129void do_sigtrap(void); /* from entry.S */ 130void gdb_handle_breakpoint(void); /* from entry.S */ 131 132extern void do_IRQ(int irq, struct pt_regs * regs); 133 134/* Handle multiple IRQs */ 135void do_multiple_IRQ(struct pt_regs* regs) 136{ 137 int bit; 138 unsigned masked; 139 unsigned mask; 140 unsigned ethmask = 0; 141 142 /* Get interrupts to mask and handle */ 143 mask = masked = *R_VECT_MASK_RD; 144 145 /* Never mask timer IRQ */ 146 mask &= ~(IO_MASK(R_VECT_MASK_RD, timer0)); 147 148 /* 149 * If either ethernet interrupt (rx or tx) is active then block 150 * the other one too. Unblock afterwards also. 151 */ 152 if (mask & 153 (IO_STATE(R_VECT_MASK_RD, dma0, active) | 154 IO_STATE(R_VECT_MASK_RD, dma1, active))) { 155 ethmask = (IO_MASK(R_VECT_MASK_RD, dma0) | 156 IO_MASK(R_VECT_MASK_RD, dma1)); 157 } 158 159 /* Block them */ 160 *R_VECT_MASK_CLR = (mask | ethmask); 161 162 /* An extra irq_enter here to prevent softIRQs to run after 163 * each do_IRQ. This will decrease the interrupt latency. 164 */ 165 irq_enter(); 166 167 /* Handle all IRQs */ 168 for (bit = 2; bit < 32; bit++) { 169 if (masked & (1 << bit)) { 170 do_IRQ(bit, regs); 171 } 172 } 173 174 /* This irq_exit() will trigger the soft IRQs. */ 175 irq_exit(); 176 177 /* Unblock the IRQs again */ 178 *R_VECT_MASK_SET = (masked | ethmask); 179} 180 181/* init_IRQ() is called by start_kernel and is responsible for fixing IRQ masks and 182 setting the irq vector table. 183*/ 184 185void __init init_IRQ(void) 186{ 187 int i; 188 189 /* clear all interrupt masks */ 190 *R_IRQ_MASK0_CLR = 0xffffffff; 191 *R_IRQ_MASK1_CLR = 0xffffffff; 192 *R_IRQ_MASK2_CLR = 0xffffffff; 193 *R_VECT_MASK_CLR = 0xffffffff; 194 195 for (i = 0; i < 256; i++) 196 etrax_irv->v[i] = weird_irq; 197 198 /* Initialize IRQ handler descriptors. */ 199 for(i = 2; i < NR_IRQS; i++) { 200 irq_set_chip_and_handler(i, &crisv10_irq_type, 201 handle_simple_irq); 202 set_int_vector(i, interrupt[i]); 203 } 204 205 /* the entries in the break vector contain actual code to be 206 executed by the associated break handler, rather than just a jump 207 address. therefore we need to setup a default breakpoint handler 208 for all breakpoints */ 209 for (i = 0; i < 16; i++) 210 set_break_vector(i, do_sigtrap); 211 212 /* except IRQ 15 which is the multiple-IRQ handler on Etrax100 */ 213 set_int_vector(15, multiple_interrupt); 214 215 /* 0 and 1 which are special breakpoint/NMI traps */ 216 set_int_vector(0, hwbreakpoint); 217 set_int_vector(1, IRQ1_interrupt); 218 219 /* and irq 14 which is the mmu bus fault handler */ 220 set_int_vector(14, mmu_bus_fault); 221 222 /* setup the system-call trap, which is reached by BREAK 13 */ 223 set_break_vector(13, system_call); 224 225 /* setup a breakpoint handler for debugging used for both user and 226 kernel mode debugging (which is why it is not inside an ifdef 227 CONFIG_ETRAX_KGDB) */ 228 set_break_vector(8, gdb_handle_breakpoint); 229 230#ifdef CONFIG_ETRAX_KGDB 231 /* setup kgdb if its enabled, and break into the debugger */ 232 kgdb_init(); 233 breakpoint(); 234#endif 235} 236