xref: /openbmc/u-boot/test/dm/bus.c (revision 286a5c44)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2014 Google, Inc
4  */
5 
6 #include <common.h>
7 #ifdef CONFIG_SANDBOX
8 #include <os.h>
9 #endif
10 #include <dm.h>
11 #include <dm/device-internal.h>
12 #include <dm/test.h>
13 #include <dm/uclass-internal.h>
14 #include <dm/util.h>
15 #include <test/ut.h>
16 
17 DECLARE_GLOBAL_DATA_PTR;
18 
19 struct dm_test_parent_platdata {
20 	int count;
21 	int bind_flag;
22 	int uclass_bind_flag;
23 };
24 
25 enum {
26 	FLAG_CHILD_PROBED	= 10,
27 	FLAG_CHILD_REMOVED	= -7,
28 };
29 
30 static struct dm_test_state *test_state;
31 
32 static int testbus_drv_probe(struct udevice *dev)
33 {
34 	return dm_scan_fdt_dev(dev);
35 }
36 
37 static int testbus_child_post_bind(struct udevice *dev)
38 {
39 	struct dm_test_parent_platdata *plat;
40 
41 	plat = dev_get_parent_platdata(dev);
42 	plat->bind_flag = 1;
43 	plat->uclass_bind_flag = 2;
44 
45 	return 0;
46 }
47 
48 static int testbus_child_pre_probe(struct udevice *dev)
49 {
50 	struct dm_test_parent_data *parent_data = dev_get_parent_priv(dev);
51 
52 	parent_data->flag += FLAG_CHILD_PROBED;
53 
54 	return 0;
55 }
56 
57 static int testbus_child_pre_probe_uclass(struct udevice *dev)
58 {
59 	struct dm_test_priv *priv = dev_get_priv(dev);
60 
61 	priv->uclass_flag++;
62 
63 	return 0;
64 }
65 
66 static int testbus_child_post_probe_uclass(struct udevice *dev)
67 {
68 	struct dm_test_priv *priv = dev_get_priv(dev);
69 
70 	priv->uclass_postp++;
71 
72 	return 0;
73 }
74 
75 static int testbus_child_post_remove(struct udevice *dev)
76 {
77 	struct dm_test_parent_data *parent_data = dev_get_parent_priv(dev);
78 	struct dm_test_state *dms = test_state;
79 
80 	parent_data->flag += FLAG_CHILD_REMOVED;
81 	if (dms)
82 		dms->removed = dev;
83 
84 	return 0;
85 }
86 
87 static const struct udevice_id testbus_ids[] = {
88 	{
89 		.compatible = "denx,u-boot-test-bus",
90 		.data = DM_TEST_TYPE_FIRST },
91 	{ }
92 };
93 
94 U_BOOT_DRIVER(testbus_drv) = {
95 	.name	= "testbus_drv",
96 	.of_match	= testbus_ids,
97 	.id	= UCLASS_TEST_BUS,
98 	.probe	= testbus_drv_probe,
99 	.child_post_bind = testbus_child_post_bind,
100 	.priv_auto_alloc_size = sizeof(struct dm_test_priv),
101 	.platdata_auto_alloc_size = sizeof(struct dm_test_pdata),
102 	.per_child_auto_alloc_size = sizeof(struct dm_test_parent_data),
103 	.per_child_platdata_auto_alloc_size =
104 			sizeof(struct dm_test_parent_platdata),
105 	.child_pre_probe = testbus_child_pre_probe,
106 	.child_post_remove = testbus_child_post_remove,
107 };
108 
109 UCLASS_DRIVER(testbus) = {
110 	.name		= "testbus",
111 	.id		= UCLASS_TEST_BUS,
112 	.flags		= DM_UC_FLAG_SEQ_ALIAS,
113 	.child_pre_probe = testbus_child_pre_probe_uclass,
114 	.child_post_probe = testbus_child_post_probe_uclass,
115 };
116 
117 /* Test that we can probe for children */
118 static int dm_test_bus_children(struct unit_test_state *uts)
119 {
120 	int num_devices = 8;
121 	struct udevice *bus;
122 	struct uclass *uc;
123 
124 	ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc));
125 	ut_asserteq(num_devices, list_count_items(&uc->dev_head));
126 
127 	/* Probe the bus, which should yield 3 more devices */
128 	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
129 	num_devices += 3;
130 
131 	ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc));
132 	ut_asserteq(num_devices, list_count_items(&uc->dev_head));
133 
134 	ut_assert(!dm_check_devices(uts, num_devices));
135 
136 	return 0;
137 }
138 DM_TEST(dm_test_bus_children, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
139 
140 /* Test our functions for accessing children */
141 static int dm_test_bus_children_funcs(struct unit_test_state *uts)
142 {
143 	const void *blob = gd->fdt_blob;
144 	struct udevice *bus, *dev;
145 	int node;
146 
147 	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
148 
149 	/* device_get_child() */
150 	ut_assertok(device_get_child(bus, 0, &dev));
151 	ut_asserteq(-ENODEV, device_get_child(bus, 4, &dev));
152 	ut_assertok(device_get_child_by_seq(bus, 5, &dev));
153 	ut_assert(dev->flags & DM_FLAG_ACTIVATED);
154 	ut_asserteq_str("c-test@5", dev->name);
155 
156 	/* Device with sequence number 0 should be accessible */
157 	ut_asserteq(-ENODEV, device_find_child_by_seq(bus, -1, true, &dev));
158 	ut_assertok(device_find_child_by_seq(bus, 0, true, &dev));
159 	ut_assert(!(dev->flags & DM_FLAG_ACTIVATED));
160 	ut_asserteq(-ENODEV, device_find_child_by_seq(bus, 0, false, &dev));
161 	ut_assertok(device_get_child_by_seq(bus, 0, &dev));
162 	ut_assert(dev->flags & DM_FLAG_ACTIVATED);
163 
164 	/* There is no device with sequence number 2 */
165 	ut_asserteq(-ENODEV, device_find_child_by_seq(bus, 2, false, &dev));
166 	ut_asserteq(-ENODEV, device_find_child_by_seq(bus, 2, true, &dev));
167 	ut_asserteq(-ENODEV, device_get_child_by_seq(bus, 2, &dev));
168 
169 	/* Looking for something that is not a child */
170 	node = fdt_path_offset(blob, "/junk");
171 	ut_asserteq(-ENODEV, device_find_child_by_of_offset(bus, node, &dev));
172 	node = fdt_path_offset(blob, "/d-test");
173 	ut_asserteq(-ENODEV, device_find_child_by_of_offset(bus, node, &dev));
174 
175 	return 0;
176 }
177 DM_TEST(dm_test_bus_children_funcs, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
178 
179 static int dm_test_bus_children_of_offset(struct unit_test_state *uts)
180 {
181 	const void *blob = gd->fdt_blob;
182 	struct udevice *bus, *dev;
183 	int node;
184 
185 	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
186 	ut_assertnonnull(bus);
187 
188 	/* Find a valid child */
189 	node = fdt_path_offset(blob, "/some-bus/c-test@1");
190 	ut_assert(node > 0);
191 	ut_assertok(device_find_child_by_of_offset(bus, node, &dev));
192 	ut_assertnonnull(dev);
193 	ut_assert(!(dev->flags & DM_FLAG_ACTIVATED));
194 	ut_assertok(device_get_child_by_of_offset(bus, node, &dev));
195 	ut_assertnonnull(dev);
196 	ut_assert(dev->flags & DM_FLAG_ACTIVATED);
197 
198 	return 0;
199 }
200 DM_TEST(dm_test_bus_children_of_offset,
201 	DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT | DM_TESTF_FLAT_TREE);
202 
203 /* Test that we can iterate through children */
204 static int dm_test_bus_children_iterators(struct unit_test_state *uts)
205 {
206 	struct udevice *bus, *dev, *child;
207 
208 	/* Walk through the children one by one */
209 	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
210 	ut_assertok(device_find_first_child(bus, &dev));
211 	ut_asserteq_str("c-test@5", dev->name);
212 	ut_assertok(device_find_next_child(&dev));
213 	ut_asserteq_str("c-test@0", dev->name);
214 	ut_assertok(device_find_next_child(&dev));
215 	ut_asserteq_str("c-test@1", dev->name);
216 	ut_assertok(device_find_next_child(&dev));
217 	ut_asserteq_ptr(dev, NULL);
218 
219 	/* Move to the next child without using device_find_first_child() */
220 	ut_assertok(device_find_child_by_seq(bus, 5, true, &dev));
221 	ut_asserteq_str("c-test@5", dev->name);
222 	ut_assertok(device_find_next_child(&dev));
223 	ut_asserteq_str("c-test@0", dev->name);
224 
225 	/* Try a device with no children */
226 	ut_assertok(device_find_first_child(dev, &child));
227 	ut_asserteq_ptr(child, NULL);
228 
229 	return 0;
230 }
231 DM_TEST(dm_test_bus_children_iterators,
232 	DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
233 
234 /* Test that the bus can store data about each child */
235 static int test_bus_parent_data(struct unit_test_state *uts)
236 {
237 	struct dm_test_parent_data *parent_data;
238 	struct udevice *bus, *dev;
239 	struct uclass *uc;
240 	int value;
241 
242 	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
243 
244 	/* Check that parent data is allocated */
245 	ut_assertok(device_find_child_by_seq(bus, 0, true, &dev));
246 	ut_asserteq_ptr(NULL, dev_get_parent_priv(dev));
247 	ut_assertok(device_get_child_by_seq(bus, 0, &dev));
248 	parent_data = dev_get_parent_priv(dev);
249 	ut_assert(NULL != parent_data);
250 
251 	/* Check that it starts at 0 and goes away when device is removed */
252 	parent_data->sum += 5;
253 	ut_asserteq(5, parent_data->sum);
254 	device_remove(dev, DM_REMOVE_NORMAL);
255 	ut_asserteq_ptr(NULL, dev_get_parent_priv(dev));
256 
257 	/* Check that we can do this twice */
258 	ut_assertok(device_get_child_by_seq(bus, 0, &dev));
259 	parent_data = dev_get_parent_priv(dev);
260 	ut_assert(NULL != parent_data);
261 	parent_data->sum += 5;
262 	ut_asserteq(5, parent_data->sum);
263 
264 	/* Add parent data to all children */
265 	ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc));
266 	value = 5;
267 	uclass_foreach_dev(dev, uc) {
268 		/* Ignore these if they are not on this bus */
269 		if (dev->parent != bus) {
270 			ut_asserteq_ptr(NULL, dev_get_parent_priv(dev));
271 			continue;
272 		}
273 		ut_assertok(device_probe(dev));
274 		parent_data = dev_get_parent_priv(dev);
275 
276 		parent_data->sum = value;
277 		value += 5;
278 	}
279 
280 	/* Check it is still there */
281 	value = 5;
282 	uclass_foreach_dev(dev, uc) {
283 		/* Ignore these if they are not on this bus */
284 		if (dev->parent != bus)
285 			continue;
286 		parent_data = dev_get_parent_priv(dev);
287 
288 		ut_asserteq(value, parent_data->sum);
289 		value += 5;
290 	}
291 
292 	return 0;
293 }
294 /* Test that the bus can store data about each child */
295 static int dm_test_bus_parent_data(struct unit_test_state *uts)
296 {
297 	return test_bus_parent_data(uts);
298 }
299 DM_TEST(dm_test_bus_parent_data, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
300 
301 /* As above but the size is controlled by the uclass */
302 static int dm_test_bus_parent_data_uclass(struct unit_test_state *uts)
303 {
304 	struct driver *drv;
305 	struct udevice *bus;
306 	int size;
307 	int ret;
308 
309 	/* Set the driver size to 0 so that the uclass size is used */
310 	ut_assertok(uclass_find_device(UCLASS_TEST_BUS, 0, &bus));
311 	drv = (struct driver *)bus->driver;
312 	size = drv->per_child_auto_alloc_size;
313 
314 #ifdef CONFIG_SANDBOX
315 	os_mprotect_allow(bus->uclass->uc_drv, sizeof(*bus->uclass->uc_drv));
316 	os_mprotect_allow(drv, sizeof(*drv));
317 #endif
318 	bus->uclass->uc_drv->per_child_auto_alloc_size = size;
319 	drv->per_child_auto_alloc_size = 0;
320 	ret = test_bus_parent_data(uts);
321 	if (ret)
322 		return ret;
323 	bus->uclass->uc_drv->per_child_auto_alloc_size = 0;
324 	drv->per_child_auto_alloc_size = size;
325 
326 	return 0;
327 }
328 DM_TEST(dm_test_bus_parent_data_uclass,
329 	DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
330 
331 /* Test that the bus ops are called when a child is probed/removed */
332 static int dm_test_bus_parent_ops(struct unit_test_state *uts)
333 {
334 	struct dm_test_parent_data *parent_data;
335 	struct dm_test_state *dms = uts->priv;
336 	struct udevice *bus, *dev;
337 	struct uclass *uc;
338 
339 	test_state = dms;
340 	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
341 	ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc));
342 
343 	uclass_foreach_dev(dev, uc) {
344 		/* Ignore these if they are not on this bus */
345 		if (dev->parent != bus)
346 			continue;
347 		ut_asserteq_ptr(NULL, dev_get_parent_priv(dev));
348 
349 		ut_assertok(device_probe(dev));
350 		parent_data = dev_get_parent_priv(dev);
351 		ut_asserteq(FLAG_CHILD_PROBED, parent_data->flag);
352 	}
353 
354 	uclass_foreach_dev(dev, uc) {
355 		/* Ignore these if they are not on this bus */
356 		if (dev->parent != bus)
357 			continue;
358 		parent_data = dev_get_parent_priv(dev);
359 		ut_asserteq(FLAG_CHILD_PROBED, parent_data->flag);
360 		ut_assertok(device_remove(dev, DM_REMOVE_NORMAL));
361 		ut_asserteq_ptr(NULL, dev_get_parent_priv(dev));
362 		ut_asserteq_ptr(dms->removed, dev);
363 	}
364 	test_state = NULL;
365 
366 	return 0;
367 }
368 DM_TEST(dm_test_bus_parent_ops, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
369 
370 static int test_bus_parent_platdata(struct unit_test_state *uts)
371 {
372 	struct dm_test_parent_platdata *plat;
373 	struct udevice *bus, *dev;
374 	int child_count;
375 
376 	/* Check that the bus has no children */
377 	ut_assertok(uclass_find_device(UCLASS_TEST_BUS, 0, &bus));
378 	device_find_first_child(bus, &dev);
379 	ut_asserteq_ptr(NULL, dev);
380 
381 	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
382 
383 	for (device_find_first_child(bus, &dev), child_count = 0;
384 	     dev;
385 	     device_find_next_child(&dev)) {
386 		/* Check that platform data is allocated */
387 		plat = dev_get_parent_platdata(dev);
388 		ut_assert(plat != NULL);
389 
390 		/*
391 		 * Check that it is not affected by the device being
392 		 * probed/removed
393 		 */
394 		plat->count++;
395 		ut_asserteq(1, plat->count);
396 		device_probe(dev);
397 		device_remove(dev, DM_REMOVE_NORMAL);
398 
399 		ut_asserteq_ptr(plat, dev_get_parent_platdata(dev));
400 		ut_asserteq(1, plat->count);
401 		ut_assertok(device_probe(dev));
402 		child_count++;
403 	}
404 	ut_asserteq(3, child_count);
405 
406 	/* Removing the bus should also have no effect (it is still bound) */
407 	device_remove(bus, DM_REMOVE_NORMAL);
408 	for (device_find_first_child(bus, &dev), child_count = 0;
409 	     dev;
410 	     device_find_next_child(&dev)) {
411 		/* Check that platform data is allocated */
412 		plat = dev_get_parent_platdata(dev);
413 		ut_assert(plat != NULL);
414 		ut_asserteq(1, plat->count);
415 		child_count++;
416 	}
417 	ut_asserteq(3, child_count);
418 
419 	/* Unbind all the children */
420 	do {
421 		device_find_first_child(bus, &dev);
422 		if (dev)
423 			device_unbind(dev);
424 	} while (dev);
425 
426 	/* Now the child platdata should be removed and re-added */
427 	device_probe(bus);
428 	for (device_find_first_child(bus, &dev), child_count = 0;
429 	     dev;
430 	     device_find_next_child(&dev)) {
431 		/* Check that platform data is allocated */
432 		plat = dev_get_parent_platdata(dev);
433 		ut_assert(plat != NULL);
434 		ut_asserteq(0, plat->count);
435 		child_count++;
436 	}
437 	ut_asserteq(3, child_count);
438 
439 	return 0;
440 }
441 
442 /* Test that the bus can store platform data about each child */
443 static int dm_test_bus_parent_platdata(struct unit_test_state *uts)
444 {
445 	return test_bus_parent_platdata(uts);
446 }
447 DM_TEST(dm_test_bus_parent_platdata, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
448 
449 /* As above but the size is controlled by the uclass */
450 static int dm_test_bus_parent_platdata_uclass(struct unit_test_state *uts)
451 {
452 	struct udevice *bus;
453 	struct driver *drv;
454 	int size;
455 	int ret;
456 
457 	/* Set the driver size to 0 so that the uclass size is used */
458 	ut_assertok(uclass_find_device(UCLASS_TEST_BUS, 0, &bus));
459 	drv = (struct driver *)bus->driver;
460 	size = drv->per_child_platdata_auto_alloc_size;
461 #ifdef CONFIG_SANDBOX
462 	os_mprotect_allow(bus->uclass->uc_drv, sizeof(*bus->uclass->uc_drv));
463 	os_mprotect_allow(drv, sizeof(*drv));
464 #endif
465 	bus->uclass->uc_drv->per_child_platdata_auto_alloc_size = size;
466 	drv->per_child_platdata_auto_alloc_size = 0;
467 	ret = test_bus_parent_platdata(uts);
468 	if (ret)
469 		return ret;
470 	bus->uclass->uc_drv->per_child_platdata_auto_alloc_size = 0;
471 	drv->per_child_platdata_auto_alloc_size = size;
472 
473 	return 0;
474 }
475 DM_TEST(dm_test_bus_parent_platdata_uclass,
476 	DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
477 
478 /* Test that the child post_bind method is called */
479 static int dm_test_bus_child_post_bind(struct unit_test_state *uts)
480 {
481 	struct dm_test_parent_platdata *plat;
482 	struct udevice *bus, *dev;
483 	int child_count;
484 
485 	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
486 	for (device_find_first_child(bus, &dev), child_count = 0;
487 	     dev;
488 	     device_find_next_child(&dev)) {
489 		/* Check that platform data is allocated */
490 		plat = dev_get_parent_platdata(dev);
491 		ut_assert(plat != NULL);
492 		ut_asserteq(1, plat->bind_flag);
493 		child_count++;
494 	}
495 	ut_asserteq(3, child_count);
496 
497 	return 0;
498 }
499 DM_TEST(dm_test_bus_child_post_bind, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
500 
501 /* Test that the child post_bind method is called */
502 static int dm_test_bus_child_post_bind_uclass(struct unit_test_state *uts)
503 {
504 	struct dm_test_parent_platdata *plat;
505 	struct udevice *bus, *dev;
506 	int child_count;
507 
508 	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
509 	for (device_find_first_child(bus, &dev), child_count = 0;
510 	     dev;
511 	     device_find_next_child(&dev)) {
512 		/* Check that platform data is allocated */
513 		plat = dev_get_parent_platdata(dev);
514 		ut_assert(plat != NULL);
515 		ut_asserteq(2, plat->uclass_bind_flag);
516 		child_count++;
517 	}
518 	ut_asserteq(3, child_count);
519 
520 	return 0;
521 }
522 DM_TEST(dm_test_bus_child_post_bind_uclass,
523 	DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
524 
525 /*
526  * Test that the bus' uclass' child_pre_probe() is called before the
527  * device's probe() method
528  */
529 static int dm_test_bus_child_pre_probe_uclass(struct unit_test_state *uts)
530 {
531 	struct udevice *bus, *dev;
532 	int child_count;
533 
534 	/*
535 	 * See testfdt_drv_probe() which effectively checks that the uclass
536 	 * flag is set before that method is called
537 	 */
538 	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
539 	for (device_find_first_child(bus, &dev), child_count = 0;
540 	     dev;
541 	     device_find_next_child(&dev)) {
542 		struct dm_test_priv *priv = dev_get_priv(dev);
543 
544 		/* Check that things happened in the right order */
545 		ut_asserteq_ptr(NULL, priv);
546 		ut_assertok(device_probe(dev));
547 
548 		priv = dev_get_priv(dev);
549 		ut_assert(priv != NULL);
550 		ut_asserteq(1, priv->uclass_flag);
551 		ut_asserteq(1, priv->uclass_total);
552 		child_count++;
553 	}
554 	ut_asserteq(3, child_count);
555 
556 	return 0;
557 }
558 DM_TEST(dm_test_bus_child_pre_probe_uclass,
559 	DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
560 
561 /*
562  * Test that the bus' uclass' child_post_probe() is called after the
563  * device's probe() method
564  */
565 static int dm_test_bus_child_post_probe_uclass(struct unit_test_state *uts)
566 {
567 	struct udevice *bus, *dev;
568 	int child_count;
569 
570 	/*
571 	 * See testfdt_drv_probe() which effectively initializes that
572 	 * the uclass postp flag is set to a value
573 	 */
574 	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
575 	for (device_find_first_child(bus, &dev), child_count = 0;
576 	     dev;
577 	     device_find_next_child(&dev)) {
578 		struct dm_test_priv *priv = dev_get_priv(dev);
579 
580 		/* Check that things happened in the right order */
581 		ut_asserteq_ptr(NULL, priv);
582 		ut_assertok(device_probe(dev));
583 
584 		priv = dev_get_priv(dev);
585 		ut_assert(priv != NULL);
586 		ut_asserteq(0, priv->uclass_postp);
587 		child_count++;
588 	}
589 	ut_asserteq(3, child_count);
590 
591 	return 0;
592 }
593 DM_TEST(dm_test_bus_child_post_probe_uclass,
594 	DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
595