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