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/device-internal.h> 16 #include <dm/uclass-internal.h> 17 #include <dm/util.h> 18 #include <test/ut.h> 19 20 DECLARE_GLOBAL_DATA_PTR; 21 22 static int testfdt_drv_ping(struct udevice *dev, int pingval, int *pingret) 23 { 24 const struct dm_test_pdata *pdata = dev->platdata; 25 struct dm_test_priv *priv = dev_get_priv(dev); 26 27 *pingret = pingval + pdata->ping_add; 28 priv->ping_total += *pingret; 29 30 return 0; 31 } 32 33 static const struct test_ops test_ops = { 34 .ping = testfdt_drv_ping, 35 }; 36 37 static int testfdt_ofdata_to_platdata(struct udevice *dev) 38 { 39 struct dm_test_pdata *pdata = dev_get_platdata(dev); 40 41 pdata->ping_add = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), 42 "ping-add", -1); 43 pdata->base = fdtdec_get_addr(gd->fdt_blob, dev_of_offset(dev), 44 "ping-expect"); 45 46 return 0; 47 } 48 49 static int testfdt_drv_probe(struct udevice *dev) 50 { 51 struct dm_test_priv *priv = dev_get_priv(dev); 52 53 priv->ping_total += DM_TEST_START_TOTAL; 54 55 /* 56 * If this device is on a bus, the uclass_flag will be set before 57 * calling this function. This is used by 58 * dm_test_bus_child_pre_probe_uclass(). 59 */ 60 priv->uclass_total += priv->uclass_flag; 61 62 return 0; 63 } 64 65 static const struct udevice_id testfdt_ids[] = { 66 { 67 .compatible = "denx,u-boot-fdt-test", 68 .data = DM_TEST_TYPE_FIRST }, 69 { 70 .compatible = "google,another-fdt-test", 71 .data = DM_TEST_TYPE_SECOND }, 72 { } 73 }; 74 75 U_BOOT_DRIVER(testfdt_drv) = { 76 .name = "testfdt_drv", 77 .of_match = testfdt_ids, 78 .id = UCLASS_TEST_FDT, 79 .ofdata_to_platdata = testfdt_ofdata_to_platdata, 80 .probe = testfdt_drv_probe, 81 .ops = &test_ops, 82 .priv_auto_alloc_size = sizeof(struct dm_test_priv), 83 .platdata_auto_alloc_size = sizeof(struct dm_test_pdata), 84 }; 85 86 /* From here is the testfdt uclass code */ 87 int testfdt_ping(struct udevice *dev, int pingval, int *pingret) 88 { 89 const struct test_ops *ops = device_get_ops(dev); 90 91 if (!ops->ping) 92 return -ENOSYS; 93 94 return ops->ping(dev, pingval, pingret); 95 } 96 97 UCLASS_DRIVER(testfdt) = { 98 .name = "testfdt", 99 .id = UCLASS_TEST_FDT, 100 .flags = DM_UC_FLAG_SEQ_ALIAS, 101 }; 102 103 struct dm_testprobe_pdata { 104 int probe_err; 105 }; 106 107 static int testprobe_drv_probe(struct udevice *dev) 108 { 109 struct dm_testprobe_pdata *pdata = dev_get_platdata(dev); 110 111 return pdata->probe_err; 112 } 113 114 static const struct udevice_id testprobe_ids[] = { 115 { .compatible = "denx,u-boot-probe-test" }, 116 { } 117 }; 118 119 U_BOOT_DRIVER(testprobe_drv) = { 120 .name = "testprobe_drv", 121 .of_match = testprobe_ids, 122 .id = UCLASS_TEST_PROBE, 123 .probe = testprobe_drv_probe, 124 .platdata_auto_alloc_size = sizeof(struct dm_testprobe_pdata), 125 }; 126 127 UCLASS_DRIVER(testprobe) = { 128 .name = "testprobe", 129 .id = UCLASS_TEST_PROBE, 130 .flags = DM_UC_FLAG_SEQ_ALIAS, 131 }; 132 133 int dm_check_devices(struct unit_test_state *uts, int num_devices) 134 { 135 struct udevice *dev; 136 int ret; 137 int i; 138 139 /* 140 * Now check that the ping adds are what we expect. This is using the 141 * ping-add property in each node. 142 */ 143 for (i = 0; i < num_devices; i++) { 144 uint32_t base; 145 146 ret = uclass_get_device(UCLASS_TEST_FDT, i, &dev); 147 ut_assert(!ret); 148 149 /* 150 * Get the 'ping-expect' property, which tells us what the 151 * ping add should be. We don't use the platdata because we 152 * want to test the code that sets that up 153 * (testfdt_drv_probe()). 154 */ 155 base = fdtdec_get_addr(gd->fdt_blob, dev_of_offset(dev), 156 "ping-expect"); 157 debug("dev=%d, base=%d: %s\n", i, base, 158 fdt_get_name(gd->fdt_blob, dev_of_offset(dev), NULL)); 159 160 ut_assert(!dm_check_operations(uts, dev, base, 161 dev_get_priv(dev))); 162 } 163 164 return 0; 165 } 166 167 /* Test that FDT-based binding works correctly */ 168 static int dm_test_fdt(struct unit_test_state *uts) 169 { 170 const int num_devices = 7; 171 struct udevice *dev; 172 struct uclass *uc; 173 int ret; 174 int i; 175 176 ret = dm_scan_fdt(gd->fdt_blob, false); 177 ut_assert(!ret); 178 179 ret = uclass_get(UCLASS_TEST_FDT, &uc); 180 ut_assert(!ret); 181 182 /* These are num_devices compatible root-level device tree nodes */ 183 ut_asserteq(num_devices, list_count_items(&uc->dev_head)); 184 185 /* Each should have platform data but no private data */ 186 for (i = 0; i < num_devices; i++) { 187 ret = uclass_find_device(UCLASS_TEST_FDT, i, &dev); 188 ut_assert(!ret); 189 ut_assert(!dev_get_priv(dev)); 190 ut_assert(dev->platdata); 191 } 192 193 ut_assertok(dm_check_devices(uts, num_devices)); 194 195 return 0; 196 } 197 DM_TEST(dm_test_fdt, 0); 198 199 static int dm_test_fdt_pre_reloc(struct unit_test_state *uts) 200 { 201 struct uclass *uc; 202 int ret; 203 204 ret = dm_scan_fdt(gd->fdt_blob, true); 205 ut_assert(!ret); 206 207 ret = uclass_get(UCLASS_TEST_FDT, &uc); 208 ut_assert(!ret); 209 210 /* These is only one pre-reloc device */ 211 ut_asserteq(1, list_count_items(&uc->dev_head)); 212 213 return 0; 214 } 215 DM_TEST(dm_test_fdt_pre_reloc, 0); 216 217 /* Test that sequence numbers are allocated properly */ 218 static int dm_test_fdt_uclass_seq(struct unit_test_state *uts) 219 { 220 struct udevice *dev; 221 222 /* A few basic santiy tests */ 223 ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_FDT, 3, true, &dev)); 224 ut_asserteq_str("b-test", dev->name); 225 226 ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_FDT, 8, true, &dev)); 227 ut_asserteq_str("a-test", dev->name); 228 229 ut_asserteq(-ENODEV, uclass_find_device_by_seq(UCLASS_TEST_FDT, 5, 230 true, &dev)); 231 ut_asserteq_ptr(NULL, dev); 232 233 /* Test aliases */ 234 ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT, 6, &dev)); 235 ut_asserteq_str("e-test", dev->name); 236 237 ut_asserteq(-ENODEV, uclass_find_device_by_seq(UCLASS_TEST_FDT, 7, 238 true, &dev)); 239 240 /* 241 * Note that c-test nodes are not probed since it is not a top-level 242 * node 243 */ 244 ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT, 3, &dev)); 245 ut_asserteq_str("b-test", dev->name); 246 247 /* 248 * d-test wants sequence number 3 also, but it can't have it because 249 * b-test gets it first. 250 */ 251 ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 2, &dev)); 252 ut_asserteq_str("d-test", dev->name); 253 254 /* d-test actually gets 0 */ 255 ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT, 0, &dev)); 256 ut_asserteq_str("d-test", dev->name); 257 258 /* initially no one wants seq 1 */ 259 ut_asserteq(-ENODEV, uclass_get_device_by_seq(UCLASS_TEST_FDT, 1, 260 &dev)); 261 ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev)); 262 ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 4, &dev)); 263 264 /* But now that it is probed, we can find it */ 265 ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT, 1, &dev)); 266 ut_asserteq_str("f-test", dev->name); 267 268 return 0; 269 } 270 DM_TEST(dm_test_fdt_uclass_seq, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); 271 272 /* Test that we can find a device by device tree offset */ 273 static int dm_test_fdt_offset(struct unit_test_state *uts) 274 { 275 const void *blob = gd->fdt_blob; 276 struct udevice *dev; 277 int node; 278 279 node = fdt_path_offset(blob, "/e-test"); 280 ut_assert(node > 0); 281 ut_assertok(uclass_get_device_by_of_offset(UCLASS_TEST_FDT, node, 282 &dev)); 283 ut_asserteq_str("e-test", dev->name); 284 285 /* This node should not be bound */ 286 node = fdt_path_offset(blob, "/junk"); 287 ut_assert(node > 0); 288 ut_asserteq(-ENODEV, uclass_get_device_by_of_offset(UCLASS_TEST_FDT, 289 node, &dev)); 290 291 /* This is not a top level node so should not be probed */ 292 node = fdt_path_offset(blob, "/some-bus/c-test@5"); 293 ut_assert(node > 0); 294 ut_asserteq(-ENODEV, uclass_get_device_by_of_offset(UCLASS_TEST_FDT, 295 node, &dev)); 296 297 return 0; 298 } 299 DM_TEST(dm_test_fdt_offset, 300 DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT | DM_TESTF_FLAT_TREE); 301 302 /** 303 * Test various error conditions with uclass_first_device() and 304 * uclass_next_device() 305 */ 306 static int dm_test_first_next_device(struct unit_test_state *uts) 307 { 308 struct dm_testprobe_pdata *pdata; 309 struct udevice *dev, *parent = NULL; 310 int count; 311 int ret; 312 313 /* There should be 4 devices */ 314 for (ret = uclass_first_device(UCLASS_TEST_PROBE, &dev), count = 0; 315 dev; 316 ret = uclass_next_device(&dev)) { 317 count++; 318 parent = dev_get_parent(dev); 319 } 320 ut_assertok(ret); 321 ut_asserteq(4, count); 322 323 /* Remove them and try again, with an error on the second one */ 324 ut_assertok(uclass_get_device(UCLASS_TEST_PROBE, 1, &dev)); 325 pdata = dev_get_platdata(dev); 326 pdata->probe_err = -ENOMEM; 327 device_remove(parent, DM_REMOVE_NORMAL); 328 ut_assertok(uclass_first_device(UCLASS_TEST_PROBE, &dev)); 329 ut_asserteq(-ENOMEM, uclass_next_device(&dev)); 330 ut_asserteq_ptr(dev, NULL); 331 332 /* Now an error on the first one */ 333 ut_assertok(uclass_get_device(UCLASS_TEST_PROBE, 0, &dev)); 334 pdata = dev_get_platdata(dev); 335 pdata->probe_err = -ENOENT; 336 device_remove(parent, DM_REMOVE_NORMAL); 337 ut_asserteq(-ENOENT, uclass_first_device(UCLASS_TEST_PROBE, &dev)); 338 339 return 0; 340 } 341 DM_TEST(dm_test_first_next_device, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); 342 343 /** 344 * check_devices() - Check return values and pointers 345 * 346 * This runs through a full sequence of uclass_first_device_check()... 347 * uclass_next_device_check() checking that the return values and devices 348 * are correct. 349 * 350 * @uts: Test state 351 * @devlist: List of expected devices 352 * @mask: Indicates which devices should return an error. Device n should 353 * return error (-NOENT - n) if bit n is set, or no error (i.e. 0) if 354 * bit n is clear. 355 */ 356 static int check_devices(struct unit_test_state *uts, 357 struct udevice *devlist[], int mask) 358 { 359 int expected_ret; 360 struct udevice *dev; 361 int i; 362 363 expected_ret = (mask & 1) ? -ENOENT : 0; 364 mask >>= 1; 365 ut_asserteq(expected_ret, 366 uclass_first_device_check(UCLASS_TEST_PROBE, &dev)); 367 for (i = 0; i < 4; i++) { 368 ut_asserteq_ptr(devlist[i], dev); 369 expected_ret = (mask & 1) ? -ENOENT - (i + 1) : 0; 370 mask >>= 1; 371 ut_asserteq(expected_ret, uclass_next_device_check(&dev)); 372 } 373 ut_asserteq_ptr(NULL, dev); 374 375 return 0; 376 } 377 378 /* Test uclass_first_device_check() and uclass_next_device_check() */ 379 static int dm_test_first_next_ok_device(struct unit_test_state *uts) 380 { 381 struct dm_testprobe_pdata *pdata; 382 struct udevice *dev, *parent = NULL, *devlist[4]; 383 int count; 384 int ret; 385 386 /* There should be 4 devices */ 387 count = 0; 388 for (ret = uclass_first_device_check(UCLASS_TEST_PROBE, &dev); 389 dev; 390 ret = uclass_next_device_check(&dev)) { 391 ut_assertok(ret); 392 devlist[count++] = dev; 393 parent = dev_get_parent(dev); 394 } 395 ut_asserteq(4, count); 396 ut_assertok(uclass_first_device_check(UCLASS_TEST_PROBE, &dev)); 397 ut_assertok(check_devices(uts, devlist, 0)); 398 399 /* Remove them and try again, with an error on the second one */ 400 pdata = dev_get_platdata(devlist[1]); 401 pdata->probe_err = -ENOENT - 1; 402 device_remove(parent, DM_REMOVE_NORMAL); 403 ut_assertok(check_devices(uts, devlist, 1 << 1)); 404 405 /* Now an error on the first one */ 406 pdata = dev_get_platdata(devlist[0]); 407 pdata->probe_err = -ENOENT - 0; 408 device_remove(parent, DM_REMOVE_NORMAL); 409 ut_assertok(check_devices(uts, devlist, 3 << 0)); 410 411 /* Now errors on all */ 412 pdata = dev_get_platdata(devlist[2]); 413 pdata->probe_err = -ENOENT - 2; 414 pdata = dev_get_platdata(devlist[3]); 415 pdata->probe_err = -ENOENT - 3; 416 device_remove(parent, DM_REMOVE_NORMAL); 417 ut_assertok(check_devices(uts, devlist, 0xf << 0)); 418 419 return 0; 420 } 421 DM_TEST(dm_test_first_next_ok_device, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); 422