X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=test%2Fdm%2Fbus.c;h=abbaccff509ce09374f30e88983252672d3c4e62;hb=0ae0cb7b50ab7836fb2a625a389d7a83698c2150;hp=08a4725648e1da7f3c2bf0d4f690652fb125f622;hpb=997c87bb0b1981fd33e34cefc26d9138f27326ce;p=u-boot diff --git a/test/dm/bus.c b/test/dm/bus.c index 08a4725648..abbaccff50 100644 --- a/test/dm/bus.c +++ b/test/dm/bus.c @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -13,11 +14,39 @@ DECLARE_GLOBAL_DATA_PTR; +enum { + FLAG_CHILD_PROBED = 10, + FLAG_CHILD_REMOVED = -7, +}; + +static struct dm_test_state *test_state; + static int testbus_drv_probe(struct udevice *dev) { return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false); } +static int testbus_child_pre_probe(struct udevice *dev) +{ + struct dm_test_parent_data *parent_data = dev_get_parentdata(dev); + + parent_data->flag += FLAG_CHILD_PROBED; + + return 0; +} + +static int testbus_child_post_remove(struct udevice *dev) +{ + struct dm_test_parent_data *parent_data = dev_get_parentdata(dev); + struct dm_test_state *dms = test_state; + + parent_data->flag += FLAG_CHILD_REMOVED; + if (dms) + dms->removed = dev; + + return 0; +} + static const struct udevice_id testbus_ids[] = { { .compatible = "denx,u-boot-test-bus", @@ -32,6 +61,9 @@ U_BOOT_DRIVER(testbus_drv) = { .probe = testbus_drv_probe, .priv_auto_alloc_size = sizeof(struct dm_test_priv), .platdata_auto_alloc_size = sizeof(struct dm_test_pdata), + .per_child_auto_alloc_size = sizeof(struct dm_test_parent_data), + .child_pre_probe = testbus_child_pre_probe, + .child_post_remove = testbus_child_post_remove, }; UCLASS_DRIVER(testbus) = { @@ -107,3 +139,135 @@ static int dm_test_bus_children_funcs(struct dm_test_state *dms) return 0; } DM_TEST(dm_test_bus_children_funcs, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); + +/* Test that we can iterate through children */ +static int dm_test_bus_children_iterators(struct dm_test_state *dms) +{ + struct udevice *bus, *dev, *child; + + /* Walk through the children one by one */ + ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); + ut_assertok(device_find_first_child(bus, &dev)); + ut_asserteq_str("c-test@5", dev->name); + ut_assertok(device_find_next_child(&dev)); + ut_asserteq_str("c-test@0", dev->name); + ut_assertok(device_find_next_child(&dev)); + ut_asserteq_str("c-test@1", dev->name); + ut_assertok(device_find_next_child(&dev)); + ut_asserteq_ptr(dev, NULL); + + /* Move to the next child without using device_find_first_child() */ + ut_assertok(device_find_child_by_seq(bus, 5, true, &dev)); + ut_asserteq_str("c-test@5", dev->name); + ut_assertok(device_find_next_child(&dev)); + ut_asserteq_str("c-test@0", dev->name); + + /* Try a device with no children */ + ut_assertok(device_find_first_child(dev, &child)); + ut_asserteq_ptr(child, NULL); + + return 0; +} +DM_TEST(dm_test_bus_children_iterators, + DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); + +/* Test that the bus can store data about each child */ +static int dm_test_bus_parent_data(struct dm_test_state *dms) +{ + struct dm_test_parent_data *parent_data; + struct udevice *bus, *dev; + struct uclass *uc; + int value; + + ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); + + /* Check that parent data is allocated */ + ut_assertok(device_find_child_by_seq(bus, 0, true, &dev)); + ut_asserteq_ptr(NULL, dev_get_parentdata(dev)); + ut_assertok(device_get_child_by_seq(bus, 0, &dev)); + parent_data = dev_get_parentdata(dev); + ut_assert(NULL != parent_data); + + /* Check that it starts at 0 and goes away when device is removed */ + parent_data->sum += 5; + ut_asserteq(5, parent_data->sum); + device_remove(dev); + ut_asserteq_ptr(NULL, dev_get_parentdata(dev)); + + /* Check that we can do this twice */ + ut_assertok(device_get_child_by_seq(bus, 0, &dev)); + parent_data = dev_get_parentdata(dev); + ut_assert(NULL != parent_data); + parent_data->sum += 5; + ut_asserteq(5, parent_data->sum); + + /* Add parent data to all children */ + ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc)); + value = 5; + uclass_foreach_dev(dev, uc) { + /* Ignore these if they are not on this bus */ + if (dev->parent != bus) { + ut_asserteq_ptr(NULL, dev_get_parentdata(dev)); + continue; + } + ut_assertok(device_probe(dev)); + parent_data = dev_get_parentdata(dev); + + parent_data->sum = value; + value += 5; + } + + /* Check it is still there */ + value = 5; + uclass_foreach_dev(dev, uc) { + /* Ignore these if they are not on this bus */ + if (dev->parent != bus) + continue; + parent_data = dev_get_parentdata(dev); + + ut_asserteq(value, parent_data->sum); + value += 5; + } + + return 0; +} + +DM_TEST(dm_test_bus_parent_data, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); + +/* Test that the bus ops are called when a child is probed/removed */ +static int dm_test_bus_parent_ops(struct dm_test_state *dms) +{ + struct dm_test_parent_data *parent_data; + struct udevice *bus, *dev; + struct uclass *uc; + + test_state = dms; + ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); + ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc)); + + uclass_foreach_dev(dev, uc) { + /* Ignore these if they are not on this bus */ + if (dev->parent != bus) + continue; + ut_asserteq_ptr(NULL, dev_get_parentdata(dev)); + + ut_assertok(device_probe(dev)); + parent_data = dev_get_parentdata(dev); + ut_asserteq(FLAG_CHILD_PROBED, parent_data->flag); + } + + uclass_foreach_dev(dev, uc) { + /* Ignore these if they are not on this bus */ + if (dev->parent != bus) + continue; + parent_data = dev_get_parentdata(dev); + ut_asserteq(FLAG_CHILD_PROBED, parent_data->flag); + ut_assertok(device_remove(dev)); + ut_asserteq_ptr(NULL, dev_get_parentdata(dev)); + ut_asserteq_ptr(dms->removed, dev); + } + test_state = NULL; + + return 0; +} +DM_TEST(dm_test_bus_parent_ops, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);