973e10aaacd5c70b1dbb48565999a1631669ea09
[linux-2.6.git] / arch / mips / mips-boards / generic / mipsIRQ.S
1 /*
2  * Carsten Langgaard, carstenl@mips.com
3  * Copyright (C) 1999, 2000 MIPS Technologies, Inc.  All rights reserved.
4  *
5  * ########################################################################
6  *
7  *  This program is free software; you can distribute it and/or modify it
8  *  under the terms of the GNU General Public License (Version 2) as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope it will be useful, but WITHOUT
12  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  *  for more details.
15  *
16  *  You should have received a copy of the GNU General Public License along
17  *  with this program; if not, write to the Free Software Foundation, Inc.,
18  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
19  *
20  * ########################################################################
21  *
22  * Interrupt exception dispatch code.
23  *
24  */
25 #include <linux/config.h>
26
27 #include <asm/asm.h>
28 #include <asm/mipsregs.h>
29 #include <asm/regdef.h>
30 #include <asm/stackframe.h>
31
32 #ifdef CONFIG_MIPS_ATLAS
33 #include <asm/mips-boards/atlasint.h>
34 #define CASCADE_IRQ             MIPSCPU_INT_ATLAS
35 #define CASCADE_DISPATCH        atlas_hw0_irqdispatch
36 #endif
37 #ifdef CONFIG_MIPS_MALTA
38 #include <asm/mips-boards/maltaint.h>
39 #define CASCADE_IRQ             MIPSCPU_INT_I8259A
40 #define CASCADE_DISPATCH        malta_hw0_irqdispatch
41 #endif
42 #ifdef CONFIG_MIPS_SEAD
43 #include <asm/mips-boards/seadint.h>
44 #endif
45
46 /* A lot of complication here is taken away because:
47  *
48  * 1) We handle one interrupt and return, sitting in a loop and moving across
49  *    all the pending IRQ bits in the cause register is _NOT_ the answer, the
50  *    common case is one pending IRQ so optimize in that direction.
51  *
52  * 2) We need not check against bits in the status register IRQ mask, that
53  *    would make this routine slow as hell.
54  *
55  * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in
56  *    between like BSD spl() brain-damage.
57  *
58  * Furthermore, the IRQs on the MIPS board look basically (barring software
59  * IRQs which we don't use at all and all external interrupt sources are
60  * combined together on hardware interrupt 0 (MIPS IRQ 2)) like:
61  *
62  *      MIPS IRQ        Source
63  *      --------        ------
64  *             0        Software (ignored)
65  *             1        Software (ignored)
66  *             2        Combined hardware interrupt (hw0)
67  *             3        Hardware (ignored)
68  *             4        Hardware (ignored)
69  *             5        Hardware (ignored)
70  *             6        Hardware (ignored)
71  *             7        R4k timer (what we use)
72  *
73  * Note: On the SEAD board thing are a little bit different.
74  *       Here IRQ 2 (hw0) is wired to the UART0 and IRQ 3 (hw1) is wired
75  *       wired to UART1.
76  *
77  * We handle the IRQ according to _our_ priority which is:
78  *
79  * Highest ----     R4k Timer
80  * Lowest  ----     Combined hardware interrupt
81  *
82  * then we just return, if multiple IRQs are pending then we will just take
83  * another exception, big deal.
84  */
85
86         .text
87         .set    noreorder
88         .set    noat
89         .align  5
90         NESTED(mipsIRQ, PT_SIZE, sp)
91         SAVE_ALL
92         CLI
93         .set    at
94
95         mfc0    s0, CP0_CAUSE           # get irq bits
96         mfc0    s1, CP0_STATUS          # get irq mask
97         andi    s0, ST0_IM              # CAUSE.CE may be non-zero!
98         and     s0, s1
99
100 #if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
101         .set    mips32
102         clz     a0, s0
103         .set    mips0
104         negu    a0
105         addu    a0, 31-CAUSEB_IP
106         bltz    a0, spurious
107 #else
108         beqz    s0, spurious
109          li     a0, 7
110
111         and     t0, s0, 0xf000
112         sltiu   t0, t0, 1
113         sll     t0, 2
114         subu    a0, t0
115         sll     s0, t0
116
117         and     t0, s0, 0xc000
118         sltiu   t0, t0, 1
119         sll     t0, 1
120         subu    a0, t0
121         sll     s0, t0
122
123         and     t0, s0, 0x8000
124         sltiu   t0, t0, 1
125         # sll   t0, 0
126         subu    a0, t0
127         # sll   s0, t0
128 #endif
129
130 #ifdef CASCADE_IRQ
131          li     a1, CASCADE_IRQ
132         bne     a0, a1, 1f
133          addu   a0, MIPSCPU_INT_BASE
134
135         jal     CASCADE_DISPATCH
136          move    a0, sp
137
138         j       ret_from_irq
139          nop
140 1:
141 #else
142          addu   a0, MIPSCPU_INT_BASE
143 #endif
144
145         jal     do_IRQ
146          move   a1, sp
147
148         j       ret_from_irq
149          nop
150
151
152 spurious:
153         jal     spurious_interrupt
154          nop
155         j       ret_from_irq
156          nop
157         END(mipsIRQ)