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