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 = 6; 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 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_assert(!(dev->flags & DM_FLAG_ACTIVATED)); 180 ut_assertok(device_get_child_by_of_offset(bus, node, &dev)); 181 ut_assert(dev->flags & DM_FLAG_ACTIVATED); 182 183 return 0; 184 } 185 DM_TEST(dm_test_bus_children_of_offset, 186 DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT | DM_TESTF_FLAT_TREE); 187 188 /* Test that we can iterate through children */ 189 static int dm_test_bus_children_iterators(struct unit_test_state *uts) 190 { 191 struct udevice *bus, *dev, *child; 192 193 /* Walk through the children one by one */ 194 ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); 195 ut_assertok(device_find_first_child(bus, &dev)); 196 ut_asserteq_str("c-test@5", dev->name); 197 ut_assertok(device_find_next_child(&dev)); 198 ut_asserteq_str("c-test@0", dev->name); 199 ut_assertok(device_find_next_child(&dev)); 200 ut_asserteq_str("c-test@1", dev->name); 201 ut_assertok(device_find_next_child(&dev)); 202 ut_asserteq_ptr(dev, NULL); 203 204 /* Move to the next child without using device_find_first_child() */ 205 ut_assertok(device_find_child_by_seq(bus, 5, true, &dev)); 206 ut_asserteq_str("c-test@5", dev->name); 207 ut_assertok(device_find_next_child(&dev)); 208 ut_asserteq_str("c-test@0", dev->name); 209 210 /* Try a device with no children */ 211 ut_assertok(device_find_first_child(dev, &child)); 212 ut_asserteq_ptr(child, NULL); 213 214 return 0; 215 } 216 DM_TEST(dm_test_bus_children_iterators, 217 DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); 218 219 /* Test that the bus can store data about each child */ 220 static int test_bus_parent_data(struct unit_test_state *uts) 221 { 222 struct dm_test_parent_data *parent_data; 223 struct udevice *bus, *dev; 224 struct uclass *uc; 225 int value; 226 227 ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); 228 229 /* Check that parent data is allocated */ 230 ut_assertok(device_find_child_by_seq(bus, 0, true, &dev)); 231 ut_asserteq_ptr(NULL, dev_get_parent_priv(dev)); 232 ut_assertok(device_get_child_by_seq(bus, 0, &dev)); 233 parent_data = dev_get_parent_priv(dev); 234 ut_assert(NULL != parent_data); 235 236 /* Check that it starts at 0 and goes away when device is removed */ 237 parent_data->sum += 5; 238 ut_asserteq(5, parent_data->sum); 239 device_remove(dev, DM_REMOVE_NORMAL); 240 ut_asserteq_ptr(NULL, dev_get_parent_priv(dev)); 241 242 /* Check that we can do this twice */ 243 ut_assertok(device_get_child_by_seq(bus, 0, &dev)); 244 parent_data = dev_get_parent_priv(dev); 245 ut_assert(NULL != parent_data); 246 parent_data->sum += 5; 247 ut_asserteq(5, parent_data->sum); 248 249 /* Add parent data to all children */ 250 ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc)); 251 value = 5; 252 uclass_foreach_dev(dev, uc) { 253 /* Ignore these if they are not on this bus */ 254 if (dev->parent != bus) { 255 ut_asserteq_ptr(NULL, dev_get_parent_priv(dev)); 256 continue; 257 } 258 ut_assertok(device_probe(dev)); 259 parent_data = dev_get_parent_priv(dev); 260 261 parent_data->sum = value; 262 value += 5; 263 } 264 265 /* Check it is still there */ 266 value = 5; 267 uclass_foreach_dev(dev, uc) { 268 /* Ignore these if they are not on this bus */ 269 if (dev->parent != bus) 270 continue; 271 parent_data = dev_get_parent_priv(dev); 272 273 ut_asserteq(value, parent_data->sum); 274 value += 5; 275 } 276 277 return 0; 278 } 279 /* Test that the bus can store data about each child */ 280 static int dm_test_bus_parent_data(struct unit_test_state *uts) 281 { 282 return test_bus_parent_data(uts); 283 } 284 DM_TEST(dm_test_bus_parent_data, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); 285 286 /* As above but the size is controlled by the uclass */ 287 static int dm_test_bus_parent_data_uclass(struct unit_test_state *uts) 288 { 289 struct driver *drv; 290 struct udevice *bus; 291 int size; 292 int ret; 293 294 /* Set the driver size to 0 so that the uclass size is used */ 295 ut_assertok(uclass_find_device(UCLASS_TEST_BUS, 0, &bus)); 296 drv = (struct driver *)bus->driver; 297 size = drv->per_child_auto_alloc_size; 298 bus->uclass->uc_drv->per_child_auto_alloc_size = size; 299 drv->per_child_auto_alloc_size = 0; 300 ret = test_bus_parent_data(uts); 301 if (ret) 302 return ret; 303 bus->uclass->uc_drv->per_child_auto_alloc_size = 0; 304 drv->per_child_auto_alloc_size = size; 305 306 return 0; 307 } 308 DM_TEST(dm_test_bus_parent_data_uclass, 309 DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); 310 311 /* Test that the bus ops are called when a child is probed/removed */ 312 static int dm_test_bus_parent_ops(struct unit_test_state *uts) 313 { 314 struct dm_test_parent_data *parent_data; 315 struct dm_test_state *dms = uts->priv; 316 struct udevice *bus, *dev; 317 struct uclass *uc; 318 319 test_state = dms; 320 ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); 321 ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc)); 322 323 uclass_foreach_dev(dev, uc) { 324 /* Ignore these if they are not on this bus */ 325 if (dev->parent != bus) 326 continue; 327 ut_asserteq_ptr(NULL, dev_get_parent_priv(dev)); 328 329 ut_assertok(device_probe(dev)); 330 parent_data = dev_get_parent_priv(dev); 331 ut_asserteq(FLAG_CHILD_PROBED, parent_data->flag); 332 } 333 334 uclass_foreach_dev(dev, uc) { 335 /* Ignore these if they are not on this bus */ 336 if (dev->parent != bus) 337 continue; 338 parent_data = dev_get_parent_priv(dev); 339 ut_asserteq(FLAG_CHILD_PROBED, parent_data->flag); 340 ut_assertok(device_remove(dev, DM_REMOVE_NORMAL)); 341 ut_asserteq_ptr(NULL, dev_get_parent_priv(dev)); 342 ut_asserteq_ptr(dms->removed, dev); 343 } 344 test_state = NULL; 345 346 return 0; 347 } 348 DM_TEST(dm_test_bus_parent_ops, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); 349 350 static int test_bus_parent_platdata(struct unit_test_state *uts) 351 { 352 struct dm_test_parent_platdata *plat; 353 struct udevice *bus, *dev; 354 int child_count; 355 356 /* Check that the bus has no children */ 357 ut_assertok(uclass_find_device(UCLASS_TEST_BUS, 0, &bus)); 358 device_find_first_child(bus, &dev); 359 ut_asserteq_ptr(NULL, dev); 360 361 ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); 362 363 for (device_find_first_child(bus, &dev), child_count = 0; 364 dev; 365 device_find_next_child(&dev)) { 366 /* Check that platform data is allocated */ 367 plat = dev_get_parent_platdata(dev); 368 ut_assert(plat != NULL); 369 370 /* 371 * Check that it is not affected by the device being 372 * probed/removed 373 */ 374 plat->count++; 375 ut_asserteq(1, plat->count); 376 device_probe(dev); 377 device_remove(dev, DM_REMOVE_NORMAL); 378 379 ut_asserteq_ptr(plat, dev_get_parent_platdata(dev)); 380 ut_asserteq(1, plat->count); 381 ut_assertok(device_probe(dev)); 382 child_count++; 383 } 384 ut_asserteq(3, child_count); 385 386 /* Removing the bus should also have no effect (it is still bound) */ 387 device_remove(bus, DM_REMOVE_NORMAL); 388 for (device_find_first_child(bus, &dev), child_count = 0; 389 dev; 390 device_find_next_child(&dev)) { 391 /* Check that platform data is allocated */ 392 plat = dev_get_parent_platdata(dev); 393 ut_assert(plat != NULL); 394 ut_asserteq(1, plat->count); 395 child_count++; 396 } 397 ut_asserteq(3, child_count); 398 399 /* Unbind all the children */ 400 do { 401 device_find_first_child(bus, &dev); 402 if (dev) 403 device_unbind(dev); 404 } while (dev); 405 406 /* Now the child platdata should be removed and re-added */ 407 device_probe(bus); 408 for (device_find_first_child(bus, &dev), child_count = 0; 409 dev; 410 device_find_next_child(&dev)) { 411 /* Check that platform data is allocated */ 412 plat = dev_get_parent_platdata(dev); 413 ut_assert(plat != NULL); 414 ut_asserteq(0, plat->count); 415 child_count++; 416 } 417 ut_asserteq(3, child_count); 418 419 return 0; 420 } 421 422 /* Test that the bus can store platform data about each child */ 423 static int dm_test_bus_parent_platdata(struct unit_test_state *uts) 424 { 425 return test_bus_parent_platdata(uts); 426 } 427 DM_TEST(dm_test_bus_parent_platdata, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); 428 429 /* As above but the size is controlled by the uclass */ 430 static int dm_test_bus_parent_platdata_uclass(struct unit_test_state *uts) 431 { 432 struct udevice *bus; 433 struct driver *drv; 434 int size; 435 int ret; 436 437 /* Set the driver size to 0 so that the uclass size is used */ 438 ut_assertok(uclass_find_device(UCLASS_TEST_BUS, 0, &bus)); 439 drv = (struct driver *)bus->driver; 440 size = drv->per_child_platdata_auto_alloc_size; 441 bus->uclass->uc_drv->per_child_platdata_auto_alloc_size = size; 442 drv->per_child_platdata_auto_alloc_size = 0; 443 ret = test_bus_parent_platdata(uts); 444 if (ret) 445 return ret; 446 bus->uclass->uc_drv->per_child_platdata_auto_alloc_size = 0; 447 drv->per_child_platdata_auto_alloc_size = size; 448 449 return 0; 450 } 451 DM_TEST(dm_test_bus_parent_platdata_uclass, 452 DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); 453 454 /* Test that the child post_bind method is called */ 455 static int dm_test_bus_child_post_bind(struct unit_test_state *uts) 456 { 457 struct dm_test_parent_platdata *plat; 458 struct udevice *bus, *dev; 459 int child_count; 460 461 ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); 462 for (device_find_first_child(bus, &dev), child_count = 0; 463 dev; 464 device_find_next_child(&dev)) { 465 /* Check that platform data is allocated */ 466 plat = dev_get_parent_platdata(dev); 467 ut_assert(plat != NULL); 468 ut_asserteq(1, plat->bind_flag); 469 child_count++; 470 } 471 ut_asserteq(3, child_count); 472 473 return 0; 474 } 475 DM_TEST(dm_test_bus_child_post_bind, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); 476 477 /* Test that the child post_bind method is called */ 478 static int dm_test_bus_child_post_bind_uclass(struct unit_test_state *uts) 479 { 480 struct dm_test_parent_platdata *plat; 481 struct udevice *bus, *dev; 482 int child_count; 483 484 ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); 485 for (device_find_first_child(bus, &dev), child_count = 0; 486 dev; 487 device_find_next_child(&dev)) { 488 /* Check that platform data is allocated */ 489 plat = dev_get_parent_platdata(dev); 490 ut_assert(plat != NULL); 491 ut_asserteq(2, plat->uclass_bind_flag); 492 child_count++; 493 } 494 ut_asserteq(3, child_count); 495 496 return 0; 497 } 498 DM_TEST(dm_test_bus_child_post_bind_uclass, 499 DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); 500 501 /* 502 * Test that the bus' uclass' child_pre_probe() is called before the 503 * device's probe() method 504 */ 505 static int dm_test_bus_child_pre_probe_uclass(struct unit_test_state *uts) 506 { 507 struct udevice *bus, *dev; 508 int child_count; 509 510 /* 511 * See testfdt_drv_probe() which effectively checks that the uclass 512 * flag is set before that method is called 513 */ 514 ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); 515 for (device_find_first_child(bus, &dev), child_count = 0; 516 dev; 517 device_find_next_child(&dev)) { 518 struct dm_test_priv *priv = dev_get_priv(dev); 519 520 /* Check that things happened in the right order */ 521 ut_asserteq_ptr(NULL, priv); 522 ut_assertok(device_probe(dev)); 523 524 priv = dev_get_priv(dev); 525 ut_assert(priv != NULL); 526 ut_asserteq(1, priv->uclass_flag); 527 ut_asserteq(1, priv->uclass_total); 528 child_count++; 529 } 530 ut_asserteq(3, child_count); 531 532 return 0; 533 } 534 DM_TEST(dm_test_bus_child_pre_probe_uclass, 535 DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); 536