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