blob: 4bb9c06f44107006f4c6330df7f0aedb23bc96a2 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 1994, 95, 96, 97, 98, 99, 2003 by Ralf Baechle
7 * Copyright (C) 1996 by Paul M. Antoine
8 * Copyright (C) 1999 Silicon Graphics
9 * Copyright (C) 2000 MIPS Technologies, Inc.
10 */
11#ifndef _ASM_INTERRUPT_H
12#define _ASM_INTERRUPT_H
13
Ralf Baechleff88f8a2005-07-12 14:54:31 +000014#include <linux/config.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070015#include <asm/hazards.h>
16
17__asm__ (
Ralf Baechleff88f8a2005-07-12 14:54:31 +000018 " .macro local_irq_enable \n"
19 " .set push \n"
20 " .set reorder \n"
21 " .set noat \n"
Ralf Baechle41c594a2006-04-05 09:45:45 +010022#ifdef CONFIG_MIPS_MT_SMTC
23 " mfc0 $1, $2, 1 # SMTC - clear TCStatus.IXMT \n"
24 " ori $1, 0x400 \n"
25 " xori $1, 0x400 \n"
26 " mtc0 $1, $2, 1 \n"
27#elif defined(CONFIG_CPU_MIPSR2)
Ralf Baechleff88f8a2005-07-12 14:54:31 +000028 " ei \n"
29#else
30 " mfc0 $1,$12 \n"
31 " ori $1,0x1f \n"
32 " xori $1,0x1e \n"
33 " mtc0 $1,$12 \n"
34#endif
35 " irq_enable_hazard \n"
36 " .set pop \n"
37 " .endm");
Linus Torvalds1da177e2005-04-16 15:20:36 -070038
39static inline void local_irq_enable(void)
40{
41 __asm__ __volatile__(
42 "local_irq_enable"
43 : /* no outputs */
44 : /* no inputs */
45 : "memory");
46}
47
48/*
49 * For cli() we have to insert nops to make sure that the new value
50 * has actually arrived in the status register before the end of this
51 * macro.
52 * R4000/R4400 need three nops, the R4600 two nops and the R10000 needs
53 * no nops at all.
54 */
Atsushi Nemotoc226f262006-02-03 01:34:01 +090055/*
56 * For TX49, operating only IE bit is not enough.
57 *
58 * If mfc0 $12 follows store and the mfc0 is last instruction of a
59 * page and fetching the next instruction causes TLB miss, the result
60 * of the mfc0 might wrongly contain EXL bit.
61 *
62 * ERT-TX49H2-027, ERT-TX49H3-012, ERT-TX49HL3-006, ERT-TX49H4-008
63 *
64 * Workaround: mask EXL bit of the result or place a nop before mfc0.
65 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070066__asm__ (
Ralf Baechleff88f8a2005-07-12 14:54:31 +000067 " .macro local_irq_disable\n"
68 " .set push \n"
69 " .set noat \n"
Ralf Baechle41c594a2006-04-05 09:45:45 +010070#ifdef CONFIG_MIPS_MT_SMTC
71 " mfc0 $1, $2, 1 \n"
72 " ori $1, 0x400 \n"
73 " .set noreorder \n"
74 " mtc0 $1, $2, 1 \n"
75#elif defined(CONFIG_CPU_MIPSR2)
Ralf Baechleff88f8a2005-07-12 14:54:31 +000076 " di \n"
77#else
78 " mfc0 $1,$12 \n"
Atsushi Nemotoc226f262006-02-03 01:34:01 +090079 " ori $1,0x1f \n"
80 " xori $1,0x1f \n"
Ralf Baechleff88f8a2005-07-12 14:54:31 +000081 " .set noreorder \n"
82 " mtc0 $1,$12 \n"
83#endif
84 " irq_disable_hazard \n"
85 " .set pop \n"
86 " .endm \n");
Linus Torvalds1da177e2005-04-16 15:20:36 -070087
88static inline void local_irq_disable(void)
89{
90 __asm__ __volatile__(
91 "local_irq_disable"
92 : /* no outputs */
93 : /* no inputs */
94 : "memory");
95}
96
97__asm__ (
Ralf Baechleff88f8a2005-07-12 14:54:31 +000098 " .macro local_save_flags flags \n"
99 " .set push \n"
100 " .set reorder \n"
Ralf Baechle41c594a2006-04-05 09:45:45 +0100101#ifdef CONFIG_MIPS_MT_SMTC
102 " mfc0 \\flags, $2, 1 \n"
103#else
Ralf Baechleff88f8a2005-07-12 14:54:31 +0000104 " mfc0 \\flags, $12 \n"
Ralf Baechle41c594a2006-04-05 09:45:45 +0100105#endif
Ralf Baechleff88f8a2005-07-12 14:54:31 +0000106 " .set pop \n"
107 " .endm \n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108
109#define local_save_flags(x) \
110__asm__ __volatile__( \
111 "local_save_flags %0" \
112 : "=r" (x))
113
114__asm__ (
Ralf Baechleff88f8a2005-07-12 14:54:31 +0000115 " .macro local_irq_save result \n"
116 " .set push \n"
117 " .set reorder \n"
118 " .set noat \n"
Ralf Baechle41c594a2006-04-05 09:45:45 +0100119#ifdef CONFIG_MIPS_MT_SMTC
120 " mfc0 \\result, $2, 1 \n"
121 " ori $1, \\result, 0x400 \n"
122 " .set noreorder \n"
123 " mtc0 $1, $2, 1 \n"
124 " andi \\result, \\result, 0x400 \n"
125#elif defined(CONFIG_CPU_MIPSR2)
Ralf Baechleff88f8a2005-07-12 14:54:31 +0000126 " di \\result \n"
Maxime Bizon15265252005-12-20 06:32:19 +0100127 " andi \\result, 1 \n"
Ralf Baechleff88f8a2005-07-12 14:54:31 +0000128#else
129 " mfc0 \\result, $12 \n"
Atsushi Nemotoc226f262006-02-03 01:34:01 +0900130 " ori $1, \\result, 0x1f \n"
131 " xori $1, 0x1f \n"
Ralf Baechleff88f8a2005-07-12 14:54:31 +0000132 " .set noreorder \n"
133 " mtc0 $1, $12 \n"
134#endif
135 " irq_disable_hazard \n"
136 " .set pop \n"
137 " .endm \n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138
139#define local_irq_save(x) \
140__asm__ __volatile__( \
141 "local_irq_save\t%0" \
142 : "=r" (x) \
143 : /* no inputs */ \
144 : "memory")
145
146__asm__ (
Ralf Baechleff88f8a2005-07-12 14:54:31 +0000147 " .macro local_irq_restore flags \n"
Ralf Baechle2e66fe22006-01-30 16:48:26 +0000148 " .set push \n"
Ralf Baechleff88f8a2005-07-12 14:54:31 +0000149 " .set noreorder \n"
150 " .set noat \n"
Ralf Baechle41c594a2006-04-05 09:45:45 +0100151#ifdef CONFIG_MIPS_MT_SMTC
152 "mfc0 $1, $2, 1 \n"
153 "andi \\flags, 0x400 \n"
154 "ori $1, 0x400 \n"
155 "xori $1, 0x400 \n"
156 "or \\flags, $1 \n"
157 "mtc0 \\flags, $2, 1 \n"
158#elif defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU)
Ralf Baechleff88f8a2005-07-12 14:54:31 +0000159 /*
160 * Slow, but doesn't suffer from a relativly unlikely race
161 * condition we're having since days 1.
162 */
163 " beqz \\flags, 1f \n"
164 " di \n"
165 " ei \n"
166 "1: \n"
Ralf Baechleec917c2c2005-10-07 16:58:15 +0100167#elif defined(CONFIG_CPU_MIPSR2)
Ralf Baechleff88f8a2005-07-12 14:54:31 +0000168 /*
169 * Fast, dangerous. Life is fun, life is good.
170 */
171 " mfc0 $1, $12 \n"
172 " ins $1, \\flags, 0, 1 \n"
173 " mtc0 $1, $12 \n"
174#else
175 " mfc0 $1, $12 \n"
176 " andi \\flags, 1 \n"
Atsushi Nemotoc226f262006-02-03 01:34:01 +0900177 " ori $1, 0x1f \n"
178 " xori $1, 0x1f \n"
Ralf Baechleff88f8a2005-07-12 14:54:31 +0000179 " or \\flags, $1 \n"
180 " mtc0 \\flags, $12 \n"
181#endif
182 " irq_disable_hazard \n"
Ralf Baechle2e66fe22006-01-30 16:48:26 +0000183 " .set pop \n"
Ralf Baechleff88f8a2005-07-12 14:54:31 +0000184 " .endm \n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185
186#define local_irq_restore(flags) \
187do { \
188 unsigned long __tmp1; \
189 \
190 __asm__ __volatile__( \
191 "local_irq_restore\t%0" \
192 : "=r" (__tmp1) \
193 : "0" (flags) \
194 : "memory"); \
195} while(0)
196
Ralf Baechle41c594a2006-04-05 09:45:45 +0100197static inline int irqs_disabled(void)
198{
199#ifdef CONFIG_MIPS_MT_SMTC
200 /*
201 * SMTC model uses TCStatus.IXMT to disable interrupts for a thread/CPU
202 */
203 unsigned long __result;
204
205 __asm__ __volatile__(
206 " .set noreorder \n"
207 " mfc0 %0, $2, 1 \n"
208 " andi %0, 0x400 \n"
209 " slt %0, $0, %0 \n"
210 " .set reorder \n"
211 : "=r" (__result));
212
213 return __result;
214#else
215 unsigned long flags;
216 local_save_flags(flags);
217
218 return !(flags & 1);
219#endif
220}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221
222#endif /* _ASM_INTERRUPT_H */