1 /* 2 * Copyright (c) 2013 Google, Inc 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <dm.h> 9 #include <errno.h> 10 #include <fdtdec.h> 11 #include <malloc.h> 12 #include <asm/io.h> 13 #include <dm/test.h> 14 #include <dm/root.h> 15 #include <dm/ut.h> 16 #include <dm/uclass-internal.h> 17 #include <dm/util.h> 18 19 DECLARE_GLOBAL_DATA_PTR; 20 21 static int testfdt_drv_ping(struct device *dev, int pingval, int *pingret) 22 { 23 const struct dm_test_pdata *pdata = dev->platdata; 24 struct dm_test_priv *priv = dev_get_priv(dev); 25 26 *pingret = pingval + pdata->ping_add; 27 priv->ping_total += *pingret; 28 29 return 0; 30 } 31 32 static const struct test_ops test_ops = { 33 .ping = testfdt_drv_ping, 34 }; 35 36 static int testfdt_ofdata_to_platdata(struct device *dev) 37 { 38 struct dm_test_pdata *pdata = dev_get_platdata(dev); 39 40 pdata->ping_add = fdtdec_get_int(gd->fdt_blob, dev->of_offset, 41 "ping-add", -1); 42 pdata->base = fdtdec_get_addr(gd->fdt_blob, dev->of_offset, "reg"); 43 44 return 0; 45 } 46 47 static int testfdt_drv_probe(struct device *dev) 48 { 49 struct dm_test_priv *priv = dev_get_priv(dev); 50 51 priv->ping_total += DM_TEST_START_TOTAL; 52 53 return 0; 54 } 55 56 static const struct device_id testfdt_ids[] = { 57 { 58 .compatible = "denx,u-boot-fdt-test", 59 .data = DM_TEST_TYPE_FIRST }, 60 { 61 .compatible = "google,another-fdt-test", 62 .data = DM_TEST_TYPE_SECOND }, 63 { } 64 }; 65 66 U_BOOT_DRIVER(testfdt_drv) = { 67 .name = "testfdt_drv", 68 .of_match = testfdt_ids, 69 .id = UCLASS_TEST_FDT, 70 .ofdata_to_platdata = testfdt_ofdata_to_platdata, 71 .probe = testfdt_drv_probe, 72 .ops = &test_ops, 73 .priv_auto_alloc_size = sizeof(struct dm_test_priv), 74 .platdata_auto_alloc_size = sizeof(struct dm_test_pdata), 75 }; 76 77 /* From here is the testfdt uclass code */ 78 int testfdt_ping(struct device *dev, int pingval, int *pingret) 79 { 80 const struct test_ops *ops = device_get_ops(dev); 81 82 if (!ops->ping) 83 return -ENOSYS; 84 85 return ops->ping(dev, pingval, pingret); 86 } 87 88 UCLASS_DRIVER(testfdt) = { 89 .name = "testfdt", 90 .id = UCLASS_TEST_FDT, 91 }; 92 93 /* Test that FDT-based binding works correctly */ 94 static int dm_test_fdt(struct dm_test_state *dms) 95 { 96 const int num_drivers = 3; 97 struct device *dev; 98 struct uclass *uc; 99 int ret; 100 int i; 101 102 ret = dm_scan_fdt(gd->fdt_blob); 103 ut_assert(!ret); 104 105 ret = uclass_get(UCLASS_TEST_FDT, &uc); 106 ut_assert(!ret); 107 108 /* These are num_drivers compatible root-level device tree nodes */ 109 ut_asserteq(num_drivers, list_count_items(&uc->dev_head)); 110 111 /* Each should have no platdata / priv */ 112 for (i = 0; i < num_drivers; i++) { 113 ret = uclass_find_device(UCLASS_TEST_FDT, i, &dev); 114 ut_assert(!ret); 115 ut_assert(!dev_get_priv(dev)); 116 ut_assert(!dev->platdata); 117 } 118 119 /* 120 * Now check that the ping adds are what we expect. This is using the 121 * ping-add property in each node. 122 */ 123 for (i = 0; i < num_drivers; i++) { 124 uint32_t base; 125 126 ret = uclass_get_device(UCLASS_TEST_FDT, i, &dev); 127 ut_assert(!ret); 128 129 /* 130 * Get the 'reg' property, which tells us what the ping add 131 * should be. We don't use the platdata because we want 132 * to test the code that sets that up (testfdt_drv_probe()). 133 */ 134 base = fdtdec_get_addr(gd->fdt_blob, dev->of_offset, "reg"); 135 debug("dev=%d, base=%d: %s\n", i, base, 136 fdt_get_name(gd->fdt_blob, dev->of_offset, NULL)); 137 138 ut_assert(!dm_check_operations(dms, dev, base, 139 dev_get_priv(dev))); 140 } 141 142 return 0; 143 } 144 DM_TEST(dm_test_fdt, 0); 145