xref: /openbmc/u-boot/test/dm/bus.c (revision e721b882)
11ca7e206SSimon Glass /*
21ca7e206SSimon Glass  * Copyright (c) 2014 Google, Inc
31ca7e206SSimon Glass  *
41ca7e206SSimon Glass  * SPDX-License-Identifier:	GPL-2.0+
51ca7e206SSimon Glass  */
61ca7e206SSimon Glass 
71ca7e206SSimon Glass #include <common.h>
81ca7e206SSimon Glass #include <dm.h>
9e59f458dSSimon Glass #include <dm/device-internal.h>
101ca7e206SSimon Glass #include <dm/root.h>
111ca7e206SSimon Glass #include <dm/test.h>
12cdc133bdSSimon Glass #include <dm/uclass-internal.h>
131ca7e206SSimon Glass #include <dm/util.h>
14*e721b882SJoe Hershberger #include <test/ut.h>
151ca7e206SSimon Glass 
161ca7e206SSimon Glass DECLARE_GLOBAL_DATA_PTR;
171ca7e206SSimon Glass 
18cdc133bdSSimon Glass struct dm_test_parent_platdata {
19cdc133bdSSimon Glass 	int count;
200118ce79SSimon Glass 	int bind_flag;
21081f2fcbSSimon Glass 	int uclass_bind_flag;
22cdc133bdSSimon Glass };
23cdc133bdSSimon Glass 
24a327dee0SSimon Glass enum {
25a327dee0SSimon Glass 	FLAG_CHILD_PROBED	= 10,
26a327dee0SSimon Glass 	FLAG_CHILD_REMOVED	= -7,
27a327dee0SSimon Glass };
28a327dee0SSimon Glass 
29a327dee0SSimon Glass static struct dm_test_state *test_state;
30a327dee0SSimon Glass 
311ca7e206SSimon Glass static int testbus_drv_probe(struct udevice *dev)
321ca7e206SSimon Glass {
331ca7e206SSimon Glass 	return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
341ca7e206SSimon Glass }
351ca7e206SSimon Glass 
360118ce79SSimon Glass static int testbus_child_post_bind(struct udevice *dev)
370118ce79SSimon Glass {
380118ce79SSimon Glass 	struct dm_test_parent_platdata *plat;
390118ce79SSimon Glass 
400118ce79SSimon Glass 	plat = dev_get_parent_platdata(dev);
410118ce79SSimon Glass 	plat->bind_flag = 1;
42081f2fcbSSimon Glass 	plat->uclass_bind_flag = 2;
430118ce79SSimon Glass 
440118ce79SSimon Glass 	return 0;
450118ce79SSimon Glass }
460118ce79SSimon Glass 
47a327dee0SSimon Glass static int testbus_child_pre_probe(struct udevice *dev)
48a327dee0SSimon Glass {
49a327dee0SSimon Glass 	struct dm_test_parent_data *parent_data = dev_get_parentdata(dev);
50a327dee0SSimon Glass 
51a327dee0SSimon Glass 	parent_data->flag += FLAG_CHILD_PROBED;
52a327dee0SSimon Glass 
53a327dee0SSimon Glass 	return 0;
54a327dee0SSimon Glass }
55a327dee0SSimon Glass 
5683c7e434SSimon Glass static int testbus_child_pre_probe_uclass(struct udevice *dev)
5783c7e434SSimon Glass {
5883c7e434SSimon Glass 	struct dm_test_priv *priv = dev_get_priv(dev);
5983c7e434SSimon Glass 
6083c7e434SSimon Glass 	priv->uclass_flag++;
6183c7e434SSimon Glass 
6283c7e434SSimon Glass 	return 0;
6383c7e434SSimon Glass }
6483c7e434SSimon Glass 
65a327dee0SSimon Glass static int testbus_child_post_remove(struct udevice *dev)
66a327dee0SSimon Glass {
67a327dee0SSimon Glass 	struct dm_test_parent_data *parent_data = dev_get_parentdata(dev);
68a327dee0SSimon Glass 	struct dm_test_state *dms = test_state;
69a327dee0SSimon Glass 
70a327dee0SSimon Glass 	parent_data->flag += FLAG_CHILD_REMOVED;
71a327dee0SSimon Glass 	if (dms)
72a327dee0SSimon Glass 		dms->removed = dev;
73a327dee0SSimon Glass 
74a327dee0SSimon Glass 	return 0;
75a327dee0SSimon Glass }
76a327dee0SSimon Glass 
771ca7e206SSimon Glass static const struct udevice_id testbus_ids[] = {
781ca7e206SSimon Glass 	{
791ca7e206SSimon Glass 		.compatible = "denx,u-boot-test-bus",
801ca7e206SSimon Glass 		.data = DM_TEST_TYPE_FIRST },
811ca7e206SSimon Glass 	{ }
821ca7e206SSimon Glass };
831ca7e206SSimon Glass 
841ca7e206SSimon Glass U_BOOT_DRIVER(testbus_drv) = {
851ca7e206SSimon Glass 	.name	= "testbus_drv",
861ca7e206SSimon Glass 	.of_match	= testbus_ids,
871ca7e206SSimon Glass 	.id	= UCLASS_TEST_BUS,
881ca7e206SSimon Glass 	.probe	= testbus_drv_probe,
890118ce79SSimon Glass 	.child_post_bind = testbus_child_post_bind,
901ca7e206SSimon Glass 	.priv_auto_alloc_size = sizeof(struct dm_test_priv),
911ca7e206SSimon Glass 	.platdata_auto_alloc_size = sizeof(struct dm_test_pdata),
92e59f458dSSimon Glass 	.per_child_auto_alloc_size = sizeof(struct dm_test_parent_data),
93cdc133bdSSimon Glass 	.per_child_platdata_auto_alloc_size =
94cdc133bdSSimon Glass 			sizeof(struct dm_test_parent_platdata),
95a327dee0SSimon Glass 	.child_pre_probe = testbus_child_pre_probe,
96a327dee0SSimon Glass 	.child_post_remove = testbus_child_post_remove,
971ca7e206SSimon Glass };
981ca7e206SSimon Glass 
991ca7e206SSimon Glass UCLASS_DRIVER(testbus) = {
1001ca7e206SSimon Glass 	.name		= "testbus",
1011ca7e206SSimon Glass 	.id		= UCLASS_TEST_BUS,
1029cc36a2bSSimon Glass 	.flags		= DM_UC_FLAG_SEQ_ALIAS,
10383c7e434SSimon Glass 	.child_pre_probe = testbus_child_pre_probe_uclass,
1041ca7e206SSimon Glass };
1051ca7e206SSimon Glass 
1061ca7e206SSimon Glass /* Test that we can probe for children */
107*e721b882SJoe Hershberger static int dm_test_bus_children(struct unit_test_state *uts)
1081ca7e206SSimon Glass {
1099cc36a2bSSimon Glass 	int num_devices = 6;
1101ca7e206SSimon Glass 	struct udevice *bus;
1111ca7e206SSimon Glass 	struct uclass *uc;
1121ca7e206SSimon Glass 
1131ca7e206SSimon Glass 	ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc));
1141ca7e206SSimon Glass 	ut_asserteq(num_devices, list_count_items(&uc->dev_head));
1151ca7e206SSimon Glass 
1161ca7e206SSimon Glass 	/* Probe the bus, which should yield 3 more devices */
1171ca7e206SSimon Glass 	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
1181ca7e206SSimon Glass 	num_devices += 3;
1191ca7e206SSimon Glass 
1201ca7e206SSimon Glass 	ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc));
1211ca7e206SSimon Glass 	ut_asserteq(num_devices, list_count_items(&uc->dev_head));
1221ca7e206SSimon Glass 
123*e721b882SJoe Hershberger 	ut_assert(!dm_check_devices(uts, num_devices));
1241ca7e206SSimon Glass 
1251ca7e206SSimon Glass 	return 0;
1261ca7e206SSimon Glass }
1271ca7e206SSimon Glass DM_TEST(dm_test_bus_children, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
128997c87bbSSimon Glass 
129997c87bbSSimon Glass /* Test our functions for accessing children */
130*e721b882SJoe Hershberger static int dm_test_bus_children_funcs(struct unit_test_state *uts)
131997c87bbSSimon Glass {
132997c87bbSSimon Glass 	const void *blob = gd->fdt_blob;
133997c87bbSSimon Glass 	struct udevice *bus, *dev;
134997c87bbSSimon Glass 	int node;
135997c87bbSSimon Glass 
136997c87bbSSimon Glass 	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
137997c87bbSSimon Glass 
138997c87bbSSimon Glass 	/* device_get_child() */
139997c87bbSSimon Glass 	ut_assertok(device_get_child(bus, 0, &dev));
140997c87bbSSimon Glass 	ut_asserteq(-ENODEV, device_get_child(bus, 4, &dev));
141997c87bbSSimon Glass 	ut_assertok(device_get_child_by_seq(bus, 5, &dev));
142997c87bbSSimon Glass 	ut_assert(dev->flags & DM_FLAG_ACTIVATED);
143997c87bbSSimon Glass 	ut_asserteq_str("c-test@5", dev->name);
144997c87bbSSimon Glass 
145997c87bbSSimon Glass 	/* Device with sequence number 0 should be accessible */
146997c87bbSSimon Glass 	ut_asserteq(-ENODEV, device_find_child_by_seq(bus, -1, true, &dev));
147997c87bbSSimon Glass 	ut_assertok(device_find_child_by_seq(bus, 0, true, &dev));
148997c87bbSSimon Glass 	ut_assert(!(dev->flags & DM_FLAG_ACTIVATED));
149997c87bbSSimon Glass 	ut_asserteq(-ENODEV, device_find_child_by_seq(bus, 0, false, &dev));
150997c87bbSSimon Glass 	ut_assertok(device_get_child_by_seq(bus, 0, &dev));
151997c87bbSSimon Glass 	ut_assert(dev->flags & DM_FLAG_ACTIVATED);
152997c87bbSSimon Glass 
153997c87bbSSimon Glass 	/* There is no device with sequence number 2 */
154997c87bbSSimon Glass 	ut_asserteq(-ENODEV, device_find_child_by_seq(bus, 2, false, &dev));
155997c87bbSSimon Glass 	ut_asserteq(-ENODEV, device_find_child_by_seq(bus, 2, true, &dev));
156997c87bbSSimon Glass 	ut_asserteq(-ENODEV, device_get_child_by_seq(bus, 2, &dev));
157997c87bbSSimon Glass 
158997c87bbSSimon Glass 	/* Looking for something that is not a child */
159997c87bbSSimon Glass 	node = fdt_path_offset(blob, "/junk");
160997c87bbSSimon Glass 	ut_asserteq(-ENODEV, device_find_child_by_of_offset(bus, node, &dev));
161997c87bbSSimon Glass 	node = fdt_path_offset(blob, "/d-test");
162997c87bbSSimon Glass 	ut_asserteq(-ENODEV, device_find_child_by_of_offset(bus, node, &dev));
163997c87bbSSimon Glass 
164997c87bbSSimon Glass 	/* Find a valid child */
165997c87bbSSimon Glass 	node = fdt_path_offset(blob, "/some-bus/c-test@1");
166997c87bbSSimon Glass 	ut_assertok(device_find_child_by_of_offset(bus, node, &dev));
167997c87bbSSimon Glass 	ut_assert(!(dev->flags & DM_FLAG_ACTIVATED));
168997c87bbSSimon Glass 	ut_assertok(device_get_child_by_of_offset(bus, node, &dev));
169997c87bbSSimon Glass 	ut_assert(dev->flags & DM_FLAG_ACTIVATED);
170997c87bbSSimon Glass 
171997c87bbSSimon Glass 	return 0;
172997c87bbSSimon Glass }
173997c87bbSSimon Glass DM_TEST(dm_test_bus_children_funcs, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
174e59f458dSSimon Glass 
175a8981d4fSSimon Glass /* Test that we can iterate through children */
176*e721b882SJoe Hershberger static int dm_test_bus_children_iterators(struct unit_test_state *uts)
177a8981d4fSSimon Glass {
178a8981d4fSSimon Glass 	struct udevice *bus, *dev, *child;
179a8981d4fSSimon Glass 
180a8981d4fSSimon Glass 	/* Walk through the children one by one */
181a8981d4fSSimon Glass 	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
182a8981d4fSSimon Glass 	ut_assertok(device_find_first_child(bus, &dev));
183a8981d4fSSimon Glass 	ut_asserteq_str("c-test@5", dev->name);
184a8981d4fSSimon Glass 	ut_assertok(device_find_next_child(&dev));
185a8981d4fSSimon Glass 	ut_asserteq_str("c-test@0", dev->name);
186a8981d4fSSimon Glass 	ut_assertok(device_find_next_child(&dev));
187a8981d4fSSimon Glass 	ut_asserteq_str("c-test@1", dev->name);
188a8981d4fSSimon Glass 	ut_assertok(device_find_next_child(&dev));
189a8981d4fSSimon Glass 	ut_asserteq_ptr(dev, NULL);
190a8981d4fSSimon Glass 
191a8981d4fSSimon Glass 	/* Move to the next child without using device_find_first_child() */
192a8981d4fSSimon Glass 	ut_assertok(device_find_child_by_seq(bus, 5, true, &dev));
193a8981d4fSSimon Glass 	ut_asserteq_str("c-test@5", dev->name);
194a8981d4fSSimon Glass 	ut_assertok(device_find_next_child(&dev));
195a8981d4fSSimon Glass 	ut_asserteq_str("c-test@0", dev->name);
196a8981d4fSSimon Glass 
197a8981d4fSSimon Glass 	/* Try a device with no children */
198a8981d4fSSimon Glass 	ut_assertok(device_find_first_child(dev, &child));
199a8981d4fSSimon Glass 	ut_asserteq_ptr(child, NULL);
200a8981d4fSSimon Glass 
201a8981d4fSSimon Glass 	return 0;
202a8981d4fSSimon Glass }
203a8981d4fSSimon Glass DM_TEST(dm_test_bus_children_iterators,
204a8981d4fSSimon Glass 	DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
205a8981d4fSSimon Glass 
206e59f458dSSimon Glass /* Test that the bus can store data about each child */
207*e721b882SJoe Hershberger static int test_bus_parent_data(struct unit_test_state *uts)
208e59f458dSSimon Glass {
209e59f458dSSimon Glass 	struct dm_test_parent_data *parent_data;
210e59f458dSSimon Glass 	struct udevice *bus, *dev;
211e59f458dSSimon Glass 	struct uclass *uc;
212e59f458dSSimon Glass 	int value;
213e59f458dSSimon Glass 
214e59f458dSSimon Glass 	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
215e59f458dSSimon Glass 
216e59f458dSSimon Glass 	/* Check that parent data is allocated */
217e59f458dSSimon Glass 	ut_assertok(device_find_child_by_seq(bus, 0, true, &dev));
218e59f458dSSimon Glass 	ut_asserteq_ptr(NULL, dev_get_parentdata(dev));
219e59f458dSSimon Glass 	ut_assertok(device_get_child_by_seq(bus, 0, &dev));
220e59f458dSSimon Glass 	parent_data = dev_get_parentdata(dev);
221e59f458dSSimon Glass 	ut_assert(NULL != parent_data);
222e59f458dSSimon Glass 
223e59f458dSSimon Glass 	/* Check that it starts at 0 and goes away when device is removed */
224e59f458dSSimon Glass 	parent_data->sum += 5;
225e59f458dSSimon Glass 	ut_asserteq(5, parent_data->sum);
226e59f458dSSimon Glass 	device_remove(dev);
227e59f458dSSimon Glass 	ut_asserteq_ptr(NULL, dev_get_parentdata(dev));
228e59f458dSSimon Glass 
229e59f458dSSimon Glass 	/* Check that we can do this twice */
230e59f458dSSimon Glass 	ut_assertok(device_get_child_by_seq(bus, 0, &dev));
231e59f458dSSimon Glass 	parent_data = dev_get_parentdata(dev);
232e59f458dSSimon Glass 	ut_assert(NULL != parent_data);
233e59f458dSSimon Glass 	parent_data->sum += 5;
234e59f458dSSimon Glass 	ut_asserteq(5, parent_data->sum);
235e59f458dSSimon Glass 
236e59f458dSSimon Glass 	/* Add parent data to all children */
237e59f458dSSimon Glass 	ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc));
238e59f458dSSimon Glass 	value = 5;
239e59f458dSSimon Glass 	uclass_foreach_dev(dev, uc) {
240e59f458dSSimon Glass 		/* Ignore these if they are not on this bus */
241e59f458dSSimon Glass 		if (dev->parent != bus) {
242e59f458dSSimon Glass 			ut_asserteq_ptr(NULL, dev_get_parentdata(dev));
243e59f458dSSimon Glass 			continue;
244e59f458dSSimon Glass 		}
245e59f458dSSimon Glass 		ut_assertok(device_probe(dev));
246e59f458dSSimon Glass 		parent_data = dev_get_parentdata(dev);
247e59f458dSSimon Glass 
248e59f458dSSimon Glass 		parent_data->sum = value;
249e59f458dSSimon Glass 		value += 5;
250e59f458dSSimon Glass 	}
251e59f458dSSimon Glass 
252e59f458dSSimon Glass 	/* Check it is still there */
253e59f458dSSimon Glass 	value = 5;
254e59f458dSSimon Glass 	uclass_foreach_dev(dev, uc) {
255e59f458dSSimon Glass 		/* Ignore these if they are not on this bus */
256e59f458dSSimon Glass 		if (dev->parent != bus)
257e59f458dSSimon Glass 			continue;
258e59f458dSSimon Glass 		parent_data = dev_get_parentdata(dev);
259e59f458dSSimon Glass 
260e59f458dSSimon Glass 		ut_asserteq(value, parent_data->sum);
261e59f458dSSimon Glass 		value += 5;
262e59f458dSSimon Glass 	}
263e59f458dSSimon Glass 
264e59f458dSSimon Glass 	return 0;
265e59f458dSSimon Glass }
266dac8db2cSSimon Glass /* Test that the bus can store data about each child */
267*e721b882SJoe Hershberger static int dm_test_bus_parent_data(struct unit_test_state *uts)
268dac8db2cSSimon Glass {
269*e721b882SJoe Hershberger 	return test_bus_parent_data(uts);
270dac8db2cSSimon Glass }
271e59f458dSSimon Glass DM_TEST(dm_test_bus_parent_data, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
272a327dee0SSimon Glass 
273dac8db2cSSimon Glass /* As above but the size is controlled by the uclass */
274*e721b882SJoe Hershberger static int dm_test_bus_parent_data_uclass(struct unit_test_state *uts)
275dac8db2cSSimon Glass {
276e23eb614SSimon Glass 	struct driver *drv;
277dac8db2cSSimon Glass 	struct udevice *bus;
278dac8db2cSSimon Glass 	int size;
279dac8db2cSSimon Glass 	int ret;
280dac8db2cSSimon Glass 
281dac8db2cSSimon Glass 	/* Set the driver size to 0 so that the uclass size is used */
282dac8db2cSSimon Glass 	ut_assertok(uclass_find_device(UCLASS_TEST_BUS, 0, &bus));
283e23eb614SSimon Glass 	drv = (struct driver *)bus->driver;
284e23eb614SSimon Glass 	size = drv->per_child_auto_alloc_size;
285dac8db2cSSimon Glass 	bus->uclass->uc_drv->per_child_auto_alloc_size = size;
286e23eb614SSimon Glass 	drv->per_child_auto_alloc_size = 0;
287*e721b882SJoe Hershberger 	ret = test_bus_parent_data(uts);
288dac8db2cSSimon Glass 	if (ret)
289dac8db2cSSimon Glass 		return ret;
290dac8db2cSSimon Glass 	bus->uclass->uc_drv->per_child_auto_alloc_size = 0;
291e23eb614SSimon Glass 	drv->per_child_auto_alloc_size = size;
292dac8db2cSSimon Glass 
293dac8db2cSSimon Glass 	return 0;
294dac8db2cSSimon Glass }
295dac8db2cSSimon Glass DM_TEST(dm_test_bus_parent_data_uclass,
296dac8db2cSSimon Glass 	DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
297dac8db2cSSimon Glass 
298a327dee0SSimon Glass /* Test that the bus ops are called when a child is probed/removed */
299*e721b882SJoe Hershberger static int dm_test_bus_parent_ops(struct unit_test_state *uts)
300a327dee0SSimon Glass {
301a327dee0SSimon Glass 	struct dm_test_parent_data *parent_data;
302*e721b882SJoe Hershberger 	struct dm_test_state *dms = uts->priv;
303a327dee0SSimon Glass 	struct udevice *bus, *dev;
304a327dee0SSimon Glass 	struct uclass *uc;
305a327dee0SSimon Glass 
306a327dee0SSimon Glass 	test_state = dms;
307a327dee0SSimon Glass 	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
308a327dee0SSimon Glass 	ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc));
309a327dee0SSimon Glass 
310a327dee0SSimon Glass 	uclass_foreach_dev(dev, uc) {
311a327dee0SSimon Glass 		/* Ignore these if they are not on this bus */
312a327dee0SSimon Glass 		if (dev->parent != bus)
313a327dee0SSimon Glass 			continue;
314a327dee0SSimon Glass 		ut_asserteq_ptr(NULL, dev_get_parentdata(dev));
315a327dee0SSimon Glass 
316a327dee0SSimon Glass 		ut_assertok(device_probe(dev));
317a327dee0SSimon Glass 		parent_data = dev_get_parentdata(dev);
318a327dee0SSimon Glass 		ut_asserteq(FLAG_CHILD_PROBED, parent_data->flag);
319a327dee0SSimon Glass 	}
320a327dee0SSimon Glass 
321a327dee0SSimon Glass 	uclass_foreach_dev(dev, uc) {
322a327dee0SSimon Glass 		/* Ignore these if they are not on this bus */
323a327dee0SSimon Glass 		if (dev->parent != bus)
324a327dee0SSimon Glass 			continue;
325a327dee0SSimon Glass 		parent_data = dev_get_parentdata(dev);
326a327dee0SSimon Glass 		ut_asserteq(FLAG_CHILD_PROBED, parent_data->flag);
327a327dee0SSimon Glass 		ut_assertok(device_remove(dev));
328a327dee0SSimon Glass 		ut_asserteq_ptr(NULL, dev_get_parentdata(dev));
329a327dee0SSimon Glass 		ut_asserteq_ptr(dms->removed, dev);
330a327dee0SSimon Glass 	}
331a327dee0SSimon Glass 	test_state = NULL;
332a327dee0SSimon Glass 
333a327dee0SSimon Glass 	return 0;
334a327dee0SSimon Glass }
335a327dee0SSimon Glass DM_TEST(dm_test_bus_parent_ops, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
336cdc133bdSSimon Glass 
337*e721b882SJoe Hershberger static int test_bus_parent_platdata(struct unit_test_state *uts)
338cdc133bdSSimon Glass {
339cdc133bdSSimon Glass 	struct dm_test_parent_platdata *plat;
340cdc133bdSSimon Glass 	struct udevice *bus, *dev;
341cdc133bdSSimon Glass 	int child_count;
342cdc133bdSSimon Glass 
343cdc133bdSSimon Glass 	/* Check that the bus has no children */
344cdc133bdSSimon Glass 	ut_assertok(uclass_find_device(UCLASS_TEST_BUS, 0, &bus));
345cdc133bdSSimon Glass 	device_find_first_child(bus, &dev);
346cdc133bdSSimon Glass 	ut_asserteq_ptr(NULL, dev);
347cdc133bdSSimon Glass 
348cdc133bdSSimon Glass 	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
349cdc133bdSSimon Glass 
350cdc133bdSSimon Glass 	for (device_find_first_child(bus, &dev), child_count = 0;
351cdc133bdSSimon Glass 	     dev;
352cdc133bdSSimon Glass 	     device_find_next_child(&dev)) {
353cdc133bdSSimon Glass 		/* Check that platform data is allocated */
354cdc133bdSSimon Glass 		plat = dev_get_parent_platdata(dev);
355cdc133bdSSimon Glass 		ut_assert(plat != NULL);
356cdc133bdSSimon Glass 
357cdc133bdSSimon Glass 		/*
358cdc133bdSSimon Glass 		 * Check that it is not affected by the device being
359cdc133bdSSimon Glass 		 * probed/removed
360cdc133bdSSimon Glass 		 */
361cdc133bdSSimon Glass 		plat->count++;
362cdc133bdSSimon Glass 		ut_asserteq(1, plat->count);
363cdc133bdSSimon Glass 		device_probe(dev);
364cdc133bdSSimon Glass 		device_remove(dev);
365cdc133bdSSimon Glass 
366cdc133bdSSimon Glass 		ut_asserteq_ptr(plat, dev_get_parent_platdata(dev));
367cdc133bdSSimon Glass 		ut_asserteq(1, plat->count);
368cdc133bdSSimon Glass 		ut_assertok(device_probe(dev));
369cdc133bdSSimon Glass 		child_count++;
370cdc133bdSSimon Glass 	}
371cdc133bdSSimon Glass 	ut_asserteq(3, child_count);
372cdc133bdSSimon Glass 
373cdc133bdSSimon Glass 	/* Removing the bus should also have no effect (it is still bound) */
374cdc133bdSSimon Glass 	device_remove(bus);
375cdc133bdSSimon Glass 	for (device_find_first_child(bus, &dev), child_count = 0;
376cdc133bdSSimon Glass 	     dev;
377cdc133bdSSimon Glass 	     device_find_next_child(&dev)) {
378cdc133bdSSimon Glass 		/* Check that platform data is allocated */
379cdc133bdSSimon Glass 		plat = dev_get_parent_platdata(dev);
380cdc133bdSSimon Glass 		ut_assert(plat != NULL);
381cdc133bdSSimon Glass 		ut_asserteq(1, plat->count);
382cdc133bdSSimon Glass 		child_count++;
383cdc133bdSSimon Glass 	}
384cdc133bdSSimon Glass 	ut_asserteq(3, child_count);
385cdc133bdSSimon Glass 
386cdc133bdSSimon Glass 	/* Unbind all the children */
387cdc133bdSSimon Glass 	do {
388cdc133bdSSimon Glass 		device_find_first_child(bus, &dev);
389cdc133bdSSimon Glass 		if (dev)
390cdc133bdSSimon Glass 			device_unbind(dev);
391cdc133bdSSimon Glass 	} while (dev);
392cdc133bdSSimon Glass 
393cdc133bdSSimon Glass 	/* Now the child platdata should be removed and re-added */
394cdc133bdSSimon Glass 	device_probe(bus);
395cdc133bdSSimon Glass 	for (device_find_first_child(bus, &dev), child_count = 0;
396cdc133bdSSimon Glass 	     dev;
397cdc133bdSSimon Glass 	     device_find_next_child(&dev)) {
398cdc133bdSSimon Glass 		/* Check that platform data is allocated */
399cdc133bdSSimon Glass 		plat = dev_get_parent_platdata(dev);
400cdc133bdSSimon Glass 		ut_assert(plat != NULL);
401cdc133bdSSimon Glass 		ut_asserteq(0, plat->count);
402cdc133bdSSimon Glass 		child_count++;
403cdc133bdSSimon Glass 	}
404cdc133bdSSimon Glass 	ut_asserteq(3, child_count);
405cdc133bdSSimon Glass 
406cdc133bdSSimon Glass 	return 0;
407cdc133bdSSimon Glass }
408ba8da9dcSSimon Glass 
409ba8da9dcSSimon Glass /* Test that the bus can store platform data about each child */
410*e721b882SJoe Hershberger static int dm_test_bus_parent_platdata(struct unit_test_state *uts)
411ba8da9dcSSimon Glass {
412*e721b882SJoe Hershberger 	return test_bus_parent_platdata(uts);
413ba8da9dcSSimon Glass }
414cdc133bdSSimon Glass DM_TEST(dm_test_bus_parent_platdata, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
415ba8da9dcSSimon Glass 
416ba8da9dcSSimon Glass /* As above but the size is controlled by the uclass */
417*e721b882SJoe Hershberger static int dm_test_bus_parent_platdata_uclass(struct unit_test_state *uts)
418ba8da9dcSSimon Glass {
419ba8da9dcSSimon Glass 	struct udevice *bus;
420e23eb614SSimon Glass 	struct driver *drv;
421ba8da9dcSSimon Glass 	int size;
422ba8da9dcSSimon Glass 	int ret;
423ba8da9dcSSimon Glass 
424ba8da9dcSSimon Glass 	/* Set the driver size to 0 so that the uclass size is used */
425ba8da9dcSSimon Glass 	ut_assertok(uclass_find_device(UCLASS_TEST_BUS, 0, &bus));
426e23eb614SSimon Glass 	drv = (struct driver *)bus->driver;
427e23eb614SSimon Glass 	size = drv->per_child_platdata_auto_alloc_size;
428ba8da9dcSSimon Glass 	bus->uclass->uc_drv->per_child_platdata_auto_alloc_size = size;
429e23eb614SSimon Glass 	drv->per_child_platdata_auto_alloc_size = 0;
430*e721b882SJoe Hershberger 	ret = test_bus_parent_platdata(uts);
431ba8da9dcSSimon Glass 	if (ret)
432ba8da9dcSSimon Glass 		return ret;
433ba8da9dcSSimon Glass 	bus->uclass->uc_drv->per_child_platdata_auto_alloc_size = 0;
434e23eb614SSimon Glass 	drv->per_child_platdata_auto_alloc_size = size;
435ba8da9dcSSimon Glass 
436ba8da9dcSSimon Glass 	return 0;
437ba8da9dcSSimon Glass }
438ba8da9dcSSimon Glass DM_TEST(dm_test_bus_parent_platdata_uclass,
439ba8da9dcSSimon Glass 	DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
4400118ce79SSimon Glass 
4410118ce79SSimon Glass /* Test that the child post_bind method is called */
442*e721b882SJoe Hershberger static int dm_test_bus_child_post_bind(struct unit_test_state *uts)
4430118ce79SSimon Glass {
4440118ce79SSimon Glass 	struct dm_test_parent_platdata *plat;
4450118ce79SSimon Glass 	struct udevice *bus, *dev;
4460118ce79SSimon Glass 	int child_count;
4470118ce79SSimon Glass 
4480118ce79SSimon Glass 	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
4490118ce79SSimon Glass 	for (device_find_first_child(bus, &dev), child_count = 0;
4500118ce79SSimon Glass 	     dev;
4510118ce79SSimon Glass 	     device_find_next_child(&dev)) {
4520118ce79SSimon Glass 		/* Check that platform data is allocated */
4530118ce79SSimon Glass 		plat = dev_get_parent_platdata(dev);
4540118ce79SSimon Glass 		ut_assert(plat != NULL);
4550118ce79SSimon Glass 		ut_asserteq(1, plat->bind_flag);
4560118ce79SSimon Glass 		child_count++;
4570118ce79SSimon Glass 	}
4580118ce79SSimon Glass 	ut_asserteq(3, child_count);
4590118ce79SSimon Glass 
4600118ce79SSimon Glass 	return 0;
4610118ce79SSimon Glass }
4620118ce79SSimon Glass DM_TEST(dm_test_bus_child_post_bind, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
463081f2fcbSSimon Glass 
464081f2fcbSSimon Glass /* Test that the child post_bind method is called */
465*e721b882SJoe Hershberger static int dm_test_bus_child_post_bind_uclass(struct unit_test_state *uts)
466081f2fcbSSimon Glass {
467081f2fcbSSimon Glass 	struct dm_test_parent_platdata *plat;
468081f2fcbSSimon Glass 	struct udevice *bus, *dev;
469081f2fcbSSimon Glass 	int child_count;
470081f2fcbSSimon Glass 
471081f2fcbSSimon Glass 	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
472081f2fcbSSimon Glass 	for (device_find_first_child(bus, &dev), child_count = 0;
473081f2fcbSSimon Glass 	     dev;
474081f2fcbSSimon Glass 	     device_find_next_child(&dev)) {
475081f2fcbSSimon Glass 		/* Check that platform data is allocated */
476081f2fcbSSimon Glass 		plat = dev_get_parent_platdata(dev);
477081f2fcbSSimon Glass 		ut_assert(plat != NULL);
478081f2fcbSSimon Glass 		ut_asserteq(2, plat->uclass_bind_flag);
479081f2fcbSSimon Glass 		child_count++;
480081f2fcbSSimon Glass 	}
481081f2fcbSSimon Glass 	ut_asserteq(3, child_count);
482081f2fcbSSimon Glass 
483081f2fcbSSimon Glass 	return 0;
484081f2fcbSSimon Glass }
485081f2fcbSSimon Glass DM_TEST(dm_test_bus_child_post_bind_uclass,
486081f2fcbSSimon Glass 	DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
48783c7e434SSimon Glass 
48883c7e434SSimon Glass /*
48983c7e434SSimon Glass  * Test that the bus' uclass' child_pre_probe() is called before the
49083c7e434SSimon Glass  * device's probe() method
49183c7e434SSimon Glass  */
492*e721b882SJoe Hershberger static int dm_test_bus_child_pre_probe_uclass(struct unit_test_state *uts)
49383c7e434SSimon Glass {
49483c7e434SSimon Glass 	struct udevice *bus, *dev;
49583c7e434SSimon Glass 	int child_count;
49683c7e434SSimon Glass 
49783c7e434SSimon Glass 	/*
49883c7e434SSimon Glass 	 * See testfdt_drv_probe() which effectively checks that the uclass
49983c7e434SSimon Glass 	 * flag is set before that method is called
50083c7e434SSimon Glass 	 */
50183c7e434SSimon Glass 	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
50283c7e434SSimon Glass 	for (device_find_first_child(bus, &dev), child_count = 0;
50383c7e434SSimon Glass 	     dev;
50483c7e434SSimon Glass 	     device_find_next_child(&dev)) {
50583c7e434SSimon Glass 		struct dm_test_priv *priv = dev_get_priv(dev);
50683c7e434SSimon Glass 
50783c7e434SSimon Glass 		/* Check that things happened in the right order */
50883c7e434SSimon Glass 		ut_asserteq_ptr(NULL, priv);
50983c7e434SSimon Glass 		ut_assertok(device_probe(dev));
51083c7e434SSimon Glass 
51183c7e434SSimon Glass 		priv = dev_get_priv(dev);
51283c7e434SSimon Glass 		ut_assert(priv != NULL);
51383c7e434SSimon Glass 		ut_asserteq(1, priv->uclass_flag);
51483c7e434SSimon Glass 		ut_asserteq(1, priv->uclass_total);
51583c7e434SSimon Glass 		child_count++;
51683c7e434SSimon Glass 	}
51783c7e434SSimon Glass 	ut_asserteq(3, child_count);
51883c7e434SSimon Glass 
51983c7e434SSimon Glass 	return 0;
52083c7e434SSimon Glass }
52183c7e434SSimon Glass DM_TEST(dm_test_bus_child_pre_probe_uclass,
52283c7e434SSimon Glass 	DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
523