summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/core/device.c36
-rw-r--r--include/dm/device.h42
-rw-r--r--include/dm/read.h3
-rw-r--r--test/dm/test-fdt.c19
4 files changed, 99 insertions, 1 deletions
diff --git a/drivers/core/device.c b/drivers/core/device.c
index b7f59fcde3..c948d8dbbc 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -792,6 +792,42 @@ int device_find_child_by_name(const struct udevice *parent, const char *name,
return -ENODEV;
}
+int device_first_child_ofdata_err(struct udevice *parent, struct udevice **devp)
+{
+ struct udevice *dev;
+ int ret;
+
+ device_find_first_child(parent, &dev);
+ if (!dev)
+ return -ENODEV;
+
+ ret = device_ofdata_to_platdata(dev);
+ if (ret)
+ return ret;
+
+ *devp = dev;
+
+ return 0;
+}
+
+int device_next_child_ofdata_err(struct udevice **devp)
+{
+ struct udevice *dev = *devp;
+ int ret;
+
+ device_find_next_child(&dev);
+ if (!dev)
+ return -ENODEV;
+
+ ret = device_ofdata_to_platdata(dev);
+ if (ret)
+ return ret;
+
+ *devp = dev;
+
+ return 0;
+}
+
struct udevice *dev_get_parent(const struct udevice *child)
{
return child->parent;
diff --git a/include/dm/device.h b/include/dm/device.h
index 611fc2e197..2618952336 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -578,6 +578,31 @@ int device_find_child_by_name(const struct udevice *parent, const char *name,
struct udevice **devp);
/**
+ * device_first_child_ofdata_err() - Find the first child and reads its platdata
+ *
+ * The ofdata_to_platdata() method is called on the child before it is returned,
+ * but the child is not probed.
+ *
+ * @parent: Parent to check
+ * @devp: Returns child that was found, if any
+ * @return 0 on success, -ENODEV if no children, other -ve on error
+ */
+int device_first_child_ofdata_err(struct udevice *parent,
+ struct udevice **devp);
+
+/*
+ * device_next_child_ofdata_err() - Find the next child and read its platdata
+ *
+ * The ofdata_to_platdata() method is called on the child before it is returned,
+ * but the child is not probed.
+ *
+ * @devp: On entry, points to the previous child; on exit returns the child that
+ * was found, if any
+ * @return 0 on success, -ENODEV if no children, other -ve on error
+ */
+int device_next_child_ofdata_err(struct udevice **devp);
+
+/**
* device_has_children() - check if a device has any children
*
* @dev: Device to check
@@ -707,6 +732,23 @@ static inline bool device_is_on_pci_bus(const struct udevice *dev)
list_for_each_entry(pos, &parent->child_head, sibling_node)
/**
+ * device_foreach_child_ofdata_to_platdata() - iterate through children
+ *
+ * This stops when it gets an error, with @pos set to the device that failed to
+ * read ofdata.
+
+ * This creates a for() loop which works through the available children of
+ * a device in order from start to end. Device ofdata is read by calling
+ * device_ofdata_to_platdata() on each one. The devices are not probed.
+ *
+ * @pos: struct udevice * for the current device
+ * @parent: parent device to scan
+ */
+#define device_foreach_child_ofdata_to_platdata(pos, parent) \
+ for (int _ret = device_first_child_ofdata_err(parent, &dev); !_ret; \
+ _ret = device_next_child_ofdata_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/include/dm/read.h b/include/dm/read.h
index 92a7328fc8..da8c7f25e7 100644
--- a/include/dm/read.h
+++ b/include/dm/read.h
@@ -844,7 +844,8 @@ static inline ofnode dev_read_next_subnode(ofnode node)
}
static inline const uint8_t *dev_read_u8_array_ptr(const struct udevice *dev,
- const char *propname, size_t sz)
+ const char *propname,
+ size_t sz)
{
return ofnode_read_u8_array_ptr(dev_ofnode(dev), propname, sz);
}
diff --git a/test/dm/test-fdt.c b/test/dm/test-fdt.c
index d59c449ce0..8fe4425b21 100644
--- a/test/dm/test-fdt.c
+++ b/test/dm/test-fdt.c
@@ -872,3 +872,22 @@ static int dm_test_read_int(struct unit_test_state *uts)
return 0;
}
DM_TEST(dm_test_read_int, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Test device_first_child_ofdata_err(), etc. */
+static int dm_test_child_ofdata(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_ofdata_to_platdata(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_child_ofdata, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);