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 | |
7230c564 BH |
98 | static inline void hard_irq_disable(void) |
99 | { | |
100 | __hard_irq_disable(); | |
101 | get_paca()->soft_enabled = 0; | |
102 | get_paca()->irq_happened |= PACA_IRQ_HARD_DIS; | |
103 | } | |
104 | ||
f948501b PM |
105 | /* include/linux/interrupt.h needs hard_irq_disable to be a macro */ |
106 | #define hard_irq_disable hard_irq_disable | |
107 | ||
0b17ba72 AB |
108 | static inline bool lazy_irq_pending(void) |
109 | { | |
110 | return !!(get_paca()->irq_happened & ~PACA_IRQ_HARD_DIS); | |
111 | } | |
112 | ||
7230c564 BH |
113 | /* |
114 | * This is called by asynchronous interrupts to conditionally | |
115 | * re-enable hard interrupts when soft-disabled after having | |
116 | * cleared the source of the interrupt | |
117 | */ | |
118 | static inline void may_hard_irq_enable(void) | |
119 | { | |
120 | get_paca()->irq_happened &= ~PACA_IRQ_HARD_DIS; | |
121 | if (!(get_paca()->irq_happened & PACA_IRQ_EE)) | |
122 | __hard_irq_enable(); | |
123 | } | |
d04c56f7 | 124 | |
a546498f BH |
125 | static inline bool arch_irq_disabled_regs(struct pt_regs *regs) |
126 | { | |
127 | return !regs->softe; | |
128 | } | |
129 | ||
be2cf20a BH |
130 | extern bool prep_irq_for_idle(void); |
131 | ||
df9ee292 | 132 | #else /* CONFIG_PPC64 */ |
1da177e4 | 133 | |
b671ad2b | 134 | #define SET_MSR_EE(x) mtmsr(x) |
df9ee292 DH |
135 | |
136 | static inline unsigned long arch_local_save_flags(void) | |
137 | { | |
138 | return mfmsr(); | |
139 | } | |
140 | ||
141 | static inline void arch_local_irq_restore(unsigned long flags) | |
142 | { | |
143 | #if defined(CONFIG_BOOKE) | |
144 | asm volatile("wrtee %0" : : "r" (flags) : "memory"); | |
b671ad2b | 145 | #else |
df9ee292 | 146 | mtmsr(flags); |
b671ad2b | 147 | #endif |
df9ee292 | 148 | } |
1da177e4 | 149 | |
df9ee292 | 150 | static inline unsigned long arch_local_irq_save(void) |
1da177e4 | 151 | { |
df9ee292 | 152 | unsigned long flags = arch_local_save_flags(); |
b671ad2b | 153 | #ifdef CONFIG_BOOKE |
df9ee292 | 154 | asm volatile("wrteei 0" : : : "memory"); |
b671ad2b | 155 | #else |
df9ee292 | 156 | SET_MSR_EE(flags & ~MSR_EE); |
b671ad2b | 157 | #endif |
df9ee292 | 158 | return flags; |
1da177e4 LT |
159 | } |
160 | ||
df9ee292 | 161 | static inline void arch_local_irq_disable(void) |
1da177e4 | 162 | { |
b671ad2b | 163 | #ifdef CONFIG_BOOKE |
df9ee292 | 164 | asm volatile("wrteei 0" : : : "memory"); |
b671ad2b | 165 | #else |
df9ee292 | 166 | arch_local_irq_save(); |
b671ad2b | 167 | #endif |
1da177e4 LT |
168 | } |
169 | ||
df9ee292 | 170 | static inline void arch_local_irq_enable(void) |
1da177e4 | 171 | { |
b671ad2b | 172 | #ifdef CONFIG_BOOKE |
df9ee292 | 173 | asm volatile("wrteei 1" : : : "memory"); |
b671ad2b | 174 | #else |
df9ee292 DH |
175 | unsigned long msr = mfmsr(); |
176 | SET_MSR_EE(msr | MSR_EE); | |
b671ad2b | 177 | #endif |
1da177e4 LT |
178 | } |
179 | ||
df9ee292 | 180 | static inline bool arch_irqs_disabled_flags(unsigned long flags) |
e0eca07b SR |
181 | { |
182 | return (flags & MSR_EE) == 0; | |
183 | } | |
184 | ||
df9ee292 DH |
185 | static inline bool arch_irqs_disabled(void) |
186 | { | |
187 | return arch_irqs_disabled_flags(arch_local_save_flags()); | |
188 | } | |
189 | ||
190 | #define hard_irq_disable() arch_local_irq_disable() | |
191 | ||
a546498f BH |
192 | static inline bool arch_irq_disabled_regs(struct pt_regs *regs) |
193 | { | |
194 | return !(regs->msr & MSR_EE); | |
195 | } | |
196 | ||
7230c564 BH |
197 | static inline void may_hard_irq_enable(void) { } |
198 | ||
d04c56f7 | 199 | #endif /* CONFIG_PPC64 */ |
1da177e4 | 200 | |
089fb442 TG |
201 | #define ARCH_IRQ_INIT_FLAGS IRQ_NOREQUEST |
202 | ||
c0ad90a3 IM |
203 | /* |
204 | * interrupt-retrigger: should we handle this via lost interrupts and IPIs | |
205 | * or should we not care like we do now ? --BenH. | |
1da177e4 | 206 | */ |
353bca5e | 207 | struct irq_chip; |
b671ad2b | 208 | |
7230c564 | 209 | #endif /* __ASSEMBLY__ */ |
b671ad2b KG |
210 | #endif /* __KERNEL__ */ |
211 | #endif /* _ASM_POWERPC_HW_IRQ_H */ |