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