xref: /rk3399_rockchip-uboot/test/dm/test-fdt.c (revision 1f383ee4cd2d6a9555aa9de5506b2fc19b24735d)
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 
testfdt_drv_ping(struct udevice * dev,int pingval,int * pingret)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 
testfdt_ofdata_to_platdata(struct udevice * dev)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 
testfdt_drv_probe(struct udevice * dev)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 */
testfdt_ping(struct udevice * dev,int pingval,int * pingret)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 
testprobe_drv_probe(struct udevice * dev)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 
dm_check_devices(struct unit_test_state * uts,int num_devices)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 */
dm_test_fdt(struct unit_test_state * uts)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 
dm_test_fdt_pre_reloc(struct unit_test_state * uts)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 */
dm_test_fdt_uclass_seq(struct unit_test_state * uts)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 */
dm_test_fdt_offset(struct unit_test_state * uts)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  */
dm_test_first_next_device(struct unit_test_state * uts)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 */
314*1f383ee4SMichal Suchanek 	for (uclass_first_device(UCLASS_TEST_PROBE, &dev), count = 0;
31598561572SSimon Glass 	     dev;
316*1f383ee4SMichal Suchanek 	     uclass_next_device(&dev)) {
31798561572SSimon Glass 		count++;
31898561572SSimon Glass 		parent = dev_get_parent(dev);
31998561572SSimon Glass 		}
32098561572SSimon Glass 	ut_asserteq(4, count);
32198561572SSimon Glass 
32298561572SSimon Glass 	/* Remove them and try again, with an error on the second one */
32398561572SSimon Glass 	ut_assertok(uclass_get_device(UCLASS_TEST_PROBE, 1, &dev));
32498561572SSimon Glass 	pdata = dev_get_platdata(dev);
32598561572SSimon Glass 	pdata->probe_err = -ENOMEM;
32698561572SSimon Glass 	device_remove(parent, DM_REMOVE_NORMAL);
327*1f383ee4SMichal Suchanek 	for (ret = uclass_first_device_check(UCLASS_TEST_PROBE, &dev),
328*1f383ee4SMichal Suchanek 		count = 0;
329*1f383ee4SMichal Suchanek 	     dev;
330*1f383ee4SMichal Suchanek 	     ret = uclass_next_device_check(&dev)) {
331*1f383ee4SMichal Suchanek 		if (!ret)
332*1f383ee4SMichal Suchanek 			count++;
333*1f383ee4SMichal Suchanek 		else
334*1f383ee4SMichal Suchanek 			ut_asserteq(-ENOMEM, ret);
335*1f383ee4SMichal Suchanek 		parent = dev_get_parent(dev);
336*1f383ee4SMichal Suchanek 		}
337*1f383ee4SMichal Suchanek 	ut_asserteq(3, count);
33898561572SSimon Glass 
33998561572SSimon Glass 	/* Now an error on the first one */
34098561572SSimon Glass 	ut_assertok(uclass_get_device(UCLASS_TEST_PROBE, 0, &dev));
34198561572SSimon Glass 	pdata = dev_get_platdata(dev);
34298561572SSimon Glass 	pdata->probe_err = -ENOENT;
34398561572SSimon Glass 	device_remove(parent, DM_REMOVE_NORMAL);
344*1f383ee4SMichal Suchanek 	for (uclass_first_device(UCLASS_TEST_PROBE, &dev), count = 0;
345*1f383ee4SMichal Suchanek 	     dev;
346*1f383ee4SMichal Suchanek 	     uclass_next_device(&dev)) {
347*1f383ee4SMichal Suchanek 		count++;
348*1f383ee4SMichal Suchanek 		parent = dev_get_parent(dev);
349*1f383ee4SMichal Suchanek 		}
350*1f383ee4SMichal Suchanek 	ut_asserteq(2, count);
35198561572SSimon Glass 
35298561572SSimon Glass 	return 0;
35398561572SSimon Glass }
35498561572SSimon Glass DM_TEST(dm_test_first_next_device, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
35595ce385aSSimon Glass 
3562c3c84fcSSimon Glass /* Test iteration through devices in a uclass */
dm_test_uclass_foreach(struct unit_test_state * uts)3572c3c84fcSSimon Glass static int dm_test_uclass_foreach(struct unit_test_state *uts)
3582c3c84fcSSimon Glass {
3592c3c84fcSSimon Glass 	struct udevice *dev;
3602c3c84fcSSimon Glass 	struct uclass *uc;
3612c3c84fcSSimon Glass 	int count;
3622c3c84fcSSimon Glass 
3632c3c84fcSSimon Glass 	count = 0;
3642c3c84fcSSimon Glass 	uclass_id_foreach_dev(UCLASS_TEST_FDT, dev, uc)
3652c3c84fcSSimon Glass 		count++;
3662c3c84fcSSimon Glass 	ut_asserteq(8, count);
3672c3c84fcSSimon Glass 
3682c3c84fcSSimon Glass 	count = 0;
3692c3c84fcSSimon Glass 	uclass_foreach_dev(dev, uc)
3702c3c84fcSSimon Glass 		count++;
3712c3c84fcSSimon Glass 	ut_asserteq(8, count);
3722c3c84fcSSimon Glass 
3732c3c84fcSSimon Glass 	return 0;
3742c3c84fcSSimon Glass }
3752c3c84fcSSimon Glass DM_TEST(dm_test_uclass_foreach, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
3762c3c84fcSSimon Glass 
37795ce385aSSimon Glass /**
37895ce385aSSimon Glass  * check_devices() - Check return values and pointers
37995ce385aSSimon Glass  *
38095ce385aSSimon Glass  * This runs through a full sequence of uclass_first_device_check()...
38195ce385aSSimon Glass  * uclass_next_device_check() checking that the return values and devices
38295ce385aSSimon Glass  * are correct.
38395ce385aSSimon Glass  *
38495ce385aSSimon Glass  * @uts: Test state
38595ce385aSSimon Glass  * @devlist: List of expected devices
38695ce385aSSimon Glass  * @mask: Indicates which devices should return an error. Device n should
38795ce385aSSimon Glass  *	  return error (-NOENT - n) if bit n is set, or no error (i.e. 0) if
38895ce385aSSimon Glass  *	  bit n is clear.
38995ce385aSSimon Glass  */
check_devices(struct unit_test_state * uts,struct udevice * devlist[],int mask)39095ce385aSSimon Glass static int check_devices(struct unit_test_state *uts,
39195ce385aSSimon Glass 			 struct udevice *devlist[], int mask)
39295ce385aSSimon Glass {
39395ce385aSSimon Glass 	int expected_ret;
39495ce385aSSimon Glass 	struct udevice *dev;
39595ce385aSSimon Glass 	int i;
39695ce385aSSimon Glass 
39795ce385aSSimon Glass 	expected_ret = (mask & 1) ? -ENOENT : 0;
39895ce385aSSimon Glass 	mask >>= 1;
39995ce385aSSimon Glass 	ut_asserteq(expected_ret,
40095ce385aSSimon Glass 		    uclass_first_device_check(UCLASS_TEST_PROBE, &dev));
40195ce385aSSimon Glass 	for (i = 0; i < 4; i++) {
40295ce385aSSimon Glass 		ut_asserteq_ptr(devlist[i], dev);
40395ce385aSSimon Glass 		expected_ret = (mask & 1) ? -ENOENT - (i + 1) : 0;
40495ce385aSSimon Glass 		mask >>= 1;
40595ce385aSSimon Glass 		ut_asserteq(expected_ret, uclass_next_device_check(&dev));
40695ce385aSSimon Glass 	}
40795ce385aSSimon Glass 	ut_asserteq_ptr(NULL, dev);
40895ce385aSSimon Glass 
40995ce385aSSimon Glass 	return 0;
41095ce385aSSimon Glass }
41195ce385aSSimon Glass 
41295ce385aSSimon Glass /* Test uclass_first_device_check() and uclass_next_device_check() */
dm_test_first_next_ok_device(struct unit_test_state * uts)41395ce385aSSimon Glass static int dm_test_first_next_ok_device(struct unit_test_state *uts)
41495ce385aSSimon Glass {
41595ce385aSSimon Glass 	struct dm_testprobe_pdata *pdata;
41695ce385aSSimon Glass 	struct udevice *dev, *parent = NULL, *devlist[4];
41795ce385aSSimon Glass 	int count;
41895ce385aSSimon Glass 	int ret;
41995ce385aSSimon Glass 
42095ce385aSSimon Glass 	/* There should be 4 devices */
42195ce385aSSimon Glass 	count = 0;
42295ce385aSSimon Glass 	for (ret = uclass_first_device_check(UCLASS_TEST_PROBE, &dev);
42395ce385aSSimon Glass 	     dev;
42495ce385aSSimon Glass 	     ret = uclass_next_device_check(&dev)) {
42595ce385aSSimon Glass 		ut_assertok(ret);
42695ce385aSSimon Glass 		devlist[count++] = dev;
42795ce385aSSimon Glass 		parent = dev_get_parent(dev);
42895ce385aSSimon Glass 		}
42995ce385aSSimon Glass 	ut_asserteq(4, count);
43095ce385aSSimon Glass 	ut_assertok(uclass_first_device_check(UCLASS_TEST_PROBE, &dev));
43195ce385aSSimon Glass 	ut_assertok(check_devices(uts, devlist, 0));
43295ce385aSSimon Glass 
43395ce385aSSimon Glass 	/* Remove them and try again, with an error on the second one */
43495ce385aSSimon Glass 	pdata = dev_get_platdata(devlist[1]);
43595ce385aSSimon Glass 	pdata->probe_err = -ENOENT - 1;
43695ce385aSSimon Glass 	device_remove(parent, DM_REMOVE_NORMAL);
43795ce385aSSimon Glass 	ut_assertok(check_devices(uts, devlist, 1 << 1));
43895ce385aSSimon Glass 
43995ce385aSSimon Glass 	/* Now an error on the first one */
44095ce385aSSimon Glass 	pdata = dev_get_platdata(devlist[0]);
44195ce385aSSimon Glass 	pdata->probe_err = -ENOENT - 0;
44295ce385aSSimon Glass 	device_remove(parent, DM_REMOVE_NORMAL);
44395ce385aSSimon Glass 	ut_assertok(check_devices(uts, devlist, 3 << 0));
44495ce385aSSimon Glass 
44595ce385aSSimon Glass 	/* Now errors on all */
44695ce385aSSimon Glass 	pdata = dev_get_platdata(devlist[2]);
44795ce385aSSimon Glass 	pdata->probe_err = -ENOENT - 2;
44895ce385aSSimon Glass 	pdata = dev_get_platdata(devlist[3]);
44995ce385aSSimon Glass 	pdata->probe_err = -ENOENT - 3;
45095ce385aSSimon Glass 	device_remove(parent, DM_REMOVE_NORMAL);
45195ce385aSSimon Glass 	ut_assertok(check_devices(uts, devlist, 0xf << 0));
45295ce385aSSimon Glass 
45395ce385aSSimon Glass 	return 0;
45495ce385aSSimon Glass }
45595ce385aSSimon Glass DM_TEST(dm_test_first_next_ok_device, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
456771aadbaSSimon Glass 
457771aadbaSSimon Glass /* Test iteration through devices by drvdata */
dm_test_uclass_drvdata(struct unit_test_state * uts)458771aadbaSSimon Glass static int dm_test_uclass_drvdata(struct unit_test_state *uts)
459771aadbaSSimon Glass {
460771aadbaSSimon Glass 	struct udevice *dev;
461771aadbaSSimon Glass 
462771aadbaSSimon Glass 	ut_assertok(uclass_first_device_drvdata(UCLASS_TEST_FDT,
463771aadbaSSimon Glass 						DM_TEST_TYPE_FIRST, &dev));
464771aadbaSSimon Glass 	ut_asserteq_str("a-test", dev->name);
465771aadbaSSimon Glass 
466771aadbaSSimon Glass 	ut_assertok(uclass_first_device_drvdata(UCLASS_TEST_FDT,
467771aadbaSSimon Glass 						DM_TEST_TYPE_SECOND, &dev));
468771aadbaSSimon Glass 	ut_asserteq_str("d-test", dev->name);
469771aadbaSSimon Glass 
470771aadbaSSimon Glass 	ut_asserteq(-ENODEV, uclass_first_device_drvdata(UCLASS_TEST_FDT,
471771aadbaSSimon Glass 							 DM_TEST_TYPE_COUNT,
472771aadbaSSimon Glass 							 &dev));
473771aadbaSSimon Glass 
474771aadbaSSimon Glass 	return 0;
475771aadbaSSimon Glass }
476771aadbaSSimon Glass DM_TEST(dm_test_uclass_drvdata, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
477