1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  *    Copyright IBM Corp. 2006, 2010
4  *    Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
5  */
6 
7 #ifndef __ASM_IRQFLAGS_H
8 #define __ASM_IRQFLAGS_H
9 
10 #include <linux/types.h>
11 
12 #define ARCH_IRQ_ENABLED	(3UL << (BITS_PER_LONG - 8))
13 
14 /* store then OR system mask. */
15 #define __arch_local_irq_stosm(__or)					\
16 ({									\
17 	unsigned long __mask;						\
18 	asm volatile(							\
19 		"	stosm	%0,%1"					\
20 		: "=Q" (__mask) : "i" (__or) : "memory");		\
21 	__mask;								\
22 })
23 
24 /* store then AND system mask. */
25 #define __arch_local_irq_stnsm(__and)					\
26 ({									\
27 	unsigned long __mask;						\
28 	asm volatile(							\
29 		"	stnsm	%0,%1"					\
30 		: "=Q" (__mask) : "i" (__and) : "memory");		\
31 	__mask;								\
32 })
33 
34 /* set system mask. */
__arch_local_irq_ssm(unsigned long flags)35 static __always_inline void __arch_local_irq_ssm(unsigned long flags)
36 {
37 	asm volatile("ssm   %0" : : "Q" (flags) : "memory");
38 }
39 
arch_local_save_flags(void)40 static __always_inline unsigned long arch_local_save_flags(void)
41 {
42 	return __arch_local_irq_stnsm(0xff);
43 }
44 
arch_local_irq_save(void)45 static __always_inline unsigned long arch_local_irq_save(void)
46 {
47 	return __arch_local_irq_stnsm(0xfc);
48 }
49 
arch_local_irq_disable(void)50 static __always_inline void arch_local_irq_disable(void)
51 {
52 	arch_local_irq_save();
53 }
54 
arch_local_irq_enable(void)55 static __always_inline void arch_local_irq_enable(void)
56 {
57 	__arch_local_irq_stosm(0x03);
58 }
59 
60 /* This only restores external and I/O interrupt state */
arch_local_irq_restore(unsigned long flags)61 static __always_inline void arch_local_irq_restore(unsigned long flags)
62 {
63 	/* only disabled->disabled and disabled->enabled is valid */
64 	if (flags & ARCH_IRQ_ENABLED)
65 		arch_local_irq_enable();
66 }
67 
arch_irqs_disabled_flags(unsigned long flags)68 static __always_inline bool arch_irqs_disabled_flags(unsigned long flags)
69 {
70 	return !(flags & ARCH_IRQ_ENABLED);
71 }
72 
arch_irqs_disabled(void)73 static __always_inline bool arch_irqs_disabled(void)
74 {
75 	return arch_irqs_disabled_flags(arch_local_save_flags());
76 }
77 
78 #endif /* __ASM_IRQFLAGS_H */
79