aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/include/asm/irq.h
diff options
context:
space:
mode:
Diffstat (limited to 'arch/blackfin/include/asm/irq.h')
-rw-r--r--arch/blackfin/include/asm/irq.h296
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 */
27static 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
31extern 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. 38void __ipipe_unstall_root(void);
44 * The machine specific files define these sources. 39
45 * 40void __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
56extern 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
58static __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
94static 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
101static 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
283static inline int irq_canonicalize(int irq)
284{
285 return irq;
286}
71 287
72#endif /* _BFIN_IRQ_H_ */ 288#endif /* _BFIN_IRQ_H_ */