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