1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (c) 2014 Google, Inc 4 */ 5 6 #include <common.h> 7 #ifdef CONFIG_SANDBOX 8 #include <os.h> 9 #endif 10 #include <dm.h> 11 #include <dm/device-internal.h> 12 #include <dm/test.h> 13 #include <dm/uclass-internal.h> 14 #include <dm/util.h> 15 #include <test/ut.h> 16 17 DECLARE_GLOBAL_DATA_PTR; 18 19 struct dm_test_parent_platdata { 20 int count; 21 int bind_flag; 22 int uclass_bind_flag; 23 }; 24 25 enum { 26 FLAG_CHILD_PROBED = 10, 27 FLAG_CHILD_REMOVED = -7, 28 }; 29 30 static struct dm_test_state *test_state; 31 32 static int testbus_drv_probe(struct udevice *dev) 33 { 34 return dm_scan_fdt_dev(dev); 35 } 36 37 static int testbus_child_post_bind(struct udevice *dev) 38 { 39 struct dm_test_parent_platdata *plat; 40 41 plat = dev_get_parent_platdata(dev); 42 plat->bind_flag = 1; 43 plat->uclass_bind_flag = 2; 44 45 return 0; 46 } 47 48 static int testbus_child_pre_probe(struct udevice *dev) 49 { 50 struct dm_test_parent_data *parent_data = dev_get_parent_priv(dev); 51 52 parent_data->flag += FLAG_CHILD_PROBED; 53 54 return 0; 55 } 56 57 static int testbus_child_pre_probe_uclass(struct udevice *dev) 58 { 59 struct dm_test_priv *priv = dev_get_priv(dev); 60 61 priv->uclass_flag++; 62 63 return 0; 64 } 65 66 static int testbus_child_post_remove(struct udevice *dev) 67 { 68 struct dm_test_parent_data *parent_data = dev_get_parent_priv(dev); 69 struct dm_test_state *dms = test_state; 70 71 parent_data->flag += FLAG_CHILD_REMOVED; 72 if (dms) 73 dms->removed = dev; 74 75 return 0; 76 } 77 78 static const struct udevice_id testbus_ids[] = { 79 { 80 .compatible = "denx,u-boot-test-bus", 81 .data = DM_TEST_TYPE_FIRST }, 82 { } 83 }; 84 85 U_BOOT_DRIVER(testbus_drv) = { 86 .name = "testbus_drv", 87 .of_match = testbus_ids, 88 .id = UCLASS_TEST_BUS, 89 .probe = testbus_drv_probe, 90 .child_post_bind = testbus_child_post_bind, 91 .priv_auto_alloc_size = sizeof(struct dm_test_priv), 92 .platdata_auto_alloc_size = sizeof(struct dm_test_pdata), 93 .per_child_auto_alloc_size = sizeof(struct dm_test_parent_data), 94 .per_child_platdata_auto_alloc_size = 95 sizeof(struct dm_test_parent_platdata), 96 .child_pre_probe = testbus_child_pre_probe, 97 .child_post_remove = testbus_child_post_remove, 98 }; 99 100 UCLASS_DRIVER(testbus) = { 101 .name = "testbus", 102 .id = UCLASS_TEST_BUS, 103 .flags = DM_UC_FLAG_SEQ_ALIAS, 104 .child_pre_probe = testbus_child_pre_probe_uclass, 105 }; 106 107 /* Test that we can probe for children */ 108 static int dm_test_bus_children(struct unit_test_state *uts) 109 { 110 int num_devices = 7; 111 struct udevice *bus; 112 struct uclass *uc; 113 114 ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc)); 115 ut_asserteq(num_devices, list_count_items(&uc->dev_head)); 116 117 /* Probe the bus, which should yield 3 more devices */ 118 ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); 119 num_devices += 3; 120 121 ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc)); 122 ut_asserteq(num_devices, list_count_items(&uc->dev_head)); 123 124 ut_assert(!dm_check_devices(uts, num_devices)); 125 126 return 0; 127 } 128 DM_TEST(dm_test_bus_children, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); 129 130 /* Test our functions for accessing children */ 131 static int dm_test_bus_children_funcs(struct unit_test_state *uts) 132 { 133 const void *blob = gd->fdt_blob; 134 struct udevice *bus, *dev; 135 int node; 136 137 ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); 138 139 /* device_get_child() */ 140 ut_assertok(device_get_child(bus, 0, &dev)); 141 ut_asserteq(-ENODEV, device_get_child(bus, 4, &dev)); 142 ut_assertok(device_get_child_by_seq(bus, 5, &dev)); 143 ut_assert(dev->flags & DM_FLAG_ACTIVATED); 144 ut_asserteq_str("c-test@5", dev->name); 145 146 /* Device with sequence number 0 should be accessible */ 147 ut_asserteq(-ENODEV, device_find_child_by_seq(bus, -1, true, &dev)); 148 ut_assertok(device_find_child_by_seq(bus, 0, true, &dev)); 149 ut_assert(!(dev->flags & DM_FLAG_ACTIVATED)); 150 ut_asserteq(-ENODEV, device_find_child_by_seq(bus, 0, false, &dev)); 151 ut_assertok(device_get_child_by_seq(bus, 0, &dev)); 152 ut_assert(dev->flags & DM_FLAG_ACTIVATED); 153 154 /* There is no device with sequence number 2 */ 155 ut_asserteq(-ENODEV, device_find_child_by_seq(bus, 2, false, &dev)); 156 ut_asserteq(-ENODEV, device_find_child_by_seq(bus, 2, true, &dev)); 157 ut_asserteq(-ENODEV, device_get_child_by_seq(bus, 2, &dev)); 158 159 /* Looking for something that is not a child */ 160 node = fdt_path_offset(blob, "/junk"); 161 ut_asserteq(-ENODEV, device_find_child_by_of_offset(bus, node, &dev)); 162 node = fdt_path_offset(blob, "/d-test"); 163 ut_asserteq(-ENODEV, device_find_child_by_of_offset(bus, node, &dev)); 164 165 return 0; 166 } 167 DM_TEST(dm_test_bus_children_funcs, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); 168 169 static int dm_test_bus_children_of_offset(struct unit_test_state *uts) 170 { 171 const void *blob = gd->fdt_blob; 172 struct udevice *bus, *dev; 173 int node; 174 175 ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); 176 ut_assertnonnull(bus); 177 178 /* Find a valid child */ 179 node = fdt_path_offset(blob, "/some-bus/c-test@1"); 180 ut_assert(node > 0); 181 ut_assertok(device_find_child_by_of_offset(bus, node, &dev)); 182 ut_assertnonnull(dev); 183 ut_assert(!(dev->flags & DM_FLAG_ACTIVATED)); 184 ut_assertok(device_get_child_by_of_offset(bus, node, &dev)); 185 ut_assertnonnull(dev); 186 ut_assert(dev->flags & DM_FLAG_ACTIVATED); 187 188 return 0; 189 } 190 DM_TEST(dm_test_bus_children_of_offset, 191 DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT | DM_TESTF_FLAT_TREE); 192 193 /* Test that we can iterate through children */ 194 static int dm_test_bus_children_iterators(struct unit_test_state *uts) 195 { 196 struct udevice *bus, *dev, *child; 197 198 /* Walk through the children one by one */ 199 ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); 200 ut_assertok(device_find_first_child(bus, &dev)); 201 ut_asserteq_str("c-test@5", dev->name); 202 ut_assertok(device_find_next_child(&dev)); 203 ut_asserteq_str("c-test@0", dev->name); 204 ut_assertok(device_find_next_child(&dev)); 205 ut_asserteq_str("c-test@1", dev->name); 206 ut_assertok(device_find_next_child(&dev)); 207 ut_asserteq_ptr(dev, NULL); 208 209 /* Move to the next child without using device_find_first_child() */ 210 ut_assertok(device_find_child_by_seq(bus, 5, true, &dev)); 211 ut_asserteq_str("c-test@5", dev->name); 212 ut_assertok(device_find_next_child(&dev)); 213 ut_asserteq_str("c-test@0", dev->name); 214 215 /* Try a device with no children */ 216 ut_assertok(device_find_first_child(dev, &child)); 217 ut_asserteq_ptr(child, NULL); 218 219 return 0; 220 } 221 DM_TEST(dm_test_bus_children_iterators, 222 DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); 223 224 /* Test that the bus can store data about each child */ 225 static int test_bus_parent_data(struct unit_test_state *uts) 226 { 227 struct dm_test_parent_data *parent_data; 228 struct udevice *bus, *dev; 229 struct uclass *uc; 230 int value; 231 232 ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); 233 234 /* Check that parent data is allocated */ 235 ut_assertok(device_find_child_by_seq(bus, 0, true, &dev)); 236 ut_asserteq_ptr(NULL, dev_get_parent_priv(dev)); 237 ut_assertok(device_get_child_by_seq(bus, 0, &dev)); 238 parent_data = dev_get_parent_priv(dev); 239 ut_assert(NULL != parent_data); 240 241 /* Check that it starts at 0 and goes away when device is removed */ 242 parent_data->sum += 5; 243 ut_asserteq(5, parent_data->sum); 244 device_remove(dev, DM_REMOVE_NORMAL); 245 ut_asserteq_ptr(NULL, dev_get_parent_priv(dev)); 246 247 /* Check that we can do this twice */ 248 ut_assertok(device_get_child_by_seq(bus, 0, &dev)); 249 parent_data = dev_get_parent_priv(dev); 250 ut_assert(NULL != parent_data); 251 parent_data->sum += 5; 252 ut_asserteq(5, parent_data->sum); 253 254 /* Add parent data to all children */ 255 ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc)); 256 value = 5; 257 uclass_foreach_dev(dev, uc) { 258 /* Ignore these if they are not on this bus */ 259 if (dev->parent != bus) { 260 ut_asserteq_ptr(NULL, dev_get_parent_priv(dev)); 261 continue; 262 } 263 ut_assertok(device_probe(dev)); 264 parent_data = dev_get_parent_priv(dev); 265 266 parent_data->sum = value; 267 value += 5; 268 } 269 270 /* Check it is still there */ 271 value = 5; 272 uclass_foreach_dev(dev, uc) { 273 /* Ignore these if they are not on this bus */ 274 if (dev->parent != bus) 275 continue; 276 parent_data = dev_get_parent_priv(dev); 277 278 ut_asserteq(value, parent_data->sum); 279 value += 5; 280 } 281 282 return 0; 283 } 284 /* Test that the bus can store data about each child */ 285 static int dm_test_bus_parent_data(struct unit_test_state *uts) 286 { 287 return test_bus_parent_data(uts); 288 } 289 DM_TEST(dm_test_bus_parent_data, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); 290 291 /* As above but the size is controlled by the uclass */ 292 static int dm_test_bus_parent_data_uclass(struct unit_test_state *uts) 293 { 294 struct driver *drv; 295 struct udevice *bus; 296 int size; 297 int ret; 298 299 /* Set the driver size to 0 so that the uclass size is used */ 300 ut_assertok(uclass_find_device(UCLASS_TEST_BUS, 0, &bus)); 301 drv = (struct driver *)bus->driver; 302 size = drv->per_child_auto_alloc_size; 303 304 #ifdef CONFIG_SANDBOX 305 os_mprotect_allow(bus->uclass->uc_drv, sizeof(*bus->uclass->uc_drv)); 306 os_mprotect_allow(drv, sizeof(*drv)); 307 #endif 308 bus->uclass->uc_drv->per_child_auto_alloc_size = size; 309 drv->per_child_auto_alloc_size = 0; 310 ret = test_bus_parent_data(uts); 311 if (ret) 312 return ret; 313 bus->uclass->uc_drv->per_child_auto_alloc_size = 0; 314 drv->per_child_auto_alloc_size = size; 315 316 return 0; 317 } 318 DM_TEST(dm_test_bus_parent_data_uclass, 319 DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); 320 321 /* Test that the bus ops are called when a child is probed/removed */ 322 static int dm_test_bus_parent_ops(struct unit_test_state *uts) 323 { 324 struct dm_test_parent_data *parent_data; 325 struct dm_test_state *dms = uts->priv; 326 struct udevice *bus, *dev; 327 struct uclass *uc; 328 329 test_state = dms; 330 ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); 331 ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc)); 332 333 uclass_foreach_dev(dev, uc) { 334 /* Ignore these if they are not on this bus */ 335 if (dev->parent != bus) 336 continue; 337 ut_asserteq_ptr(NULL, dev_get_parent_priv(dev)); 338 339 ut_assertok(device_probe(dev)); 340 parent_data = dev_get_parent_priv(dev); 341 ut_asserteq(FLAG_CHILD_PROBED, parent_data->flag); 342 } 343 344 uclass_foreach_dev(dev, uc) { 345 /* Ignore these if they are not on this bus */ 346 if (dev->parent != bus) 347 continue; 348 parent_data = dev_get_parent_priv(dev); 349 ut_asserteq(FLAG_CHILD_PROBED, parent_data->flag); 350 ut_assertok(device_remove(dev, DM_REMOVE_NORMAL)); 351 ut_asserteq_ptr(NULL, dev_get_parent_priv(dev)); 352 ut_asserteq_ptr(dms->removed, dev); 353 } 354 test_state = NULL; 355 356 return 0; 357 } 358 DM_TEST(dm_test_bus_parent_ops, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); 359 360 static int test_bus_parent_platdata(struct unit_test_state *uts) 361 { 362 struct dm_test_parent_platdata *plat; 363 struct udevice *bus, *dev; 364 int child_count; 365 366 /* Check that the bus has no children */ 367 ut_assertok(uclass_find_device(UCLASS_TEST_BUS, 0, &bus)); 368 device_find_first_child(bus, &dev); 369 ut_asserteq_ptr(NULL, dev); 370 371 ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); 372 373 for (device_find_first_child(bus, &dev), child_count = 0; 374 dev; 375 device_find_next_child(&dev)) { 376 /* Check that platform data is allocated */ 377 plat = dev_get_parent_platdata(dev); 378 ut_assert(plat != NULL); 379 380 /* 381 * Check that it is not affected by the device being 382 * probed/removed 383 */ 384 plat->count++; 385 ut_asserteq(1, plat->count); 386 device_probe(dev); 387 device_remove(dev, DM_REMOVE_NORMAL); 388 389 ut_asserteq_ptr(plat, dev_get_parent_platdata(dev)); 390 ut_asserteq(1, plat->count); 391 ut_assertok(device_probe(dev)); 392 child_count++; 393 } 394 ut_asserteq(3, child_count); 395 396 /* Removing the bus should also have no effect (it is still bound) */ 397 device_remove(bus, DM_REMOVE_NORMAL); 398 for (device_find_first_child(bus, &dev), child_count = 0; 399 dev; 400 device_find_next_child(&dev)) { 401 /* Check that platform data is allocated */ 402 plat = dev_get_parent_platdata(dev); 403 ut_assert(plat != NULL); 404 ut_asserteq(1, plat->count); 405 child_count++; 406 } 407 ut_asserteq(3, child_count); 408 409 /* Unbind all the children */ 410 do { 411 device_find_first_child(bus, &dev); 412 if (dev) 413 device_unbind(dev); 414 } while (dev); 415 416 /* Now the child platdata should be removed and re-added */ 417 device_probe(bus); 418 for (device_find_first_child(bus, &dev), child_count = 0; 419 dev; 420 device_find_next_child(&dev)) { 421 /* Check that platform data is allocated */ 422 plat = dev_get_parent_platdata(dev); 423 ut_assert(plat != NULL); 424 ut_asserteq(0, plat->count); 425 child_count++; 426 } 427 ut_asserteq(3, child_count); 428 429 return 0; 430 } 431 432 /* Test that the bus can store platform data about each child */ 433 static int dm_test_bus_parent_platdata(struct unit_test_state *uts) 434 { 435 return test_bus_parent_platdata(uts); 436 } 437 DM_TEST(dm_test_bus_parent_platdata, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); 438 439 /* As above but the size is controlled by the uclass */ 440 static int dm_test_bus_parent_platdata_uclass(struct unit_test_state *uts) 441 { 442 struct udevice *bus; 443 struct driver *drv; 444 int size; 445 int ret; 446 447 /* Set the driver size to 0 so that the uclass size is used */ 448 ut_assertok(uclass_find_device(UCLASS_TEST_BUS, 0, &bus)); 449 drv = (struct driver *)bus->driver; 450 size = drv->per_child_platdata_auto_alloc_size; 451 #ifdef CONFIG_SANDBOX 452 os_mprotect_allow(bus->uclass->uc_drv, sizeof(*bus->uclass->uc_drv)); 453 os_mprotect_allow(drv, sizeof(*drv)); 454 #endif 455 bus->uclass->uc_drv->per_child_platdata_auto_alloc_size = size; 456 drv->per_child_platdata_auto_alloc_size = 0; 457 ret = test_bus_parent_platdata(uts); 458 if (ret) 459 return ret; 460 bus->uclass->uc_drv->per_child_platdata_auto_alloc_size = 0; 461 drv->per_child_platdata_auto_alloc_size = size; 462 463 return 0; 464 } 465 DM_TEST(dm_test_bus_parent_platdata_uclass, 466 DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); 467 468 /* Test that the child post_bind method is called */ 469 static int dm_test_bus_child_post_bind(struct unit_test_state *uts) 470 { 471 struct dm_test_parent_platdata *plat; 472 struct udevice *bus, *dev; 473 int child_count; 474 475 ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); 476 for (device_find_first_child(bus, &dev), child_count = 0; 477 dev; 478 device_find_next_child(&dev)) { 479 /* Check that platform data is allocated */ 480 plat = dev_get_parent_platdata(dev); 481 ut_assert(plat != NULL); 482 ut_asserteq(1, plat->bind_flag); 483 child_count++; 484 } 485 ut_asserteq(3, child_count); 486 487 return 0; 488 } 489 DM_TEST(dm_test_bus_child_post_bind, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); 490 491 /* Test that the child post_bind method is called */ 492 static int dm_test_bus_child_post_bind_uclass(struct unit_test_state *uts) 493 { 494 struct dm_test_parent_platdata *plat; 495 struct udevice *bus, *dev; 496 int child_count; 497 498 ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); 499 for (device_find_first_child(bus, &dev), child_count = 0; 500 dev; 501 device_find_next_child(&dev)) { 502 /* Check that platform data is allocated */ 503 plat = dev_get_parent_platdata(dev); 504 ut_assert(plat != NULL); 505 ut_asserteq(2, plat->uclass_bind_flag); 506 child_count++; 507 } 508 ut_asserteq(3, child_count); 509 510 return 0; 511 } 512 DM_TEST(dm_test_bus_child_post_bind_uclass, 513 DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); 514 515 /* 516 * Test that the bus' uclass' child_pre_probe() is called before the 517 * device's probe() method 518 */ 519 static int dm_test_bus_child_pre_probe_uclass(struct unit_test_state *uts) 520 { 521 struct udevice *bus, *dev; 522 int child_count; 523 524 /* 525 * See testfdt_drv_probe() which effectively checks that the uclass 526 * flag is set before that method is called 527 */ 528 ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); 529 for (device_find_first_child(bus, &dev), child_count = 0; 530 dev; 531 device_find_next_child(&dev)) { 532 struct dm_test_priv *priv = dev_get_priv(dev); 533 534 /* Check that things happened in the right order */ 535 ut_asserteq_ptr(NULL, priv); 536 ut_assertok(device_probe(dev)); 537 538 priv = dev_get_priv(dev); 539 ut_assert(priv != NULL); 540 ut_asserteq(1, priv->uclass_flag); 541 ut_asserteq(1, priv->uclass_total); 542 child_count++; 543 } 544 ut_asserteq(3, child_count); 545 546 return 0; 547 } 548 DM_TEST(dm_test_bus_child_pre_probe_uclass, 549 DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); 550