drivers/devicetree/fdt: add additional fdt parsing utilities.

These utilities remove some of the boilerplate needed for FDT parsing and device initialization.
This commit is contained in:
Stuart Ianna 2024-05-15 15:38:41 +10:00 committed by Xiang Xiao
parent d6445484fe
commit 39e6e25565
2 changed files with 152 additions and 0 deletions

View File

@ -26,6 +26,7 @@
#include <endian.h>
#include <errno.h>
#include <assert.h>
#include <ctype.h>
#include <nuttx/compiler.h>
#include <nuttx/fdt.h>
#include <libfdt.h>
@ -290,3 +291,95 @@ uintptr_t fdt_get_clock_frequency_from_clocks(FAR const void *fdt,
return fdt_get_clock_frequency(fdt, pv_offset);
}
int fdt_node_index_from_label(FAR const char *node_label, int count)
{
int dev_number = 0;
size_t label_length;
if (!node_label)
{
return -ENOENT;
}
label_length = strnlen(node_label, CONFIG_PATH_MAX);
if (count > label_length || count <= 0)
{
return -EINVAL;
}
for (int i = 0; i < count; i++)
{
int number = atoi(&node_label[label_length - i]);
if (number)
{
dev_number = number;
}
}
/* atoi returns 0 on failure, so check that the number isn't actually 0 */
if (!dev_number && !isdigit(node_label[label_length - 1]))
{
return -ENOENT;
}
return dev_number;
}
void fdt_node_from_compat(FAR const void *fdt,
FAR const char **compatible_ids,
FAR void (*driver_callback)(FAR const void *fdt,
int offset))
{
int offset = 0;
DEBUGASSERT(compatible_ids);
DEBUGASSERT(driver_callback);
while (*compatible_ids)
{
while (true)
{
offset
= fdt_node_offset_by_compatible(fdt, offset, *compatible_ids);
if (offset == -FDT_ERR_NOTFOUND)
{
break;
}
if (!fdt_device_is_available(fdt, offset))
{
continue;
}
driver_callback(fdt, offset);
}
compatible_ids++;
}
}
int fdt_load_prop_u32(FAR const void *fdt, int offset,
FAR const char *property, int index,
FAR uint32_t *value)
{
DEBUGASSERT(property);
DEBUGASSERT(value);
int length;
const fdt32_t *pv = fdt_getprop(fdt, offset, property, &length);
if (!pv)
{
return -ENOENT;
}
if (index >= length)
{
return -EINVAL;
}
*value = fdt32_ld(pv + index);
return OK;
}

View File

@ -350,4 +350,63 @@ uintptr_t fdt_get_clock_frequency_from_clocks(FAR const void *fdt,
int offset,
int index);
/****************************************************************************
* Name: fdt_node_index_from_label
*
* Description:
* Get the node index from a device tree label.
*
* Input Parameters:
* label - The device tree node_label
* count - The number of characters from the end of the label to search
*
* Returns
* The integer number found at the end of the label. e.g returns 4 for a
* label called (i2c_4). Returns -ENOENT if an integer cannot be found.
*
****************************************************************************/
int fdt_node_index_from_label(FAR const char *node_label, int count);
/****************************************************************************
* Name: fdt_node_from_compat
*
* Description:
* Find all devices with a matching compatibility string and call a device
* specific callback.
*
* Input Parameters:
* fdt - The pointer to the raw FDT.
* compatible_ids - NULL terminated list of compatible ids.
* driver_callback - Function called on every found instance of the ID.
*
****************************************************************************/
void fdt_node_from_compat(FAR const void *fdt,
FAR const char **compatible_ids,
FAR void (*driver_callback)(FAR const void *fdt,
int offset));
/****************************************************************************
* Name: fdt_load_prop_u32
*
* Description:
* Load an uint32_t type from a property at a given index
*
* Input Parameters:
* fdt - The pointer to the raw FDT.
* offset - The node offset
* property - The property to load from.
* index - The value index inside the property
* value - Output parameter for found value.
*
* Returns:
* OK on success, errno of failure.
*
****************************************************************************/
int fdt_load_prop_u32(FAR const void *fdt, int offset,
FAR const char *property, int index,
FAR uint32_t *value);
#endif /* __INCLUDE_NUTTX_FDT_H */