blob: 994d76791016a7794c53a95a31bfe1c04aed19a9 [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>
16/* Forward decl needed due to cdef inter dependencies */
17static inline uint32_t __pure bfin_dspid(void);
18# define blackfin_core_id() (bfin_dspid() & 0xff)
19# define bfin_irq_flags cpu_pda[blackfin_core_id()].imask
20#else
21extern unsigned long bfin_irq_flags;
22#endif
23
24static inline void bfin_sti(unsigned long flags)
25{
26 asm volatile("sti %0;" : : "d" (flags));
27}
28
29static inline unsigned long bfin_cli(void)
30{
31 unsigned long flags;
32 asm volatile("cli %0;" : "=d" (flags));
33 return flags;
34}
35
Philippe Gerum06ecc192009-06-16 05:25:37 +020036#ifdef CONFIG_DEBUG_HWERR
37# define bfin_no_irqs 0x3f
38#else
39# define bfin_no_irqs 0x1f
40#endif
41
David Howells3b139cd2010-10-07 14:08:52 +010042/*****************************************************************************/
43/*
44 * Hard, untraced CPU interrupt flag manipulation and access.
45 */
46static inline void __hard_local_irq_disable(void)
47{
48 bfin_cli();
49}
Philippe Gerum06ecc192009-06-16 05:25:37 +020050
David Howells3b139cd2010-10-07 14:08:52 +010051static inline void __hard_local_irq_enable(void)
52{
53 bfin_sti(bfin_irq_flags);
54}
Philippe Gerum06ecc192009-06-16 05:25:37 +020055
David Howells3b139cd2010-10-07 14:08:52 +010056static inline unsigned long hard_local_save_flags(void)
57{
58 return bfin_read_IMASK();
59}
Philippe Gerum06ecc192009-06-16 05:25:37 +020060
David Howells3b139cd2010-10-07 14:08:52 +010061static inline unsigned long __hard_local_irq_save(void)
62{
63 unsigned long flags;
64 flags = bfin_cli();
65#ifdef CONFIG_DEBUG_HWERR
66 bfin_sti(0x3f);
67#endif
68 return flags;
69}
Philippe Gerum06ecc192009-06-16 05:25:37 +020070
David Howells3b139cd2010-10-07 14:08:52 +010071static inline int hard_irqs_disabled_flags(unsigned long flags)
72{
73 return (flags & ~0x3f) == 0;
74}
Philippe Gerum06ecc192009-06-16 05:25:37 +020075
David Howells3b139cd2010-10-07 14:08:52 +010076static inline int hard_irqs_disabled(void)
77{
78 unsigned long flags = hard_local_save_flags();
79 return hard_irqs_disabled_flags(flags);
80}
Philippe Gerum06ecc192009-06-16 05:25:37 +020081
David Howells3b139cd2010-10-07 14:08:52 +010082static inline void __hard_local_irq_restore(unsigned long flags)
83{
84 if (!hard_irqs_disabled_flags(flags))
85 __hard_local_irq_enable();
86}
Philippe Gerum06ecc192009-06-16 05:25:37 +020087
David Howells3b139cd2010-10-07 14:08:52 +010088/*****************************************************************************/
89/*
90 * Interrupt pipe handling.
91 */
92#ifdef CONFIG_IPIPE
93
94#include <linux/compiler.h>
95#include <linux/ipipe_base.h>
96#include <linux/ipipe_trace.h>
97
98/*
99 * Interrupt pipe interface to linux/irqflags.h.
100 */
101static inline void arch_local_irq_disable(void)
102{
103 ipipe_check_context(ipipe_root_domain);
104 __ipipe_stall_root();
105 barrier();
106}
107
108static inline void arch_local_irq_enable(void)
109{
110 barrier();
111 ipipe_check_context(ipipe_root_domain);
112 __ipipe_unstall_root();
113}
114
115static inline unsigned long arch_local_save_flags(void)
116{
117 return __ipipe_test_root() ? bfin_no_irqs : bfin_irq_flags;
118}
119
120static inline int arch_irqs_disabled_flags(unsigned long flags)
121{
122 return flags == bfin_no_irqs;
123}
124
125static inline void arch_local_irq_save_ptr(unsigned long *_flags)
126{
127 x = __ipipe_test_and_stall_root() ? bfin_no_irqs : bfin_irq_flags;
128 barrier();
129}
130
131static inline unsigned long arch_local_irq_save(void)
132{
133 ipipe_check_context(ipipe_root_domain);
134 return __hard_local_irq_save();
135}
136
137static inline unsigned long arch_mangle_irq_bits(int virt, unsigned long real)
Philippe Gerum06ecc192009-06-16 05:25:37 +0200138{
139 /*
140 * Merge virtual and real interrupt mask bits into a single
141 * 32bit word.
142 */
143 return (real & ~(1 << 31)) | ((virt != 0) << 31);
144}
145
David Howells3b139cd2010-10-07 14:08:52 +0100146static inline int arch_demangle_irq_bits(unsigned long *x)
Philippe Gerum06ecc192009-06-16 05:25:37 +0200147{
148 int virt = (*x & (1 << 31)) != 0;
149 *x &= ~(1L << 31);
150 return virt;
151}
152
David Howells3b139cd2010-10-07 14:08:52 +0100153/*
154 * Interface to various arch routines that may be traced.
155 */
Philippe Gerum06ecc192009-06-16 05:25:37 +0200156#ifdef CONFIG_IPIPE_TRACE_IRQSOFF
David Howells3b139cd2010-10-07 14:08:52 +0100157static inline void hard_local_irq_disable(void)
158{
159 if (!hard_irqs_disabled()) {
160 __hard_local_irq_disable();
161 ipipe_trace_begin(0x80000000);
162 }
163}
164
165static inline void hard_local_irq_enable(void)
166{
167 if (hard_irqs_disabled()) {
168 ipipe_trace_end(0x80000000);
169 __hard_local_irq_enable();
170 }
171}
172
173static inline unsigned long hard_local_irq_save(void)
174{
175 unsigned long flags = hard_local_save_flags();
176 if (!hard_irqs_disabled_flags(flags)) {
177 __hard_local_irq_disable();
178 ipipe_trace_begin(0x80000001);
179 }
180 return flags;
181}
182
183static inline void hard_local_irq_restore(unsigned long flags)
184{
185 if (!hard_irqs_disabled_flags(flags)) {
186 ipipe_trace_end(0x80000001);
187 __hard_local_irq_enable();
188 }
189}
190
Philippe Gerum06ecc192009-06-16 05:25:37 +0200191#else /* !CONFIG_IPIPE_TRACE_IRQSOFF */
David Howells3b139cd2010-10-07 14:08:52 +0100192# define hard_local_irq_disable() __hard_local_irq_disable()
193# define hard_local_irq_enable() __hard_local_irq_enable()
194# define hard_local_irq_save() __hard_local_irq_save()
195# define hard_local_irq_restore(flags) __hard_local_irq_restore(flags)
Philippe Gerum06ecc192009-06-16 05:25:37 +0200196#endif /* !CONFIG_IPIPE_TRACE_IRQSOFF */
197
198#else /* CONFIG_IPIPE */
199
David Howells3b139cd2010-10-07 14:08:52 +0100200/*
201 * Direct interface to linux/irqflags.h.
202 */
203#define arch_local_save_flags() hard_local_save_flags()
204#define arch_local_irq_save(flags) __hard_local_irq_save()
205#define arch_local_irq_restore(flags) __hard_local_irq_restore(flags)
206#define arch_local_irq_enable() __hard_local_irq_enable()
207#define arch_local_irq_disable() __hard_local_irq_disable()
208#define arch_irqs_disabled_flags(flags) hard_irqs_disabled_flags(flags)
209#define arch_irqs_disabled() hard_irqs_disabled()
Mike Frysinger8f860012009-06-08 12:49:48 -0400210
David Howells3b139cd2010-10-07 14:08:52 +0100211/*
212 * Interface to various arch routines that may be traced.
213 */
214#define hard_local_irq_save() __hard_local_irq_save()
215#define hard_local_irq_restore(flags) __hard_local_irq_restore(flags)
216#define hard_local_irq_enable() __hard_local_irq_enable()
217#define hard_local_irq_disable() __hard_local_irq_disable()
David Howells5c748742010-10-07 14:08:51 +0100218
Philippe Gerum06ecc192009-06-16 05:25:37 +0200219
220#endif /* !CONFIG_IPIPE */
221
David Howells3b139cd2010-10-07 14:08:52 +0100222/*
223 * Raw interface to linux/irqflags.h.
224 */
225#define raw_local_save_flags(flags) do { (flags) = arch_local_save_flags(); } while (0)
226#define raw_local_irq_save(flags) do { (flags) = arch_local_irq_save(); } while (0)
227#define raw_local_irq_restore(flags) arch_local_irq_restore(flags)
228#define raw_local_irq_enable() arch_local_irq_enable()
229#define raw_local_irq_disable() arch_local_irq_disable()
230#define raw_irqs_disabled_flags(flags) arch_irqs_disabled_flags(flags)
231#define raw_irqs_disabled() arch_irqs_disabled()
Philippe Gerum06ecc192009-06-16 05:25:37 +0200232
Mike Frysinger8f860012009-06-08 12:49:48 -0400233#endif