[PATCH v3 1/2] core: ofnode: add of_graph parsing helpers

Svyatoslav Ryhel clamor95 at gmail.com
Tue Feb 18 18:08:38 CET 2025


Add a mostly complete list of ofnode analogs of of_graph
parsing helpers.

Signed-off-by: Svyatoslav Ryhel <clamor95 at gmail.com>
---
 drivers/core/Makefile       |   2 +-
 drivers/core/ofnode_graph.c | 217 ++++++++++++++++++++++++++++++++++++
 include/dm/ofnode_graph.h   |  90 +++++++++++++++
 3 files changed, 308 insertions(+), 1 deletion(-)
 create mode 100644 drivers/core/ofnode_graph.c
 create mode 100644 include/dm/ofnode_graph.h

diff --git a/drivers/core/Makefile b/drivers/core/Makefile
index 9ea57911f89..657e589c286 100644
--- a/drivers/core/Makefile
+++ b/drivers/core/Makefile
@@ -16,6 +16,6 @@ ifndef CONFIG_DM_DEV_READ_INLINE
 obj-$(CONFIG_OF_CONTROL) += read.o
 endif
 obj-$(CONFIG_$(XPL_)OF_PLATDATA) += read.o
-obj-$(CONFIG_OF_CONTROL) += of_extra.o ofnode.o read_extra.o
+obj-$(CONFIG_OF_CONTROL) += of_extra.o ofnode.o read_extra.o ofnode_graph.o
 
 ccflags-$(CONFIG_DM_DEBUG) += -DDEBUG
diff --git a/drivers/core/ofnode_graph.c b/drivers/core/ofnode_graph.c
new file mode 100644
index 00000000000..90c92af3258
--- /dev/null
+++ b/drivers/core/ofnode_graph.c
@@ -0,0 +1,217 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2025 Svyatoslav Ryhel <clamor95 at gmail.com>
+ */
+
+#define LOG_CATEGORY	LOGC_DT
+
+#include <dm.h>
+#include <log.h>
+#include <dm/ofnode.h>
+#include <linux/err.h>
+
+/**
+ * ofnode_graph_get_endpoint_count() - get the number of endpoints in a device ofnode
+ * @parent: ofnode to the device containing ports and endpoints
+ *
+ * Return: count of endpoint of this device ofnode
+ */
+unsigned int ofnode_graph_get_endpoint_count(ofnode parent)
+{
+	ofnode ports, port, endpoint;
+	unsigned int num = 0;
+
+	/* Check if ports node exists */
+	ports = ofnode_find_subnode(parent, "ports");
+	if (ofnode_valid(ports))
+		parent = ports;
+
+	ofnode_for_each_subnode(port, parent) {
+		if (!strncmp(ofnode_get_name(port), "port", 4)) {
+			/* Port node can only contain endpoints */
+			ofnode_for_each_subnode(endpoint, port)
+				num++;
+		}
+	};
+
+	log_debug("%s: detected %d endpoints\n", __func__, num);
+
+	return num++;
+}
+
+/**
+ * ofnode_graph_get_port_count() - get the number of port in a device or ports ofnode
+ * @parent: ofnode to the device or ports node
+ *
+ * Return: count of port of this device or ports node
+ */
+unsigned int ofnode_graph_get_port_count(ofnode parent)
+{
+	ofnode ports, port;
+	unsigned int num = 0;
+
+	/* Check if ports node exists */
+	ports = ofnode_find_subnode(parent, "ports");
+	if (ofnode_valid(ports))
+		parent = ports;
+
+	ofnode_for_each_subnode(port, parent)
+		if (!strncmp(ofnode_get_name(port), "port", 4))
+			num++;
+
+	log_debug("%s: detected %d ports\n", __func__, num);
+
+	return num++;
+}
+
+/**
+ * ofnode_graph_get_port_by_id() - get the port matching a given id
+ * @parent: parent ofnode
+ * @id: id of the port
+ *
+ * Return: ofnode in given port.
+ */
+ofnode ofnode_graph_get_port_by_id(ofnode parent, u32 id)
+{
+	ofnode ports, port;
+	u32 port_id;
+
+	ports = ofnode_find_subnode(parent, "ports");
+	if (!ofnode_valid(ports))
+		return ofnode_null();
+
+	/* Check ports for node with desired id */
+	ofnode_for_each_subnode(port, ports) {
+		ofnode_read_u32(port, "reg", &port_id);
+		log_debug("%s: detected port %d\n", __func__, port_id);
+		if (port_id == id)
+			return port;
+	}
+
+	return ofnode_null();
+}
+
+/**
+ * ofnode_graph_get_endpoint_by_regs() - get the endpoint matching a given id
+ * @parent: parent ofnode
+ * @reg_id: id of the port
+ * @id: id for the endpoint
+ *
+ * Return: ofnode in given endpoint or ofnode_null() if not found.
+ * reg and port_reg are ignored when they are -1.
+ */
+ofnode ofnode_graph_get_endpoint_by_regs(ofnode parent, int reg_id, int id)
+{
+	ofnode port, endpoint;
+	u32 ep_id;
+
+	/* get the port to work with */
+	if (reg_id < 0)
+		port = ofnode_find_subnode(parent, "port");
+	else
+		port = ofnode_graph_get_port_by_id(parent, reg_id);
+
+	if (!ofnode_valid(port)) {
+		log_debug("%s: port node is not found\n", __func__);
+		return ofnode_null();
+	}
+
+	if (id < 0)
+		return ofnode_find_subnode(port, "endpoint");
+
+	/* Check endpoints for node with desired id */
+	ofnode_for_each_subnode(endpoint, port) {
+		ofnode_read_u32(endpoint, "reg", &ep_id);
+		log_debug("%s: detected endpoint %d\n", __func__, ep_id);
+		if (ep_id == id)
+			return endpoint;
+	}
+
+	return ofnode_null();
+}
+
+/**
+ * ofnode_graph_get_remote_endpoint() - get remote endpoint node
+ * @endpoint: ofnode of a local endpoint
+ *
+ * Return: Remote endpoint ofnode linked with local endpoint.
+ */
+ofnode ofnode_graph_get_remote_endpoint(ofnode endpoint)
+{
+	/* Get remote endpoint node. */
+	return ofnode_parse_phandle(endpoint, "remote-endpoint", 0);
+}
+
+/**
+ * ofnode_graph_get_port_parent() - get port's parent node
+ * @endpoint: ofnode of a local endpoint
+ *
+ * Return: device ofnode associated with endpoint
+ */
+ofnode ofnode_graph_get_port_parent(ofnode endpoint)
+{
+	ofnode port = ofnode_get_parent(endpoint);
+	ofnode parent = ofnode_get_parent(port);
+
+	/* check if we are on top level or in ports node */
+	if (!strcmp(ofnode_get_name(parent), "ports"))
+		parent = ofnode_get_parent(parent);
+
+	return parent;
+}
+
+/**
+ * ofnode_graph_get_remote_port_parent() - get remote port's parent ofnode
+ * @endpoint: ofnode of a local endpoint
+ *
+ * Return: device ofnode associated with endpoint linked to local endpoint.
+ */
+ofnode ofnode_graph_get_remote_port_parent(ofnode endpoint)
+{
+	ofnode remote_endpoint = ofnode_graph_get_remote_endpoint(endpoint);
+	if (!ofnode_valid(remote_endpoint)) {
+		log_debug("%s: remote endpoint is not found\n", __func__);
+		return ofnode_null();
+	}
+
+	return ofnode_graph_get_port_parent(remote_endpoint);
+}
+
+/**
+ * ofnode_graph_get_remote_port() - get remote port ofnode
+ * @endpoint: ofnode of a local endpoint
+ *
+ * Return: port ofnode associated with remote endpoint node linked
+ * to local endpoint.
+ */
+ofnode ofnode_graph_get_remote_port(ofnode endpoint)
+{
+	ofnode remote_endpoint = ofnode_graph_get_remote_endpoint(endpoint);
+	if (!ofnode_valid(remote_endpoint)) {
+		log_debug("%s: remote endpoint is not found\n", __func__);
+		return ofnode_null();
+	}
+
+	return ofnode_get_parent(remote_endpoint);
+}
+
+/**
+ * ofnode_graph_get_remote_node() - get remote parent ofnode for given port/endpoint
+ * @parent: parent ofnode containing graph port/endpoint
+ * @port: identifier (value of reg property) of the parent port ofnode
+ * @endpoint: identifier (value of reg property) of the endpoint ofnode
+ *
+ * Return: device ofnode associated with endpoint linked to local endpoint.
+ */
+ofnode ofnode_graph_get_remote_node(ofnode parent, int port, int endpoint)
+{
+	ofnode endpoint_ofnode;
+
+	endpoint_ofnode = ofnode_graph_get_endpoint_by_regs(parent, port, endpoint);
+	if (!ofnode_valid(endpoint_ofnode)) {
+		log_debug("%s: endpoint is not found\n", __func__);
+		return ofnode_null();
+	}
+
+	return ofnode_graph_get_remote_port_parent(endpoint_ofnode);
+}
diff --git a/include/dm/ofnode_graph.h b/include/dm/ofnode_graph.h
new file mode 100644
index 00000000000..908c990a3f3
--- /dev/null
+++ b/include/dm/ofnode_graph.h
@@ -0,0 +1,90 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2025 Svyatoslav Ryhel <clamor95 at gmail.com>
+ */
+
+#ifndef _DM_OFNODE_GRAPH_H
+#define _DM_OFNODE_GRAPH_H
+
+#include <dm/of.h>
+
+/**
+ * ofnode_graph_get_endpoint_count() - get the number of endpoints in a device ofnode
+ * @parent: ofnode to the device containing ports and endpoints
+ *
+ * Return: count of endpoint of this device ofnode
+ */
+unsigned int ofnode_graph_get_endpoint_count(ofnode parent);
+
+/**
+ * ofnode_graph_get_port_count() - get the number of port in a device or ports ofnode
+ * @parent: ofnode to the device or ports node
+ *
+ * Return: count of port of this device or ports node
+ */
+unsigned int ofnode_graph_get_port_count(ofnode parent);
+
+/**
+ * ofnode_graph_get_port_by_id() - get the port matching a given id
+ * @parent: parent ofnode
+ * @id: id of the port
+ *
+ * Return: ofnode in given port.
+ */
+ofnode ofnode_graph_get_port_by_id(ofnode parent, u32 id);
+
+/**
+ * ofnode_graph_get_endpoint_by_regs() - get the endpoint matching a given id
+ * @parent: parent ofnode
+ * @reg_id: id of the port
+ * @id: id for the endpoint
+ *
+ * Return: ofnode in given endpoint or NULL if not found.
+ * reg and port_reg are ignored when they are -1.
+ */
+ofnode ofnode_graph_get_endpoint_by_regs(ofnode parent, u32 reg_id, u32 id);
+
+/**
+ * ofnode_graph_get_remote_endpoint() - get remote endpoint node
+ * @endoint: ofnode of a local endpoint
+ *
+ * Return: Remote endpoint ofnode linked with local endpoint.
+ */
+ofnode ofnode_graph_get_remote_endpoint(ofnode endpoint);
+
+/**
+ * ofnode_graph_get_port_parent() - get port's parent node
+ * @endpoint: ofnode of a local endpoint
+ *
+ * Return: device ofnode associated with endpoint
+ */
+ofnode ofnode_graph_get_port_parent(ofnode endpoint);
+
+/**
+ * ofnode_graph_get_remote_port_parent() - get remote port's parent ofnode
+ * @endoint: ofnode of a local endpoint
+ *
+ * Return: device ofnode associated with endpoint linked to local endpoint.
+ */
+ofnode ofnode_graph_get_remote_port_parent(ofnode endpoint);
+
+/**
+ * ofnode_graph_get_remote_port() - get remote port ofnode
+ * @endoint: ofnode of a local endpoint
+ *
+ * Return: port ofnode associated with remote endpoint node linked
+ * to local endpoint.
+ */
+ofnode ofnode_graph_get_remote_port(ofnode endpoint);
+
+/**
+ * ofnode_graph_get_remote_node() - get remote parent ofnode for given port/endpoint
+ * @parent: parent ofnode containing graph port/endpoint
+ * @port: identifier (value of reg property) of the parent port ofnode
+ * @endpoint: identifier (value of reg property) of the endpoint ofnode
+ *
+ * Return: device ofnode associated with endpoint linked to local endpoint.
+ */
+ofnode ofnode_graph_get_remote_node(ofnode parent, u32 port, u32 endpoint);
+
+#endif
-- 
2.43.0



More information about the U-Boot mailing list