summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2014-07-23 12:55:21 (GMT)
committerSimon Glass <sjg@chromium.org>2014-07-23 13:08:37 (GMT)
commita327dee0f40bcdebaba1a3e47f2b9f1ceb970d2a (patch)
tree20ba09ee61b51416bc86808abf7315fe6266e1ed /test
parente59f458de6999b8a786da857e653db6777f675ca (diff)
downloadu-boot-a327dee0f40bcdebaba1a3e47f2b9f1ceb970d2a.tar.xz
dm: Add child_pre_probe() and child_post_remove() methods
Some devices (particularly bus devices) must track their children, knowing when a new child is added so that it can be set up for communication on the bus. Add a child_pre_probe() method to provide this feature, and a corresponding child_post_remove() method. Signed-off-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'test')
-rw-r--r--test/dm/bus.c68
1 files changed, 68 insertions, 0 deletions
diff --git a/test/dm/bus.c b/test/dm/bus.c
index df8edcb..873d64e 100644
--- a/test/dm/bus.c
+++ b/test/dm/bus.c
@@ -14,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",
@@ -34,6 +62,8 @@ U_BOOT_DRIVER(testbus_drv) = {
.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) = {
@@ -172,3 +202,41 @@ static int dm_test_bus_parent_data(struct dm_test_state *dms)
}
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);