]>
Commit | Line | Data |
---|---|---|
2e7d35d2 SG |
1 | /* |
2 | * Tests for the core driver model code | |
3 | * | |
4 | * Copyright (c) 2013 Google, Inc | |
5 | * | |
6 | * SPDX-License-Identifier: GPL-2.0+ | |
7 | */ | |
8 | ||
9 | #include <common.h> | |
10 | #include <errno.h> | |
11 | #include <dm.h> | |
12 | #include <fdtdec.h> | |
13 | #include <malloc.h> | |
14 | #include <dm/device-internal.h> | |
15 | #include <dm/root.h> | |
16 | #include <dm/ut.h> | |
17 | #include <dm/util.h> | |
18 | #include <dm/test.h> | |
19 | #include <dm/uclass-internal.h> | |
20 | ||
21 | DECLARE_GLOBAL_DATA_PTR; | |
22 | ||
23 | enum { | |
24 | TEST_INTVAL1 = 0, | |
25 | TEST_INTVAL2 = 3, | |
26 | TEST_INTVAL3 = 6, | |
27 | TEST_INTVAL_MANUAL = 101112, | |
00606d7e | 28 | TEST_INTVAL_PRE_RELOC = 7, |
2e7d35d2 SG |
29 | }; |
30 | ||
31 | static const struct dm_test_pdata test_pdata[] = { | |
32 | { .ping_add = TEST_INTVAL1, }, | |
33 | { .ping_add = TEST_INTVAL2, }, | |
34 | { .ping_add = TEST_INTVAL3, }, | |
35 | }; | |
36 | ||
37 | static const struct dm_test_pdata test_pdata_manual = { | |
38 | .ping_add = TEST_INTVAL_MANUAL, | |
39 | }; | |
40 | ||
00606d7e SG |
41 | static const struct dm_test_pdata test_pdata_pre_reloc = { |
42 | .ping_add = TEST_INTVAL_PRE_RELOC, | |
43 | }; | |
44 | ||
2e7d35d2 SG |
45 | U_BOOT_DEVICE(dm_test_info1) = { |
46 | .name = "test_drv", | |
47 | .platdata = &test_pdata[0], | |
48 | }; | |
49 | ||
50 | U_BOOT_DEVICE(dm_test_info2) = { | |
51 | .name = "test_drv", | |
52 | .platdata = &test_pdata[1], | |
53 | }; | |
54 | ||
55 | U_BOOT_DEVICE(dm_test_info3) = { | |
56 | .name = "test_drv", | |
57 | .platdata = &test_pdata[2], | |
58 | }; | |
59 | ||
60 | static struct driver_info driver_info_manual = { | |
61 | .name = "test_manual_drv", | |
62 | .platdata = &test_pdata_manual, | |
63 | }; | |
64 | ||
00606d7e SG |
65 | static struct driver_info driver_info_pre_reloc = { |
66 | .name = "test_pre_reloc_drv", | |
67 | .platdata = &test_pdata_manual, | |
68 | }; | |
69 | ||
756ac0bb SG |
70 | void dm_leak_check_start(struct dm_test_state *dms) |
71 | { | |
72 | dms->start = mallinfo(); | |
73 | if (!dms->start.uordblks) | |
74 | puts("Warning: Please add '#define DEBUG' to the top of common/dlmalloc.c\n"); | |
75 | } | |
76 | ||
77 | int dm_leak_check_end(struct dm_test_state *dms) | |
78 | { | |
79 | struct mallinfo end; | |
80 | int id; | |
81 | ||
82 | /* Don't delete the root class, since we started with that */ | |
83 | for (id = UCLASS_ROOT + 1; id < UCLASS_COUNT; id++) { | |
84 | struct uclass *uc; | |
85 | ||
86 | uc = uclass_find(id); | |
87 | if (!uc) | |
88 | continue; | |
89 | ut_assertok(uclass_destroy(uc)); | |
90 | } | |
91 | ||
92 | end = mallinfo(); | |
93 | ut_asserteq(dms->start.uordblks, end.uordblks); | |
94 | ||
95 | return 0; | |
96 | } | |
97 | ||
2e7d35d2 SG |
98 | /* Test that binding with platdata occurs correctly */ |
99 | static int dm_test_autobind(struct dm_test_state *dms) | |
100 | { | |
54c5d08a | 101 | struct udevice *dev; |
2e7d35d2 SG |
102 | |
103 | /* | |
104 | * We should have a single class (UCLASS_ROOT) and a single root | |
105 | * device with no children. | |
106 | */ | |
107 | ut_assert(dms->root); | |
108 | ut_asserteq(1, list_count_items(&gd->uclass_root)); | |
109 | ut_asserteq(0, list_count_items(&gd->dm_root->child_head)); | |
110 | ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_POST_BIND]); | |
111 | ||
00606d7e | 112 | ut_assertok(dm_scan_platdata(false)); |
2e7d35d2 SG |
113 | |
114 | /* We should have our test class now at least, plus more children */ | |
115 | ut_assert(1 < list_count_items(&gd->uclass_root)); | |
116 | ut_assert(0 < list_count_items(&gd->dm_root->child_head)); | |
117 | ||
118 | /* Our 3 dm_test_infox children should be bound to the test uclass */ | |
119 | ut_asserteq(3, dm_testdrv_op_count[DM_TEST_OP_POST_BIND]); | |
120 | ||
121 | /* No devices should be probed */ | |
122 | list_for_each_entry(dev, &gd->dm_root->child_head, sibling_node) | |
123 | ut_assert(!(dev->flags & DM_FLAG_ACTIVATED)); | |
124 | ||
125 | /* Our test driver should have been bound 3 times */ | |
126 | ut_assert(dm_testdrv_op_count[DM_TEST_OP_BIND] == 3); | |
127 | ||
128 | return 0; | |
129 | } | |
130 | DM_TEST(dm_test_autobind, 0); | |
131 | ||
132 | /* Test that autoprobe finds all the expected devices */ | |
133 | static int dm_test_autoprobe(struct dm_test_state *dms) | |
134 | { | |
135 | int expected_base_add; | |
54c5d08a | 136 | struct udevice *dev; |
2e7d35d2 SG |
137 | struct uclass *uc; |
138 | int i; | |
139 | ||
140 | ut_assertok(uclass_get(UCLASS_TEST, &uc)); | |
141 | ut_assert(uc); | |
142 | ||
143 | ut_asserteq(1, dm_testdrv_op_count[DM_TEST_OP_INIT]); | |
144 | ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_POST_PROBE]); | |
145 | ||
146 | /* The root device should not be activated until needed */ | |
7497812d | 147 | ut_assert(dms->root->flags & DM_FLAG_ACTIVATED); |
2e7d35d2 SG |
148 | |
149 | /* | |
150 | * We should be able to find the three test devices, and they should | |
151 | * all be activated as they are used (lazy activation, required by | |
152 | * U-Boot) | |
153 | */ | |
154 | for (i = 0; i < 3; i++) { | |
155 | ut_assertok(uclass_find_device(UCLASS_TEST, i, &dev)); | |
156 | ut_assert(dev); | |
157 | ut_assertf(!(dev->flags & DM_FLAG_ACTIVATED), | |
158 | "Driver %d/%s already activated", i, dev->name); | |
159 | ||
160 | /* This should activate it */ | |
161 | ut_assertok(uclass_get_device(UCLASS_TEST, i, &dev)); | |
162 | ut_assert(dev); | |
163 | ut_assert(dev->flags & DM_FLAG_ACTIVATED); | |
164 | ||
165 | /* Activating a device should activate the root device */ | |
166 | if (!i) | |
167 | ut_assert(dms->root->flags & DM_FLAG_ACTIVATED); | |
168 | } | |
169 | ||
170 | /* Our 3 dm_test_infox children should be passed to post_probe */ | |
171 | ut_asserteq(3, dm_testdrv_op_count[DM_TEST_OP_POST_PROBE]); | |
172 | ||
173 | /* Also we can check the per-device data */ | |
174 | expected_base_add = 0; | |
175 | for (i = 0; i < 3; i++) { | |
176 | struct dm_test_uclass_perdev_priv *priv; | |
177 | struct dm_test_pdata *pdata; | |
178 | ||
179 | ut_assertok(uclass_find_device(UCLASS_TEST, i, &dev)); | |
180 | ut_assert(dev); | |
181 | ||
182 | priv = dev->uclass_priv; | |
183 | ut_assert(priv); | |
184 | ut_asserteq(expected_base_add, priv->base_add); | |
185 | ||
186 | pdata = dev->platdata; | |
187 | expected_base_add += pdata->ping_add; | |
188 | } | |
189 | ||
190 | return 0; | |
191 | } | |
192 | DM_TEST(dm_test_autoprobe, DM_TESTF_SCAN_PDATA); | |
193 | ||
194 | /* Check that we see the correct platdata in each device */ | |
195 | static int dm_test_platdata(struct dm_test_state *dms) | |
196 | { | |
197 | const struct dm_test_pdata *pdata; | |
54c5d08a | 198 | struct udevice *dev; |
2e7d35d2 SG |
199 | int i; |
200 | ||
201 | for (i = 0; i < 3; i++) { | |
202 | ut_assertok(uclass_find_device(UCLASS_TEST, i, &dev)); | |
203 | ut_assert(dev); | |
204 | pdata = dev->platdata; | |
205 | ut_assert(pdata->ping_add == test_pdata[i].ping_add); | |
206 | } | |
207 | ||
208 | return 0; | |
209 | } | |
210 | DM_TEST(dm_test_platdata, DM_TESTF_SCAN_PDATA); | |
211 | ||
212 | /* Test that we can bind, probe, remove, unbind a driver */ | |
213 | static int dm_test_lifecycle(struct dm_test_state *dms) | |
214 | { | |
215 | int op_count[DM_TEST_OP_COUNT]; | |
54c5d08a | 216 | struct udevice *dev, *test_dev; |
2e7d35d2 SG |
217 | int pingret; |
218 | int ret; | |
219 | ||
220 | memcpy(op_count, dm_testdrv_op_count, sizeof(op_count)); | |
221 | ||
00606d7e | 222 | ut_assertok(device_bind_by_name(dms->root, false, &driver_info_manual, |
2e7d35d2 SG |
223 | &dev)); |
224 | ut_assert(dev); | |
225 | ut_assert(dm_testdrv_op_count[DM_TEST_OP_BIND] | |
226 | == op_count[DM_TEST_OP_BIND] + 1); | |
227 | ut_assert(!dev->priv); | |
228 | ||
229 | /* Probe the device - it should fail allocating private data */ | |
230 | dms->force_fail_alloc = 1; | |
231 | ret = device_probe(dev); | |
232 | ut_assert(ret == -ENOMEM); | |
233 | ut_assert(dm_testdrv_op_count[DM_TEST_OP_PROBE] | |
234 | == op_count[DM_TEST_OP_PROBE] + 1); | |
235 | ut_assert(!dev->priv); | |
236 | ||
237 | /* Try again without the alloc failure */ | |
238 | dms->force_fail_alloc = 0; | |
239 | ut_assertok(device_probe(dev)); | |
240 | ut_assert(dm_testdrv_op_count[DM_TEST_OP_PROBE] | |
241 | == op_count[DM_TEST_OP_PROBE] + 2); | |
242 | ut_assert(dev->priv); | |
243 | ||
244 | /* This should be device 3 in the uclass */ | |
245 | ut_assertok(uclass_find_device(UCLASS_TEST, 3, &test_dev)); | |
246 | ut_assert(dev == test_dev); | |
247 | ||
248 | /* Try ping */ | |
249 | ut_assertok(test_ping(dev, 100, &pingret)); | |
250 | ut_assert(pingret == 102); | |
251 | ||
252 | /* Now remove device 3 */ | |
253 | ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_PRE_REMOVE]); | |
254 | ut_assertok(device_remove(dev)); | |
255 | ut_asserteq(1, dm_testdrv_op_count[DM_TEST_OP_PRE_REMOVE]); | |
256 | ||
257 | ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_UNBIND]); | |
258 | ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_PRE_UNBIND]); | |
259 | ut_assertok(device_unbind(dev)); | |
260 | ut_asserteq(1, dm_testdrv_op_count[DM_TEST_OP_UNBIND]); | |
261 | ut_asserteq(1, dm_testdrv_op_count[DM_TEST_OP_PRE_UNBIND]); | |
262 | ||
263 | return 0; | |
264 | } | |
265 | DM_TEST(dm_test_lifecycle, DM_TESTF_SCAN_PDATA | DM_TESTF_PROBE_TEST); | |
266 | ||
267 | /* Test that we can bind/unbind and the lists update correctly */ | |
268 | static int dm_test_ordering(struct dm_test_state *dms) | |
269 | { | |
54c5d08a | 270 | struct udevice *dev, *dev_penultimate, *dev_last, *test_dev; |
2e7d35d2 SG |
271 | int pingret; |
272 | ||
00606d7e | 273 | ut_assertok(device_bind_by_name(dms->root, false, &driver_info_manual, |
2e7d35d2 SG |
274 | &dev)); |
275 | ut_assert(dev); | |
276 | ||
277 | /* Bind two new devices (numbers 4 and 5) */ | |
00606d7e | 278 | ut_assertok(device_bind_by_name(dms->root, false, &driver_info_manual, |
2e7d35d2 SG |
279 | &dev_penultimate)); |
280 | ut_assert(dev_penultimate); | |
00606d7e | 281 | ut_assertok(device_bind_by_name(dms->root, false, &driver_info_manual, |
2e7d35d2 SG |
282 | &dev_last)); |
283 | ut_assert(dev_last); | |
284 | ||
285 | /* Now remove device 3 */ | |
286 | ut_assertok(device_remove(dev)); | |
287 | ut_assertok(device_unbind(dev)); | |
288 | ||
289 | /* The device numbering should have shifted down one */ | |
290 | ut_assertok(uclass_find_device(UCLASS_TEST, 3, &test_dev)); | |
291 | ut_assert(dev_penultimate == test_dev); | |
292 | ut_assertok(uclass_find_device(UCLASS_TEST, 4, &test_dev)); | |
293 | ut_assert(dev_last == test_dev); | |
294 | ||
295 | /* Add back the original device 3, now in position 5 */ | |
00606d7e SG |
296 | ut_assertok(device_bind_by_name(dms->root, false, &driver_info_manual, |
297 | &dev)); | |
2e7d35d2 SG |
298 | ut_assert(dev); |
299 | ||
300 | /* Try ping */ | |
301 | ut_assertok(test_ping(dev, 100, &pingret)); | |
302 | ut_assert(pingret == 102); | |
303 | ||
304 | /* Remove 3 and 4 */ | |
305 | ut_assertok(device_remove(dev_penultimate)); | |
306 | ut_assertok(device_unbind(dev_penultimate)); | |
307 | ut_assertok(device_remove(dev_last)); | |
308 | ut_assertok(device_unbind(dev_last)); | |
309 | ||
310 | /* Our device should now be in position 3 */ | |
311 | ut_assertok(uclass_find_device(UCLASS_TEST, 3, &test_dev)); | |
312 | ut_assert(dev == test_dev); | |
313 | ||
314 | /* Now remove device 3 */ | |
315 | ut_assertok(device_remove(dev)); | |
316 | ut_assertok(device_unbind(dev)); | |
317 | ||
318 | return 0; | |
319 | } | |
320 | DM_TEST(dm_test_ordering, DM_TESTF_SCAN_PDATA); | |
321 | ||
322 | /* Check that we can perform operations on a device (do a ping) */ | |
54c5d08a | 323 | int dm_check_operations(struct dm_test_state *dms, struct udevice *dev, |
2e7d35d2 SG |
324 | uint32_t base, struct dm_test_priv *priv) |
325 | { | |
326 | int expected; | |
327 | int pingret; | |
328 | ||
329 | /* Getting the child device should allocate platdata / priv */ | |
330 | ut_assertok(testfdt_ping(dev, 10, &pingret)); | |
331 | ut_assert(dev->priv); | |
332 | ut_assert(dev->platdata); | |
333 | ||
334 | expected = 10 + base; | |
335 | ut_asserteq(expected, pingret); | |
336 | ||
337 | /* Do another ping */ | |
338 | ut_assertok(testfdt_ping(dev, 20, &pingret)); | |
339 | expected = 20 + base; | |
340 | ut_asserteq(expected, pingret); | |
341 | ||
342 | /* Now check the ping_total */ | |
343 | priv = dev->priv; | |
344 | ut_asserteq(DM_TEST_START_TOTAL + 10 + 20 + base * 2, | |
345 | priv->ping_total); | |
346 | ||
347 | return 0; | |
348 | } | |
349 | ||
350 | /* Check that we can perform operations on devices */ | |
351 | static int dm_test_operations(struct dm_test_state *dms) | |
352 | { | |
54c5d08a | 353 | struct udevice *dev; |
2e7d35d2 SG |
354 | int i; |
355 | ||
356 | /* | |
357 | * Now check that the ping adds are what we expect. This is using the | |
358 | * ping-add property in each node. | |
359 | */ | |
360 | for (i = 0; i < ARRAY_SIZE(test_pdata); i++) { | |
361 | uint32_t base; | |
362 | ||
363 | ut_assertok(uclass_get_device(UCLASS_TEST, i, &dev)); | |
364 | ||
365 | /* | |
366 | * Get the 'reg' property, which tells us what the ping add | |
367 | * should be. We don't use the platdata because we want | |
368 | * to test the code that sets that up (testfdt_drv_probe()). | |
369 | */ | |
370 | base = test_pdata[i].ping_add; | |
371 | debug("dev=%d, base=%d\n", i, base); | |
372 | ||
373 | ut_assert(!dm_check_operations(dms, dev, base, dev->priv)); | |
374 | } | |
375 | ||
376 | return 0; | |
377 | } | |
378 | DM_TEST(dm_test_operations, DM_TESTF_SCAN_PDATA); | |
379 | ||
380 | /* Remove all drivers and check that things work */ | |
381 | static int dm_test_remove(struct dm_test_state *dms) | |
382 | { | |
54c5d08a | 383 | struct udevice *dev; |
2e7d35d2 SG |
384 | int i; |
385 | ||
386 | for (i = 0; i < 3; i++) { | |
387 | ut_assertok(uclass_find_device(UCLASS_TEST, i, &dev)); | |
388 | ut_assert(dev); | |
389 | ut_assertf(dev->flags & DM_FLAG_ACTIVATED, | |
390 | "Driver %d/%s not activated", i, dev->name); | |
391 | ut_assertok(device_remove(dev)); | |
392 | ut_assertf(!(dev->flags & DM_FLAG_ACTIVATED), | |
393 | "Driver %d/%s should have deactivated", i, | |
394 | dev->name); | |
395 | ut_assert(!dev->priv); | |
396 | } | |
397 | ||
398 | return 0; | |
399 | } | |
400 | DM_TEST(dm_test_remove, DM_TESTF_SCAN_PDATA | DM_TESTF_PROBE_TEST); | |
401 | ||
402 | /* Remove and recreate everything, check for memory leaks */ | |
403 | static int dm_test_leak(struct dm_test_state *dms) | |
404 | { | |
405 | int i; | |
406 | ||
407 | for (i = 0; i < 2; i++) { | |
54c5d08a | 408 | struct udevice *dev; |
2e7d35d2 SG |
409 | int ret; |
410 | int id; | |
411 | ||
756ac0bb | 412 | dm_leak_check_start(dms); |
2e7d35d2 | 413 | |
00606d7e SG |
414 | ut_assertok(dm_scan_platdata(false)); |
415 | ut_assertok(dm_scan_fdt(gd->fdt_blob, false)); | |
2e7d35d2 SG |
416 | |
417 | /* Scanning the uclass is enough to probe all the devices */ | |
418 | for (id = UCLASS_ROOT; id < UCLASS_COUNT; id++) { | |
419 | for (ret = uclass_first_device(UCLASS_TEST, &dev); | |
420 | dev; | |
421 | ret = uclass_next_device(&dev)) | |
422 | ; | |
423 | ut_assertok(ret); | |
424 | } | |
425 | ||
756ac0bb | 426 | ut_assertok(dm_leak_check_end(dms)); |
2e7d35d2 SG |
427 | } |
428 | ||
429 | return 0; | |
430 | } | |
431 | DM_TEST(dm_test_leak, 0); | |
432 | ||
433 | /* Test uclass init/destroy methods */ | |
434 | static int dm_test_uclass(struct dm_test_state *dms) | |
435 | { | |
436 | struct uclass *uc; | |
437 | ||
438 | ut_assertok(uclass_get(UCLASS_TEST, &uc)); | |
439 | ut_asserteq(1, dm_testdrv_op_count[DM_TEST_OP_INIT]); | |
440 | ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_DESTROY]); | |
441 | ut_assert(uc->priv); | |
442 | ||
443 | ut_assertok(uclass_destroy(uc)); | |
444 | ut_asserteq(1, dm_testdrv_op_count[DM_TEST_OP_INIT]); | |
445 | ut_asserteq(1, dm_testdrv_op_count[DM_TEST_OP_DESTROY]); | |
446 | ||
447 | return 0; | |
448 | } | |
449 | DM_TEST(dm_test_uclass, 0); | |
450 | ||
451 | /** | |
452 | * create_children() - Create children of a parent node | |
453 | * | |
454 | * @dms: Test system state | |
455 | * @parent: Parent device | |
456 | * @count: Number of children to create | |
457 | * @key: Key value to put in first child. Subsequence children | |
458 | * receive an incrementing value | |
459 | * @child: If not NULL, then the child device pointers are written into | |
460 | * this array. | |
461 | * @return 0 if OK, -ve on error | |
462 | */ | |
54c5d08a HS |
463 | static int create_children(struct dm_test_state *dms, struct udevice *parent, |
464 | int count, int key, struct udevice *child[]) | |
2e7d35d2 | 465 | { |
54c5d08a | 466 | struct udevice *dev; |
2e7d35d2 SG |
467 | int i; |
468 | ||
469 | for (i = 0; i < count; i++) { | |
470 | struct dm_test_pdata *pdata; | |
471 | ||
00606d7e SG |
472 | ut_assertok(device_bind_by_name(parent, false, |
473 | &driver_info_manual, &dev)); | |
2e7d35d2 SG |
474 | pdata = calloc(1, sizeof(*pdata)); |
475 | pdata->ping_add = key + i; | |
476 | dev->platdata = pdata; | |
477 | if (child) | |
478 | child[i] = dev; | |
479 | } | |
480 | ||
481 | return 0; | |
482 | } | |
483 | ||
484 | #define NODE_COUNT 10 | |
485 | ||
486 | static int dm_test_children(struct dm_test_state *dms) | |
487 | { | |
54c5d08a HS |
488 | struct udevice *top[NODE_COUNT]; |
489 | struct udevice *child[NODE_COUNT]; | |
490 | struct udevice *grandchild[NODE_COUNT]; | |
491 | struct udevice *dev; | |
2e7d35d2 SG |
492 | int total; |
493 | int ret; | |
494 | int i; | |
495 | ||
496 | /* We don't care about the numbering for this test */ | |
497 | dms->skip_post_probe = 1; | |
498 | ||
499 | ut_assert(NODE_COUNT > 5); | |
500 | ||
501 | /* First create 10 top-level children */ | |
502 | ut_assertok(create_children(dms, dms->root, NODE_COUNT, 0, top)); | |
503 | ||
504 | /* Now a few have their own children */ | |
505 | ut_assertok(create_children(dms, top[2], NODE_COUNT, 2, NULL)); | |
506 | ut_assertok(create_children(dms, top[5], NODE_COUNT, 5, child)); | |
507 | ||
508 | /* And grandchildren */ | |
509 | for (i = 0; i < NODE_COUNT; i++) | |
510 | ut_assertok(create_children(dms, child[i], NODE_COUNT, 50 * i, | |
511 | i == 2 ? grandchild : NULL)); | |
512 | ||
513 | /* Check total number of devices */ | |
514 | total = NODE_COUNT * (3 + NODE_COUNT); | |
515 | ut_asserteq(total, dm_testdrv_op_count[DM_TEST_OP_BIND]); | |
516 | ||
517 | /* Try probing one of the grandchildren */ | |
518 | ut_assertok(uclass_get_device(UCLASS_TEST, | |
519 | NODE_COUNT * 3 + 2 * NODE_COUNT, &dev)); | |
520 | ut_asserteq_ptr(grandchild[0], dev); | |
521 | ||
522 | /* | |
523 | * This should have probed the child and top node also, for a total | |
524 | * of 3 nodes. | |
525 | */ | |
526 | ut_asserteq(3, dm_testdrv_op_count[DM_TEST_OP_PROBE]); | |
527 | ||
528 | /* Probe the other grandchildren */ | |
529 | for (i = 1; i < NODE_COUNT; i++) | |
530 | ut_assertok(device_probe(grandchild[i])); | |
531 | ||
532 | ut_asserteq(2 + NODE_COUNT, dm_testdrv_op_count[DM_TEST_OP_PROBE]); | |
533 | ||
534 | /* Probe everything */ | |
535 | for (ret = uclass_first_device(UCLASS_TEST, &dev); | |
536 | dev; | |
537 | ret = uclass_next_device(&dev)) | |
538 | ; | |
539 | ut_assertok(ret); | |
540 | ||
541 | ut_asserteq(total, dm_testdrv_op_count[DM_TEST_OP_PROBE]); | |
542 | ||
543 | /* Remove a top-level child and check that the children are removed */ | |
544 | ut_assertok(device_remove(top[2])); | |
545 | ut_asserteq(NODE_COUNT + 1, dm_testdrv_op_count[DM_TEST_OP_REMOVE]); | |
546 | dm_testdrv_op_count[DM_TEST_OP_REMOVE] = 0; | |
547 | ||
548 | /* Try one with grandchildren */ | |
549 | ut_assertok(uclass_get_device(UCLASS_TEST, 5, &dev)); | |
550 | ut_asserteq_ptr(dev, top[5]); | |
551 | ut_assertok(device_remove(dev)); | |
552 | ut_asserteq(1 + NODE_COUNT * (1 + NODE_COUNT), | |
553 | dm_testdrv_op_count[DM_TEST_OP_REMOVE]); | |
554 | ||
555 | /* Try the same with unbind */ | |
556 | ut_assertok(device_unbind(top[2])); | |
557 | ut_asserteq(NODE_COUNT + 1, dm_testdrv_op_count[DM_TEST_OP_UNBIND]); | |
558 | dm_testdrv_op_count[DM_TEST_OP_UNBIND] = 0; | |
559 | ||
560 | /* Try one with grandchildren */ | |
561 | ut_assertok(uclass_get_device(UCLASS_TEST, 5, &dev)); | |
562 | ut_asserteq_ptr(dev, top[6]); | |
563 | ut_assertok(device_unbind(top[5])); | |
564 | ut_asserteq(1 + NODE_COUNT * (1 + NODE_COUNT), | |
565 | dm_testdrv_op_count[DM_TEST_OP_UNBIND]); | |
566 | ||
567 | return 0; | |
568 | } | |
569 | DM_TEST(dm_test_children, 0); | |
00606d7e SG |
570 | |
571 | /* Test that pre-relocation devices work as expected */ | |
572 | static int dm_test_pre_reloc(struct dm_test_state *dms) | |
573 | { | |
574 | struct udevice *dev; | |
575 | ||
576 | /* The normal driver should refuse to bind before relocation */ | |
577 | ut_asserteq(-EPERM, device_bind_by_name(dms->root, true, | |
578 | &driver_info_manual, &dev)); | |
579 | ||
580 | /* But this one is marked pre-reloc */ | |
581 | ut_assertok(device_bind_by_name(dms->root, true, | |
582 | &driver_info_pre_reloc, &dev)); | |
583 | ||
584 | return 0; | |
585 | } | |
586 | DM_TEST(dm_test_pre_reloc, 0); | |
c910e2e2 SG |
587 | |
588 | static int dm_test_uclass_before_ready(struct dm_test_state *dms) | |
589 | { | |
590 | struct uclass *uc; | |
591 | ||
592 | ut_assertok(uclass_get(UCLASS_TEST, &uc)); | |
593 | ||
594 | memset(gd, '\0', sizeof(*gd)); | |
595 | ut_asserteq_ptr(NULL, uclass_find(UCLASS_TEST)); | |
596 | ||
597 | return 0; | |
598 | } | |
599 | ||
600 | DM_TEST(dm_test_uclass_before_ready, 0); | |
b3670531 SG |
601 | |
602 | static int dm_test_device_get_uclass_id(struct dm_test_state *dms) | |
603 | { | |
604 | struct udevice *dev; | |
605 | ||
606 | ut_assertok(uclass_get_device(UCLASS_TEST, 0, &dev)); | |
607 | ut_asserteq(UCLASS_TEST, device_get_uclass_id(dev)); | |
608 | ||
609 | return 0; | |
610 | } | |
611 | DM_TEST(dm_test_device_get_uclass_id, DM_TESTF_SCAN_PDATA); |