diff options
author | Simon Glass <sjg@chromium.org> | 2014-10-13 23:41:49 -0600 |
---|---|---|
committer | Simon Glass <sjg@chromium.org> | 2014-10-22 10:36:45 -0600 |
commit | a8981d4f80b010666ad754d20a4f389f94d6726d (patch) | |
tree | 48bf392bb2e0f00248ac4949fdceefa4b7509cb6 | |
parent | 0b304a2494eed170562a9fdd64e31332ad5ae73a (diff) | |
download | u-boot-imx-a8981d4f80b010666ad754d20a4f389f94d6726d.zip u-boot-imx-a8981d4f80b010666ad754d20a4f389f94d6726d.tar.gz u-boot-imx-a8981d4f80b010666ad754d20a4f389f94d6726d.tar.bz2 |
dm: core: Add functions for iterating through device children
Buses need to iterate through their children in some situations. Add a few
functions to make this easy.
Signed-off-by: Simon Glass <sjg@chromium.org>
Acked-by: Jagannadha Sutradharudu Teki <jagannadh.teki@gmail.com>
-rw-r--r-- | doc/driver-model/README.txt | 3 | ||||
-rw-r--r-- | drivers/core/device.c | 27 | ||||
-rw-r--r-- | include/dm/device.h | 18 | ||||
-rw-r--r-- | test/dm/bus.c | 31 |
4 files changed, 78 insertions, 1 deletions
diff --git a/doc/driver-model/README.txt b/doc/driver-model/README.txt index f9b68be..c435cdc 100644 --- a/doc/driver-model/README.txt +++ b/doc/driver-model/README.txt @@ -95,7 +95,7 @@ are provided in test/dm. To run them, try: You should see something like this: <...U-Boot banner...> - Running 21 driver model tests + Running 22 driver model tests Test: dm_test_autobind Test: dm_test_autoprobe Test: dm_test_bus_children @@ -103,6 +103,7 @@ You should see something like this: Device 'c-test@0': seq 0 is in use by 'a-test' Device 'c-test@1': seq 1 is in use by 'd-test' Test: dm_test_bus_children_funcs + Test: dm_test_bus_children_iterators Test: dm_test_bus_parent_data Test: dm_test_bus_parent_ops Test: dm_test_children diff --git a/drivers/core/device.c b/drivers/core/device.c index 32e80e8..9538874 100644 --- a/drivers/core/device.c +++ b/drivers/core/device.c @@ -514,3 +514,30 @@ int device_get_child_by_of_offset(struct udevice *parent, int seq, ret = device_find_child_by_of_offset(parent, seq, &dev); return device_get_device_tail(dev, ret, devp); } + +int device_find_first_child(struct udevice *parent, struct udevice **devp) +{ + if (list_empty(&parent->child_head)) { + *devp = NULL; + } else { + *devp = list_first_entry(&parent->child_head, struct udevice, + sibling_node); + } + + return 0; +} + +int device_find_next_child(struct udevice **devp) +{ + struct udevice *dev = *devp; + struct udevice *parent = dev->parent; + + if (list_is_last(&dev->sibling_node, &parent->child_head)) { + *devp = NULL; + } else { + *devp = list_entry(dev->sibling_node.next, struct udevice, + sibling_node); + } + + return 0; +} diff --git a/include/dm/device.h b/include/dm/device.h index e08d496..160cd58 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -280,4 +280,22 @@ int device_find_child_by_of_offset(struct udevice *parent, int of_offset, int device_get_child_by_of_offset(struct udevice *parent, int seq, struct udevice **devp); +/** + * device_find_first_child() - Find the first child of a device + * + * @parent: Parent device to search + * @devp: Returns first child device, or NULL if none + * @return 0 + */ +int device_find_first_child(struct udevice *parent, struct udevice **devp); + +/** + * device_find_first_child() - Find the first child of a device + * + * @devp: Pointer to previous child device on entry. Returns pointer to next + * child device, or NULL if none + * @return 0 + */ +int device_find_next_child(struct udevice **devp); + #endif diff --git a/test/dm/bus.c b/test/dm/bus.c index 873d64e..abbaccf 100644 --- a/test/dm/bus.c +++ b/test/dm/bus.c @@ -140,6 +140,37 @@ static int dm_test_bus_children_funcs(struct dm_test_state *dms) } 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) { |