Pull acpi_os_allocate into test branch
[pandora-kernel.git] / include / asm-mips / interrupt.h
1 /*
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
14 #include <asm/hazards.h>
15
16 __asm__ (
17         "       .macro  local_irq_enable                                \n"
18         "       .set    push                                            \n"
19         "       .set    reorder                                         \n"
20         "       .set    noat                                            \n"
21 #ifdef CONFIG_MIPS_MT_SMTC
22         "       mfc0    $1, $2, 1       # SMTC - clear TCStatus.IXMT    \n"
23         "       ori     $1, 0x400                                       \n"
24         "       xori    $1, 0x400                                       \n"
25         "       mtc0    $1, $2, 1                                       \n"
26 #elif defined(CONFIG_CPU_MIPSR2)
27         "       ei                                                      \n"
28 #else
29         "       mfc0    $1,$12                                          \n"
30         "       ori     $1,0x1f                                         \n"
31         "       xori    $1,0x1e                                         \n"
32         "       mtc0    $1,$12                                          \n"
33 #endif
34         "       irq_enable_hazard                                       \n"
35         "       .set    pop                                             \n"
36         "       .endm");
37
38 static inline void local_irq_enable(void)
39 {
40         __asm__ __volatile__(
41                 "local_irq_enable"
42                 : /* no outputs */
43                 : /* no inputs */
44                 : "memory");
45 }
46
47 /*
48  * For cli() we have to insert nops to make sure that the new value
49  * has actually arrived in the status register before the end of this
50  * macro.
51  * R4000/R4400 need three nops, the R4600 two nops and the R10000 needs
52  * no nops at all.
53  */
54 /*
55  * For TX49, operating only IE bit is not enough.
56  *
57  * If mfc0 $12 follows store and the mfc0 is last instruction of a
58  * page and fetching the next instruction causes TLB miss, the result
59  * of the mfc0 might wrongly contain EXL bit.
60  *
61  * ERT-TX49H2-027, ERT-TX49H3-012, ERT-TX49HL3-006, ERT-TX49H4-008
62  *
63  * Workaround: mask EXL bit of the result or place a nop before mfc0.
64  */
65 __asm__ (
66         "       .macro  local_irq_disable\n"
67         "       .set    push                                            \n"
68         "       .set    noat                                            \n"
69 #ifdef CONFIG_MIPS_MT_SMTC
70         "       mfc0    $1, $2, 1                                       \n"
71         "       ori     $1, 0x400                                       \n"
72         "       .set    noreorder                                       \n"
73         "       mtc0    $1, $2, 1                                       \n"
74 #elif defined(CONFIG_CPU_MIPSR2)
75         "       di                                                      \n"
76 #else
77         "       mfc0    $1,$12                                          \n"
78         "       ori     $1,0x1f                                         \n"
79         "       xori    $1,0x1f                                         \n"
80         "       .set    noreorder                                       \n"
81         "       mtc0    $1,$12                                          \n"
82 #endif
83         "       irq_disable_hazard                                      \n"
84         "       .set    pop                                             \n"
85         "       .endm                                                   \n");
86
87 static inline void local_irq_disable(void)
88 {
89         __asm__ __volatile__(
90                 "local_irq_disable"
91                 : /* no outputs */
92                 : /* no inputs */
93                 : "memory");
94 }
95
96 __asm__ (
97         "       .macro  local_save_flags flags                          \n"
98         "       .set    push                                            \n"
99         "       .set    reorder                                         \n"
100 #ifdef CONFIG_MIPS_MT_SMTC
101         "       mfc0    \\flags, $2, 1                                  \n"
102 #else
103         "       mfc0    \\flags, $12                                    \n"
104 #endif
105         "       .set    pop                                             \n"
106         "       .endm                                                   \n");
107
108 #define local_save_flags(x)                                             \
109 __asm__ __volatile__(                                                   \
110         "local_save_flags %0"                                           \
111         : "=r" (x))
112
113 __asm__ (
114         "       .macro  local_irq_save result                           \n"
115         "       .set    push                                            \n"
116         "       .set    reorder                                         \n"
117         "       .set    noat                                            \n"
118 #ifdef CONFIG_MIPS_MT_SMTC
119         "       mfc0    \\result, $2, 1                                 \n"
120         "       ori     $1, \\result, 0x400                             \n"
121         "       .set    noreorder                                       \n"
122         "       mtc0    $1, $2, 1                                       \n"
123         "       andi    \\result, \\result, 0x400                       \n"
124 #elif defined(CONFIG_CPU_MIPSR2)
125         "       di      \\result                                        \n"
126         "       andi    \\result, 1                                     \n"
127 #else
128         "       mfc0    \\result, $12                                   \n"
129         "       ori     $1, \\result, 0x1f                              \n"
130         "       xori    $1, 0x1f                                        \n"
131         "       .set    noreorder                                       \n"
132         "       mtc0    $1, $12                                         \n"
133 #endif
134         "       irq_disable_hazard                                      \n"
135         "       .set    pop                                             \n"
136         "       .endm                                                   \n");
137
138 #define local_irq_save(x)                                               \
139 __asm__ __volatile__(                                                   \
140         "local_irq_save\t%0"                                            \
141         : "=r" (x)                                                      \
142         : /* no inputs */                                               \
143         : "memory")
144
145 __asm__ (
146         "       .macro  local_irq_restore flags                         \n"
147         "       .set    push                                            \n"
148         "       .set    noreorder                                       \n"
149         "       .set    noat                                            \n"
150 #ifdef CONFIG_MIPS_MT_SMTC
151         "mfc0   $1, $2, 1                                               \n"
152         "andi   \\flags, 0x400                                          \n"
153         "ori    $1, 0x400                                               \n"
154         "xori   $1, 0x400                                               \n"
155         "or     \\flags, $1                                             \n"
156         "mtc0   \\flags, $2, 1                                          \n"
157 #elif defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU)
158         /*
159          * Slow, but doesn't suffer from a relativly unlikely race
160          * condition we're having since days 1.
161          */
162         "       beqz    \\flags, 1f                                     \n"
163         "        di                                                     \n"
164         "       ei                                                      \n"
165         "1:                                                             \n"
166 #elif defined(CONFIG_CPU_MIPSR2)
167         /*
168          * Fast, dangerous.  Life is fun, life is good.
169          */
170         "       mfc0    $1, $12                                         \n"
171         "       ins     $1, \\flags, 0, 1                               \n"
172         "       mtc0    $1, $12                                         \n"
173 #else
174         "       mfc0    $1, $12                                         \n"
175         "       andi    \\flags, 1                                      \n"
176         "       ori     $1, 0x1f                                        \n"
177         "       xori    $1, 0x1f                                        \n"
178         "       or      \\flags, $1                                     \n"
179         "       mtc0    \\flags, $12                                    \n"
180 #endif
181         "       irq_disable_hazard                                      \n"
182         "       .set    pop                                             \n"
183         "       .endm                                                   \n");
184
185 #define local_irq_restore(flags)                                        \
186 do {                                                                    \
187         unsigned long __tmp1;                                           \
188                                                                         \
189         __asm__ __volatile__(                                           \
190                 "local_irq_restore\t%0"                                 \
191                 : "=r" (__tmp1)                                         \
192                 : "0" (flags)                                           \
193                 : "memory");                                            \
194 } while(0)
195
196 static inline int irqs_disabled(void)
197 {
198 #ifdef CONFIG_MIPS_MT_SMTC
199         /*
200          * SMTC model uses TCStatus.IXMT to disable interrupts for a thread/CPU
201          */
202         unsigned long __result;
203
204         __asm__ __volatile__(
205         "       .set    noreorder                                       \n"
206         "       mfc0    %0, $2, 1                                       \n"
207         "       andi    %0, 0x400                                       \n"
208         "       slt     %0, $0, %0                                      \n"
209         "       .set    reorder                                         \n"
210         : "=r" (__result));
211
212         return __result;
213 #else
214         unsigned long flags;
215         local_save_flags(flags);
216
217         return !(flags & 1);
218 #endif
219 }
220
221 #endif /* _ASM_INTERRUPT_H */