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 542e7d35d2SSimon Glass return 0; 552e7d35d2SSimon Glass } 562e7d35d2SSimon Glass 57ae7f4513SSimon Glass static const struct udevice_id testfdt_ids[] = { 582e7d35d2SSimon Glass { 592e7d35d2SSimon Glass .compatible = "denx,u-boot-fdt-test", 602e7d35d2SSimon Glass .data = DM_TEST_TYPE_FIRST }, 612e7d35d2SSimon Glass { 622e7d35d2SSimon Glass .compatible = "google,another-fdt-test", 632e7d35d2SSimon Glass .data = DM_TEST_TYPE_SECOND }, 642e7d35d2SSimon Glass { } 652e7d35d2SSimon Glass }; 662e7d35d2SSimon Glass 672e7d35d2SSimon Glass U_BOOT_DRIVER(testfdt_drv) = { 682e7d35d2SSimon Glass .name = "testfdt_drv", 692e7d35d2SSimon Glass .of_match = testfdt_ids, 702e7d35d2SSimon Glass .id = UCLASS_TEST_FDT, 712e7d35d2SSimon Glass .ofdata_to_platdata = testfdt_ofdata_to_platdata, 722e7d35d2SSimon Glass .probe = testfdt_drv_probe, 732e7d35d2SSimon Glass .ops = &test_ops, 742e7d35d2SSimon Glass .priv_auto_alloc_size = sizeof(struct dm_test_priv), 752e7d35d2SSimon Glass .platdata_auto_alloc_size = sizeof(struct dm_test_pdata), 762e7d35d2SSimon Glass }; 772e7d35d2SSimon Glass 782e7d35d2SSimon Glass /* From here is the testfdt uclass code */ 7954c5d08aSHeiko Schocher int testfdt_ping(struct udevice *dev, int pingval, int *pingret) 802e7d35d2SSimon Glass { 812e7d35d2SSimon Glass const struct test_ops *ops = device_get_ops(dev); 822e7d35d2SSimon Glass 832e7d35d2SSimon Glass if (!ops->ping) 842e7d35d2SSimon Glass return -ENOSYS; 852e7d35d2SSimon Glass 862e7d35d2SSimon Glass return ops->ping(dev, pingval, pingret); 872e7d35d2SSimon Glass } 882e7d35d2SSimon Glass 892e7d35d2SSimon Glass UCLASS_DRIVER(testfdt) = { 902e7d35d2SSimon Glass .name = "testfdt", 912e7d35d2SSimon Glass .id = UCLASS_TEST_FDT, 922e7d35d2SSimon Glass }; 932e7d35d2SSimon Glass 94*1ca7e206SSimon Glass int dm_check_devices(struct dm_test_state *dms, int num_devices) 952e7d35d2SSimon Glass { 9654c5d08aSHeiko Schocher struct udevice *dev; 972e7d35d2SSimon Glass int ret; 982e7d35d2SSimon Glass int i; 992e7d35d2SSimon Glass 1002e7d35d2SSimon Glass /* 1012e7d35d2SSimon Glass * Now check that the ping adds are what we expect. This is using the 1022e7d35d2SSimon Glass * ping-add property in each node. 1032e7d35d2SSimon Glass */ 104*1ca7e206SSimon Glass for (i = 0; i < num_devices; i++) { 1052e7d35d2SSimon Glass uint32_t base; 1062e7d35d2SSimon Glass 1072e7d35d2SSimon Glass ret = uclass_get_device(UCLASS_TEST_FDT, i, &dev); 1082e7d35d2SSimon Glass ut_assert(!ret); 1092e7d35d2SSimon Glass 1102e7d35d2SSimon Glass /* 111eb9ef5feSSimon Glass * Get the 'ping-expect' property, which tells us what the 112eb9ef5feSSimon Glass * ping add should be. We don't use the platdata because we 113eb9ef5feSSimon Glass * want to test the code that sets that up 114eb9ef5feSSimon Glass * (testfdt_drv_probe()). 1152e7d35d2SSimon Glass */ 116eb9ef5feSSimon Glass base = fdtdec_get_addr(gd->fdt_blob, dev->of_offset, 117eb9ef5feSSimon Glass "ping-expect"); 1182e7d35d2SSimon Glass debug("dev=%d, base=%d: %s\n", i, base, 1192e7d35d2SSimon Glass fdt_get_name(gd->fdt_blob, dev->of_offset, NULL)); 1202e7d35d2SSimon Glass 1212e7d35d2SSimon Glass ut_assert(!dm_check_operations(dms, dev, base, 1222e7d35d2SSimon Glass dev_get_priv(dev))); 1232e7d35d2SSimon Glass } 1242e7d35d2SSimon Glass 1252e7d35d2SSimon Glass return 0; 1262e7d35d2SSimon Glass } 127*1ca7e206SSimon Glass 128*1ca7e206SSimon Glass /* Test that FDT-based binding works correctly */ 129*1ca7e206SSimon Glass static int dm_test_fdt(struct dm_test_state *dms) 130*1ca7e206SSimon Glass { 131*1ca7e206SSimon Glass const int num_devices = 4; 132*1ca7e206SSimon Glass struct udevice *dev; 133*1ca7e206SSimon Glass struct uclass *uc; 134*1ca7e206SSimon Glass int ret; 135*1ca7e206SSimon Glass int i; 136*1ca7e206SSimon Glass 137*1ca7e206SSimon Glass ret = dm_scan_fdt(gd->fdt_blob, false); 138*1ca7e206SSimon Glass ut_assert(!ret); 139*1ca7e206SSimon Glass 140*1ca7e206SSimon Glass ret = uclass_get(UCLASS_TEST_FDT, &uc); 141*1ca7e206SSimon Glass ut_assert(!ret); 142*1ca7e206SSimon Glass 143*1ca7e206SSimon Glass /* These are num_devices compatible root-level device tree nodes */ 144*1ca7e206SSimon Glass ut_asserteq(num_devices, list_count_items(&uc->dev_head)); 145*1ca7e206SSimon Glass 146*1ca7e206SSimon Glass /* Each should have no platdata / priv */ 147*1ca7e206SSimon Glass for (i = 0; i < num_devices; i++) { 148*1ca7e206SSimon Glass ret = uclass_find_device(UCLASS_TEST_FDT, i, &dev); 149*1ca7e206SSimon Glass ut_assert(!ret); 150*1ca7e206SSimon Glass ut_assert(!dev_get_priv(dev)); 151*1ca7e206SSimon Glass ut_assert(!dev->platdata); 152*1ca7e206SSimon Glass } 153*1ca7e206SSimon Glass 154*1ca7e206SSimon Glass ut_assertok(dm_check_devices(dms, num_devices)); 155*1ca7e206SSimon Glass 156*1ca7e206SSimon Glass return 0; 157*1ca7e206SSimon Glass } 1582e7d35d2SSimon Glass DM_TEST(dm_test_fdt, 0); 15900606d7eSSimon Glass 16000606d7eSSimon Glass static int dm_test_fdt_pre_reloc(struct dm_test_state *dms) 16100606d7eSSimon Glass { 16200606d7eSSimon Glass struct uclass *uc; 16300606d7eSSimon Glass int ret; 16400606d7eSSimon Glass 16500606d7eSSimon Glass ret = dm_scan_fdt(gd->fdt_blob, true); 16600606d7eSSimon Glass ut_assert(!ret); 16700606d7eSSimon Glass 16800606d7eSSimon Glass ret = uclass_get(UCLASS_TEST_FDT, &uc); 16900606d7eSSimon Glass ut_assert(!ret); 17000606d7eSSimon Glass 17100606d7eSSimon Glass /* These is only one pre-reloc device */ 17200606d7eSSimon Glass ut_asserteq(1, list_count_items(&uc->dev_head)); 17300606d7eSSimon Glass 17400606d7eSSimon Glass return 0; 17500606d7eSSimon Glass } 17600606d7eSSimon Glass DM_TEST(dm_test_fdt_pre_reloc, 0); 1775a66a8ffSSimon Glass 1785a66a8ffSSimon Glass /* Test that sequence numbers are allocated properly */ 1795a66a8ffSSimon Glass static int dm_test_fdt_uclass_seq(struct dm_test_state *dms) 1805a66a8ffSSimon Glass { 1815a66a8ffSSimon Glass struct udevice *dev; 1825a66a8ffSSimon Glass 1835a66a8ffSSimon Glass /* A few basic santiy tests */ 1845a66a8ffSSimon Glass ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_FDT, 3, true, &dev)); 1855a66a8ffSSimon Glass ut_asserteq_str("b-test", dev->name); 1865a66a8ffSSimon Glass 1875a66a8ffSSimon Glass ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_FDT, 0, true, &dev)); 1885a66a8ffSSimon Glass ut_asserteq_str("a-test", dev->name); 1895a66a8ffSSimon Glass 1905a66a8ffSSimon Glass ut_asserteq(-ENODEV, uclass_find_device_by_seq(UCLASS_TEST_FDT, 5, 1915a66a8ffSSimon Glass true, &dev)); 1925a66a8ffSSimon Glass ut_asserteq_ptr(NULL, dev); 1935a66a8ffSSimon Glass 1945a66a8ffSSimon Glass /* Test aliases */ 1955a66a8ffSSimon Glass ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT, 6, &dev)); 1965a66a8ffSSimon Glass ut_asserteq_str("e-test", dev->name); 1975a66a8ffSSimon Glass 1985a66a8ffSSimon Glass ut_asserteq(-ENODEV, uclass_find_device_by_seq(UCLASS_TEST_FDT, 7, 1995a66a8ffSSimon Glass true, &dev)); 2005a66a8ffSSimon Glass 201*1ca7e206SSimon Glass /* 202*1ca7e206SSimon Glass * Note that c-test nodes are not probed since it is not a top-level 203*1ca7e206SSimon Glass * node 204*1ca7e206SSimon Glass */ 2055a66a8ffSSimon Glass ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT, 3, &dev)); 2065a66a8ffSSimon Glass ut_asserteq_str("b-test", dev->name); 2075a66a8ffSSimon Glass 2085a66a8ffSSimon Glass /* 2095a66a8ffSSimon Glass * d-test wants sequence number 3 also, but it can't have it because 2105a66a8ffSSimon Glass * b-test gets it first. 2115a66a8ffSSimon Glass */ 2125a66a8ffSSimon Glass ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 2, &dev)); 2135a66a8ffSSimon Glass ut_asserteq_str("d-test", dev->name); 2145a66a8ffSSimon Glass 2155a66a8ffSSimon Glass /* d-test actually gets 0 */ 2165a66a8ffSSimon Glass ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT, 0, &dev)); 2175a66a8ffSSimon Glass ut_asserteq_str("d-test", dev->name); 2185a66a8ffSSimon Glass 2195a66a8ffSSimon Glass /* initially no one wants seq 1 */ 2205a66a8ffSSimon Glass ut_asserteq(-ENODEV, uclass_get_device_by_seq(UCLASS_TEST_FDT, 1, 2215a66a8ffSSimon Glass &dev)); 2225a66a8ffSSimon Glass ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev)); 2235a66a8ffSSimon Glass ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 1, &dev)); 2245a66a8ffSSimon Glass 2255a66a8ffSSimon Glass /* But now that it is probed, we can find it */ 2265a66a8ffSSimon Glass ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT, 1, &dev)); 2275a66a8ffSSimon Glass ut_asserteq_str("a-test", dev->name); 2285a66a8ffSSimon Glass 2295a66a8ffSSimon Glass return 0; 2305a66a8ffSSimon Glass } 2315a66a8ffSSimon Glass DM_TEST(dm_test_fdt_uclass_seq, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); 232f4cdead2SSimon Glass 233f4cdead2SSimon Glass /* Test that we can find a device by device tree offset */ 234f4cdead2SSimon Glass static int dm_test_fdt_offset(struct dm_test_state *dms) 235f4cdead2SSimon Glass { 236f4cdead2SSimon Glass const void *blob = gd->fdt_blob; 237f4cdead2SSimon Glass struct udevice *dev; 238f4cdead2SSimon Glass int node; 239f4cdead2SSimon Glass 240f4cdead2SSimon Glass node = fdt_path_offset(blob, "/e-test"); 241f4cdead2SSimon Glass ut_assert(node > 0); 242f4cdead2SSimon Glass ut_assertok(uclass_get_device_by_of_offset(UCLASS_TEST_FDT, node, 243f4cdead2SSimon Glass &dev)); 244f4cdead2SSimon Glass ut_asserteq_str("e-test", dev->name); 245f4cdead2SSimon Glass 246f4cdead2SSimon Glass /* This node should not be bound */ 247f4cdead2SSimon Glass node = fdt_path_offset(blob, "/junk"); 248f4cdead2SSimon Glass ut_assert(node > 0); 249f4cdead2SSimon Glass ut_asserteq(-ENODEV, uclass_get_device_by_of_offset(UCLASS_TEST_FDT, 250f4cdead2SSimon Glass node, &dev)); 251f4cdead2SSimon Glass 252f4cdead2SSimon Glass /* This is not a top level node so should not be probed */ 253*1ca7e206SSimon Glass node = fdt_path_offset(blob, "/some-bus/c-test@5"); 254f4cdead2SSimon Glass ut_assert(node > 0); 255f4cdead2SSimon Glass ut_asserteq(-ENODEV, uclass_get_device_by_of_offset(UCLASS_TEST_FDT, 256f4cdead2SSimon Glass node, &dev)); 257f4cdead2SSimon Glass 258f4cdead2SSimon Glass return 0; 259f4cdead2SSimon Glass } 260f4cdead2SSimon Glass DM_TEST(dm_test_fdt_offset, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); 261