11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * IRQ vector handles 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * This file is subject to the terms and conditions of the GNU General Public 51da177e4SLinus Torvalds * License. See the file "COPYING" in the main directory of this archive 61da177e4SLinus Torvalds * for more details. 71da177e4SLinus Torvalds * 81da177e4SLinus Torvalds * Copyright (C) 1995, 1996, 1997, 2003 by Ralf Baechle 91da177e4SLinus Torvalds */ 101da177e4SLinus Torvalds #include <linux/kernel.h> 111da177e4SLinus Torvalds #include <linux/init.h> 121da177e4SLinus Torvalds #include <linux/irq.h> 13*c4ed38a0SRalf Baechle #include <linux/interrupt.h> 14*c4ed38a0SRalf Baechle #include <linux/pci.h> 151da177e4SLinus Torvalds 161da177e4SLinus Torvalds #include <asm/i8259.h> 171da177e4SLinus Torvalds #include <asm/irq_cpu.h> 181da177e4SLinus Torvalds #include <asm/gt64120.h> 191da177e4SLinus Torvalds #include <asm/ptrace.h> 201da177e4SLinus Torvalds 211da177e4SLinus Torvalds #include <asm/cobalt/cobalt.h> 221da177e4SLinus Torvalds 231da177e4SLinus Torvalds extern void cobalt_handle_int(void); 241da177e4SLinus Torvalds 251da177e4SLinus Torvalds /* 261da177e4SLinus Torvalds * We have two types of interrupts that we handle, ones that come in through 271da177e4SLinus Torvalds * the CPU interrupt lines, and ones that come in on the via chip. The CPU 281da177e4SLinus Torvalds * mappings are: 291da177e4SLinus Torvalds * 30*c4ed38a0SRalf Baechle * 16 - Software interrupt 0 (unused) IE_SW0 31*c4ed38a0SRalf Baechle * 17 - Software interrupt 1 (unused) IE_SW1 321da177e4SLinus Torvalds * 18 - Galileo chip (timer) IE_IRQ0 331da177e4SLinus Torvalds * 19 - Tulip 0 + NCR SCSI IE_IRQ1 341da177e4SLinus Torvalds * 20 - Tulip 1 IE_IRQ2 351da177e4SLinus Torvalds * 21 - 16550 UART IE_IRQ3 361da177e4SLinus Torvalds * 22 - VIA southbridge PIC IE_IRQ4 371da177e4SLinus Torvalds * 23 - unused IE_IRQ5 381da177e4SLinus Torvalds * 391da177e4SLinus Torvalds * The VIA chip is a master/slave 8259 setup and has the following interrupts: 401da177e4SLinus Torvalds * 411da177e4SLinus Torvalds * 8 - RTC 421da177e4SLinus Torvalds * 9 - PCI 431da177e4SLinus Torvalds * 14 - IDE0 441da177e4SLinus Torvalds * 15 - IDE1 451da177e4SLinus Torvalds */ 461da177e4SLinus Torvalds 47*c4ed38a0SRalf Baechle static inline void galileo_irq(struct pt_regs *regs) 481da177e4SLinus Torvalds { 49*c4ed38a0SRalf Baechle unsigned int mask, pending, devfn; 501da177e4SLinus Torvalds 51*c4ed38a0SRalf Baechle mask = GALILEO_INL(GT_INTRMASK_OFS); 52*c4ed38a0SRalf Baechle pending = GALILEO_INL(GT_INTRCAUSE_OFS) & mask; 531da177e4SLinus Torvalds 54*c4ed38a0SRalf Baechle if (pending & GALILEO_INTR_T0EXP) { 55*c4ed38a0SRalf Baechle 56*c4ed38a0SRalf Baechle GALILEO_OUTL(~GALILEO_INTR_T0EXP, GT_INTRCAUSE_OFS); 57*c4ed38a0SRalf Baechle do_IRQ(COBALT_GALILEO_IRQ, regs); 58*c4ed38a0SRalf Baechle 59*c4ed38a0SRalf Baechle } else if (pending & GALILEO_INTR_RETRY_CTR) { 60*c4ed38a0SRalf Baechle 61*c4ed38a0SRalf Baechle devfn = GALILEO_INL(GT_PCI0_CFGADDR_OFS) >> 8; 62*c4ed38a0SRalf Baechle GALILEO_OUTL(~GALILEO_INTR_RETRY_CTR, GT_INTRCAUSE_OFS); 63*c4ed38a0SRalf Baechle printk(KERN_WARNING "Galileo: PCI retry count exceeded (%02x.%u)\n", 64*c4ed38a0SRalf Baechle PCI_SLOT(devfn), PCI_FUNC(devfn)); 65*c4ed38a0SRalf Baechle 66*c4ed38a0SRalf Baechle } else { 67*c4ed38a0SRalf Baechle 68*c4ed38a0SRalf Baechle GALILEO_OUTL(mask & ~pending, GT_INTRMASK_OFS); 69*c4ed38a0SRalf Baechle printk(KERN_WARNING "Galileo: masking unexpected interrupt %08x\n", pending); 701da177e4SLinus Torvalds } 711da177e4SLinus Torvalds } 721da177e4SLinus Torvalds 73*c4ed38a0SRalf Baechle static inline void via_pic_irq(struct pt_regs *regs) 74*c4ed38a0SRalf Baechle { 75*c4ed38a0SRalf Baechle int irq; 761da177e4SLinus Torvalds 77*c4ed38a0SRalf Baechle irq = i8259_irq(); 781da177e4SLinus Torvalds if (irq >= 0) 791da177e4SLinus Torvalds do_IRQ(irq, regs); 801da177e4SLinus Torvalds } 811da177e4SLinus Torvalds 82*c4ed38a0SRalf Baechle asmlinkage void cobalt_irq(struct pt_regs *regs) 83*c4ed38a0SRalf Baechle { 84*c4ed38a0SRalf Baechle unsigned pending; 85*c4ed38a0SRalf Baechle 86*c4ed38a0SRalf Baechle pending = read_c0_status() & read_c0_cause(); 87*c4ed38a0SRalf Baechle 88*c4ed38a0SRalf Baechle if (pending & CAUSEF_IP2) /* COBALT_GALILEO_IRQ (18) */ 89*c4ed38a0SRalf Baechle 90*c4ed38a0SRalf Baechle galileo_irq(regs); 91*c4ed38a0SRalf Baechle 92*c4ed38a0SRalf Baechle else if (pending & CAUSEF_IP6) /* COBALT_VIA_IRQ (22) */ 93*c4ed38a0SRalf Baechle 94*c4ed38a0SRalf Baechle via_pic_irq(regs); 95*c4ed38a0SRalf Baechle 96*c4ed38a0SRalf Baechle else if (pending & CAUSEF_IP3) /* COBALT_ETH0_IRQ (19) */ 97*c4ed38a0SRalf Baechle 98*c4ed38a0SRalf Baechle do_IRQ(COBALT_CPU_IRQ + 3, regs); 99*c4ed38a0SRalf Baechle 100*c4ed38a0SRalf Baechle else if (pending & CAUSEF_IP4) /* COBALT_ETH1_IRQ (20) */ 101*c4ed38a0SRalf Baechle 102*c4ed38a0SRalf Baechle do_IRQ(COBALT_CPU_IRQ + 4, regs); 103*c4ed38a0SRalf Baechle 104*c4ed38a0SRalf Baechle else if (pending & CAUSEF_IP5) /* COBALT_SERIAL_IRQ (21) */ 105*c4ed38a0SRalf Baechle 106*c4ed38a0SRalf Baechle do_IRQ(COBALT_CPU_IRQ + 5, regs); 107*c4ed38a0SRalf Baechle 108*c4ed38a0SRalf Baechle else if (pending & CAUSEF_IP7) /* IRQ 23 */ 109*c4ed38a0SRalf Baechle 110*c4ed38a0SRalf Baechle do_IRQ(COBALT_CPU_IRQ + 7, regs); 1111da177e4SLinus Torvalds } 1121da177e4SLinus Torvalds 113*c4ed38a0SRalf Baechle static struct irqaction irq_via = { 114*c4ed38a0SRalf Baechle no_action, 0, { { 0, } }, "cascade", NULL, NULL 115*c4ed38a0SRalf Baechle }; 1161da177e4SLinus Torvalds 1171da177e4SLinus Torvalds void __init arch_init_irq(void) 1181da177e4SLinus Torvalds { 119*c4ed38a0SRalf Baechle /* 120*c4ed38a0SRalf Baechle * Mask all Galileo interrupts. The Galileo 121*c4ed38a0SRalf Baechle * handler is set in cobalt_timer_setup() 122*c4ed38a0SRalf Baechle */ 123*c4ed38a0SRalf Baechle GALILEO_OUTL(0, GT_INTRMASK_OFS); 124*c4ed38a0SRalf Baechle 1251da177e4SLinus Torvalds set_except_vector(0, cobalt_handle_int); 1261da177e4SLinus Torvalds 1271da177e4SLinus Torvalds init_i8259_irqs(); /* 0 ... 15 */ 128*c4ed38a0SRalf Baechle mips_cpu_irq_init(COBALT_CPU_IRQ); /* 16 ... 23 */ 1291da177e4SLinus Torvalds 1301da177e4SLinus Torvalds /* 1311da177e4SLinus Torvalds * Mask all cpu interrupts 1321da177e4SLinus Torvalds * (except IE4, we already masked those at VIA level) 1331da177e4SLinus Torvalds */ 1341da177e4SLinus Torvalds change_c0_status(ST0_IM, IE_IRQ4); 135*c4ed38a0SRalf Baechle 136*c4ed38a0SRalf Baechle setup_irq(COBALT_VIA_IRQ, &irq_via); 1371da177e4SLinus Torvalds } 138