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
25static 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
37static 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
47static 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
72static 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
90static 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
106static 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
156static 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
169static 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
179static 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