From 903e83ee84649c1a70bfd8b9ec84dacb8c24e7cb Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 27 Jan 2020 08:49:48 -0700 Subject: dm: core: Add a way to iterate through children, probing each It is sometimes useful to process all children, making sure they are probed first. Add functions to help with this and a macro to make it more convenient. Signed-off-by: Simon Glass --- drivers/core/device.c | 22 ++++++++++++++++++++++ include/dm/device.h | 39 +++++++++++++++++++++++++++++++++++++++ test/dm/test-fdt.c | 19 +++++++++++++++++++ 3 files changed, 80 insertions(+) diff --git a/drivers/core/device.c b/drivers/core/device.c index c948d8d..89ea820 100644 --- a/drivers/core/device.c +++ b/drivers/core/device.c @@ -792,6 +792,28 @@ int device_find_child_by_name(const struct udevice *parent, const char *name, return -ENODEV; } +int device_first_child_err(struct udevice *parent, struct udevice **devp) +{ + struct udevice *dev; + + device_find_first_child(parent, &dev); + if (!dev) + return -ENODEV; + + return device_get_device_tail(dev, 0, devp); +} + +int device_next_child_err(struct udevice **devp) +{ + struct udevice *dev = *devp; + + device_find_next_child(&dev); + if (!dev) + return -ENODEV; + + return device_get_device_tail(dev, 0, devp); +} + int device_first_child_ofdata_err(struct udevice *parent, struct udevice **devp) { struct udevice *dev; diff --git a/include/dm/device.h b/include/dm/device.h index 2618952..517ae7f 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -603,6 +603,28 @@ int device_first_child_ofdata_err(struct udevice *parent, int device_next_child_ofdata_err(struct udevice **devp); /** + * device_first_child_err() - Get the first child of a device + * + * The device returned is probed if necessary, and ready for use + * + * @parent: Parent device to search + * @devp: Returns device found, if any + * @return 0 if found, -ENODEV if not, -ve error if device failed to probe + */ +int device_first_child_err(struct udevice *parent, struct udevice **devp); + +/** + * device_next_child_err() - Get the next child of a parent device + * + * The device returned is probed if necessary, and ready for use + * + * @devp: On entry, pointer to device to lookup. On exit, returns pointer + * to the next sibling if no error occurred + * @return 0 if found, -ENODEV if not, -ve error if device failed to probe + */ +int device_next_child_err(struct udevice **devp); + +/** * device_has_children() - check if a device has any children * * @dev: Device to check @@ -749,6 +771,23 @@ static inline bool device_is_on_pci_bus(const struct udevice *dev) _ret = device_next_child_ofdata_err(&dev)) /** + * device_foreach_child_probe() - iterate through children, probing them + * + * This creates a for() loop which works through the available children of + * a device in order from start to end. Devices are probed if necessary, + * and ready for use. + * + * This stops when it gets an error, with @pos set to the device that failed to + * probe + * + * @pos: struct udevice * for the current device + * @parent: parent device to scan + */ +#define device_foreach_child_probe(pos, parent) \ + for (int _ret = device_first_child_err(parent, &dev); !_ret; \ + _ret = device_next_child_err(&dev)) + +/** * dm_scan_fdt_dev() - Bind child device in a the device tree * * This handles device which have sub-nodes in the device tree. It scans all diff --git a/test/dm/test-fdt.c b/test/dm/test-fdt.c index 8fe4425..cd65e42 100644 --- a/test/dm/test-fdt.c +++ b/test/dm/test-fdt.c @@ -891,3 +891,22 @@ static int dm_test_child_ofdata(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_child_ofdata, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); + +/* Test device_first_child_err(), etc. */ +static int dm_test_first_child_probe(struct unit_test_state *uts) +{ + struct udevice *bus, *dev; + int count; + + ut_assertok(uclass_first_device_err(UCLASS_TEST_BUS, &bus)); + count = 0; + device_foreach_child_probe(dev, bus) { + ut_assert(dev->flags & DM_FLAG_PLATDATA_VALID); + ut_assert(dev->flags & DM_FLAG_ACTIVATED); + count++; + } + ut_asserteq(3, count); + + return 0; +} +DM_TEST(dm_test_first_child_probe, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); -- cgit v1.1