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 #ifdef CONFIG_BF60x 71 return (flags & IMASK_IVG11) == 0; 72 #else 73 return (flags & ~0x3f) == 0; 74 #endif 75 } 76 hard_irqs_disabled(void)77static inline notrace int hard_irqs_disabled(void) 78 { 79 unsigned long flags = hard_local_save_flags(); 80 return hard_irqs_disabled_flags(flags); 81 } 82 __hard_local_irq_restore(unsigned long flags)83static inline notrace void __hard_local_irq_restore(unsigned long flags) 84 { 85 if (!hard_irqs_disabled_flags(flags)) 86 __hard_local_irq_enable(); 87 } 88 89 /*****************************************************************************/ 90 /* 91 * Interrupt pipe handling. 92 */ 93 #ifdef CONFIG_IPIPE 94 95 #include <linux/compiler.h> 96 #include <linux/ipipe_trace.h> 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 */ 102 void __ipipe_stall_root(void); 103 void __ipipe_unstall_root(void); 104 unsigned long __ipipe_test_root(void); 105 unsigned long __ipipe_test_and_stall_root(void); 106 void __ipipe_restore_root(unsigned long flags); 107 108 #ifdef CONFIG_IPIPE_DEBUG_CONTEXT 109 struct ipipe_domain; 110 extern struct ipipe_domain ipipe_root; 111 void 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 */ 116 117 /* 118 * Interrupt pipe interface to linux/irqflags.h. 119 */ arch_local_irq_disable(void)120static inline notrace void arch_local_irq_disable(void) 121 { 122 __check_irqop_context(); 123 __ipipe_stall_root(); 124 barrier(); 125 } 126 arch_local_irq_enable(void)127static inline notrace void arch_local_irq_enable(void) 128 { 129 barrier(); 130 __check_irqop_context(); 131 __ipipe_unstall_root(); 132 } 133 arch_local_save_flags(void)134static inline notrace unsigned long arch_local_save_flags(void) 135 { 136 return __ipipe_test_root() ? bfin_no_irqs : bfin_irq_flags; 137 } 138 arch_irqs_disabled_flags(unsigned long flags)139static inline notrace int arch_irqs_disabled_flags(unsigned long flags) 140 { 141 return flags == bfin_no_irqs; 142 } 143 arch_local_irq_save(void)144static inline notrace unsigned long arch_local_irq_save(void) 145 { 146 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 arch_local_irq_restore(unsigned long flags)155static inline notrace void arch_local_irq_restore(unsigned long flags) 156 { 157 __check_irqop_context(); 158 __ipipe_restore_root(flags == bfin_no_irqs); 159 } 160 arch_mangle_irq_bits(int virt,unsigned long real)161static inline notrace unsigned long arch_mangle_irq_bits(int virt, unsigned long real) 162 { 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 arch_demangle_irq_bits(unsigned long * x)170static inline notrace int arch_demangle_irq_bits(unsigned long *x) 171 { 172 int virt = (*x & (1 << 31)) != 0; 173 *x &= ~(1L << 31); 174 return virt; 175 } 176 177 /* 178 * Interface to various arch routines that may be traced. 179 */ 180 #ifdef CONFIG_IPIPE_TRACE_IRQSOFF hard_local_irq_disable(void)181static inline notrace void hard_local_irq_disable(void) 182 { 183 if (!hard_irqs_disabled()) { 184 __hard_local_irq_disable(); 185 ipipe_trace_begin(0x80000000); 186 } 187 } 188 hard_local_irq_enable(void)189static inline notrace void hard_local_irq_enable(void) 190 { 191 if (hard_irqs_disabled()) { 192 ipipe_trace_end(0x80000000); 193 __hard_local_irq_enable(); 194 } 195 } 196 hard_local_irq_save(void)197static inline notrace unsigned long hard_local_irq_save(void) 198 { 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 hard_local_irq_restore(unsigned long flags)207static inline notrace void hard_local_irq_restore(unsigned long flags) 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 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 */ 226 227 /* 228 * Direct interface to linux/irqflags.h. 229 */ 230 #define arch_local_save_flags() hard_local_save_flags() 231 #define arch_local_irq_save() __hard_local_irq_save() 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() 245 #define hard_local_irq_save_cond() hard_local_save_flags() 246 #define hard_local_irq_restore_cond(flags) do { (void)(flags); } while (0) 247 248 #endif /* !CONFIG_IPIPE */ 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 289 #endif 290