xref: /rk3399_rockchip-uboot/test/dm/bus.c (revision e23eb614a415afa6bc2b3609b4f7a07c0f425744)
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/ut.h>
141ca7e206SSimon Glass #include <dm/util.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 */
1071ca7e206SSimon Glass static int dm_test_bus_children(struct dm_test_state *dms)
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 
1231ca7e206SSimon Glass 	ut_assert(!dm_check_devices(dms, 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 */
130997c87bbSSimon Glass static int dm_test_bus_children_funcs(struct dm_test_state *dms)
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 */
176a8981d4fSSimon Glass static int dm_test_bus_children_iterators(struct dm_test_state *dms)
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 */
207dac8db2cSSimon Glass static int test_bus_parent_data(struct dm_test_state *dms)
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 */
267dac8db2cSSimon Glass static int dm_test_bus_parent_data(struct dm_test_state *dms)
268dac8db2cSSimon Glass {
269dac8db2cSSimon Glass 	return test_bus_parent_data(dms);
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 */
274dac8db2cSSimon Glass static int dm_test_bus_parent_data_uclass(struct dm_test_state *dms)
275dac8db2cSSimon Glass {
276*e23eb614SSimon 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));
283*e23eb614SSimon Glass 	drv = (struct driver *)bus->driver;
284*e23eb614SSimon Glass 	size = drv->per_child_auto_alloc_size;
285dac8db2cSSimon Glass 	bus->uclass->uc_drv->per_child_auto_alloc_size = size;
286*e23eb614SSimon Glass 	drv->per_child_auto_alloc_size = 0;
287dac8db2cSSimon Glass 	ret = test_bus_parent_data(dms);
288dac8db2cSSimon Glass 	if (ret)
289dac8db2cSSimon Glass 		return ret;
290dac8db2cSSimon Glass 	bus->uclass->uc_drv->per_child_auto_alloc_size = 0;
291*e23eb614SSimon 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 */
299a327dee0SSimon Glass static int dm_test_bus_parent_ops(struct dm_test_state *dms)
300a327dee0SSimon Glass {
301a327dee0SSimon Glass 	struct dm_test_parent_data *parent_data;
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;
313a327dee0SSimon Glass 		ut_asserteq_ptr(NULL, dev_get_parentdata(dev));
314a327dee0SSimon Glass 
315a327dee0SSimon Glass 		ut_assertok(device_probe(dev));
316a327dee0SSimon Glass 		parent_data = dev_get_parentdata(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;
324a327dee0SSimon Glass 		parent_data = dev_get_parentdata(dev);
325a327dee0SSimon Glass 		ut_asserteq(FLAG_CHILD_PROBED, parent_data->flag);
326a327dee0SSimon Glass 		ut_assertok(device_remove(dev));
327a327dee0SSimon Glass 		ut_asserteq_ptr(NULL, dev_get_parentdata(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 
336ba8da9dcSSimon Glass static int test_bus_parent_platdata(struct dm_test_state *dms)
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);
363cdc133bdSSimon Glass 		device_remove(dev);
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) */
373cdc133bdSSimon Glass 	device_remove(bus);
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 */
409ba8da9dcSSimon Glass static int dm_test_bus_parent_platdata(struct dm_test_state *dms)
410ba8da9dcSSimon Glass {
411ba8da9dcSSimon Glass 	return test_bus_parent_platdata(dms);
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 */
416ba8da9dcSSimon Glass static int dm_test_bus_parent_platdata_uclass(struct dm_test_state *dms)
417ba8da9dcSSimon Glass {
418ba8da9dcSSimon Glass 	struct udevice *bus;
419*e23eb614SSimon 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));
425*e23eb614SSimon Glass 	drv = (struct driver *)bus->driver;
426*e23eb614SSimon Glass 	size = drv->per_child_platdata_auto_alloc_size;
427ba8da9dcSSimon Glass 	bus->uclass->uc_drv->per_child_platdata_auto_alloc_size = size;
428*e23eb614SSimon Glass 	drv->per_child_platdata_auto_alloc_size = 0;
429ba8da9dcSSimon Glass 	ret = test_bus_parent_platdata(dms);
430ba8da9dcSSimon Glass 	if (ret)
431ba8da9dcSSimon Glass 		return ret;
432ba8da9dcSSimon Glass 	bus->uclass->uc_drv->per_child_platdata_auto_alloc_size = 0;
433*e23eb614SSimon 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 */
4410118ce79SSimon Glass static int dm_test_bus_child_post_bind(struct dm_test_state *dms)
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 */
464081f2fcbSSimon Glass static int dm_test_bus_child_post_bind_uclass(struct dm_test_state *dms)
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  */
49183c7e434SSimon Glass static int dm_test_bus_child_pre_probe_uclass(struct dm_test_state *dms)
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