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 <casey.connolly@linaro.org>
This commit is contained in:
Casey Connolly
2026-04-01 16:15:20 +02:00
committed by Tom Rini
parent 139f5292e7
commit 45c610d718
6 changed files with 204 additions and 0 deletions

View File

@@ -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)
{

View File

@@ -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)
{

View File

@@ -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
*

View File

@@ -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

View File

@@ -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

View File

@@ -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)
{