| Mike Frysinger | 8f86001 | 2009-06-08 12:49:48 -0400 | [diff] [blame] | 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 |  | 
| David Howells | 5c74874 | 2010-10-07 14:08:51 +0100 | [diff] [blame] | 11 | #include <mach/blackfin.h> | 
 | 12 |  | 
| Mike Frysinger | 8f86001 | 2009-06-08 12:49:48 -0400 | [diff] [blame] | 13 | #ifdef CONFIG_SMP | 
 | 14 | # include <asm/pda.h> | 
 | 15 | # include <asm/processor.h> | 
| Mike Frysinger | 8f86001 | 2009-06-08 12:49:48 -0400 | [diff] [blame] | 16 | # define bfin_irq_flags cpu_pda[blackfin_core_id()].imask | 
 | 17 | #else | 
 | 18 | extern unsigned long bfin_irq_flags; | 
 | 19 | #endif | 
 | 20 |  | 
| Steven Rostedt | a2de3f7 | 2011-07-01 23:04:38 -0400 | [diff] [blame] | 21 | static inline notrace void bfin_sti(unsigned long flags) | 
| Mike Frysinger | 8f86001 | 2009-06-08 12:49:48 -0400 | [diff] [blame] | 22 | { | 
 | 23 | 	asm volatile("sti %0;" : : "d" (flags)); | 
 | 24 | } | 
 | 25 |  | 
| Steven Rostedt | a2de3f7 | 2011-07-01 23:04:38 -0400 | [diff] [blame] | 26 | static inline notrace unsigned long bfin_cli(void) | 
| Mike Frysinger | 8f86001 | 2009-06-08 12:49:48 -0400 | [diff] [blame] | 27 | { | 
 | 28 | 	unsigned long flags; | 
 | 29 | 	asm volatile("cli %0;" : "=d" (flags)); | 
 | 30 | 	return flags; | 
 | 31 | } | 
 | 32 |  | 
| Philippe Gerum | 06ecc19 | 2009-06-16 05:25:37 +0200 | [diff] [blame] | 33 | #ifdef CONFIG_DEBUG_HWERR | 
 | 34 | # define bfin_no_irqs 0x3f | 
 | 35 | #else | 
 | 36 | # define bfin_no_irqs 0x1f | 
 | 37 | #endif | 
 | 38 |  | 
| David Howells | 3b139cd | 2010-10-07 14:08:52 +0100 | [diff] [blame] | 39 | /*****************************************************************************/ | 
 | 40 | /* | 
 | 41 |  * Hard, untraced CPU interrupt flag manipulation and access. | 
 | 42 |  */ | 
| Steven Rostedt | a2de3f7 | 2011-07-01 23:04:38 -0400 | [diff] [blame] | 43 | static inline notrace void __hard_local_irq_disable(void) | 
| David Howells | 3b139cd | 2010-10-07 14:08:52 +0100 | [diff] [blame] | 44 | { | 
 | 45 | 	bfin_cli(); | 
 | 46 | } | 
| Philippe Gerum | 06ecc19 | 2009-06-16 05:25:37 +0200 | [diff] [blame] | 47 |  | 
| Steven Rostedt | a2de3f7 | 2011-07-01 23:04:38 -0400 | [diff] [blame] | 48 | static inline notrace void __hard_local_irq_enable(void) | 
| David Howells | 3b139cd | 2010-10-07 14:08:52 +0100 | [diff] [blame] | 49 | { | 
 | 50 | 	bfin_sti(bfin_irq_flags); | 
 | 51 | } | 
| Philippe Gerum | 06ecc19 | 2009-06-16 05:25:37 +0200 | [diff] [blame] | 52 |  | 
| Steven Rostedt | a2de3f7 | 2011-07-01 23:04:38 -0400 | [diff] [blame] | 53 | static inline notrace unsigned long hard_local_save_flags(void) | 
| David Howells | 3b139cd | 2010-10-07 14:08:52 +0100 | [diff] [blame] | 54 | { | 
 | 55 | 	return bfin_read_IMASK(); | 
 | 56 | } | 
| Philippe Gerum | 06ecc19 | 2009-06-16 05:25:37 +0200 | [diff] [blame] | 57 |  | 
| Steven Rostedt | a2de3f7 | 2011-07-01 23:04:38 -0400 | [diff] [blame] | 58 | static inline notrace unsigned long __hard_local_irq_save(void) | 
| David Howells | 3b139cd | 2010-10-07 14:08:52 +0100 | [diff] [blame] | 59 | { | 
 | 60 | 	unsigned long flags; | 
 | 61 | 	flags = bfin_cli(); | 
 | 62 | #ifdef CONFIG_DEBUG_HWERR | 
 | 63 | 	bfin_sti(0x3f); | 
 | 64 | #endif | 
 | 65 | 	return flags; | 
 | 66 | } | 
| Philippe Gerum | 06ecc19 | 2009-06-16 05:25:37 +0200 | [diff] [blame] | 67 |  | 
| Steven Rostedt | a2de3f7 | 2011-07-01 23:04:38 -0400 | [diff] [blame] | 68 | static inline notrace int hard_irqs_disabled_flags(unsigned long flags) | 
| David Howells | 3b139cd | 2010-10-07 14:08:52 +0100 | [diff] [blame] | 69 | { | 
 | 70 | 	return (flags & ~0x3f) == 0; | 
 | 71 | } | 
| Philippe Gerum | 06ecc19 | 2009-06-16 05:25:37 +0200 | [diff] [blame] | 72 |  | 
| Steven Rostedt | a2de3f7 | 2011-07-01 23:04:38 -0400 | [diff] [blame] | 73 | static inline notrace int hard_irqs_disabled(void) | 
| David Howells | 3b139cd | 2010-10-07 14:08:52 +0100 | [diff] [blame] | 74 | { | 
 | 75 | 	unsigned long flags = hard_local_save_flags(); | 
 | 76 | 	return hard_irqs_disabled_flags(flags); | 
 | 77 | } | 
| Philippe Gerum | 06ecc19 | 2009-06-16 05:25:37 +0200 | [diff] [blame] | 78 |  | 
| Steven Rostedt | a2de3f7 | 2011-07-01 23:04:38 -0400 | [diff] [blame] | 79 | static inline notrace void __hard_local_irq_restore(unsigned long flags) | 
| David Howells | 3b139cd | 2010-10-07 14:08:52 +0100 | [diff] [blame] | 80 | { | 
 | 81 | 	if (!hard_irqs_disabled_flags(flags)) | 
 | 82 | 		__hard_local_irq_enable(); | 
 | 83 | } | 
| Philippe Gerum | 06ecc19 | 2009-06-16 05:25:37 +0200 | [diff] [blame] | 84 |  | 
| David Howells | 3b139cd | 2010-10-07 14:08:52 +0100 | [diff] [blame] | 85 | /*****************************************************************************/ | 
 | 86 | /* | 
 | 87 |  * Interrupt pipe handling. | 
 | 88 |  */ | 
 | 89 | #ifdef CONFIG_IPIPE | 
 | 90 |  | 
 | 91 | #include <linux/compiler.h> | 
| David Howells | 3b139cd | 2010-10-07 14:08:52 +0100 | [diff] [blame] | 92 | #include <linux/ipipe_trace.h> | 
| Philippe Gerum | 1353d05 | 2011-03-17 02:16:16 -0400 | [diff] [blame] | 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 */ | 
| David Howells | 3b139cd | 2010-10-07 14:08:52 +0100 | [diff] [blame] | 112 |  | 
 | 113 | /* | 
 | 114 |  * Interrupt pipe interface to linux/irqflags.h. | 
 | 115 |  */ | 
| Steven Rostedt | a2de3f7 | 2011-07-01 23:04:38 -0400 | [diff] [blame] | 116 | static inline notrace void arch_local_irq_disable(void) | 
| David Howells | 3b139cd | 2010-10-07 14:08:52 +0100 | [diff] [blame] | 117 | { | 
| Philippe Gerum | 1353d05 | 2011-03-17 02:16:16 -0400 | [diff] [blame] | 118 | 	__check_irqop_context(); | 
| David Howells | 3b139cd | 2010-10-07 14:08:52 +0100 | [diff] [blame] | 119 | 	__ipipe_stall_root(); | 
 | 120 | 	barrier(); | 
 | 121 | } | 
 | 122 |  | 
| Steven Rostedt | a2de3f7 | 2011-07-01 23:04:38 -0400 | [diff] [blame] | 123 | static inline notrace void arch_local_irq_enable(void) | 
| David Howells | 3b139cd | 2010-10-07 14:08:52 +0100 | [diff] [blame] | 124 | { | 
 | 125 | 	barrier(); | 
| Philippe Gerum | 1353d05 | 2011-03-17 02:16:16 -0400 | [diff] [blame] | 126 | 	__check_irqop_context(); | 
| David Howells | 3b139cd | 2010-10-07 14:08:52 +0100 | [diff] [blame] | 127 | 	__ipipe_unstall_root(); | 
 | 128 | } | 
 | 129 |  | 
| Steven Rostedt | a2de3f7 | 2011-07-01 23:04:38 -0400 | [diff] [blame] | 130 | static inline notrace unsigned long arch_local_save_flags(void) | 
| David Howells | 3b139cd | 2010-10-07 14:08:52 +0100 | [diff] [blame] | 131 | { | 
 | 132 | 	return __ipipe_test_root() ? bfin_no_irqs : bfin_irq_flags; | 
 | 133 | } | 
 | 134 |  | 
| Steven Rostedt | a2de3f7 | 2011-07-01 23:04:38 -0400 | [diff] [blame] | 135 | static inline notrace int arch_irqs_disabled_flags(unsigned long flags) | 
| David Howells | 3b139cd | 2010-10-07 14:08:52 +0100 | [diff] [blame] | 136 | { | 
 | 137 | 	return flags == bfin_no_irqs; | 
 | 138 | } | 
 | 139 |  | 
| Steven Rostedt | a2de3f7 | 2011-07-01 23:04:38 -0400 | [diff] [blame] | 140 | static inline notrace unsigned long arch_local_irq_save(void) | 
| David Howells | 3b139cd | 2010-10-07 14:08:52 +0100 | [diff] [blame] | 141 | { | 
| Philippe Gerum | 1353d05 | 2011-03-17 02:16:16 -0400 | [diff] [blame] | 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 |  | 
| Steven Rostedt | a2de3f7 | 2011-07-01 23:04:38 -0400 | [diff] [blame] | 151 | static inline notrace void arch_local_irq_restore(unsigned long flags) | 
| Philippe Gerum | 1353d05 | 2011-03-17 02:16:16 -0400 | [diff] [blame] | 152 | { | 
 | 153 | 	__check_irqop_context(); | 
 | 154 | 	__ipipe_restore_root(flags == bfin_no_irqs); | 
| David Howells | 3b139cd | 2010-10-07 14:08:52 +0100 | [diff] [blame] | 155 | } | 
 | 156 |  | 
| Steven Rostedt | a2de3f7 | 2011-07-01 23:04:38 -0400 | [diff] [blame] | 157 | static inline notrace unsigned long arch_mangle_irq_bits(int virt, unsigned long real) | 
| Philippe Gerum | 06ecc19 | 2009-06-16 05:25:37 +0200 | [diff] [blame] | 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 |  | 
| Steven Rostedt | a2de3f7 | 2011-07-01 23:04:38 -0400 | [diff] [blame] | 166 | static inline notrace int arch_demangle_irq_bits(unsigned long *x) | 
| Philippe Gerum | 06ecc19 | 2009-06-16 05:25:37 +0200 | [diff] [blame] | 167 | { | 
 | 168 | 	int virt = (*x & (1 << 31)) != 0; | 
 | 169 | 	*x &= ~(1L << 31); | 
 | 170 | 	return virt; | 
 | 171 | } | 
 | 172 |  | 
| David Howells | 3b139cd | 2010-10-07 14:08:52 +0100 | [diff] [blame] | 173 | /* | 
 | 174 |  * Interface to various arch routines that may be traced. | 
 | 175 |  */ | 
| Philippe Gerum | 06ecc19 | 2009-06-16 05:25:37 +0200 | [diff] [blame] | 176 | #ifdef CONFIG_IPIPE_TRACE_IRQSOFF | 
| Steven Rostedt | a2de3f7 | 2011-07-01 23:04:38 -0400 | [diff] [blame] | 177 | static inline notrace void hard_local_irq_disable(void) | 
| David Howells | 3b139cd | 2010-10-07 14:08:52 +0100 | [diff] [blame] | 178 | { | 
 | 179 | 	if (!hard_irqs_disabled()) { | 
 | 180 | 		__hard_local_irq_disable(); | 
 | 181 | 		ipipe_trace_begin(0x80000000); | 
 | 182 | 	} | 
 | 183 | } | 
 | 184 |  | 
| Steven Rostedt | a2de3f7 | 2011-07-01 23:04:38 -0400 | [diff] [blame] | 185 | static inline notrace void hard_local_irq_enable(void) | 
| David Howells | 3b139cd | 2010-10-07 14:08:52 +0100 | [diff] [blame] | 186 | { | 
 | 187 | 	if (hard_irqs_disabled()) { | 
 | 188 | 		ipipe_trace_end(0x80000000); | 
 | 189 | 		__hard_local_irq_enable(); | 
 | 190 | 	} | 
 | 191 | } | 
 | 192 |  | 
| Steven Rostedt | a2de3f7 | 2011-07-01 23:04:38 -0400 | [diff] [blame] | 193 | static inline notrace unsigned long hard_local_irq_save(void) | 
| David Howells | 3b139cd | 2010-10-07 14:08:52 +0100 | [diff] [blame] | 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 |  | 
| Steven Rostedt | a2de3f7 | 2011-07-01 23:04:38 -0400 | [diff] [blame] | 203 | static inline notrace void hard_local_irq_restore(unsigned long flags) | 
| David Howells | 3b139cd | 2010-10-07 14:08:52 +0100 | [diff] [blame] | 204 | { | 
 | 205 | 	if (!hard_irqs_disabled_flags(flags)) { | 
 | 206 | 		ipipe_trace_end(0x80000001); | 
 | 207 | 		__hard_local_irq_enable(); | 
 | 208 | 	} | 
 | 209 | } | 
 | 210 |  | 
| Philippe Gerum | 06ecc19 | 2009-06-16 05:25:37 +0200 | [diff] [blame] | 211 | #else /* !CONFIG_IPIPE_TRACE_IRQSOFF */ | 
| David Howells | 3b139cd | 2010-10-07 14:08:52 +0100 | [diff] [blame] | 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) | 
| Philippe Gerum | 06ecc19 | 2009-06-16 05:25:37 +0200 | [diff] [blame] | 216 | #endif /* !CONFIG_IPIPE_TRACE_IRQSOFF */ | 
 | 217 |  | 
| Philippe Gerum | 1353d05 | 2011-03-17 02:16:16 -0400 | [diff] [blame] | 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 */ | 
| Philippe Gerum | 06ecc19 | 2009-06-16 05:25:37 +0200 | [diff] [blame] | 222 |  | 
| David Howells | 3b139cd | 2010-10-07 14:08:52 +0100 | [diff] [blame] | 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() | 
| Mike Frysinger | 8f86001 | 2009-06-08 12:49:48 -0400 | [diff] [blame] | 233 |  | 
| David Howells | 3b139cd | 2010-10-07 14:08:52 +0100 | [diff] [blame] | 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() | 
| Philippe Gerum | 1353d05 | 2011-03-17 02:16:16 -0400 | [diff] [blame] | 241 | #define hard_local_irq_save_cond()		hard_local_save_flags() | 
 | 242 | #define hard_local_irq_restore_cond(flags)	do { (void)(flags); } while (0) | 
| Philippe Gerum | 06ecc19 | 2009-06-16 05:25:37 +0200 | [diff] [blame] | 243 |  | 
 | 244 | #endif /* !CONFIG_IPIPE */ | 
| Philippe Gerum | 1353d05 | 2011-03-17 02:16:16 -0400 | [diff] [blame] | 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 |  | 
| Mike Frysinger | 8f86001 | 2009-06-08 12:49:48 -0400 | [diff] [blame] | 285 | #endif |