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