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