1 /*
2  * Copyright (c) 2016 Cadence Design Systems, Inc.
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 
6 #ifndef ZEPHYR_INCLUDE_ARCH_XTENSA_XTENSA_IRQ_H_
7 #define ZEPHYR_INCLUDE_ARCH_XTENSA_XTENSA_IRQ_H_
8 
9 #include <stdint.h>
10 
11 #include <zephyr/toolchain.h>
12 #include <xtensa/config/core-isa.h>
13 
14 #define CONFIG_GEN_IRQ_START_VECTOR 0
15 
16 /*
17  * Call this function to enable the specified interrupts.
18  *
19  * mask     - Bit mask of interrupts to be enabled.
20  */
z_xt_ints_on(unsigned int mask)21 static inline void z_xt_ints_on(unsigned int mask)
22 {
23 	int val;
24 
25 	__asm__ volatile("rsr.intenable %0" : "=r"(val));
26 	val |= mask;
27 	__asm__ volatile("wsr.intenable %0; rsync" : : "r"(val));
28 }
29 
30 
31 /*
32  * Call this function to disable the specified interrupts.
33  *
34  * mask     - Bit mask of interrupts to be disabled.
35  */
z_xt_ints_off(unsigned int mask)36 static inline void z_xt_ints_off(unsigned int mask)
37 {
38 	int val;
39 
40 	__asm__ volatile("rsr.intenable %0" : "=r"(val));
41 	val &= ~mask;
42 	__asm__ volatile("wsr.intenable %0; rsync" : : "r"(val));
43 }
44 
45 /*
46  * Call this function to set the specified (s/w) interrupt.
47  */
z_xt_set_intset(unsigned int arg)48 static inline void z_xt_set_intset(unsigned int arg)
49 {
50 #if XCHAL_HAVE_INTERRUPTS
51 	__asm__ volatile("wsr.intset %0; rsync" : : "r"(arg));
52 #else
53 	ARG_UNUSED(arg);
54 #endif
55 }
56 
57 #ifdef CONFIG_MULTI_LEVEL_INTERRUPTS
58 
59 /* for _soc_irq_*() */
60 #include <soc.h>
61 
62 #ifdef CONFIG_2ND_LEVEL_INTERRUPTS
63 #ifdef CONFIG_3RD_LEVEL_INTERRUPTS
64 #define CONFIG_NUM_IRQS (XCHAL_NUM_INTERRUPTS +\
65 			(CONFIG_NUM_2ND_LEVEL_AGGREGATORS +\
66 			CONFIG_NUM_3RD_LEVEL_AGGREGATORS) *\
67 			CONFIG_MAX_IRQ_PER_AGGREGATOR)
68 #else
69 #define CONFIG_NUM_IRQS (XCHAL_NUM_INTERRUPTS +\
70 			CONFIG_NUM_2ND_LEVEL_AGGREGATORS *\
71 			CONFIG_MAX_IRQ_PER_AGGREGATOR)
72 #endif /* CONFIG_3RD_LEVEL_INTERRUPTS */
73 #else
74 #define CONFIG_NUM_IRQS XCHAL_NUM_INTERRUPTS
75 #endif /* CONFIG_2ND_LEVEL_INTERRUPTS */
76 
77 void z_soc_irq_init(void);
78 void z_soc_irq_enable(unsigned int irq);
79 void z_soc_irq_disable(unsigned int irq);
80 int z_soc_irq_is_enabled(unsigned int irq);
81 
82 #define arch_irq_enable(irq)	z_soc_irq_enable(irq)
83 #define arch_irq_disable(irq)	z_soc_irq_disable(irq)
84 
85 #define arch_irq_is_enabled(irq)	z_soc_irq_is_enabled(irq)
86 
87 #ifdef CONFIG_DYNAMIC_INTERRUPTS
88 extern int z_soc_irq_connect_dynamic(unsigned int irq, unsigned int priority,
89 				     void (*routine)(const void *parameter),
90 				     const void *parameter, uint32_t flags);
91 #endif
92 
93 #else
94 
95 #define CONFIG_NUM_IRQS XCHAL_NUM_INTERRUPTS
96 
97 #define arch_irq_enable(irq)	z_xtensa_irq_enable(irq)
98 #define arch_irq_disable(irq)	z_xtensa_irq_disable(irq)
99 
100 #define arch_irq_is_enabled(irq)	z_xtensa_irq_is_enabled(irq)
101 
102 #endif
103 
z_xtensa_irq_enable(uint32_t irq)104 static ALWAYS_INLINE void z_xtensa_irq_enable(uint32_t irq)
105 {
106 	z_xt_ints_on(1 << irq);
107 }
108 
z_xtensa_irq_disable(uint32_t irq)109 static ALWAYS_INLINE void z_xtensa_irq_disable(uint32_t irq)
110 {
111 	z_xt_ints_off(1 << irq);
112 }
113 
arch_irq_lock(void)114 static ALWAYS_INLINE unsigned int arch_irq_lock(void)
115 {
116 	unsigned int key;
117 
118 	__asm__ volatile("rsil %0, %1"
119 			 : "=r"(key) : "i"(XCHAL_EXCM_LEVEL) : "memory");
120 	return key;
121 }
122 
arch_irq_unlock(unsigned int key)123 static ALWAYS_INLINE void arch_irq_unlock(unsigned int key)
124 {
125 	__asm__ volatile("wsr.ps %0; rsync"
126 			 :: "r"(key) : "memory");
127 }
128 
arch_irq_unlocked(unsigned int key)129 static ALWAYS_INLINE bool arch_irq_unlocked(unsigned int key)
130 {
131 	return (key & 0xf) == 0; /* INTLEVEL field */
132 }
133 
134 extern int z_xtensa_irq_is_enabled(unsigned int irq);
135 
136 #include <zephyr/irq.h>
137 
138 #endif /* ZEPHYR_INCLUDE_ARCH_XTENSA_XTENSA_IRQ_H_ */
139