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> 13c4ed38a0SRalf Baechle #include <linux/interrupt.h> 14c4ed38a0SRalf 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 21*11ed6d5bSRalf Baechle #include <asm/mach-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 * 30c4ed38a0SRalf Baechle * 16 - Software interrupt 0 (unused) IE_SW0 31c4ed38a0SRalf 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 47c4ed38a0SRalf Baechle static inline void galileo_irq(struct pt_regs *regs) 481da177e4SLinus Torvalds { 49c4ed38a0SRalf Baechle unsigned int mask, pending, devfn; 501da177e4SLinus Torvalds 51c4ed38a0SRalf Baechle mask = GALILEO_INL(GT_INTRMASK_OFS); 52c4ed38a0SRalf Baechle pending = GALILEO_INL(GT_INTRCAUSE_OFS) & mask; 531da177e4SLinus Torvalds 54c4ed38a0SRalf Baechle if (pending & GALILEO_INTR_T0EXP) { 55c4ed38a0SRalf Baechle 56c4ed38a0SRalf Baechle GALILEO_OUTL(~GALILEO_INTR_T0EXP, GT_INTRCAUSE_OFS); 57c4ed38a0SRalf Baechle do_IRQ(COBALT_GALILEO_IRQ, regs); 58c4ed38a0SRalf Baechle 59c4ed38a0SRalf Baechle } else if (pending & GALILEO_INTR_RETRY_CTR) { 60c4ed38a0SRalf Baechle 61c4ed38a0SRalf Baechle devfn = GALILEO_INL(GT_PCI0_CFGADDR_OFS) >> 8; 62c4ed38a0SRalf Baechle GALILEO_OUTL(~GALILEO_INTR_RETRY_CTR, GT_INTRCAUSE_OFS); 63c4ed38a0SRalf Baechle printk(KERN_WARNING "Galileo: PCI retry count exceeded (%02x.%u)\n", 64c4ed38a0SRalf Baechle PCI_SLOT(devfn), PCI_FUNC(devfn)); 65c4ed38a0SRalf Baechle 66c4ed38a0SRalf Baechle } else { 67c4ed38a0SRalf Baechle 68c4ed38a0SRalf Baechle GALILEO_OUTL(mask & ~pending, GT_INTRMASK_OFS); 69c4ed38a0SRalf Baechle printk(KERN_WARNING "Galileo: masking unexpected interrupt %08x\n", pending); 701da177e4SLinus Torvalds } 711da177e4SLinus Torvalds } 721da177e4SLinus Torvalds 73c4ed38a0SRalf Baechle static inline void via_pic_irq(struct pt_regs *regs) 74c4ed38a0SRalf Baechle { 75c4ed38a0SRalf Baechle int irq; 761da177e4SLinus Torvalds 77c4ed38a0SRalf Baechle irq = i8259_irq(); 781da177e4SLinus Torvalds if (irq >= 0) 791da177e4SLinus Torvalds do_IRQ(irq, regs); 801da177e4SLinus Torvalds } 811da177e4SLinus Torvalds 82c4ed38a0SRalf Baechle asmlinkage void cobalt_irq(struct pt_regs *regs) 83c4ed38a0SRalf Baechle { 84c4ed38a0SRalf Baechle unsigned pending; 85c4ed38a0SRalf Baechle 86c4ed38a0SRalf Baechle pending = read_c0_status() & read_c0_cause(); 87c4ed38a0SRalf Baechle 88c4ed38a0SRalf Baechle if (pending & CAUSEF_IP2) /* COBALT_GALILEO_IRQ (18) */ 89c4ed38a0SRalf Baechle 90c4ed38a0SRalf Baechle galileo_irq(regs); 91c4ed38a0SRalf Baechle 92c4ed38a0SRalf Baechle else if (pending & CAUSEF_IP6) /* COBALT_VIA_IRQ (22) */ 93c4ed38a0SRalf Baechle 94c4ed38a0SRalf Baechle via_pic_irq(regs); 95c4ed38a0SRalf Baechle 96c4ed38a0SRalf Baechle else if (pending & CAUSEF_IP3) /* COBALT_ETH0_IRQ (19) */ 97c4ed38a0SRalf Baechle 98c4ed38a0SRalf Baechle do_IRQ(COBALT_CPU_IRQ + 3, regs); 99c4ed38a0SRalf Baechle 100c4ed38a0SRalf Baechle else if (pending & CAUSEF_IP4) /* COBALT_ETH1_IRQ (20) */ 101c4ed38a0SRalf Baechle 102c4ed38a0SRalf Baechle do_IRQ(COBALT_CPU_IRQ + 4, regs); 103c4ed38a0SRalf Baechle 104c4ed38a0SRalf Baechle else if (pending & CAUSEF_IP5) /* COBALT_SERIAL_IRQ (21) */ 105c4ed38a0SRalf Baechle 106c4ed38a0SRalf Baechle do_IRQ(COBALT_CPU_IRQ + 5, regs); 107c4ed38a0SRalf Baechle 108c4ed38a0SRalf Baechle else if (pending & CAUSEF_IP7) /* IRQ 23 */ 109c4ed38a0SRalf Baechle 110c4ed38a0SRalf Baechle do_IRQ(COBALT_CPU_IRQ + 7, regs); 1111da177e4SLinus Torvalds } 1121da177e4SLinus Torvalds 113c4ed38a0SRalf Baechle static struct irqaction irq_via = { 114c4ed38a0SRalf Baechle no_action, 0, { { 0, } }, "cascade", NULL, NULL 115c4ed38a0SRalf Baechle }; 1161da177e4SLinus Torvalds 1171da177e4SLinus Torvalds void __init arch_init_irq(void) 1181da177e4SLinus Torvalds { 119c4ed38a0SRalf Baechle /* 120c4ed38a0SRalf Baechle * Mask all Galileo interrupts. The Galileo 121c4ed38a0SRalf Baechle * handler is set in cobalt_timer_setup() 122c4ed38a0SRalf Baechle */ 123c4ed38a0SRalf Baechle GALILEO_OUTL(0, GT_INTRMASK_OFS); 124c4ed38a0SRalf Baechle 1251da177e4SLinus Torvalds set_except_vector(0, cobalt_handle_int); 1261da177e4SLinus Torvalds 1271da177e4SLinus Torvalds init_i8259_irqs(); /* 0 ... 15 */ 128c4ed38a0SRalf 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); 135c4ed38a0SRalf Baechle 136c4ed38a0SRalf Baechle setup_irq(COBALT_VIA_IRQ, &irq_via); 1371da177e4SLinus Torvalds } 138