1 /*
2  * Copyright (c) 2023 Meta
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include "sw_isr_common.h"
8 
9 #include <zephyr/ztest.h>
10 
11 extern const struct _irq_parent_entry _lvl2_irq_list[];
12 
13 #define PARENT_IRQ_FN(i, _) CONFIG_2ND_LVL_INTR_0##i##_OFFSET
14 #if DT_HAS_COMPAT_STATUS_OKAY(sifive_plic_1_0_0)
15 #define PARENT_DEV_FN(i, _) DEVICE_DT_GET(DT_INST(i, sifive_plic_1_0_0))
16 #define INTC_SUPPORTS_MULTI_INSTANCE 1
17 #else
18 #define PARENT_DEV_FN(i, _) (NULL)
19 #endif
20 
21 /**
22  * @brief Test sw_isr_table index-related function(s)
23  *
24  * @details Validates that:
25  * - z_get_sw_isr_table_idx() returns the corresponding SW ISR table index for an IRQN
26  */
ZTEST(interrupt_feature,test_sw_isr_irq_parent_table_idx)27 ZTEST(interrupt_feature, test_sw_isr_irq_parent_table_idx)
28 {
29 	/* ground truths */
30 	const unsigned int parent_irq[CONFIG_NUM_2ND_LEVEL_AGGREGATORS] = {
31 		LISTIFY(CONFIG_NUM_2ND_LEVEL_AGGREGATORS, PARENT_IRQ_FN, (,)),
32 	};
33 	const unsigned int l2_isr_offset = CONFIG_2ND_LVL_ISR_TBL_OFFSET;
34 
35 	for (size_t i = 0; i < CONFIG_NUM_2ND_LEVEL_AGGREGATORS; i++) {
36 		for (unsigned int local_irq = 0;
37 		     local_irq < CONFIG_MAX_IRQ_PER_AGGREGATOR; local_irq++) {
38 			unsigned int test_irq = irq_to_level_2(local_irq) | parent_irq[i];
39 			unsigned int test_isr_offset = z_get_sw_isr_table_idx(test_irq);
40 			unsigned int isr_offset =
41 				l2_isr_offset + local_irq + (i * CONFIG_MAX_IRQ_PER_AGGREGATOR);
42 
43 			zassert_equal(isr_offset, test_isr_offset,
44 				      "%d: expected offset: %d, got: %d", i,
45 				      isr_offset, test_isr_offset);
46 		}
47 	}
48 }
49 
50 /**
51  * @brief Test sw_isr_table device-related function(s)
52  *
53  * This test only works on driver that supports multi-instances
54  *
55  * @details Validates that:
56  * - z_get_sw_isr_device_from_irq() returns the parent interrupt controller for an IRQN
57  * - z_get_sw_isr_irq_from_device() returns the IRQN of a parent interrupt controller
58  */
ZTEST(interrupt_feature,test_sw_isr_irq_parent_table_dev)59 ZTEST(interrupt_feature, test_sw_isr_irq_parent_table_dev)
60 {
61 	Z_TEST_SKIP_IFNDEF(INTC_SUPPORTS_MULTI_INSTANCE);
62 
63 	/* ground truths */
64 	const struct device *parent_dev[CONFIG_NUM_2ND_LEVEL_AGGREGATORS] = {
65 		LISTIFY(CONFIG_NUM_2ND_LEVEL_AGGREGATORS, PARENT_DEV_FN, (,)),
66 	};
67 	const unsigned int parent_irq[CONFIG_NUM_2ND_LEVEL_AGGREGATORS] = {
68 		LISTIFY(CONFIG_NUM_2ND_LEVEL_AGGREGATORS, PARENT_IRQ_FN, (,)),
69 	};
70 
71 	for (size_t i = 0; i < CONFIG_NUM_2ND_LEVEL_AGGREGATORS; i++) {
72 		const struct device *test_dev;
73 		unsigned int test_irq;
74 
75 		zassert_not_null(parent_dev[i]);
76 
77 		for (unsigned int local_irq = 0;
78 		     local_irq < CONFIG_MAX_IRQ_PER_AGGREGATOR; local_irq++) {
79 			test_irq = irq_to_level_2(local_irq) | parent_irq[i];
80 			test_dev = z_get_sw_isr_device_from_irq(test_irq);
81 			zassert_equal_ptr(parent_dev[i], test_dev, "%d: expected dev: %p, got: %p",
82 					  i, parent_dev[i], test_dev);
83 		}
84 
85 		test_irq = z_get_sw_isr_irq_from_device(parent_dev[i]);
86 		zassert_equal(parent_irq[i], test_irq, "%d: expected offset: %d, got: %d", i,
87 			      parent_irq[i], test_irq);
88 	}
89 }
90