]> git.ipfire.org Git - thirdparty/u-boot.git/blame - test/dm/bus.c
test: Remove <common.h> and add needed includes
[thirdparty/u-boot.git] / test / dm / bus.c
CommitLineData
83d290c5 1// SPDX-License-Identifier: GPL-2.0+
1ca7e206
SG
2/*
3 * Copyright (c) 2014 Google, Inc
1ca7e206
SG
4 */
5
9f8037ea 6#ifdef CONFIG_SANDBOX
f7ae49fc 7#include <log.h>
9f8037ea
SG
8#include <os.h>
9#endif
1ca7e206 10#include <dm.h>
401d1c4f 11#include <asm/global_data.h>
240b9320 12#include <dm/device.h>
e59f458d 13#include <dm/device-internal.h>
1ca7e206 14#include <dm/test.h>
cdc133bd 15#include <dm/uclass-internal.h>
1ca7e206 16#include <dm/util.h>
0e1fad43 17#include <test/test.h>
e721b882 18#include <test/ut.h>
1ca7e206
SG
19
20DECLARE_GLOBAL_DATA_PTR;
21
1ca7e206 22/* Test that we can probe for children */
e721b882 23static int dm_test_bus_children(struct unit_test_state *uts)
1ca7e206 24{
88e6a60e 25 int num_devices = 9;
1ca7e206
SG
26 struct udevice *bus;
27 struct uclass *uc;
28
29 ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc));
30 ut_asserteq(num_devices, list_count_items(&uc->dev_head));
31
32 /* Probe the bus, which should yield 3 more devices */
33 ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
34 num_devices += 3;
35
36 ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc));
37 ut_asserteq(num_devices, list_count_items(&uc->dev_head));
38
e721b882 39 ut_assert(!dm_check_devices(uts, num_devices));
1ca7e206
SG
40
41 return 0;
42}
e180c2b1 43DM_TEST(dm_test_bus_children, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
997c87bb
SG
44
45/* Test our functions for accessing children */
e721b882 46static int dm_test_bus_children_funcs(struct unit_test_state *uts)
997c87bb
SG
47{
48 const void *blob = gd->fdt_blob;
49 struct udevice *bus, *dev;
50 int node;
51
52 ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
53
54 /* device_get_child() */
55 ut_assertok(device_get_child(bus, 0, &dev));
56 ut_asserteq(-ENODEV, device_get_child(bus, 4, &dev));
57 ut_assertok(device_get_child_by_seq(bus, 5, &dev));
73466df3 58 ut_assert(dev_get_flags(dev) & DM_FLAG_ACTIVATED);
997c87bb
SG
59 ut_asserteq_str("c-test@5", dev->name);
60
61 /* Device with sequence number 0 should be accessible */
99175919
SG
62 ut_asserteq(-ENODEV, device_find_child_by_seq(bus, -1, &dev));
63 ut_assertok(device_find_child_by_seq(bus, 0, &dev));
73466df3 64 ut_assert(!(dev_get_flags(dev) & DM_FLAG_ACTIVATED));
99175919 65 ut_asserteq(0, device_find_child_by_seq(bus, 0, &dev));
997c87bb 66 ut_assertok(device_get_child_by_seq(bus, 0, &dev));
73466df3 67 ut_assert(dev_get_flags(dev) & DM_FLAG_ACTIVATED);
99175919 68 ut_asserteq(0, device_find_child_by_seq(bus, 0, &dev));
997c87bb
SG
69
70 /* There is no device with sequence number 2 */
99175919
SG
71 ut_asserteq(-ENODEV, device_find_child_by_seq(bus, 2, &dev));
72 ut_asserteq(-ENODEV, device_find_child_by_seq(bus, 2, &dev));
997c87bb
SG
73 ut_asserteq(-ENODEV, device_get_child_by_seq(bus, 2, &dev));
74
75 /* Looking for something that is not a child */
76 node = fdt_path_offset(blob, "/junk");
77 ut_asserteq(-ENODEV, device_find_child_by_of_offset(bus, node, &dev));
78 node = fdt_path_offset(blob, "/d-test");
79 ut_asserteq(-ENODEV, device_find_child_by_of_offset(bus, node, &dev));
80
298afb52
SG
81 return 0;
82}
e180c2b1 83DM_TEST(dm_test_bus_children_funcs, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
298afb52
SG
84
85static int dm_test_bus_children_of_offset(struct unit_test_state *uts)
86{
87 const void *blob = gd->fdt_blob;
88 struct udevice *bus, *dev;
89 int node;
90
91 ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
4f414d39 92 ut_assertnonnull(bus);
298afb52 93
997c87bb
SG
94 /* Find a valid child */
95 node = fdt_path_offset(blob, "/some-bus/c-test@1");
298afb52 96 ut_assert(node > 0);
997c87bb 97 ut_assertok(device_find_child_by_of_offset(bus, node, &dev));
4f414d39 98 ut_assertnonnull(dev);
73466df3 99 ut_assert(!(dev_get_flags(dev) & DM_FLAG_ACTIVATED));
997c87bb 100 ut_assertok(device_get_child_by_of_offset(bus, node, &dev));
4f414d39 101 ut_assertnonnull(dev);
73466df3 102 ut_assert(dev_get_flags(dev) & DM_FLAG_ACTIVATED);
997c87bb
SG
103
104 return 0;
105}
298afb52 106DM_TEST(dm_test_bus_children_of_offset,
e180c2b1 107 UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT | UT_TESTF_FLAT_TREE);
e59f458d 108
a8981d4f 109/* Test that we can iterate through children */
e721b882 110static int dm_test_bus_children_iterators(struct unit_test_state *uts)
a8981d4f
SG
111{
112 struct udevice *bus, *dev, *child;
113
114 /* Walk through the children one by one */
115 ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
116 ut_assertok(device_find_first_child(bus, &dev));
117 ut_asserteq_str("c-test@5", dev->name);
118 ut_assertok(device_find_next_child(&dev));
119 ut_asserteq_str("c-test@0", dev->name);
120 ut_assertok(device_find_next_child(&dev));
121 ut_asserteq_str("c-test@1", dev->name);
122 ut_assertok(device_find_next_child(&dev));
123 ut_asserteq_ptr(dev, NULL);
124
125 /* Move to the next child without using device_find_first_child() */
99175919 126 ut_assertok(device_find_child_by_seq(bus, 5, &dev));
a8981d4f
SG
127 ut_asserteq_str("c-test@5", dev->name);
128 ut_assertok(device_find_next_child(&dev));
129 ut_asserteq_str("c-test@0", dev->name);
130
131 /* Try a device with no children */
132 ut_assertok(device_find_first_child(dev, &child));
133 ut_asserteq_ptr(child, NULL);
134
135 return 0;
136}
137DM_TEST(dm_test_bus_children_iterators,
e180c2b1 138 UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
a8981d4f 139
e59f458d 140/* Test that the bus can store data about each child */
e721b882 141static int test_bus_parent_data(struct unit_test_state *uts)
e59f458d
SG
142{
143 struct dm_test_parent_data *parent_data;
144 struct udevice *bus, *dev;
145 struct uclass *uc;
146 int value;
147
148 ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
149
150 /* Check that parent data is allocated */
99175919 151 ut_assertok(device_find_child_by_seq(bus, 0, &dev));
bcbe3d15 152 ut_asserteq_ptr(NULL, dev_get_parent_priv(dev));
e59f458d 153 ut_assertok(device_get_child_by_seq(bus, 0, &dev));
bcbe3d15 154 parent_data = dev_get_parent_priv(dev);
e59f458d
SG
155 ut_assert(NULL != parent_data);
156
157 /* Check that it starts at 0 and goes away when device is removed */
158 parent_data->sum += 5;
159 ut_asserteq(5, parent_data->sum);
706865af 160 device_remove(dev, DM_REMOVE_NORMAL);
bcbe3d15 161 ut_asserteq_ptr(NULL, dev_get_parent_priv(dev));
e59f458d
SG
162
163 /* Check that we can do this twice */
164 ut_assertok(device_get_child_by_seq(bus, 0, &dev));
bcbe3d15 165 parent_data = dev_get_parent_priv(dev);
e59f458d
SG
166 ut_assert(NULL != parent_data);
167 parent_data->sum += 5;
168 ut_asserteq(5, parent_data->sum);
169
170 /* Add parent data to all children */
171 ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc));
172 value = 5;
173 uclass_foreach_dev(dev, uc) {
174 /* Ignore these if they are not on this bus */
175 if (dev->parent != bus) {
bcbe3d15 176 ut_asserteq_ptr(NULL, dev_get_parent_priv(dev));
e59f458d
SG
177 continue;
178 }
179 ut_assertok(device_probe(dev));
bcbe3d15 180 parent_data = dev_get_parent_priv(dev);
e59f458d
SG
181
182 parent_data->sum = value;
183 value += 5;
184 }
185
186 /* Check it is still there */
187 value = 5;
188 uclass_foreach_dev(dev, uc) {
189 /* Ignore these if they are not on this bus */
190 if (dev->parent != bus)
191 continue;
bcbe3d15 192 parent_data = dev_get_parent_priv(dev);
e59f458d
SG
193
194 ut_asserteq(value, parent_data->sum);
195 value += 5;
196 }
197
198 return 0;
199}
dac8db2c 200/* Test that the bus can store data about each child */
e721b882 201static int dm_test_bus_parent_data(struct unit_test_state *uts)
dac8db2c 202{
e721b882 203 return test_bus_parent_data(uts);
dac8db2c 204}
e180c2b1 205DM_TEST(dm_test_bus_parent_data, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
a327dee0 206
dac8db2c 207/* As above but the size is controlled by the uclass */
e721b882 208static int dm_test_bus_parent_data_uclass(struct unit_test_state *uts)
dac8db2c 209{
e23eb614 210 struct driver *drv;
dac8db2c
SG
211 struct udevice *bus;
212 int size;
213 int ret;
214
215 /* Set the driver size to 0 so that the uclass size is used */
216 ut_assertok(uclass_find_device(UCLASS_TEST_BUS, 0, &bus));
e23eb614 217 drv = (struct driver *)bus->driver;
41575d8e 218 size = drv->per_child_auto;
9f8037ea
SG
219
220#ifdef CONFIG_SANDBOX
221 os_mprotect_allow(bus->uclass->uc_drv, sizeof(*bus->uclass->uc_drv));
222 os_mprotect_allow(drv, sizeof(*drv));
223#endif
41575d8e
SG
224 bus->uclass->uc_drv->per_child_auto = size;
225 drv->per_child_auto = 0;
e721b882 226 ret = test_bus_parent_data(uts);
dac8db2c
SG
227 if (ret)
228 return ret;
41575d8e
SG
229 bus->uclass->uc_drv->per_child_auto = 0;
230 drv->per_child_auto = size;
dac8db2c
SG
231
232 return 0;
233}
234DM_TEST(dm_test_bus_parent_data_uclass,
e180c2b1 235 UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
dac8db2c 236
a327dee0 237/* Test that the bus ops are called when a child is probed/removed */
e721b882 238static int dm_test_bus_parent_ops(struct unit_test_state *uts)
a327dee0
SG
239{
240 struct dm_test_parent_data *parent_data;
241 struct udevice *bus, *dev;
242 struct uclass *uc;
243
079ac595 244 testbus_get_clear_removed();
a327dee0
SG
245 ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
246 ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc));
247
248 uclass_foreach_dev(dev, uc) {
249 /* Ignore these if they are not on this bus */
250 if (dev->parent != bus)
251 continue;
bcbe3d15 252 ut_asserteq_ptr(NULL, dev_get_parent_priv(dev));
a327dee0
SG
253
254 ut_assertok(device_probe(dev));
bcbe3d15 255 parent_data = dev_get_parent_priv(dev);
079ac595 256 ut_asserteq(TEST_FLAG_CHILD_PROBED, parent_data->flag);
a327dee0
SG
257 }
258
259 uclass_foreach_dev(dev, uc) {
260 /* Ignore these if they are not on this bus */
261 if (dev->parent != bus)
262 continue;
bcbe3d15 263 parent_data = dev_get_parent_priv(dev);
079ac595 264 ut_asserteq(TEST_FLAG_CHILD_PROBED, parent_data->flag);
706865af 265 ut_assertok(device_remove(dev, DM_REMOVE_NORMAL));
bcbe3d15 266 ut_asserteq_ptr(NULL, dev_get_parent_priv(dev));
079ac595 267 ut_asserteq_ptr(testbus_get_clear_removed(), dev);
a327dee0 268 }
a327dee0
SG
269
270 return 0;
271}
e180c2b1 272DM_TEST(dm_test_bus_parent_ops, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
cdc133bd 273
caa4daa2 274static int test_bus_parent_plat(struct unit_test_state *uts)
cdc133bd 275{
caa4daa2 276 struct dm_test_parent_plat *plat;
cdc133bd 277 struct udevice *bus, *dev;
cdc133bd
SG
278
279 /* Check that the bus has no children */
280 ut_assertok(uclass_find_device(UCLASS_TEST_BUS, 0, &bus));
281 device_find_first_child(bus, &dev);
282 ut_asserteq_ptr(NULL, dev);
283
284 ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
285
240b9320 286 for (device_find_first_child(bus, &dev);
cdc133bd
SG
287 dev;
288 device_find_next_child(&dev)) {
289 /* Check that platform data is allocated */
caa4daa2 290 plat = dev_get_parent_plat(dev);
cdc133bd
SG
291 ut_assert(plat != NULL);
292
293 /*
294 * Check that it is not affected by the device being
295 * probed/removed
296 */
297 plat->count++;
298 ut_asserteq(1, plat->count);
299 device_probe(dev);
706865af 300 device_remove(dev, DM_REMOVE_NORMAL);
cdc133bd 301
caa4daa2 302 ut_asserteq_ptr(plat, dev_get_parent_plat(dev));
cdc133bd
SG
303 ut_asserteq(1, plat->count);
304 ut_assertok(device_probe(dev));
cdc133bd 305 }
240b9320 306 ut_asserteq(3, device_get_child_count(bus));
cdc133bd
SG
307
308 /* Removing the bus should also have no effect (it is still bound) */
706865af 309 device_remove(bus, DM_REMOVE_NORMAL);
240b9320 310 for (device_find_first_child(bus, &dev);
cdc133bd
SG
311 dev;
312 device_find_next_child(&dev)) {
313 /* Check that platform data is allocated */
caa4daa2 314 plat = dev_get_parent_plat(dev);
cdc133bd
SG
315 ut_assert(plat != NULL);
316 ut_asserteq(1, plat->count);
cdc133bd 317 }
240b9320 318 ut_asserteq(3, device_get_child_count(bus));
cdc133bd
SG
319
320 /* Unbind all the children */
321 do {
322 device_find_first_child(bus, &dev);
323 if (dev)
324 device_unbind(dev);
325 } while (dev);
326
caa4daa2 327 /* Now the child plat should be removed and re-added */
cdc133bd 328 device_probe(bus);
240b9320 329 for (device_find_first_child(bus, &dev);
cdc133bd
SG
330 dev;
331 device_find_next_child(&dev)) {
332 /* Check that platform data is allocated */
caa4daa2 333 plat = dev_get_parent_plat(dev);
cdc133bd
SG
334 ut_assert(plat != NULL);
335 ut_asserteq(0, plat->count);
cdc133bd 336 }
240b9320 337 ut_asserteq(3, device_get_child_count(bus));
cdc133bd
SG
338
339 return 0;
340}
ba8da9dc
SG
341
342/* Test that the bus can store platform data about each child */
caa4daa2 343static int dm_test_bus_parent_plat(struct unit_test_state *uts)
ba8da9dc 344{
caa4daa2 345 return test_bus_parent_plat(uts);
ba8da9dc 346}
caa4daa2 347DM_TEST(dm_test_bus_parent_plat, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
ba8da9dc
SG
348
349/* As above but the size is controlled by the uclass */
caa4daa2 350static int dm_test_bus_parent_plat_uclass(struct unit_test_state *uts)
ba8da9dc
SG
351{
352 struct udevice *bus;
e23eb614 353 struct driver *drv;
ba8da9dc
SG
354 int size;
355 int ret;
356
357 /* Set the driver size to 0 so that the uclass size is used */
358 ut_assertok(uclass_find_device(UCLASS_TEST_BUS, 0, &bus));
e23eb614 359 drv = (struct driver *)bus->driver;
caa4daa2 360 size = drv->per_child_plat_auto;
9f8037ea
SG
361#ifdef CONFIG_SANDBOX
362 os_mprotect_allow(bus->uclass->uc_drv, sizeof(*bus->uclass->uc_drv));
363 os_mprotect_allow(drv, sizeof(*drv));
364#endif
caa4daa2
SG
365 bus->uclass->uc_drv->per_child_plat_auto = size;
366 drv->per_child_plat_auto = 0;
367 ret = test_bus_parent_plat(uts);
ba8da9dc
SG
368 if (ret)
369 return ret;
caa4daa2
SG
370 bus->uclass->uc_drv->per_child_plat_auto = 0;
371 drv->per_child_plat_auto = size;
ba8da9dc
SG
372
373 return 0;
374}
caa4daa2 375DM_TEST(dm_test_bus_parent_plat_uclass,
e180c2b1 376 UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
0118ce79
SG
377
378/* Test that the child post_bind method is called */
e721b882 379static int dm_test_bus_child_post_bind(struct unit_test_state *uts)
0118ce79 380{
caa4daa2 381 struct dm_test_parent_plat *plat;
0118ce79 382 struct udevice *bus, *dev;
0118ce79
SG
383
384 ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
240b9320 385 for (device_find_first_child(bus, &dev);
0118ce79
SG
386 dev;
387 device_find_next_child(&dev)) {
388 /* Check that platform data is allocated */
caa4daa2 389 plat = dev_get_parent_plat(dev);
0118ce79
SG
390 ut_assert(plat != NULL);
391 ut_asserteq(1, plat->bind_flag);
0118ce79 392 }
240b9320 393 ut_asserteq(3, device_get_child_count(bus));
0118ce79
SG
394
395 return 0;
396}
e180c2b1 397DM_TEST(dm_test_bus_child_post_bind, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
081f2fcb
SG
398
399/* Test that the child post_bind method is called */
e721b882 400static int dm_test_bus_child_post_bind_uclass(struct unit_test_state *uts)
081f2fcb 401{
caa4daa2 402 struct dm_test_parent_plat *plat;
081f2fcb 403 struct udevice *bus, *dev;
081f2fcb
SG
404
405 ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
240b9320 406 for (device_find_first_child(bus, &dev);
081f2fcb
SG
407 dev;
408 device_find_next_child(&dev)) {
409 /* Check that platform data is allocated */
caa4daa2 410 plat = dev_get_parent_plat(dev);
081f2fcb
SG
411 ut_assert(plat != NULL);
412 ut_asserteq(2, plat->uclass_bind_flag);
081f2fcb 413 }
240b9320 414 ut_asserteq(3, device_get_child_count(bus));
081f2fcb
SG
415
416 return 0;
417}
418DM_TEST(dm_test_bus_child_post_bind_uclass,
e180c2b1 419 UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
83c7e434
SG
420
421/*
422 * Test that the bus' uclass' child_pre_probe() is called before the
423 * device's probe() method
424 */
e721b882 425static int dm_test_bus_child_pre_probe_uclass(struct unit_test_state *uts)
83c7e434
SG
426{
427 struct udevice *bus, *dev;
83c7e434
SG
428
429 /*
430 * See testfdt_drv_probe() which effectively checks that the uclass
431 * flag is set before that method is called
432 */
433 ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
240b9320 434 for (device_find_first_child(bus, &dev);
83c7e434
SG
435 dev;
436 device_find_next_child(&dev)) {
437 struct dm_test_priv *priv = dev_get_priv(dev);
438
439 /* Check that things happened in the right order */
440 ut_asserteq_ptr(NULL, priv);
441 ut_assertok(device_probe(dev));
442
443 priv = dev_get_priv(dev);
444 ut_assert(priv != NULL);
445 ut_asserteq(1, priv->uclass_flag);
446 ut_asserteq(1, priv->uclass_total);
83c7e434 447 }
240b9320 448 ut_asserteq(3, device_get_child_count(bus));
83c7e434
SG
449
450 return 0;
451}
452DM_TEST(dm_test_bus_child_pre_probe_uclass,
e180c2b1 453 UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
d92878aa
BM
454
455/*
456 * Test that the bus' uclass' child_post_probe() is called after the
457 * device's probe() method
458 */
459static int dm_test_bus_child_post_probe_uclass(struct unit_test_state *uts)
460{
461 struct udevice *bus, *dev;
d92878aa
BM
462
463 /*
464 * See testfdt_drv_probe() which effectively initializes that
465 * the uclass postp flag is set to a value
466 */
467 ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
240b9320 468 for (device_find_first_child(bus, &dev);
d92878aa
BM
469 dev;
470 device_find_next_child(&dev)) {
471 struct dm_test_priv *priv = dev_get_priv(dev);
472
473 /* Check that things happened in the right order */
474 ut_asserteq_ptr(NULL, priv);
475 ut_assertok(device_probe(dev));
476
477 priv = dev_get_priv(dev);
478 ut_assert(priv != NULL);
479 ut_asserteq(0, priv->uclass_postp);
d92878aa 480 }
240b9320 481 ut_asserteq(3, device_get_child_count(bus));
d92878aa
BM
482
483 return 0;
484}
485DM_TEST(dm_test_bus_child_post_probe_uclass,
e180c2b1 486 UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);