From: Simon Glass Date: Tue, 14 Oct 2014 05:41:49 +0000 (-0600) Subject: dm: core: Add functions for iterating through device children X-Git-Tag: KARO-TXA5-2015-06-26~525^2~41 X-Git-Url: https://git.kernelconcepts.de/?p=karo-tx-uboot.git;a=commitdiff_plain;h=a8981d4f80b010666ad754d20a4f389f94d6726d 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 Acked-by: Jagannadha Sutradharudu Teki --- diff --git a/doc/driver-model/README.txt b/doc/driver-model/README.txt index f9b68beb6f..c435cdc6db 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 32e80e82b5..9538874017 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 e08d496e6a..160cd5883a 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 873d64e42a..abbaccff50 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) {