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