// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 2025 Svyatoslav Ryhel */ #define LOG_CATEGORY LOGC_DT #include #include #include #include /** * 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); }