1 /*
2  * Copyright 2023 NXP
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include "test_shared_irq.h"
8 
9 #define GIC_IRQ1 10
10 #define GIC_IRQ2 11
11 
12 /**
13  * @brief Test writing to a vector using static shared interrupts.
14  *
15  * @ingroup kernel_interrupt_tests
16  *
17  * @details This tests if interrupts are statically shared successfully
18  * (i.e: multiple ISR/arg pairs are called whenever the interrupt they
19  * were registered for is triggered).
20  */
ZTEST(interrupt_feature,test_static_shared_irq_write)21 ZTEST(interrupt_feature, test_static_shared_irq_write)
22 {
23 	/* note: this test is very brittle since it requires that
24 	 * the chosen interrupt lines be unused for all of the
25 	 * testing platforms. Failing to meet this requirement
26 	 * leads to build failures due to the number of clients
27 	 * exceeding the limit. Still, it's important to test that
28 	 * the static shared interrupts work properly. As such,
29 	 * this test shall be restricted to a single platform, thus
30 	 * decreasing the risk of build errors appearing due to the
31 	 * chosen interrupts being used.
32 	 */
33 #ifndef CONFIG_BOARD_QEMU_CORTEX_A53
34 	ztest_test_skip();
35 #else
36 	int i;
37 
38 	IRQ_CONNECT(GIC_IRQ1, IRQ_PRIORITY, test_isr_0, 0, 0);
39 	IRQ_CONNECT(GIC_IRQ1, IRQ_PRIORITY, test_isr_1, (void *)1, 0);
40 	IRQ_CONNECT(GIC_IRQ2, IRQ_PRIORITY, test_isr_2, (void *)2, 0);
41 
42 	zassert_true(_sw_isr_table[GIC_IRQ1].isr == z_shared_isr,
43 		     "wrong _sw_isr_table ISR at GIC_IRQ1");
44 	zassert_true(_sw_isr_table[GIC_IRQ2].isr == test_isr_2,
45 		     "wrong _sw_isr_table ISR at GIC_IRQ1");
46 
47 	zassert_true(_sw_isr_table[GIC_IRQ1].arg ==
48 		     &z_shared_sw_isr_table[GIC_IRQ1],
49 		     "wrong _sw_isr_table arg at GIC_IRQ1");
50 	zassert_true(_sw_isr_table[GIC_IRQ2].arg == (void *)2,
51 		     "wrong _sw_isr_table arg at GIC_IRQ2");
52 
53 	zassert_true(z_shared_sw_isr_table[GIC_IRQ1].client_num == 2,
54 		     "wrong client number for GIC_IRQ1");
55 	zassert_true(!z_shared_sw_isr_table[GIC_IRQ2].client_num,
56 		     "wrong client number for GIC_IRQ2");
57 
58 	zassert_true(client_exists_at_index(test_isr_0, 0, GIC_IRQ1,
59 					    TEST_INVALID_IDX),
60 		     "test_isr_0 not a client for GIC_IRQ1");
61 	zassert_true(client_exists_at_index(test_isr_1, (void *)1, GIC_IRQ1,
62 					    TEST_INVALID_IDX),
63 		     "test_isr_1 not a client for GIC_IRQ1");
64 
65 	irq_enable(GIC_IRQ1);
66 	irq_enable(GIC_IRQ2);
67 
68 	trigger_irq(GIC_IRQ1);
69 	trigger_irq(GIC_IRQ2);
70 
71 	/* wait 5ms before checking the results */
72 	k_busy_wait(5000);
73 
74 	for (i = 0; i < TEST_VECTOR_SIZE; i++) {
75 		zassert_true(test_vector[i] == result_vector[i],
76 			     "wrong test_vector value at %d: 0x%x vs 0x%x",
77 			     i, test_vector[i], result_vector[i]);
78 	}
79 
80 	irq_disable(GIC_IRQ1);
81 	irq_disable(GIC_IRQ2);
82 
83 #ifdef CONFIG_DYNAMIC_INTERRUPTS
84 	/* if dynamic interrupts are enabled this will restore the _sw_isr_table
85 	 * entries for GIC_IRQ1 and GIC_IRQ2 to their default values (NULL,
86 	 * z_irq_spurious). In turn, this will increase the probability of
87 	 * dynamic_shared_irq.c's get_irq_slot() being able to find an available
88 	 * slot.
89 	 */
90 	arch_irq_disconnect_dynamic(GIC_IRQ1, IRQ_PRIORITY, test_isr_0, 0, 0);
91 	arch_irq_disconnect_dynamic(GIC_IRQ1, IRQ_PRIORITY, test_isr_1, (void *)1, 0);
92 	arch_irq_disconnect_dynamic(GIC_IRQ2, IRQ_PRIORITY, test_isr_2, (void *)2, 0);
93 #endif /* CONFIG_DYNAMIC_INTERRUPTS */
94 
95 #endif /* CONFIG_BOARD_QEMU_CORTEX_A53 */
96 }
97