1/* 2 * Copyright (C) 2000, 2001, 2002, 2003 Broadcom Corporation 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 2 7 * of the License, or (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17 */ 18 19/* 20 * sb1250_handle_int() is the routine that is actually called when an interrupt 21 * occurs. It is installed as the exception vector handler in init_IRQ() in 22 * arch/mips/sibyte/sb1250/irq.c 23 * 24 * In the handle we figure out which interrupts need handling, and use that to 25 * call the dispatcher, which will take care of actually calling registered 26 * handlers 27 * 28 * Note that we take care of all raised interrupts in one go at the handler. 29 * This is more BSDish than the Indy code, and also, IMHO, more sane. 30 */ 31#include <linux/config.h> 32 33#include <asm/addrspace.h> 34#include <asm/processor.h> 35#include <asm/asm.h> 36#include <asm/mipsregs.h> 37#include <asm/regdef.h> 38#include <asm/stackframe.h> 39#include <asm/sibyte/sb1250_defs.h> 40#include <asm/sibyte/sb1250_regs.h> 41#include <asm/sibyte/sb1250_int.h> 42 43/* 44 * What a pain. We have to be really careful saving the upper 32 bits of any 45 * register across function calls if we don't want them trashed--since were 46 * running in -o32, the calling routing never saves the full 64 bits of a 47 * register across a function call. Being the interrupt handler, we're 48 * guaranteed that interrupts are disabled during this code so we don't have 49 * to worry about random interrupts blasting the high 32 bits. 50 */ 51 52 .text 53 .set push 54 .set noreorder 55 .set noat 56 #.set mips64 57 .set mips4 58 .align 5 59 NESTED(sb1250_irq_handler, PT_SIZE, sp) 60 SAVE_ALL 61 CLI 62 63#ifdef CONFIG_SIBYTE_SB1250_PROF 64 /* Set compare to count to silence count/compare timer interrupts */ 65 mfc0 t1, CP0_COUNT 66 mtc0 t1, CP0_COMPARE /* pause to clear IP[7] bit of cause ? */ 67#endif 68 /* Read cause */ 69 mfc0 s0, CP0_CAUSE 70 71#ifdef CONFIG_SIBYTE_SB1250_PROF 72 /* Cpu performance counter interrupt is routed to IP[7] */ 73 andi t1, s0, CAUSEF_IP7 74 beqz t1, 0f 75 srl t1, s0, (CAUSEB_BD-2) /* Shift BD bit to bit 2 */ 76 and t1, t1, 0x4 /* mask to get just BD bit */ 77 mfc0 a0, CP0_EPC 78 jal sbprof_cpu_intr 79 addu a0, a0, t1 /* a0 = EPC + (BD ? 4 : 0) */ 80 j ret_from_irq 81 nop 820: 83#endif 84 85 /* Timer interrupt is routed to IP[4] */ 86 andi t1, s0, CAUSEF_IP4 87 beqz t1, 1f 88 nop 89 jal sb1250_timer_interrupt 90 move a0, sp /* Pass the registers along */ 91 j ret_from_irq 92 nop # delay slot 931: 94 95#ifdef CONFIG_SMP 96 /* Mailbox interrupt is routed to IP[3] */ 97 andi t1, s0, CAUSEF_IP3 98 beqz t1, 2f 99 nop 100 jal sb1250_mailbox_interrupt 101 move a0, sp 102 j ret_from_irq 103 nop # delay slot 1042: 105#endif 106 107#ifdef CONFIG_KGDB 108 /* KGDB (uart 1) interrupt is routed to IP[6] */ 109 andi t1, s0, CAUSEF_IP6 110 beqz t1, 1f 111 nop # delay slot 112 jal sb1250_kgdb_interrupt 113 move a0, sp 114 j ret_from_irq 115 nop # delay slot 1161: 117#endif 118 119 and t1, s0, CAUSEF_IP2 120 beqz t1, 4f 121 nop 122 123 /* 124 * Default...we've hit an IP[2] interrupt, which means we've got to 125 * check the 1250 interrupt registers to figure out what to do 126 * Need to detect which CPU we're on, now that smp_affinity is supported. 127 */ 128 PTR_LA v0, KSEG1 + A_IMR_CPU0_BASE 129#ifdef CONFIG_SMP 130 lw t1, TASK_PROCESSOR($28) 131 sll t1, IMR_REGISTER_SPACING_SHIFT 132 addu v0, t1 133#endif 134 ld s0, R_IMR_INTERRUPT_STATUS_BASE(v0) /* read IP[2] status */ 135 136 beqz s0, 4f /* No interrupts. Return */ 137 move a1, sp 138 1393: #dclz s1, s0 /* Find the next interrupt */ 140 .word 0x72118824 # dclz s1, s0 141 dsubu a0, zero, s1 142 daddiu a0, a0, 63 143 jal do_IRQ 144 nop 145 1464: j ret_from_irq 147 nop 148 149 .set pop 150 END(sb1250_irq_handler) 151