]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
2e7d35d2 SG |
2 | /* |
3 | * Tests for the core driver model code | |
4 | * | |
5 | * Copyright (c) 2013 Google, Inc | |
2e7d35d2 SG |
6 | */ |
7 | ||
8 | #include <common.h> | |
9 | #include <errno.h> | |
10 | #include <dm.h> | |
11 | #include <fdtdec.h> | |
f7ae49fc | 12 | #include <log.h> |
2e7d35d2 | 13 | #include <malloc.h> |
401d1c4f | 14 | #include <asm/global_data.h> |
2e7d35d2 SG |
15 | #include <dm/device-internal.h> |
16 | #include <dm/root.h> | |
2e7d35d2 SG |
17 | #include <dm/util.h> |
18 | #include <dm/test.h> | |
19 | #include <dm/uclass-internal.h> | |
0e1fad43 | 20 | #include <test/test.h> |
e721b882 | 21 | #include <test/ut.h> |
2e7d35d2 SG |
22 | |
23 | DECLARE_GLOBAL_DATA_PTR; | |
24 | ||
25 | enum { | |
26 | TEST_INTVAL1 = 0, | |
27 | TEST_INTVAL2 = 3, | |
28 | TEST_INTVAL3 = 6, | |
29 | TEST_INTVAL_MANUAL = 101112, | |
00606d7e | 30 | TEST_INTVAL_PRE_RELOC = 7, |
2e7d35d2 SG |
31 | }; |
32 | ||
33 | static const struct dm_test_pdata test_pdata[] = { | |
34 | { .ping_add = TEST_INTVAL1, }, | |
35 | { .ping_add = TEST_INTVAL2, }, | |
36 | { .ping_add = TEST_INTVAL3, }, | |
37 | }; | |
38 | ||
39 | static const struct dm_test_pdata test_pdata_manual = { | |
40 | .ping_add = TEST_INTVAL_MANUAL, | |
41 | }; | |
42 | ||
00606d7e SG |
43 | static const struct dm_test_pdata test_pdata_pre_reloc = { |
44 | .ping_add = TEST_INTVAL_PRE_RELOC, | |
45 | }; | |
46 | ||
20e442ab | 47 | U_BOOT_DRVINFO(dm_test_info1) = { |
2e7d35d2 | 48 | .name = "test_drv", |
caa4daa2 | 49 | .plat = &test_pdata[0], |
2e7d35d2 SG |
50 | }; |
51 | ||
20e442ab | 52 | U_BOOT_DRVINFO(dm_test_info2) = { |
2e7d35d2 | 53 | .name = "test_drv", |
caa4daa2 | 54 | .plat = &test_pdata[1], |
2e7d35d2 SG |
55 | }; |
56 | ||
20e442ab | 57 | U_BOOT_DRVINFO(dm_test_info3) = { |
2e7d35d2 | 58 | .name = "test_drv", |
caa4daa2 | 59 | .plat = &test_pdata[2], |
2e7d35d2 SG |
60 | }; |
61 | ||
62 | static struct driver_info driver_info_manual = { | |
63 | .name = "test_manual_drv", | |
caa4daa2 | 64 | .plat = &test_pdata_manual, |
2e7d35d2 SG |
65 | }; |
66 | ||
00606d7e SG |
67 | static struct driver_info driver_info_pre_reloc = { |
68 | .name = "test_pre_reloc_drv", | |
caa4daa2 | 69 | .plat = &test_pdata_pre_reloc, |
00606d7e SG |
70 | }; |
71 | ||
24f927c5 SR |
72 | static struct driver_info driver_info_act_dma = { |
73 | .name = "test_act_dma_drv", | |
74 | }; | |
75 | ||
cc6f4c8f MV |
76 | static struct driver_info driver_info_vital_clk = { |
77 | .name = "test_vital_clk_drv", | |
78 | }; | |
79 | ||
80 | static struct driver_info driver_info_act_dma_vital_clk = { | |
81 | .name = "test_act_dma_vital_clk_drv", | |
82 | }; | |
83 | ||
e721b882 | 84 | void dm_leak_check_start(struct unit_test_state *uts) |
756ac0bb | 85 | { |
e721b882 JH |
86 | uts->start = mallinfo(); |
87 | if (!uts->start.uordblks) | |
756ac0bb SG |
88 | puts("Warning: Please add '#define DEBUG' to the top of common/dlmalloc.c\n"); |
89 | } | |
90 | ||
e721b882 | 91 | int dm_leak_check_end(struct unit_test_state *uts) |
756ac0bb SG |
92 | { |
93 | struct mallinfo end; | |
cbfc2ff9 | 94 | int id, diff; |
756ac0bb SG |
95 | |
96 | /* Don't delete the root class, since we started with that */ | |
97 | for (id = UCLASS_ROOT + 1; id < UCLASS_COUNT; id++) { | |
98 | struct uclass *uc; | |
99 | ||
100 | uc = uclass_find(id); | |
101 | if (!uc) | |
102 | continue; | |
103 | ut_assertok(uclass_destroy(uc)); | |
104 | } | |
105 | ||
106 | end = mallinfo(); | |
cbfc2ff9 SG |
107 | diff = end.uordblks - uts->start.uordblks; |
108 | if (diff > 0) | |
109 | printf("Leak: lost %#xd bytes\n", diff); | |
110 | else if (diff < 0) | |
111 | printf("Leak: gained %#xd bytes\n", -diff); | |
e721b882 | 112 | ut_asserteq(uts->start.uordblks, end.uordblks); |
756ac0bb SG |
113 | |
114 | return 0; | |
115 | } | |
116 | ||
caa4daa2 | 117 | /* Test that binding with plat occurs correctly */ |
e721b882 | 118 | static int dm_test_autobind(struct unit_test_state *uts) |
2e7d35d2 | 119 | { |
54c5d08a | 120 | struct udevice *dev; |
2e7d35d2 SG |
121 | |
122 | /* | |
123 | * We should have a single class (UCLASS_ROOT) and a single root | |
124 | * device with no children. | |
125 | */ | |
4a467c6d | 126 | ut_assert(uts->root); |
8a715530 | 127 | ut_asserteq(1, list_count_items(gd->uclass_root)); |
2e7d35d2 SG |
128 | ut_asserteq(0, list_count_items(&gd->dm_root->child_head)); |
129 | ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_POST_BIND]); | |
130 | ||
8a8d24bd | 131 | ut_assertok(dm_scan_plat(false)); |
2e7d35d2 SG |
132 | |
133 | /* We should have our test class now at least, plus more children */ | |
8a715530 | 134 | ut_assert(1 < list_count_items(gd->uclass_root)); |
2e7d35d2 SG |
135 | ut_assert(0 < list_count_items(&gd->dm_root->child_head)); |
136 | ||
137 | /* Our 3 dm_test_infox children should be bound to the test uclass */ | |
138 | ut_asserteq(3, dm_testdrv_op_count[DM_TEST_OP_POST_BIND]); | |
139 | ||
140 | /* No devices should be probed */ | |
141 | list_for_each_entry(dev, &gd->dm_root->child_head, sibling_node) | |
73466df3 | 142 | ut_assert(!(dev_get_flags(dev) & DM_FLAG_ACTIVATED)); |
2e7d35d2 SG |
143 | |
144 | /* Our test driver should have been bound 3 times */ | |
145 | ut_assert(dm_testdrv_op_count[DM_TEST_OP_BIND] == 3); | |
146 | ||
147 | return 0; | |
148 | } | |
149 | DM_TEST(dm_test_autobind, 0); | |
150 | ||
caa4daa2 | 151 | /* Test that binding with uclass plat allocation occurs correctly */ |
e721b882 | 152 | static int dm_test_autobind_uclass_pdata_alloc(struct unit_test_state *uts) |
754e71e8 PM |
153 | { |
154 | struct dm_test_perdev_uc_pdata *uc_pdata; | |
155 | struct udevice *dev; | |
156 | struct uclass *uc; | |
157 | ||
158 | ut_assertok(uclass_get(UCLASS_TEST, &uc)); | |
159 | ut_assert(uc); | |
160 | ||
161 | /** | |
162 | * Test if test uclass driver requires allocation for the uclass | |
caa4daa2 | 163 | * platform data and then check the dev->uclass_plat pointer. |
754e71e8 | 164 | */ |
caa4daa2 | 165 | ut_assert(uc->uc_drv->per_device_plat_auto); |
754e71e8 PM |
166 | |
167 | for (uclass_find_first_device(UCLASS_TEST, &dev); | |
168 | dev; | |
169 | uclass_find_next_device(&dev)) { | |
331caeaf | 170 | ut_assertnonnull(dev); |
754e71e8 | 171 | |
caa4daa2 | 172 | uc_pdata = dev_get_uclass_plat(dev); |
754e71e8 PM |
173 | ut_assert(uc_pdata); |
174 | } | |
175 | ||
176 | return 0; | |
177 | } | |
e180c2b1 | 178 | DM_TEST(dm_test_autobind_uclass_pdata_alloc, UT_TESTF_SCAN_PDATA); |
754e71e8 | 179 | |
9f6ae6de KVA |
180 | /* compare node names ignoring the unit address */ |
181 | static int dm_test_compare_node_name(struct unit_test_state *uts) | |
182 | { | |
183 | ofnode node; | |
184 | ||
185 | node = ofnode_path("/mmio-bus@0"); | |
186 | ut_assert(ofnode_valid(node)); | |
187 | ut_assert(ofnode_name_eq(node, "mmio-bus")); | |
188 | ||
189 | return 0; | |
190 | } | |
191 | ||
192 | DM_TEST(dm_test_compare_node_name, UT_TESTF_SCAN_PDATA); | |
193 | ||
caa4daa2 | 194 | /* Test that binding with uclass plat setting occurs correctly */ |
e721b882 | 195 | static int dm_test_autobind_uclass_pdata_valid(struct unit_test_state *uts) |
754e71e8 PM |
196 | { |
197 | struct dm_test_perdev_uc_pdata *uc_pdata; | |
198 | struct udevice *dev; | |
199 | ||
200 | /** | |
201 | * In the test_postbind() method of test uclass driver, the uclass | |
202 | * platform data should be set to three test int values - test it. | |
203 | */ | |
204 | for (uclass_find_first_device(UCLASS_TEST, &dev); | |
205 | dev; | |
206 | uclass_find_next_device(&dev)) { | |
331caeaf | 207 | ut_assertnonnull(dev); |
754e71e8 | 208 | |
caa4daa2 | 209 | uc_pdata = dev_get_uclass_plat(dev); |
754e71e8 PM |
210 | ut_assert(uc_pdata); |
211 | ut_assert(uc_pdata->intval1 == TEST_UC_PDATA_INTVAL1); | |
212 | ut_assert(uc_pdata->intval2 == TEST_UC_PDATA_INTVAL2); | |
213 | ut_assert(uc_pdata->intval3 == TEST_UC_PDATA_INTVAL3); | |
214 | } | |
215 | ||
216 | return 0; | |
217 | } | |
e180c2b1 | 218 | DM_TEST(dm_test_autobind_uclass_pdata_valid, UT_TESTF_SCAN_PDATA); |
754e71e8 | 219 | |
2e7d35d2 | 220 | /* Test that autoprobe finds all the expected devices */ |
e721b882 | 221 | static int dm_test_autoprobe(struct unit_test_state *uts) |
2e7d35d2 SG |
222 | { |
223 | int expected_base_add; | |
54c5d08a | 224 | struct udevice *dev; |
2e7d35d2 SG |
225 | struct uclass *uc; |
226 | int i; | |
227 | ||
228 | ut_assertok(uclass_get(UCLASS_TEST, &uc)); | |
229 | ut_assert(uc); | |
230 | ||
231 | ut_asserteq(1, dm_testdrv_op_count[DM_TEST_OP_INIT]); | |
02c07b37 | 232 | ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_PRE_PROBE]); |
2e7d35d2 SG |
233 | ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_POST_PROBE]); |
234 | ||
235 | /* The root device should not be activated until needed */ | |
4a467c6d | 236 | ut_assert(dev_get_flags(uts->root) & DM_FLAG_ACTIVATED); |
2e7d35d2 SG |
237 | |
238 | /* | |
239 | * We should be able to find the three test devices, and they should | |
240 | * all be activated as they are used (lazy activation, required by | |
241 | * U-Boot) | |
242 | */ | |
243 | for (i = 0; i < 3; i++) { | |
244 | ut_assertok(uclass_find_device(UCLASS_TEST, i, &dev)); | |
245 | ut_assert(dev); | |
73466df3 | 246 | ut_assertf(!(dev_get_flags(dev) & DM_FLAG_ACTIVATED), |
2e7d35d2 SG |
247 | "Driver %d/%s already activated", i, dev->name); |
248 | ||
249 | /* This should activate it */ | |
250 | ut_assertok(uclass_get_device(UCLASS_TEST, i, &dev)); | |
251 | ut_assert(dev); | |
73466df3 | 252 | ut_assert(dev_get_flags(dev) & DM_FLAG_ACTIVATED); |
2e7d35d2 SG |
253 | |
254 | /* Activating a device should activate the root device */ | |
255 | if (!i) | |
4a467c6d | 256 | ut_assert(dev_get_flags(uts->root) & DM_FLAG_ACTIVATED); |
2e7d35d2 SG |
257 | } |
258 | ||
02c07b37 SG |
259 | /* |
260 | * Our 3 dm_test_info children should be passed to pre_probe and | |
261 | * post_probe | |
262 | */ | |
2e7d35d2 | 263 | ut_asserteq(3, dm_testdrv_op_count[DM_TEST_OP_POST_PROBE]); |
02c07b37 | 264 | ut_asserteq(3, dm_testdrv_op_count[DM_TEST_OP_PRE_PROBE]); |
2e7d35d2 SG |
265 | |
266 | /* Also we can check the per-device data */ | |
267 | expected_base_add = 0; | |
268 | for (i = 0; i < 3; i++) { | |
269 | struct dm_test_uclass_perdev_priv *priv; | |
270 | struct dm_test_pdata *pdata; | |
271 | ||
272 | ut_assertok(uclass_find_device(UCLASS_TEST, i, &dev)); | |
273 | ut_assert(dev); | |
274 | ||
e564f054 | 275 | priv = dev_get_uclass_priv(dev); |
2e7d35d2 SG |
276 | ut_assert(priv); |
277 | ut_asserteq(expected_base_add, priv->base_add); | |
278 | ||
0fd3d911 | 279 | pdata = dev_get_plat(dev); |
2e7d35d2 SG |
280 | expected_base_add += pdata->ping_add; |
281 | } | |
282 | ||
283 | return 0; | |
284 | } | |
e180c2b1 | 285 | DM_TEST(dm_test_autoprobe, UT_TESTF_SCAN_PDATA); |
2e7d35d2 | 286 | |
caa4daa2 | 287 | /* Check that we see the correct plat in each device */ |
8a8d24bd | 288 | static int dm_test_plat(struct unit_test_state *uts) |
2e7d35d2 SG |
289 | { |
290 | const struct dm_test_pdata *pdata; | |
54c5d08a | 291 | struct udevice *dev; |
2e7d35d2 SG |
292 | int i; |
293 | ||
294 | for (i = 0; i < 3; i++) { | |
295 | ut_assertok(uclass_find_device(UCLASS_TEST, i, &dev)); | |
296 | ut_assert(dev); | |
0fd3d911 | 297 | pdata = dev_get_plat(dev); |
2e7d35d2 SG |
298 | ut_assert(pdata->ping_add == test_pdata[i].ping_add); |
299 | } | |
300 | ||
301 | return 0; | |
302 | } | |
8a8d24bd | 303 | DM_TEST(dm_test_plat, UT_TESTF_SCAN_PDATA); |
2e7d35d2 SG |
304 | |
305 | /* Test that we can bind, probe, remove, unbind a driver */ | |
e721b882 | 306 | static int dm_test_lifecycle(struct unit_test_state *uts) |
2e7d35d2 SG |
307 | { |
308 | int op_count[DM_TEST_OP_COUNT]; | |
54c5d08a | 309 | struct udevice *dev, *test_dev; |
6476c4d9 SG |
310 | int start_dev_count, start_uc_count; |
311 | int dev_count, uc_count; | |
2e7d35d2 SG |
312 | int pingret; |
313 | int ret; | |
314 | ||
315 | memcpy(op_count, dm_testdrv_op_count, sizeof(op_count)); | |
316 | ||
6476c4d9 SG |
317 | dm_get_stats(&start_dev_count, &start_uc_count); |
318 | ||
4a467c6d | 319 | ut_assertok(device_bind_by_name(uts->root, false, &driver_info_manual, |
2e7d35d2 SG |
320 | &dev)); |
321 | ut_assert(dev); | |
322 | ut_assert(dm_testdrv_op_count[DM_TEST_OP_BIND] | |
323 | == op_count[DM_TEST_OP_BIND] + 1); | |
0fd3d911 | 324 | ut_assert(!dev_get_priv(dev)); |
2e7d35d2 | 325 | |
6476c4d9 SG |
326 | /* We should have one more device */ |
327 | dm_get_stats(&dev_count, &uc_count); | |
328 | ut_asserteq(start_dev_count + 1, dev_count); | |
329 | ut_asserteq(start_uc_count, uc_count); | |
330 | ||
2e7d35d2 | 331 | /* Probe the device - it should fail allocating private data */ |
4a467c6d | 332 | uts->force_fail_alloc = 1; |
2e7d35d2 SG |
333 | ret = device_probe(dev); |
334 | ut_assert(ret == -ENOMEM); | |
335 | ut_assert(dm_testdrv_op_count[DM_TEST_OP_PROBE] | |
336 | == op_count[DM_TEST_OP_PROBE] + 1); | |
0fd3d911 | 337 | ut_assert(!dev_get_priv(dev)); |
2e7d35d2 SG |
338 | |
339 | /* Try again without the alloc failure */ | |
4a467c6d | 340 | uts->force_fail_alloc = 0; |
2e7d35d2 SG |
341 | ut_assertok(device_probe(dev)); |
342 | ut_assert(dm_testdrv_op_count[DM_TEST_OP_PROBE] | |
343 | == op_count[DM_TEST_OP_PROBE] + 2); | |
0fd3d911 | 344 | ut_assert(dev_get_priv(dev)); |
2e7d35d2 SG |
345 | |
346 | /* This should be device 3 in the uclass */ | |
347 | ut_assertok(uclass_find_device(UCLASS_TEST, 3, &test_dev)); | |
348 | ut_assert(dev == test_dev); | |
349 | ||
350 | /* Try ping */ | |
351 | ut_assertok(test_ping(dev, 100, &pingret)); | |
352 | ut_assert(pingret == 102); | |
353 | ||
354 | /* Now remove device 3 */ | |
355 | ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_PRE_REMOVE]); | |
706865af | 356 | ut_assertok(device_remove(dev, DM_REMOVE_NORMAL)); |
2e7d35d2 SG |
357 | ut_asserteq(1, dm_testdrv_op_count[DM_TEST_OP_PRE_REMOVE]); |
358 | ||
359 | ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_UNBIND]); | |
360 | ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_PRE_UNBIND]); | |
361 | ut_assertok(device_unbind(dev)); | |
362 | ut_asserteq(1, dm_testdrv_op_count[DM_TEST_OP_UNBIND]); | |
363 | ut_asserteq(1, dm_testdrv_op_count[DM_TEST_OP_PRE_UNBIND]); | |
364 | ||
6476c4d9 SG |
365 | /* We should have one less device */ |
366 | dm_get_stats(&dev_count, &uc_count); | |
367 | ut_asserteq(start_dev_count, dev_count); | |
368 | ut_asserteq(start_uc_count, uc_count); | |
369 | ||
2e7d35d2 SG |
370 | return 0; |
371 | } | |
e180c2b1 | 372 | DM_TEST(dm_test_lifecycle, UT_TESTF_SCAN_PDATA | UT_TESTF_PROBE_TEST); |
2e7d35d2 SG |
373 | |
374 | /* Test that we can bind/unbind and the lists update correctly */ | |
e721b882 | 375 | static int dm_test_ordering(struct unit_test_state *uts) |
2e7d35d2 | 376 | { |
54c5d08a | 377 | struct udevice *dev, *dev_penultimate, *dev_last, *test_dev; |
2e7d35d2 SG |
378 | int pingret; |
379 | ||
4a467c6d | 380 | ut_assertok(device_bind_by_name(uts->root, false, &driver_info_manual, |
2e7d35d2 SG |
381 | &dev)); |
382 | ut_assert(dev); | |
383 | ||
384 | /* Bind two new devices (numbers 4 and 5) */ | |
4a467c6d | 385 | ut_assertok(device_bind_by_name(uts->root, false, &driver_info_manual, |
2e7d35d2 SG |
386 | &dev_penultimate)); |
387 | ut_assert(dev_penultimate); | |
4a467c6d | 388 | ut_assertok(device_bind_by_name(uts->root, false, &driver_info_manual, |
2e7d35d2 SG |
389 | &dev_last)); |
390 | ut_assert(dev_last); | |
391 | ||
392 | /* Now remove device 3 */ | |
706865af | 393 | ut_assertok(device_remove(dev, DM_REMOVE_NORMAL)); |
2e7d35d2 SG |
394 | ut_assertok(device_unbind(dev)); |
395 | ||
396 | /* The device numbering should have shifted down one */ | |
397 | ut_assertok(uclass_find_device(UCLASS_TEST, 3, &test_dev)); | |
398 | ut_assert(dev_penultimate == test_dev); | |
399 | ut_assertok(uclass_find_device(UCLASS_TEST, 4, &test_dev)); | |
400 | ut_assert(dev_last == test_dev); | |
401 | ||
402 | /* Add back the original device 3, now in position 5 */ | |
4a467c6d | 403 | ut_assertok(device_bind_by_name(uts->root, false, &driver_info_manual, |
00606d7e | 404 | &dev)); |
2e7d35d2 SG |
405 | ut_assert(dev); |
406 | ||
407 | /* Try ping */ | |
408 | ut_assertok(test_ping(dev, 100, &pingret)); | |
409 | ut_assert(pingret == 102); | |
410 | ||
411 | /* Remove 3 and 4 */ | |
706865af | 412 | ut_assertok(device_remove(dev_penultimate, DM_REMOVE_NORMAL)); |
2e7d35d2 | 413 | ut_assertok(device_unbind(dev_penultimate)); |
706865af | 414 | ut_assertok(device_remove(dev_last, DM_REMOVE_NORMAL)); |
2e7d35d2 SG |
415 | ut_assertok(device_unbind(dev_last)); |
416 | ||
417 | /* Our device should now be in position 3 */ | |
418 | ut_assertok(uclass_find_device(UCLASS_TEST, 3, &test_dev)); | |
419 | ut_assert(dev == test_dev); | |
420 | ||
421 | /* Now remove device 3 */ | |
706865af | 422 | ut_assertok(device_remove(dev, DM_REMOVE_NORMAL)); |
2e7d35d2 SG |
423 | ut_assertok(device_unbind(dev)); |
424 | ||
425 | return 0; | |
426 | } | |
e180c2b1 | 427 | DM_TEST(dm_test_ordering, UT_TESTF_SCAN_PDATA); |
2e7d35d2 SG |
428 | |
429 | /* Check that we can perform operations on a device (do a ping) */ | |
e721b882 | 430 | int dm_check_operations(struct unit_test_state *uts, struct udevice *dev, |
2e7d35d2 SG |
431 | uint32_t base, struct dm_test_priv *priv) |
432 | { | |
433 | int expected; | |
434 | int pingret; | |
435 | ||
caa4daa2 | 436 | /* Getting the child device should allocate plat / priv */ |
2e7d35d2 | 437 | ut_assertok(testfdt_ping(dev, 10, &pingret)); |
0fd3d911 SG |
438 | ut_assert(dev_get_priv(dev)); |
439 | ut_assert(dev_get_plat(dev)); | |
2e7d35d2 SG |
440 | |
441 | expected = 10 + base; | |
442 | ut_asserteq(expected, pingret); | |
443 | ||
444 | /* Do another ping */ | |
445 | ut_assertok(testfdt_ping(dev, 20, &pingret)); | |
446 | expected = 20 + base; | |
447 | ut_asserteq(expected, pingret); | |
448 | ||
449 | /* Now check the ping_total */ | |
0fd3d911 | 450 | priv = dev_get_priv(dev); |
2e7d35d2 SG |
451 | ut_asserteq(DM_TEST_START_TOTAL + 10 + 20 + base * 2, |
452 | priv->ping_total); | |
453 | ||
454 | return 0; | |
455 | } | |
456 | ||
457 | /* Check that we can perform operations on devices */ | |
e721b882 | 458 | static int dm_test_operations(struct unit_test_state *uts) |
2e7d35d2 | 459 | { |
54c5d08a | 460 | struct udevice *dev; |
2e7d35d2 SG |
461 | int i; |
462 | ||
463 | /* | |
464 | * Now check that the ping adds are what we expect. This is using the | |
465 | * ping-add property in each node. | |
466 | */ | |
467 | for (i = 0; i < ARRAY_SIZE(test_pdata); i++) { | |
468 | uint32_t base; | |
469 | ||
470 | ut_assertok(uclass_get_device(UCLASS_TEST, i, &dev)); | |
471 | ||
472 | /* | |
473 | * Get the 'reg' property, which tells us what the ping add | |
caa4daa2 | 474 | * should be. We don't use the plat because we want |
2e7d35d2 SG |
475 | * to test the code that sets that up (testfdt_drv_probe()). |
476 | */ | |
477 | base = test_pdata[i].ping_add; | |
478 | debug("dev=%d, base=%d\n", i, base); | |
479 | ||
0fd3d911 | 480 | ut_assert(!dm_check_operations(uts, dev, base, dev_get_priv(dev))); |
2e7d35d2 SG |
481 | } |
482 | ||
483 | return 0; | |
484 | } | |
e180c2b1 | 485 | DM_TEST(dm_test_operations, UT_TESTF_SCAN_PDATA); |
2e7d35d2 SG |
486 | |
487 | /* Remove all drivers and check that things work */ | |
e721b882 | 488 | static int dm_test_remove(struct unit_test_state *uts) |
2e7d35d2 | 489 | { |
54c5d08a | 490 | struct udevice *dev; |
2e7d35d2 SG |
491 | int i; |
492 | ||
493 | for (i = 0; i < 3; i++) { | |
494 | ut_assertok(uclass_find_device(UCLASS_TEST, i, &dev)); | |
495 | ut_assert(dev); | |
73466df3 | 496 | ut_assertf(dev_get_flags(dev) & DM_FLAG_ACTIVATED, |
2e7d35d2 | 497 | "Driver %d/%s not activated", i, dev->name); |
706865af | 498 | ut_assertok(device_remove(dev, DM_REMOVE_NORMAL)); |
73466df3 | 499 | ut_assertf(!(dev_get_flags(dev) & DM_FLAG_ACTIVATED), |
2e7d35d2 SG |
500 | "Driver %d/%s should have deactivated", i, |
501 | dev->name); | |
0fd3d911 | 502 | ut_assert(!dev_get_priv(dev)); |
2e7d35d2 SG |
503 | } |
504 | ||
505 | return 0; | |
506 | } | |
e180c2b1 | 507 | DM_TEST(dm_test_remove, UT_TESTF_SCAN_PDATA | UT_TESTF_PROBE_TEST); |
2e7d35d2 SG |
508 | |
509 | /* Remove and recreate everything, check for memory leaks */ | |
e721b882 | 510 | static int dm_test_leak(struct unit_test_state *uts) |
2e7d35d2 SG |
511 | { |
512 | int i; | |
513 | ||
514 | for (i = 0; i < 2; i++) { | |
54c5d08a | 515 | struct udevice *dev; |
2e7d35d2 SG |
516 | int ret; |
517 | int id; | |
518 | ||
e721b882 | 519 | dm_leak_check_start(uts); |
2e7d35d2 | 520 | |
8a8d24bd | 521 | ut_assertok(dm_scan_plat(false)); |
725e4fce | 522 | ut_assertok(dm_scan_fdt(false)); |
2e7d35d2 SG |
523 | |
524 | /* Scanning the uclass is enough to probe all the devices */ | |
525 | for (id = UCLASS_ROOT; id < UCLASS_COUNT; id++) { | |
526 | for (ret = uclass_first_device(UCLASS_TEST, &dev); | |
527 | dev; | |
528 | ret = uclass_next_device(&dev)) | |
529 | ; | |
530 | ut_assertok(ret); | |
531 | } | |
532 | ||
e721b882 | 533 | ut_assertok(dm_leak_check_end(uts)); |
2e7d35d2 SG |
534 | } |
535 | ||
536 | return 0; | |
537 | } | |
538 | DM_TEST(dm_test_leak, 0); | |
539 | ||
540 | /* Test uclass init/destroy methods */ | |
e721b882 | 541 | static int dm_test_uclass(struct unit_test_state *uts) |
2e7d35d2 | 542 | { |
6476c4d9 | 543 | int dev_count, uc_count; |
2e7d35d2 SG |
544 | struct uclass *uc; |
545 | ||
6476c4d9 SG |
546 | /* We should have just the root device and uclass */ |
547 | dm_get_stats(&dev_count, &uc_count); | |
548 | ut_asserteq(1, dev_count); | |
549 | ut_asserteq(1, uc_count); | |
550 | ||
2e7d35d2 SG |
551 | ut_assertok(uclass_get(UCLASS_TEST, &uc)); |
552 | ut_asserteq(1, dm_testdrv_op_count[DM_TEST_OP_INIT]); | |
553 | ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_DESTROY]); | |
0fd3d911 | 554 | ut_assert(uclass_get_priv(uc)); |
2e7d35d2 | 555 | |
6476c4d9 SG |
556 | dm_get_stats(&dev_count, &uc_count); |
557 | ut_asserteq(1, dev_count); | |
558 | ut_asserteq(2, uc_count); | |
559 | ||
2e7d35d2 SG |
560 | ut_assertok(uclass_destroy(uc)); |
561 | ut_asserteq(1, dm_testdrv_op_count[DM_TEST_OP_INIT]); | |
562 | ut_asserteq(1, dm_testdrv_op_count[DM_TEST_OP_DESTROY]); | |
563 | ||
6476c4d9 SG |
564 | dm_get_stats(&dev_count, &uc_count); |
565 | ut_asserteq(1, dev_count); | |
566 | ut_asserteq(1, uc_count); | |
567 | ||
2e7d35d2 SG |
568 | return 0; |
569 | } | |
570 | DM_TEST(dm_test_uclass, 0); | |
571 | ||
572 | /** | |
573 | * create_children() - Create children of a parent node | |
574 | * | |
575 | * @dms: Test system state | |
576 | * @parent: Parent device | |
577 | * @count: Number of children to create | |
578 | * @key: Key value to put in first child. Subsequence children | |
579 | * receive an incrementing value | |
580 | * @child: If not NULL, then the child device pointers are written into | |
581 | * this array. | |
582 | * @return 0 if OK, -ve on error | |
583 | */ | |
e721b882 | 584 | static int create_children(struct unit_test_state *uts, struct udevice *parent, |
54c5d08a | 585 | int count, int key, struct udevice *child[]) |
2e7d35d2 | 586 | { |
54c5d08a | 587 | struct udevice *dev; |
2e7d35d2 SG |
588 | int i; |
589 | ||
590 | for (i = 0; i < count; i++) { | |
591 | struct dm_test_pdata *pdata; | |
592 | ||
00606d7e SG |
593 | ut_assertok(device_bind_by_name(parent, false, |
594 | &driver_info_manual, &dev)); | |
2e7d35d2 SG |
595 | pdata = calloc(1, sizeof(*pdata)); |
596 | pdata->ping_add = key + i; | |
0fd3d911 | 597 | dev_set_plat(dev, pdata); |
2e7d35d2 SG |
598 | if (child) |
599 | child[i] = dev; | |
600 | } | |
601 | ||
602 | return 0; | |
603 | } | |
604 | ||
605 | #define NODE_COUNT 10 | |
606 | ||
e721b882 | 607 | static int dm_test_children(struct unit_test_state *uts) |
2e7d35d2 | 608 | { |
54c5d08a HS |
609 | struct udevice *top[NODE_COUNT]; |
610 | struct udevice *child[NODE_COUNT]; | |
611 | struct udevice *grandchild[NODE_COUNT]; | |
612 | struct udevice *dev; | |
2e7d35d2 SG |
613 | int total; |
614 | int ret; | |
615 | int i; | |
616 | ||
617 | /* We don't care about the numbering for this test */ | |
4a467c6d | 618 | uts->skip_post_probe = 1; |
2e7d35d2 SG |
619 | |
620 | ut_assert(NODE_COUNT > 5); | |
621 | ||
622 | /* First create 10 top-level children */ | |
4a467c6d | 623 | ut_assertok(create_children(uts, uts->root, NODE_COUNT, 0, top)); |
2e7d35d2 SG |
624 | |
625 | /* Now a few have their own children */ | |
e721b882 JH |
626 | ut_assertok(create_children(uts, top[2], NODE_COUNT, 2, NULL)); |
627 | ut_assertok(create_children(uts, top[5], NODE_COUNT, 5, child)); | |
2e7d35d2 SG |
628 | |
629 | /* And grandchildren */ | |
630 | for (i = 0; i < NODE_COUNT; i++) | |
e721b882 | 631 | ut_assertok(create_children(uts, child[i], NODE_COUNT, 50 * i, |
2e7d35d2 SG |
632 | i == 2 ? grandchild : NULL)); |
633 | ||
634 | /* Check total number of devices */ | |
635 | total = NODE_COUNT * (3 + NODE_COUNT); | |
636 | ut_asserteq(total, dm_testdrv_op_count[DM_TEST_OP_BIND]); | |
637 | ||
638 | /* Try probing one of the grandchildren */ | |
639 | ut_assertok(uclass_get_device(UCLASS_TEST, | |
640 | NODE_COUNT * 3 + 2 * NODE_COUNT, &dev)); | |
641 | ut_asserteq_ptr(grandchild[0], dev); | |
642 | ||
643 | /* | |
644 | * This should have probed the child and top node also, for a total | |
645 | * of 3 nodes. | |
646 | */ | |
647 | ut_asserteq(3, dm_testdrv_op_count[DM_TEST_OP_PROBE]); | |
648 | ||
649 | /* Probe the other grandchildren */ | |
650 | for (i = 1; i < NODE_COUNT; i++) | |
651 | ut_assertok(device_probe(grandchild[i])); | |
652 | ||
653 | ut_asserteq(2 + NODE_COUNT, dm_testdrv_op_count[DM_TEST_OP_PROBE]); | |
654 | ||
655 | /* Probe everything */ | |
656 | for (ret = uclass_first_device(UCLASS_TEST, &dev); | |
657 | dev; | |
658 | ret = uclass_next_device(&dev)) | |
659 | ; | |
660 | ut_assertok(ret); | |
661 | ||
662 | ut_asserteq(total, dm_testdrv_op_count[DM_TEST_OP_PROBE]); | |
663 | ||
664 | /* Remove a top-level child and check that the children are removed */ | |
706865af | 665 | ut_assertok(device_remove(top[2], DM_REMOVE_NORMAL)); |
2e7d35d2 SG |
666 | ut_asserteq(NODE_COUNT + 1, dm_testdrv_op_count[DM_TEST_OP_REMOVE]); |
667 | dm_testdrv_op_count[DM_TEST_OP_REMOVE] = 0; | |
668 | ||
669 | /* Try one with grandchildren */ | |
670 | ut_assertok(uclass_get_device(UCLASS_TEST, 5, &dev)); | |
671 | ut_asserteq_ptr(dev, top[5]); | |
706865af | 672 | ut_assertok(device_remove(dev, DM_REMOVE_NORMAL)); |
2e7d35d2 SG |
673 | ut_asserteq(1 + NODE_COUNT * (1 + NODE_COUNT), |
674 | dm_testdrv_op_count[DM_TEST_OP_REMOVE]); | |
675 | ||
676 | /* Try the same with unbind */ | |
677 | ut_assertok(device_unbind(top[2])); | |
678 | ut_asserteq(NODE_COUNT + 1, dm_testdrv_op_count[DM_TEST_OP_UNBIND]); | |
679 | dm_testdrv_op_count[DM_TEST_OP_UNBIND] = 0; | |
680 | ||
681 | /* Try one with grandchildren */ | |
682 | ut_assertok(uclass_get_device(UCLASS_TEST, 5, &dev)); | |
683 | ut_asserteq_ptr(dev, top[6]); | |
684 | ut_assertok(device_unbind(top[5])); | |
685 | ut_asserteq(1 + NODE_COUNT * (1 + NODE_COUNT), | |
686 | dm_testdrv_op_count[DM_TEST_OP_UNBIND]); | |
687 | ||
688 | return 0; | |
689 | } | |
690 | DM_TEST(dm_test_children, 0); | |
00606d7e | 691 | |
cfecbaf4 CB |
692 | static int dm_test_device_reparent(struct unit_test_state *uts) |
693 | { | |
cfecbaf4 CB |
694 | struct udevice *top[NODE_COUNT]; |
695 | struct udevice *child[NODE_COUNT]; | |
696 | struct udevice *grandchild[NODE_COUNT]; | |
697 | struct udevice *dev; | |
698 | int total; | |
699 | int ret; | |
700 | int i; | |
701 | ||
702 | /* We don't care about the numbering for this test */ | |
4a467c6d | 703 | uts->skip_post_probe = 1; |
cfecbaf4 CB |
704 | |
705 | ut_assert(NODE_COUNT > 5); | |
706 | ||
707 | /* First create 10 top-level children */ | |
4a467c6d | 708 | ut_assertok(create_children(uts, uts->root, NODE_COUNT, 0, top)); |
cfecbaf4 CB |
709 | |
710 | /* Now a few have their own children */ | |
711 | ut_assertok(create_children(uts, top[2], NODE_COUNT, 2, NULL)); | |
712 | ut_assertok(create_children(uts, top[5], NODE_COUNT, 5, child)); | |
713 | ||
714 | /* And grandchildren */ | |
715 | for (i = 0; i < NODE_COUNT; i++) | |
716 | ut_assertok(create_children(uts, child[i], NODE_COUNT, 50 * i, | |
717 | i == 2 ? grandchild : NULL)); | |
718 | ||
719 | /* Check total number of devices */ | |
720 | total = NODE_COUNT * (3 + NODE_COUNT); | |
721 | ut_asserteq(total, dm_testdrv_op_count[DM_TEST_OP_BIND]); | |
722 | ||
723 | /* Probe everything */ | |
724 | for (i = 0; i < total; i++) | |
725 | ut_assertok(uclass_get_device(UCLASS_TEST, i, &dev)); | |
726 | ||
727 | /* Re-parent top-level children with no grandchildren. */ | |
728 | ut_assertok(device_reparent(top[3], top[0])); | |
729 | /* try to get devices */ | |
730 | for (ret = uclass_find_first_device(UCLASS_TEST, &dev); | |
731 | dev; | |
732 | ret = uclass_find_next_device(&dev)) { | |
733 | ut_assert(!ret); | |
734 | ut_assertnonnull(dev); | |
735 | } | |
736 | ||
737 | ut_assertok(device_reparent(top[4], top[0])); | |
738 | /* try to get devices */ | |
739 | for (ret = uclass_find_first_device(UCLASS_TEST, &dev); | |
740 | dev; | |
741 | ret = uclass_find_next_device(&dev)) { | |
742 | ut_assert(!ret); | |
743 | ut_assertnonnull(dev); | |
744 | } | |
745 | ||
746 | /* Re-parent top-level children with grandchildren. */ | |
747 | ut_assertok(device_reparent(top[2], top[0])); | |
748 | /* try to get devices */ | |
749 | for (ret = uclass_find_first_device(UCLASS_TEST, &dev); | |
750 | dev; | |
751 | ret = uclass_find_next_device(&dev)) { | |
752 | ut_assert(!ret); | |
753 | ut_assertnonnull(dev); | |
754 | } | |
755 | ||
756 | ut_assertok(device_reparent(top[5], top[2])); | |
757 | /* try to get devices */ | |
758 | for (ret = uclass_find_first_device(UCLASS_TEST, &dev); | |
759 | dev; | |
760 | ret = uclass_find_next_device(&dev)) { | |
761 | ut_assert(!ret); | |
762 | ut_assertnonnull(dev); | |
763 | } | |
764 | ||
765 | /* Re-parent grandchildren. */ | |
766 | ut_assertok(device_reparent(grandchild[0], top[1])); | |
767 | /* try to get devices */ | |
768 | for (ret = uclass_find_first_device(UCLASS_TEST, &dev); | |
769 | dev; | |
770 | ret = uclass_find_next_device(&dev)) { | |
771 | ut_assert(!ret); | |
772 | ut_assertnonnull(dev); | |
773 | } | |
774 | ||
775 | ut_assertok(device_reparent(grandchild[1], top[1])); | |
776 | /* try to get devices */ | |
777 | for (ret = uclass_find_first_device(UCLASS_TEST, &dev); | |
778 | dev; | |
779 | ret = uclass_find_next_device(&dev)) { | |
780 | ut_assert(!ret); | |
781 | ut_assertnonnull(dev); | |
782 | } | |
783 | ||
784 | /* Remove re-pareneted devices. */ | |
785 | ut_assertok(device_remove(top[3], DM_REMOVE_NORMAL)); | |
786 | /* try to get devices */ | |
787 | for (ret = uclass_find_first_device(UCLASS_TEST, &dev); | |
788 | dev; | |
789 | ret = uclass_find_next_device(&dev)) { | |
790 | ut_assert(!ret); | |
791 | ut_assertnonnull(dev); | |
792 | } | |
793 | ||
794 | ut_assertok(device_remove(top[4], DM_REMOVE_NORMAL)); | |
795 | /* try to get devices */ | |
796 | for (ret = uclass_find_first_device(UCLASS_TEST, &dev); | |
797 | dev; | |
798 | ret = uclass_find_next_device(&dev)) { | |
799 | ut_assert(!ret); | |
800 | ut_assertnonnull(dev); | |
801 | } | |
802 | ||
803 | ut_assertok(device_remove(top[5], DM_REMOVE_NORMAL)); | |
804 | /* try to get devices */ | |
805 | for (ret = uclass_find_first_device(UCLASS_TEST, &dev); | |
806 | dev; | |
807 | ret = uclass_find_next_device(&dev)) { | |
808 | ut_assert(!ret); | |
809 | ut_assertnonnull(dev); | |
810 | } | |
811 | ||
812 | ut_assertok(device_remove(top[2], DM_REMOVE_NORMAL)); | |
813 | for (ret = uclass_find_first_device(UCLASS_TEST, &dev); | |
814 | dev; | |
815 | ret = uclass_find_next_device(&dev)) { | |
816 | ut_assert(!ret); | |
817 | ut_assertnonnull(dev); | |
818 | } | |
819 | ||
820 | ut_assertok(device_remove(grandchild[0], DM_REMOVE_NORMAL)); | |
821 | /* try to get devices */ | |
822 | for (ret = uclass_find_first_device(UCLASS_TEST, &dev); | |
823 | dev; | |
824 | ret = uclass_find_next_device(&dev)) { | |
825 | ut_assert(!ret); | |
826 | ut_assertnonnull(dev); | |
827 | } | |
828 | ||
829 | ut_assertok(device_remove(grandchild[1], DM_REMOVE_NORMAL)); | |
830 | /* try to get devices */ | |
831 | for (ret = uclass_find_first_device(UCLASS_TEST, &dev); | |
832 | dev; | |
833 | ret = uclass_find_next_device(&dev)) { | |
834 | ut_assert(!ret); | |
835 | ut_assertnonnull(dev); | |
836 | } | |
837 | ||
838 | /* Try the same with unbind */ | |
839 | ut_assertok(device_unbind(top[3])); | |
840 | ut_assertok(device_unbind(top[4])); | |
841 | ut_assertok(device_unbind(top[5])); | |
842 | ut_assertok(device_unbind(top[2])); | |
843 | ||
844 | ut_assertok(device_unbind(grandchild[0])); | |
845 | ut_assertok(device_unbind(grandchild[1])); | |
846 | ||
847 | return 0; | |
848 | } | |
849 | DM_TEST(dm_test_device_reparent, 0); | |
850 | ||
00606d7e | 851 | /* Test that pre-relocation devices work as expected */ |
e721b882 | 852 | static int dm_test_pre_reloc(struct unit_test_state *uts) |
00606d7e SG |
853 | { |
854 | struct udevice *dev; | |
855 | ||
856 | /* The normal driver should refuse to bind before relocation */ | |
4a467c6d | 857 | ut_asserteq(-EPERM, device_bind_by_name(uts->root, true, |
00606d7e SG |
858 | &driver_info_manual, &dev)); |
859 | ||
860 | /* But this one is marked pre-reloc */ | |
4a467c6d | 861 | ut_assertok(device_bind_by_name(uts->root, true, |
00606d7e SG |
862 | &driver_info_pre_reloc, &dev)); |
863 | ||
864 | return 0; | |
865 | } | |
866 | DM_TEST(dm_test_pre_reloc, 0); | |
c910e2e2 | 867 | |
24f927c5 SR |
868 | /* |
869 | * Test that removal of devices, either via the "normal" device_remove() | |
870 | * API or via the device driver selective flag works as expected | |
871 | */ | |
872 | static int dm_test_remove_active_dma(struct unit_test_state *uts) | |
873 | { | |
24f927c5 SR |
874 | struct udevice *dev; |
875 | ||
4a467c6d | 876 | ut_assertok(device_bind_by_name(uts->root, false, &driver_info_act_dma, |
24f927c5 SR |
877 | &dev)); |
878 | ut_assert(dev); | |
879 | ||
880 | /* Probe the device */ | |
881 | ut_assertok(device_probe(dev)); | |
882 | ||
883 | /* Test if device is active right now */ | |
884 | ut_asserteq(true, device_active(dev)); | |
885 | ||
886 | /* Remove the device via selective remove flag */ | |
887 | dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL); | |
888 | ||
889 | /* Test if device is inactive right now */ | |
890 | ut_asserteq(false, device_active(dev)); | |
891 | ||
892 | /* Probe the device again */ | |
893 | ut_assertok(device_probe(dev)); | |
894 | ||
895 | /* Test if device is active right now */ | |
896 | ut_asserteq(true, device_active(dev)); | |
897 | ||
898 | /* Remove the device via "normal" remove API */ | |
899 | ut_assertok(device_remove(dev, DM_REMOVE_NORMAL)); | |
900 | ||
901 | /* Test if device is inactive right now */ | |
902 | ut_asserteq(false, device_active(dev)); | |
903 | ||
904 | /* | |
905 | * Test if a device without the active DMA flags is not removed upon | |
906 | * the active DMA remove call | |
907 | */ | |
908 | ut_assertok(device_unbind(dev)); | |
4a467c6d | 909 | ut_assertok(device_bind_by_name(uts->root, false, &driver_info_manual, |
24f927c5 SR |
910 | &dev)); |
911 | ut_assert(dev); | |
912 | ||
913 | /* Probe the device */ | |
914 | ut_assertok(device_probe(dev)); | |
915 | ||
916 | /* Test if device is active right now */ | |
917 | ut_asserteq(true, device_active(dev)); | |
918 | ||
919 | /* Remove the device via selective remove flag */ | |
920 | dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL); | |
921 | ||
922 | /* Test if device is still active right now */ | |
923 | ut_asserteq(true, device_active(dev)); | |
924 | ||
925 | return 0; | |
926 | } | |
927 | DM_TEST(dm_test_remove_active_dma, 0); | |
928 | ||
cc6f4c8f MV |
929 | /* Test removal of 'vital' devices */ |
930 | static int dm_test_remove_vital(struct unit_test_state *uts) | |
931 | { | |
cc6f4c8f MV |
932 | struct udevice *normal, *dma, *vital, *dma_vital; |
933 | ||
934 | /* Skip the behaviour in test_post_probe() */ | |
4a467c6d | 935 | uts->skip_post_probe = 1; |
cc6f4c8f | 936 | |
4a467c6d | 937 | ut_assertok(device_bind_by_name(uts->root, false, &driver_info_manual, |
cc6f4c8f MV |
938 | &normal)); |
939 | ut_assertnonnull(normal); | |
940 | ||
4a467c6d | 941 | ut_assertok(device_bind_by_name(uts->root, false, &driver_info_act_dma, |
cc6f4c8f MV |
942 | &dma)); |
943 | ut_assertnonnull(dma); | |
944 | ||
4a467c6d | 945 | ut_assertok(device_bind_by_name(uts->root, false, |
cc6f4c8f MV |
946 | &driver_info_vital_clk, &vital)); |
947 | ut_assertnonnull(vital); | |
948 | ||
4a467c6d | 949 | ut_assertok(device_bind_by_name(uts->root, false, |
cc6f4c8f MV |
950 | &driver_info_act_dma_vital_clk, |
951 | &dma_vital)); | |
952 | ut_assertnonnull(dma_vital); | |
953 | ||
954 | /* Probe the devices */ | |
955 | ut_assertok(device_probe(normal)); | |
956 | ut_assertok(device_probe(dma)); | |
957 | ut_assertok(device_probe(vital)); | |
958 | ut_assertok(device_probe(dma_vital)); | |
959 | ||
960 | /* Check that devices are active right now */ | |
961 | ut_asserteq(true, device_active(normal)); | |
962 | ut_asserteq(true, device_active(dma)); | |
963 | ut_asserteq(true, device_active(vital)); | |
964 | ut_asserteq(true, device_active(dma_vital)); | |
965 | ||
966 | /* Remove active devices via selective remove flag */ | |
967 | dm_remove_devices_flags(DM_REMOVE_NON_VITAL | DM_REMOVE_ACTIVE_ALL); | |
968 | ||
969 | /* | |
970 | * Check that this only has an effect on the dma device, since two | |
971 | * devices are vital and the third does not have active DMA | |
972 | */ | |
973 | ut_asserteq(true, device_active(normal)); | |
974 | ut_asserteq(false, device_active(dma)); | |
975 | ut_asserteq(true, device_active(vital)); | |
976 | ut_asserteq(true, device_active(dma_vital)); | |
977 | ||
978 | /* Remove active devices via selective remove flag */ | |
979 | ut_assertok(device_probe(dma)); | |
980 | dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL); | |
981 | ||
982 | /* This should have affected both active-dma devices */ | |
983 | ut_asserteq(true, device_active(normal)); | |
984 | ut_asserteq(false, device_active(dma)); | |
985 | ut_asserteq(true, device_active(vital)); | |
986 | ut_asserteq(false, device_active(dma_vital)); | |
987 | ||
988 | /* Remove non-vital devices */ | |
989 | ut_assertok(device_probe(dma)); | |
990 | ut_assertok(device_probe(dma_vital)); | |
991 | dm_remove_devices_flags(DM_REMOVE_NON_VITAL); | |
992 | ||
993 | /* This should have affected only non-vital devices */ | |
994 | ut_asserteq(false, device_active(normal)); | |
995 | ut_asserteq(false, device_active(dma)); | |
996 | ut_asserteq(true, device_active(vital)); | |
997 | ut_asserteq(true, device_active(dma_vital)); | |
998 | ||
999 | /* Remove vital devices via normal remove flag */ | |
1000 | ut_assertok(device_probe(normal)); | |
1001 | ut_assertok(device_probe(dma)); | |
1002 | dm_remove_devices_flags(DM_REMOVE_NORMAL); | |
1003 | ||
1004 | /* Check that all devices are inactive right now */ | |
1005 | ut_asserteq(false, device_active(normal)); | |
1006 | ut_asserteq(false, device_active(dma)); | |
1007 | ut_asserteq(false, device_active(vital)); | |
1008 | ut_asserteq(false, device_active(dma_vital)); | |
1009 | ||
1010 | return 0; | |
1011 | } | |
1012 | DM_TEST(dm_test_remove_vital, 0); | |
1013 | ||
e721b882 | 1014 | static int dm_test_uclass_before_ready(struct unit_test_state *uts) |
c910e2e2 SG |
1015 | { |
1016 | struct uclass *uc; | |
1017 | ||
1018 | ut_assertok(uclass_get(UCLASS_TEST, &uc)); | |
1019 | ||
f9fd4558 SG |
1020 | gd->dm_root = NULL; |
1021 | gd->dm_root_f = NULL; | |
1022 | memset(&gd->uclass_root, '\0', sizeof(gd->uclass_root)); | |
1023 | ||
c910e2e2 | 1024 | ut_asserteq_ptr(NULL, uclass_find(UCLASS_TEST)); |
1e9ced28 | 1025 | ut_asserteq(-EDEADLK, uclass_get(UCLASS_TEST, &uc)); |
c910e2e2 SG |
1026 | |
1027 | return 0; | |
1028 | } | |
c910e2e2 | 1029 | DM_TEST(dm_test_uclass_before_ready, 0); |
b3670531 | 1030 | |
e721b882 | 1031 | static int dm_test_uclass_devices_find(struct unit_test_state *uts) |
9e85f13d PM |
1032 | { |
1033 | struct udevice *dev; | |
1034 | int ret; | |
1035 | ||
1036 | for (ret = uclass_find_first_device(UCLASS_TEST, &dev); | |
1037 | dev; | |
1038 | ret = uclass_find_next_device(&dev)) { | |
1039 | ut_assert(!ret); | |
331caeaf | 1040 | ut_assertnonnull(dev); |
9e85f13d PM |
1041 | } |
1042 | ||
4805a7af | 1043 | ut_assertok(uclass_find_first_device(UCLASS_TEST_DUMMY, &dev)); |
331caeaf | 1044 | ut_assertnull(dev); |
f3885649 | 1045 | |
9e85f13d PM |
1046 | return 0; |
1047 | } | |
e180c2b1 | 1048 | DM_TEST(dm_test_uclass_devices_find, UT_TESTF_SCAN_PDATA); |
9e85f13d | 1049 | |
e721b882 | 1050 | static int dm_test_uclass_devices_find_by_name(struct unit_test_state *uts) |
6e0c4880 PM |
1051 | { |
1052 | struct udevice *finddev; | |
1053 | struct udevice *testdev; | |
1054 | int findret, ret; | |
1055 | ||
1056 | /* | |
1057 | * For each test device found in fdt like: "a-test", "b-test", etc., | |
1058 | * use its name and try to find it by uclass_find_device_by_name(). | |
1059 | * Then, on success check if: | |
1060 | * - current 'testdev' name is equal to the returned 'finddev' name | |
1061 | * - current 'testdev' pointer is equal to the returned 'finddev' | |
1062 | * | |
1063 | * We assume that, each uclass's device name is unique, so if not, then | |
1064 | * this will fail on checking condition: testdev == finddev, since the | |
1065 | * uclass_find_device_by_name(), returns the first device by given name. | |
1066 | */ | |
1067 | for (ret = uclass_find_first_device(UCLASS_TEST_FDT, &testdev); | |
1068 | testdev; | |
1069 | ret = uclass_find_next_device(&testdev)) { | |
1070 | ut_assertok(ret); | |
331caeaf | 1071 | ut_assertnonnull(testdev); |
6e0c4880 PM |
1072 | |
1073 | findret = uclass_find_device_by_name(UCLASS_TEST_FDT, | |
1074 | testdev->name, | |
1075 | &finddev); | |
1076 | ||
1077 | ut_assertok(findret); | |
1078 | ut_assert(testdev); | |
1079 | ut_asserteq_str(testdev->name, finddev->name); | |
1080 | ut_asserteq_ptr(testdev, finddev); | |
1081 | } | |
1082 | ||
1083 | return 0; | |
1084 | } | |
e180c2b1 | 1085 | DM_TEST(dm_test_uclass_devices_find_by_name, UT_TESTF_SCAN_FDT); |
6e0c4880 | 1086 | |
e721b882 | 1087 | static int dm_test_uclass_devices_get(struct unit_test_state *uts) |
9e85f13d PM |
1088 | { |
1089 | struct udevice *dev; | |
1090 | int ret; | |
1091 | ||
1092 | for (ret = uclass_first_device(UCLASS_TEST, &dev); | |
1093 | dev; | |
1094 | ret = uclass_next_device(&dev)) { | |
1095 | ut_assert(!ret); | |
1096 | ut_assert(dev); | |
1097 | ut_assert(device_active(dev)); | |
1098 | } | |
1099 | ||
1100 | return 0; | |
1101 | } | |
e180c2b1 | 1102 | DM_TEST(dm_test_uclass_devices_get, UT_TESTF_SCAN_PDATA); |
9e85f13d | 1103 | |
e721b882 | 1104 | static int dm_test_uclass_devices_get_by_name(struct unit_test_state *uts) |
6e0c4880 PM |
1105 | { |
1106 | struct udevice *finddev; | |
1107 | struct udevice *testdev; | |
1108 | int ret, findret; | |
1109 | ||
1110 | /* | |
1111 | * For each test device found in fdt like: "a-test", "b-test", etc., | |
1112 | * use its name and try to get it by uclass_get_device_by_name(). | |
1113 | * On success check if: | |
1114 | * - returned finddev' is active | |
1115 | * - current 'testdev' name is equal to the returned 'finddev' name | |
1116 | * - current 'testdev' pointer is equal to the returned 'finddev' | |
1117 | * | |
1118 | * We asserts that the 'testdev' is active on each loop entry, so we | |
1119 | * could be sure that the 'finddev' is activated too, but for sure | |
1120 | * we check it again. | |
1121 | * | |
1122 | * We assume that, each uclass's device name is unique, so if not, then | |
1123 | * this will fail on checking condition: testdev == finddev, since the | |
1124 | * uclass_get_device_by_name(), returns the first device by given name. | |
1125 | */ | |
1126 | for (ret = uclass_first_device(UCLASS_TEST_FDT, &testdev); | |
1127 | testdev; | |
1128 | ret = uclass_next_device(&testdev)) { | |
1129 | ut_assertok(ret); | |
1130 | ut_assert(testdev); | |
1131 | ut_assert(device_active(testdev)); | |
1132 | ||
1133 | findret = uclass_get_device_by_name(UCLASS_TEST_FDT, | |
1134 | testdev->name, | |
1135 | &finddev); | |
1136 | ||
1137 | ut_assertok(findret); | |
1138 | ut_assert(finddev); | |
1139 | ut_assert(device_active(finddev)); | |
1140 | ut_asserteq_str(testdev->name, finddev->name); | |
1141 | ut_asserteq_ptr(testdev, finddev); | |
1142 | } | |
1143 | ||
1144 | return 0; | |
1145 | } | |
e180c2b1 | 1146 | DM_TEST(dm_test_uclass_devices_get_by_name, UT_TESTF_SCAN_FDT); |
6e0c4880 | 1147 | |
e721b882 | 1148 | static int dm_test_device_get_uclass_id(struct unit_test_state *uts) |
b3670531 SG |
1149 | { |
1150 | struct udevice *dev; | |
1151 | ||
1152 | ut_assertok(uclass_get_device(UCLASS_TEST, 0, &dev)); | |
1153 | ut_asserteq(UCLASS_TEST, device_get_uclass_id(dev)); | |
1154 | ||
1155 | return 0; | |
1156 | } | |
e180c2b1 | 1157 | DM_TEST(dm_test_device_get_uclass_id, UT_TESTF_SCAN_PDATA); |
6e43d1b1 SG |
1158 | |
1159 | static int dm_test_uclass_names(struct unit_test_state *uts) | |
1160 | { | |
1161 | ut_asserteq_str("test", uclass_get_name(UCLASS_TEST)); | |
1162 | ut_asserteq(UCLASS_TEST, uclass_get_by_name("test")); | |
1163 | ||
1164 | return 0; | |
1165 | } | |
e180c2b1 | 1166 | DM_TEST(dm_test_uclass_names, UT_TESTF_SCAN_PDATA); |
cdb6aa0a SG |
1167 | |
1168 | static int dm_test_inactive_child(struct unit_test_state *uts) | |
1169 | { | |
cdb6aa0a SG |
1170 | struct udevice *parent, *dev1, *dev2; |
1171 | ||
1172 | /* Skip the behaviour in test_post_probe() */ | |
4a467c6d | 1173 | uts->skip_post_probe = 1; |
cdb6aa0a SG |
1174 | |
1175 | ut_assertok(uclass_first_device_err(UCLASS_TEST, &parent)); | |
1176 | ||
1177 | /* | |
1178 | * Create a child but do not activate it. Calling the function again | |
1179 | * should return the same child. | |
1180 | */ | |
1181 | ut_asserteq(-ENODEV, device_find_first_inactive_child(parent, | |
1182 | UCLASS_TEST, &dev1)); | |
65e25bea | 1183 | ut_assertok(device_bind(parent, DM_DRIVER_GET(test_drv), |
734206dd | 1184 | "test_child", 0, ofnode_null(), &dev1)); |
cdb6aa0a SG |
1185 | |
1186 | ut_assertok(device_find_first_inactive_child(parent, UCLASS_TEST, | |
1187 | &dev2)); | |
1188 | ut_asserteq_ptr(dev1, dev2); | |
1189 | ||
1190 | ut_assertok(device_probe(dev1)); | |
1191 | ut_asserteq(-ENODEV, device_find_first_inactive_child(parent, | |
1192 | UCLASS_TEST, &dev2)); | |
1193 | ||
1194 | return 0; | |
1195 | } | |
e180c2b1 | 1196 | DM_TEST(dm_test_inactive_child, UT_TESTF_SCAN_PDATA); |
1c55b229 SG |
1197 | |
1198 | /* Make sure all bound devices have a sequence number */ | |
1199 | static int dm_test_all_have_seq(struct unit_test_state *uts) | |
1200 | { | |
1201 | struct udevice *dev; | |
1202 | struct uclass *uc; | |
1203 | ||
8a715530 | 1204 | list_for_each_entry(uc, gd->uclass_root, sibling_node) { |
1c55b229 | 1205 | list_for_each_entry(dev, &uc->dev_head, uclass_node) { |
2462139f | 1206 | if (dev->seq_ == -1) |
1c55b229 | 1207 | printf("Device '%s' has no seq (%d)\n", |
2462139f SG |
1208 | dev->name, dev->seq_); |
1209 | ut_assert(dev->seq_ != -1); | |
1c55b229 SG |
1210 | } |
1211 | } | |
1212 | ||
1213 | return 0; | |
1214 | } | |
1215 | DM_TEST(dm_test_all_have_seq, UT_TESTF_SCAN_PDATA); | |
e8801876 | 1216 | |
bf8188e4 | 1217 | #if CONFIG_IS_ENABLED(DM_DMA) |
e8801876 NSJ |
1218 | static int dm_test_dma_offset(struct unit_test_state *uts) |
1219 | { | |
1220 | struct udevice *dev; | |
1221 | ofnode node; | |
1222 | ||
1223 | /* Make sure the bus's dma-ranges aren't taken into account here */ | |
1224 | node = ofnode_path("/mmio-bus@0"); | |
1225 | ut_assert(ofnode_valid(node)); | |
1226 | ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_BUS, node, &dev)); | |
1227 | ut_asserteq_64(0, dev->dma_offset); | |
1228 | ||
1229 | /* Device behind a bus with dma-ranges */ | |
1230 | node = ofnode_path("/mmio-bus@0/subnode@0"); | |
1231 | ut_assert(ofnode_valid(node)); | |
1232 | ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_FDT, node, &dev)); | |
1233 | ut_asserteq_64(-0x10000000ULL, dev->dma_offset); | |
1234 | ||
1235 | /* This one has no dma-ranges */ | |
1236 | node = ofnode_path("/mmio-bus@1"); | |
1237 | ut_assert(ofnode_valid(node)); | |
1238 | ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_BUS, node, &dev)); | |
1239 | node = ofnode_path("/mmio-bus@1/subnode@0"); | |
1240 | ut_assert(ofnode_valid(node)); | |
1241 | ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_FDT, node, &dev)); | |
1242 | ut_asserteq_64(0, dev->dma_offset); | |
1243 | ||
1244 | return 0; | |
1245 | } | |
1246 | DM_TEST(dm_test_dma_offset, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); | |
bf8188e4 | 1247 | #endif |
6476c4d9 SG |
1248 | |
1249 | /* Test dm_get_stats() */ | |
1250 | static int dm_test_get_stats(struct unit_test_state *uts) | |
1251 | { | |
1252 | int dev_count, uc_count; | |
1253 | ||
1254 | dm_get_stats(&dev_count, &uc_count); | |
1255 | ut_assert(dev_count > 50); | |
1256 | ut_assert(uc_count > 30); | |
1257 | ||
1258 | return 0; | |
1259 | } | |
1260 | DM_TEST(dm_test_get_stats, UT_TESTF_SCAN_FDT); |