1 /*
2 * Copyright (c) 2020 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/ztest.h>
8 #include <zephyr/devicetree.h>
9 #include <zephyr/device.h>
10
11 #define TEST_GPIO DT_NODELABEL(test_gpio_0)
12 #define TEST_I2C DT_NODELABEL(test_i2c)
13 #define TEST_DEVA DT_NODELABEL(test_dev_a)
14 #define TEST_GPIOX DT_NODELABEL(test_gpiox)
15 #define TEST_DEVB DT_NODELABEL(test_dev_b)
16 #define TEST_DEVC DT_NODELABEL(test_dev_c)
17 #define TEST_PARTITION DT_NODELABEL(test_p0)
18 #define TEST_GPIO_INJECTED DT_NODELABEL(test_gpio_injected)
19 #define TEST_NOLABEL DT_PATH(test, i2c_11112222, test_i2c_dev_14)
20
21 static const struct device *devlist;
22 static const struct device *devlist_end;
23
24 static device_handle_t init_order[10];
25
dev_init(const struct device * dev)26 static int dev_init(const struct device *dev)
27 {
28 static uint8_t init_idx;
29
30 __ASSERT_NO_MSG(init_idx < ARRAY_SIZE(init_order));
31 init_order[init_idx++] = device_handle_get(dev);
32
33 return 0;
34 }
35
36 DEVICE_DT_DEFINE(TEST_GPIO, dev_init, NULL,
37 NULL, NULL, PRE_KERNEL_1, 90, NULL);
38 DEVICE_DT_DEFINE(TEST_I2C, dev_init, NULL,
39 NULL, NULL, POST_KERNEL, 10, NULL);
40 DEVICE_DT_DEFINE(TEST_DEVA, dev_init, NULL,
41 NULL, NULL, POST_KERNEL, 20, NULL);
42 /* NB: Intentional init devb before required gpiox */
43 DEVICE_DT_DEFINE(TEST_DEVB, dev_init, NULL,
44 NULL, NULL, POST_KERNEL, 30, NULL);
45 DEVICE_DT_DEFINE(TEST_GPIOX, dev_init, NULL,
46 NULL, NULL, POST_KERNEL, 40, NULL);
47 DEVICE_DT_DEFINE(TEST_DEVC, dev_init, NULL,
48 NULL, NULL, POST_KERNEL, 50, NULL);
49 DEVICE_DT_DEFINE(TEST_PARTITION, dev_init, NULL,
50 NULL, NULL, POST_KERNEL, 60, NULL);
51 /* Device with both an existing and missing injected dependency */
52 DEVICE_DT_DEFINE(TEST_GPIO_INJECTED, dev_init, NULL,
53 NULL, NULL, POST_KERNEL, 70, NULL, DT_DEP_ORD(TEST_DEVB), 999);
54 /* Manually specified device */
55 DEVICE_DEFINE(manual_dev, "Manual Device", dev_init, NULL,
56 NULL, NULL, POST_KERNEL, 80, NULL);
57 /* Device with no nodelabel */
58 DEVICE_DT_DEFINE(TEST_NOLABEL, dev_init, NULL,
59 NULL, NULL, POST_KERNEL, 90, NULL);
60
61 #define DEV_HDL(node_id) device_handle_get(DEVICE_DT_GET(node_id))
62 #define DEV_HDL_NAME(name) device_handle_get(DEVICE_GET(name))
63
ZTEST(devicetree_devices,test_init_get)64 ZTEST(devicetree_devices, test_init_get)
65 {
66 /* Check device pointers */
67 zassert_equal(DEVICE_INIT_DT_GET(TEST_GPIO)->dev,
68 DEVICE_DT_GET(TEST_GPIO), NULL);
69 zassert_equal(DEVICE_INIT_DT_GET(TEST_I2C)->dev,
70 DEVICE_DT_GET(TEST_I2C), NULL);
71 zassert_equal(DEVICE_INIT_DT_GET(TEST_DEVA)->dev,
72 DEVICE_DT_GET(TEST_DEVA), NULL);
73 zassert_equal(DEVICE_INIT_DT_GET(TEST_DEVB)->dev,
74 DEVICE_DT_GET(TEST_DEVB), NULL);
75 zassert_equal(DEVICE_INIT_DT_GET(TEST_GPIOX)->dev,
76 DEVICE_DT_GET(TEST_GPIOX), NULL);
77 zassert_equal(DEVICE_INIT_DT_GET(TEST_DEVC)->dev,
78 DEVICE_DT_GET(TEST_DEVC), NULL);
79 zassert_equal(DEVICE_INIT_DT_GET(TEST_PARTITION)->dev,
80 DEVICE_DT_GET(TEST_PARTITION), NULL);
81 zassert_equal(DEVICE_INIT_DT_GET(TEST_GPIO_INJECTED)->dev,
82 DEVICE_DT_GET(TEST_GPIO_INJECTED), NULL);
83 zassert_equal(DEVICE_INIT_GET(manual_dev)->dev,
84 DEVICE_GET(manual_dev), NULL);
85 zassert_equal(DEVICE_INIT_DT_GET(TEST_NOLABEL)->dev,
86 DEVICE_DT_GET(TEST_NOLABEL), NULL);
87
88 /* Check init functions */
89 zassert_equal(DEVICE_INIT_DT_GET(TEST_GPIO)->init_fn.dev, dev_init);
90 zassert_equal(DEVICE_INIT_DT_GET(TEST_I2C)->init_fn.dev, dev_init);
91 zassert_equal(DEVICE_INIT_DT_GET(TEST_DEVA)->init_fn.dev, dev_init);
92 zassert_equal(DEVICE_INIT_DT_GET(TEST_DEVB)->init_fn.dev, dev_init);
93 zassert_equal(DEVICE_INIT_DT_GET(TEST_GPIOX)->init_fn.dev, dev_init);
94 zassert_equal(DEVICE_INIT_DT_GET(TEST_DEVC)->init_fn.dev, dev_init);
95 zassert_equal(DEVICE_INIT_DT_GET(TEST_PARTITION)->init_fn.dev, dev_init);
96 zassert_equal(DEVICE_INIT_DT_GET(TEST_GPIO_INJECTED)->init_fn.dev, dev_init);
97 zassert_equal(DEVICE_INIT_GET(manual_dev)->init_fn.dev, dev_init);
98 zassert_equal(DEVICE_INIT_DT_GET(TEST_NOLABEL)->init_fn.dev, dev_init);
99 }
100
ZTEST(devicetree_devices,test_init_order)101 ZTEST(devicetree_devices, test_init_order)
102 {
103 zassert_equal(init_order[0], DEV_HDL(TEST_GPIO));
104 zassert_equal(init_order[1], DEV_HDL(TEST_I2C));
105 zassert_equal(init_order[2], DEV_HDL(TEST_DEVA));
106 zassert_equal(init_order[3], DEV_HDL(TEST_DEVB));
107 zassert_equal(init_order[4], DEV_HDL(TEST_GPIOX));
108 zassert_equal(init_order[5], DEV_HDL(TEST_DEVC));
109 zassert_equal(init_order[6], DEV_HDL(TEST_PARTITION));
110 zassert_equal(init_order[7], DEV_HDL(TEST_GPIO_INJECTED));
111 zassert_equal(init_order[8], DEV_HDL_NAME(manual_dev));
112 zassert_equal(init_order[9], DEV_HDL(TEST_NOLABEL));
113 }
114
check_handle(device_handle_t hdl,const device_handle_t * hdls,size_t nhdls)115 static bool check_handle(device_handle_t hdl,
116 const device_handle_t *hdls,
117 size_t nhdls)
118 {
119 const device_handle_t *hdle = hdls + nhdls;
120
121 while (hdls < hdle) {
122 if (*hdls == hdl) {
123 return true;
124 }
125 ++hdls;
126 }
127
128 return false;
129 }
130
131 struct visitor_context {
132 uint8_t ndevs;
133 const struct device *rdevs[2];
134 };
135
device_visitor(const struct device * dev,void * context)136 static int device_visitor(const struct device *dev,
137 void *context)
138 {
139 struct visitor_context *ctx = context;
140 const struct device **rdp = ctx->rdevs;
141
142 while (rdp < (ctx->rdevs + ctx->ndevs)) {
143 if (*rdp == NULL) {
144 *rdp = dev;
145 return 0;
146 }
147
148 ++rdp;
149 }
150
151 return -ENOSPC;
152 }
153
ZTEST(devicetree_devices,test_requires)154 ZTEST(devicetree_devices, test_requires)
155 {
156 size_t nhdls = 0;
157 const device_handle_t *hdls;
158 const struct device *dev;
159 struct visitor_context ctx = { 0 };
160
161 /* TEST_GPIO: no req */
162 dev = device_get_binding(DEVICE_DT_NAME(TEST_GPIO));
163 zassert_equal(dev, DEVICE_DT_GET(TEST_GPIO));
164 hdls = device_required_handles_get(dev, &nhdls);
165 zassert_equal(nhdls, 0);
166 zassert_equal(0, device_required_foreach(dev, device_visitor, &ctx),
167 NULL);
168
169 /* TEST_GPIO_INJECTED: no req */
170 dev = device_get_binding(DEVICE_DT_NAME(TEST_GPIO_INJECTED));
171 zassert_equal(dev, DEVICE_DT_GET(TEST_GPIO_INJECTED));
172 hdls = device_required_handles_get(dev, &nhdls);
173 zassert_equal(nhdls, 0);
174 zassert_equal(0, device_required_foreach(dev, device_visitor, &ctx),
175 NULL);
176
177 /* TEST_I2C: no req */
178 dev = device_get_binding(DEVICE_DT_NAME(TEST_I2C));
179 zassert_equal(dev, DEVICE_DT_GET(TEST_I2C));
180 hdls = device_required_handles_get(dev, &nhdls);
181 zassert_equal(nhdls, 0);
182 zassert_equal(0, device_required_foreach(dev, device_visitor, &ctx),
183 NULL);
184
185 /* TEST_DEVA: TEST_I2C GPIO */
186 dev = device_get_binding(DEVICE_DT_NAME(TEST_DEVA));
187 zassert_equal(dev, DEVICE_DT_GET(TEST_DEVA));
188 hdls = device_required_handles_get(dev, &nhdls);
189 zassert_equal(nhdls, 2);
190 zassert_true(check_handle(DEV_HDL(TEST_I2C), hdls, nhdls));
191 zassert_true(check_handle(DEV_HDL(TEST_GPIO), hdls, nhdls));
192
193 /* Visit fails if not enough space */
194 ctx = (struct visitor_context){
195 .ndevs = 1,
196 };
197 zassert_equal(-ENOSPC, device_required_foreach(dev, device_visitor, &ctx),
198 NULL);
199
200 /* Visit succeeds if enough space. */
201 ctx = (struct visitor_context){
202 .ndevs = 2,
203 };
204 zassert_equal(2, device_required_foreach(dev, device_visitor, &ctx),
205 NULL);
206 zassert_true((ctx.rdevs[0] == device_from_handle(DEV_HDL(TEST_I2C)))
207 || (ctx.rdevs[1] == device_from_handle(DEV_HDL(TEST_I2C))),
208 NULL);
209 zassert_true((ctx.rdevs[0] == device_from_handle(DEV_HDL(TEST_GPIO)))
210 || (ctx.rdevs[1] == device_from_handle(DEV_HDL(TEST_GPIO))),
211 NULL);
212
213 /* TEST_GPIOX: TEST_I2C */
214 dev = device_get_binding(DEVICE_DT_NAME(TEST_GPIOX));
215 zassert_equal(dev, DEVICE_DT_GET(TEST_GPIOX));
216 hdls = device_required_handles_get(dev, &nhdls);
217 zassert_equal(nhdls, 1);
218 zassert_true(check_handle(DEV_HDL(TEST_I2C), hdls, nhdls));
219 ctx = (struct visitor_context){
220 .ndevs = 3,
221 };
222 zassert_equal(1, device_required_foreach(dev, device_visitor, &ctx),
223 NULL);
224 zassert_true(ctx.rdevs[0] == device_from_handle(DEV_HDL(TEST_I2C)),
225 NULL);
226
227 /* TEST_DEVB: TEST_I2C TEST_GPIOX */
228 dev = device_get_binding(DEVICE_DT_NAME(TEST_DEVB));
229 zassert_equal(dev, DEVICE_DT_GET(TEST_DEVB));
230 hdls = device_required_handles_get(dev, &nhdls);
231 zassert_equal(nhdls, 2);
232 zassert_true(check_handle(DEV_HDL(TEST_I2C), hdls, nhdls));
233 zassert_true(check_handle(DEV_HDL(TEST_GPIOX), hdls, nhdls));
234
235 /* TEST_GPIO_INJECTED: NONE */
236 dev = device_get_binding(DEVICE_DT_NAME(TEST_GPIO_INJECTED));
237 zassert_equal(dev, DEVICE_DT_GET(TEST_GPIO_INJECTED));
238 hdls = device_required_handles_get(dev, &nhdls);
239 zassert_equal(nhdls, 0);
240 }
241
ZTEST(devicetree_devices,test_injected)242 ZTEST(devicetree_devices, test_injected)
243 {
244 size_t nhdls = 0;
245 const device_handle_t *hdls;
246 const struct device *dev;
247
248 /* TEST_GPIO: NONE */
249 dev = device_get_binding(DEVICE_DT_NAME(TEST_GPIO));
250 hdls = device_injected_handles_get(dev, &nhdls);
251 zassert_equal(nhdls, 0);
252
253 /* TEST_DEVB: NONE */
254 dev = device_get_binding(DEVICE_DT_NAME(TEST_DEVB));
255 hdls = device_injected_handles_get(dev, &nhdls);
256 zassert_equal(nhdls, 0);
257
258 /* TEST_GPIO_INJECTED: TEST_DEVB */
259 dev = device_get_binding(DEVICE_DT_NAME(TEST_GPIO_INJECTED));
260 hdls = device_injected_handles_get(dev, &nhdls);
261 zassert_equal(nhdls, 1);
262 zassert_true(check_handle(DEV_HDL(TEST_DEVB), hdls, nhdls));
263 }
264
ZTEST(devicetree_devices,test_get_or_null)265 ZTEST(devicetree_devices, test_get_or_null)
266 {
267 const struct device *dev;
268
269 dev = DEVICE_DT_GET_OR_NULL(TEST_DEVA);
270 zassert_not_equal(dev, NULL, NULL);
271
272 dev = DEVICE_DT_GET_OR_NULL(non_existing_node);
273 zassert_is_null(dev);
274 }
275
ZTEST(devicetree_devices,test_supports)276 ZTEST(devicetree_devices, test_supports)
277 {
278 size_t nhdls = 0;
279 const device_handle_t *hdls;
280 const struct device *dev;
281 struct visitor_context ctx = { 0 };
282
283 /* TEST_DEVB: None */
284 dev = DEVICE_DT_GET(TEST_DEVB);
285 hdls = device_supported_handles_get(dev, &nhdls);
286 zassert_equal(nhdls, 1);
287 zassert_true(check_handle(DEV_HDL(TEST_GPIO_INJECTED), hdls, nhdls));
288
289 /* TEST_GPIO_INJECTED: None */
290 dev = DEVICE_DT_GET(TEST_GPIO_INJECTED);
291 hdls = device_supported_handles_get(dev, &nhdls);
292 zassert_equal(nhdls, 0);
293
294 /* TEST_GPIO: TEST_DEVA */
295 dev = DEVICE_DT_GET(TEST_GPIO);
296 hdls = device_supported_handles_get(dev, &nhdls);
297 zassert_equal(nhdls, 1);
298 zassert_true(check_handle(DEV_HDL(TEST_DEVA), hdls, nhdls));
299
300 /* Visit fails if not enough space */
301 ctx = (struct visitor_context){
302 .ndevs = 0,
303 };
304 zassert_equal(-ENOSPC, device_supported_foreach(dev, device_visitor, &ctx));
305
306 /* Visit succeeds if enough space. */
307 ctx = (struct visitor_context){
308 .ndevs = 1,
309 };
310 zassert_equal(1, device_supported_foreach(dev, device_visitor, &ctx));
311 zassert_true(ctx.rdevs[0] == device_from_handle(DEV_HDL(TEST_DEVA)));
312
313 /* TEST_I2C: TEST_DEVA TEST_GPIOX TEST_DEVB TEST_DEVC */
314 dev = DEVICE_DT_GET(TEST_I2C);
315 hdls = device_supported_handles_get(dev, &nhdls);
316 zassert_equal(nhdls, 5);
317 zassert_true(check_handle(DEV_HDL(TEST_DEVA), hdls, nhdls));
318 zassert_true(check_handle(DEV_HDL(TEST_GPIOX), hdls, nhdls));
319 zassert_true(check_handle(DEV_HDL(TEST_DEVB), hdls, nhdls));
320 zassert_true(check_handle(DEV_HDL(TEST_DEVC), hdls, nhdls));
321 zassert_true(check_handle(DEV_HDL(TEST_NOLABEL), hdls, nhdls));
322
323 /* Support forwarding (intermediate missing devicetree node)
324 * TEST_DEVC: TEST_PARTITION
325 */
326 dev = DEVICE_DT_GET(TEST_DEVC);
327 hdls = device_supported_handles_get(dev, &nhdls);
328 zassert_equal(nhdls, 1);
329 zassert_true(check_handle(DEV_HDL(TEST_PARTITION), hdls, nhdls));
330 }
331
devicetree_devices_setup(void)332 void *devicetree_devices_setup(void)
333 {
334 size_t ndevs;
335
336 ndevs = z_device_get_all_static(&devlist);
337 devlist_end = devlist + ndevs;
338
339 return NULL;
340 }
341 ZTEST_SUITE(devicetree_devices, NULL, devicetree_devices_setup, NULL, NULL, NULL);
342