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 11 #include <mach/blackfin.h> 12 13 #ifdef CONFIG_SMP 14 # include <asm/pda.h> 15 # include <asm/processor.h> 16 # define bfin_irq_flags cpu_pda[blackfin_core_id()].imask 17 #else 18 extern unsigned long bfin_irq_flags; 19 #endif 20 bfin_sti(unsigned long flags)21static inline notrace void bfin_sti(unsigned long flags) 22 { 23 asm volatile("sti %0;" : : "d" (flags)); 24 } 25 bfin_cli(void)26static inline notrace unsigned long bfin_cli(void) 27 { 28 unsigned long flags; 29 asm volatile("cli %0;" : "=d" (flags)); 30 return flags; 31 } 32 33 #ifdef CONFIG_DEBUG_HWERR 34 # define bfin_no_irqs 0x3f 35 #else 36 # define bfin_no_irqs 0x1f 37 #endif 38 39 /*****************************************************************************/ 40 /* 41 * Hard, untraced CPU interrupt flag manipulation and access. 42 */ __hard_local_irq_disable(void)43static inline notrace void __hard_local_irq_disable(void) 44 { 45 bfin_cli(); 46 } 47 __hard_local_irq_enable(void)48static inline notrace void __hard_local_irq_enable(void) 49 { 50 bfin_sti(bfin_irq_flags); 51 } 52 hard_local_save_flags(void)53static inline notrace unsigned long hard_local_save_flags(void) 54 { 55 return bfin_read_IMASK(); 56 } 57 __hard_local_irq_save(void)58static inline notrace unsigned long __hard_local_irq_save(void) 59 { 60 unsigned long flags; 61 flags = bfin_cli(); 62 #ifdef CONFIG_DEBUG_HWERR 63 bfin_sti(0x3f); 64 #endif 65 return flags; 66 } 67 hard_irqs_disabled_flags(unsigned long flags)68static inline notrace int hard_irqs_disabled_flags(unsigned long flags) 69 { 70 return (flags & ~0x3f) == 0; 71 } 72 hard_irqs_disabled(void)73static inline notrace int hard_irqs_disabled(void) 74 { 75 unsigned long flags = hard_local_save_flags(); 76 return hard_irqs_disabled_flags(flags); 77 } 78 __hard_local_irq_restore(unsigned long flags)79static inline notrace void __hard_local_irq_restore(unsigned long flags) 80 { 81 if (!hard_irqs_disabled_flags(flags)) 82 __hard_local_irq_enable(); 83 } 84 85 /*****************************************************************************/ 86 /* 87 * Interrupt pipe handling. 88 */ 89 #ifdef CONFIG_IPIPE 90 91 #include <linux/compiler.h> 92 #include <linux/ipipe_trace.h> 93 /* 94 * Way too many inter-deps between low-level headers in this port, so 95 * we redeclare the required bits we cannot pick from 96 * <asm/ipipe_base.h> to prevent circular dependencies. 97 */ 98 void __ipipe_stall_root(void); 99 void __ipipe_unstall_root(void); 100 unsigned long __ipipe_test_root(void); 101 unsigned long __ipipe_test_and_stall_root(void); 102 void __ipipe_restore_root(unsigned long flags); 103 104 #ifdef CONFIG_IPIPE_DEBUG_CONTEXT 105 struct ipipe_domain; 106 extern struct ipipe_domain ipipe_root; 107 void ipipe_check_context(struct ipipe_domain *ipd); 108 #define __check_irqop_context(ipd) ipipe_check_context(&ipipe_root) 109 #else /* !CONFIG_IPIPE_DEBUG_CONTEXT */ 110 #define __check_irqop_context(ipd) do { } while (0) 111 #endif /* !CONFIG_IPIPE_DEBUG_CONTEXT */ 112 113 /* 114 * Interrupt pipe interface to linux/irqflags.h. 115 */ arch_local_irq_disable(void)116static inline notrace void arch_local_irq_disable(void) 117 { 118 __check_irqop_context(); 119 __ipipe_stall_root(); 120 barrier(); 121 } 122 arch_local_irq_enable(void)123static inline notrace void arch_local_irq_enable(void) 124 { 125 barrier(); 126 __check_irqop_context(); 127 __ipipe_unstall_root(); 128 } 129 arch_local_save_flags(void)130static inline notrace unsigned long arch_local_save_flags(void) 131 { 132 return __ipipe_test_root() ? bfin_no_irqs : bfin_irq_flags; 133 } 134 arch_irqs_disabled_flags(unsigned long flags)135static inline notrace int arch_irqs_disabled_flags(unsigned long flags) 136 { 137 return flags == bfin_no_irqs; 138 } 139 arch_local_irq_save(void)140static inline notrace unsigned long arch_local_irq_save(void) 141 { 142 unsigned long flags; 143 144 __check_irqop_context(); 145 flags = __ipipe_test_and_stall_root() ? bfin_no_irqs : bfin_irq_flags; 146 barrier(); 147 148 return flags; 149 } 150 arch_local_irq_restore(unsigned long flags)151static inline notrace void arch_local_irq_restore(unsigned long flags) 152 { 153 __check_irqop_context(); 154 __ipipe_restore_root(flags == bfin_no_irqs); 155 } 156 arch_mangle_irq_bits(int virt,unsigned long real)157static inline notrace unsigned long arch_mangle_irq_bits(int virt, unsigned long real) 158 { 159 /* 160 * Merge virtual and real interrupt mask bits into a single 161 * 32bit word. 162 */ 163 return (real & ~(1 << 31)) | ((virt != 0) << 31); 164 } 165 arch_demangle_irq_bits(unsigned long * x)166static inline notrace int arch_demangle_irq_bits(unsigned long *x) 167 { 168 int virt = (*x & (1 << 31)) != 0; 169 *x &= ~(1L << 31); 170 return virt; 171 } 172 173 /* 174 * Interface to various arch routines that may be traced. 175 */ 176 #ifdef CONFIG_IPIPE_TRACE_IRQSOFF hard_local_irq_disable(void)177static inline notrace void hard_local_irq_disable(void) 178 { 179 if (!hard_irqs_disabled()) { 180 __hard_local_irq_disable(); 181 ipipe_trace_begin(0x80000000); 182 } 183 } 184 hard_local_irq_enable(void)185static inline notrace void hard_local_irq_enable(void) 186 { 187 if (hard_irqs_disabled()) { 188 ipipe_trace_end(0x80000000); 189 __hard_local_irq_enable(); 190 } 191 } 192 hard_local_irq_save(void)193static inline notrace unsigned long hard_local_irq_save(void) 194 { 195 unsigned long flags = hard_local_save_flags(); 196 if (!hard_irqs_disabled_flags(flags)) { 197 __hard_local_irq_disable(); 198 ipipe_trace_begin(0x80000001); 199 } 200 return flags; 201 } 202 hard_local_irq_restore(unsigned long flags)203static inline notrace void hard_local_irq_restore(unsigned long flags) 204 { 205 if (!hard_irqs_disabled_flags(flags)) { 206 ipipe_trace_end(0x80000001); 207 __hard_local_irq_enable(); 208 } 209 } 210 211 #else /* !CONFIG_IPIPE_TRACE_IRQSOFF */ 212 # define hard_local_irq_disable() __hard_local_irq_disable() 213 # define hard_local_irq_enable() __hard_local_irq_enable() 214 # define hard_local_irq_save() __hard_local_irq_save() 215 # define hard_local_irq_restore(flags) __hard_local_irq_restore(flags) 216 #endif /* !CONFIG_IPIPE_TRACE_IRQSOFF */ 217 218 #define hard_local_irq_save_cond() hard_local_irq_save() 219 #define hard_local_irq_restore_cond(flags) hard_local_irq_restore(flags) 220 221 #else /* !CONFIG_IPIPE */ 222 223 /* 224 * Direct interface to linux/irqflags.h. 225 */ 226 #define arch_local_save_flags() hard_local_save_flags() 227 #define arch_local_irq_save(flags) __hard_local_irq_save() 228 #define arch_local_irq_restore(flags) __hard_local_irq_restore(flags) 229 #define arch_local_irq_enable() __hard_local_irq_enable() 230 #define arch_local_irq_disable() __hard_local_irq_disable() 231 #define arch_irqs_disabled_flags(flags) hard_irqs_disabled_flags(flags) 232 #define arch_irqs_disabled() hard_irqs_disabled() 233 234 /* 235 * Interface to various arch routines that may be traced. 236 */ 237 #define hard_local_irq_save() __hard_local_irq_save() 238 #define hard_local_irq_restore(flags) __hard_local_irq_restore(flags) 239 #define hard_local_irq_enable() __hard_local_irq_enable() 240 #define hard_local_irq_disable() __hard_local_irq_disable() 241 #define hard_local_irq_save_cond() hard_local_save_flags() 242 #define hard_local_irq_restore_cond(flags) do { (void)(flags); } while (0) 243 244 #endif /* !CONFIG_IPIPE */ 245 246 #ifdef CONFIG_SMP 247 #define hard_local_irq_save_smp() hard_local_irq_save() 248 #define hard_local_irq_restore_smp(flags) hard_local_irq_restore(flags) 249 #else 250 #define hard_local_irq_save_smp() hard_local_save_flags() 251 #define hard_local_irq_restore_smp(flags) do { (void)(flags); } while (0) 252 #endif 253 254 /* 255 * Remap the arch-neutral IRQ state manipulation macros to the 256 * blackfin-specific hard_local_irq_* API. 257 */ 258 #define local_irq_save_hw(flags) \ 259 do { \ 260 (flags) = hard_local_irq_save(); \ 261 } while (0) 262 #define local_irq_restore_hw(flags) \ 263 do { \ 264 hard_local_irq_restore(flags); \ 265 } while (0) 266 #define local_irq_disable_hw() \ 267 do { \ 268 hard_local_irq_disable(); \ 269 } while (0) 270 #define local_irq_enable_hw() \ 271 do { \ 272 hard_local_irq_enable(); \ 273 } while (0) 274 #define local_irq_save_hw_notrace(flags) \ 275 do { \ 276 (flags) = __hard_local_irq_save(); \ 277 } while (0) 278 #define local_irq_restore_hw_notrace(flags) \ 279 do { \ 280 __hard_local_irq_restore(flags); \ 281 } while (0) 282 283 #define irqs_disabled_hw() hard_irqs_disabled() 284 285 #endif 286