diff mbox series

[u-boot-marvell,RESEND,06/11] fdt_support: Add some useful functions

Message ID 20211126135715.26485-7-kabel@kernel.org
State Accepted
Commit 9ab0c2f837241b819b23cbb5d48fa43acc2938d5
Delegated to: Stefan Roese
Headers show
Series Some mvebu comphy + mox + fdt_support changes | expand

Commit Message

Marek Behún Nov. 26, 2021, 1:57 p.m. UTC
From: Marek Behún <marek.behun@nic.cz>

Add functions
  fdt_node_offset_by_pathf(),
  fdt_create_phandle_by_pathf(),
  fdt_set_status_by_pathf()
to get node offset, get/create node phandle and set status for node
given by path/alias formatted with sprintf.

Add functions
  fdt_create_phandle_by_compatible(),
  fdt_set_status_by_compatible()
to get/create node phandle and set status for first node given by
compatible.

Signed-off-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
---
 common/fdt_support.c  | 119 ++++++++++++++++++++++++++++++++++++++++++
 include/fdt_support.h |  30 +++++++++++
 2 files changed, 149 insertions(+)
diff mbox series

Patch

diff --git a/common/fdt_support.c b/common/fdt_support.c
index df111f708c..c2e16727e1 100644
--- a/common/fdt_support.c
+++ b/common/fdt_support.c
@@ -1463,6 +1463,37 @@  int fdt_node_offset_by_compat_reg(void *blob, const char *compat,
 	return -FDT_ERR_NOTFOUND;
 }
 
+static int vnode_offset_by_pathf(void *blob, const char *fmt, va_list ap)
+{
+	char path[512];
+	int len;
+
+	len = vsnprintf(path, sizeof(path), fmt, ap);
+	if (len < 0 || len + 1 > sizeof(path))
+		return -FDT_ERR_NOSPACE;
+
+	return fdt_path_offset(blob, path);
+}
+
+/**
+ * fdt_node_offset_by_pathf: Find node offset by sprintf formatted path
+ *
+ * @blob: ptr to device tree
+ * @fmt: path format
+ * @ap: vsnprintf arguments
+ */
+int fdt_node_offset_by_pathf(void *blob, const char *fmt, ...)
+{
+	va_list ap;
+	int res;
+
+	va_start(ap, fmt);
+	res = vnode_offset_by_pathf(blob, fmt, ap);
+	va_end(ap);
+
+	return res;
+}
+
 /*
  * fdt_set_phandle: Create a phandle property for the given node
  *
@@ -1536,6 +1567,51 @@  unsigned int fdt_create_phandle(void *fdt, int nodeoffset)
 	return phandle;
 }
 
+/**
+ * fdt_create_phandle_by_compatible: Get or create a phandle for first node with
+ *				     given compatible
+ *
+ * @fdt: ptr to device tree
+ * @compat: node's compatible string
+ */
+unsigned int fdt_create_phandle_by_compatible(void *fdt, const char *compat)
+{
+	int offset = fdt_node_offset_by_compatible(fdt, -1, compat);
+
+	if (offset < 0) {
+		printf("Can't find node with compatible \"%s\": %s\n", compat,
+		       fdt_strerror(offset));
+		return 0;
+	}
+
+	return fdt_create_phandle(fdt, offset);
+}
+
+/**
+ * fdt_create_phandle_by_pathf: Get or create a phandle for node given by
+ *				sprintf-formatted path
+ *
+ * @fdt: ptr to device tree
+ * @fmt, ...: path format string and arguments to pass to sprintf
+ */
+unsigned int fdt_create_phandle_by_pathf(void *fdt, const char *fmt, ...)
+{
+	va_list ap;
+	int offset;
+
+	va_start(ap, fmt);
+	offset = vnode_offset_by_pathf(fdt, fmt, ap);
+	va_end(ap);
+
+	if (offset < 0) {
+		printf("Can't find node by given path: %s\n",
+		       fdt_strerror(offset));
+		return 0;
+	}
+
+	return fdt_create_phandle(fdt, offset);
+}
+
 /*
  * fdt_set_node_status: Set status for the given node
  *
@@ -1584,6 +1660,49 @@  int fdt_set_status_by_alias(void *fdt, const char* alias,
 	return fdt_set_node_status(fdt, offset, status);
 }
 
+/**
+ * fdt_set_status_by_compatible: Set node status for first node with given
+ *				 compatible
+ *
+ * @fdt: ptr to device tree
+ * @compat: node's compatible string
+ * @status: FDT_STATUS_OKAY, FDT_STATUS_DISABLED, FDT_STATUS_FAIL
+ */
+int fdt_set_status_by_compatible(void *fdt, const char *compat,
+				 enum fdt_status status)
+{
+	int offset = fdt_node_offset_by_compatible(fdt, -1, compat);
+
+	if (offset < 0)
+		return offset;
+
+	return fdt_set_node_status(fdt, offset, status);
+}
+
+/**
+ * fdt_set_status_by_pathf: Set node status for node given by sprintf-formatted
+ *			    path
+ *
+ * @fdt: ptr to device tree
+ * @status: FDT_STATUS_OKAY, FDT_STATUS_DISABLED, FDT_STATUS_FAIL
+ * @fmt, ...: path format string and arguments to pass to sprintf
+ */
+int fdt_set_status_by_pathf(void *fdt, enum fdt_status status, const char *fmt,
+			    ...)
+{
+	va_list ap;
+	int offset;
+
+	va_start(ap, fmt);
+	offset = vnode_offset_by_pathf(fdt, fmt, ap);
+	va_end(ap);
+
+	if (offset < 0)
+		return offset;
+
+	return fdt_set_node_status(fdt, offset, status);
+}
+
 #if defined(CONFIG_VIDEO) || defined(CONFIG_LCD)
 int fdt_add_edid(void *blob, const char *compat, unsigned char *edid_buf)
 {
diff --git a/include/fdt_support.h b/include/fdt_support.h
index 850c860bd4..d40586725b 100644
--- a/include/fdt_support.h
+++ b/include/fdt_support.h
@@ -285,8 +285,13 @@  int fdt_get_dma_range(const void *blob, int node_offset, phys_addr_t *cpu,
 
 int fdt_node_offset_by_compat_reg(void *blob, const char *compat,
 					phys_addr_t compat_off);
+int fdt_node_offset_by_pathf(void *blob, const char *fmt, ...)
+	__attribute__ ((format (printf, 2, 3)));
 int fdt_set_phandle(void *fdt, int nodeoffset, uint32_t phandle);
 unsigned int fdt_create_phandle(void *fdt, int nodeoffset);
+unsigned int fdt_create_phandle_by_compatible(void *fdt, const char *compat);
+unsigned int fdt_create_phandle_by_pathf(void *fdt, const char *fmt, ...)
+	__attribute__ ((format (printf, 2, 3)));
 int fdt_add_edid(void *blob, const char *compat, unsigned char *buf);
 
 int fdt_verify_alias_address(void *fdt, int anode, const char *alias,
@@ -329,6 +334,31 @@  static inline int fdt_status_fail_by_alias(void *fdt, const char *alias)
 	return fdt_set_status_by_alias(fdt, alias, FDT_STATUS_FAIL);
 }
 
+int fdt_set_status_by_compatible(void *fdt, const char *compat,
+				 enum fdt_status status);
+static inline int fdt_status_okay_by_compatible(void *fdt, const char *compat)
+{
+	return fdt_set_status_by_compatible(fdt, compat, FDT_STATUS_OKAY);
+}
+static inline int fdt_status_disabled_by_compatible(void *fdt,
+						    const char *compat)
+{
+	return fdt_set_status_by_compatible(fdt, compat, FDT_STATUS_DISABLED);
+}
+static inline int fdt_status_fail_by_compatible(void *fdt, const char *compat)
+{
+	return fdt_set_status_by_compatible(fdt, compat, FDT_STATUS_FAIL);
+}
+
+int fdt_set_status_by_pathf(void *fdt, enum fdt_status status, const char *fmt,
+			    ...) __attribute__ ((format (printf, 3, 4)));
+#define fdt_status_okay_by_pathf(fdt, fmt, ...) \
+	fdt_set_status_by_pathf((fdt), FDT_STATUS_OKAY, (fmt), ##__VA_ARGS__)
+#define fdt_status_disabled_by_pathf(fdt, fmt, ...) \
+	fdt_set_status_by_pathf((fdt), FDT_STATUS_DISABLED, (fmt), ##__VA_ARGS__)
+#define fdt_status_fail_by_pathf(fdt, fmt, ...) \
+	fdt_set_status_by_pathf((fdt), FDT_STATUS_FAIL, (fmt), ##__VA_ARGS__)
+
 /* Helper to read a big number; size is in cells (not bytes) */
 static inline u64 fdt_read_number(const fdt32_t *cell, int size)
 {