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> 152e7d35d2SSimon Glass #include <dm/ut.h> 162e7d35d2SSimon Glass #include <dm/uclass-internal.h> 172e7d35d2SSimon Glass #include <dm/util.h> 182e7d35d2SSimon Glass 192e7d35d2SSimon Glass DECLARE_GLOBAL_DATA_PTR; 202e7d35d2SSimon Glass 2154c5d08aSHeiko Schocher static int testfdt_drv_ping(struct udevice *dev, int pingval, int *pingret) 222e7d35d2SSimon Glass { 232e7d35d2SSimon Glass const struct dm_test_pdata *pdata = dev->platdata; 242e7d35d2SSimon Glass struct dm_test_priv *priv = dev_get_priv(dev); 252e7d35d2SSimon Glass 262e7d35d2SSimon Glass *pingret = pingval + pdata->ping_add; 272e7d35d2SSimon Glass priv->ping_total += *pingret; 282e7d35d2SSimon Glass 292e7d35d2SSimon Glass return 0; 302e7d35d2SSimon Glass } 312e7d35d2SSimon Glass 322e7d35d2SSimon Glass static const struct test_ops test_ops = { 332e7d35d2SSimon Glass .ping = testfdt_drv_ping, 342e7d35d2SSimon Glass }; 352e7d35d2SSimon Glass 3654c5d08aSHeiko Schocher static int testfdt_ofdata_to_platdata(struct udevice *dev) 372e7d35d2SSimon Glass { 382e7d35d2SSimon Glass struct dm_test_pdata *pdata = dev_get_platdata(dev); 392e7d35d2SSimon Glass 402e7d35d2SSimon Glass pdata->ping_add = fdtdec_get_int(gd->fdt_blob, dev->of_offset, 412e7d35d2SSimon Glass "ping-add", -1); 42eb9ef5feSSimon Glass pdata->base = fdtdec_get_addr(gd->fdt_blob, dev->of_offset, 43eb9ef5feSSimon Glass "ping-expect"); 442e7d35d2SSimon Glass 452e7d35d2SSimon Glass return 0; 462e7d35d2SSimon Glass } 472e7d35d2SSimon Glass 4854c5d08aSHeiko Schocher static int testfdt_drv_probe(struct udevice *dev) 492e7d35d2SSimon Glass { 502e7d35d2SSimon Glass struct dm_test_priv *priv = dev_get_priv(dev); 512e7d35d2SSimon Glass 522e7d35d2SSimon Glass priv->ping_total += DM_TEST_START_TOTAL; 532e7d35d2SSimon Glass 54*83c7e434SSimon Glass /* 55*83c7e434SSimon Glass * If this device is on a bus, the uclass_flag will be set before 56*83c7e434SSimon Glass * calling this function. This is used by 57*83c7e434SSimon Glass * dm_test_bus_child_pre_probe_uclass(). 58*83c7e434SSimon Glass */ 59*83c7e434SSimon Glass priv->uclass_total += priv->uclass_flag; 60*83c7e434SSimon Glass 612e7d35d2SSimon Glass return 0; 622e7d35d2SSimon Glass } 632e7d35d2SSimon Glass 64ae7f4513SSimon Glass static const struct udevice_id testfdt_ids[] = { 652e7d35d2SSimon Glass { 662e7d35d2SSimon Glass .compatible = "denx,u-boot-fdt-test", 672e7d35d2SSimon Glass .data = DM_TEST_TYPE_FIRST }, 682e7d35d2SSimon Glass { 692e7d35d2SSimon Glass .compatible = "google,another-fdt-test", 702e7d35d2SSimon Glass .data = DM_TEST_TYPE_SECOND }, 712e7d35d2SSimon Glass { } 722e7d35d2SSimon Glass }; 732e7d35d2SSimon Glass 742e7d35d2SSimon Glass U_BOOT_DRIVER(testfdt_drv) = { 752e7d35d2SSimon Glass .name = "testfdt_drv", 762e7d35d2SSimon Glass .of_match = testfdt_ids, 772e7d35d2SSimon Glass .id = UCLASS_TEST_FDT, 782e7d35d2SSimon Glass .ofdata_to_platdata = testfdt_ofdata_to_platdata, 792e7d35d2SSimon Glass .probe = testfdt_drv_probe, 802e7d35d2SSimon Glass .ops = &test_ops, 812e7d35d2SSimon Glass .priv_auto_alloc_size = sizeof(struct dm_test_priv), 822e7d35d2SSimon Glass .platdata_auto_alloc_size = sizeof(struct dm_test_pdata), 832e7d35d2SSimon Glass }; 842e7d35d2SSimon Glass 852e7d35d2SSimon Glass /* From here is the testfdt uclass code */ 8654c5d08aSHeiko Schocher int testfdt_ping(struct udevice *dev, int pingval, int *pingret) 872e7d35d2SSimon Glass { 882e7d35d2SSimon Glass const struct test_ops *ops = device_get_ops(dev); 892e7d35d2SSimon Glass 902e7d35d2SSimon Glass if (!ops->ping) 912e7d35d2SSimon Glass return -ENOSYS; 922e7d35d2SSimon Glass 932e7d35d2SSimon Glass return ops->ping(dev, pingval, pingret); 942e7d35d2SSimon Glass } 952e7d35d2SSimon Glass 962e7d35d2SSimon Glass UCLASS_DRIVER(testfdt) = { 972e7d35d2SSimon Glass .name = "testfdt", 982e7d35d2SSimon Glass .id = UCLASS_TEST_FDT, 999cc36a2bSSimon Glass .flags = DM_UC_FLAG_SEQ_ALIAS, 1002e7d35d2SSimon Glass }; 1012e7d35d2SSimon Glass 1021ca7e206SSimon Glass int dm_check_devices(struct dm_test_state *dms, int num_devices) 1032e7d35d2SSimon Glass { 10454c5d08aSHeiko Schocher struct udevice *dev; 1052e7d35d2SSimon Glass int ret; 1062e7d35d2SSimon Glass int i; 1072e7d35d2SSimon Glass 1082e7d35d2SSimon Glass /* 1092e7d35d2SSimon Glass * Now check that the ping adds are what we expect. This is using the 1102e7d35d2SSimon Glass * ping-add property in each node. 1112e7d35d2SSimon Glass */ 1121ca7e206SSimon Glass for (i = 0; i < num_devices; i++) { 1132e7d35d2SSimon Glass uint32_t base; 1142e7d35d2SSimon Glass 1152e7d35d2SSimon Glass ret = uclass_get_device(UCLASS_TEST_FDT, i, &dev); 1162e7d35d2SSimon Glass ut_assert(!ret); 1172e7d35d2SSimon Glass 1182e7d35d2SSimon Glass /* 119eb9ef5feSSimon Glass * Get the 'ping-expect' property, which tells us what the 120eb9ef5feSSimon Glass * ping add should be. We don't use the platdata because we 121eb9ef5feSSimon Glass * want to test the code that sets that up 122eb9ef5feSSimon Glass * (testfdt_drv_probe()). 1232e7d35d2SSimon Glass */ 124eb9ef5feSSimon Glass base = fdtdec_get_addr(gd->fdt_blob, dev->of_offset, 125eb9ef5feSSimon Glass "ping-expect"); 1262e7d35d2SSimon Glass debug("dev=%d, base=%d: %s\n", i, base, 1272e7d35d2SSimon Glass fdt_get_name(gd->fdt_blob, dev->of_offset, NULL)); 1282e7d35d2SSimon Glass 1292e7d35d2SSimon Glass ut_assert(!dm_check_operations(dms, dev, base, 1302e7d35d2SSimon Glass dev_get_priv(dev))); 1312e7d35d2SSimon Glass } 1322e7d35d2SSimon Glass 1332e7d35d2SSimon Glass return 0; 1342e7d35d2SSimon Glass } 1351ca7e206SSimon Glass 1361ca7e206SSimon Glass /* Test that FDT-based binding works correctly */ 1371ca7e206SSimon Glass static int dm_test_fdt(struct dm_test_state *dms) 1381ca7e206SSimon Glass { 1399cc36a2bSSimon Glass const int num_devices = 6; 1401ca7e206SSimon Glass struct udevice *dev; 1411ca7e206SSimon Glass struct uclass *uc; 1421ca7e206SSimon Glass int ret; 1431ca7e206SSimon Glass int i; 1441ca7e206SSimon Glass 1451ca7e206SSimon Glass ret = dm_scan_fdt(gd->fdt_blob, false); 1461ca7e206SSimon Glass ut_assert(!ret); 1471ca7e206SSimon Glass 1481ca7e206SSimon Glass ret = uclass_get(UCLASS_TEST_FDT, &uc); 1491ca7e206SSimon Glass ut_assert(!ret); 1501ca7e206SSimon Glass 1511ca7e206SSimon Glass /* These are num_devices compatible root-level device tree nodes */ 1521ca7e206SSimon Glass ut_asserteq(num_devices, list_count_items(&uc->dev_head)); 1531ca7e206SSimon Glass 154f8a85449SSimon Glass /* Each should have platform data but no private data */ 1551ca7e206SSimon Glass for (i = 0; i < num_devices; i++) { 1561ca7e206SSimon Glass ret = uclass_find_device(UCLASS_TEST_FDT, i, &dev); 1571ca7e206SSimon Glass ut_assert(!ret); 1581ca7e206SSimon Glass ut_assert(!dev_get_priv(dev)); 159f8a85449SSimon Glass ut_assert(dev->platdata); 1601ca7e206SSimon Glass } 1611ca7e206SSimon Glass 1621ca7e206SSimon Glass ut_assertok(dm_check_devices(dms, num_devices)); 1631ca7e206SSimon Glass 1641ca7e206SSimon Glass return 0; 1651ca7e206SSimon Glass } 1662e7d35d2SSimon Glass DM_TEST(dm_test_fdt, 0); 16700606d7eSSimon Glass 16800606d7eSSimon Glass static int dm_test_fdt_pre_reloc(struct dm_test_state *dms) 16900606d7eSSimon Glass { 17000606d7eSSimon Glass struct uclass *uc; 17100606d7eSSimon Glass int ret; 17200606d7eSSimon Glass 17300606d7eSSimon Glass ret = dm_scan_fdt(gd->fdt_blob, true); 17400606d7eSSimon Glass ut_assert(!ret); 17500606d7eSSimon Glass 17600606d7eSSimon Glass ret = uclass_get(UCLASS_TEST_FDT, &uc); 17700606d7eSSimon Glass ut_assert(!ret); 17800606d7eSSimon Glass 17900606d7eSSimon Glass /* These is only one pre-reloc device */ 18000606d7eSSimon Glass ut_asserteq(1, list_count_items(&uc->dev_head)); 18100606d7eSSimon Glass 18200606d7eSSimon Glass return 0; 18300606d7eSSimon Glass } 18400606d7eSSimon Glass DM_TEST(dm_test_fdt_pre_reloc, 0); 1855a66a8ffSSimon Glass 1865a66a8ffSSimon Glass /* Test that sequence numbers are allocated properly */ 1875a66a8ffSSimon Glass static int dm_test_fdt_uclass_seq(struct dm_test_state *dms) 1885a66a8ffSSimon Glass { 1895a66a8ffSSimon Glass struct udevice *dev; 1905a66a8ffSSimon Glass 1915a66a8ffSSimon Glass /* A few basic santiy tests */ 1925a66a8ffSSimon Glass ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_FDT, 3, true, &dev)); 1935a66a8ffSSimon Glass ut_asserteq_str("b-test", dev->name); 1945a66a8ffSSimon Glass 1959cc36a2bSSimon Glass ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_FDT, 8, true, &dev)); 1965a66a8ffSSimon Glass ut_asserteq_str("a-test", dev->name); 1975a66a8ffSSimon Glass 1985a66a8ffSSimon Glass ut_asserteq(-ENODEV, uclass_find_device_by_seq(UCLASS_TEST_FDT, 5, 1995a66a8ffSSimon Glass true, &dev)); 2005a66a8ffSSimon Glass ut_asserteq_ptr(NULL, dev); 2015a66a8ffSSimon Glass 2025a66a8ffSSimon Glass /* Test aliases */ 2035a66a8ffSSimon Glass ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT, 6, &dev)); 2045a66a8ffSSimon Glass ut_asserteq_str("e-test", dev->name); 2055a66a8ffSSimon Glass 2065a66a8ffSSimon Glass ut_asserteq(-ENODEV, uclass_find_device_by_seq(UCLASS_TEST_FDT, 7, 2075a66a8ffSSimon Glass true, &dev)); 2085a66a8ffSSimon Glass 2091ca7e206SSimon Glass /* 2101ca7e206SSimon Glass * Note that c-test nodes are not probed since it is not a top-level 2111ca7e206SSimon Glass * node 2121ca7e206SSimon Glass */ 2135a66a8ffSSimon Glass ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT, 3, &dev)); 2145a66a8ffSSimon Glass ut_asserteq_str("b-test", dev->name); 2155a66a8ffSSimon Glass 2165a66a8ffSSimon Glass /* 2175a66a8ffSSimon Glass * d-test wants sequence number 3 also, but it can't have it because 2185a66a8ffSSimon Glass * b-test gets it first. 2195a66a8ffSSimon Glass */ 2205a66a8ffSSimon Glass ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 2, &dev)); 2215a66a8ffSSimon Glass ut_asserteq_str("d-test", dev->name); 2225a66a8ffSSimon Glass 2235a66a8ffSSimon Glass /* d-test actually gets 0 */ 2245a66a8ffSSimon Glass ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT, 0, &dev)); 2255a66a8ffSSimon Glass ut_asserteq_str("d-test", dev->name); 2265a66a8ffSSimon Glass 2275a66a8ffSSimon Glass /* initially no one wants seq 1 */ 2285a66a8ffSSimon Glass ut_asserteq(-ENODEV, uclass_get_device_by_seq(UCLASS_TEST_FDT, 1, 2295a66a8ffSSimon Glass &dev)); 2305a66a8ffSSimon Glass ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev)); 2319cc36a2bSSimon Glass ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 4, &dev)); 2325a66a8ffSSimon Glass 2335a66a8ffSSimon Glass /* But now that it is probed, we can find it */ 2345a66a8ffSSimon Glass ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT, 1, &dev)); 2359cc36a2bSSimon Glass ut_asserteq_str("f-test", dev->name); 2365a66a8ffSSimon Glass 2375a66a8ffSSimon Glass return 0; 2385a66a8ffSSimon Glass } 2395a66a8ffSSimon Glass DM_TEST(dm_test_fdt_uclass_seq, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); 240f4cdead2SSimon Glass 241f4cdead2SSimon Glass /* Test that we can find a device by device tree offset */ 242f4cdead2SSimon Glass static int dm_test_fdt_offset(struct dm_test_state *dms) 243f4cdead2SSimon Glass { 244f4cdead2SSimon Glass const void *blob = gd->fdt_blob; 245f4cdead2SSimon Glass struct udevice *dev; 246f4cdead2SSimon Glass int node; 247f4cdead2SSimon Glass 248f4cdead2SSimon Glass node = fdt_path_offset(blob, "/e-test"); 249f4cdead2SSimon Glass ut_assert(node > 0); 250f4cdead2SSimon Glass ut_assertok(uclass_get_device_by_of_offset(UCLASS_TEST_FDT, node, 251f4cdead2SSimon Glass &dev)); 252f4cdead2SSimon Glass ut_asserteq_str("e-test", dev->name); 253f4cdead2SSimon Glass 254f4cdead2SSimon Glass /* This node should not be bound */ 255f4cdead2SSimon Glass node = fdt_path_offset(blob, "/junk"); 256f4cdead2SSimon Glass ut_assert(node > 0); 257f4cdead2SSimon Glass ut_asserteq(-ENODEV, uclass_get_device_by_of_offset(UCLASS_TEST_FDT, 258f4cdead2SSimon Glass node, &dev)); 259f4cdead2SSimon Glass 260f4cdead2SSimon Glass /* This is not a top level node so should not be probed */ 2611ca7e206SSimon Glass node = fdt_path_offset(blob, "/some-bus/c-test@5"); 262f4cdead2SSimon Glass ut_assert(node > 0); 263f4cdead2SSimon Glass ut_asserteq(-ENODEV, uclass_get_device_by_of_offset(UCLASS_TEST_FDT, 264f4cdead2SSimon Glass node, &dev)); 265f4cdead2SSimon Glass 266f4cdead2SSimon Glass return 0; 267f4cdead2SSimon Glass } 268f4cdead2SSimon Glass DM_TEST(dm_test_fdt_offset, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); 269