1 /* 2 * Galileo Technology chip interrupt handler 3 * 4 * Modified by RidgeRun, Inc. 5 */ 6 #include <linux/module.h> 7 #include <linux/interrupt.h> 8 #include <linux/kernel.h> 9 #include <asm/ptrace.h> 10 #include <linux/config.h> 11 #include <linux/sched.h> 12 #include <linux/kernel_stat.h> 13 #include <asm/io.h> 14 #include <asm/gt64120.h> 15 #include <asm/galileo-boards/ev64120.h> 16 #include <asm/galileo-boards/ev64120int.h> 17 18 /* 19 * These are interrupt handlers for the GT on-chip interrupts. They all come 20 * in to the MIPS on a single interrupt line, and have to be handled and ack'ed 21 * differently than other MIPS interrupts. 22 */ 23 24 #if CURRENTLY_UNUSED 25 26 struct tq_struct irq_handlers[MAX_CAUSE_REGS][MAX_CAUSE_REG_WIDTH]; 27 void hook_irq_handler(int int_cause, int bit_num, void *isr_ptr); 28 29 /* 30 * hook_irq_handler 31 * 32 * Hooks IRQ handler to the system. When the system is interrupted 33 * the interrupt service routine is called. 34 * 35 * Inputs : 36 * int_cause - The interrupt cause number. In EVB64120 two parameters 37 * are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH. 38 * bit_num - Indicates which bit number in the cause register 39 * isr_ptr - Pointer to the interrupt service routine 40 * 41 * Outputs : 42 */ 43 void hook_irq_handler(int int_cause, int bit_num, void *isr_ptr) 44 { 45 irq_handlers[int_cause][bit_num].routine = isr_ptr; 46 } 47 48 49 /* 50 * enable_galileo_irq 51 * 52 * Enables the IRQ on Galileo Chip 53 * 54 * Inputs : 55 * int_cause - The interrupt cause number. In EVB64120 two parameters 56 * are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH. 57 * bit_num - Indicates which bit number in the cause register 58 * 59 * Outputs : 60 * 1 if succesful, 0 if failure 61 */ 62 int enable_galileo_irq(int int_cause, int bit_num) 63 { 64 if (int_cause == INT_CAUSE_MAIN) 65 SET_REG_BITS(CPU_INTERRUPT_MASK_REGISTER, (1 << bit_num)); 66 else if (int_cause == INT_CAUSE_HIGH) 67 SET_REG_BITS(CPU_HIGH_INTERRUPT_MASK_REGISTER, 68 (1 << bit_num)); 69 else 70 return 0; 71 return 1; 72 } 73 74 /* 75 * disable_galileo_irq 76 * 77 * Disables the IRQ on Galileo Chip 78 * 79 * Inputs : 80 * int_cause - The interrupt cause number. In EVB64120 two parameters 81 * are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH. 82 * bit_num - Indicates which bit number in the cause register 83 * 84 * Outputs : 85 * 1 if succesful, 0 if failure 86 */ 87 int disable_galileo_irq(int int_cause, int bit_num) 88 { 89 if (int_cause == INT_CAUSE_MAIN) 90 RESET_REG_BITS(CPU_INTERRUPT_MASK_REGISTER, 91 (1 << bit_num)); 92 else if (int_cause == INT_CAUSE_HIGH) 93 RESET_REG_BITS(CPU_HIGH_INTERRUPT_MASK_REGISTER, 94 (1 << bit_num)); 95 else 96 return 0; 97 return 1; 98 } 99 100 #endif /* UNUSED */ 101 102 /* 103 * galileo_irq - 104 * 105 * Interrupt handler for interrupts coming from the Galileo chip. 106 * It could be timer interrupt, built in ethernet ports etc... 107 * 108 * Inputs : 109 * 110 * Outputs : 111 * 112 */ 113 static void galileo_irq(int irq, void *dev_id, struct pt_regs *regs) 114 { 115 unsigned int irq_src, int_high_src, irq_src_mask, 116 int_high_src_mask; 117 int handled; 118 unsigned int count; 119 static int counter = 0; 120 121 GT_READ(GT_INTRCAUSE_OFS, &irq_src); 122 GT_READ(GT_INTRMASK_OFS, &irq_src_mask); 123 GT_READ(GT_HINTRCAUSE_OFS, &int_high_src); 124 GT_READ(GT_HINTRMASK_OFS, &int_high_src_mask); 125 irq_src = irq_src & irq_src_mask; 126 int_high_src = int_high_src & int_high_src_mask; 127 128 handled = 0; 129 130 /* Execute all interrupt handlers */ 131 /* Check for timer interrupt */ 132 if (irq_src & 0x00000800) { 133 handled = 1; 134 irq_src &= ~0x00000800; 135 // RESET_REG_BITS (INTERRUPT_CAUSE_REGISTER,BIT8); 136 do_timer(regs); 137 } 138 139 if (irq_src) { 140 printk(KERN_INFO 141 "Other Galileo interrupt received irq_src %x\n", 142 irq_src); 143 #if CURRENTLY_UNUSED 144 for (count = 0; count < MAX_CAUSE_REG_WIDTH; count++) { 145 if (irq_src & (1 << count)) { 146 if (irq_handlers[INT_CAUSE_MAIN][count]. 147 routine) { 148 queue_task(&irq_handlers 149 [INT_CAUSE_MAIN][count], 150 &tq_immediate); 151 mark_bh(IMMEDIATE_BH); 152 handled = 1; 153 } 154 } 155 } 156 #endif /* UNUSED */ 157 } 158 GT_WRITE(GT_INTRCAUSE_OFS, 0); 159 GT_WRITE(GT_HINTRCAUSE_OFS, 0); 160 161 #undef GALILEO_I2O 162 #ifdef GALILEO_I2O 163 /* 164 Future I2O support. We currently attach I2O interrupt handlers to the 165 Galileo interrupt (int 4) and handle them in do_IRQ. 166 */ 167 if (isInBoundDoorBellInterruptSet()) { 168 printk(KERN_INFO "I2O doorbell interrupt received.\n"); 169 handled = 1; 170 } 171 172 if (isInBoundPostQueueInterruptSet()) { 173 printk(KERN_INFO "I2O Queue interrupt received.\n"); 174 handled = 1; 175 } 176 177 /* 178 This normally would be outside of the ifdef, but since 179 we're handling I2O outside of this handler, this 180 printk shows up every time we get a valid I2O 181 interrupt. So turn this off for now. 182 */ 183 if (handled == 0) { 184 if (counter < 50) { 185 printk("Spurious Galileo interrupt...\n"); 186 counter++; 187 } 188 } 189 #endif 190 } 191 192 /* 193 * galileo_time_init - 194 * 195 * Initializes timer using galileo's built in timer. 196 * 197 * 198 * Inputs : 199 * irq - number of irq to be used by the timer 200 * 201 * Outpus : 202 * 203 */ 204 #ifdef CONFIG_SYSCLK_100 205 #define Sys_clock (100 * 1000000) // 100 MHz 206 #endif 207 #ifdef CONFIG_SYSCLK_83 208 #define Sys_clock (83.333 * 1000000) // 83.333 MHz 209 #endif 210 #ifdef CONFIG_SYSCLK_75 211 #define Sys_clock (75 * 1000000) // 75 MHz 212 #endif 213 214 /* 215 * This will ignore the standard MIPS timer interrupt handler that is passed 216 * in as *irq (=irq0 in ../kernel/time.c). We will do our own timer interrupt 217 * handling. 218 */ 219 void galileo_time_init(struct irqaction *irq) 220 { 221 extern irq_desc_t irq_desc[NR_IRQS]; 222 static struct irqaction timer; 223 224 /* Disable timer first */ 225 GT_WRITE(GT_TC_CONTROL_OFS, 0); 226 /* Load timer value for 100 Hz */ 227 GT_WRITE(GT_TC3_OFS, Sys_clock / 100); 228 229 /* 230 * Create the IRQ structure entry for the timer. Since we're too early 231 * in the boot process to use the "request_irq()" call, we'll hard-code 232 * the values to the correct interrupt line. 233 */ 234 timer.handler = &galileo_irq; 235 timer.flags = SA_SHIRQ; 236 timer.name = "timer"; 237 timer.dev_id = NULL; 238 timer.next = NULL; 239 timer.mask = 0; 240 irq_desc[TIMER].action = &timer; 241 242 /* Enable timer ints */ 243 GT_WRITE(GT_TC_CONTROL_OFS, 0xc0); 244 /* clear Cause register first */ 245 GT_WRITE(GT_INTRCAUSE_OFS, 0x0); 246 /* Unmask timer int */ 247 GT_WRITE(GT_INTRMASK_OFS, 0x800); 248 /* Clear High int register */ 249 GT_WRITE(GT_HINTRCAUSE_OFS, 0x0); 250 /* Mask All interrupts at High cause interrupt */ 251 GT_WRITE(GT_HINTRMASK_OFS, 0x0); 252 253 } 254 255 void galileo_irq_init(void) 256 { 257 #if CURRENTLY_UNUSED 258 int i, j; 259 260 /* Reset irq handlers pointers to NULL */ 261 for (i = 0; i < MAX_CAUSE_REGS; i++) { 262 for (j = 0; j < MAX_CAUSE_REG_WIDTH; j++) { 263 irq_handlers[i][j].next = NULL; 264 irq_handlers[i][j].sync = 0; 265 irq_handlers[i][j].routine = NULL; 266 irq_handlers[i][j].data = NULL; 267 } 268 } 269 #endif 270 } 271
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.