xref: /rk3399_rockchip-uboot/test/dm/bus.c (revision 4f414d392fb5d7c4ac547c4ee9f02b81648c00dd)
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 
testbus_drv_probe(struct udevice * dev)301ca7e206SSimon Glass static int testbus_drv_probe(struct udevice *dev)
311ca7e206SSimon Glass {
322e3f1ff6SSimon Glass 	return dm_scan_fdt_dev(dev);
331ca7e206SSimon Glass }
341ca7e206SSimon Glass 
testbus_child_post_bind(struct udevice * dev)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 
testbus_child_pre_probe(struct udevice * dev)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 
testbus_child_pre_probe_uclass(struct udevice * dev)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 
testbus_child_post_remove(struct udevice * dev)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 */
dm_test_bus_children(struct unit_test_state * uts)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 */
dm_test_bus_children_funcs(struct unit_test_state * uts)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 
163298afb52SSimon Glass 	return 0;
164298afb52SSimon Glass }
165298afb52SSimon Glass DM_TEST(dm_test_bus_children_funcs, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
166298afb52SSimon Glass 
dm_test_bus_children_of_offset(struct unit_test_state * uts)167298afb52SSimon Glass static int dm_test_bus_children_of_offset(struct unit_test_state *uts)
168298afb52SSimon Glass {
169298afb52SSimon Glass 	const void *blob = gd->fdt_blob;
170298afb52SSimon Glass 	struct udevice *bus, *dev;
171298afb52SSimon Glass 	int node;
172298afb52SSimon Glass 
173298afb52SSimon Glass 	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
174*4f414d39SSimon Glass 	ut_assertnonnull(bus);
175298afb52SSimon Glass 
176997c87bbSSimon Glass 	/* Find a valid child */
177997c87bbSSimon Glass 	node = fdt_path_offset(blob, "/some-bus/c-test@1");
178298afb52SSimon Glass 	ut_assert(node > 0);
179997c87bbSSimon Glass 	ut_assertok(device_find_child_by_of_offset(bus, node, &dev));
180*4f414d39SSimon Glass 	ut_assertnonnull(dev);
181997c87bbSSimon Glass 	ut_assert(!(dev->flags & DM_FLAG_ACTIVATED));
182997c87bbSSimon Glass 	ut_assertok(device_get_child_by_of_offset(bus, node, &dev));
183*4f414d39SSimon Glass 	ut_assertnonnull(dev);
184997c87bbSSimon Glass 	ut_assert(dev->flags & DM_FLAG_ACTIVATED);
185997c87bbSSimon Glass 
186997c87bbSSimon Glass 	return 0;
187997c87bbSSimon Glass }
188298afb52SSimon Glass DM_TEST(dm_test_bus_children_of_offset,
189298afb52SSimon Glass 	DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT | DM_TESTF_FLAT_TREE);
190e59f458dSSimon Glass 
191a8981d4fSSimon Glass /* Test that we can iterate through children */
dm_test_bus_children_iterators(struct unit_test_state * uts)192e721b882SJoe Hershberger static int dm_test_bus_children_iterators(struct unit_test_state *uts)
193a8981d4fSSimon Glass {
194a8981d4fSSimon Glass 	struct udevice *bus, *dev, *child;
195a8981d4fSSimon Glass 
196a8981d4fSSimon Glass 	/* Walk through the children one by one */
197a8981d4fSSimon Glass 	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
198a8981d4fSSimon Glass 	ut_assertok(device_find_first_child(bus, &dev));
199a8981d4fSSimon Glass 	ut_asserteq_str("c-test@5", dev->name);
200a8981d4fSSimon Glass 	ut_assertok(device_find_next_child(&dev));
201a8981d4fSSimon Glass 	ut_asserteq_str("c-test@0", dev->name);
202a8981d4fSSimon Glass 	ut_assertok(device_find_next_child(&dev));
203a8981d4fSSimon Glass 	ut_asserteq_str("c-test@1", dev->name);
204a8981d4fSSimon Glass 	ut_assertok(device_find_next_child(&dev));
205a8981d4fSSimon Glass 	ut_asserteq_ptr(dev, NULL);
206a8981d4fSSimon Glass 
207a8981d4fSSimon Glass 	/* Move to the next child without using device_find_first_child() */
208a8981d4fSSimon Glass 	ut_assertok(device_find_child_by_seq(bus, 5, true, &dev));
209a8981d4fSSimon Glass 	ut_asserteq_str("c-test@5", dev->name);
210a8981d4fSSimon Glass 	ut_assertok(device_find_next_child(&dev));
211a8981d4fSSimon Glass 	ut_asserteq_str("c-test@0", dev->name);
212a8981d4fSSimon Glass 
213a8981d4fSSimon Glass 	/* Try a device with no children */
214a8981d4fSSimon Glass 	ut_assertok(device_find_first_child(dev, &child));
215a8981d4fSSimon Glass 	ut_asserteq_ptr(child, NULL);
216a8981d4fSSimon Glass 
217a8981d4fSSimon Glass 	return 0;
218a8981d4fSSimon Glass }
219a8981d4fSSimon Glass DM_TEST(dm_test_bus_children_iterators,
220a8981d4fSSimon Glass 	DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
221a8981d4fSSimon Glass 
222e59f458dSSimon Glass /* Test that the bus can store data about each child */
test_bus_parent_data(struct unit_test_state * uts)223e721b882SJoe Hershberger static int test_bus_parent_data(struct unit_test_state *uts)
224e59f458dSSimon Glass {
225e59f458dSSimon Glass 	struct dm_test_parent_data *parent_data;
226e59f458dSSimon Glass 	struct udevice *bus, *dev;
227e59f458dSSimon Glass 	struct uclass *uc;
228e59f458dSSimon Glass 	int value;
229e59f458dSSimon Glass 
230e59f458dSSimon Glass 	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
231e59f458dSSimon Glass 
232e59f458dSSimon Glass 	/* Check that parent data is allocated */
233e59f458dSSimon Glass 	ut_assertok(device_find_child_by_seq(bus, 0, true, &dev));
234bcbe3d15SSimon Glass 	ut_asserteq_ptr(NULL, dev_get_parent_priv(dev));
235e59f458dSSimon Glass 	ut_assertok(device_get_child_by_seq(bus, 0, &dev));
236bcbe3d15SSimon Glass 	parent_data = dev_get_parent_priv(dev);
237e59f458dSSimon Glass 	ut_assert(NULL != parent_data);
238e59f458dSSimon Glass 
239e59f458dSSimon Glass 	/* Check that it starts at 0 and goes away when device is removed */
240e59f458dSSimon Glass 	parent_data->sum += 5;
241e59f458dSSimon Glass 	ut_asserteq(5, parent_data->sum);
242706865afSStefan Roese 	device_remove(dev, DM_REMOVE_NORMAL);
243bcbe3d15SSimon Glass 	ut_asserteq_ptr(NULL, dev_get_parent_priv(dev));
244e59f458dSSimon Glass 
245e59f458dSSimon Glass 	/* Check that we can do this twice */
246e59f458dSSimon Glass 	ut_assertok(device_get_child_by_seq(bus, 0, &dev));
247bcbe3d15SSimon Glass 	parent_data = dev_get_parent_priv(dev);
248e59f458dSSimon Glass 	ut_assert(NULL != parent_data);
249e59f458dSSimon Glass 	parent_data->sum += 5;
250e59f458dSSimon Glass 	ut_asserteq(5, parent_data->sum);
251e59f458dSSimon Glass 
252e59f458dSSimon Glass 	/* Add parent data to all children */
253e59f458dSSimon Glass 	ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc));
254e59f458dSSimon Glass 	value = 5;
255e59f458dSSimon Glass 	uclass_foreach_dev(dev, uc) {
256e59f458dSSimon Glass 		/* Ignore these if they are not on this bus */
257e59f458dSSimon Glass 		if (dev->parent != bus) {
258bcbe3d15SSimon Glass 			ut_asserteq_ptr(NULL, dev_get_parent_priv(dev));
259e59f458dSSimon Glass 			continue;
260e59f458dSSimon Glass 		}
261e59f458dSSimon Glass 		ut_assertok(device_probe(dev));
262bcbe3d15SSimon Glass 		parent_data = dev_get_parent_priv(dev);
263e59f458dSSimon Glass 
264e59f458dSSimon Glass 		parent_data->sum = value;
265e59f458dSSimon Glass 		value += 5;
266e59f458dSSimon Glass 	}
267e59f458dSSimon Glass 
268e59f458dSSimon Glass 	/* Check it is still there */
269e59f458dSSimon Glass 	value = 5;
270e59f458dSSimon Glass 	uclass_foreach_dev(dev, uc) {
271e59f458dSSimon Glass 		/* Ignore these if they are not on this bus */
272e59f458dSSimon Glass 		if (dev->parent != bus)
273e59f458dSSimon Glass 			continue;
274bcbe3d15SSimon Glass 		parent_data = dev_get_parent_priv(dev);
275e59f458dSSimon Glass 
276e59f458dSSimon Glass 		ut_asserteq(value, parent_data->sum);
277e59f458dSSimon Glass 		value += 5;
278e59f458dSSimon Glass 	}
279e59f458dSSimon Glass 
280e59f458dSSimon Glass 	return 0;
281e59f458dSSimon Glass }
282dac8db2cSSimon Glass /* Test that the bus can store data about each child */
dm_test_bus_parent_data(struct unit_test_state * uts)283e721b882SJoe Hershberger static int dm_test_bus_parent_data(struct unit_test_state *uts)
284dac8db2cSSimon Glass {
285e721b882SJoe Hershberger 	return test_bus_parent_data(uts);
286dac8db2cSSimon Glass }
287e59f458dSSimon Glass DM_TEST(dm_test_bus_parent_data, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
288a327dee0SSimon Glass 
289dac8db2cSSimon Glass /* As above but the size is controlled by the uclass */
dm_test_bus_parent_data_uclass(struct unit_test_state * uts)290e721b882SJoe Hershberger static int dm_test_bus_parent_data_uclass(struct unit_test_state *uts)
291dac8db2cSSimon Glass {
292e23eb614SSimon Glass 	struct driver *drv;
293dac8db2cSSimon Glass 	struct udevice *bus;
294dac8db2cSSimon Glass 	int size;
295dac8db2cSSimon Glass 	int ret;
296dac8db2cSSimon Glass 
297dac8db2cSSimon Glass 	/* Set the driver size to 0 so that the uclass size is used */
298dac8db2cSSimon Glass 	ut_assertok(uclass_find_device(UCLASS_TEST_BUS, 0, &bus));
299e23eb614SSimon Glass 	drv = (struct driver *)bus->driver;
300e23eb614SSimon Glass 	size = drv->per_child_auto_alloc_size;
301dac8db2cSSimon Glass 	bus->uclass->uc_drv->per_child_auto_alloc_size = size;
302e23eb614SSimon Glass 	drv->per_child_auto_alloc_size = 0;
303e721b882SJoe Hershberger 	ret = test_bus_parent_data(uts);
304dac8db2cSSimon Glass 	if (ret)
305dac8db2cSSimon Glass 		return ret;
306dac8db2cSSimon Glass 	bus->uclass->uc_drv->per_child_auto_alloc_size = 0;
307e23eb614SSimon Glass 	drv->per_child_auto_alloc_size = size;
308dac8db2cSSimon Glass 
309dac8db2cSSimon Glass 	return 0;
310dac8db2cSSimon Glass }
311dac8db2cSSimon Glass DM_TEST(dm_test_bus_parent_data_uclass,
312dac8db2cSSimon Glass 	DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
313dac8db2cSSimon Glass 
314a327dee0SSimon Glass /* Test that the bus ops are called when a child is probed/removed */
dm_test_bus_parent_ops(struct unit_test_state * uts)315e721b882SJoe Hershberger static int dm_test_bus_parent_ops(struct unit_test_state *uts)
316a327dee0SSimon Glass {
317a327dee0SSimon Glass 	struct dm_test_parent_data *parent_data;
318e721b882SJoe Hershberger 	struct dm_test_state *dms = uts->priv;
319a327dee0SSimon Glass 	struct udevice *bus, *dev;
320a327dee0SSimon Glass 	struct uclass *uc;
321a327dee0SSimon Glass 
322a327dee0SSimon Glass 	test_state = dms;
323a327dee0SSimon Glass 	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
324a327dee0SSimon Glass 	ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc));
325a327dee0SSimon Glass 
326a327dee0SSimon Glass 	uclass_foreach_dev(dev, uc) {
327a327dee0SSimon Glass 		/* Ignore these if they are not on this bus */
328a327dee0SSimon Glass 		if (dev->parent != bus)
329a327dee0SSimon Glass 			continue;
330bcbe3d15SSimon Glass 		ut_asserteq_ptr(NULL, dev_get_parent_priv(dev));
331a327dee0SSimon Glass 
332a327dee0SSimon Glass 		ut_assertok(device_probe(dev));
333bcbe3d15SSimon Glass 		parent_data = dev_get_parent_priv(dev);
334a327dee0SSimon Glass 		ut_asserteq(FLAG_CHILD_PROBED, parent_data->flag);
335a327dee0SSimon Glass 	}
336a327dee0SSimon Glass 
337a327dee0SSimon Glass 	uclass_foreach_dev(dev, uc) {
338a327dee0SSimon Glass 		/* Ignore these if they are not on this bus */
339a327dee0SSimon Glass 		if (dev->parent != bus)
340a327dee0SSimon Glass 			continue;
341bcbe3d15SSimon Glass 		parent_data = dev_get_parent_priv(dev);
342a327dee0SSimon Glass 		ut_asserteq(FLAG_CHILD_PROBED, parent_data->flag);
343706865afSStefan Roese 		ut_assertok(device_remove(dev, DM_REMOVE_NORMAL));
344bcbe3d15SSimon Glass 		ut_asserteq_ptr(NULL, dev_get_parent_priv(dev));
345a327dee0SSimon Glass 		ut_asserteq_ptr(dms->removed, dev);
346a327dee0SSimon Glass 	}
347a327dee0SSimon Glass 	test_state = NULL;
348a327dee0SSimon Glass 
349a327dee0SSimon Glass 	return 0;
350a327dee0SSimon Glass }
351a327dee0SSimon Glass DM_TEST(dm_test_bus_parent_ops, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
352cdc133bdSSimon Glass 
test_bus_parent_platdata(struct unit_test_state * uts)353e721b882SJoe Hershberger static int test_bus_parent_platdata(struct unit_test_state *uts)
354cdc133bdSSimon Glass {
355cdc133bdSSimon Glass 	struct dm_test_parent_platdata *plat;
356cdc133bdSSimon Glass 	struct udevice *bus, *dev;
357cdc133bdSSimon Glass 	int child_count;
358cdc133bdSSimon Glass 
359cdc133bdSSimon Glass 	/* Check that the bus has no children */
360cdc133bdSSimon Glass 	ut_assertok(uclass_find_device(UCLASS_TEST_BUS, 0, &bus));
361cdc133bdSSimon Glass 	device_find_first_child(bus, &dev);
362cdc133bdSSimon Glass 	ut_asserteq_ptr(NULL, dev);
363cdc133bdSSimon Glass 
364cdc133bdSSimon Glass 	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
365cdc133bdSSimon Glass 
366cdc133bdSSimon Glass 	for (device_find_first_child(bus, &dev), child_count = 0;
367cdc133bdSSimon Glass 	     dev;
368cdc133bdSSimon Glass 	     device_find_next_child(&dev)) {
369cdc133bdSSimon Glass 		/* Check that platform data is allocated */
370cdc133bdSSimon Glass 		plat = dev_get_parent_platdata(dev);
371cdc133bdSSimon Glass 		ut_assert(plat != NULL);
372cdc133bdSSimon Glass 
373cdc133bdSSimon Glass 		/*
374cdc133bdSSimon Glass 		 * Check that it is not affected by the device being
375cdc133bdSSimon Glass 		 * probed/removed
376cdc133bdSSimon Glass 		 */
377cdc133bdSSimon Glass 		plat->count++;
378cdc133bdSSimon Glass 		ut_asserteq(1, plat->count);
379cdc133bdSSimon Glass 		device_probe(dev);
380706865afSStefan Roese 		device_remove(dev, DM_REMOVE_NORMAL);
381cdc133bdSSimon Glass 
382cdc133bdSSimon Glass 		ut_asserteq_ptr(plat, dev_get_parent_platdata(dev));
383cdc133bdSSimon Glass 		ut_asserteq(1, plat->count);
384cdc133bdSSimon Glass 		ut_assertok(device_probe(dev));
385cdc133bdSSimon Glass 		child_count++;
386cdc133bdSSimon Glass 	}
387cdc133bdSSimon Glass 	ut_asserteq(3, child_count);
388cdc133bdSSimon Glass 
389cdc133bdSSimon Glass 	/* Removing the bus should also have no effect (it is still bound) */
390706865afSStefan Roese 	device_remove(bus, DM_REMOVE_NORMAL);
391cdc133bdSSimon Glass 	for (device_find_first_child(bus, &dev), child_count = 0;
392cdc133bdSSimon Glass 	     dev;
393cdc133bdSSimon Glass 	     device_find_next_child(&dev)) {
394cdc133bdSSimon Glass 		/* Check that platform data is allocated */
395cdc133bdSSimon Glass 		plat = dev_get_parent_platdata(dev);
396cdc133bdSSimon Glass 		ut_assert(plat != NULL);
397cdc133bdSSimon Glass 		ut_asserteq(1, plat->count);
398cdc133bdSSimon Glass 		child_count++;
399cdc133bdSSimon Glass 	}
400cdc133bdSSimon Glass 	ut_asserteq(3, child_count);
401cdc133bdSSimon Glass 
402cdc133bdSSimon Glass 	/* Unbind all the children */
403cdc133bdSSimon Glass 	do {
404cdc133bdSSimon Glass 		device_find_first_child(bus, &dev);
405cdc133bdSSimon Glass 		if (dev)
406cdc133bdSSimon Glass 			device_unbind(dev);
407cdc133bdSSimon Glass 	} while (dev);
408cdc133bdSSimon Glass 
409cdc133bdSSimon Glass 	/* Now the child platdata should be removed and re-added */
410cdc133bdSSimon Glass 	device_probe(bus);
411cdc133bdSSimon Glass 	for (device_find_first_child(bus, &dev), child_count = 0;
412cdc133bdSSimon Glass 	     dev;
413cdc133bdSSimon Glass 	     device_find_next_child(&dev)) {
414cdc133bdSSimon Glass 		/* Check that platform data is allocated */
415cdc133bdSSimon Glass 		plat = dev_get_parent_platdata(dev);
416cdc133bdSSimon Glass 		ut_assert(plat != NULL);
417cdc133bdSSimon Glass 		ut_asserteq(0, plat->count);
418cdc133bdSSimon Glass 		child_count++;
419cdc133bdSSimon Glass 	}
420cdc133bdSSimon Glass 	ut_asserteq(3, child_count);
421cdc133bdSSimon Glass 
422cdc133bdSSimon Glass 	return 0;
423cdc133bdSSimon Glass }
424ba8da9dcSSimon Glass 
425ba8da9dcSSimon Glass /* Test that the bus can store platform data about each child */
dm_test_bus_parent_platdata(struct unit_test_state * uts)426e721b882SJoe Hershberger static int dm_test_bus_parent_platdata(struct unit_test_state *uts)
427ba8da9dcSSimon Glass {
428e721b882SJoe Hershberger 	return test_bus_parent_platdata(uts);
429ba8da9dcSSimon Glass }
430cdc133bdSSimon Glass DM_TEST(dm_test_bus_parent_platdata, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
431ba8da9dcSSimon Glass 
432ba8da9dcSSimon Glass /* As above but the size is controlled by the uclass */
dm_test_bus_parent_platdata_uclass(struct unit_test_state * uts)433e721b882SJoe Hershberger static int dm_test_bus_parent_platdata_uclass(struct unit_test_state *uts)
434ba8da9dcSSimon Glass {
435ba8da9dcSSimon Glass 	struct udevice *bus;
436e23eb614SSimon Glass 	struct driver *drv;
437ba8da9dcSSimon Glass 	int size;
438ba8da9dcSSimon Glass 	int ret;
439ba8da9dcSSimon Glass 
440ba8da9dcSSimon Glass 	/* Set the driver size to 0 so that the uclass size is used */
441ba8da9dcSSimon Glass 	ut_assertok(uclass_find_device(UCLASS_TEST_BUS, 0, &bus));
442e23eb614SSimon Glass 	drv = (struct driver *)bus->driver;
443e23eb614SSimon Glass 	size = drv->per_child_platdata_auto_alloc_size;
444ba8da9dcSSimon Glass 	bus->uclass->uc_drv->per_child_platdata_auto_alloc_size = size;
445e23eb614SSimon Glass 	drv->per_child_platdata_auto_alloc_size = 0;
446e721b882SJoe Hershberger 	ret = test_bus_parent_platdata(uts);
447ba8da9dcSSimon Glass 	if (ret)
448ba8da9dcSSimon Glass 		return ret;
449ba8da9dcSSimon Glass 	bus->uclass->uc_drv->per_child_platdata_auto_alloc_size = 0;
450e23eb614SSimon Glass 	drv->per_child_platdata_auto_alloc_size = size;
451ba8da9dcSSimon Glass 
452ba8da9dcSSimon Glass 	return 0;
453ba8da9dcSSimon Glass }
454ba8da9dcSSimon Glass DM_TEST(dm_test_bus_parent_platdata_uclass,
455ba8da9dcSSimon Glass 	DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
4560118ce79SSimon Glass 
4570118ce79SSimon Glass /* Test that the child post_bind method is called */
dm_test_bus_child_post_bind(struct unit_test_state * uts)458e721b882SJoe Hershberger static int dm_test_bus_child_post_bind(struct unit_test_state *uts)
4590118ce79SSimon Glass {
4600118ce79SSimon Glass 	struct dm_test_parent_platdata *plat;
4610118ce79SSimon Glass 	struct udevice *bus, *dev;
4620118ce79SSimon Glass 	int child_count;
4630118ce79SSimon Glass 
4640118ce79SSimon Glass 	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
4650118ce79SSimon Glass 	for (device_find_first_child(bus, &dev), child_count = 0;
4660118ce79SSimon Glass 	     dev;
4670118ce79SSimon Glass 	     device_find_next_child(&dev)) {
4680118ce79SSimon Glass 		/* Check that platform data is allocated */
4690118ce79SSimon Glass 		plat = dev_get_parent_platdata(dev);
4700118ce79SSimon Glass 		ut_assert(plat != NULL);
4710118ce79SSimon Glass 		ut_asserteq(1, plat->bind_flag);
4720118ce79SSimon Glass 		child_count++;
4730118ce79SSimon Glass 	}
4740118ce79SSimon Glass 	ut_asserteq(3, child_count);
4750118ce79SSimon Glass 
4760118ce79SSimon Glass 	return 0;
4770118ce79SSimon Glass }
4780118ce79SSimon Glass DM_TEST(dm_test_bus_child_post_bind, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
479081f2fcbSSimon Glass 
480081f2fcbSSimon Glass /* Test that the child post_bind method is called */
dm_test_bus_child_post_bind_uclass(struct unit_test_state * uts)481e721b882SJoe Hershberger static int dm_test_bus_child_post_bind_uclass(struct unit_test_state *uts)
482081f2fcbSSimon Glass {
483081f2fcbSSimon Glass 	struct dm_test_parent_platdata *plat;
484081f2fcbSSimon Glass 	struct udevice *bus, *dev;
485081f2fcbSSimon Glass 	int child_count;
486081f2fcbSSimon Glass 
487081f2fcbSSimon Glass 	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
488081f2fcbSSimon Glass 	for (device_find_first_child(bus, &dev), child_count = 0;
489081f2fcbSSimon Glass 	     dev;
490081f2fcbSSimon Glass 	     device_find_next_child(&dev)) {
491081f2fcbSSimon Glass 		/* Check that platform data is allocated */
492081f2fcbSSimon Glass 		plat = dev_get_parent_platdata(dev);
493081f2fcbSSimon Glass 		ut_assert(plat != NULL);
494081f2fcbSSimon Glass 		ut_asserteq(2, plat->uclass_bind_flag);
495081f2fcbSSimon Glass 		child_count++;
496081f2fcbSSimon Glass 	}
497081f2fcbSSimon Glass 	ut_asserteq(3, child_count);
498081f2fcbSSimon Glass 
499081f2fcbSSimon Glass 	return 0;
500081f2fcbSSimon Glass }
501081f2fcbSSimon Glass DM_TEST(dm_test_bus_child_post_bind_uclass,
502081f2fcbSSimon Glass 	DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
50383c7e434SSimon Glass 
50483c7e434SSimon Glass /*
50583c7e434SSimon Glass  * Test that the bus' uclass' child_pre_probe() is called before the
50683c7e434SSimon Glass  * device's probe() method
50783c7e434SSimon Glass  */
dm_test_bus_child_pre_probe_uclass(struct unit_test_state * uts)508e721b882SJoe Hershberger static int dm_test_bus_child_pre_probe_uclass(struct unit_test_state *uts)
50983c7e434SSimon Glass {
51083c7e434SSimon Glass 	struct udevice *bus, *dev;
51183c7e434SSimon Glass 	int child_count;
51283c7e434SSimon Glass 
51383c7e434SSimon Glass 	/*
51483c7e434SSimon Glass 	 * See testfdt_drv_probe() which effectively checks that the uclass
51583c7e434SSimon Glass 	 * flag is set before that method is called
51683c7e434SSimon Glass 	 */
51783c7e434SSimon Glass 	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
51883c7e434SSimon Glass 	for (device_find_first_child(bus, &dev), child_count = 0;
51983c7e434SSimon Glass 	     dev;
52083c7e434SSimon Glass 	     device_find_next_child(&dev)) {
52183c7e434SSimon Glass 		struct dm_test_priv *priv = dev_get_priv(dev);
52283c7e434SSimon Glass 
52383c7e434SSimon Glass 		/* Check that things happened in the right order */
52483c7e434SSimon Glass 		ut_asserteq_ptr(NULL, priv);
52583c7e434SSimon Glass 		ut_assertok(device_probe(dev));
52683c7e434SSimon Glass 
52783c7e434SSimon Glass 		priv = dev_get_priv(dev);
52883c7e434SSimon Glass 		ut_assert(priv != NULL);
52983c7e434SSimon Glass 		ut_asserteq(1, priv->uclass_flag);
53083c7e434SSimon Glass 		ut_asserteq(1, priv->uclass_total);
53183c7e434SSimon Glass 		child_count++;
53283c7e434SSimon Glass 	}
53383c7e434SSimon Glass 	ut_asserteq(3, child_count);
53483c7e434SSimon Glass 
53583c7e434SSimon Glass 	return 0;
53683c7e434SSimon Glass }
53783c7e434SSimon Glass DM_TEST(dm_test_bus_child_pre_probe_uclass,
53883c7e434SSimon Glass 	DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
539