GNU Linux-libre 4.14.266-gnu1
[releases.git] / arch / metag / include / asm / irqflags.h
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * IRQ flags handling
4  *
5  * This file gets included from lowlevel asm headers too, to provide
6  * wrapped versions of the local_irq_*() APIs, based on the
7  * raw_local_irq_*() functions from the lowlevel headers.
8  */
9 #ifndef _ASM_IRQFLAGS_H
10 #define _ASM_IRQFLAGS_H
11
12 #ifndef __ASSEMBLY__
13
14 #include <asm/core_reg.h>
15 #include <asm/metag_regs.h>
16
17 #define INTS_OFF_MASK TXSTATI_BGNDHALT_BIT
18
19 #ifdef CONFIG_SMP
20 extern unsigned int get_trigger_mask(void);
21 #else
22
23 extern unsigned int global_trigger_mask;
24
25 static inline unsigned int get_trigger_mask(void)
26 {
27         return global_trigger_mask;
28 }
29 #endif
30
31 static inline unsigned long arch_local_save_flags(void)
32 {
33         return __core_reg_get(TXMASKI);
34 }
35
36 static inline int arch_irqs_disabled_flags(unsigned long flags)
37 {
38         return (flags & ~INTS_OFF_MASK) == 0;
39 }
40
41 static inline int arch_irqs_disabled(void)
42 {
43         unsigned long flags = arch_local_save_flags();
44
45         return arch_irqs_disabled_flags(flags);
46 }
47
48 static inline unsigned long __irqs_disabled(void)
49 {
50         /*
51          * We shouldn't enable exceptions if they are not already
52          * enabled. This is required for chancalls to work correctly.
53          */
54         return arch_local_save_flags() & INTS_OFF_MASK;
55 }
56
57 /*
58  * For spinlocks, etc:
59  */
60 static inline unsigned long arch_local_irq_save(void)
61 {
62         unsigned long flags = __irqs_disabled();
63
64         asm volatile("SWAP %0,TXMASKI\n" : "=r" (flags) : "0" (flags)
65                      : "memory");
66
67         return flags;
68 }
69
70 static inline void arch_local_irq_restore(unsigned long flags)
71 {
72         asm volatile("MOV TXMASKI,%0\n" : : "r" (flags) : "memory");
73 }
74
75 static inline void arch_local_irq_disable(void)
76 {
77         unsigned long flags = __irqs_disabled();
78
79         asm volatile("MOV TXMASKI,%0\n" : : "r" (flags) : "memory");
80 }
81
82 #ifdef CONFIG_SMP
83 /* Avoid circular include dependencies through <linux/preempt.h> */
84 void arch_local_irq_enable(void);
85 #else
86 static inline void arch_local_irq_enable(void)
87 {
88         arch_local_irq_restore(get_trigger_mask());
89 }
90 #endif
91
92 #endif /* (__ASSEMBLY__) */
93
94 #endif /* !(_ASM_IRQFLAGS_H) */