1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
|
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2025 Svyatoslav Ryhel <clamor95@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_id and id 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);
}
|