Commit | Line | Data |
---|---|---|
8f86001f MF |
1 | /* |
2 | * interface to Blackfin CEC | |
3 | * | |
4 | * Copyright 2009 Analog Devices Inc. | |
5 | * Licensed under the GPL-2 or later. | |
6 | */ | |
7 | ||
8 | #ifndef __ASM_BFIN_IRQFLAGS_H__ | |
9 | #define __ASM_BFIN_IRQFLAGS_H__ | |
10 | ||
5c74874b DH |
11 | #include <mach/blackfin.h> |
12 | ||
8f86001f MF |
13 | #ifdef CONFIG_SMP |
14 | # include <asm/pda.h> | |
15 | # include <asm/processor.h> | |
8f86001f MF |
16 | # define bfin_irq_flags cpu_pda[blackfin_core_id()].imask |
17 | #else | |
18 | extern unsigned long bfin_irq_flags; | |
19 | #endif | |
20 | ||
a2de3f79 | 21 | static inline notrace void bfin_sti(unsigned long flags) |
8f86001f MF |
22 | { |
23 | asm volatile("sti %0;" : : "d" (flags)); | |
24 | } | |
25 | ||
a2de3f79 | 26 | static inline notrace unsigned long bfin_cli(void) |
8f86001f MF |
27 | { |
28 | unsigned long flags; | |
29 | asm volatile("cli %0;" : "=d" (flags)); | |
30 | return flags; | |
31 | } | |
32 | ||
06ecc190 PG |
33 | #ifdef CONFIG_DEBUG_HWERR |
34 | # define bfin_no_irqs 0x3f | |
35 | #else | |
36 | # define bfin_no_irqs 0x1f | |
37 | #endif | |
38 | ||
3b139cdb DH |
39 | /*****************************************************************************/ |
40 | /* | |
41 | * Hard, untraced CPU interrupt flag manipulation and access. | |
42 | */ | |
a2de3f79 | 43 | static inline notrace void __hard_local_irq_disable(void) |
3b139cdb DH |
44 | { |
45 | bfin_cli(); | |
46 | } | |
06ecc190 | 47 | |
a2de3f79 | 48 | static inline notrace void __hard_local_irq_enable(void) |
3b139cdb DH |
49 | { |
50 | bfin_sti(bfin_irq_flags); | |
51 | } | |
06ecc190 | 52 | |
a2de3f79 | 53 | static inline notrace unsigned long hard_local_save_flags(void) |
06ecc190 | 54 | { |
3b139cdb | 55 | return bfin_read_IMASK(); |
06ecc190 PG |
56 | } |
57 | ||
a2de3f79 | 58 | static inline notrace unsigned long __hard_local_irq_save(void) |
06ecc190 | 59 | { |
3b139cdb DH |
60 | unsigned long flags; |
61 | flags = bfin_cli(); | |
62 | #ifdef CONFIG_DEBUG_HWERR | |
63 | bfin_sti(0x3f); | |
64 | #endif | |
65 | return flags; | |
06ecc190 PG |
66 | } |
67 | ||
a2de3f79 | 68 | static inline notrace int hard_irqs_disabled_flags(unsigned long flags) |
06ecc190 | 69 | { |
4f6b600f SM |
70 | #ifdef CONFIG_BF60x |
71 | return (flags & IMASK_IVG11) == 0; | |
72 | #else | |
3b139cdb | 73 | return (flags & ~0x3f) == 0; |
4f6b600f | 74 | #endif |
06ecc190 PG |
75 | } |
76 | ||
a2de3f79 | 77 | static inline notrace int hard_irqs_disabled(void) |
06ecc190 | 78 | { |
3b139cdb DH |
79 | unsigned long flags = hard_local_save_flags(); |
80 | return hard_irqs_disabled_flags(flags); | |
06ecc190 PG |
81 | } |
82 | ||
a2de3f79 | 83 | static inline notrace void __hard_local_irq_restore(unsigned long flags) |
3b139cdb DH |
84 | { |
85 | if (!hard_irqs_disabled_flags(flags)) | |
86 | __hard_local_irq_enable(); | |
87 | } | |
06ecc190 | 88 | |
3b139cdb DH |
89 | /*****************************************************************************/ |
90 | /* | |
91 | * Interrupt pipe handling. | |
92 | */ | |
93 | #ifdef CONFIG_IPIPE | |
06ecc190 | 94 | |
3b139cdb | 95 | #include <linux/compiler.h> |
3b139cdb | 96 | #include <linux/ipipe_trace.h> |
1353d050 PG |
97 | /* |
98 | * Way too many inter-deps between low-level headers in this port, so | |
99 | * we redeclare the required bits we cannot pick from | |
100 | * <asm/ipipe_base.h> to prevent circular dependencies. | |
101 | */ | |
102 | void __ipipe_stall_root(void); | |
103 | void __ipipe_unstall_root(void); | |
104 | unsigned long __ipipe_test_root(void); | |
105 | unsigned long __ipipe_test_and_stall_root(void); | |
106 | void __ipipe_restore_root(unsigned long flags); | |
107 | ||
108 | #ifdef CONFIG_IPIPE_DEBUG_CONTEXT | |
109 | struct ipipe_domain; | |
110 | extern struct ipipe_domain ipipe_root; | |
111 | void ipipe_check_context(struct ipipe_domain *ipd); | |
112 | #define __check_irqop_context(ipd) ipipe_check_context(&ipipe_root) | |
113 | #else /* !CONFIG_IPIPE_DEBUG_CONTEXT */ | |
114 | #define __check_irqop_context(ipd) do { } while (0) | |
115 | #endif /* !CONFIG_IPIPE_DEBUG_CONTEXT */ | |
06ecc190 | 116 | |
3b139cdb DH |
117 | /* |
118 | * Interrupt pipe interface to linux/irqflags.h. | |
119 | */ | |
a2de3f79 | 120 | static inline notrace void arch_local_irq_disable(void) |
06ecc190 | 121 | { |
1353d050 | 122 | __check_irqop_context(); |
3b139cdb DH |
123 | __ipipe_stall_root(); |
124 | barrier(); | |
06ecc190 PG |
125 | } |
126 | ||
a2de3f79 | 127 | static inline notrace void arch_local_irq_enable(void) |
3b139cdb DH |
128 | { |
129 | barrier(); | |
1353d050 | 130 | __check_irqop_context(); |
3b139cdb DH |
131 | __ipipe_unstall_root(); |
132 | } | |
06ecc190 | 133 | |
a2de3f79 | 134 | static inline notrace unsigned long arch_local_save_flags(void) |
06ecc190 | 135 | { |
3b139cdb | 136 | return __ipipe_test_root() ? bfin_no_irqs : bfin_irq_flags; |
06ecc190 PG |
137 | } |
138 | ||
a2de3f79 | 139 | static inline notrace int arch_irqs_disabled_flags(unsigned long flags) |
3b139cdb DH |
140 | { |
141 | return flags == bfin_no_irqs; | |
142 | } | |
06ecc190 | 143 | |
a2de3f79 | 144 | static inline notrace unsigned long arch_local_irq_save(void) |
3b139cdb | 145 | { |
1353d050 PG |
146 | unsigned long flags; |
147 | ||
148 | __check_irqop_context(); | |
149 | flags = __ipipe_test_and_stall_root() ? bfin_no_irqs : bfin_irq_flags; | |
3b139cdb | 150 | barrier(); |
1353d050 PG |
151 | |
152 | return flags; | |
3b139cdb | 153 | } |
06ecc190 | 154 | |
a2de3f79 | 155 | static inline notrace void arch_local_irq_restore(unsigned long flags) |
8f86001f | 156 | { |
1353d050 PG |
157 | __check_irqop_context(); |
158 | __ipipe_restore_root(flags == bfin_no_irqs); | |
8f86001f | 159 | } |
3b139cdb | 160 | |
a2de3f79 | 161 | static inline notrace unsigned long arch_mangle_irq_bits(int virt, unsigned long real) |
8f86001f | 162 | { |
3b139cdb DH |
163 | /* |
164 | * Merge virtual and real interrupt mask bits into a single | |
165 | * 32bit word. | |
166 | */ | |
167 | return (real & ~(1 << 31)) | ((virt != 0) << 31); | |
8f86001f MF |
168 | } |
169 | ||
a2de3f79 | 170 | static inline notrace int arch_demangle_irq_bits(unsigned long *x) |
5c74874b | 171 | { |
3b139cdb DH |
172 | int virt = (*x & (1 << 31)) != 0; |
173 | *x &= ~(1L << 31); | |
174 | return virt; | |
5c74874b DH |
175 | } |
176 | ||
3b139cdb DH |
177 | /* |
178 | * Interface to various arch routines that may be traced. | |
179 | */ | |
180 | #ifdef CONFIG_IPIPE_TRACE_IRQSOFF | |
a2de3f79 | 181 | static inline notrace void hard_local_irq_disable(void) |
3b139cdb DH |
182 | { |
183 | if (!hard_irqs_disabled()) { | |
184 | __hard_local_irq_disable(); | |
185 | ipipe_trace_begin(0x80000000); | |
186 | } | |
187 | } | |
8f86001f | 188 | |
a2de3f79 | 189 | static inline notrace void hard_local_irq_enable(void) |
3b139cdb DH |
190 | { |
191 | if (hard_irqs_disabled()) { | |
192 | ipipe_trace_end(0x80000000); | |
193 | __hard_local_irq_enable(); | |
194 | } | |
195 | } | |
8f86001f | 196 | |
a2de3f79 | 197 | static inline notrace unsigned long hard_local_irq_save(void) |
8f86001f | 198 | { |
3b139cdb DH |
199 | unsigned long flags = hard_local_save_flags(); |
200 | if (!hard_irqs_disabled_flags(flags)) { | |
201 | __hard_local_irq_disable(); | |
202 | ipipe_trace_begin(0x80000001); | |
203 | } | |
8f86001f MF |
204 | return flags; |
205 | } | |
8f86001f | 206 | |
a2de3f79 | 207 | static inline notrace void hard_local_irq_restore(unsigned long flags) |
3b139cdb DH |
208 | { |
209 | if (!hard_irqs_disabled_flags(flags)) { | |
210 | ipipe_trace_end(0x80000001); | |
211 | __hard_local_irq_enable(); | |
212 | } | |
213 | } | |
214 | ||
215 | #else /* !CONFIG_IPIPE_TRACE_IRQSOFF */ | |
216 | # define hard_local_irq_disable() __hard_local_irq_disable() | |
217 | # define hard_local_irq_enable() __hard_local_irq_enable() | |
218 | # define hard_local_irq_save() __hard_local_irq_save() | |
219 | # define hard_local_irq_restore(flags) __hard_local_irq_restore(flags) | |
220 | #endif /* !CONFIG_IPIPE_TRACE_IRQSOFF */ | |
221 | ||
1353d050 PG |
222 | #define hard_local_irq_save_cond() hard_local_irq_save() |
223 | #define hard_local_irq_restore_cond(flags) hard_local_irq_restore(flags) | |
224 | ||
225 | #else /* !CONFIG_IPIPE */ | |
3b139cdb DH |
226 | |
227 | /* | |
228 | * Direct interface to linux/irqflags.h. | |
229 | */ | |
230 | #define arch_local_save_flags() hard_local_save_flags() | |
4f6b600f | 231 | #define arch_local_irq_save() __hard_local_irq_save() |
3b139cdb DH |
232 | #define arch_local_irq_restore(flags) __hard_local_irq_restore(flags) |
233 | #define arch_local_irq_enable() __hard_local_irq_enable() | |
234 | #define arch_local_irq_disable() __hard_local_irq_disable() | |
235 | #define arch_irqs_disabled_flags(flags) hard_irqs_disabled_flags(flags) | |
236 | #define arch_irqs_disabled() hard_irqs_disabled() | |
237 | ||
238 | /* | |
239 | * Interface to various arch routines that may be traced. | |
240 | */ | |
241 | #define hard_local_irq_save() __hard_local_irq_save() | |
242 | #define hard_local_irq_restore(flags) __hard_local_irq_restore(flags) | |
243 | #define hard_local_irq_enable() __hard_local_irq_enable() | |
244 | #define hard_local_irq_disable() __hard_local_irq_disable() | |
1353d050 PG |
245 | #define hard_local_irq_save_cond() hard_local_save_flags() |
246 | #define hard_local_irq_restore_cond(flags) do { (void)(flags); } while (0) | |
06ecc190 PG |
247 | |
248 | #endif /* !CONFIG_IPIPE */ | |
1353d050 PG |
249 | |
250 | #ifdef CONFIG_SMP | |
251 | #define hard_local_irq_save_smp() hard_local_irq_save() | |
252 | #define hard_local_irq_restore_smp(flags) hard_local_irq_restore(flags) | |
253 | #else | |
254 | #define hard_local_irq_save_smp() hard_local_save_flags() | |
255 | #define hard_local_irq_restore_smp(flags) do { (void)(flags); } while (0) | |
256 | #endif | |
257 | ||
258 | /* | |
259 | * Remap the arch-neutral IRQ state manipulation macros to the | |
260 | * blackfin-specific hard_local_irq_* API. | |
261 | */ | |
262 | #define local_irq_save_hw(flags) \ | |
263 | do { \ | |
264 | (flags) = hard_local_irq_save(); \ | |
265 | } while (0) | |
266 | #define local_irq_restore_hw(flags) \ | |
267 | do { \ | |
268 | hard_local_irq_restore(flags); \ | |
269 | } while (0) | |
270 | #define local_irq_disable_hw() \ | |
271 | do { \ | |
272 | hard_local_irq_disable(); \ | |
273 | } while (0) | |
274 | #define local_irq_enable_hw() \ | |
275 | do { \ | |
276 | hard_local_irq_enable(); \ | |
277 | } while (0) | |
278 | #define local_irq_save_hw_notrace(flags) \ | |
279 | do { \ | |
280 | (flags) = __hard_local_irq_save(); \ | |
281 | } while (0) | |
282 | #define local_irq_restore_hw_notrace(flags) \ | |
283 | do { \ | |
284 | __hard_local_irq_restore(flags); \ | |
285 | } while (0) | |
286 | ||
287 | #define irqs_disabled_hw() hard_irqs_disabled() | |
288 | ||
8f86001f | 289 | #endif |