+
+/* 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);