Zephyr API Documentation 4.0.0
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>
17#include <zephyr/types.h>
18
19#ifdef __cplusplus
20extern "C" {
21#endif
22
23#if defined(CONFIG_MULTI_LEVEL_INTERRUPTS) || defined(__DOXYGEN__)
24
25typedef union _z_irq {
26 /* Zephyr multilevel-encoded IRQ */
27 uint32_t irq;
28
29 /* Interrupt bits */
30 struct {
31 /* First level interrupt bits */
32 uint32_t l1: CONFIG_1ST_LEVEL_INTERRUPT_BITS;
33 /* Second level interrupt bits */
34 uint32_t l2: CONFIG_2ND_LEVEL_INTERRUPT_BITS;
35 /* Third level interrupt bits */
36 uint32_t l3: CONFIG_3RD_LEVEL_INTERRUPT_BITS;
37 } bits;
38
39 /* Third level IRQ's interrupt controller */
40 struct {
41 /* IRQ of the third level interrupt aggregator */
42 uint32_t irq: CONFIG_1ST_LEVEL_INTERRUPT_BITS + CONFIG_2ND_LEVEL_INTERRUPT_BITS;
43 } l3_intc;
44
45 /* Second level IRQ's interrupt controller */
46 struct {
47 /* IRQ of the second level interrupt aggregator */
48 uint32_t irq: CONFIG_1ST_LEVEL_INTERRUPT_BITS;
49 } l2_intc;
50} _z_irq_t;
51
52BUILD_ASSERT(sizeof(_z_irq_t) == sizeof(uint32_t), "Size of `_z_irq_t` must equal to `uint32_t`");
53
54static inline uint32_t _z_l1_irq(_z_irq_t irq)
55{
56 return irq.bits.l1;
57}
58
59static inline uint32_t _z_l2_irq(_z_irq_t irq)
60{
61 return irq.bits.l2 - 1;
62}
63
64static inline uint32_t _z_l3_irq(_z_irq_t irq)
65{
66 return irq.bits.l3 - 1;
67}
68
69static inline unsigned int _z_irq_get_level(_z_irq_t z_irq)
70{
71 if (z_irq.bits.l3 != 0) {
72 return 3;
73 }
74
75 if (z_irq.bits.l2 != 0) {
76 return 2;
77 }
78
79 return 1;
80}
81
90static inline unsigned int irq_get_level(unsigned int irq)
91{
92 _z_irq_t z_irq = {
93 .irq = irq,
94 };
95
96 return _z_irq_get_level(z_irq);
97}
98
109static inline unsigned int irq_from_level_2(unsigned int irq)
110{
111 _z_irq_t z_irq = {
112 .irq = irq,
113 };
114
115 return _z_l2_irq(z_irq);
116}
117
125#define IRQ_TO_L2(irq) ((irq + 1) << CONFIG_1ST_LEVEL_INTERRUPT_BITS)
126
139static inline unsigned int irq_to_level_2(unsigned int irq)
140{
141 _z_irq_t z_irq = {
142 .bits = {
143 .l1 = 0,
144 .l2 = irq + 1,
145 .l3 = 0,
146 },
147 };
148
149 return z_irq.irq;
150}
151
162static inline unsigned int irq_parent_level_2(unsigned int irq)
163{
164 _z_irq_t z_irq = {
165 .irq = irq,
166 };
167
168 return _z_l1_irq(z_irq);
169}
170
182static inline unsigned int irq_from_level_3(unsigned int irq)
183{
184 _z_irq_t z_irq = {
185 .irq = irq,
186 };
187
188 return _z_l3_irq(z_irq);
189}
190
198#define IRQ_TO_L3(irq) \
199 ((irq + 1) << (CONFIG_1ST_LEVEL_INTERRUPT_BITS + CONFIG_2ND_LEVEL_INTERRUPT_BITS))
200
213static inline unsigned int irq_to_level_3(unsigned int irq)
214{
215 _z_irq_t z_irq = {
216 .bits = {
217 .l1 = 0,
218 .l2 = 0,
219 .l3 = irq + 1,
220 },
221 };
222
223 return z_irq.irq;
224}
225
236static inline unsigned int irq_parent_level_3(unsigned int irq)
237{
238 _z_irq_t z_irq = {
239 .irq = irq,
240 };
241
242 return _z_l2_irq(z_irq);
243}
244
253static inline unsigned int irq_from_level(unsigned int irq, unsigned int level)
254{
255 if (level == 1) {
256 return irq;
257 } else if (level == 2) {
258 return irq_from_level_2(irq);
259 } else if (level == 3) {
260 return irq_from_level_3(irq);
261 }
262
263 /* level is higher than 3 */
264 __ASSERT_NO_MSG(false);
265 return irq;
266}
267
276static inline unsigned int irq_to_level(unsigned int irq, unsigned int level)
277{
278 if (level == 1) {
279 return irq;
280 } else if (level == 2) {
281 return irq_to_level_2(irq);
282 } else if (level == 3) {
283 return irq_to_level_3(irq);
284 }
285
286 /* level is higher than 3 */
287 __ASSERT_NO_MSG(false);
288 return irq;
289}
290
299static inline unsigned int irq_parent_level(unsigned int irq, unsigned int level)
300{
301 if (level == 1) {
302 /* doesn't really make sense, but return anyway */
303 return irq;
304 } else if (level == 2) {
305 return irq_parent_level_2(irq);
306 } else if (level == 3) {
307 return irq_parent_level_3(irq);
308 }
309
310 /* level is higher than 3 */
311 __ASSERT_NO_MSG(false);
312 return irq;
313}
314
322static inline unsigned int irq_get_intc_irq(unsigned int irq)
323{
324 const unsigned int level = irq_get_level(irq);
325
326 __ASSERT_NO_MSG(level <= 3);
327 _z_irq_t z_irq = {
328 .irq = irq,
329 };
330
331 if (level == 3) {
332 return z_irq.l3_intc.irq;
333 } else if (level == 2) {
334 return z_irq.l2_intc.irq;
335 } else {
336 return irq;
337 }
338}
339
348static inline unsigned int irq_increment(unsigned int irq, unsigned int val)
349{
350 _z_irq_t z_irq = {
351 .irq = irq,
352 };
353
354 if (z_irq.bits.l3 != 0) {
355 z_irq.bits.l3 += val;
356 } else if (z_irq.bits.l2 != 0) {
357 z_irq.bits.l2 += val;
358 } else {
359 z_irq.bits.l1 += val;
360 }
361
362 return z_irq.irq;
363}
364
365#endif /* CONFIG_MULTI_LEVEL_INTERRUPTS */
366#ifdef __cplusplus
367}
368#endif
369
370#endif /* _ASMLANGUAGE */
371#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:253
static unsigned int irq_to_level_3(unsigned int irq)
Converts irq from level 1 to level 3 format.
Definition irq_multilevel.h:213
static unsigned int irq_from_level_3(unsigned int irq)
Return the 3rd level interrupt number.
Definition irq_multilevel.h:182
static unsigned int irq_from_level_2(unsigned int irq)
Return the 2nd level interrupt number.
Definition irq_multilevel.h:109
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:90
static unsigned int irq_increment(unsigned int irq, unsigned int val)
Increments the multilevel-encoded irq by val.
Definition irq_multilevel.h:348
static unsigned int irq_to_level_2(unsigned int irq)
Converts irq from level 1 to level 2 format.
Definition irq_multilevel.h:139
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:299
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:322
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:162
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:236
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:276
__UINT32_TYPE__ uint32_t
Definition stdint.h:90
Macro utilities.