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 2111ed6d5bSRalf Baechle #include <asm/mach-cobalt/cobalt.h> 221da177e4SLinus Torvalds 231da177e4SLinus Torvalds /* 241da177e4SLinus Torvalds * We have two types of interrupts that we handle, ones that come in through 251da177e4SLinus Torvalds * the CPU interrupt lines, and ones that come in on the via chip. The CPU 261da177e4SLinus Torvalds * mappings are: 271da177e4SLinus Torvalds * 28c4ed38a0SRalf Baechle * 16 - Software interrupt 0 (unused) IE_SW0 29c4ed38a0SRalf Baechle * 17 - Software interrupt 1 (unused) IE_SW1 301da177e4SLinus Torvalds * 18 - Galileo chip (timer) IE_IRQ0 311da177e4SLinus Torvalds * 19 - Tulip 0 + NCR SCSI IE_IRQ1 321da177e4SLinus Torvalds * 20 - Tulip 1 IE_IRQ2 331da177e4SLinus Torvalds * 21 - 16550 UART IE_IRQ3 341da177e4SLinus Torvalds * 22 - VIA southbridge PIC IE_IRQ4 351da177e4SLinus Torvalds * 23 - unused IE_IRQ5 361da177e4SLinus Torvalds * 371da177e4SLinus Torvalds * The VIA chip is a master/slave 8259 setup and has the following interrupts: 381da177e4SLinus Torvalds * 391da177e4SLinus Torvalds * 8 - RTC 401da177e4SLinus Torvalds * 9 - PCI 411da177e4SLinus Torvalds * 14 - IDE0 421da177e4SLinus Torvalds * 15 - IDE1 431da177e4SLinus Torvalds */ 441da177e4SLinus Torvalds 45*937a8015SRalf Baechle static inline void galileo_irq(void) 461da177e4SLinus Torvalds { 47c4ed38a0SRalf Baechle unsigned int mask, pending, devfn; 481da177e4SLinus Torvalds 49c4ed38a0SRalf Baechle mask = GALILEO_INL(GT_INTRMASK_OFS); 50c4ed38a0SRalf Baechle pending = GALILEO_INL(GT_INTRCAUSE_OFS) & mask; 511da177e4SLinus Torvalds 52c4ed38a0SRalf Baechle if (pending & GALILEO_INTR_T0EXP) { 53c4ed38a0SRalf Baechle 54c4ed38a0SRalf Baechle GALILEO_OUTL(~GALILEO_INTR_T0EXP, GT_INTRCAUSE_OFS); 55*937a8015SRalf Baechle do_IRQ(COBALT_GALILEO_IRQ); 56c4ed38a0SRalf Baechle 57c4ed38a0SRalf Baechle } else if (pending & GALILEO_INTR_RETRY_CTR) { 58c4ed38a0SRalf Baechle 59c4ed38a0SRalf Baechle devfn = GALILEO_INL(GT_PCI0_CFGADDR_OFS) >> 8; 60c4ed38a0SRalf Baechle GALILEO_OUTL(~GALILEO_INTR_RETRY_CTR, GT_INTRCAUSE_OFS); 61c4ed38a0SRalf Baechle printk(KERN_WARNING "Galileo: PCI retry count exceeded (%02x.%u)\n", 62c4ed38a0SRalf Baechle PCI_SLOT(devfn), PCI_FUNC(devfn)); 63c4ed38a0SRalf Baechle 64c4ed38a0SRalf Baechle } else { 65c4ed38a0SRalf Baechle 66c4ed38a0SRalf Baechle GALILEO_OUTL(mask & ~pending, GT_INTRMASK_OFS); 67c4ed38a0SRalf Baechle printk(KERN_WARNING "Galileo: masking unexpected interrupt %08x\n", pending); 681da177e4SLinus Torvalds } 691da177e4SLinus Torvalds } 701da177e4SLinus Torvalds 71*937a8015SRalf Baechle static inline void via_pic_irq(void) 72c4ed38a0SRalf Baechle { 73c4ed38a0SRalf Baechle int irq; 741da177e4SLinus Torvalds 75c4ed38a0SRalf Baechle irq = i8259_irq(); 761da177e4SLinus Torvalds if (irq >= 0) 77*937a8015SRalf Baechle do_IRQ(irq); 781da177e4SLinus Torvalds } 791da177e4SLinus Torvalds 80*937a8015SRalf Baechle asmlinkage void plat_irq_dispatch(void) 81c4ed38a0SRalf Baechle { 82*937a8015SRalf Baechle unsigned pending = read_c0_status() & read_c0_cause(); 83c4ed38a0SRalf Baechle 84c4ed38a0SRalf Baechle if (pending & CAUSEF_IP2) /* COBALT_GALILEO_IRQ (18) */ 85*937a8015SRalf Baechle galileo_irq(); 86c4ed38a0SRalf Baechle else if (pending & CAUSEF_IP6) /* COBALT_VIA_IRQ (22) */ 87*937a8015SRalf Baechle via_pic_irq(); 88c4ed38a0SRalf Baechle else if (pending & CAUSEF_IP3) /* COBALT_ETH0_IRQ (19) */ 89*937a8015SRalf Baechle do_IRQ(COBALT_CPU_IRQ + 3); 90c4ed38a0SRalf Baechle else if (pending & CAUSEF_IP4) /* COBALT_ETH1_IRQ (20) */ 91*937a8015SRalf Baechle do_IRQ(COBALT_CPU_IRQ + 4); 92c4ed38a0SRalf Baechle else if (pending & CAUSEF_IP5) /* COBALT_SERIAL_IRQ (21) */ 93*937a8015SRalf Baechle do_IRQ(COBALT_CPU_IRQ + 5); 94c4ed38a0SRalf Baechle else if (pending & CAUSEF_IP7) /* IRQ 23 */ 95*937a8015SRalf Baechle do_IRQ(COBALT_CPU_IRQ + 7); 961da177e4SLinus Torvalds } 971da177e4SLinus Torvalds 98c4ed38a0SRalf Baechle static struct irqaction irq_via = { 99c4ed38a0SRalf Baechle no_action, 0, { { 0, } }, "cascade", NULL, NULL 100c4ed38a0SRalf Baechle }; 1011da177e4SLinus Torvalds 1021da177e4SLinus Torvalds void __init arch_init_irq(void) 1031da177e4SLinus Torvalds { 104c4ed38a0SRalf Baechle /* 105c4ed38a0SRalf Baechle * Mask all Galileo interrupts. The Galileo 106c4ed38a0SRalf Baechle * handler is set in cobalt_timer_setup() 107c4ed38a0SRalf Baechle */ 108c4ed38a0SRalf Baechle GALILEO_OUTL(0, GT_INTRMASK_OFS); 109c4ed38a0SRalf Baechle 1101da177e4SLinus Torvalds init_i8259_irqs(); /* 0 ... 15 */ 111c4ed38a0SRalf Baechle mips_cpu_irq_init(COBALT_CPU_IRQ); /* 16 ... 23 */ 1121da177e4SLinus Torvalds 1131da177e4SLinus Torvalds /* 1141da177e4SLinus Torvalds * Mask all cpu interrupts 1151da177e4SLinus Torvalds * (except IE4, we already masked those at VIA level) 1161da177e4SLinus Torvalds */ 1171da177e4SLinus Torvalds change_c0_status(ST0_IM, IE_IRQ4); 118c4ed38a0SRalf Baechle 119c4ed38a0SRalf Baechle setup_irq(COBALT_VIA_IRQ, &irq_via); 1201da177e4SLinus Torvalds } 121