[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