Loading...
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); } |