From: Casey Connolly Date: Wed, 1 Apr 2026 14:15:20 +0000 (+0200) Subject: ofnode: add read_u64_array and count_elems_of_size X-Git-Tag: v2026.07-rc1~34^2~7 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=45c610d718bd605a1b3bdf99ec0386620b54b559;p=thirdparty%2Fu-boot.git ofnode: add read_u64_array and count_elems_of_size These are similar to their Linux counterparts, adding helpers for reading arrays of 64-bit values with of_access and fdtdec implementations. Signed-off-by: Casey Connolly --- diff --git a/drivers/core/of_access.c b/drivers/core/of_access.c index b11e36202c1..969492aae37 100644 --- a/drivers/core/of_access.c +++ b/drivers/core/of_access.c @@ -598,6 +598,25 @@ int of_read_u64(const struct device_node *np, const char *propname, u64 *outp) return of_read_u64_index(np, propname, 0, outp); } +int of_read_u64_array(const struct device_node *np, const char *propname, + u64 *out_values, size_t sz) +{ + const __be64 *val; + + log_debug("%s: %s: ", __func__, propname); + val = of_find_property_value_of_size(np, propname, + sz * sizeof(*out_values)); + + if (IS_ERR(val)) + return PTR_ERR(val); + + log_debug("size %zd\n", sz); + while (sz--) + *out_values++ = be64_to_cpup(val++); + + return 0; +} + int of_property_match_string(const struct device_node *np, const char *propname, const char *string) { @@ -845,6 +864,39 @@ int of_count_phandle_with_args(const struct device_node *np, cell_count); } +/** + * of_property_count_elems_of_size - Count the number of elements in a property + * + * @np: device node from which the property value is to be read. + * @propname: name of the property to be searched. + * @elem_size: size of the individual element + * + * Search for a property in a device node and count the number of elements of + * size elem_size in it. + * + * Return: The number of elements on sucess, -EINVAL if the property does not + * exist or its length does not match a multiple of elem_size and -ENODATA if + * the property does not have a value. + */ +int of_property_count_elems_of_size(const struct device_node *np, + const char *propname, int elem_size) +{ + const struct property *prop = of_find_property(np, propname, NULL); + + if (!prop) + return -EINVAL; + if (!prop->value) + return -ENODATA; + + if (prop->length % elem_size != 0) { + pr_err("size of %s in node %pOF is not a multiple of %d\n", + propname, np, elem_size); + return -EINVAL; + } + + return prop->length / elem_size; +} + static void of_alias_add(struct alias_prop *ap, struct device_node *np, int id, const char *stem, int stem_len) { diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index 3a36b6fdd03..d605c0f7b7c 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -664,6 +664,54 @@ int ofnode_read_u32_array(ofnode node, const char *propname, } } +int ofnode_read_u64_array(ofnode node, const char *propname, + u64 *out_values, size_t sz) +{ + assert(ofnode_valid(node)); + log_debug("%s: %s: ", __func__, propname); + + if (ofnode_is_np(node)) { + return of_read_u64_array(ofnode_to_np(node), propname, + out_values, sz); + } else { + int ret; + + ret = fdtdec_get_long_array(ofnode_to_fdt(node), + ofnode_to_offset(node), propname, + out_values, sz); + + /* get the error right, but space is more important in SPL */ + if (!IS_ENABLED(CONFIG_XPL_BUILD)) { + if (ret == -FDT_ERR_NOTFOUND) + return -EINVAL; + else if (ret == -FDT_ERR_BADLAYOUT) + return -EOVERFLOW; + } + return ret; + } +} + +int ofnode_count_elems_of_size(ofnode node, const char *propname, int elem_size) +{ + const char *prop; + int len; + assert(ofnode_valid(node)); + + if (ofnode_is_np(node)) { + return of_property_count_elems_of_size(node.np, propname, elem_size); + } else { + prop = fdt_getprop(ofnode_to_fdt(node), ofnode_to_offset(node), propname, &len); + if (!prop) + return -ENOENT; + if (len % elem_size != 0) { + log_debug("size of %s in node %pOF is not a multiple of %d\n", + propname, &node, elem_size); + return -EINVAL; + } + return len / elem_size; + } +} + #if !CONFIG_IS_ENABLED(DM_INLINE_OFNODE) bool ofnode_is_enabled(ofnode node) { diff --git a/include/dm/of_access.h b/include/dm/of_access.h index 44143a5a391..fe0de73d7e2 100644 --- a/include/dm/of_access.h +++ b/include/dm/of_access.h @@ -385,6 +385,23 @@ int of_read_u64(const struct device_node *np, const char *propname, u64 *outp); int of_read_u32_array(const struct device_node *np, const char *propname, u32 *out_values, size_t sz); +/** + * of_read_u64_array() - Find and read an array of 64 bit integers + * + * Search for a property in a device node and read 64-bit value(s) from + * it. + * + * @np: device node from which the property value is to be read. + * @propname: name of the property to be searched. + * @out_values: pointer to return value, modified only if return value is 0. + * @sz: number of array elements to read + * Return: + * 0 on success, -EINVAL if the property does not exist, or -EOVERFLOW if + * longer than sz. + */ +int of_read_u64_array(const struct device_node *np, const char *propname, + u64 *out_values, size_t sz); + /** * of_property_match_string() - Find string in a list and return index * @@ -616,6 +633,9 @@ int of_count_phandle_with_args(const struct device_node *np, const char *list_name, const char *cells_name, int cells_count); +int of_property_count_elems_of_size(const struct device_node *np, + const char *propname, int elem_size); + /** * of_alias_scan() - Scan all properties of the 'aliases' node * diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h index 120393426db..c905e86b283 100644 --- a/include/dm/ofnode.h +++ b/include/dm/ofnode.h @@ -375,6 +375,13 @@ static inline oftree oftree_from_np(struct device_node *root) return tree; } +/* Dummy put for Linux compat */ +static inline void ofnode_put(ofnode node) +{ + if (ofnode_is_np(node)) + of_node_put(node.np); +} + /** * oftree_dispose() - Dispose of an oftree * @@ -588,6 +595,25 @@ const char *ofnode_read_string(ofnode node, const char *propname); int ofnode_read_u32_array(ofnode node, const char *propname, u32 *out_values, size_t sz); +/** + * ofnode_read_u64_array() - Find and read an array of 64 bit integers + * + * @node: valid node reference to read property from + * @propname: name of the property to read + * @out_values: pointer to return value, modified only if return value is 0 + * @sz: number of array elements to read + * Return: 0 on success, -EINVAL if the property does not exist, + * -ENODATA if property does not have a value, and -EOVERFLOW if the + * property data isn't large enough + * + * Search for a property in a device node and read 64-bit value(s) from + * it. + * + * The out_values is modified only if a valid u64 value can be decoded. + */ +int ofnode_read_u64_array(ofnode node, const char *propname, + u64 *out_values, size_t sz); + /** * ofnode_read_bool() - read a boolean value from a property * @@ -652,6 +678,30 @@ static inline ofnode ofnode_next_subnode(ofnode node) fdt_next_subnode(gd->fdt_blob, ofnode_to_offset(node))); } #else + +/** + * ofnode_count_elems_of_size() - count the number of elements of size @elem_size + * in the property @propname. + * + * @node: ofnode to check + * @propname: the name of the property to count + * @elem_size: the size of each element + * + * Returns: the number of elements or -EINVAL if the property size is not a + * multiple of elem_size. + */ +int ofnode_count_elems_of_size(ofnode node, const char *propname, int elem_size); + +static inline int ofnode_count_u32_elems(ofnode node, const char *propname) +{ + return ofnode_count_elems_of_size(node, propname, 4); +} + +static inline int ofnode_count_u64_elems(ofnode node, const char *propname) +{ + return ofnode_count_elems_of_size(node, propname, 8); +} + /** * ofnode_is_enabled() - Checks whether a node is enabled. * This looks for a 'status' property. If this exists, then returns true if diff --git a/include/fdtdec.h b/include/fdtdec.h index d9fcd037ed2..3d199e56b03 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -700,6 +700,22 @@ int fdtdec_lookup_phandle(const void *blob, int node, const char *prop_name); int fdtdec_get_int_array(const void *blob, int node, const char *prop_name, u32 *array, int count); +/** + * Look up a property in a node and return its contents in a u64 + * array of given length. The property must have at least enough data for + * the array (8*count bytes). It may have more, but this will be ignored. + * + * @param blob FDT blob + * @param node node to examine + * @param prop_name name of property to find + * @param array array to fill with data + * @param count number of array elements + * Return: 0 if ok, or -FDT_ERR_NOTFOUND if the property is not found, + * or -FDT_ERR_BADLAYOUT if not enough data + */ +int fdtdec_get_long_array(const void *blob, int node, const char *prop_name, + u64 *array, int count); + /** * Look up a property in a node and return its contents in an integer * array of given length. The property must exist but may have less data that diff --git a/lib/fdtdec.c b/lib/fdtdec.c index c38738b48c7..e23e53f58f2 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -714,6 +714,24 @@ int fdtdec_get_int_array(const void *blob, int node, const char *prop_name, return err; } +int fdtdec_get_long_array(const void *blob, int node, const char *prop_name, + u64 *array, int count) +{ + const u64 *cell; + int err = 0; + + debug("%s: %s\n", __func__, prop_name); + cell = get_prop_check_min_len(blob, node, prop_name, + sizeof(u64) * count, &err); + if (!err) { + int i; + + for (i = 0; i < count; i++) + array[i] = fdt64_to_cpu(cell[i]); + } + return err; +} + int fdtdec_get_int_array_count(const void *blob, int node, const char *prop_name, u32 *array, int count) {