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