1 /*
2  * Copyright (c) 2021 BayLibre, SAS
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/ztest.h>
8 #include <zephyr/device.h>
9 #include <zephyr/drivers/interrupt_controller/gicv3_its.h>
10 
11 #define DT_DRV_COMPAT   arm_gic_v3_its
12 
13 static volatile unsigned int last_lpi_irq_num;
14 
lpi_irq_handle(const void * parameter)15 static void lpi_irq_handle(const void *parameter)
16 {
17 	uintptr_t i = (uintptr_t)parameter;
18 
19 	last_lpi_irq_num = i;
20 }
21 
22 /* Generate a DeviceID over the whole 16bits */
23 #define ITS_TEST_DEV(id)        ((((id + 256) % 16) << 12) | (((id + 256) % 24) << 8) | (id & 0xff))
24 
25 /* Cover up to 8192 LPIs over 256 DevicesIDs and 32 EventIDs per DeviceID */
26 #define ITS_TEST_NUM_DEVS       256
27 #define ITS_TEST_NUM_ITES       32
28 
29 /* Do not test all 8192 irqs, iterate with a prime offset to cover most of the possible event_ids */
30 #define ITS_TEST_NEXT		13
31 
32 /* Active-wait loops waiting for an interrupt */
33 #define ITS_TEST_LOOPS		10
34 
35 unsigned int vectors[ITS_TEST_NUM_DEVS][ITS_TEST_NUM_ITES];
36 
ZTEST(arm64_gicv3_its,test_gicv3_its_alloc)37 ZTEST(arm64_gicv3_its, test_gicv3_its_alloc)
38 {
39 	int devn, event_id;
40 	const struct device *const dev = DEVICE_DT_INST_GET(0);
41 
42 	zassert_false(dev == NULL, "");
43 
44 	for (devn = 0; devn < ITS_TEST_NUM_DEVS; ++devn) {
45 		int device_id = ITS_TEST_DEV(devn);
46 
47 		zassert_true(its_setup_deviceid(dev, device_id, ITS_TEST_NUM_ITES) == 0, "");
48 
49 		for (event_id = 0; event_id < ITS_TEST_NUM_ITES; ++event_id) {
50 			vectors[devn][event_id] = its_alloc_intid(dev);
51 			zassert_true(vectors[devn][event_id] >= 8192, "");
52 			zassert_true(vectors[devn][event_id] < CONFIG_NUM_IRQS, "");
53 
54 			zassert_true(its_map_intid(dev, device_id, event_id,
55 						   vectors[devn][event_id]) == 0, "");
56 		}
57 	}
58 }
59 
ZTEST(arm64_gicv3_its,test_gicv3_its_connect)60 ZTEST(arm64_gicv3_its, test_gicv3_its_connect)
61 {
62 	int devn, event_id;
63 	const struct device *const dev = DEVICE_DT_INST_GET(0);
64 	unsigned int remain = 0;
65 
66 	zassert_false(dev == NULL, "");
67 
68 	for (devn = 0; devn < ITS_TEST_NUM_DEVS; ++devn) {
69 		for (event_id = remain; event_id < ITS_TEST_NUM_ITES; event_id += ITS_TEST_NEXT) {
70 			unsigned int irqn = vectors[devn][event_id];
71 
72 			zassert_true(irq_connect_dynamic(irqn, 0, lpi_irq_handle,
73 							 (void *)(uintptr_t)(irqn), 0) == irqn, "");
74 
75 			irq_enable(irqn);
76 		}
77 		remain = event_id - ITS_TEST_NUM_ITES;
78 	}
79 }
80 
ZTEST(arm64_gicv3_its,test_gicv3_its_irq_simple)81 ZTEST(arm64_gicv3_its, test_gicv3_its_irq_simple)
82 {
83 	const struct device *const dev = DEVICE_DT_INST_GET(0);
84 	unsigned int irqn = vectors[0][0];
85 	unsigned int timeout;
86 	int device_id = ITS_TEST_DEV(0);
87 	int event_id = 0;
88 
89 	zassert_false(dev == NULL, "");
90 
91 	last_lpi_irq_num = 0;
92 	zassert_true(its_send_int(dev, device_id, event_id) == 0, "");
93 
94 	timeout = ITS_TEST_LOOPS;
95 	while (!last_lpi_irq_num && timeout) {
96 		timeout--;
97 	}
98 
99 	zassert_true(last_lpi_irq_num == irqn,
100 			"IRQ %d of DeviceID %x EventID %d failed",
101 			irqn, device_id, event_id);
102 }
103 
ZTEST(arm64_gicv3_its,test_gicv3_its_irq_disable)104 ZTEST(arm64_gicv3_its, test_gicv3_its_irq_disable)
105 {
106 	const struct device *const dev = DEVICE_DT_INST_GET(0);
107 	unsigned int irqn = vectors[0][0];
108 	unsigned int timeout;
109 	int device_id = ITS_TEST_DEV(0);
110 	int event_id = 0;
111 
112 	zassert_false(dev == NULL, "");
113 
114 	irq_disable(irqn);
115 
116 	last_lpi_irq_num = 0;
117 	zassert_true(its_send_int(dev, device_id, event_id) == 0, "");
118 
119 	timeout = ITS_TEST_LOOPS;
120 	while (!last_lpi_irq_num && timeout) {
121 		timeout--;
122 	}
123 
124 	zassert_true(last_lpi_irq_num == 0,
125 			"IRQ %d of DeviceID %x EventID %d disable failed",
126 			irqn, device_id, event_id);
127 
128 	irq_enable(irqn);
129 
130 	last_lpi_irq_num = 0;
131 	zassert_true(its_send_int(dev, device_id, event_id) == 0, "");
132 
133 	timeout = ITS_TEST_LOOPS;
134 	while (!last_lpi_irq_num && timeout) {
135 		timeout--;
136 	}
137 
138 	zassert_true(last_lpi_irq_num == irqn,
139 			"IRQ %d of DeviceID %x EventID %d re-enable failed",
140 			irqn, device_id, event_id);
141 }
142 
ZTEST(arm64_gicv3_its,test_gicv3_its_irq)143 ZTEST(arm64_gicv3_its, test_gicv3_its_irq)
144 {
145 	int devn, event_id;
146 	const struct device *const dev = DEVICE_DT_INST_GET(0);
147 	unsigned int timeout;
148 	unsigned int remain = 0;
149 
150 	zassert_false(dev == NULL, "");
151 
152 	for (devn = 0; devn < ITS_TEST_NUM_DEVS; ++devn) {
153 		int device_id = ITS_TEST_DEV(devn);
154 
155 		for (event_id = remain; event_id < ITS_TEST_NUM_ITES; event_id += ITS_TEST_NEXT) {
156 			unsigned int irqn = vectors[devn][event_id];
157 
158 			last_lpi_irq_num = 0;
159 			zassert_true(its_send_int(dev, device_id, event_id) == 0, "");
160 
161 			timeout = ITS_TEST_LOOPS;
162 			while (!last_lpi_irq_num && timeout) {
163 				timeout--;
164 			}
165 
166 			zassert_true(last_lpi_irq_num == irqn,
167 				     "IRQ %d of DeviceID %x EventID %d failed",
168 				     irqn, device_id, event_id);
169 		}
170 
171 		remain = event_id - ITS_TEST_NUM_ITES;
172 	}
173 }
174 
175 ZTEST_SUITE(arm64_gicv3_its, NULL, NULL, NULL, NULL, NULL);
176