1
0
Fork 0
forked from nuttx/nuttx-update

drivers/devicetree: Add a set of commonly used FDT utilities.

This commit is contained in:
Stuart Ianna 2024-05-08 12:17:33 +10:00 committed by Xiang Xiao
parent 297b3b0209
commit c4dbabb1bb
4 changed files with 254 additions and 7 deletions

View file

@ -70,7 +70,7 @@ static void register_virtio_devices_from_fdt(const void *fdt)
break;
}
addr = fdt_get_reg_base(fdt, offset);
addr = fdt_get_reg_base(fdt, offset, 0);
irqnum = fdt_get_irq(fdt, offset, 1, QEMU_SPI_IRQ_BASE);
if (addr > 0 && irqnum >= 0)
{

View file

@ -70,7 +70,7 @@ static void register_virtio_devices_from_fdt(const void *fdt)
break;
}
addr = fdt_get_reg_base(fdt, offset);
addr = fdt_get_reg_base(fdt, offset, 0);
irqnum = fdt_get_irq(fdt, offset, 1, QEMU_SPI_IRQ_BASE);
if (addr > 0 && irqnum >= 0)
{

View file

@ -122,15 +122,41 @@ uintptr_t fdt_ld_by_cells(FAR const void *value, int cells)
}
}
uintptr_t fdt_get_reg_base(FAR const void *fdt, int offset)
uintptr_t fdt_get_reg_base_by_name(FAR const void *fdt, int offset,
const char *reg_name)
{
uintptr_t addr = 0;
int reg_index
= fdt_stringlist_search(fdt, offset, "reg-names", reg_name);
if (reg_index < 0)
{
return addr;
}
return fdt_get_reg_base(fdt, offset, reg_index);
}
uintptr_t fdt_get_reg_base(FAR const void *fdt, int offset, int index)
{
FAR const void *reg;
uintptr_t addr = 0;
int reg_length;
reg = fdt_getprop(fdt, offset, "reg", NULL);
/* Register cells contain a tuple of two values */
index *= 2;
reg = fdt_getprop(fdt, offset, "reg", &reg_length);
if (reg != NULL)
{
addr = fdt_ld_by_cells(reg, fdt_get_parent_address_cells(fdt, offset));
if ((index * sizeof(uintptr_t)) > reg_length)
{
return addr;
}
addr = fdt_ld_by_cells(reg + index * sizeof(uintptr_t),
fdt_get_parent_address_cells(fdt, offset));
}
return addr;
@ -152,6 +178,115 @@ uintptr_t fdt_get_reg_size(FAR const void *fdt, int offset)
uintptr_t fdt_get_reg_base_by_path(FAR const void *fdt, FAR const char *path)
{
return fdt_get_reg_base(fdt, fdt_path_offset(fdt, path));
return fdt_get_reg_base(fdt, fdt_path_offset(fdt, path), 0);
}
bool fdt_device_is_available(FAR const void *fdt, int node)
{
const char *status = fdt_getprop(fdt, node, "status", NULL);
if (!status)
{
return true;
}
if (!strcmp(status, "ok") || !strcmp(status, "okay"))
{
return true;
}
return false;
}
const char *fdt_get_node_label(FAR const void *fdt, int node)
{
int symbols_offset;
int property_offset;
int ret;
const char *property_name;
const char *label_name;
char path_buffer[CONFIG_PATH_MAX] =
{
0
};
symbols_offset = fdt_path_offset(fdt, "/__symbols__");
if (symbols_offset < 0)
{
return NULL;
}
ret = fdt_get_path(fdt, node, path_buffer, sizeof(path_buffer));
if (ret < 0)
{
return NULL;
}
fdt_for_each_property_offset(property_offset, fdt, symbols_offset)
{
property_name = fdt_getprop_by_offset(
fdt, property_offset, &label_name, NULL);
/* The symbols section is a list of parameters in the format
* label_name = node_path. So the value of each property needs to be
* checked with the full path found earlier.
*
*/
if (!strncmp(property_name, path_buffer, sizeof(path_buffer)))
{
return label_name;
}
}
return NULL;
}
uintptr_t fdt_get_clock_frequency(FAR const void *fdt, int offset)
{
const void *pv;
uintptr_t clock_frequency = 0;
pv = fdt_getprop(fdt, offset, "clock-frequency", NULL);
if (!pv)
{
return clock_frequency;
}
clock_frequency = fdt_ld_by_cells(pv,
fdt_get_parent_address_cells(fdt,
offset));
return clock_frequency;
}
uintptr_t fdt_get_clock_frequency_from_clocks(FAR const void *fdt,
int offset,
int index)
{
const fdt32_t *pv;
fdt32_t clk_phandle;
int pv_offset;
uintptr_t clock_frequency = 0;
int clk_length;
pv = fdt_getprop(fdt, offset, "clocks", &clk_length);
if (!pv)
{
return clock_frequency;
}
if ((index * sizeof(fdt32_t)) > clk_length)
{
return clock_frequency;
}
clk_phandle = fdt32_ld(pv + index);
pv_offset = fdt_node_offset_by_phandle(fdt, clk_phandle);
if (pv_offset < 0)
{
return clock_frequency;
}
return fdt_get_clock_frequency(fdt, pv_offset);
}

View file

@ -28,6 +28,7 @@
#include <nuttx/config.h>
#include <stdint.h>
#include <stdbool.h>
#include <nuttx/compiler.h>
/****************************************************************************
@ -186,6 +187,31 @@ int fdt_get_parent_size_cells(FAR const void *fdt, int offset);
uintptr_t fdt_ld_by_cells(FAR const void *value, int cells);
/****************************************************************************
* Name: fdt_get_reg_base_by_name
*
* Description:
* Get the value of the "reg" property by its offset in the "reg-names"
* property
*
* Input Parameters:
* fdt - The pointer to the raw FDT.
* offset - The offset to the node.
* reg_name - The name of the register
*
* Returned Value:
* The register address determined by its name. Returns 0 if:
* - The reg-names property doesn't exist.
* - The reg property doesn't exits.
* - The reg-names property doesn't contain the "reg_name".
* - The offset combined with the size is larger than the width of the
* "reg" field
*
****************************************************************************/
uintptr_t fdt_get_reg_base_by_name(FAR const void *fdt, int offset,
const char *reg_name);
/****************************************************************************
* Name: fdt_get_reg_base
*
@ -195,13 +221,14 @@ uintptr_t fdt_ld_by_cells(FAR const void *value, int cells);
* Input Parameters:
* fdt - The pointer to the raw FDT.
* offset - The offset of the node
* index - The index of the register in the reg field.
*
* Return:
* The base address of the register space
*
****************************************************************************/
uintptr_t fdt_get_reg_base(FAR const void *fdt, int offset);
uintptr_t fdt_get_reg_base(FAR const void *fdt, int offset, int index);
/****************************************************************************
* Name: fdt_get_reg_size
@ -238,4 +265,89 @@ uintptr_t fdt_get_reg_size(FAR const void *fdt, int offset);
uintptr_t fdt_get_reg_base_by_path(FAR const void *fdt,
FAR const char *path);
/****************************************************************************
* Name: fdt_device_is_available
*
* Description:
* Test if node contains the "status" property with field set to okay or
* ok.
*
* Input Parameters:
* fdt - The pointer to the raw FDT.
* offset - The offset to the node to query.
*
* Returned Value:
* true: The node contains the status propertry, and is set to okay or
* ok.
* false: The node contains the status propertry, but it is set to
* something other than ok or okay.
* Always returns true if the node doesn't contain a status property.
*
****************************************************************************/
bool fdt_device_is_available(FAR const void * fdt, int offset);
/****************************************************************************
* Name: fdt_get_node_label
*
* Description:
* Get the label for a given node. The device tree must be compiled with
* the -@ option in order for the symbol table to be generated.
*
* Input Parameters:
* fdt - The pointer to the raw FDT.
* offset - The offset to the node to query.
*
* Returned Value:
* Node label if found. NULL is returned if no label if found for the given
* node.
*
****************************************************************************/
const char *fdt_get_node_label(FAR const void *fdt, int offset);
/****************************************************************************
* Name: fdt_get_clock_frequency
*
* Description:
* Get the value of the "clock-frequency" value for the given node.
*
* Input Parameters:
* fdt - The pointer to the raw FDT.
* offset - The offset to the node to query.
*
* Returned Value:
* The value of the clock-frequency property of the node. Zero is
* returned if the node doesn't contain a clock-frequency property.
*
****************************************************************************/
uintptr_t fdt_get_clock_frequency(FAR const void *fdt, int offset);
/****************************************************************************
* Name: fdt_get_clock_frequency_from_clocks
*
* Description:
* Get the "clock-frequency" property for the given node, using the phandle
* specified in the "clocks" property
*
* Input Parameters:
* fdt - The pointer to the raw FDT.
* node - The offset to the node to query.
* offset - The offset of the phandle in the clocks property
*
* Returned Value:
* The value of the clock-frequency property of the node, following the
* specified phandle in the "clocks"' property. Returns 0 if:
* - The node doesn't have a "clocks" property
* - The offset given is larger than the length of the "clocks" property
* - The phandle specified by the "clocks" property doesn't contain a
* "clock-frequency" property.
*
****************************************************************************/
uintptr_t fdt_get_clock_frequency_from_clocks(FAR const void *fdt,
int offset,
int index);
#endif /* __INCLUDE_NUTTX_FDT_H */