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