Zephyr API Documentation 4.4.99
A Scalable Open Source RTOS
Loading...
Searching...
No Matches
irq_multilevel.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2023 Meta
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
11#ifndef ZEPHYR_INCLUDE_IRQ_MULTILEVEL_H_
12#define ZEPHYR_INCLUDE_IRQ_MULTILEVEL_H_
13
14#ifndef _ASMLANGUAGE
15#include <zephyr/sys/__assert.h>
16#include <zephyr/sys/util.h>
17#include <zephyr/types.h>
18
19#ifdef __cplusplus
20extern "C" {
21#endif
22
23#if defined(CONFIG_MULTI_LEVEL_INTERRUPTS) || defined(__DOXYGEN__)
24
25#if defined(CONFIG_2ND_LEVEL_INTERRUPTS)
26BUILD_ASSERT(CONFIG_2ND_LEVEL_INTERRUPT_BITS > 0,
27 "Second-level IRQ field must contain at least one bit");
28#endif
29
30#if defined(CONFIG_3RD_LEVEL_INTERRUPTS)
31BUILD_ASSERT(CONFIG_3RD_LEVEL_INTERRUPT_BITS > 0,
32 "Third-level IRQ field must contain at least one bit");
33BUILD_ASSERT(CONFIG_1ST_LEVEL_INTERRUPT_BITS + CONFIG_2ND_LEVEL_INTERRUPT_BITS +
34 CONFIG_3RD_LEVEL_INTERRUPT_BITS <=
35 32,
36 "Multilevel IRQ encoding exceeds 32 bits");
37#elif defined(CONFIG_2ND_LEVEL_INTERRUPTS)
38BUILD_ASSERT(CONFIG_1ST_LEVEL_INTERRUPT_BITS + CONFIG_2ND_LEVEL_INTERRUPT_BITS <= 32,
39 "Multilevel IRQ encoding exceeds 32 bits");
40#endif
41
42/* Masks for fields in the numeric multilevel IRQ encoding. */
43#define Z_IRQ_L1_MASK ((uint32_t)GENMASK(CONFIG_1ST_LEVEL_INTERRUPT_BITS - 1, 0))
44#define Z_IRQ_L2_MASK \
45 ((uint32_t)GENMASK(CONFIG_1ST_LEVEL_INTERRUPT_BITS + CONFIG_2ND_LEVEL_INTERRUPT_BITS - 1, \
46 CONFIG_1ST_LEVEL_INTERRUPT_BITS))
47#if defined(CONFIG_3RD_LEVEL_INTERRUPTS) || defined(__DOXYGEN__)
48#define Z_IRQ_L3_MASK \
49 ((uint32_t)GENMASK(CONFIG_1ST_LEVEL_INTERRUPT_BITS + CONFIG_2ND_LEVEL_INTERRUPT_BITS + \
50 CONFIG_3RD_LEVEL_INTERRUPT_BITS - 1, \
51 CONFIG_1ST_LEVEL_INTERRUPT_BITS + CONFIG_2ND_LEVEL_INTERRUPT_BITS))
52#endif /* CONFIG_3RD_LEVEL_INTERRUPTS */
53
62static inline unsigned int irq_get_level(unsigned int irq)
63{
64#ifdef CONFIG_3RD_LEVEL_INTERRUPTS
65 if ((irq & Z_IRQ_L3_MASK) != 0U) {
66 return 3;
67 }
68#endif /* CONFIG_3RD_LEVEL_INTERRUPTS */
69
70 if ((irq & Z_IRQ_L2_MASK) != 0U) {
71 return 2;
72 }
73
74 return 1;
75}
76
87static inline unsigned int irq_from_level_2(unsigned int irq)
88{
89 return FIELD_GET(Z_IRQ_L2_MASK, irq) - 1U;
90}
91
99#define IRQ_TO_L2(irq) FIELD_PREP(Z_IRQ_L2_MASK, (irq) + 1U)
100
113static inline unsigned int irq_to_level_2(unsigned int irq)
114{
115 return IRQ_TO_L2(irq);
116}
117
128static inline unsigned int irq_parent_level_2(unsigned int irq)
129{
130 return FIELD_GET(Z_IRQ_L1_MASK, irq);
131}
132
133#if defined(CONFIG_3RD_LEVEL_INTERRUPTS) || defined(__DOXYGEN__)
145static inline unsigned int irq_from_level_3(unsigned int irq)
146{
147 return FIELD_GET(Z_IRQ_L3_MASK, irq) - 1U;
148}
149
157#define IRQ_TO_L3(irq) FIELD_PREP(Z_IRQ_L3_MASK, (irq) + 1U)
158
171static inline unsigned int irq_to_level_3(unsigned int irq)
172{
173 return IRQ_TO_L3(irq);
174}
175
186static inline unsigned int irq_parent_level_3(unsigned int irq)
187{
188 return irq_from_level_2(irq);
189}
190#endif /* CONFIG_3RD_LEVEL_INTERRUPTS */
191
200static inline unsigned int irq_from_level(unsigned int irq, unsigned int level)
201{
202 if (level == 1) {
203 return irq;
204 } else if (level == 2) {
205 return irq_from_level_2(irq);
206 }
207#ifdef CONFIG_3RD_LEVEL_INTERRUPTS
208 else if (level == 3) {
209 return irq_from_level_3(irq);
210 }
211#endif /* CONFIG_3RD_LEVEL_INTERRUPTS */
212
213 /* level is higher than what's supported */
214 __ASSERT_NO_MSG(false);
215 return irq;
216}
217
226static inline unsigned int irq_to_level(unsigned int irq, unsigned int level)
227{
228 if (level == 1) {
229 return irq;
230 } else if (level == 2) {
231 return irq_to_level_2(irq);
232 }
233#ifdef CONFIG_3RD_LEVEL_INTERRUPTS
234 else if (level == 3) {
235 return irq_to_level_3(irq);
236 }
237#endif /* CONFIG_3RD_LEVEL_INTERRUPTS */
238
239 /* level is higher than what's supported */
240 __ASSERT_NO_MSG(false);
241 return irq;
242}
243
252static inline unsigned int irq_parent_level(unsigned int irq, unsigned int level)
253{
254 if (level == 1) {
255 /* doesn't really make sense, but return anyway */
256 return irq;
257 } else if (level == 2) {
258 return irq_parent_level_2(irq);
259 }
260#ifdef CONFIG_3RD_LEVEL_INTERRUPTS
261 else if (level == 3) {
262 return irq_parent_level_3(irq);
263 }
264#endif /* CONFIG_3RD_LEVEL_INTERRUPTS */
265
266 /* level is higher than what's supported */
267 __ASSERT_NO_MSG(false);
268 return irq;
269}
270
278static inline unsigned int irq_get_intc_irq(unsigned int irq)
279{
280 const unsigned int level = irq_get_level(irq);
281
282#ifdef CONFIG_3RD_LEVEL_INTERRUPTS
283 __ASSERT_NO_MSG(level <= 3);
284 if (level == 3) {
285 return irq & (Z_IRQ_L1_MASK | Z_IRQ_L2_MASK);
286 }
287#else
288 __ASSERT_NO_MSG(level <= 2);
289#endif /* CONFIG_3RD_LEVEL_INTERRUPTS */
290
291 if (level == 2) {
292 return irq_parent_level_2(irq);
293 }
294
295 return irq;
296}
297
306static inline unsigned int irq_increment(unsigned int irq, unsigned int val)
307{
308 unsigned int mask;
309 const unsigned int level = irq_get_level(irq);
310
311 if (false) {
312 /* so that it evaluates the next condition */
313#ifdef CONFIG_3RD_LEVEL_INTERRUPTS
314 } else if (level == 3) {
315 mask = Z_IRQ_L3_MASK;
316#endif /* CONFIG_3RD_LEVEL_INTERRUPTS */
317 } else if (level == 2) {
318 mask = Z_IRQ_L2_MASK;
319 } else {
320 mask = Z_IRQ_L1_MASK;
321 }
322
323 return (irq & ~mask) | FIELD_PREP(mask, FIELD_GET(mask, irq) + val);
324}
325
326#endif /* CONFIG_MULTI_LEVEL_INTERRUPTS */
327#ifdef __cplusplus
328}
329#endif
330
331#endif /* _ASMLANGUAGE */
332#endif /* ZEPHYR_INCLUDE_IRQ_MULTILEVEL_H_ */
static unsigned int irq_from_level(unsigned int irq, unsigned int level)
Return the interrupt number for a given level.
Definition irq_multilevel.h:200
#define IRQ_TO_L3(irq)
Preprocessor macro to convert irq from level 1 to level 3 format.
Definition irq_multilevel.h:157
static unsigned int irq_to_level_3(unsigned int irq)
Converts irq from level 1 to level 3 format.
Definition irq_multilevel.h:171
static unsigned int irq_from_level_3(unsigned int irq)
Return the 3rd level interrupt number.
Definition irq_multilevel.h:145
static unsigned int irq_from_level_2(unsigned int irq)
Return the 2nd level interrupt number.
Definition irq_multilevel.h:87
static unsigned int irq_get_level(unsigned int irq)
Return IRQ level This routine returns the interrupt level number of the provided interrupt.
Definition irq_multilevel.h:62
static unsigned int irq_increment(unsigned int irq, unsigned int val)
Increments the multilevel-encoded irq by val.
Definition irq_multilevel.h:306
static unsigned int irq_to_level_2(unsigned int irq)
Converts irq from level 1 to level 2 format.
Definition irq_multilevel.h:113
static unsigned int irq_parent_level(unsigned int irq, unsigned int level)
Returns the parent IRQ of the given level raw IRQ number.
Definition irq_multilevel.h:252
#define IRQ_TO_L2(irq)
Preprocessor macro to convert irq from level 1 to level 2 format.
Definition irq_multilevel.h:99
static unsigned int irq_get_intc_irq(unsigned int irq)
Returns the parent interrupt controller IRQ of the given IRQ number.
Definition irq_multilevel.h:278
static unsigned int irq_parent_level_2(unsigned int irq)
Returns the parent IRQ of the level 2 raw IRQ number.
Definition irq_multilevel.h:128
static unsigned int irq_parent_level_3(unsigned int irq)
Returns the parent IRQ of the level 3 raw IRQ number.
Definition irq_multilevel.h:186
static unsigned int irq_to_level(unsigned int irq, unsigned int level)
Converts irq from level 1 to a given level.
Definition irq_multilevel.h:226
#define FIELD_PREP(mask, value)
Definition silabs-pinctrl-siwx91x.h:15
#define FIELD_GET(mask, value)
Definition silabs-pinctrl-siwx91x.h:14
Misc utilities.