xref: /rk3399_rockchip-uboot/test/dm/test-fdt.c (revision 2c3c84fc7fd0ab439baf1e634c8b5504daa40db4)
12e7d35d2SSimon Glass /*
22e7d35d2SSimon Glass  * Copyright (c) 2013 Google, Inc
32e7d35d2SSimon Glass  *
42e7d35d2SSimon Glass  * SPDX-License-Identifier:	GPL-2.0+
52e7d35d2SSimon Glass  */
62e7d35d2SSimon Glass 
72e7d35d2SSimon Glass #include <common.h>
82e7d35d2SSimon Glass #include <dm.h>
92e7d35d2SSimon Glass #include <errno.h>
102e7d35d2SSimon Glass #include <fdtdec.h>
112e7d35d2SSimon Glass #include <malloc.h>
122e7d35d2SSimon Glass #include <asm/io.h>
132e7d35d2SSimon Glass #include <dm/test.h>
142e7d35d2SSimon Glass #include <dm/root.h>
1598561572SSimon Glass #include <dm/device-internal.h>
162e7d35d2SSimon Glass #include <dm/uclass-internal.h>
172e7d35d2SSimon Glass #include <dm/util.h>
18e721b882SJoe Hershberger #include <test/ut.h>
192e7d35d2SSimon Glass 
202e7d35d2SSimon Glass DECLARE_GLOBAL_DATA_PTR;
212e7d35d2SSimon Glass 
2254c5d08aSHeiko Schocher static int testfdt_drv_ping(struct udevice *dev, int pingval, int *pingret)
232e7d35d2SSimon Glass {
242e7d35d2SSimon Glass 	const struct dm_test_pdata *pdata = dev->platdata;
252e7d35d2SSimon Glass 	struct dm_test_priv *priv = dev_get_priv(dev);
262e7d35d2SSimon Glass 
272e7d35d2SSimon Glass 	*pingret = pingval + pdata->ping_add;
282e7d35d2SSimon Glass 	priv->ping_total += *pingret;
292e7d35d2SSimon Glass 
302e7d35d2SSimon Glass 	return 0;
312e7d35d2SSimon Glass }
322e7d35d2SSimon Glass 
332e7d35d2SSimon Glass static const struct test_ops test_ops = {
342e7d35d2SSimon Glass 	.ping = testfdt_drv_ping,
352e7d35d2SSimon Glass };
362e7d35d2SSimon Glass 
3754c5d08aSHeiko Schocher static int testfdt_ofdata_to_platdata(struct udevice *dev)
382e7d35d2SSimon Glass {
392e7d35d2SSimon Glass 	struct dm_test_pdata *pdata = dev_get_platdata(dev);
402e7d35d2SSimon Glass 
41e160f7d4SSimon Glass 	pdata->ping_add = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
422e7d35d2SSimon Glass 					"ping-add", -1);
43e160f7d4SSimon Glass 	pdata->base = fdtdec_get_addr(gd->fdt_blob, dev_of_offset(dev),
44eb9ef5feSSimon Glass 				      "ping-expect");
452e7d35d2SSimon Glass 
462e7d35d2SSimon Glass 	return 0;
472e7d35d2SSimon Glass }
482e7d35d2SSimon Glass 
4954c5d08aSHeiko Schocher static int testfdt_drv_probe(struct udevice *dev)
502e7d35d2SSimon Glass {
512e7d35d2SSimon Glass 	struct dm_test_priv *priv = dev_get_priv(dev);
522e7d35d2SSimon Glass 
532e7d35d2SSimon Glass 	priv->ping_total += DM_TEST_START_TOTAL;
542e7d35d2SSimon Glass 
5583c7e434SSimon Glass 	/*
5683c7e434SSimon Glass 	 * If this device is on a bus, the uclass_flag will be set before
5783c7e434SSimon Glass 	 * calling this function. This is used by
5883c7e434SSimon Glass 	 * dm_test_bus_child_pre_probe_uclass().
5983c7e434SSimon Glass 	 */
6083c7e434SSimon Glass 	priv->uclass_total += priv->uclass_flag;
6183c7e434SSimon Glass 
622e7d35d2SSimon Glass 	return 0;
632e7d35d2SSimon Glass }
642e7d35d2SSimon Glass 
65ae7f4513SSimon Glass static const struct udevice_id testfdt_ids[] = {
662e7d35d2SSimon Glass 	{
672e7d35d2SSimon Glass 		.compatible = "denx,u-boot-fdt-test",
682e7d35d2SSimon Glass 		.data = DM_TEST_TYPE_FIRST },
692e7d35d2SSimon Glass 	{
702e7d35d2SSimon Glass 		.compatible = "google,another-fdt-test",
712e7d35d2SSimon Glass 		.data = DM_TEST_TYPE_SECOND },
722e7d35d2SSimon Glass 	{ }
732e7d35d2SSimon Glass };
742e7d35d2SSimon Glass 
752e7d35d2SSimon Glass U_BOOT_DRIVER(testfdt_drv) = {
762e7d35d2SSimon Glass 	.name	= "testfdt_drv",
772e7d35d2SSimon Glass 	.of_match	= testfdt_ids,
782e7d35d2SSimon Glass 	.id	= UCLASS_TEST_FDT,
792e7d35d2SSimon Glass 	.ofdata_to_platdata = testfdt_ofdata_to_platdata,
802e7d35d2SSimon Glass 	.probe	= testfdt_drv_probe,
812e7d35d2SSimon Glass 	.ops	= &test_ops,
822e7d35d2SSimon Glass 	.priv_auto_alloc_size = sizeof(struct dm_test_priv),
832e7d35d2SSimon Glass 	.platdata_auto_alloc_size = sizeof(struct dm_test_pdata),
842e7d35d2SSimon Glass };
852e7d35d2SSimon Glass 
862e7d35d2SSimon Glass /* From here is the testfdt uclass code */
8754c5d08aSHeiko Schocher int testfdt_ping(struct udevice *dev, int pingval, int *pingret)
882e7d35d2SSimon Glass {
892e7d35d2SSimon Glass 	const struct test_ops *ops = device_get_ops(dev);
902e7d35d2SSimon Glass 
912e7d35d2SSimon Glass 	if (!ops->ping)
922e7d35d2SSimon Glass 		return -ENOSYS;
932e7d35d2SSimon Glass 
942e7d35d2SSimon Glass 	return ops->ping(dev, pingval, pingret);
952e7d35d2SSimon Glass }
962e7d35d2SSimon Glass 
972e7d35d2SSimon Glass UCLASS_DRIVER(testfdt) = {
982e7d35d2SSimon Glass 	.name		= "testfdt",
992e7d35d2SSimon Glass 	.id		= UCLASS_TEST_FDT,
1009cc36a2bSSimon Glass 	.flags		= DM_UC_FLAG_SEQ_ALIAS,
1012e7d35d2SSimon Glass };
1022e7d35d2SSimon Glass 
10398561572SSimon Glass struct dm_testprobe_pdata {
10498561572SSimon Glass 	int probe_err;
10598561572SSimon Glass };
10698561572SSimon Glass 
10798561572SSimon Glass static int testprobe_drv_probe(struct udevice *dev)
10898561572SSimon Glass {
10998561572SSimon Glass 	struct dm_testprobe_pdata *pdata = dev_get_platdata(dev);
11098561572SSimon Glass 
11198561572SSimon Glass 	return pdata->probe_err;
11298561572SSimon Glass }
11398561572SSimon Glass 
11498561572SSimon Glass static const struct udevice_id testprobe_ids[] = {
11598561572SSimon Glass 	{ .compatible = "denx,u-boot-probe-test" },
11698561572SSimon Glass 	{ }
11798561572SSimon Glass };
11898561572SSimon Glass 
11998561572SSimon Glass U_BOOT_DRIVER(testprobe_drv) = {
12098561572SSimon Glass 	.name	= "testprobe_drv",
12198561572SSimon Glass 	.of_match	= testprobe_ids,
12298561572SSimon Glass 	.id	= UCLASS_TEST_PROBE,
12398561572SSimon Glass 	.probe	= testprobe_drv_probe,
12498561572SSimon Glass 	.platdata_auto_alloc_size	= sizeof(struct dm_testprobe_pdata),
12598561572SSimon Glass };
12698561572SSimon Glass 
12798561572SSimon Glass UCLASS_DRIVER(testprobe) = {
12898561572SSimon Glass 	.name		= "testprobe",
12998561572SSimon Glass 	.id		= UCLASS_TEST_PROBE,
13098561572SSimon Glass 	.flags		= DM_UC_FLAG_SEQ_ALIAS,
13198561572SSimon Glass };
13298561572SSimon Glass 
133e721b882SJoe Hershberger int dm_check_devices(struct unit_test_state *uts, int num_devices)
1342e7d35d2SSimon Glass {
13554c5d08aSHeiko Schocher 	struct udevice *dev;
1362e7d35d2SSimon Glass 	int ret;
1372e7d35d2SSimon Glass 	int i;
1382e7d35d2SSimon Glass 
1392e7d35d2SSimon Glass 	/*
1402e7d35d2SSimon Glass 	 * Now check that the ping adds are what we expect. This is using the
1412e7d35d2SSimon Glass 	 * ping-add property in each node.
1422e7d35d2SSimon Glass 	 */
1431ca7e206SSimon Glass 	for (i = 0; i < num_devices; i++) {
1442e7d35d2SSimon Glass 		uint32_t base;
1452e7d35d2SSimon Glass 
1462e7d35d2SSimon Glass 		ret = uclass_get_device(UCLASS_TEST_FDT, i, &dev);
1472e7d35d2SSimon Glass 		ut_assert(!ret);
1482e7d35d2SSimon Glass 
1492e7d35d2SSimon Glass 		/*
150eb9ef5feSSimon Glass 		 * Get the 'ping-expect' property, which tells us what the
151eb9ef5feSSimon Glass 		 * ping add should be. We don't use the platdata because we
152eb9ef5feSSimon Glass 		 * want to test the code that sets that up
153eb9ef5feSSimon Glass 		 * (testfdt_drv_probe()).
1542e7d35d2SSimon Glass 		 */
155e160f7d4SSimon Glass 		base = fdtdec_get_addr(gd->fdt_blob, dev_of_offset(dev),
156eb9ef5feSSimon Glass 				       "ping-expect");
1572e7d35d2SSimon Glass 		debug("dev=%d, base=%d: %s\n", i, base,
158e160f7d4SSimon Glass 		      fdt_get_name(gd->fdt_blob, dev_of_offset(dev), NULL));
1592e7d35d2SSimon Glass 
160e721b882SJoe Hershberger 		ut_assert(!dm_check_operations(uts, dev, base,
1612e7d35d2SSimon Glass 					       dev_get_priv(dev)));
1622e7d35d2SSimon Glass 	}
1632e7d35d2SSimon Glass 
1642e7d35d2SSimon Glass 	return 0;
1652e7d35d2SSimon Glass }
1661ca7e206SSimon Glass 
1671ca7e206SSimon Glass /* Test that FDT-based binding works correctly */
168e721b882SJoe Hershberger static int dm_test_fdt(struct unit_test_state *uts)
1691ca7e206SSimon Glass {
1709cc36a2bSSimon Glass 	const int num_devices = 6;
1711ca7e206SSimon Glass 	struct udevice *dev;
1721ca7e206SSimon Glass 	struct uclass *uc;
1731ca7e206SSimon Glass 	int ret;
1741ca7e206SSimon Glass 	int i;
1751ca7e206SSimon Glass 
1761ca7e206SSimon Glass 	ret = dm_scan_fdt(gd->fdt_blob, false);
1771ca7e206SSimon Glass 	ut_assert(!ret);
1781ca7e206SSimon Glass 
1791ca7e206SSimon Glass 	ret = uclass_get(UCLASS_TEST_FDT, &uc);
1801ca7e206SSimon Glass 	ut_assert(!ret);
1811ca7e206SSimon Glass 
1821ca7e206SSimon Glass 	/* These are num_devices compatible root-level device tree nodes */
1831ca7e206SSimon Glass 	ut_asserteq(num_devices, list_count_items(&uc->dev_head));
1841ca7e206SSimon Glass 
185f8a85449SSimon Glass 	/* Each should have platform data but no private data */
1861ca7e206SSimon Glass 	for (i = 0; i < num_devices; i++) {
1871ca7e206SSimon Glass 		ret = uclass_find_device(UCLASS_TEST_FDT, i, &dev);
1881ca7e206SSimon Glass 		ut_assert(!ret);
1891ca7e206SSimon Glass 		ut_assert(!dev_get_priv(dev));
190f8a85449SSimon Glass 		ut_assert(dev->platdata);
1911ca7e206SSimon Glass 	}
1921ca7e206SSimon Glass 
193e721b882SJoe Hershberger 	ut_assertok(dm_check_devices(uts, num_devices));
1941ca7e206SSimon Glass 
1951ca7e206SSimon Glass 	return 0;
1961ca7e206SSimon Glass }
1972e7d35d2SSimon Glass DM_TEST(dm_test_fdt, 0);
19800606d7eSSimon Glass 
199e721b882SJoe Hershberger static int dm_test_fdt_pre_reloc(struct unit_test_state *uts)
20000606d7eSSimon Glass {
20100606d7eSSimon Glass 	struct uclass *uc;
20200606d7eSSimon Glass 	int ret;
20300606d7eSSimon Glass 
20400606d7eSSimon Glass 	ret = dm_scan_fdt(gd->fdt_blob, true);
20500606d7eSSimon Glass 	ut_assert(!ret);
20600606d7eSSimon Glass 
20700606d7eSSimon Glass 	ret = uclass_get(UCLASS_TEST_FDT, &uc);
20800606d7eSSimon Glass 	ut_assert(!ret);
20900606d7eSSimon Glass 
21000606d7eSSimon Glass 	/* These is only one pre-reloc device */
21100606d7eSSimon Glass 	ut_asserteq(1, list_count_items(&uc->dev_head));
21200606d7eSSimon Glass 
21300606d7eSSimon Glass 	return 0;
21400606d7eSSimon Glass }
21500606d7eSSimon Glass DM_TEST(dm_test_fdt_pre_reloc, 0);
2165a66a8ffSSimon Glass 
2175a66a8ffSSimon Glass /* Test that sequence numbers are allocated properly */
218e721b882SJoe Hershberger static int dm_test_fdt_uclass_seq(struct unit_test_state *uts)
2195a66a8ffSSimon Glass {
2205a66a8ffSSimon Glass 	struct udevice *dev;
2215a66a8ffSSimon Glass 
2225a66a8ffSSimon Glass 	/* A few basic santiy tests */
2235a66a8ffSSimon Glass 	ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_FDT, 3, true, &dev));
2245a66a8ffSSimon Glass 	ut_asserteq_str("b-test", dev->name);
2255a66a8ffSSimon Glass 
2269cc36a2bSSimon Glass 	ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_FDT, 8, true, &dev));
2275a66a8ffSSimon Glass 	ut_asserteq_str("a-test", dev->name);
2285a66a8ffSSimon Glass 
2295a66a8ffSSimon Glass 	ut_asserteq(-ENODEV, uclass_find_device_by_seq(UCLASS_TEST_FDT, 5,
2305a66a8ffSSimon Glass 						       true, &dev));
2315a66a8ffSSimon Glass 	ut_asserteq_ptr(NULL, dev);
2325a66a8ffSSimon Glass 
2335a66a8ffSSimon Glass 	/* Test aliases */
2345a66a8ffSSimon Glass 	ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT, 6, &dev));
2355a66a8ffSSimon Glass 	ut_asserteq_str("e-test", dev->name);
2365a66a8ffSSimon Glass 
2375a66a8ffSSimon Glass 	ut_asserteq(-ENODEV, uclass_find_device_by_seq(UCLASS_TEST_FDT, 7,
2385a66a8ffSSimon Glass 						       true, &dev));
2395a66a8ffSSimon Glass 
2401ca7e206SSimon Glass 	/*
2411ca7e206SSimon Glass 	 * Note that c-test nodes are not probed since it is not a top-level
2421ca7e206SSimon Glass 	 * node
2431ca7e206SSimon Glass 	 */
2445a66a8ffSSimon Glass 	ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT, 3, &dev));
2455a66a8ffSSimon Glass 	ut_asserteq_str("b-test", dev->name);
2465a66a8ffSSimon Glass 
2475a66a8ffSSimon Glass 	/*
2485a66a8ffSSimon Glass 	 * d-test wants sequence number 3 also, but it can't have it because
2495a66a8ffSSimon Glass 	 * b-test gets it first.
2505a66a8ffSSimon Glass 	 */
2515a66a8ffSSimon Glass 	ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 2, &dev));
2525a66a8ffSSimon Glass 	ut_asserteq_str("d-test", dev->name);
2535a66a8ffSSimon Glass 
2545a66a8ffSSimon Glass 	/* d-test actually gets 0 */
2555a66a8ffSSimon Glass 	ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT, 0, &dev));
2565a66a8ffSSimon Glass 	ut_asserteq_str("d-test", dev->name);
2575a66a8ffSSimon Glass 
2585a66a8ffSSimon Glass 	/* initially no one wants seq 1 */
2595a66a8ffSSimon Glass 	ut_asserteq(-ENODEV, uclass_get_device_by_seq(UCLASS_TEST_FDT, 1,
2605a66a8ffSSimon Glass 						      &dev));
2615a66a8ffSSimon Glass 	ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev));
2629cc36a2bSSimon Glass 	ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 4, &dev));
2635a66a8ffSSimon Glass 
2645a66a8ffSSimon Glass 	/* But now that it is probed, we can find it */
2655a66a8ffSSimon Glass 	ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT, 1, &dev));
2669cc36a2bSSimon Glass 	ut_asserteq_str("f-test", dev->name);
2675a66a8ffSSimon Glass 
2685a66a8ffSSimon Glass 	return 0;
2695a66a8ffSSimon Glass }
2705a66a8ffSSimon Glass DM_TEST(dm_test_fdt_uclass_seq, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
271f4cdead2SSimon Glass 
272f4cdead2SSimon Glass /* Test that we can find a device by device tree offset */
273e721b882SJoe Hershberger static int dm_test_fdt_offset(struct unit_test_state *uts)
274f4cdead2SSimon Glass {
275f4cdead2SSimon Glass 	const void *blob = gd->fdt_blob;
276f4cdead2SSimon Glass 	struct udevice *dev;
277f4cdead2SSimon Glass 	int node;
278f4cdead2SSimon Glass 
279f4cdead2SSimon Glass 	node = fdt_path_offset(blob, "/e-test");
280f4cdead2SSimon Glass 	ut_assert(node > 0);
281f4cdead2SSimon Glass 	ut_assertok(uclass_get_device_by_of_offset(UCLASS_TEST_FDT, node,
282f4cdead2SSimon Glass 						   &dev));
283f4cdead2SSimon Glass 	ut_asserteq_str("e-test", dev->name);
284f4cdead2SSimon Glass 
285f4cdead2SSimon Glass 	/* This node should not be bound */
286f4cdead2SSimon Glass 	node = fdt_path_offset(blob, "/junk");
287f4cdead2SSimon Glass 	ut_assert(node > 0);
288f4cdead2SSimon Glass 	ut_asserteq(-ENODEV, uclass_get_device_by_of_offset(UCLASS_TEST_FDT,
289f4cdead2SSimon Glass 							    node, &dev));
290f4cdead2SSimon Glass 
291f4cdead2SSimon Glass 	/* This is not a top level node so should not be probed */
2921ca7e206SSimon Glass 	node = fdt_path_offset(blob, "/some-bus/c-test@5");
293f4cdead2SSimon Glass 	ut_assert(node > 0);
294f4cdead2SSimon Glass 	ut_asserteq(-ENODEV, uclass_get_device_by_of_offset(UCLASS_TEST_FDT,
295f4cdead2SSimon Glass 							    node, &dev));
296f4cdead2SSimon Glass 
297f4cdead2SSimon Glass 	return 0;
298f4cdead2SSimon Glass }
29986b54eceSSimon Glass DM_TEST(dm_test_fdt_offset,
30086b54eceSSimon Glass 	DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT | DM_TESTF_FLAT_TREE);
30198561572SSimon Glass 
30298561572SSimon Glass /**
30398561572SSimon Glass  * Test various error conditions with uclass_first_device() and
30498561572SSimon Glass  * uclass_next_device()
30598561572SSimon Glass  */
30698561572SSimon Glass static int dm_test_first_next_device(struct unit_test_state *uts)
30798561572SSimon Glass {
30898561572SSimon Glass 	struct dm_testprobe_pdata *pdata;
30998561572SSimon Glass 	struct udevice *dev, *parent = NULL;
31098561572SSimon Glass 	int count;
31198561572SSimon Glass 	int ret;
31298561572SSimon Glass 
31398561572SSimon Glass 	/* There should be 4 devices */
31498561572SSimon Glass 	for (ret = uclass_first_device(UCLASS_TEST_PROBE, &dev), count = 0;
31598561572SSimon Glass 	     dev;
31698561572SSimon Glass 	     ret = uclass_next_device(&dev)) {
31798561572SSimon Glass 		count++;
31898561572SSimon Glass 		parent = dev_get_parent(dev);
31998561572SSimon Glass 		}
32098561572SSimon Glass 	ut_assertok(ret);
32198561572SSimon Glass 	ut_asserteq(4, count);
32298561572SSimon Glass 
32398561572SSimon Glass 	/* Remove them and try again, with an error on the second one */
32498561572SSimon Glass 	ut_assertok(uclass_get_device(UCLASS_TEST_PROBE, 1, &dev));
32598561572SSimon Glass 	pdata = dev_get_platdata(dev);
32698561572SSimon Glass 	pdata->probe_err = -ENOMEM;
32798561572SSimon Glass 	device_remove(parent, DM_REMOVE_NORMAL);
32898561572SSimon Glass 	ut_assertok(uclass_first_device(UCLASS_TEST_PROBE, &dev));
32998561572SSimon Glass 	ut_asserteq(-ENOMEM, uclass_next_device(&dev));
33098561572SSimon Glass 	ut_asserteq_ptr(dev, NULL);
33198561572SSimon Glass 
33298561572SSimon Glass 	/* Now an error on the first one */
33398561572SSimon Glass 	ut_assertok(uclass_get_device(UCLASS_TEST_PROBE, 0, &dev));
33498561572SSimon Glass 	pdata = dev_get_platdata(dev);
33598561572SSimon Glass 	pdata->probe_err = -ENOENT;
33698561572SSimon Glass 	device_remove(parent, DM_REMOVE_NORMAL);
33798561572SSimon Glass 	ut_asserteq(-ENOENT, uclass_first_device(UCLASS_TEST_PROBE, &dev));
33898561572SSimon Glass 
33998561572SSimon Glass 	return 0;
34098561572SSimon Glass }
34198561572SSimon Glass DM_TEST(dm_test_first_next_device, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
34295ce385aSSimon Glass 
343*2c3c84fcSSimon Glass /* Test iteration through devices in a uclass */
344*2c3c84fcSSimon Glass static int dm_test_uclass_foreach(struct unit_test_state *uts)
345*2c3c84fcSSimon Glass {
346*2c3c84fcSSimon Glass 	struct udevice *dev;
347*2c3c84fcSSimon Glass 	struct uclass *uc;
348*2c3c84fcSSimon Glass 	int count;
349*2c3c84fcSSimon Glass 
350*2c3c84fcSSimon Glass 	count = 0;
351*2c3c84fcSSimon Glass 	uclass_id_foreach_dev(UCLASS_TEST_FDT, dev, uc)
352*2c3c84fcSSimon Glass 		count++;
353*2c3c84fcSSimon Glass 	ut_asserteq(8, count);
354*2c3c84fcSSimon Glass 
355*2c3c84fcSSimon Glass 	count = 0;
356*2c3c84fcSSimon Glass 	uclass_foreach_dev(dev, uc)
357*2c3c84fcSSimon Glass 		count++;
358*2c3c84fcSSimon Glass 	ut_asserteq(8, count);
359*2c3c84fcSSimon Glass 
360*2c3c84fcSSimon Glass 	return 0;
361*2c3c84fcSSimon Glass }
362*2c3c84fcSSimon Glass DM_TEST(dm_test_uclass_foreach, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
363*2c3c84fcSSimon Glass 
36495ce385aSSimon Glass /**
36595ce385aSSimon Glass  * check_devices() - Check return values and pointers
36695ce385aSSimon Glass  *
36795ce385aSSimon Glass  * This runs through a full sequence of uclass_first_device_check()...
36895ce385aSSimon Glass  * uclass_next_device_check() checking that the return values and devices
36995ce385aSSimon Glass  * are correct.
37095ce385aSSimon Glass  *
37195ce385aSSimon Glass  * @uts: Test state
37295ce385aSSimon Glass  * @devlist: List of expected devices
37395ce385aSSimon Glass  * @mask: Indicates which devices should return an error. Device n should
37495ce385aSSimon Glass  *	  return error (-NOENT - n) if bit n is set, or no error (i.e. 0) if
37595ce385aSSimon Glass  *	  bit n is clear.
37695ce385aSSimon Glass  */
37795ce385aSSimon Glass static int check_devices(struct unit_test_state *uts,
37895ce385aSSimon Glass 			 struct udevice *devlist[], int mask)
37995ce385aSSimon Glass {
38095ce385aSSimon Glass 	int expected_ret;
38195ce385aSSimon Glass 	struct udevice *dev;
38295ce385aSSimon Glass 	int i;
38395ce385aSSimon Glass 
38495ce385aSSimon Glass 	expected_ret = (mask & 1) ? -ENOENT : 0;
38595ce385aSSimon Glass 	mask >>= 1;
38695ce385aSSimon Glass 	ut_asserteq(expected_ret,
38795ce385aSSimon Glass 		    uclass_first_device_check(UCLASS_TEST_PROBE, &dev));
38895ce385aSSimon Glass 	for (i = 0; i < 4; i++) {
38995ce385aSSimon Glass 		ut_asserteq_ptr(devlist[i], dev);
39095ce385aSSimon Glass 		expected_ret = (mask & 1) ? -ENOENT - (i + 1) : 0;
39195ce385aSSimon Glass 		mask >>= 1;
39295ce385aSSimon Glass 		ut_asserteq(expected_ret, uclass_next_device_check(&dev));
39395ce385aSSimon Glass 	}
39495ce385aSSimon Glass 	ut_asserteq_ptr(NULL, dev);
39595ce385aSSimon Glass 
39695ce385aSSimon Glass 	return 0;
39795ce385aSSimon Glass }
39895ce385aSSimon Glass 
39995ce385aSSimon Glass /* Test uclass_first_device_check() and uclass_next_device_check() */
40095ce385aSSimon Glass static int dm_test_first_next_ok_device(struct unit_test_state *uts)
40195ce385aSSimon Glass {
40295ce385aSSimon Glass 	struct dm_testprobe_pdata *pdata;
40395ce385aSSimon Glass 	struct udevice *dev, *parent = NULL, *devlist[4];
40495ce385aSSimon Glass 	int count;
40595ce385aSSimon Glass 	int ret;
40695ce385aSSimon Glass 
40795ce385aSSimon Glass 	/* There should be 4 devices */
40895ce385aSSimon Glass 	count = 0;
40995ce385aSSimon Glass 	for (ret = uclass_first_device_check(UCLASS_TEST_PROBE, &dev);
41095ce385aSSimon Glass 	     dev;
41195ce385aSSimon Glass 	     ret = uclass_next_device_check(&dev)) {
41295ce385aSSimon Glass 		ut_assertok(ret);
41395ce385aSSimon Glass 		devlist[count++] = dev;
41495ce385aSSimon Glass 		parent = dev_get_parent(dev);
41595ce385aSSimon Glass 		}
41695ce385aSSimon Glass 	ut_asserteq(4, count);
41795ce385aSSimon Glass 	ut_assertok(uclass_first_device_check(UCLASS_TEST_PROBE, &dev));
41895ce385aSSimon Glass 	ut_assertok(check_devices(uts, devlist, 0));
41995ce385aSSimon Glass 
42095ce385aSSimon Glass 	/* Remove them and try again, with an error on the second one */
42195ce385aSSimon Glass 	pdata = dev_get_platdata(devlist[1]);
42295ce385aSSimon Glass 	pdata->probe_err = -ENOENT - 1;
42395ce385aSSimon Glass 	device_remove(parent, DM_REMOVE_NORMAL);
42495ce385aSSimon Glass 	ut_assertok(check_devices(uts, devlist, 1 << 1));
42595ce385aSSimon Glass 
42695ce385aSSimon Glass 	/* Now an error on the first one */
42795ce385aSSimon Glass 	pdata = dev_get_platdata(devlist[0]);
42895ce385aSSimon Glass 	pdata->probe_err = -ENOENT - 0;
42995ce385aSSimon Glass 	device_remove(parent, DM_REMOVE_NORMAL);
43095ce385aSSimon Glass 	ut_assertok(check_devices(uts, devlist, 3 << 0));
43195ce385aSSimon Glass 
43295ce385aSSimon Glass 	/* Now errors on all */
43395ce385aSSimon Glass 	pdata = dev_get_platdata(devlist[2]);
43495ce385aSSimon Glass 	pdata->probe_err = -ENOENT - 2;
43595ce385aSSimon Glass 	pdata = dev_get_platdata(devlist[3]);
43695ce385aSSimon Glass 	pdata->probe_err = -ENOENT - 3;
43795ce385aSSimon Glass 	device_remove(parent, DM_REMOVE_NORMAL);
43895ce385aSSimon Glass 	ut_assertok(check_devices(uts, devlist, 0xf << 0));
43995ce385aSSimon Glass 
44095ce385aSSimon Glass 	return 0;
44195ce385aSSimon Glass }
44295ce385aSSimon Glass DM_TEST(dm_test_first_next_ok_device, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
443