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 18extern unsigned long bfin_irq_flags; 19#endif 20 21static inline notrace void bfin_sti(unsigned long flags) 22{ 23 asm volatile("sti %0;" : : "d" (flags)); 24} 25 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 */ 43static inline notrace void __hard_local_irq_disable(void) 44{ 45 bfin_cli(); 46} 47 48static inline notrace void __hard_local_irq_enable(void) 49{ 50 bfin_sti(bfin_irq_flags); 51} 52 53static inline notrace unsigned long hard_local_save_flags(void) 54{ 55 return bfin_read_IMASK(); 56} 57 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 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 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 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 */ 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 */ 116 117/* 118 * Interrupt pipe interface to linux/irqflags.h. 119 */ 120static inline notrace void arch_local_irq_disable(void) 121{ 122 __check_irqop_context(); 123 __ipipe_stall_root(); 124 barrier(); 125} 126 127static inline notrace void arch_local_irq_enable(void) 128{ 129 barrier(); 130 __check_irqop_context(); 131 __ipipe_unstall_root(); 132} 133 134static inline notrace unsigned long arch_local_save_flags(void) 135{ 136 return __ipipe_test_root() ? bfin_no_irqs : bfin_irq_flags; 137} 138 139static inline notrace int arch_irqs_disabled_flags(unsigned long flags) 140{ 141 return flags == bfin_no_irqs; 142} 143 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 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 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 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 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 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 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 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