blob: 07aff230a8128bb4561991beb8682bdace64c744 [file] [log] [blame]
Mike Frysinger8f860012009-06-08 12:49:48 -04001/*
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
David Howells5c748742010-10-07 14:08:51 +010011#include <mach/blackfin.h>
12
Mike Frysinger8f860012009-06-08 12:49:48 -040013#ifdef CONFIG_SMP
14# include <asm/pda.h>
15# include <asm/processor.h>
Mike Frysinger8f860012009-06-08 12:49:48 -040016# define bfin_irq_flags cpu_pda[blackfin_core_id()].imask
17#else
18extern unsigned long bfin_irq_flags;
19#endif
20
Steven Rostedta2de3f72011-07-01 23:04:38 -040021static inline notrace void bfin_sti(unsigned long flags)
Mike Frysinger8f860012009-06-08 12:49:48 -040022{
23 asm volatile("sti %0;" : : "d" (flags));
24}
25
Steven Rostedta2de3f72011-07-01 23:04:38 -040026static inline notrace unsigned long bfin_cli(void)
Mike Frysinger8f860012009-06-08 12:49:48 -040027{
28 unsigned long flags;
29 asm volatile("cli %0;" : "=d" (flags));
30 return flags;
31}
32
Philippe Gerum06ecc192009-06-16 05:25:37 +020033#ifdef CONFIG_DEBUG_HWERR
34# define bfin_no_irqs 0x3f
35#else
36# define bfin_no_irqs 0x1f
37#endif
38
David Howells3b139cd2010-10-07 14:08:52 +010039/*****************************************************************************/
40/*
41 * Hard, untraced CPU interrupt flag manipulation and access.
42 */
Steven Rostedta2de3f72011-07-01 23:04:38 -040043static inline notrace void __hard_local_irq_disable(void)
David Howells3b139cd2010-10-07 14:08:52 +010044{
45 bfin_cli();
46}
Philippe Gerum06ecc192009-06-16 05:25:37 +020047
Steven Rostedta2de3f72011-07-01 23:04:38 -040048static inline notrace void __hard_local_irq_enable(void)
David Howells3b139cd2010-10-07 14:08:52 +010049{
50 bfin_sti(bfin_irq_flags);
51}
Philippe Gerum06ecc192009-06-16 05:25:37 +020052
Steven Rostedta2de3f72011-07-01 23:04:38 -040053static inline notrace unsigned long hard_local_save_flags(void)
David Howells3b139cd2010-10-07 14:08:52 +010054{
55 return bfin_read_IMASK();
56}
Philippe Gerum06ecc192009-06-16 05:25:37 +020057
Steven Rostedta2de3f72011-07-01 23:04:38 -040058static inline notrace unsigned long __hard_local_irq_save(void)
David Howells3b139cd2010-10-07 14:08:52 +010059{
60 unsigned long flags;
61 flags = bfin_cli();
62#ifdef CONFIG_DEBUG_HWERR
63 bfin_sti(0x3f);
64#endif
65 return flags;
66}
Philippe Gerum06ecc192009-06-16 05:25:37 +020067
Steven Rostedta2de3f72011-07-01 23:04:38 -040068static inline notrace int hard_irqs_disabled_flags(unsigned long flags)
David Howells3b139cd2010-10-07 14:08:52 +010069{
Steven Miao4f6b6002012-05-16 17:56:51 +080070#ifdef CONFIG_BF60x
71 return (flags & IMASK_IVG11) == 0;
72#else
David Howells3b139cd2010-10-07 14:08:52 +010073 return (flags & ~0x3f) == 0;
Steven Miao4f6b6002012-05-16 17:56:51 +080074#endif
David Howells3b139cd2010-10-07 14:08:52 +010075}
Philippe Gerum06ecc192009-06-16 05:25:37 +020076
Steven Rostedta2de3f72011-07-01 23:04:38 -040077static inline notrace int hard_irqs_disabled(void)
David Howells3b139cd2010-10-07 14:08:52 +010078{
79 unsigned long flags = hard_local_save_flags();
80 return hard_irqs_disabled_flags(flags);
81}
Philippe Gerum06ecc192009-06-16 05:25:37 +020082
Steven Rostedta2de3f72011-07-01 23:04:38 -040083static inline notrace void __hard_local_irq_restore(unsigned long flags)
David Howells3b139cd2010-10-07 14:08:52 +010084{
85 if (!hard_irqs_disabled_flags(flags))
86 __hard_local_irq_enable();
87}
Philippe Gerum06ecc192009-06-16 05:25:37 +020088
David Howells3b139cd2010-10-07 14:08:52 +010089/*****************************************************************************/
90/*
91 * Interrupt pipe handling.
92 */
93#ifdef CONFIG_IPIPE
94
95#include <linux/compiler.h>
David Howells3b139cd2010-10-07 14:08:52 +010096#include <linux/ipipe_trace.h>
Philippe Gerum1353d052011-03-17 02:16:16 -040097/*
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 */
David Howells3b139cd2010-10-07 14:08:52 +0100116
117/*
118 * Interrupt pipe interface to linux/irqflags.h.
119 */
Steven Rostedta2de3f72011-07-01 23:04:38 -0400120static inline notrace void arch_local_irq_disable(void)
David Howells3b139cd2010-10-07 14:08:52 +0100121{
Philippe Gerum1353d052011-03-17 02:16:16 -0400122 __check_irqop_context();
David Howells3b139cd2010-10-07 14:08:52 +0100123 __ipipe_stall_root();
124 barrier();
125}
126
Steven Rostedta2de3f72011-07-01 23:04:38 -0400127static inline notrace void arch_local_irq_enable(void)
David Howells3b139cd2010-10-07 14:08:52 +0100128{
129 barrier();
Philippe Gerum1353d052011-03-17 02:16:16 -0400130 __check_irqop_context();
David Howells3b139cd2010-10-07 14:08:52 +0100131 __ipipe_unstall_root();
132}
133
Steven Rostedta2de3f72011-07-01 23:04:38 -0400134static inline notrace unsigned long arch_local_save_flags(void)
David Howells3b139cd2010-10-07 14:08:52 +0100135{
136 return __ipipe_test_root() ? bfin_no_irqs : bfin_irq_flags;
137}
138
Steven Rostedta2de3f72011-07-01 23:04:38 -0400139static inline notrace int arch_irqs_disabled_flags(unsigned long flags)
David Howells3b139cd2010-10-07 14:08:52 +0100140{
141 return flags == bfin_no_irqs;
142}
143
Steven Rostedta2de3f72011-07-01 23:04:38 -0400144static inline notrace unsigned long arch_local_irq_save(void)
David Howells3b139cd2010-10-07 14:08:52 +0100145{
Philippe Gerum1353d052011-03-17 02:16:16 -0400146 unsigned long flags;
147
148 __check_irqop_context();
149 flags = __ipipe_test_and_stall_root() ? bfin_no_irqs : bfin_irq_flags;
150 barrier();
151
152 return flags;
153}
154
Steven Rostedta2de3f72011-07-01 23:04:38 -0400155static inline notrace void arch_local_irq_restore(unsigned long flags)
Philippe Gerum1353d052011-03-17 02:16:16 -0400156{
157 __check_irqop_context();
158 __ipipe_restore_root(flags == bfin_no_irqs);
David Howells3b139cd2010-10-07 14:08:52 +0100159}
160
Steven Rostedta2de3f72011-07-01 23:04:38 -0400161static inline notrace unsigned long arch_mangle_irq_bits(int virt, unsigned long real)
Philippe Gerum06ecc192009-06-16 05:25:37 +0200162{
163 /*
164 * Merge virtual and real interrupt mask bits into a single
165 * 32bit word.
166 */
167 return (real & ~(1 << 31)) | ((virt != 0) << 31);
168}
169
Steven Rostedta2de3f72011-07-01 23:04:38 -0400170static inline notrace int arch_demangle_irq_bits(unsigned long *x)
Philippe Gerum06ecc192009-06-16 05:25:37 +0200171{
172 int virt = (*x & (1 << 31)) != 0;
173 *x &= ~(1L << 31);
174 return virt;
175}
176
David Howells3b139cd2010-10-07 14:08:52 +0100177/*
178 * Interface to various arch routines that may be traced.
179 */
Philippe Gerum06ecc192009-06-16 05:25:37 +0200180#ifdef CONFIG_IPIPE_TRACE_IRQSOFF
Steven Rostedta2de3f72011-07-01 23:04:38 -0400181static inline notrace void hard_local_irq_disable(void)
David Howells3b139cd2010-10-07 14:08:52 +0100182{
183 if (!hard_irqs_disabled()) {
184 __hard_local_irq_disable();
185 ipipe_trace_begin(0x80000000);
186 }
187}
188
Steven Rostedta2de3f72011-07-01 23:04:38 -0400189static inline notrace void hard_local_irq_enable(void)
David Howells3b139cd2010-10-07 14:08:52 +0100190{
191 if (hard_irqs_disabled()) {
192 ipipe_trace_end(0x80000000);
193 __hard_local_irq_enable();
194 }
195}
196
Steven Rostedta2de3f72011-07-01 23:04:38 -0400197static inline notrace unsigned long hard_local_irq_save(void)
David Howells3b139cd2010-10-07 14:08:52 +0100198{
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 }
204 return flags;
205}
206
Steven Rostedta2de3f72011-07-01 23:04:38 -0400207static inline notrace void hard_local_irq_restore(unsigned long flags)
David Howells3b139cd2010-10-07 14:08:52 +0100208{
209 if (!hard_irqs_disabled_flags(flags)) {
210 ipipe_trace_end(0x80000001);
211 __hard_local_irq_enable();
212 }
213}
214
Philippe Gerum06ecc192009-06-16 05:25:37 +0200215#else /* !CONFIG_IPIPE_TRACE_IRQSOFF */
David Howells3b139cd2010-10-07 14:08:52 +0100216# 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)
Philippe Gerum06ecc192009-06-16 05:25:37 +0200220#endif /* !CONFIG_IPIPE_TRACE_IRQSOFF */
221
Philippe Gerum1353d052011-03-17 02:16:16 -0400222#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 */
Philippe Gerum06ecc192009-06-16 05:25:37 +0200226
David Howells3b139cd2010-10-07 14:08:52 +0100227/*
228 * Direct interface to linux/irqflags.h.
229 */
230#define arch_local_save_flags() hard_local_save_flags()
Steven Miao4f6b6002012-05-16 17:56:51 +0800231#define arch_local_irq_save() __hard_local_irq_save()
David Howells3b139cd2010-10-07 14:08:52 +0100232#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()
Mike Frysinger8f860012009-06-08 12:49:48 -0400237
David Howells3b139cd2010-10-07 14:08:52 +0100238/*
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()
Philippe Gerum1353d052011-03-17 02:16:16 -0400245#define hard_local_irq_save_cond() hard_local_save_flags()
246#define hard_local_irq_restore_cond(flags) do { (void)(flags); } while (0)
Philippe Gerum06ecc192009-06-16 05:25:37 +0200247
248#endif /* !CONFIG_IPIPE */
Philippe Gerum1353d052011-03-17 02:16:16 -0400249
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
Mike Frysinger8f860012009-06-08 12:49:48 -0400289#endif