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