blob: 90c92af3258ce73209e19c0d0ee6a8f35ef4e26a [file] [log] [blame]
Svyatoslav Ryhel2e237462025-02-15 19:46:29 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (c) 2025 Svyatoslav Ryhel <clamor95@gmail.com>
4 */
5
6#define LOG_CATEGORY LOGC_DT
7
8#include <dm.h>
9#include <log.h>
10#include <dm/ofnode.h>
11#include <linux/err.h>
12
13/**
14 * ofnode_graph_get_endpoint_count() - get the number of endpoints in a device ofnode
15 * @parent: ofnode to the device containing ports and endpoints
16 *
17 * Return: count of endpoint of this device ofnode
18 */
19unsigned int ofnode_graph_get_endpoint_count(ofnode parent)
20{
21 ofnode ports, port, endpoint;
22 unsigned int num = 0;
23
24 /* Check if ports node exists */
25 ports = ofnode_find_subnode(parent, "ports");
26 if (ofnode_valid(ports))
27 parent = ports;
28
29 ofnode_for_each_subnode(port, parent) {
30 if (!strncmp(ofnode_get_name(port), "port", 4)) {
31 /* Port node can only contain endpoints */
32 ofnode_for_each_subnode(endpoint, port)
33 num++;
34 }
35 };
36
37 log_debug("%s: detected %d endpoints\n", __func__, num);
38
39 return num++;
40}
41
42/**
43 * ofnode_graph_get_port_count() - get the number of port in a device or ports ofnode
44 * @parent: ofnode to the device or ports node
45 *
46 * Return: count of port of this device or ports node
47 */
48unsigned int ofnode_graph_get_port_count(ofnode parent)
49{
50 ofnode ports, port;
51 unsigned int num = 0;
52
53 /* Check if ports node exists */
54 ports = ofnode_find_subnode(parent, "ports");
55 if (ofnode_valid(ports))
56 parent = ports;
57
58 ofnode_for_each_subnode(port, parent)
59 if (!strncmp(ofnode_get_name(port), "port", 4))
60 num++;
61
62 log_debug("%s: detected %d ports\n", __func__, num);
63
64 return num++;
65}
66
67/**
68 * ofnode_graph_get_port_by_id() - get the port matching a given id
69 * @parent: parent ofnode
70 * @id: id of the port
71 *
72 * Return: ofnode in given port.
73 */
74ofnode ofnode_graph_get_port_by_id(ofnode parent, u32 id)
75{
76 ofnode ports, port;
77 u32 port_id;
78
79 ports = ofnode_find_subnode(parent, "ports");
80 if (!ofnode_valid(ports))
81 return ofnode_null();
82
83 /* Check ports for node with desired id */
84 ofnode_for_each_subnode(port, ports) {
85 ofnode_read_u32(port, "reg", &port_id);
86 log_debug("%s: detected port %d\n", __func__, port_id);
87 if (port_id == id)
88 return port;
89 }
90
91 return ofnode_null();
92}
93
94/**
95 * ofnode_graph_get_endpoint_by_regs() - get the endpoint matching a given id
96 * @parent: parent ofnode
97 * @reg_id: id of the port
98 * @id: id for the endpoint
99 *
100 * Return: ofnode in given endpoint or ofnode_null() if not found.
101 * reg and port_reg are ignored when they are -1.
102 */
103ofnode ofnode_graph_get_endpoint_by_regs(ofnode parent, int reg_id, int id)
104{
105 ofnode port, endpoint;
106 u32 ep_id;
107
108 /* get the port to work with */
109 if (reg_id < 0)
110 port = ofnode_find_subnode(parent, "port");
111 else
112 port = ofnode_graph_get_port_by_id(parent, reg_id);
113
114 if (!ofnode_valid(port)) {
115 log_debug("%s: port node is not found\n", __func__);
116 return ofnode_null();
117 }
118
119 if (id < 0)
120 return ofnode_find_subnode(port, "endpoint");
121
122 /* Check endpoints for node with desired id */
123 ofnode_for_each_subnode(endpoint, port) {
124 ofnode_read_u32(endpoint, "reg", &ep_id);
125 log_debug("%s: detected endpoint %d\n", __func__, ep_id);
126 if (ep_id == id)
127 return endpoint;
128 }
129
130 return ofnode_null();
131}
132
133/**
134 * ofnode_graph_get_remote_endpoint() - get remote endpoint node
135 * @endpoint: ofnode of a local endpoint
136 *
137 * Return: Remote endpoint ofnode linked with local endpoint.
138 */
139ofnode ofnode_graph_get_remote_endpoint(ofnode endpoint)
140{
141 /* Get remote endpoint node. */
142 return ofnode_parse_phandle(endpoint, "remote-endpoint", 0);
143}
144
145/**
146 * ofnode_graph_get_port_parent() - get port's parent node
147 * @endpoint: ofnode of a local endpoint
148 *
149 * Return: device ofnode associated with endpoint
150 */
151ofnode ofnode_graph_get_port_parent(ofnode endpoint)
152{
153 ofnode port = ofnode_get_parent(endpoint);
154 ofnode parent = ofnode_get_parent(port);
155
156 /* check if we are on top level or in ports node */
157 if (!strcmp(ofnode_get_name(parent), "ports"))
158 parent = ofnode_get_parent(parent);
159
160 return parent;
161}
162
163/**
164 * ofnode_graph_get_remote_port_parent() - get remote port's parent ofnode
165 * @endpoint: ofnode of a local endpoint
166 *
167 * Return: device ofnode associated with endpoint linked to local endpoint.
168 */
169ofnode ofnode_graph_get_remote_port_parent(ofnode endpoint)
170{
171 ofnode remote_endpoint = ofnode_graph_get_remote_endpoint(endpoint);
172 if (!ofnode_valid(remote_endpoint)) {
173 log_debug("%s: remote endpoint is not found\n", __func__);
174 return ofnode_null();
175 }
176
177 return ofnode_graph_get_port_parent(remote_endpoint);
178}
179
180/**
181 * ofnode_graph_get_remote_port() - get remote port ofnode
182 * @endpoint: ofnode of a local endpoint
183 *
184 * Return: port ofnode associated with remote endpoint node linked
185 * to local endpoint.
186 */
187ofnode ofnode_graph_get_remote_port(ofnode endpoint)
188{
189 ofnode remote_endpoint = ofnode_graph_get_remote_endpoint(endpoint);
190 if (!ofnode_valid(remote_endpoint)) {
191 log_debug("%s: remote endpoint is not found\n", __func__);
192 return ofnode_null();
193 }
194
195 return ofnode_get_parent(remote_endpoint);
196}
197
198/**
199 * ofnode_graph_get_remote_node() - get remote parent ofnode for given port/endpoint
200 * @parent: parent ofnode containing graph port/endpoint
201 * @port: identifier (value of reg property) of the parent port ofnode
202 * @endpoint: identifier (value of reg property) of the endpoint ofnode
203 *
204 * Return: device ofnode associated with endpoint linked to local endpoint.
205 */
206ofnode ofnode_graph_get_remote_node(ofnode parent, int port, int endpoint)
207{
208 ofnode endpoint_ofnode;
209
210 endpoint_ofnode = ofnode_graph_get_endpoint_by_regs(parent, port, endpoint);
211 if (!ofnode_valid(endpoint_ofnode)) {
212 log_debug("%s: endpoint is not found\n", __func__);
213 return ofnode_null();
214 }
215
216 return ofnode_graph_get_remote_port_parent(endpoint_ofnode);
217}