Merge remote-tracking branch 'stable/linux-5.15.y' into rpi-5.15.y
[platform/kernel/linux-rpi.git] / arch / arm / include / asm / irqflags.h
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef __ASM_ARM_IRQFLAGS_H
3 #define __ASM_ARM_IRQFLAGS_H
4
5 #ifdef __KERNEL__
6
7 #include <asm/ptrace.h>
8
9 /*
10  * CPU interrupt mask handling.
11  */
12 #ifdef CONFIG_CPU_V7M
13 #define IRQMASK_REG_NAME_R "primask"
14 #define IRQMASK_REG_NAME_W "primask"
15 #define IRQMASK_I_BIT   1
16 #else
17 #define IRQMASK_REG_NAME_R "cpsr"
18 #define IRQMASK_REG_NAME_W "cpsr_c"
19 #define IRQMASK_I_BIT   PSR_I_BIT
20 #endif
21
22 #if __LINUX_ARM_ARCH__ >= 6
23
24 #define arch_local_irq_save arch_local_irq_save
25 static inline unsigned long arch_local_irq_save(void)
26 {
27         unsigned long flags;
28
29         asm volatile(
30                 "       mrs     %0, " IRQMASK_REG_NAME_R "      @ arch_local_irq_save\n"
31                 "       cpsid   i"
32                 : "=r" (flags) : : "memory", "cc");
33         return flags;
34 }
35
36 #define arch_local_irq_enable arch_local_irq_enable
37 static inline void arch_local_irq_enable(void)
38 {
39         asm volatile(
40                 "       cpsie i                 @ arch_local_irq_enable"
41                 :
42                 :
43                 : "memory", "cc");
44 }
45
46 #define arch_local_irq_disable arch_local_irq_disable
47 static inline void arch_local_irq_disable(void)
48 {
49         asm volatile(
50                 "       cpsid i                 @ arch_local_irq_disable"
51                 :
52                 :
53                 : "memory", "cc");
54 }
55
56 #define local_fiq_enable()  __asm__("cpsie f    @ __stf" : : : "memory", "cc")
57 #define local_fiq_disable() __asm__("cpsid f    @ __clf" : : : "memory", "cc")
58
59 #ifndef CONFIG_CPU_V7M
60 #define local_abt_enable()  __asm__("cpsie a    @ __sta" : : : "memory", "cc")
61 #define local_abt_disable() __asm__("cpsid a    @ __cla" : : : "memory", "cc")
62 #else
63 #define local_abt_enable()      do { } while (0)
64 #define local_abt_disable()     do { } while (0)
65 #endif
66 #else
67
68 /*
69  * Save the current interrupt enable state & disable IRQs
70  */
71 #define arch_local_irq_save arch_local_irq_save
72 static inline unsigned long arch_local_irq_save(void)
73 {
74         unsigned long flags, temp;
75
76         asm volatile(
77                 "       mrs     %0, cpsr        @ arch_local_irq_save\n"
78                 "       orr     %1, %0, #128\n"
79                 "       msr     cpsr_c, %1"
80                 : "=r" (flags), "=r" (temp)
81                 :
82                 : "memory", "cc");
83         return flags;
84 }
85
86 /*
87  * Enable IRQs
88  */
89 #define arch_local_irq_enable arch_local_irq_enable
90 static inline void arch_local_irq_enable(void)
91 {
92         unsigned long temp;
93         asm volatile(
94                 "       mrs     %0, cpsr        @ arch_local_irq_enable\n"
95                 "       bic     %0, %0, #128\n"
96                 "       msr     cpsr_c, %0"
97                 : "=r" (temp)
98                 :
99                 : "memory", "cc");
100 }
101
102 /*
103  * Disable IRQs
104  */
105 #define arch_local_irq_disable arch_local_irq_disable
106 static inline void arch_local_irq_disable(void)
107 {
108         unsigned long temp;
109         asm volatile(
110                 "       mrs     %0, cpsr        @ arch_local_irq_disable\n"
111                 "       orr     %0, %0, #128\n"
112                 "       msr     cpsr_c, %0"
113                 : "=r" (temp)
114                 :
115                 : "memory", "cc");
116 }
117
118 /*
119  * Enable FIQs
120  */
121 #define local_fiq_enable()                                      \
122         ({                                                      \
123                 unsigned long temp;                             \
124         __asm__ __volatile__(                                   \
125         "mrs    %0, cpsr                @ stf\n"                \
126 "       bic     %0, %0, #64\n"                                  \
127 "       msr     cpsr_c, %0"                                     \
128         : "=r" (temp)                                           \
129         :                                                       \
130         : "memory", "cc");                                      \
131         })
132
133 /*
134  * Disable FIQs
135  */
136 #define local_fiq_disable()                                     \
137         ({                                                      \
138                 unsigned long temp;                             \
139         __asm__ __volatile__(                                   \
140         "mrs    %0, cpsr                @ clf\n"                \
141 "       orr     %0, %0, #64\n"                                  \
142 "       msr     cpsr_c, %0"                                     \
143         : "=r" (temp)                                           \
144         :                                                       \
145         : "memory", "cc");                                      \
146         })
147
148 #define local_abt_enable()      do { } while (0)
149 #define local_abt_disable()     do { } while (0)
150 #endif
151
152 /*
153  * Save the current interrupt enable state.
154  */
155 #define arch_local_save_flags arch_local_save_flags
156 static inline unsigned long arch_local_save_flags(void)
157 {
158         unsigned long flags;
159         asm volatile(
160                 "       mrs     %0, " IRQMASK_REG_NAME_R "      @ local_save_flags"
161                 : "=r" (flags) : : "memory", "cc");
162         return flags;
163 }
164
165 /*
166  * restore saved IRQ state
167  */
168 #define arch_local_irq_restore arch_local_irq_restore
169 static inline void arch_local_irq_restore(unsigned long flags)
170 {
171         unsigned long temp = 0;
172         flags &= ~(1 << 6);
173         asm volatile (
174                 " mrs %0, cpsr"
175                 : "=r" (temp)
176                 :
177                 : "memory", "cc");
178                 /* Preserve FIQ bit */
179                 temp &= (1 << 6);
180                 flags = flags | temp;
181         asm volatile (
182                 "    msr    cpsr_c, %0    @ local_irq_restore"
183                 :
184                 : "r" (flags)
185                 : "memory", "cc");
186 }
187
188 #define arch_irqs_disabled_flags arch_irqs_disabled_flags
189 static inline int arch_irqs_disabled_flags(unsigned long flags)
190 {
191         return flags & IRQMASK_I_BIT;
192 }
193
194 #include <asm-generic/irqflags.h>
195
196 #endif /* ifdef __KERNEL__ */
197 #endif /* ifndef __ASM_ARM_IRQFLAGS_H */