1#ifndef __ASM_ARM_IRQFLAGS_H
2#define __ASM_ARM_IRQFLAGS_H
3
4#ifdef __KERNEL__
5
6#include <asm/ptrace.h>
7
8/*
9 * CPU interrupt mask handling.
10 */
11#ifdef CONFIG_CPU_V7M
12#define IRQMASK_REG_NAME_R "primask"
13#define IRQMASK_REG_NAME_W "primask"
14#define IRQMASK_I_BIT	1
15#else
16#define IRQMASK_REG_NAME_R "cpsr"
17#define IRQMASK_REG_NAME_W "cpsr_c"
18#define IRQMASK_I_BIT	PSR_I_BIT
19#endif
20
21#if __LINUX_ARM_ARCH__ >= 6
22
23static inline unsigned long arch_local_irq_save(void)
24{
25	unsigned long flags;
26
27	asm volatile(
28		"	mrs	%0, " IRQMASK_REG_NAME_R "	@ arch_local_irq_save\n"
29		"	cpsid	i"
30		: "=r" (flags) : : "memory", "cc");
31	return flags;
32}
33
34static inline void arch_local_irq_enable(void)
35{
36	asm volatile(
37		"	cpsie i			@ arch_local_irq_enable"
38		:
39		:
40		: "memory", "cc");
41}
42
43static inline void arch_local_irq_disable(void)
44{
45	asm volatile(
46		"	cpsid i			@ arch_local_irq_disable"
47		:
48		:
49		: "memory", "cc");
50}
51
52#define local_fiq_enable()  __asm__("cpsie f	@ __stf" : : : "memory", "cc")
53#define local_fiq_disable() __asm__("cpsid f	@ __clf" : : : "memory", "cc")
54#else
55
56/*
57 * Save the current interrupt enable state & disable IRQs
58 */
59static inline unsigned long arch_local_irq_save(void)
60{
61	unsigned long flags, temp;
62
63	asm volatile(
64		"	mrs	%0, cpsr	@ arch_local_irq_save\n"
65		"	orr	%1, %0, #128\n"
66		"	msr	cpsr_c, %1"
67		: "=r" (flags), "=r" (temp)
68		:
69		: "memory", "cc");
70	return flags;
71}
72
73/*
74 * Enable IRQs
75 */
76static inline void arch_local_irq_enable(void)
77{
78	unsigned long temp;
79	asm volatile(
80		"	mrs	%0, cpsr	@ arch_local_irq_enable\n"
81		"	bic	%0, %0, #128\n"
82		"	msr	cpsr_c, %0"
83		: "=r" (temp)
84		:
85		: "memory", "cc");
86}
87
88/*
89 * Disable IRQs
90 */
91static inline void arch_local_irq_disable(void)
92{
93	unsigned long temp;
94	asm volatile(
95		"	mrs	%0, cpsr	@ arch_local_irq_disable\n"
96		"	orr	%0, %0, #128\n"
97		"	msr	cpsr_c, %0"
98		: "=r" (temp)
99		:
100		: "memory", "cc");
101}
102
103/*
104 * Enable FIQs
105 */
106#define local_fiq_enable()					\
107	({							\
108		unsigned long temp;				\
109	__asm__ __volatile__(					\
110	"mrs	%0, cpsr		@ stf\n"		\
111"	bic	%0, %0, #64\n"					\
112"	msr	cpsr_c, %0"					\
113	: "=r" (temp)						\
114	:							\
115	: "memory", "cc");					\
116	})
117
118/*
119 * Disable FIQs
120 */
121#define local_fiq_disable()					\
122	({							\
123		unsigned long temp;				\
124	__asm__ __volatile__(					\
125	"mrs	%0, cpsr		@ clf\n"		\
126"	orr	%0, %0, #64\n"					\
127"	msr	cpsr_c, %0"					\
128	: "=r" (temp)						\
129	:							\
130	: "memory", "cc");					\
131	})
132
133#endif
134
135/*
136 * Save the current interrupt enable state.
137 */
138static inline unsigned long arch_local_save_flags(void)
139{
140	unsigned long flags;
141	asm volatile(
142		"	mrs	%0, " IRQMASK_REG_NAME_R "	@ local_save_flags"
143		: "=r" (flags) : : "memory", "cc");
144	return flags;
145}
146
147/*
148 * restore saved IRQ & FIQ state
149 */
150static inline void arch_local_irq_restore(unsigned long flags)
151{
152	asm volatile(
153		"	msr	" IRQMASK_REG_NAME_W ", %0	@ local_irq_restore"
154		:
155		: "r" (flags)
156		: "memory", "cc");
157}
158
159static inline int arch_irqs_disabled_flags(unsigned long flags)
160{
161	return flags & IRQMASK_I_BIT;
162}
163
164#endif /* ifdef __KERNEL__ */
165#endif /* ifndef __ASM_ARM_IRQFLAGS_H */
166