stm32mp: add DT helper for reg by name
Add a new entry to find register properties by name and
include new assert functions to limit address cells to 1
and size cells to 1.
Change-Id: Ide59a795a05fb2af36bd07fec15e5a3adf196226
Signed-off-by: Lionel Debieve <lionel.debieve@st.com>
diff --git a/plat/st/common/include/stm32mp_dt.h b/plat/st/common/include/stm32mp_dt.h
index 74b01b3..a29d914 100644
--- a/plat/st/common/include/stm32mp_dt.h
+++ b/plat/st/common/include/stm32mp_dt.h
@@ -32,6 +32,8 @@
uint32_t dflt_value);
int fdt_read_uint32_array(int node, const char *prop_name,
uint32_t *array, uint32_t count);
+int fdt_get_reg_props_by_name(int node, const char *name, uintptr_t *base,
+ size_t *size);
int dt_set_stdout_pinctrl(void);
void dt_fill_device_info(struct dt_node_info *info, int node);
int dt_get_node(struct dt_node_info *info, int offset, const char *compat);
diff --git a/plat/st/common/stm32mp_dt.c b/plat/st/common/stm32mp_dt.c
index 17da490..4fa796f 100644
--- a/plat/st/common/stm32mp_dt.c
+++ b/plat/st/common/stm32mp_dt.c
@@ -93,6 +93,46 @@
}
/*******************************************************************************
+ * This function returns the address cells from the node parent.
+ * Returns:
+ * - #address-cells value if success.
+ * - invalid value if error.
+ * - a default value if undefined #address-cells property as per libfdt
+ * implementation.
+ ******************************************************************************/
+int fdt_get_node_parent_address_cells(int node)
+{
+ int parent;
+
+ parent = fdt_parent_offset(fdt, node);
+ if (parent < 0) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ return fdt_address_cells(fdt, parent);
+}
+
+/*******************************************************************************
+ * This function returns the size cells from the node parent.
+ * Returns:
+ * - #size-cells value if success.
+ * - invalid value if error.
+ * - a default value if undefined #size-cells property as per libfdt
+ * implementation.
+ ******************************************************************************/
+int fdt_get_node_parent_size_cells(int node)
+{
+ int parent;
+
+ parent = fdt_parent_offset(fdt, node);
+ if (parent < 0) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ return fdt_size_cells(fdt, parent);
+}
+
+/*******************************************************************************
* This function reads a value of a node property (generic use of fdt
* library).
* Returns value if success, and a default value if property not found.
@@ -146,6 +186,46 @@
}
/*******************************************************************************
+ * This function fills reg node info (base & size) with an index found by
+ * checking the reg-names node.
+ * Returns 0 on success and a negative FDT error code on failure.
+ ******************************************************************************/
+int fdt_get_reg_props_by_name(int node, const char *name, uintptr_t *base,
+ size_t *size)
+{
+ const fdt32_t *cuint;
+ int index, len;
+
+ assert((fdt_get_node_parent_address_cells(node) == 1) &&
+ (fdt_get_node_parent_size_cells(node) == 1));
+
+ index = fdt_stringlist_search(fdt, node, "reg-names", name);
+ if (index < 0) {
+ return index;
+ }
+
+ cuint = fdt_getprop(fdt, node, "reg", &len);
+ if (cuint == NULL) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ if ((index * (int)sizeof(uint32_t)) > len) {
+ return -FDT_ERR_BADVALUE;
+ }
+
+ cuint += index << 1;
+ if (base != NULL) {
+ *base = fdt32_to_cpu(*cuint);
+ }
+ cuint++;
+ if (size != NULL) {
+ *size = fdt32_to_cpu(*cuint);
+ }
+
+ return 0;
+}
+
+/*******************************************************************************
* This function gets the stdout path node.
* It reads the value indicated inside the device tree.
* Returns node offset on success and a negative FDT error code on failure.
@@ -215,6 +295,8 @@
{
const fdt32_t *cuint;
+ assert(fdt_get_node_parent_address_cells(node) == 1);
+
cuint = fdt_getprop(fdt, node, "reg", NULL);
if (cuint != NULL) {
info->base = fdt32_to_cpu(*cuint);
@@ -309,6 +391,9 @@
return 0;
}
+ assert((fdt_get_node_parent_address_cells(node) == 1) &&
+ (fdt_get_node_parent_size_cells(node) == 1));
+
if (fdt_read_uint32_array(node, "reg", array, 4) < 0) {
return 0;
}
@@ -331,6 +416,9 @@
return 0;
}
+ assert((fdt_get_node_parent_address_cells(node) == 1) &&
+ (fdt_get_node_parent_size_cells(node) == 1));
+
if (fdt_read_uint32_array(node, "reg", array, 4) < 0) {
return 0;
}
@@ -353,6 +441,8 @@
return 0;
}
+ assert(fdt_get_node_parent_address_cells(node) == 1);
+
cuint = fdt_getprop(fdt, node, "reg", NULL);
if (cuint == NULL) {
return 0;
@@ -415,6 +505,8 @@
return 0;
}
+ assert(fdt_get_node_parent_address_cells(node) == 1);
+
cuint = fdt_getprop(fdt, node, "reg", NULL);
if (cuint == NULL) {
return 0;