From: Thierry Reding <tred...@nvidia.com>

The fdtdec_get_carveout() and fdtdec_set_carveout() function can be used
to read a carveout from a given node or add a carveout to a given node
using the standard device tree bindings (involving reserved-memory nodes
and the memory-region property).

Reviewed-by: Simon Glass <s...@chromium.org>
Signed-off-by: Thierry Reding <tred...@nvidia.com>
---
Changes in v2:
- use debug() instead of printf() to save code size
- fix carveout size computations, was off by one
- use fdtdec_get_addr_size_auto_noparent()

 include/fdtdec.h | 39 ++++++++++++++++++++++
 lib/fdtdec.c     | 87 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 126 insertions(+)

diff --git a/include/fdtdec.h b/include/fdtdec.h
index 5c23a9e5f104..14fff6806df2 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -1021,6 +1021,45 @@ int fdtdec_add_reserved_memory(void *blob, const char 
*basename,
                               const struct fdt_memory *carveout,
                               uint32_t *phandlep);
 
+/**
+ * fdtdec_get_carveout() - reads a carveout from an FDT
+ *
+ * Reads information about a carveout region from an FDT. The carveout is a
+ * referenced by its phandle that is read from a given property in a given
+ * node.
+ *
+ * @param blob         FDT blob
+ * @param node         name of a node
+ * @param name         name of the property in the given node that contains
+ *                     the phandle for the carveout
+ * @param index                index of the phandle for which to read the 
carveout
+ * @param carveout     return location for the carveout information
+ * @return 0 on success or a negative error code on failure
+ */
+int fdtdec_get_carveout(const void *blob, const char *node, const char *name,
+                       unsigned int index, struct fdt_memory *carveout);
+
+/**
+ * fdtdec_set_carveout() - sets a carveout region for a given node
+ *
+ * Sets a carveout region for a given node. If a reserved-memory node already
+ * exists for the carveout, the phandle for that node will be reused. If no
+ * such node exists, a new one will be created and a phandle to it stored in
+ * a specified property of the given node.
+ *
+ * @param blob         FDT blob
+ * @param node         name of the node to add the carveout to
+ * @param prop_name    name of the property in which to store the phandle of
+ *                     the carveout
+ * @param index                index of the phandle to store
+ * @param name         base name of the reserved-memory node to create
+ * @param carveout     information about the carveout to add
+ * @return 0 on success or a negative error code on failure
+ */
+int fdtdec_set_carveout(void *blob, const char *node, const char *prop_name,
+                       unsigned int index, const char *name,
+                       const struct fdt_memory *carveout);
+
 /**
  * Set up the device tree ready for use
  */
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index bef331df9a08..8ab41682104e 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -1409,6 +1409,93 @@ int fdtdec_add_reserved_memory(void *blob, const char 
*basename,
        return 0;
 }
 
+int fdtdec_get_carveout(const void *blob, const char *node, const char *name,
+                       unsigned int index, struct fdt_memory *carveout)
+{
+       const fdt32_t *prop;
+       uint32_t phandle;
+       int offset, len;
+       fdt_size_t size;
+
+       offset = fdt_path_offset(blob, node);
+       if (offset < 0)
+               return offset;
+
+       prop = fdt_getprop(blob, offset, name, &len);
+       if (!prop) {
+               debug("failed to get %s for %s\n", name, node);
+               return -FDT_ERR_NOTFOUND;
+       }
+
+       if ((len % sizeof(phandle)) != 0) {
+               debug("invalid phandle property\n");
+               return -FDT_ERR_BADPHANDLE;
+       }
+
+       if (len < (sizeof(phandle) * (index + 1))) {
+               debug("invalid phandle index\n");
+               return -FDT_ERR_BADPHANDLE;
+       }
+
+       phandle = fdt32_to_cpu(prop[index]);
+
+       offset = fdt_node_offset_by_phandle(blob, phandle);
+       if (offset < 0) {
+               debug("failed to find node for phandle %u\n", phandle);
+               return offset;
+       }
+
+       carveout->start = fdtdec_get_addr_size_auto_noparent(blob, offset,
+                                                            "reg", 0, &size,
+                                                            true);
+       if (carveout->start == FDT_ADDR_T_NONE) {
+               debug("failed to read address/size from \"reg\" property\n");
+               return -FDT_ERR_NOTFOUND;
+       }
+
+       carveout->end = carveout->start + size - 1;
+
+       return 0;
+}
+
+int fdtdec_set_carveout(void *blob, const char *node, const char *prop_name,
+                       unsigned int index, const char *name,
+                       const struct fdt_memory *carveout)
+{
+       uint32_t phandle;
+       int err, offset;
+       fdt32_t value;
+
+       /* XXX implement support for multiple phandles */
+       if (index > 0) {
+               debug("invalid index %u\n", index);
+               return -FDT_ERR_BADOFFSET;
+       }
+
+       err = fdtdec_add_reserved_memory(blob, name, carveout, &phandle);
+       if (err < 0) {
+               debug("failed to add reserved memory: %d\n", err);
+               return err;
+       }
+
+       offset = fdt_path_offset(blob, node);
+       if (offset < 0) {
+               debug("failed to find offset for node %s: %d\n", node, offset);
+               return offset;
+       }
+
+       value = cpu_to_fdt32(phandle);
+
+       err = fdt_setprop(blob, offset, prop_name, &value, sizeof(value));
+       if (err < 0) {
+               debug("failed to set %s property for node %s: %d\n", prop_name,
+                     node, err);
+               return err;
+       }
+
+       return 0;
+}
+
 int fdtdec_setup(void)
 {
 #if CONFIG_IS_ENABLED(OF_CONTROL)
-- 
2.20.1

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

Reply via email to