1*1da177e4SLinus Torvalds /* 2*1da177e4SLinus Torvalds * linux/arch/m68k/kernel/ints.c -- Linux/m68k general interrupt handling code 3*1da177e4SLinus Torvalds * 4*1da177e4SLinus Torvalds * This file is subject to the terms and conditions of the GNU General Public 5*1da177e4SLinus Torvalds * License. See the file COPYING in the main directory of this archive 6*1da177e4SLinus Torvalds * for more details. 7*1da177e4SLinus Torvalds * 8*1da177e4SLinus Torvalds * 07/03/96: Timer initialization, and thus mach_sched_init(), 9*1da177e4SLinus Torvalds * removed from request_irq() and moved to init_time(). 10*1da177e4SLinus Torvalds * We should therefore consider renaming our add_isr() and 11*1da177e4SLinus Torvalds * remove_isr() to request_irq() and free_irq() 12*1da177e4SLinus Torvalds * respectively, so they are compliant with the other 13*1da177e4SLinus Torvalds * architectures. /Jes 14*1da177e4SLinus Torvalds * 11/07/96: Changed all add_/remove_isr() to request_/free_irq() calls. 15*1da177e4SLinus Torvalds * Removed irq list support, if any machine needs an irq server 16*1da177e4SLinus Torvalds * it must implement this itself (as it's already done), instead 17*1da177e4SLinus Torvalds * only default handler are used with mach_default_handler. 18*1da177e4SLinus Torvalds * request_irq got some flags different from other architectures: 19*1da177e4SLinus Torvalds * - IRQ_FLG_REPLACE : Replace an existing handler (the default one 20*1da177e4SLinus Torvalds * can be replaced without this flag) 21*1da177e4SLinus Torvalds * - IRQ_FLG_LOCK : handler can't be replaced 22*1da177e4SLinus Torvalds * There are other machine depending flags, see there 23*1da177e4SLinus Torvalds * If you want to replace a default handler you should know what 24*1da177e4SLinus Torvalds * you're doing, since it might handle different other irq sources 25*1da177e4SLinus Torvalds * which must be served /Roman Zippel 26*1da177e4SLinus Torvalds */ 27*1da177e4SLinus Torvalds 28*1da177e4SLinus Torvalds #include <linux/config.h> 29*1da177e4SLinus Torvalds #include <linux/module.h> 30*1da177e4SLinus Torvalds #include <linux/types.h> 31*1da177e4SLinus Torvalds #include <linux/sched.h> 32*1da177e4SLinus Torvalds #include <linux/kernel_stat.h> 33*1da177e4SLinus Torvalds #include <linux/errno.h> 34*1da177e4SLinus Torvalds #include <linux/init.h> 35*1da177e4SLinus Torvalds 36*1da177e4SLinus Torvalds #include <asm/setup.h> 37*1da177e4SLinus Torvalds #include <asm/system.h> 38*1da177e4SLinus Torvalds #include <asm/irq.h> 39*1da177e4SLinus Torvalds #include <asm/traps.h> 40*1da177e4SLinus Torvalds #include <asm/page.h> 41*1da177e4SLinus Torvalds #include <asm/machdep.h> 42*1da177e4SLinus Torvalds 43*1da177e4SLinus Torvalds #ifdef CONFIG_Q40 44*1da177e4SLinus Torvalds #include <asm/q40ints.h> 45*1da177e4SLinus Torvalds #endif 46*1da177e4SLinus Torvalds 47*1da177e4SLinus Torvalds /* table for system interrupt handlers */ 48*1da177e4SLinus Torvalds static irq_handler_t irq_list[SYS_IRQS]; 49*1da177e4SLinus Torvalds 50*1da177e4SLinus Torvalds static const char *default_names[SYS_IRQS] = { 51*1da177e4SLinus Torvalds [0] = "spurious int", 52*1da177e4SLinus Torvalds [1] = "int1 handler", 53*1da177e4SLinus Torvalds [2] = "int2 handler", 54*1da177e4SLinus Torvalds [3] = "int3 handler", 55*1da177e4SLinus Torvalds [4] = "int4 handler", 56*1da177e4SLinus Torvalds [5] = "int5 handler", 57*1da177e4SLinus Torvalds [6] = "int6 handler", 58*1da177e4SLinus Torvalds [7] = "int7 handler" 59*1da177e4SLinus Torvalds }; 60*1da177e4SLinus Torvalds 61*1da177e4SLinus Torvalds /* The number of spurious interrupts */ 62*1da177e4SLinus Torvalds volatile unsigned int num_spurious; 63*1da177e4SLinus Torvalds 64*1da177e4SLinus Torvalds #define NUM_IRQ_NODES 100 65*1da177e4SLinus Torvalds static irq_node_t nodes[NUM_IRQ_NODES]; 66*1da177e4SLinus Torvalds 67*1da177e4SLinus Torvalds static void dummy_enable_irq(unsigned int irq); 68*1da177e4SLinus Torvalds static void dummy_disable_irq(unsigned int irq); 69*1da177e4SLinus Torvalds static int dummy_request_irq(unsigned int irq, 70*1da177e4SLinus Torvalds irqreturn_t (*handler) (int, void *, struct pt_regs *), 71*1da177e4SLinus Torvalds unsigned long flags, const char *devname, void *dev_id); 72*1da177e4SLinus Torvalds static void dummy_free_irq(unsigned int irq, void *dev_id); 73*1da177e4SLinus Torvalds 74*1da177e4SLinus Torvalds void (*enable_irq) (unsigned int) = dummy_enable_irq; 75*1da177e4SLinus Torvalds void (*disable_irq) (unsigned int) = dummy_disable_irq; 76*1da177e4SLinus Torvalds 77*1da177e4SLinus Torvalds int (*mach_request_irq) (unsigned int, irqreturn_t (*)(int, void *, struct pt_regs *), 78*1da177e4SLinus Torvalds unsigned long, const char *, void *) = dummy_request_irq; 79*1da177e4SLinus Torvalds void (*mach_free_irq) (unsigned int, void *) = dummy_free_irq; 80*1da177e4SLinus Torvalds 81*1da177e4SLinus Torvalds void init_irq_proc(void); 82*1da177e4SLinus Torvalds 83*1da177e4SLinus Torvalds /* 84*1da177e4SLinus Torvalds * void init_IRQ(void) 85*1da177e4SLinus Torvalds * 86*1da177e4SLinus Torvalds * Parameters: None 87*1da177e4SLinus Torvalds * 88*1da177e4SLinus Torvalds * Returns: Nothing 89*1da177e4SLinus Torvalds * 90*1da177e4SLinus Torvalds * This function should be called during kernel startup to initialize 91*1da177e4SLinus Torvalds * the IRQ handling routines. 92*1da177e4SLinus Torvalds */ 93*1da177e4SLinus Torvalds 94*1da177e4SLinus Torvalds void __init init_IRQ(void) 95*1da177e4SLinus Torvalds { 96*1da177e4SLinus Torvalds int i; 97*1da177e4SLinus Torvalds 98*1da177e4SLinus Torvalds for (i = 0; i < SYS_IRQS; i++) { 99*1da177e4SLinus Torvalds if (mach_default_handler) 100*1da177e4SLinus Torvalds irq_list[i].handler = (*mach_default_handler)[i]; 101*1da177e4SLinus Torvalds irq_list[i].flags = 0; 102*1da177e4SLinus Torvalds irq_list[i].dev_id = NULL; 103*1da177e4SLinus Torvalds irq_list[i].devname = default_names[i]; 104*1da177e4SLinus Torvalds } 105*1da177e4SLinus Torvalds 106*1da177e4SLinus Torvalds for (i = 0; i < NUM_IRQ_NODES; i++) 107*1da177e4SLinus Torvalds nodes[i].handler = NULL; 108*1da177e4SLinus Torvalds 109*1da177e4SLinus Torvalds mach_init_IRQ (); 110*1da177e4SLinus Torvalds } 111*1da177e4SLinus Torvalds 112*1da177e4SLinus Torvalds irq_node_t *new_irq_node(void) 113*1da177e4SLinus Torvalds { 114*1da177e4SLinus Torvalds irq_node_t *node; 115*1da177e4SLinus Torvalds short i; 116*1da177e4SLinus Torvalds 117*1da177e4SLinus Torvalds for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--) 118*1da177e4SLinus Torvalds if (!node->handler) 119*1da177e4SLinus Torvalds return node; 120*1da177e4SLinus Torvalds 121*1da177e4SLinus Torvalds printk ("new_irq_node: out of nodes\n"); 122*1da177e4SLinus Torvalds return NULL; 123*1da177e4SLinus Torvalds } 124*1da177e4SLinus Torvalds 125*1da177e4SLinus Torvalds /* 126*1da177e4SLinus Torvalds * We will keep these functions until I have convinced Linus to move 127*1da177e4SLinus Torvalds * the declaration of them from include/linux/sched.h to 128*1da177e4SLinus Torvalds * include/asm/irq.h. 129*1da177e4SLinus Torvalds */ 130*1da177e4SLinus Torvalds int request_irq(unsigned int irq, 131*1da177e4SLinus Torvalds irqreturn_t (*handler) (int, void *, struct pt_regs *), 132*1da177e4SLinus Torvalds unsigned long flags, const char *devname, void *dev_id) 133*1da177e4SLinus Torvalds { 134*1da177e4SLinus Torvalds return mach_request_irq(irq, handler, flags, devname, dev_id); 135*1da177e4SLinus Torvalds } 136*1da177e4SLinus Torvalds 137*1da177e4SLinus Torvalds EXPORT_SYMBOL(request_irq); 138*1da177e4SLinus Torvalds 139*1da177e4SLinus Torvalds void free_irq(unsigned int irq, void *dev_id) 140*1da177e4SLinus Torvalds { 141*1da177e4SLinus Torvalds mach_free_irq(irq, dev_id); 142*1da177e4SLinus Torvalds } 143*1da177e4SLinus Torvalds 144*1da177e4SLinus Torvalds EXPORT_SYMBOL(free_irq); 145*1da177e4SLinus Torvalds 146*1da177e4SLinus Torvalds int cpu_request_irq(unsigned int irq, 147*1da177e4SLinus Torvalds irqreturn_t (*handler)(int, void *, struct pt_regs *), 148*1da177e4SLinus Torvalds unsigned long flags, const char *devname, void *dev_id) 149*1da177e4SLinus Torvalds { 150*1da177e4SLinus Torvalds if (irq < IRQ1 || irq > IRQ7) { 151*1da177e4SLinus Torvalds printk("%s: Incorrect IRQ %d from %s\n", 152*1da177e4SLinus Torvalds __FUNCTION__, irq, devname); 153*1da177e4SLinus Torvalds return -ENXIO; 154*1da177e4SLinus Torvalds } 155*1da177e4SLinus Torvalds 156*1da177e4SLinus Torvalds #if 0 157*1da177e4SLinus Torvalds if (!(irq_list[irq].flags & IRQ_FLG_STD)) { 158*1da177e4SLinus Torvalds if (irq_list[irq].flags & IRQ_FLG_LOCK) { 159*1da177e4SLinus Torvalds printk("%s: IRQ %d from %s is not replaceable\n", 160*1da177e4SLinus Torvalds __FUNCTION__, irq, irq_list[irq].devname); 161*1da177e4SLinus Torvalds return -EBUSY; 162*1da177e4SLinus Torvalds } 163*1da177e4SLinus Torvalds if (!(flags & IRQ_FLG_REPLACE)) { 164*1da177e4SLinus Torvalds printk("%s: %s can't replace IRQ %d from %s\n", 165*1da177e4SLinus Torvalds __FUNCTION__, devname, irq, irq_list[irq].devname); 166*1da177e4SLinus Torvalds return -EBUSY; 167*1da177e4SLinus Torvalds } 168*1da177e4SLinus Torvalds } 169*1da177e4SLinus Torvalds #endif 170*1da177e4SLinus Torvalds 171*1da177e4SLinus Torvalds irq_list[irq].handler = handler; 172*1da177e4SLinus Torvalds irq_list[irq].flags = flags; 173*1da177e4SLinus Torvalds irq_list[irq].dev_id = dev_id; 174*1da177e4SLinus Torvalds irq_list[irq].devname = devname; 175*1da177e4SLinus Torvalds return 0; 176*1da177e4SLinus Torvalds } 177*1da177e4SLinus Torvalds 178*1da177e4SLinus Torvalds void cpu_free_irq(unsigned int irq, void *dev_id) 179*1da177e4SLinus Torvalds { 180*1da177e4SLinus Torvalds if (irq < IRQ1 || irq > IRQ7) { 181*1da177e4SLinus Torvalds printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq); 182*1da177e4SLinus Torvalds return; 183*1da177e4SLinus Torvalds } 184*1da177e4SLinus Torvalds 185*1da177e4SLinus Torvalds if (irq_list[irq].dev_id != dev_id) 186*1da177e4SLinus Torvalds printk("%s: Removing probably wrong IRQ %d from %s\n", 187*1da177e4SLinus Torvalds __FUNCTION__, irq, irq_list[irq].devname); 188*1da177e4SLinus Torvalds 189*1da177e4SLinus Torvalds irq_list[irq].handler = (*mach_default_handler)[irq]; 190*1da177e4SLinus Torvalds irq_list[irq].flags = 0; 191*1da177e4SLinus Torvalds irq_list[irq].dev_id = NULL; 192*1da177e4SLinus Torvalds irq_list[irq].devname = default_names[irq]; 193*1da177e4SLinus Torvalds } 194*1da177e4SLinus Torvalds 195*1da177e4SLinus Torvalds /* 196*1da177e4SLinus Torvalds * Do we need these probe functions on the m68k? 197*1da177e4SLinus Torvalds * 198*1da177e4SLinus Torvalds * ... may be useful with ISA devices 199*1da177e4SLinus Torvalds */ 200*1da177e4SLinus Torvalds unsigned long probe_irq_on (void) 201*1da177e4SLinus Torvalds { 202*1da177e4SLinus Torvalds #ifdef CONFIG_Q40 203*1da177e4SLinus Torvalds if (MACH_IS_Q40) 204*1da177e4SLinus Torvalds return q40_probe_irq_on(); 205*1da177e4SLinus Torvalds #endif 206*1da177e4SLinus Torvalds return 0; 207*1da177e4SLinus Torvalds } 208*1da177e4SLinus Torvalds 209*1da177e4SLinus Torvalds EXPORT_SYMBOL(probe_irq_on); 210*1da177e4SLinus Torvalds 211*1da177e4SLinus Torvalds int probe_irq_off (unsigned long irqs) 212*1da177e4SLinus Torvalds { 213*1da177e4SLinus Torvalds #ifdef CONFIG_Q40 214*1da177e4SLinus Torvalds if (MACH_IS_Q40) 215*1da177e4SLinus Torvalds return q40_probe_irq_off(irqs); 216*1da177e4SLinus Torvalds #endif 217*1da177e4SLinus Torvalds return 0; 218*1da177e4SLinus Torvalds } 219*1da177e4SLinus Torvalds 220*1da177e4SLinus Torvalds EXPORT_SYMBOL(probe_irq_off); 221*1da177e4SLinus Torvalds 222*1da177e4SLinus Torvalds static void dummy_enable_irq(unsigned int irq) 223*1da177e4SLinus Torvalds { 224*1da177e4SLinus Torvalds printk("calling uninitialized enable_irq()\n"); 225*1da177e4SLinus Torvalds } 226*1da177e4SLinus Torvalds 227*1da177e4SLinus Torvalds static void dummy_disable_irq(unsigned int irq) 228*1da177e4SLinus Torvalds { 229*1da177e4SLinus Torvalds printk("calling uninitialized disable_irq()\n"); 230*1da177e4SLinus Torvalds } 231*1da177e4SLinus Torvalds 232*1da177e4SLinus Torvalds static int dummy_request_irq(unsigned int irq, 233*1da177e4SLinus Torvalds irqreturn_t (*handler) (int, void *, struct pt_regs *), 234*1da177e4SLinus Torvalds unsigned long flags, const char *devname, void *dev_id) 235*1da177e4SLinus Torvalds { 236*1da177e4SLinus Torvalds printk("calling uninitialized request_irq()\n"); 237*1da177e4SLinus Torvalds return 0; 238*1da177e4SLinus Torvalds } 239*1da177e4SLinus Torvalds 240*1da177e4SLinus Torvalds static void dummy_free_irq(unsigned int irq, void *dev_id) 241*1da177e4SLinus Torvalds { 242*1da177e4SLinus Torvalds printk("calling uninitialized disable_irq()\n"); 243*1da177e4SLinus Torvalds } 244*1da177e4SLinus Torvalds 245*1da177e4SLinus Torvalds asmlinkage void process_int(unsigned long vec, struct pt_regs *fp) 246*1da177e4SLinus Torvalds { 247*1da177e4SLinus Torvalds if (vec >= VEC_INT1 && vec <= VEC_INT7 && !MACH_IS_BVME6000) { 248*1da177e4SLinus Torvalds vec -= VEC_SPUR; 249*1da177e4SLinus Torvalds kstat_cpu(0).irqs[vec]++; 250*1da177e4SLinus Torvalds irq_list[vec].handler(vec, irq_list[vec].dev_id, fp); 251*1da177e4SLinus Torvalds } else { 252*1da177e4SLinus Torvalds if (mach_process_int) 253*1da177e4SLinus Torvalds mach_process_int(vec, fp); 254*1da177e4SLinus Torvalds else 255*1da177e4SLinus Torvalds panic("Can't process interrupt vector %ld\n", vec); 256*1da177e4SLinus Torvalds return; 257*1da177e4SLinus Torvalds } 258*1da177e4SLinus Torvalds } 259*1da177e4SLinus Torvalds 260*1da177e4SLinus Torvalds int show_interrupts(struct seq_file *p, void *v) 261*1da177e4SLinus Torvalds { 262*1da177e4SLinus Torvalds int i = *(loff_t *) v; 263*1da177e4SLinus Torvalds 264*1da177e4SLinus Torvalds /* autovector interrupts */ 265*1da177e4SLinus Torvalds if (i < SYS_IRQS) { 266*1da177e4SLinus Torvalds if (mach_default_handler) { 267*1da177e4SLinus Torvalds seq_printf(p, "auto %2d: %10u ", i, 268*1da177e4SLinus Torvalds i ? kstat_cpu(0).irqs[i] : num_spurious); 269*1da177e4SLinus Torvalds seq_puts(p, " "); 270*1da177e4SLinus Torvalds seq_printf(p, "%s\n", irq_list[i].devname); 271*1da177e4SLinus Torvalds } 272*1da177e4SLinus Torvalds } else if (i == SYS_IRQS) 273*1da177e4SLinus Torvalds mach_get_irq_list(p, v); 274*1da177e4SLinus Torvalds return 0; 275*1da177e4SLinus Torvalds } 276*1da177e4SLinus Torvalds 277*1da177e4SLinus Torvalds void init_irq_proc(void) 278*1da177e4SLinus Torvalds { 279*1da177e4SLinus Torvalds /* Insert /proc/irq driver here */ 280*1da177e4SLinus Torvalds } 281*1da177e4SLinus Torvalds 282