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 */ | |
28 | ||
29 | #endif /* CONFIG_PPC64 */ | |
30 | ||
31 | #ifndef __ASSEMBLY__ | |
32 | ||
33 | extern void __replay_interrupt(unsigned int vector); | |
34 | ||
c7aeffc4 | 35 | extern void timer_interrupt(struct pt_regs *); |
7cc1e8ee | 36 | extern void performance_monitor_exception(struct pt_regs *regs); |
6328e593 BB |
37 | extern void WatchdogException(struct pt_regs *regs); |
38 | extern void unknown_exception(struct pt_regs *regs); | |
1da177e4 | 39 | |
d04c56f7 PM |
40 | #ifdef CONFIG_PPC64 |
41 | #include <asm/paca.h> | |
42 | ||
df9ee292 | 43 | static inline unsigned long arch_local_save_flags(void) |
d04c56f7 | 44 | { |
ef2b343e HD |
45 | unsigned long flags; |
46 | ||
df9ee292 DH |
47 | asm volatile( |
48 | "lbz %0,%1(13)" | |
49 | : "=r" (flags) | |
50 | : "i" (offsetof(struct paca_struct, soft_enabled))); | |
ef2b343e HD |
51 | |
52 | return flags; | |
d04c56f7 PM |
53 | } |
54 | ||
df9ee292 | 55 | static inline unsigned long arch_local_irq_disable(void) |
d04c56f7 | 56 | { |
ef2b343e HD |
57 | unsigned long flags, zero; |
58 | ||
df9ee292 DH |
59 | asm volatile( |
60 | "li %1,0; lbz %0,%2(13); stb %1,%2(13)" | |
61 | : "=r" (flags), "=&r" (zero) | |
62 | : "i" (offsetof(struct paca_struct, soft_enabled)) | |
63 | : "memory"); | |
ef2b343e HD |
64 | |
65 | return flags; | |
d04c56f7 | 66 | } |
1da177e4 | 67 | |
df9ee292 | 68 | extern void arch_local_irq_restore(unsigned long); |
1da177e4 | 69 | |
df9ee292 DH |
70 | static inline void arch_local_irq_enable(void) |
71 | { | |
72 | arch_local_irq_restore(1); | |
73 | } | |
74 | ||
75 | static inline unsigned long arch_local_irq_save(void) | |
76 | { | |
77 | return arch_local_irq_disable(); | |
78 | } | |
79 | ||
80 | static inline bool arch_irqs_disabled_flags(unsigned long flags) | |
81 | { | |
82 | return flags == 0; | |
83 | } | |
1da177e4 | 84 | |
df9ee292 DH |
85 | static inline bool arch_irqs_disabled(void) |
86 | { | |
87 | return arch_irqs_disabled_flags(arch_local_save_flags()); | |
88 | } | |
1da177e4 | 89 | |
2d27cfd3 | 90 | #ifdef CONFIG_PPC_BOOK3E |
21b2de34 BH |
91 | #define __hard_irq_enable() asm volatile("wrteei 1" : : : "memory") |
92 | #define __hard_irq_disable() asm volatile("wrteei 0" : : : "memory") | |
2d27cfd3 | 93 | #else |
d9ada91a BH |
94 | #define __hard_irq_enable() __mtmsrd(local_paca->kernel_msr | MSR_EE, 1) |
95 | #define __hard_irq_disable() __mtmsrd(local_paca->kernel_msr, 1) | |
2d27cfd3 | 96 | #endif |
e1fa2e13 | 97 | |
5737789c | 98 | #define hard_irq_disable() do { \ |
4a3b8d0b | 99 | u8 _was_enabled = get_paca()->soft_enabled; \ |
5737789c | 100 | __hard_irq_disable(); \ |
5737789c BH |
101 | get_paca()->soft_enabled = 0; \ |
102 | get_paca()->irq_happened |= PACA_IRQ_HARD_DIS; \ | |
4a3b8d0b SW |
103 | if (_was_enabled) \ |
104 | trace_hardirqs_off(); \ | |
5737789c | 105 | } while(0) |
f948501b | 106 | |
0b17ba72 AB |
107 | static inline bool lazy_irq_pending(void) |
108 | { | |
109 | return !!(get_paca()->irq_happened & ~PACA_IRQ_HARD_DIS); | |
110 | } | |
111 | ||
7230c564 BH |
112 | /* |
113 | * This is called by asynchronous interrupts to conditionally | |
114 | * re-enable hard interrupts when soft-disabled after having | |
115 | * cleared the source of the interrupt | |
116 | */ | |
117 | static inline void may_hard_irq_enable(void) | |
118 | { | |
119 | get_paca()->irq_happened &= ~PACA_IRQ_HARD_DIS; | |
120 | if (!(get_paca()->irq_happened & PACA_IRQ_EE)) | |
121 | __hard_irq_enable(); | |
122 | } | |
d04c56f7 | 123 | |
a546498f BH |
124 | static inline bool arch_irq_disabled_regs(struct pt_regs *regs) |
125 | { | |
126 | return !regs->softe; | |
127 | } | |
128 | ||
be2cf20a BH |
129 | extern bool prep_irq_for_idle(void); |
130 | ||
df9ee292 | 131 | #else /* CONFIG_PPC64 */ |
1da177e4 | 132 | |
b671ad2b | 133 | #define SET_MSR_EE(x) mtmsr(x) |
df9ee292 DH |
134 | |
135 | static inline unsigned long arch_local_save_flags(void) | |
136 | { | |
137 | return mfmsr(); | |
138 | } | |
139 | ||
140 | static inline void arch_local_irq_restore(unsigned long flags) | |
141 | { | |
142 | #if defined(CONFIG_BOOKE) | |
143 | asm volatile("wrtee %0" : : "r" (flags) : "memory"); | |
b671ad2b | 144 | #else |
df9ee292 | 145 | mtmsr(flags); |
b671ad2b | 146 | #endif |
df9ee292 | 147 | } |
1da177e4 | 148 | |
df9ee292 | 149 | static inline unsigned long arch_local_irq_save(void) |
1da177e4 | 150 | { |
df9ee292 | 151 | unsigned long flags = arch_local_save_flags(); |
b671ad2b | 152 | #ifdef CONFIG_BOOKE |
df9ee292 | 153 | asm volatile("wrteei 0" : : : "memory"); |
b671ad2b | 154 | #else |
df9ee292 | 155 | SET_MSR_EE(flags & ~MSR_EE); |
b671ad2b | 156 | #endif |
df9ee292 | 157 | return flags; |
1da177e4 LT |
158 | } |
159 | ||
df9ee292 | 160 | static inline void arch_local_irq_disable(void) |
1da177e4 | 161 | { |
b671ad2b | 162 | #ifdef CONFIG_BOOKE |
df9ee292 | 163 | asm volatile("wrteei 0" : : : "memory"); |
b671ad2b | 164 | #else |
df9ee292 | 165 | arch_local_irq_save(); |
b671ad2b | 166 | #endif |
1da177e4 LT |
167 | } |
168 | ||
df9ee292 | 169 | static inline void arch_local_irq_enable(void) |
1da177e4 | 170 | { |
b671ad2b | 171 | #ifdef CONFIG_BOOKE |
df9ee292 | 172 | asm volatile("wrteei 1" : : : "memory"); |
b671ad2b | 173 | #else |
df9ee292 DH |
174 | unsigned long msr = mfmsr(); |
175 | SET_MSR_EE(msr | MSR_EE); | |
b671ad2b | 176 | #endif |
1da177e4 LT |
177 | } |
178 | ||
df9ee292 | 179 | static inline bool arch_irqs_disabled_flags(unsigned long flags) |
e0eca07b SR |
180 | { |
181 | return (flags & MSR_EE) == 0; | |
182 | } | |
183 | ||
df9ee292 DH |
184 | static inline bool arch_irqs_disabled(void) |
185 | { | |
186 | return arch_irqs_disabled_flags(arch_local_save_flags()); | |
187 | } | |
188 | ||
189 | #define hard_irq_disable() arch_local_irq_disable() | |
190 | ||
a546498f BH |
191 | static inline bool arch_irq_disabled_regs(struct pt_regs *regs) |
192 | { | |
193 | return !(regs->msr & MSR_EE); | |
194 | } | |
195 | ||
7230c564 BH |
196 | static inline void may_hard_irq_enable(void) { } |
197 | ||
d04c56f7 | 198 | #endif /* CONFIG_PPC64 */ |
1da177e4 | 199 | |
089fb442 TG |
200 | #define ARCH_IRQ_INIT_FLAGS IRQ_NOREQUEST |
201 | ||
c0ad90a3 IM |
202 | /* |
203 | * interrupt-retrigger: should we handle this via lost interrupts and IPIs | |
204 | * or should we not care like we do now ? --BenH. | |
1da177e4 | 205 | */ |
353bca5e | 206 | struct irq_chip; |
b671ad2b | 207 | |
7230c564 | 208 | #endif /* __ASSEMBLY__ */ |
b671ad2b KG |
209 | #endif /* __KERNEL__ */ |
210 | #endif /* _ASM_POWERPC_HW_IRQ_H */ |