]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu> | |
1da177e4 | 3 | */ |
b671ad2b KG |
4 | #ifndef _ASM_POWERPC_HW_IRQ_H |
5 | #define _ASM_POWERPC_HW_IRQ_H | |
6 | ||
1da177e4 | 7 | #ifdef __KERNEL__ |
1da177e4 | 8 | |
1da177e4 | 9 | #include <linux/errno.h> |
d04c56f7 | 10 | #include <linux/compiler.h> |
b671ad2b KG |
11 | #include <asm/ptrace.h> |
12 | #include <asm/processor.h> | |
1da177e4 | 13 | |
7230c564 BH |
14 | #ifdef CONFIG_PPC64 |
15 | ||
16 | /* | |
17 | * PACA flags in paca->irq_happened. | |
18 | * | |
19 | * This bits are set when interrupts occur while soft-disabled | |
20 | * and allow a proper replay. Additionally, PACA_IRQ_HARD_DIS | |
21 | * is set whenever we manually hard disable. | |
22 | */ | |
23 | #define PACA_IRQ_HARD_DIS 0x01 | |
24 | #define PACA_IRQ_DBELL 0x02 | |
25 | #define PACA_IRQ_EE 0x04 | |
26 | #define PACA_IRQ_DEC 0x08 /* Or FIT */ | |
27 | #define PACA_IRQ_EE_EDGE 0x10 /* BookE only */ | |
0869b6fd | 28 | #define PACA_IRQ_HMI 0x20 |
7230c564 BH |
29 | |
30 | #endif /* CONFIG_PPC64 */ | |
31 | ||
32 | #ifndef __ASSEMBLY__ | |
33 | ||
34 | extern void __replay_interrupt(unsigned int vector); | |
35 | ||
c7aeffc4 | 36 | extern void timer_interrupt(struct pt_regs *); |
7cc1e8ee | 37 | extern void performance_monitor_exception(struct pt_regs *regs); |
6328e593 BB |
38 | extern void WatchdogException(struct pt_regs *regs); |
39 | extern void unknown_exception(struct pt_regs *regs); | |
1da177e4 | 40 | |
d04c56f7 PM |
41 | #ifdef CONFIG_PPC64 |
42 | #include <asm/paca.h> | |
43 | ||
df9ee292 | 44 | static inline unsigned long arch_local_save_flags(void) |
d04c56f7 | 45 | { |
ef2b343e HD |
46 | unsigned long flags; |
47 | ||
df9ee292 DH |
48 | asm volatile( |
49 | "lbz %0,%1(13)" | |
50 | : "=r" (flags) | |
51 | : "i" (offsetof(struct paca_struct, soft_enabled))); | |
ef2b343e HD |
52 | |
53 | return flags; | |
d04c56f7 PM |
54 | } |
55 | ||
df9ee292 | 56 | static inline unsigned long arch_local_irq_disable(void) |
d04c56f7 | 57 | { |
ef2b343e HD |
58 | unsigned long flags, zero; |
59 | ||
df9ee292 DH |
60 | asm volatile( |
61 | "li %1,0; lbz %0,%2(13); stb %1,%2(13)" | |
62 | : "=r" (flags), "=&r" (zero) | |
63 | : "i" (offsetof(struct paca_struct, soft_enabled)) | |
64 | : "memory"); | |
ef2b343e HD |
65 | |
66 | return flags; | |
d04c56f7 | 67 | } |
1da177e4 | 68 | |
df9ee292 | 69 | extern void arch_local_irq_restore(unsigned long); |
1da177e4 | 70 | |
df9ee292 DH |
71 | static inline void arch_local_irq_enable(void) |
72 | { | |
73 | arch_local_irq_restore(1); | |
74 | } | |
75 | ||
76 | static inline unsigned long arch_local_irq_save(void) | |
77 | { | |
78 | return arch_local_irq_disable(); | |
79 | } | |
80 | ||
81 | static inline bool arch_irqs_disabled_flags(unsigned long flags) | |
82 | { | |
83 | return flags == 0; | |
84 | } | |
1da177e4 | 85 | |
df9ee292 DH |
86 | static inline bool arch_irqs_disabled(void) |
87 | { | |
88 | return arch_irqs_disabled_flags(arch_local_save_flags()); | |
89 | } | |
1da177e4 | 90 | |
2d27cfd3 | 91 | #ifdef CONFIG_PPC_BOOK3E |
21b2de34 BH |
92 | #define __hard_irq_enable() asm volatile("wrteei 1" : : : "memory") |
93 | #define __hard_irq_disable() asm volatile("wrteei 0" : : : "memory") | |
2d27cfd3 | 94 | #else |
d9ada91a BH |
95 | #define __hard_irq_enable() __mtmsrd(local_paca->kernel_msr | MSR_EE, 1) |
96 | #define __hard_irq_disable() __mtmsrd(local_paca->kernel_msr, 1) | |
2d27cfd3 | 97 | #endif |
e1fa2e13 | 98 | |
5737789c | 99 | #define hard_irq_disable() do { \ |
0b88f772 | 100 | u8 _was_enabled; \ |
5737789c | 101 | __hard_irq_disable(); \ |
0b88f772 TC |
102 | _was_enabled = local_paca->soft_enabled; \ |
103 | local_paca->soft_enabled = 0; \ | |
104 | local_paca->irq_happened |= PACA_IRQ_HARD_DIS; \ | |
4a3b8d0b SW |
105 | if (_was_enabled) \ |
106 | trace_hardirqs_off(); \ | |
5737789c | 107 | } while(0) |
f948501b | 108 | |
0b17ba72 AB |
109 | static inline bool lazy_irq_pending(void) |
110 | { | |
111 | return !!(get_paca()->irq_happened & ~PACA_IRQ_HARD_DIS); | |
112 | } | |
113 | ||
7230c564 BH |
114 | /* |
115 | * This is called by asynchronous interrupts to conditionally | |
116 | * re-enable hard interrupts when soft-disabled after having | |
117 | * cleared the source of the interrupt | |
118 | */ | |
119 | static inline void may_hard_irq_enable(void) | |
120 | { | |
121 | get_paca()->irq_happened &= ~PACA_IRQ_HARD_DIS; | |
122 | if (!(get_paca()->irq_happened & PACA_IRQ_EE)) | |
123 | __hard_irq_enable(); | |
124 | } | |
d04c56f7 | 125 | |
a546498f BH |
126 | static inline bool arch_irq_disabled_regs(struct pt_regs *regs) |
127 | { | |
128 | return !regs->softe; | |
129 | } | |
130 | ||
be2cf20a BH |
131 | extern bool prep_irq_for_idle(void); |
132 | ||
1d607bb3 BH |
133 | extern void force_external_irq_replay(void); |
134 | ||
df9ee292 | 135 | #else /* CONFIG_PPC64 */ |
1da177e4 | 136 | |
b671ad2b | 137 | #define SET_MSR_EE(x) mtmsr(x) |
df9ee292 DH |
138 | |
139 | static inline unsigned long arch_local_save_flags(void) | |
140 | { | |
141 | return mfmsr(); | |
142 | } | |
143 | ||
144 | static inline void arch_local_irq_restore(unsigned long flags) | |
145 | { | |
146 | #if defined(CONFIG_BOOKE) | |
147 | asm volatile("wrtee %0" : : "r" (flags) : "memory"); | |
b671ad2b | 148 | #else |
df9ee292 | 149 | mtmsr(flags); |
b671ad2b | 150 | #endif |
df9ee292 | 151 | } |
1da177e4 | 152 | |
df9ee292 | 153 | static inline unsigned long arch_local_irq_save(void) |
1da177e4 | 154 | { |
df9ee292 | 155 | unsigned long flags = arch_local_save_flags(); |
b671ad2b | 156 | #ifdef CONFIG_BOOKE |
df9ee292 | 157 | asm volatile("wrteei 0" : : : "memory"); |
834e5a69 CL |
158 | #elif defined(CONFIG_PPC_8xx) |
159 | wrtspr(SPRN_EID); | |
b671ad2b | 160 | #else |
df9ee292 | 161 | SET_MSR_EE(flags & ~MSR_EE); |
b671ad2b | 162 | #endif |
df9ee292 | 163 | return flags; |
1da177e4 LT |
164 | } |
165 | ||
df9ee292 | 166 | static inline void arch_local_irq_disable(void) |
1da177e4 | 167 | { |
b671ad2b | 168 | #ifdef CONFIG_BOOKE |
df9ee292 | 169 | asm volatile("wrteei 0" : : : "memory"); |
834e5a69 CL |
170 | #elif defined(CONFIG_PPC_8xx) |
171 | wrtspr(SPRN_EID); | |
b671ad2b | 172 | #else |
df9ee292 | 173 | arch_local_irq_save(); |
b671ad2b | 174 | #endif |
1da177e4 LT |
175 | } |
176 | ||
df9ee292 | 177 | static inline void arch_local_irq_enable(void) |
1da177e4 | 178 | { |
b671ad2b | 179 | #ifdef CONFIG_BOOKE |
df9ee292 | 180 | asm volatile("wrteei 1" : : : "memory"); |
834e5a69 CL |
181 | #elif defined(CONFIG_PPC_8xx) |
182 | wrtspr(SPRN_EIE); | |
b671ad2b | 183 | #else |
df9ee292 DH |
184 | unsigned long msr = mfmsr(); |
185 | SET_MSR_EE(msr | MSR_EE); | |
b671ad2b | 186 | #endif |
1da177e4 LT |
187 | } |
188 | ||
df9ee292 | 189 | static inline bool arch_irqs_disabled_flags(unsigned long flags) |
e0eca07b SR |
190 | { |
191 | return (flags & MSR_EE) == 0; | |
192 | } | |
193 | ||
df9ee292 DH |
194 | static inline bool arch_irqs_disabled(void) |
195 | { | |
196 | return arch_irqs_disabled_flags(arch_local_save_flags()); | |
197 | } | |
198 | ||
199 | #define hard_irq_disable() arch_local_irq_disable() | |
200 | ||
a546498f BH |
201 | static inline bool arch_irq_disabled_regs(struct pt_regs *regs) |
202 | { | |
203 | return !(regs->msr & MSR_EE); | |
204 | } | |
205 | ||
7230c564 BH |
206 | static inline void may_hard_irq_enable(void) { } |
207 | ||
d04c56f7 | 208 | #endif /* CONFIG_PPC64 */ |
1da177e4 | 209 | |
089fb442 TG |
210 | #define ARCH_IRQ_INIT_FLAGS IRQ_NOREQUEST |
211 | ||
c0ad90a3 IM |
212 | /* |
213 | * interrupt-retrigger: should we handle this via lost interrupts and IPIs | |
214 | * or should we not care like we do now ? --BenH. | |
1da177e4 | 215 | */ |
353bca5e | 216 | struct irq_chip; |
b671ad2b | 217 | |
7230c564 | 218 | #endif /* __ASSEMBLY__ */ |
b671ad2b KG |
219 | #endif /* __KERNEL__ */ |
220 | #endif /* _ASM_POWERPC_HW_IRQ_H */ |