1 /* 2 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 as 6 * published by the Free Software Foundation. 7 */ 8 9 #ifndef __ASM_ARC_IRQFLAGS_H 10 #define __ASM_ARC_IRQFLAGS_H 11 12 /* vineetg: March 2010 : local_irq_save( ) optimisation 13 * -Remove explicit mov of current status32 into reg, that is not needed 14 * -Use BIC insn instead of INVERTED + AND 15 * -Conditionally disable interrupts (if they are not enabled, don't disable) 16 */ 17 18 #include <asm/arcregs.h> 19 20 /* status32 Reg bits related to Interrupt Handling */ 21 #define STATUS_E1_BIT 1 /* Int 1 enable */ 22 #define STATUS_E2_BIT 2 /* Int 2 enable */ 23 #define STATUS_A1_BIT 3 /* Int 1 active */ 24 #define STATUS_A2_BIT 4 /* Int 2 active */ 25 26 #define STATUS_E1_MASK (1<<STATUS_E1_BIT) 27 #define STATUS_E2_MASK (1<<STATUS_E2_BIT) 28 #define STATUS_A1_MASK (1<<STATUS_A1_BIT) 29 #define STATUS_A2_MASK (1<<STATUS_A2_BIT) 30 31 /* Other Interrupt Handling related Aux regs */ 32 #define AUX_IRQ_LEV 0x200 /* IRQ Priority: L1 or L2 */ 33 #define AUX_IRQ_HINT 0x201 /* For generating Soft Interrupts */ 34 #define AUX_IRQ_LV12 0x43 /* interrupt level register */ 35 36 #define AUX_IENABLE 0x40c 37 #define AUX_ITRIGGER 0x40d 38 #define AUX_IPULSE 0x415 39 40 #ifndef __ASSEMBLY__ 41 42 /****************************************************************** 43 * IRQ Control Macros 44 ******************************************************************/ 45 46 /* 47 * Save IRQ state and disable IRQs 48 */ 49 static inline long arch_local_irq_save(void) 50 { 51 unsigned long temp, flags; 52 53 __asm__ __volatile__( 54 " lr %1, [status32] \n" 55 " bic %0, %1, %2 \n" 56 " and.f 0, %1, %2 \n" 57 " flag.nz %0 \n" 58 : "=r"(temp), "=r"(flags) 59 : "n"((STATUS_E1_MASK | STATUS_E2_MASK)) 60 : "memory", "cc"); 61 62 return flags; 63 } 64 65 /* 66 * restore saved IRQ state 67 */ 68 static inline void arch_local_irq_restore(unsigned long flags) 69 { 70 71 __asm__ __volatile__( 72 " flag %0 \n" 73 : 74 : "r"(flags) 75 : "memory"); 76 } 77 78 /* 79 * Unconditionally Enable IRQs 80 */ 81 extern void arch_local_irq_enable(void); 82 83 /* 84 * Unconditionally Disable IRQs 85 */ 86 static inline void arch_local_irq_disable(void) 87 { 88 unsigned long temp; 89 90 __asm__ __volatile__( 91 " lr %0, [status32] \n" 92 " and %0, %0, %1 \n" 93 " flag %0 \n" 94 : "=&r"(temp) 95 : "n"(~(STATUS_E1_MASK | STATUS_E2_MASK)) 96 : "memory"); 97 } 98 99 /* 100 * save IRQ state 101 */ 102 static inline long arch_local_save_flags(void) 103 { 104 unsigned long temp; 105 106 __asm__ __volatile__( 107 " lr %0, [status32] \n" 108 : "=&r"(temp) 109 : 110 : "memory"); 111 112 return temp; 113 } 114 115 /* 116 * Query IRQ state 117 */ 118 static inline int arch_irqs_disabled_flags(unsigned long flags) 119 { 120 return !(flags & (STATUS_E1_MASK 121 #ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS 122 | STATUS_E2_MASK 123 #endif 124 )); 125 } 126 127 static inline int arch_irqs_disabled(void) 128 { 129 return arch_irqs_disabled_flags(arch_local_save_flags()); 130 } 131 132 #else 133 134 #ifdef CONFIG_TRACE_IRQFLAGS 135 136 .macro TRACE_ASM_IRQ_DISABLE 137 bl trace_hardirqs_off 138 .endm 139 140 .macro TRACE_ASM_IRQ_ENABLE 141 bl trace_hardirqs_on 142 .endm 143 144 #else 145 146 .macro TRACE_ASM_IRQ_DISABLE 147 .endm 148 149 .macro TRACE_ASM_IRQ_ENABLE 150 .endm 151 152 #endif 153 154 .macro IRQ_DISABLE scratch 155 lr \scratch, [status32] 156 bic \scratch, \scratch, (STATUS_E1_MASK | STATUS_E2_MASK) 157 flag \scratch 158 TRACE_ASM_IRQ_DISABLE 159 .endm 160 161 .macro IRQ_ENABLE scratch 162 lr \scratch, [status32] 163 or \scratch, \scratch, (STATUS_E1_MASK | STATUS_E2_MASK) 164 flag \scratch 165 TRACE_ASM_IRQ_ENABLE 166 .endm 167 168 #endif /* __ASSEMBLY__ */ 169 170 #endif 171