Line data Source code
1 0 : /*
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 0 : #define CONFIG_GEN_IRQ_START_VECTOR 0
15 :
16 : /**
17 : * @cond INTERNAL_HIDDEN
18 : */
19 :
20 : /*
21 : * Call these functions to enable the specified interrupts.
22 : *
23 : * mask - Bit mask of interrupts to be enabled.
24 : */
25 : static inline void z_xt_ints_on(unsigned int mask)
26 : {
27 : int val;
28 :
29 : __asm__ volatile("rsr.intenable %0" : "=r"(val));
30 : val |= mask;
31 : __asm__ volatile("wsr.intenable %0; rsync" : : "r"(val));
32 : }
33 : #if XCHAL_NUM_INTERRUPTS > 32
34 : static inline void z_xt_ints1_on(unsigned int mask)
35 : {
36 : int val;
37 :
38 : __asm__ volatile("rsr.intenable1 %0" : "=r"(val));
39 : val |= mask;
40 : __asm__ volatile("wsr.intenable1 %0; rsync" : : "r"(val));
41 : }
42 : #endif
43 : #if XCHAL_NUM_INTERRUPTS > 64
44 : static inline void z_xt_ints2_on(unsigned int mask)
45 : {
46 : int val;
47 :
48 : __asm__ volatile("rsr.intenable2 %0" : "=r"(val));
49 : val |= mask;
50 : __asm__ volatile("wsr.intenable2 %0; rsync" : : "r"(val));
51 : }
52 : #endif
53 : #if XCHAL_NUM_INTERRUPTS > 96
54 : static inline void z_xt_ints3_on(unsigned int mask)
55 : {
56 : int val;
57 :
58 : __asm__ volatile("rsr.intenable3 %0" : "=r"(val));
59 : val |= mask;
60 : __asm__ volatile("wsr.intenable3 %0; rsync" : : "r"(val));
61 : }
62 : #endif
63 :
64 :
65 : /*
66 : * Call these functions to disable the specified interrupts.
67 : *
68 : * mask - Bit mask of interrupts to be disabled.
69 : */
70 : static inline void z_xt_ints_off(unsigned int mask)
71 : {
72 : int val;
73 :
74 : __asm__ volatile("rsr.intenable %0" : "=r"(val));
75 : val &= ~mask;
76 : __asm__ volatile("wsr.intenable %0; rsync" : : "r"(val));
77 : }
78 : #if XCHAL_NUM_INTERRUPTS > 32
79 : static inline void z_xt_ints1_off(unsigned int mask)
80 : {
81 : int val;
82 :
83 : __asm__ volatile("rsr.intenable1 %0" : "=r"(val));
84 : val &= ~mask;
85 : __asm__ volatile("wsr.intenable1 %0; rsync" : : "r"(val));
86 : }
87 : #endif
88 : #if XCHAL_NUM_INTERRUPTS > 64
89 : static inline void z_xt_ints2_off(unsigned int mask)
90 : {
91 : int val;
92 :
93 : __asm__ volatile("rsr.intenable2 %0" : "=r"(val));
94 : val &= ~mask;
95 : __asm__ volatile("wsr.intenable2 %0; rsync" : : "r"(val));
96 : }
97 : #endif
98 : #if XCHAL_NUM_INTERRUPTS > 96
99 : static inline void z_xt_ints3_off(unsigned int mask)
100 : {
101 : int val;
102 :
103 : __asm__ volatile("rsr.intenable3 %0" : "=r"(val));
104 : val &= ~mask;
105 : __asm__ volatile("wsr.intenable3 %0; rsync" : : "r"(val));
106 : }
107 : #endif
108 :
109 :
110 : /*
111 : * Call these functions to set the specified (s/w) interrupt.
112 : */
113 : static inline void z_xt_set_intset(unsigned int arg)
114 : {
115 : #if XCHAL_HAVE_INTERRUPTS
116 : __asm__ volatile("wsr.intset %0; rsync" : : "r"(arg));
117 : #else
118 : ARG_UNUSED(arg);
119 : #endif
120 : }
121 : #if XCHAL_NUM_INTERRUPTS > 32
122 : static inline void z_xt_set_intset1(unsigned int arg)
123 : {
124 : __asm__ volatile("wsr.intset1 %0; rsync" : : "r"(arg));
125 : }
126 : #endif
127 : #if XCHAL_NUM_INTERRUPTS > 64
128 : static inline void z_xt_set_intset2(unsigned int arg)
129 : {
130 : __asm__ volatile("wsr.intset2 %0; rsync" : : "r"(arg));
131 : }
132 : #endif
133 : #if XCHAL_NUM_INTERRUPTS > 96
134 : static inline void z_xt_set_intset3(unsigned int arg)
135 : {
136 : __asm__ volatile("wsr.intset3 %0; rsync" : : "r"(arg));
137 : }
138 : #endif
139 :
140 :
141 : /**
142 : * INTERNAL_HIDDEN @endcond
143 : */
144 :
145 : #ifdef CONFIG_MULTI_LEVEL_INTERRUPTS
146 :
147 : /* for _soc_irq_*() */
148 : #include <soc.h>
149 :
150 : #ifdef CONFIG_2ND_LEVEL_INTERRUPTS
151 : #ifdef CONFIG_3RD_LEVEL_INTERRUPTS
152 : #define CONFIG_NUM_IRQS (XCHAL_NUM_INTERRUPTS +\
153 : (CONFIG_NUM_2ND_LEVEL_AGGREGATORS +\
154 : CONFIG_NUM_3RD_LEVEL_AGGREGATORS) *\
155 : CONFIG_MAX_IRQ_PER_AGGREGATOR)
156 : #else
157 : #define CONFIG_NUM_IRQS (XCHAL_NUM_INTERRUPTS +\
158 : CONFIG_NUM_2ND_LEVEL_AGGREGATORS *\
159 : CONFIG_MAX_IRQ_PER_AGGREGATOR)
160 : #endif /* CONFIG_3RD_LEVEL_INTERRUPTS */
161 : #else
162 : #define CONFIG_NUM_IRQS XCHAL_NUM_INTERRUPTS
163 : #endif /* CONFIG_2ND_LEVEL_INTERRUPTS */
164 :
165 : void z_soc_irq_init(void);
166 : void z_soc_irq_enable(unsigned int irq);
167 : void z_soc_irq_disable(unsigned int irq);
168 : int z_soc_irq_is_enabled(unsigned int irq);
169 :
170 : #define arch_irq_enable(irq) z_soc_irq_enable(irq)
171 : #define arch_irq_disable(irq) z_soc_irq_disable(irq)
172 :
173 : #define arch_irq_is_enabled(irq) z_soc_irq_is_enabled(irq)
174 :
175 : #ifdef CONFIG_DYNAMIC_INTERRUPTS
176 : extern int z_soc_irq_connect_dynamic(unsigned int irq, unsigned int priority,
177 : void (*routine)(const void *parameter),
178 : const void *parameter, uint32_t flags);
179 : #endif
180 :
181 : #else
182 :
183 0 : #define CONFIG_NUM_IRQS XCHAL_NUM_INTERRUPTS
184 :
185 0 : #define arch_irq_enable(irq) xtensa_irq_enable(irq)
186 0 : #define arch_irq_disable(irq) xtensa_irq_disable(irq)
187 :
188 0 : #define arch_irq_is_enabled(irq) xtensa_irq_is_enabled(irq)
189 :
190 : #endif
191 :
192 : /**
193 : * @brief Enable interrupt on Xtensa core.
194 : *
195 : * @param irq Interrupt to be enabled.
196 : */
197 1 : static ALWAYS_INLINE void xtensa_irq_enable(uint32_t irq)
198 : {
199 : #if XCHAL_NUM_INTERRUPTS > 32
200 : switch (irq >> 5) {
201 : case 0:
202 : z_xt_ints_on(1 << irq);
203 : break;
204 : case 1:
205 : z_xt_ints1_on(1 << irq);
206 : break;
207 : #if XCHAL_NUM_INTERRUPTS > 64
208 : case 2:
209 : z_xt_ints2_on(1 << irq);
210 : break;
211 : #endif
212 : #if XCHAL_NUM_INTERRUPTS > 96
213 : case 3:
214 : z_xt_ints3_on(1 << irq);
215 : break;
216 : #endif
217 : default:
218 : break;
219 : }
220 : #else
221 : z_xt_ints_on(1 << irq);
222 : #endif
223 : }
224 :
225 : /**
226 : * @brief Disable interrupt on Xtensa core.
227 : *
228 : * @param irq Interrupt to be disabled.
229 : */
230 1 : static ALWAYS_INLINE void xtensa_irq_disable(uint32_t irq)
231 : {
232 : #if XCHAL_NUM_INTERRUPTS > 32
233 : switch (irq >> 5) {
234 : case 0:
235 : z_xt_ints_off(1 << irq);
236 : break;
237 : case 1:
238 : z_xt_ints1_off(1 << irq);
239 : break;
240 : #if XCHAL_NUM_INTERRUPTS > 64
241 : case 2:
242 : z_xt_ints2_off(1 << irq);
243 : break;
244 : #endif
245 : #if XCHAL_NUM_INTERRUPTS > 96
246 : case 3:
247 : z_xt_ints3_off(1 << irq);
248 : break;
249 : #endif
250 : default:
251 : break;
252 : }
253 : #else
254 : z_xt_ints_off(1 << irq);
255 : #endif
256 : }
257 :
258 : /** Implementation of @ref arch_irq_lock. */
259 1 : static ALWAYS_INLINE unsigned int arch_irq_lock(void)
260 : {
261 : unsigned int key;
262 :
263 : __asm__ volatile("rsil %0, %1"
264 : : "=r"(key) : "i"(XCHAL_EXCM_LEVEL) : "memory");
265 : return key;
266 : }
267 :
268 : /** Implementation of @ref arch_irq_unlock. */
269 1 : static ALWAYS_INLINE void arch_irq_unlock(unsigned int key)
270 : {
271 : __asm__ volatile("wsr.ps %0; rsync"
272 : :: "r"(key) : "memory");
273 : }
274 :
275 : /** Implementation of @ref arch_irq_unlocked. */
276 1 : static ALWAYS_INLINE bool arch_irq_unlocked(unsigned int key)
277 : {
278 : return (key & 0xf) == 0; /* INTLEVEL field */
279 : }
280 :
281 : /**
282 : * @brief Query if an interrupt is enabled on Xtensa core.
283 : *
284 : * @param irq Interrupt to be queried.
285 : *
286 : * @return True if interrupt is enabled, false otherwise.
287 : */
288 1 : int xtensa_irq_is_enabled(unsigned int irq);
289 :
290 : #include <zephyr/irq.h>
291 :
292 : #endif /* ZEPHYR_INCLUDE_ARCH_XTENSA_XTENSA_IRQ_H_ */
|