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