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