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
arch_local_irq_save(void)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
arch_local_irq_enable(void)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
arch_local_irq_disable(void)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
arch_local_irq_save(void)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
arch_local_irq_enable(void)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
arch_local_irq_disable(void)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
arch_local_save_flags(void)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 & FIQ state
167  */
168 #define arch_local_irq_restore arch_local_irq_restore
arch_local_irq_restore(unsigned long flags)169 static inline void arch_local_irq_restore(unsigned long flags)
170 {
171 	asm volatile(
172 		"	msr	" IRQMASK_REG_NAME_W ", %0	@ local_irq_restore"
173 		:
174 		: "r" (flags)
175 		: "memory", "cc");
176 }
177 
178 #define arch_irqs_disabled_flags arch_irqs_disabled_flags
arch_irqs_disabled_flags(unsigned long flags)179 static inline int arch_irqs_disabled_flags(unsigned long flags)
180 {
181 	return flags & IRQMASK_I_BIT;
182 }
183 
184 #include <asm-generic/irqflags.h>
185 
186 #endif /* ifdef __KERNEL__ */
187 #endif /* ifndef __ASM_ARM_IRQFLAGS_H */
188