1 /*
2 * Copyright 2023 NXP
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /**
8 * @file
9 * @brief Driver for NXP's IRQ_STEER IP.
10 *
11 * Below you may find some useful information that will help you better understand how the
12 * driver works. The ">" sign is used to mark ideas that are considered important and should
13 * be taken note of.
14 *
15 * 1) What is the IRQ_STEER IP?
16 * - in Zephyr terminology, the IRQ_STEER can be considered an interrupt aggregator. As such,
17 * its main goal is to multiplex multiple interrupt lines into a single/multiple ones.
18 *
19 * 2) How does the IRQ_STEER IP work?
20 * - below you may find a diagram meant to give you an intuition regarding the IP's structure
21 * and how it works (all of the information below is applicable to i.MX8MP but it can be
22 * extended to any NXP SoC using the IRQ_STEER IP):
23 *
24 * SYSTEM_INTID[0:159]
25 * |
26 * MASK[0:4]------ |
27 * | |
28 * +------+
29 * | |
30 * |32 AND|
31 * | |
32 * +------+
33 * |
34 * SET[0:4]------ |
35 * | |
36 * +------+
37 * | |
38 * |32 OR |
39 * | |
40 * +------+
41 * |__________ STATUS[0:4]
42 * |
43 * +------+
44 * |GROUP |
45 * | BY |
46 * | 64 |
47 * +------+
48 * | | |
49 * _____________| | |________________
50 * | | |
51 * MASTER_IN[0] MASTER_IN[1] MASTER_IN[2]
52 * | | |
53 * | | |
54 * |_____________ | _______________|
55 * | | |
56 * +------+
57 * | |
58 * | AND | ---------- MINTDIS[0:2]
59 * | |
60 * +------+
61 * | | |
62 * _____________| | |________________
63 * | | |
64 * MASTER_OUT[0] MASTER_OUT[1] MASTER_OUT[2]
65 *
66 * - initially, all SYSTEM_INTID are grouped by 32 => 5 groups.
67 *
68 * > each of these groups is controlled by a MASK, SET and STATUS index as follows:
69 *
70 * MASK/SET/STATUS[0] => SYSTEM_INTID[159:128]
71 * MASK/SET/STATUS[1] => SYSTEM_INTID[127:96]
72 * MASK/SET/STATUS[2] => SYSTEM_INTID[95:64]
73 * MASK/SET/STATUS[3] => SYSTEM_INTID[63:32]
74 * MASK/SET/STATUS[4] => SYSTEM_INTID[31:0]
75 *
76 * > after that, all SYSTEM_INTID are grouped by 64 as follows:
77 *
78 * SYSTEM_INTID[159:96] => MASTER_IN[2]
79 * SYSTEM_INTID[95:32] => MASTER_IN[1]
80 * SYSTEM_INTID[31:0] => MASTER_IN[0]
81 *
82 * note: MASTER_IN[0] is only responsible for 32 interrupts
83 *
84 * > the value of MASTER_IN[x] is obtained by OR'ing the input interrupt lines.
85 *
86 * > the value of MASTER_OUT[x] is obtained by AND'ing MASTER_IN[x] with !MINTDIS[x].
87 *
88 * - whenever a SYSTEM_INTID is asserted, its corresponding MASTER_OUT signal will also
89 * be asserted, thus signaling the target processor.
90 *
91 * > please note the difference between an IRQ_STEER channel and an IRQ_STEER master output.
92 * An IRQ_STEER channel refers to an IRQ_STEER instance (e.g: the DSP uses IRQ_STEER channel
93 * 0 a.k.a instance 0). An IRQ_STEER channel has multiple master outputs. For example, in
94 * the case of i.MX8MP each IRQ_STEER channel has 3 master outputs since an IRQ_STEER channel
95 * routes 160 interrupts (32 for first master output, 64 for second master output, and 64 for
96 * the third master output).
97 *
98 * 3) Using Zephyr's multi-level interrupt support
99 * - since Zephyr supports organizing interrupts on multiple levels, we can use this to
100 * separate the interrupts in 2 levels:
101 * 1) LEVEL 1 INTERRUPTS
102 * - these are the interrupts that go directly to the processor (for example,
103 * on i.MX8MP the MU can directly assert the DSP's interrupt line 7)
104 *
105 * 2) LEVEL 2 INTERRUPTS
106 * - these interrupts go through IRQ_STEER and are signaled by a single
107 * processor interrupt line.
108 * - e.g: for i.MX8MP, INTID 34 (SDMA3) goes through IRQ_STEER and is signaled
109 * to the DSP by INTID 20 which is a direct interrupt (or LEVEL 1 interrupt).
110 *
111 * - the following diagram (1) shows the interrupt organization on i.MX8MP:
112 * +------------+
113 * | |
114 * SYSTEM_INTID[31:0] ------ IRQ_STEER_MASTER_0 ---- | 19 |
115 * | |
116 * SYSTEM_INTID[95:32] ----- IRQ_STEER_MASTER_1 ---- | 20 DSP |
117 * | |
118 * SYSTEM_INTID[159:96] ---- IRQ_STEER_MASTER_2 ---- | 21 |
119 * | |
120 * +------------+
121 *
122 * - as such, asserting a system interrupt will lead to asserting its corresponding DSP
123 * interrupt line (for example, if system interrupt 34 is asserted, that would lead to
124 * interrupt 20 being asserted)
125 *
126 * - in the above diagram, SYSTEM_INTID[x] are LEVEL 2 interrupts, while 19, 20, and 21 are
127 * LEVEL 1 interrupts.
128 *
129 * - INTID 19 is the parent of SYSTEM_INTID[31:0] and so on.
130 *
131 * > before going into how the INTIDs are encoded, we need to distinguish between 3 types of
132 * INTIDs:
133 * 1) System INTIDs
134 * - these are the values that can be found in NXP's TRMs for different
135 * SoCs (usually they have the same IDs as the GIC SPIs)
136 * - for example, INTID 34 is a system INTID for SDMA3 (i.MX8MP).
137 *
138 * 2) Zephyr INTIDs
139 * - these are the Zephyr-specific encodings of the system INTIDs.
140 * - these are used to encode multi-level interrupts (for more information
141 * please see [1])
142 * > if you need to register an interrupt dynamically, you need to use this
143 * encoding when specifying the interrupt.
144 *
145 * 3) DTS INTIDs
146 * - these are the encodings of the system INTIDs used in the DTS.
147 * - all of these INTIDs are relative to IRQ_STEER's MASTER_OUTs.
148 *
149 * > encoding an INTID:
150 * 1) SYSTEM INTID => ZEPHYR INTID
151 * - the following steps need to be performed:
152 *
153 * a) Find out which IRQ_STEER MASTER
154 * is in charge of aggregating this interrupt.
155 * * for instance, SYSTEM_INTID 34 (SDMA3 on i.MX8MP) is
156 * aggregated by MASTER 1 as depicted in diagram (1).
157 *
158 * b) After finding the MASTER aggregator, you need
159 * to find the corresponding parent interrupt.
160 * * for example, SYSTEM_INTID 34 (SDMA3 on i.MX8MP) is
161 * aggregated by MASTER 1, which has the parent INTID 20
162 * as depicted in diagram (1) => PARENT_INTID(34) = 20.
163 *
164 * c) Find the INTID relative to the MASTER aggregator. This is done
165 * by subtracting the number of interrupts each of the previous
166 * master aggregators is in charge of. If the master aggregator is
167 * MASTER 0 then RELATIVE_INTID=SYSTEM_INTID.
168 * * for example, SYSTEM_ID 34 is aggregated by MASTER 1.
169 * As such, we need to subtract 32 from 34 (because the
170 * previous master - MASTER 0 - is in charge of aggregating
171 * 32 interrupts) => RELATIVE_INTID(34) = 2.
172 *
173 * * generally speaking, RELATIVE_INTID can be computed using
174 * the following formula (assuming SYSTEM_INTID belongs to
175 * MASTER y):
176 * RELATIVE_INTID(x) = x -
177 * \sum{i=0}^{y - 1} GET_MASTER_INT_NUM(i)
178 * where:
179 * 1) GET_MASTER_INT_NUM(x) computes the number of
180 * interrupts master x aggregates
181 * 2) x is the system interrupt
182 *
183 * * to make sure your computation is correct use the
184 * following restriction:
185 * 0 <= RELATIVE_INTID(x) < GET_MASTER_INT_NUM(y)
186 *
187 * d) To the obtained RELATIVE_INTID you need to add the value of 1,
188 * left shift the result by the number of bits used to encode the
189 * level 1 interrupts (see [1] for details) and OR the parent ID.
190 * * for example, RELATIVE_INTID(34) = 2 (i.MX8MP),
191 * PARENT_INTID(34) = 20 => ZEPHYR_INTID = ((2 + 1) << 8) | 20
192 *
193 * * generally speaking, ZEPHYR_INTID can be computed using
194 * the following formula:
195 * ZEPHYR_INTID(x) = ((RELATIVE_INTID(x) + 1) <<
196 * NUM_LVL1_BITS) | PARENT_INTID(x)
197 * where:
198 * 1) RELATIVE_INTID(x) computes the relative INTID
199 * of system interrupt x (step c).
200 *
201 * 2) NUM_LVL1_BITS is the number of bits used to
202 * encode level 1 interrupts.
203 *
204 * 3) PARENT_INTID(x) computes the parent INTID of a
205 * system interrupt x (step b)
206 *
207 * - all of these steps are performed by to_zephyr_irq().
208 * > for interrupts aggregated by MASTER 0 you may skip step c) as
209 * RELATIVE_INTID(x) = x.
210 *
211 * 2) SYSTEM INTID => DTS INTID
212 * - for this you just have to compute RELATIVE_INTID as described above in
213 * step c).
214 * - for example, if an IP uses INTID 34 you'd write its interrupts property
215 * as follows (i.MX8MP):
216 * interrupts = <&master1 2>;
217 *
218 * 4) Notes and comments
219 * > PLEASE DON'T MISTAKE THE ZEPHYR MULTI-LEVEL INTERRUPT ORGANIZATION WITH THE XTENSA ONE.
220 * THEY ARE DIFFERENT THINGS.
221 *
222 * [1]: https://docs.zephyrproject.org/latest/kernel/services/interrupts.html#multi-level-interrupt-handling
223 */
224
225 #include <zephyr/device.h>
226 #include <zephyr/devicetree/interrupt_controller.h>
227 #include <zephyr/irq.h>
228 #include <fsl_irqsteer.h>
229 #include <zephyr/cache.h>
230 #include <zephyr/sw_isr_table.h>
231 #include <zephyr/logging/log.h>
232 #include <zephyr/pm/device_runtime.h>
233 #include <zephyr/pm/device.h>
234
235 #include "sw_isr_common.h"
236
237 LOG_MODULE_REGISTER(nxp_irqstr);
238
239 /* used for driver binding */
240 #define DT_DRV_COMPAT nxp_irqsteer_intc
241
242 /* macros used for DTS parsing */
243 #define _IRQSTEER_REGISTER_DISPATCHER(node_id) \
244 IRQ_CONNECT(DT_IRQN(node_id), \
245 DT_IRQ(node_id, priority), \
246 irqsteer_isr_dispatcher, \
247 &dispatchers[DT_REG_ADDR(node_id)], \
248 0)
249
250 #define _IRQSTEER_DECLARE_DISPATCHER(node_id) \
251 { \
252 .dev = DEVICE_DT_GET(DT_PARENT(node_id)), \
253 .master_index = DT_REG_ADDR(node_id), \
254 .irq = DT_IRQN(node_id), \
255 }
256
257 #define IRQSTEER_DECLARE_DISPATCHERS(parent_id)\
258 DT_FOREACH_CHILD_STATUS_OKAY_SEP(parent_id, _IRQSTEER_DECLARE_DISPATCHER, (,))
259
260 #define IRQSTEER_REGISTER_DISPATCHERS(parent_id)\
261 DT_FOREACH_CHILD_STATUS_OKAY_SEP(parent_id, _IRQSTEER_REGISTER_DISPATCHER, (;))
262
263 /* utility macros */
264 #define UINT_TO_IRQSTEER(x) ((IRQSTEER_Type *)(x))
265 #define DISPATCHER_REGMAP(disp) \
266 (((const struct irqsteer_config *)disp->dev->config)->regmap_phys)
267
268 struct irqsteer_config {
269 uint32_t regmap_phys;
270 uint32_t regmap_size;
271 struct irqsteer_dispatcher *dispatchers;
272 };
273
274 struct irqsteer_dispatcher {
275 const struct device *dev;
276 /* which set of interrupts is the dispatcher in charge of? */
277 uint32_t master_index;
278 /* which interrupt line is the dispatcher tied to? */
279 uint32_t irq;
280 /* reference count for all IRQs aggregated by dispatcher */
281 uint8_t irq_refcnt[CONFIG_MAX_IRQ_PER_AGGREGATOR];
282 /* dispatcher lock */
283 struct k_spinlock lock;
284 /* reference count for dispatcher */
285 uint8_t refcnt;
286 };
287
288 static struct irqsteer_dispatcher dispatchers[] = {
289 IRQSTEER_DECLARE_DISPATCHERS(DT_NODELABEL(irqsteer))
290 };
291
292 /* used to convert system INTID to zephyr INTID */
to_zephyr_irq(uint32_t regmap,uint32_t irq,struct irqsteer_dispatcher * dispatcher)293 static int to_zephyr_irq(uint32_t regmap, uint32_t irq,
294 struct irqsteer_dispatcher *dispatcher)
295 {
296 int i, idx;
297
298 idx = irq;
299
300 for (i = dispatcher->master_index - 1; i >= 0; i--) {
301 idx -= IRQSTEER_GetMasterIrqCount(UINT_TO_IRQSTEER(regmap), i);
302 }
303
304 return irq_to_level_2(idx) | dispatcher->irq;
305 }
306
307 /* used to convert master-relative INTID to system INTID */
to_system_irq(uint32_t regmap,int irq,int master_index)308 static int to_system_irq(uint32_t regmap, int irq, int master_index)
309 {
310 int i;
311
312 for (i = master_index - 1; i >= 0; i--) {
313 irq += IRQSTEER_GetMasterIrqCount(UINT_TO_IRQSTEER(regmap), i);
314 }
315
316 return irq;
317 }
318
319 /* used to convert zephyr INTID to system INTID */
from_zephyr_irq(uint32_t regmap,uint32_t irq,uint32_t master_index)320 static int from_zephyr_irq(uint32_t regmap, uint32_t irq, uint32_t master_index)
321 {
322 int i, idx;
323
324 idx = irq;
325
326 for (i = 0; i < master_index; i++) {
327 idx += IRQSTEER_GetMasterIrqCount(UINT_TO_IRQSTEER(regmap), i);
328 }
329
330 return idx;
331 }
332
_irqstr_disp_enable_disable(struct irqsteer_dispatcher * disp,bool enable)333 static void _irqstr_disp_enable_disable(struct irqsteer_dispatcher *disp,
334 bool enable)
335 {
336 uint32_t regmap = DISPATCHER_REGMAP(disp);
337
338 if (enable) {
339 xtensa_irq_enable(XTENSA_IRQ_NUMBER(disp->irq));
340
341 IRQSTEER_EnableMasterInterrupt(UINT_TO_IRQSTEER(regmap), disp->irq);
342 } else {
343 IRQSTEER_DisableMasterInterrupt(UINT_TO_IRQSTEER(regmap), disp->irq);
344
345 xtensa_irq_disable(XTENSA_IRQ_NUMBER(disp->irq));
346 }
347 }
348
_irqstr_disp_get_unlocked(struct irqsteer_dispatcher * disp)349 static void _irqstr_disp_get_unlocked(struct irqsteer_dispatcher *disp)
350 {
351 int ret;
352
353 if (disp->refcnt == UINT8_MAX) {
354 LOG_WRN("disp for irq %d reference count reached limit", disp->irq);
355 return;
356 }
357
358 if (!disp->refcnt) {
359 ret = pm_device_runtime_get(disp->dev);
360 if (ret < 0) {
361 LOG_ERR("failed to enable PM resources: %d", ret);
362 return;
363 }
364
365 _irqstr_disp_enable_disable(disp, true);
366 }
367
368 disp->refcnt++;
369
370 LOG_DBG("get on disp for irq %d results in refcnt: %d",
371 disp->irq, disp->refcnt);
372 }
373
_irqstr_disp_put_unlocked(struct irqsteer_dispatcher * disp)374 static void _irqstr_disp_put_unlocked(struct irqsteer_dispatcher *disp)
375 {
376 int ret;
377
378 if (!disp->refcnt) {
379 LOG_WRN("disp for irq %d already put", disp->irq);
380 return;
381 }
382
383 disp->refcnt--;
384
385 if (!disp->refcnt) {
386 _irqstr_disp_enable_disable(disp, false);
387
388 ret = pm_device_runtime_put(disp->dev);
389 if (ret < 0) {
390 LOG_ERR("failed to disable PM resources: %d", ret);
391 return;
392 }
393 }
394
395 LOG_DBG("put on disp for irq %d results in refcnt: %d",
396 disp->irq, disp->refcnt);
397 }
398
_irqstr_enable_disable_irq(struct irqsteer_dispatcher * disp,uint32_t system_irq,bool enable)399 static void _irqstr_enable_disable_irq(struct irqsteer_dispatcher *disp,
400 uint32_t system_irq, bool enable)
401 {
402 uint32_t regmap = DISPATCHER_REGMAP(disp);
403
404 if (enable) {
405 IRQSTEER_EnableInterrupt(UINT_TO_IRQSTEER(regmap), system_irq);
406 } else {
407 IRQSTEER_DisableInterrupt(UINT_TO_IRQSTEER(regmap), system_irq);
408 }
409 }
410
irqstr_request_irq_unlocked(struct irqsteer_dispatcher * disp,uint32_t zephyr_irq)411 static void irqstr_request_irq_unlocked(struct irqsteer_dispatcher *disp,
412 uint32_t zephyr_irq)
413 {
414 uint32_t system_irq = from_zephyr_irq(DISPATCHER_REGMAP(disp),
415 zephyr_irq, disp->master_index);
416
417 #ifndef CONFIG_SHARED_INTERRUPTS
418 if (disp->irq_refcnt[zephyr_irq]) {
419 LOG_WRN("irq %d already requested", system_irq);
420 return;
421 }
422 #endif /* CONFIG_SHARED_INTERRUPTS */
423
424 if (disp->irq_refcnt[zephyr_irq] == UINT8_MAX) {
425 LOG_WRN("irq %d reference count reached limit", system_irq);
426 return;
427 }
428
429 if (!disp->irq_refcnt[zephyr_irq]) {
430 _irqstr_disp_get_unlocked(disp);
431 _irqstr_enable_disable_irq(disp, system_irq, true);
432 }
433
434 disp->irq_refcnt[zephyr_irq]++;
435
436 LOG_DBG("requested irq %d has refcount %d",
437 system_irq, disp->irq_refcnt[zephyr_irq]);
438 }
439
irqstr_release_irq_unlocked(struct irqsteer_dispatcher * disp,uint32_t zephyr_irq)440 static void irqstr_release_irq_unlocked(struct irqsteer_dispatcher *disp,
441 uint32_t zephyr_irq)
442 {
443 uint32_t system_irq = from_zephyr_irq(DISPATCHER_REGMAP(disp),
444 zephyr_irq, disp->master_index);
445
446 if (!disp->irq_refcnt[zephyr_irq]) {
447 LOG_WRN("irq %d already released", system_irq);
448 return;
449 }
450
451 disp->irq_refcnt[zephyr_irq]--;
452
453 if (!disp->irq_refcnt[zephyr_irq]) {
454 _irqstr_enable_disable_irq(disp, system_irq, false);
455 _irqstr_disp_put_unlocked(disp);
456 }
457
458 LOG_DBG("released irq %d has refcount %d",
459 system_irq, disp->irq_refcnt[zephyr_irq]);
460 }
461
z_soc_irq_enable_disable(uint32_t irq,bool enable)462 void z_soc_irq_enable_disable(uint32_t irq, bool enable)
463 {
464 uint32_t parent_irq;
465 int i, level2_irq;
466
467 if (irq_get_level(irq) == 1) {
468 /* LEVEL 1 interrupts are DSP direct */
469 if (enable) {
470 xtensa_irq_enable(XTENSA_IRQ_NUMBER(irq));
471 } else {
472 xtensa_irq_disable(XTENSA_IRQ_NUMBER(irq));
473 }
474 return;
475 }
476
477 parent_irq = irq_parent_level_2(irq);
478 level2_irq = irq_from_level_2(irq);
479
480 /* find dispatcher responsible for this interrupt */
481 for (i = 0; i < ARRAY_SIZE(dispatchers); i++) {
482 if (dispatchers[i].irq != parent_irq) {
483 continue;
484 }
485
486 K_SPINLOCK(&dispatchers[i].lock) {
487 if (enable) {
488 irqstr_request_irq_unlocked(&dispatchers[i], level2_irq);
489 } else {
490 irqstr_release_irq_unlocked(&dispatchers[i], level2_irq);
491 }
492 }
493
494 return;
495 }
496 }
497
z_soc_irq_enable(uint32_t irq)498 void z_soc_irq_enable(uint32_t irq)
499 {
500 z_soc_irq_enable_disable(irq, true);
501 }
502
z_soc_irq_disable(uint32_t irq)503 void z_soc_irq_disable(uint32_t irq)
504 {
505 z_soc_irq_enable_disable(irq, false);
506 }
507
z_soc_irq_is_enabled(unsigned int irq)508 int z_soc_irq_is_enabled(unsigned int irq)
509 {
510 uint32_t parent_irq;
511 int i;
512 const struct irqsteer_config *cfg;
513 bool enabled;
514
515 if (irq_get_level(irq) == 1) {
516 /* LEVEL 1 interrupts are DSP direct */
517 return xtensa_irq_is_enabled(XTENSA_IRQ_NUMBER(irq));
518 }
519
520 parent_irq = irq_parent_level_2(irq);
521 enabled = false;
522
523 /* find dispatcher responsible for this interrupt */
524 for (i = 0; i < ARRAY_SIZE(dispatchers); i++) {
525 if (dispatchers[i].irq != parent_irq) {
526 continue;
527 }
528
529 cfg = dispatchers[i].dev->config;
530
531 K_SPINLOCK(&dispatchers[i].lock) {
532 enabled = dispatchers[i].irq_refcnt[irq_from_level_2(irq)];
533 }
534
535 return enabled;
536 }
537
538 return false;
539 }
540
541
irqsteer_isr_dispatcher(const void * data)542 static void irqsteer_isr_dispatcher(const void *data)
543 {
544 struct irqsteer_dispatcher *dispatcher;
545 const struct irqsteer_config *cfg;
546 uint32_t table_idx;
547 int system_irq, zephyr_irq, i;
548 uint64_t status;
549
550 dispatcher = (struct irqsteer_dispatcher *)data;
551 cfg = dispatcher->dev->config;
552
553 /* fetch master interrupts status */
554 status = IRQSTEER_GetMasterInterruptsStatus(UINT_TO_IRQSTEER(cfg->regmap_phys),
555 dispatcher->master_index);
556
557 for (i = 0; status; i++) {
558 /* if bit 0 is set then that means relative INTID i is asserted */
559 if (status & 1) {
560 /* convert master-relative INTID to a system INTID */
561 system_irq = to_system_irq(cfg->regmap_phys, i,
562 dispatcher->master_index);
563
564 /* convert system INTID to a Zephyr INTID */
565 zephyr_irq = to_zephyr_irq(cfg->regmap_phys, system_irq, dispatcher);
566
567 /* compute index in the SW ISR table */
568 table_idx = z_get_sw_isr_table_idx(zephyr_irq);
569
570 /* call child's ISR */
571 _sw_isr_table[table_idx].isr(_sw_isr_table[table_idx].arg);
572 }
573
574 status >>= 1;
575 }
576 }
577
irqstr_pm_action(const struct device * dev,enum pm_device_action action)578 __maybe_unused static int irqstr_pm_action(const struct device *dev,
579 enum pm_device_action action)
580 {
581 /* nothing to be done here */
582 return 0;
583 }
584
irqsteer_init(const struct device * dev)585 static int irqsteer_init(const struct device *dev)
586 {
587 IRQSTEER_REGISTER_DISPATCHERS(DT_NODELABEL(irqsteer));
588
589 return pm_device_runtime_enable(dev);
590 }
591
592
593 /* TODO: do we need to add support for MMU-based SoCs? */
594 static struct irqsteer_config irqsteer_config = {
595 .regmap_phys = DT_REG_ADDR(DT_NODELABEL(irqsteer)),
596 .regmap_size = DT_REG_SIZE(DT_NODELABEL(irqsteer)),
597 .dispatchers = dispatchers,
598 };
599
600 /* assumption: only 1 IRQ_STEER instance */
601 PM_DEVICE_DT_INST_DEFINE(0, irqstr_pm_action);
602 DEVICE_DT_INST_DEFINE(0,
603 &irqsteer_init,
604 PM_DEVICE_DT_INST_GET(0),
605 NULL, &irqsteer_config,
606 PRE_KERNEL_1, CONFIG_INTC_INIT_PRIORITY,
607 NULL);
608
609 #define NXP_IRQSTEER_MASTER_IRQ_ENTRY_DEF(node_id) \
610 IRQ_PARENT_ENTRY_DEFINE(CONCAT(nxp_irqsteer_master_, DT_NODE_CHILD_IDX(node_id)), NULL, \
611 DT_IRQN(node_id), INTC_CHILD_ISR_TBL_OFFSET(node_id), \
612 DT_INTC_GET_AGGREGATOR_LEVEL(node_id));
613
614 DT_INST_FOREACH_CHILD_STATUS_OKAY(0, NXP_IRQSTEER_MASTER_IRQ_ENTRY_DEF);
615