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