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