1/* 2 * Carsten Langgaard, carstenl@mips.com 3 * Copyright (C) 2000, 2001 MIPS Technologies, Inc. 4 * Copyright (C) 2001 Ralf Baechle 5 * 6 * This program is free software; you can distribute it and/or modify it 7 * under the terms of the GNU General Public License (Version 2) as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * for more details. 14 * 15 * You should have received a copy of the GNU General Public License along 16 * with this program; if not, write to the Free Software Foundation, Inc., 17 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. 18 * 19 * Routines for generic manipulation of the interrupts found on the MIPS 20 * Malta board. 21 * The interrupt controller is located in the South Bridge a PIIX4 device 22 * with two internal 82C95 interrupt controllers. 23 */ 24#include <linux/config.h> 25#include <linux/init.h> 26#include <linux/sched.h> 27#include <linux/slab.h> 28#include <linux/interrupt.h> 29#include <linux/kernel_stat.h> 30#include <linux/random.h> 31 32#include <asm/irq.h> 33#include <asm/io.h> 34#include <asm/mips-boards/malta.h> 35#include <asm/mips-boards/maltaint.h> 36#include <asm/mips-boards/piix4.h> 37#include <asm/gt64120.h> 38#include <asm/mips-boards/generic.h> 39#include <asm/mips-boards/msc01_pci.h> 40 41extern asmlinkage void mipsIRQ(void); 42extern asmlinkage void do_IRQ(int irq, struct pt_regs *regs); 43extern void init_i8259_irqs (void); 44extern int mips_pcibios_iack(void); 45 46static spinlock_t mips_irq_lock = SPIN_LOCK_UNLOCKED; 47 48static inline int get_int(int *irq) 49{ 50 unsigned long flags; 51 52 spin_lock_irqsave(&mips_irq_lock, flags); 53 54 *irq = mips_pcibios_iack(); 55 56 /* 57 * IRQ7 is used to detect spurious interrupts. 58 * The interrupt acknowledge cycle returns IRQ7, if no 59 * interrupts is requested. 60 * We can differentiate between this situation and a 61 * "Normal" IRQ7 by reading the ISR. 62 */ 63 if (*irq == 7) 64 { 65 outb(PIIX4_OCW3_SEL | PIIX4_OCW3_ISR, 66 PIIX4_ICTLR1_OCW3); 67 if (!(inb(PIIX4_ICTLR1_OCW3) & (1 << 7))) { 68 spin_unlock_irqrestore(&mips_irq_lock, flags); 69 printk("We got a spurious interrupt from PIIX4.\n"); 70 atomic_inc(&irq_err_count); 71 return -1; /* Spurious interrupt. */ 72 } 73 } 74 75 spin_unlock_irqrestore(&mips_irq_lock, flags); 76 77 return 0; 78} 79 80void malta_hw0_irqdispatch(struct pt_regs *regs) 81{ 82 int irq; 83 84 if (get_int(&irq)) 85 return; /* interrupt has already been cleared */ 86 87 do_IRQ(irq, regs); 88} 89 90void corehi_irqdispatch(struct pt_regs *regs) 91{ 92 unsigned int data,datahi; 93 94 /* Mask out corehi interrupt. */ 95 clear_c0_status(IE_IRQ3); 96 97 printk("CoreHI interrupt, shouldn't happen, so we die here!!!\n"); 98 printk("epc : %08lx\nStatus: %08lx\nCause : %08lx\nbadVaddr : %08lx\n" 99, regs->cp0_epc, regs->cp0_status, regs->cp0_cause, regs->cp0_badvaddr); 100 switch(mips_revision_corid) { 101 case MIPS_REVISION_CORID_CORE_MSC: 102 break; 103 case MIPS_REVISION_CORID_QED_RM5261: 104 case MIPS_REVISION_CORID_CORE_LV: 105 case MIPS_REVISION_CORID_CORE_FPGA: 106 GT_READ(GT_INTRCAUSE_OFS, data); 107 printk("GT_INTRCAUSE = %08x\n", data); 108 GT_READ(0x70, data); 109 GT_READ(0x78, datahi); 110 printk("GT_CPU_ERR_ADDR = %0x2%08x\n", datahi,data); 111 break; 112 case MIPS_REVISION_CORID_BONITO64: 113 case MIPS_REVISION_CORID_CORE_20K: 114 data = BONITO_INTISR; 115 printk("BONITO_INTISR = %08x\n", data); 116 data = BONITO_INTEN; 117 printk("BONITO_INTEN = %08x\n", data); 118 data = BONITO_INTPOL; 119 printk("BONITO_INTPOL = %08x\n", data); 120 data = BONITO_INTEDGE; 121 printk("BONITO_INTEDGE = %08x\n", data); 122 data = BONITO_INTSTEER; 123 printk("BONITO_INTSTEER = %08x\n", data); 124 data = BONITO_PCICMD; 125 printk("BONITO_PCICMD = %08x\n", data); 126 break; 127 } 128 129 /* We die here*/ 130 die("CoreHi interrupt", regs); 131} 132 133void __init init_IRQ(void) 134{ 135 set_except_vector(0, mipsIRQ); 136 init_generic_irq(); 137 init_i8259_irqs(); 138 139#ifdef CONFIG_REMOTE_DEBUG 140 if (remote_debug) { 141 set_debug_traps(); 142 breakpoint(); 143 } 144#endif 145} 146 147 148