blackfin: fix copy_from_user()
[linux-2.6-block.git] / arch / blackfin / include / asm / irqflags.h
CommitLineData
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
18extern unsigned long bfin_irq_flags;
19#endif
20
a2de3f79 21static inline notrace void bfin_sti(unsigned long flags)
8f86001f
MF
22{
23 asm volatile("sti %0;" : : "d" (flags));
24}
25
a2de3f79 26static 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 43static inline notrace void __hard_local_irq_disable(void)
3b139cdb
DH
44{
45 bfin_cli();
46}
06ecc190 47
a2de3f79 48static inline notrace void __hard_local_irq_enable(void)
3b139cdb
DH
49{
50 bfin_sti(bfin_irq_flags);
51}
06ecc190 52
a2de3f79 53static inline notrace unsigned long hard_local_save_flags(void)
06ecc190 54{
3b139cdb 55 return bfin_read_IMASK();
06ecc190
PG
56}
57
a2de3f79 58static 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 68static 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 77static 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 83static 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 */
102void __ipipe_stall_root(void);
103void __ipipe_unstall_root(void);
104unsigned long __ipipe_test_root(void);
105unsigned long __ipipe_test_and_stall_root(void);
106void __ipipe_restore_root(unsigned long flags);
107
108#ifdef CONFIG_IPIPE_DEBUG_CONTEXT
109struct ipipe_domain;
110extern struct ipipe_domain ipipe_root;
111void 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 120static 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 127static 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 134static 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 139static inline notrace int arch_irqs_disabled_flags(unsigned long flags)
3b139cdb
DH
140{
141 return flags == bfin_no_irqs;
142}
06ecc190 143
a2de3f79 144static 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 155static 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 161static 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 170static 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 181static 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 189static 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 197static 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 207static 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