1 /* 2 * linux/arch/m68k/kernel/ints.c -- Linux/m68k general interrupt handling code 3 * 4 * This file is subject to the terms and conditions of the GNU General Public 5 * License. See the file COPYING in the main directory of this archive 6 * for more details. 7 * 8 * 07/03/96: Timer initialization, and thus mach_sched_init(), 9 * removed from request_irq() and moved to init_time(). 10 * We should therefore consider renaming our add_isr() and 11 * remove_isr() to request_irq() and free_irq() 12 * respectively, so they are compliant with the other 13 * architectures. /Jes 14 * 11/07/96: Changed all add_/remove_isr() to request_/free_irq() calls. 15 * Removed irq list support, if any machine needs an irq server 16 * it must implement this itself (as it's already done), instead 17 * only default handler are used with mach_default_handler. 18 * request_irq got some flags different from other architectures: 19 * - IRQ_FLG_REPLACE : Replace an existing handler (the default one 20 * can be replaced without this flag) 21 * - IRQ_FLG_LOCK : handler can't be replaced 22 * There are other machine depending flags, see there 23 * If you want to replace a default handler you should know what 24 * you're doing, since it might handle different other irq sources 25 * which must be served /Roman Zippel 26 */ 27 28 #include <linux/module.h> 29 #include <linux/types.h> 30 #include <linux/sched.h> 31 #include <linux/kernel_stat.h> 32 #include <linux/errno.h> 33 #include <linux/init.h> 34 35 #include <asm/setup.h> 36 #include <asm/system.h> 37 #include <asm/irq.h> 38 #include <asm/traps.h> 39 #include <asm/page.h> 40 #include <asm/machdep.h> 41 #include <asm/cacheflush.h> 42 #include <asm/irq_regs.h> 43 44 #ifdef CONFIG_Q40 45 #include <asm/q40ints.h> 46 #endif 47 48 extern u32 auto_irqhandler_fixup[]; 49 extern u32 user_irqhandler_fixup[]; 50 extern u16 user_irqvec_fixup[]; 51 52 /* table for system interrupt handlers */ 53 static struct irq_node *irq_list[NR_IRQS]; 54 static struct irq_controller *irq_controller[NR_IRQS]; 55 static int irq_depth[NR_IRQS]; 56 57 static int m68k_first_user_vec; 58 59 static struct irq_controller auto_irq_controller = { 60 .name = "auto", 61 .lock = SPIN_LOCK_UNLOCKED, 62 .startup = m68k_irq_startup, 63 .shutdown = m68k_irq_shutdown, 64 }; 65 66 static struct irq_controller user_irq_controller = { 67 .name = "user", 68 .lock = SPIN_LOCK_UNLOCKED, 69 .startup = m68k_irq_startup, 70 .shutdown = m68k_irq_shutdown, 71 }; 72 73 #define NUM_IRQ_NODES 100 74 static irq_node_t nodes[NUM_IRQ_NODES]; 75 76 /* 77 * void init_IRQ(void) 78 * 79 * Parameters: None 80 * 81 * Returns: Nothing 82 * 83 * This function should be called during kernel startup to initialize 84 * the IRQ handling routines. 85 */ 86 87 void __init init_IRQ(void) 88 { 89 int i; 90 91 /* assembly irq entry code relies on this... */ 92 if (HARDIRQ_MASK != 0x00ff0000) { 93 extern void hardirq_mask_is_broken(void); 94 hardirq_mask_is_broken(); 95 } 96 97 for (i = IRQ_AUTO_1; i <= IRQ_AUTO_7; i++) 98 irq_controller[i] = &auto_irq_controller; 99 100 mach_init_IRQ(); 101 } 102 103 /** 104 * m68k_setup_auto_interrupt 105 * @handler: called from auto vector interrupts 106 * 107 * setup the handler to be called from auto vector interrupts instead of the 108 * standard __m68k_handle_int(), it will be called with irq numbers in the range 109 * from IRQ_AUTO_1 - IRQ_AUTO_7. 110 */ 111 void __init m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_regs *)) 112 { 113 if (handler) 114 *auto_irqhandler_fixup = (u32)handler; 115 flush_icache(); 116 } 117 118 /** 119 * m68k_setup_user_interrupt 120 * @vec: first user vector interrupt to handle 121 * @cnt: number of active user vector interrupts 122 * @handler: called from user vector interrupts 123 * 124 * setup user vector interrupts, this includes activating the specified range 125 * of interrupts, only then these interrupts can be requested (note: this is 126 * different from auto vector interrupts). An optional handler can be installed 127 * to be called instead of the default __m68k_handle_int(), it will be called 128 * with irq numbers starting from IRQ_USER. 129 */ 130 void __init m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt, 131 void (*handler)(unsigned int, struct pt_regs *)) 132 { 133 int i; 134 135 BUG_ON(IRQ_USER + cnt >= NR_IRQS); 136 m68k_first_user_vec = vec; 137 for (i = 0; i < cnt; i++) 138 irq_controller[IRQ_USER + i] = &user_irq_controller; 139 *user_irqvec_fixup = vec - IRQ_USER; 140 if (handler) 141 *user_irqhandler_fixup = (u32)handler; 142 flush_icache(); 143 } 144 145 /** 146 * m68k_setup_irq_controller 147 * @contr: irq controller which controls specified irq 148 * @irq: first irq to be managed by the controller 149 * 150 * Change the controller for the specified range of irq, which will be used to 151 * manage these irq. auto/user irq already have a default controller, which can 152 * be changed as well, but the controller probably should use m68k_irq_startup/ 153 * m68k_irq_shutdown. 154 */ 155 void m68k_setup_irq_controller(struct irq_controller *contr, unsigned int irq, 156 unsigned int cnt) 157 { 158 int i; 159 160 for (i = 0; i < cnt; i++) 161 irq_controller[irq + i] = contr; 162 } 163 164 irq_node_t *new_irq_node(void) 165 { 166 irq_node_t *node; 167 short i; 168 169 for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--) { 170 if (!node->handler) { 171 memset(node, 0, sizeof(*node)); 172 return node; 173 } 174 } 175 176 printk ("new_irq_node: out of nodes\n"); 177 return NULL; 178 } 179 180 int setup_irq(unsigned int irq, struct irq_node *node) 181 { 182 struct irq_controller *contr; 183 struct irq_node **prev; 184 unsigned long flags; 185 186 if (irq >= NR_IRQS || !(contr = irq_controller[irq])) { 187 printk("%s: Incorrect IRQ %d from %s\n", 188 __FUNCTION__, irq, node->devname); 189 return -ENXIO; 190 } 191 192 spin_lock_irqsave(&contr->lock, flags); 193 194 prev = irq_list + irq; 195 if (*prev) { 196 /* Can't share interrupts unless both agree to */ 197 if (!((*prev)->flags & node->flags & IRQF_SHARED)) { 198 spin_unlock_irqrestore(&contr->lock, flags); 199 return -EBUSY; 200 } 201 while (*prev) 202 prev = &(*prev)->next; 203 } 204 205 if (!irq_list[irq]) { 206 if (contr->startup) 207 contr->startup(irq); 208 else 209 contr->enable(irq); 210 } 211 node->next = NULL; 212 *prev = node; 213 214 spin_unlock_irqrestore(&contr->lock, flags); 215 216 return 0; 217 } 218 219 int request_irq(unsigned int irq, 220 irq_handler_t handler, 221 unsigned long flags, const char *devname, void *dev_id) 222 { 223 struct irq_node *node; 224 int res; 225 226 node = new_irq_node(); 227 if (!node) 228 return -ENOMEM; 229 230 node->handler = handler; 231 node->flags = flags; 232 node->dev_id = dev_id; 233 node->devname = devname; 234 235 res = setup_irq(irq, node); 236 if (res) 237 node->handler = NULL; 238 239 return res; 240 } 241 242 EXPORT_SYMBOL(request_irq); 243 244 void free_irq(unsigned int irq, void *dev_id) 245 { 246 struct irq_controller *contr; 247 struct irq_node **p, *node; 248 unsigned long flags; 249 250 if (irq >= NR_IRQS || !(contr = irq_controller[irq])) { 251 printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq); 252 return; 253 } 254 255 spin_lock_irqsave(&contr->lock, flags); 256 257 p = irq_list + irq; 258 while ((node = *p)) { 259 if (node->dev_id == dev_id) 260 break; 261 p = &node->next; 262 } 263 264 if (node) { 265 *p = node->next; 266 node->handler = NULL; 267 } else 268 printk("%s: Removing probably wrong IRQ %d\n", 269 __FUNCTION__, irq); 270 271 if (!irq_list[irq]) { 272 if (contr->shutdown) 273 contr->shutdown(irq); 274 else 275 contr->disable(irq); 276 } 277 278 spin_unlock_irqrestore(&contr->lock, flags); 279 } 280 281 EXPORT_SYMBOL(free_irq); 282 283 void enable_irq(unsigned int irq) 284 { 285 struct irq_controller *contr; 286 unsigned long flags; 287 288 if (irq >= NR_IRQS || !(contr = irq_controller[irq])) { 289 printk("%s: Incorrect IRQ %d\n", 290 __FUNCTION__, irq); 291 return; 292 } 293 294 spin_lock_irqsave(&contr->lock, flags); 295 if (irq_depth[irq]) { 296 if (!--irq_depth[irq]) { 297 if (contr->enable) 298 contr->enable(irq); 299 } 300 } else 301 WARN_ON(1); 302 spin_unlock_irqrestore(&contr->lock, flags); 303 } 304 305 EXPORT_SYMBOL(enable_irq); 306 307 void disable_irq(unsigned int irq) 308 { 309 struct irq_controller *contr; 310 unsigned long flags; 311 312 if (irq >= NR_IRQS || !(contr = irq_controller[irq])) { 313 printk("%s: Incorrect IRQ %d\n", 314 __FUNCTION__, irq); 315 return; 316 } 317 318 spin_lock_irqsave(&contr->lock, flags); 319 if (!irq_depth[irq]++) { 320 if (contr->disable) 321 contr->disable(irq); 322 } 323 spin_unlock_irqrestore(&contr->lock, flags); 324 } 325 326 EXPORT_SYMBOL(disable_irq); 327 328 int m68k_irq_startup(unsigned int irq) 329 { 330 if (irq <= IRQ_AUTO_7) 331 vectors[VEC_SPUR + irq] = auto_inthandler; 332 else 333 vectors[m68k_first_user_vec + irq - IRQ_USER] = user_inthandler; 334 return 0; 335 } 336 337 void m68k_irq_shutdown(unsigned int irq) 338 { 339 if (irq <= IRQ_AUTO_7) 340 vectors[VEC_SPUR + irq] = bad_inthandler; 341 else 342 vectors[m68k_first_user_vec + irq - IRQ_USER] = bad_inthandler; 343 } 344 345 346 /* 347 * Do we need these probe functions on the m68k? 348 * 349 * ... may be useful with ISA devices 350 */ 351 unsigned long probe_irq_on (void) 352 { 353 #ifdef CONFIG_Q40 354 if (MACH_IS_Q40) 355 return q40_probe_irq_on(); 356 #endif 357 return 0; 358 } 359 360 EXPORT_SYMBOL(probe_irq_on); 361 362 int probe_irq_off (unsigned long irqs) 363 { 364 #ifdef CONFIG_Q40 365 if (MACH_IS_Q40) 366 return q40_probe_irq_off(irqs); 367 #endif 368 return 0; 369 } 370 371 EXPORT_SYMBOL(probe_irq_off); 372 373 unsigned int irq_canonicalize(unsigned int irq) 374 { 375 #ifdef CONFIG_Q40 376 if (MACH_IS_Q40 && irq == 11) 377 irq = 10; 378 #endif 379 return irq; 380 } 381 382 EXPORT_SYMBOL(irq_canonicalize); 383 384 asmlinkage void m68k_handle_int(unsigned int irq) 385 { 386 struct irq_node *node; 387 kstat_cpu(0).irqs[irq]++; 388 node = irq_list[irq]; 389 do { 390 node->handler(irq, node->dev_id); 391 node = node->next; 392 } while (node); 393 } 394 395 asmlinkage void __m68k_handle_int(unsigned int irq, struct pt_regs *regs) 396 { 397 struct pt_regs *old_regs; 398 old_regs = set_irq_regs(regs); 399 m68k_handle_int(irq); 400 set_irq_regs(old_regs); 401 } 402 403 asmlinkage void handle_badint(struct pt_regs *regs) 404 { 405 kstat_cpu(0).irqs[0]++; 406 printk("unexpected interrupt from %u\n", regs->vector); 407 } 408 409 int show_interrupts(struct seq_file *p, void *v) 410 { 411 struct irq_controller *contr; 412 struct irq_node *node; 413 int i = *(loff_t *) v; 414 415 /* autovector interrupts */ 416 if (irq_list[i]) { 417 contr = irq_controller[i]; 418 node = irq_list[i]; 419 seq_printf(p, "%-8s %3u: %10u %s", contr->name, i, kstat_cpu(0).irqs[i], node->devname); 420 while ((node = node->next)) 421 seq_printf(p, ", %s", node->devname); 422 seq_puts(p, "\n"); 423 } 424 return 0; 425 } 426 427 void init_irq_proc(void) 428 { 429 /* Insert /proc/irq driver here */ 430 } 431 432