1 /*
2 * Copyright (c) 2024 Meta Platforms
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/irq.h>
8 #include <zephyr/irq_multilevel.h>
9 #include <zephyr/ztest.h>
10
test_multi_level_bit_masks_fn(uint32_t irq1,uint32_t irq2,uint32_t irq3)11 static void test_multi_level_bit_masks_fn(uint32_t irq1, uint32_t irq2, uint32_t irq3)
12 {
13 const uint32_t l2_shift = CONFIG_1ST_LEVEL_INTERRUPT_BITS;
14 const uint32_t l3_shift = CONFIG_1ST_LEVEL_INTERRUPT_BITS + CONFIG_2ND_LEVEL_INTERRUPT_BITS;
15 const uint32_t hwirq1 = irq1;
16 const uint32_t hwirq2 = irq2 - 1;
17 const uint32_t irqn_l1 = irq1;
18 const uint32_t irqn_l2 = (irq2 << l2_shift) | irqn_l1;
19 const uint32_t irqn = (irq3 << l3_shift) | irqn_l2;
20 int level;
21
22 if (IS_ENABLED(CONFIG_3RD_LEVEL_INTERRUPTS) && (irq3 > 0)) {
23 level = 3;
24 } else if (IS_ENABLED(CONFIG_2ND_LEVEL_INTERRUPTS) && (irq2 > 0)) {
25 level = 2;
26 } else {
27 level = 1;
28 }
29 zassert_equal(level, irq_get_level(irqn));
30
31 if (irq2 > 0) {
32 zassert_equal(hwirq2, irq_from_level_2(irqn));
33 zassert_equal(hwirq2, irq_from_level(irqn, 2));
34 zassert_equal((hwirq2 + 1) << l2_shift, irq_to_level_2(hwirq2));
35 zassert_equal((hwirq2 + 1) << l2_shift, irq_to_level(hwirq2, 2));
36 zassert_equal(hwirq1, irq_parent_level_2(irqn));
37 zassert_equal(hwirq1, irq_parent_level(irqn, 2));
38 }
39
40 #ifdef CONFIG_3RD_LEVEL_INTERRUPTS
41 if (irq3 > 0) {
42 const uint32_t hwirq3 = irq3 - 1;
43
44 zassert_equal(hwirq3, irq_from_level_3(irqn));
45 zassert_equal(hwirq3, irq_from_level(irqn, 3));
46 zassert_equal((hwirq3 + 1) << l3_shift, irq_to_level_3(hwirq3));
47 zassert_equal((hwirq3 + 1) << l3_shift, irq_to_level(hwirq3, 3));
48 zassert_equal(hwirq2, irq_parent_level_3(irqn));
49 zassert_equal(hwirq2, irq_parent_level(irqn, 3));
50 }
51 #endif /* CONFIG_3RD_LEVEL_INTERRUPTS */
52
53 if (false) {
54 /* always skipped */
55 #ifdef CONFIG_3RD_LEVEL_INTERRUPTS
56 } else if (irq3 > 0) {
57 zassert_equal(irqn_l2, irq_get_intc_irq(irqn));
58 #endif /* CONFIG_3RD_LEVEL_INTERRUPTS */
59 } else if (irq2 > 0) {
60 zassert_equal(irqn_l1, irq_get_intc_irq(irqn));
61 } else {
62 /* degenerate cases */
63 if (false) {
64 zassert_equal(irqn, irq_get_intc_irq(irqn));
65 }
66 }
67 }
68
ZTEST(gen_isr_table_multilevel,test_multi_level_bit_masks_l1)69 ZTEST(gen_isr_table_multilevel, test_multi_level_bit_masks_l1)
70 {
71 uint32_t irq1;
72
73 /* First IRQ of level 1 */
74 irq1 = 0;
75 test_multi_level_bit_masks_fn(irq1, 0, 0);
76
77 /* Somewhere in-between */
78 irq1 = BIT_MASK(CONFIG_1ST_LEVEL_INTERRUPT_BITS) >> 1;
79 test_multi_level_bit_masks_fn(irq1, 0, 0);
80
81 /* Last IRQ of level 1 */
82 irq1 = BIT_MASK(CONFIG_1ST_LEVEL_INTERRUPT_BITS);
83 test_multi_level_bit_masks_fn(irq1, 0, 0);
84 }
85
ZTEST(gen_isr_table_multilevel,test_multi_level_bit_masks_l2)86 ZTEST(gen_isr_table_multilevel, test_multi_level_bit_masks_l2)
87 {
88 if (!IS_ENABLED(CONFIG_2ND_LEVEL_INTERRUPTS)) {
89 ztest_test_skip();
90 }
91
92 uint32_t irq1, irq2;
93
94 /* First IRQ of level 2 */
95 irq1 = 0;
96 /* First irq of level 2 and onwards is 1, as 0 means that the irq is not present */
97 irq2 = 1;
98 test_multi_level_bit_masks_fn(irq1, irq2, 0);
99
100 /* Somewhere in-between */
101 irq1 = BIT_MASK(CONFIG_1ST_LEVEL_INTERRUPT_BITS) >> 1;
102 irq2 = BIT_MASK(CONFIG_2ND_LEVEL_INTERRUPT_BITS) >> 1;
103 test_multi_level_bit_masks_fn(irq1, irq2, 0);
104
105 /* Last IRQ of level 2 */
106 irq1 = BIT_MASK(CONFIG_1ST_LEVEL_INTERRUPT_BITS);
107 irq2 = BIT_MASK(CONFIG_2ND_LEVEL_INTERRUPT_BITS);
108 test_multi_level_bit_masks_fn(irq1, irq2, 0);
109 }
110
ZTEST(gen_isr_table_multilevel,test_multi_level_bit_masks_l3)111 ZTEST(gen_isr_table_multilevel, test_multi_level_bit_masks_l3)
112 {
113 if (!IS_ENABLED(CONFIG_3RD_LEVEL_INTERRUPTS)) {
114 ztest_test_skip();
115 }
116
117 uint32_t irq1, irq2, irq3;
118
119 /* First IRQ of level 3 */
120 irq1 = 0;
121 /* First irq of level 2 and onwards is 1, as 0 means that the irq is not present */
122 irq2 = 1;
123 irq3 = 1;
124 test_multi_level_bit_masks_fn(irq1, irq2, irq3);
125
126 /* Somewhere in-between */
127 irq1 = BIT_MASK(CONFIG_1ST_LEVEL_INTERRUPT_BITS) >> 1;
128 irq2 = BIT_MASK(CONFIG_2ND_LEVEL_INTERRUPT_BITS) >> 1;
129 irq3 = BIT_MASK(CONFIG_3RD_LEVEL_INTERRUPT_BITS) >> 1;
130 test_multi_level_bit_masks_fn(irq1, irq2, irq3);
131
132 /* Last IRQ of level 3 */
133 irq1 = BIT_MASK(CONFIG_1ST_LEVEL_INTERRUPT_BITS);
134 irq2 = BIT_MASK(CONFIG_2ND_LEVEL_INTERRUPT_BITS);
135 irq3 = BIT_MASK(CONFIG_3RD_LEVEL_INTERRUPT_BITS);
136 test_multi_level_bit_masks_fn(irq1, irq2, irq3);
137 }
138
139 ZTEST_SUITE(gen_isr_table_multilevel, NULL, NULL, NULL, NULL, NULL);
140