diff options
Diffstat (limited to 'arch/blackfin/include/asm/irq.h')
-rw-r--r-- | arch/blackfin/include/asm/irq.h | 296 |
1 files changed, 256 insertions, 40 deletions
diff --git a/arch/blackfin/include/asm/irq.h b/arch/blackfin/include/asm/irq.h index 89f59e18af93..3d977909ce7d 100644 --- a/arch/blackfin/include/asm/irq.h +++ b/arch/blackfin/include/asm/irq.h | |||
@@ -17,56 +17,272 @@ | |||
17 | #ifndef _BFIN_IRQ_H_ | 17 | #ifndef _BFIN_IRQ_H_ |
18 | #define _BFIN_IRQ_H_ | 18 | #define _BFIN_IRQ_H_ |
19 | 19 | ||
20 | /* SYS_IRQS and NR_IRQS are defined in <mach-bf5xx/irq.h>*/ | ||
20 | #include <mach/irq.h> | 21 | #include <mach/irq.h> |
21 | #include <asm/ptrace.h> | 22 | #include <asm/pda.h> |
22 | 23 | #include <asm/processor.h> | |
23 | /******************************************************************************* | ||
24 | ***** INTRODUCTION *********** | ||
25 | * On the Blackfin, the interrupt structure allows remmapping of the hardware | ||
26 | * levels. | ||
27 | * - I'm going to assume that the H/W level is going to stay at the default | ||
28 | * settings. If someone wants to go through and abstart this out, feel free | ||
29 | * to mod the interrupt numbering scheme. | ||
30 | * - I'm abstracting the interrupts so that uClinux does not know anything | ||
31 | * about the H/W levels. If you want to change the H/W AND keep the abstracted | ||
32 | * levels that uClinux sees, you should be able to do most of it here. | ||
33 | * - I've left the "abstract" numbering sparce in case someone wants to pull the | ||
34 | * interrupts apart (just the TX/RX for the various devices) | ||
35 | *******************************************************************************/ | ||
36 | 24 | ||
37 | /* SYS_IRQS and NR_IRQS are defined in <mach-bf5xx/irq.h>*/ | 25 | #ifdef CONFIG_SMP |
26 | /* Forward decl needed due to cdef inter dependencies */ | ||
27 | static inline uint32_t __pure bfin_dspid(void); | ||
28 | # define blackfin_core_id() (bfin_dspid() & 0xff) | ||
29 | # define bfin_irq_flags cpu_pda[blackfin_core_id()].imask | ||
30 | #else | ||
31 | extern unsigned long bfin_irq_flags; | ||
32 | #endif | ||
38 | 33 | ||
39 | /* | 34 | #ifdef CONFIG_IPIPE |
40 | * Machine specific interrupt sources. | 35 | |
41 | * | 36 | #include <linux/ipipe_trace.h> |
42 | * Adding an interrupt service routine for a source with this bit | 37 | |
43 | * set indicates a special machine specific interrupt source. | 38 | void __ipipe_unstall_root(void); |
44 | * The machine specific files define these sources. | 39 | |
45 | * | 40 | void __ipipe_restore_root(unsigned long flags); |
46 | * The IRQ_MACHSPEC bit is now gone - the only thing it did was to | 41 | |
47 | * introduce unnecessary overhead. | 42 | #ifdef CONFIG_DEBUG_HWERR |
48 | * | 43 | # define __all_masked_irq_flags 0x3f |
49 | * All interrupt handling is actually machine specific so it is better | 44 | # define __save_and_cli_hw(x) \ |
50 | * to use function pointers, as used by the Sparc port, and select the | 45 | __asm__ __volatile__( \ |
51 | * interrupt handling functions when initializing the kernel. This way | 46 | "cli %0;" \ |
52 | * we save some unnecessary overhead at run-time. | 47 | "sti %1;" \ |
53 | * 01/11/97 - Jes | 48 | : "=&d"(x) \ |
54 | */ | 49 | : "d" (0x3F) \ |
50 | ) | ||
51 | #else | ||
52 | # define __all_masked_irq_flags 0x1f | ||
53 | # define __save_and_cli_hw(x) \ | ||
54 | __asm__ __volatile__( \ | ||
55 | "cli %0;" \ | ||
56 | : "=&d"(x) \ | ||
57 | ) | ||
58 | #endif | ||
59 | |||
60 | #define irqs_enabled_from_flags_hw(x) ((x) != __all_masked_irq_flags) | ||
61 | #define raw_irqs_disabled_flags(flags) (!irqs_enabled_from_flags_hw(flags)) | ||
62 | #define local_test_iflag_hw(x) irqs_enabled_from_flags_hw(x) | ||
55 | 63 | ||
56 | extern void ack_bad_irq(unsigned int irq); | 64 | #define local_save_flags(x) \ |
65 | do { \ | ||
66 | (x) = __ipipe_test_root() ? \ | ||
67 | __all_masked_irq_flags : bfin_irq_flags; \ | ||
68 | } while (0) | ||
57 | 69 | ||
58 | static __inline__ int irq_canonicalize(int irq) | 70 | #define local_irq_save(x) \ |
71 | do { \ | ||
72 | (x) = __ipipe_test_and_stall_root(); \ | ||
73 | } while (0) | ||
74 | |||
75 | #define local_irq_restore(x) __ipipe_restore_root(x) | ||
76 | #define local_irq_disable() __ipipe_stall_root() | ||
77 | #define local_irq_enable() __ipipe_unstall_root() | ||
78 | #define irqs_disabled() __ipipe_test_root() | ||
79 | |||
80 | #define local_save_flags_hw(x) \ | ||
81 | __asm__ __volatile__( \ | ||
82 | "cli %0;" \ | ||
83 | "sti %0;" \ | ||
84 | : "=d"(x) \ | ||
85 | ) | ||
86 | |||
87 | #define irqs_disabled_hw() \ | ||
88 | ({ \ | ||
89 | unsigned long flags; \ | ||
90 | local_save_flags_hw(flags); \ | ||
91 | !irqs_enabled_from_flags_hw(flags); \ | ||
92 | }) | ||
93 | |||
94 | static inline unsigned long raw_mangle_irq_bits(int virt, unsigned long real) | ||
59 | { | 95 | { |
60 | return irq; | 96 | /* Merge virtual and real interrupt mask bits into a single |
97 | 32bit word. */ | ||
98 | return (real & ~(1 << 31)) | ((virt != 0) << 31); | ||
99 | } | ||
100 | |||
101 | static inline int raw_demangle_irq_bits(unsigned long *x) | ||
102 | { | ||
103 | int virt = (*x & (1 << 31)) != 0; | ||
104 | *x &= ~(1L << 31); | ||
105 | return virt; | ||
61 | } | 106 | } |
62 | 107 | ||
63 | /* count of spurious interrupts */ | 108 | #ifdef CONFIG_IPIPE_TRACE_IRQSOFF |
64 | /* extern volatile unsigned int num_spurious; */ | 109 | |
110 | #define local_irq_disable_hw() \ | ||
111 | do { \ | ||
112 | int _tmp_dummy; \ | ||
113 | if (!irqs_disabled_hw()) \ | ||
114 | ipipe_trace_begin(0x80000000); \ | ||
115 | __asm__ __volatile__ ("cli %0;" : "=d" (_tmp_dummy) : ); \ | ||
116 | } while (0) | ||
117 | |||
118 | #define local_irq_enable_hw() \ | ||
119 | do { \ | ||
120 | if (irqs_disabled_hw()) \ | ||
121 | ipipe_trace_end(0x80000000); \ | ||
122 | __asm__ __volatile__ ("sti %0;" : : "d"(bfin_irq_flags)); \ | ||
123 | } while (0) | ||
124 | |||
125 | #define local_irq_save_hw(x) \ | ||
126 | do { \ | ||
127 | __save_and_cli_hw(x); \ | ||
128 | if (local_test_iflag_hw(x)) \ | ||
129 | ipipe_trace_begin(0x80000001); \ | ||
130 | } while (0) | ||
131 | |||
132 | #define local_irq_restore_hw(x) \ | ||
133 | do { \ | ||
134 | if (local_test_iflag_hw(x)) { \ | ||
135 | ipipe_trace_end(0x80000001); \ | ||
136 | local_irq_enable_hw_notrace(); \ | ||
137 | } \ | ||
138 | } while (0) | ||
139 | |||
140 | #define local_irq_disable_hw_notrace() \ | ||
141 | do { \ | ||
142 | int _tmp_dummy; \ | ||
143 | __asm__ __volatile__ ("cli %0;" : "=d" (_tmp_dummy) : ); \ | ||
144 | } while (0) | ||
145 | |||
146 | #define local_irq_enable_hw_notrace() \ | ||
147 | __asm__ __volatile__( \ | ||
148 | "sti %0;" \ | ||
149 | : \ | ||
150 | : "d"(bfin_irq_flags) \ | ||
151 | ) | ||
65 | 152 | ||
66 | #ifndef NO_IRQ | 153 | #define local_irq_save_hw_notrace(x) __save_and_cli_hw(x) |
67 | #define NO_IRQ ((unsigned int)(-1)) | 154 | |
155 | #define local_irq_restore_hw_notrace(x) \ | ||
156 | do { \ | ||
157 | if (local_test_iflag_hw(x)) \ | ||
158 | local_irq_enable_hw_notrace(); \ | ||
159 | } while (0) | ||
160 | |||
161 | #else /* CONFIG_IPIPE_TRACE_IRQSOFF */ | ||
162 | |||
163 | #define local_irq_enable_hw() \ | ||
164 | __asm__ __volatile__( \ | ||
165 | "sti %0;" \ | ||
166 | : \ | ||
167 | : "d"(bfin_irq_flags) \ | ||
168 | ) | ||
169 | |||
170 | #define local_irq_disable_hw() \ | ||
171 | do { \ | ||
172 | int _tmp_dummy; \ | ||
173 | __asm__ __volatile__ ( \ | ||
174 | "cli %0;" \ | ||
175 | : "=d" (_tmp_dummy)); \ | ||
176 | } while (0) | ||
177 | |||
178 | #define local_irq_restore_hw(x) \ | ||
179 | do { \ | ||
180 | if (irqs_enabled_from_flags_hw(x)) \ | ||
181 | local_irq_enable_hw(); \ | ||
182 | } while (0) | ||
183 | |||
184 | #define local_irq_save_hw(x) __save_and_cli_hw(x) | ||
185 | |||
186 | #define local_irq_disable_hw_notrace() local_irq_disable_hw() | ||
187 | #define local_irq_enable_hw_notrace() local_irq_enable_hw() | ||
188 | #define local_irq_save_hw_notrace(x) local_irq_save_hw(x) | ||
189 | #define local_irq_restore_hw_notrace(x) local_irq_restore_hw(x) | ||
190 | |||
191 | #endif /* CONFIG_IPIPE_TRACE_IRQSOFF */ | ||
192 | |||
193 | #else /* !CONFIG_IPIPE */ | ||
194 | |||
195 | /* | ||
196 | * Interrupt configuring macros. | ||
197 | */ | ||
198 | #define local_irq_disable() \ | ||
199 | do { \ | ||
200 | int __tmp_dummy; \ | ||
201 | __asm__ __volatile__( \ | ||
202 | "cli %0;" \ | ||
203 | : "=d" (__tmp_dummy) \ | ||
204 | ); \ | ||
205 | } while (0) | ||
206 | |||
207 | #define local_irq_enable() \ | ||
208 | __asm__ __volatile__( \ | ||
209 | "sti %0;" \ | ||
210 | : \ | ||
211 | : "d" (bfin_irq_flags) \ | ||
212 | ) | ||
213 | |||
214 | #ifdef CONFIG_DEBUG_HWERR | ||
215 | # define __save_and_cli(x) \ | ||
216 | __asm__ __volatile__( \ | ||
217 | "cli %0;" \ | ||
218 | "sti %1;" \ | ||
219 | : "=&d" (x) \ | ||
220 | : "d" (0x3F) \ | ||
221 | ) | ||
222 | #else | ||
223 | # define __save_and_cli(x) \ | ||
224 | __asm__ __volatile__( \ | ||
225 | "cli %0;" \ | ||
226 | : "=&d" (x) \ | ||
227 | ) | ||
68 | #endif | 228 | #endif |
69 | 229 | ||
70 | #define SIC_SYSIRQ(irq) (irq - (IRQ_CORETMR + 1)) | 230 | #define local_save_flags(x) \ |
231 | __asm__ __volatile__( \ | ||
232 | "cli %0;" \ | ||
233 | "sti %0;" \ | ||
234 | : "=d" (x) \ | ||
235 | ) | ||
236 | |||
237 | #ifdef CONFIG_DEBUG_HWERR | ||
238 | #define irqs_enabled_from_flags(x) (((x) & ~0x3f) != 0) | ||
239 | #else | ||
240 | #define irqs_enabled_from_flags(x) ((x) != 0x1f) | ||
241 | #endif | ||
242 | |||
243 | #define local_irq_restore(x) \ | ||
244 | do { \ | ||
245 | if (irqs_enabled_from_flags(x)) \ | ||
246 | local_irq_enable(); \ | ||
247 | } while (0) | ||
248 | |||
249 | /* For spinlocks etc */ | ||
250 | #define local_irq_save(x) __save_and_cli(x) | ||
251 | |||
252 | #define irqs_disabled() \ | ||
253 | ({ \ | ||
254 | unsigned long flags; \ | ||
255 | local_save_flags(flags); \ | ||
256 | !irqs_enabled_from_flags(flags); \ | ||
257 | }) | ||
258 | |||
259 | #define local_irq_save_hw(x) local_irq_save(x) | ||
260 | #define local_irq_restore_hw(x) local_irq_restore(x) | ||
261 | #define local_irq_enable_hw() local_irq_enable() | ||
262 | #define local_irq_disable_hw() local_irq_disable() | ||
263 | #define irqs_disabled_hw() irqs_disabled() | ||
264 | |||
265 | #endif /* !CONFIG_IPIPE */ | ||
266 | |||
267 | #if ANOMALY_05000244 && defined(CONFIG_BFIN_ICACHE) | ||
268 | # define NOP_PAD_ANOMALY_05000244 "nop; nop;" | ||
269 | #else | ||
270 | # define NOP_PAD_ANOMALY_05000244 | ||
271 | #endif | ||
272 | |||
273 | #define idle_with_irq_disabled() \ | ||
274 | __asm__ __volatile__( \ | ||
275 | NOP_PAD_ANOMALY_05000244 \ | ||
276 | ".align 8;" \ | ||
277 | "sti %0;" \ | ||
278 | "idle;" \ | ||
279 | : \ | ||
280 | : "d" (bfin_irq_flags) \ | ||
281 | ) | ||
282 | |||
283 | static inline int irq_canonicalize(int irq) | ||
284 | { | ||
285 | return irq; | ||
286 | } | ||
71 | 287 | ||
72 | #endif /* _BFIN_IRQ_H_ */ | 288 | #endif /* _BFIN_IRQ_H_ */ |