Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

device property: Add fwnode_graph_get_endpoint_by_id()

fwnode_graph_get_endpoint_by_id() is intended for obtaining local
endpoints by a given local port.

fwnode_graph_get_endpoint_by_id() is slightly different from its OF
counterpart, of_graph_get_endpoint_by_regs(): instead of using -1 as
a value to indicate that a port or an endpoint number does not matter,
it uses flags to look for equal or greater endpoint. The port number
is always fixed. It also returns only remote endpoints that belong
to an available device, a behaviour that can be turned off with a flag.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
[ rjw: Changelog ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

authored by

Sakari Ailus and committed by
Rafael J. Wysocki
0fcc2bdc 5f21f305

+93
+75
drivers/base/property.c
··· 984 984 EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_node); 985 985 986 986 /** 987 + * fwnode_graph_get_endpoint_by_id - get endpoint by port and endpoint numbers 988 + * @fwnode: parent fwnode_handle containing the graph 989 + * @port: identifier of the port node 990 + * @endpoint: identifier of the endpoint node under the port node 991 + * @flags: fwnode lookup flags 992 + * 993 + * Return the fwnode handle of the local endpoint corresponding the port and 994 + * endpoint IDs or NULL if not found. 995 + * 996 + * If FWNODE_GRAPH_ENDPOINT_NEXT is passed in @flags and the specified endpoint 997 + * has not been found, look for the closest endpoint ID greater than the 998 + * specified one and return the endpoint that corresponds to it, if present. 999 + * 1000 + * Do not return endpoints that belong to disabled devices, unless 1001 + * FWNODE_GRAPH_DEVICE_DISABLED is passed in @flags. 1002 + * 1003 + * The returned endpoint needs to be released by calling fwnode_handle_put() on 1004 + * it when it is not needed any more. 1005 + */ 1006 + struct fwnode_handle * 1007 + fwnode_graph_get_endpoint_by_id(const struct fwnode_handle *fwnode, 1008 + u32 port, u32 endpoint, unsigned long flags) 1009 + { 1010 + struct fwnode_handle *ep = NULL, *best_ep = NULL; 1011 + unsigned int best_ep_id = 0; 1012 + bool endpoint_next = flags & FWNODE_GRAPH_ENDPOINT_NEXT; 1013 + bool enabled_only = !(flags & FWNODE_GRAPH_DEVICE_DISABLED); 1014 + 1015 + while ((ep = fwnode_graph_get_next_endpoint(fwnode, ep))) { 1016 + struct fwnode_endpoint fwnode_ep = { 0 }; 1017 + int ret; 1018 + 1019 + if (enabled_only) { 1020 + struct fwnode_handle *dev_node; 1021 + bool available; 1022 + 1023 + dev_node = fwnode_graph_get_remote_port_parent(ep); 1024 + available = fwnode_device_is_available(dev_node); 1025 + fwnode_handle_put(dev_node); 1026 + if (!available) 1027 + continue; 1028 + } 1029 + 1030 + ret = fwnode_graph_parse_endpoint(ep, &fwnode_ep); 1031 + if (ret < 0) 1032 + continue; 1033 + 1034 + if (fwnode_ep.port != port) 1035 + continue; 1036 + 1037 + if (fwnode_ep.id == endpoint) 1038 + return ep; 1039 + 1040 + if (!endpoint_next) 1041 + continue; 1042 + 1043 + /* 1044 + * If the endpoint that has just been found is not the first 1045 + * matching one and the ID of the one found previously is closer 1046 + * to the requested endpoint ID, skip it. 1047 + */ 1048 + if (fwnode_ep.id < endpoint || 1049 + (best_ep && best_ep_id < fwnode_ep.id)) 1050 + continue; 1051 + 1052 + fwnode_handle_put(best_ep); 1053 + best_ep = fwnode_handle_get(ep); 1054 + best_ep_id = fwnode_ep.id; 1055 + } 1056 + 1057 + return best_ep; 1058 + } 1059 + EXPORT_SYMBOL_GPL(fwnode_graph_get_endpoint_by_id); 1060 + 1061 + /** 987 1062 * fwnode_graph_parse_endpoint - parse common endpoint node properties 988 1063 * @fwnode: pointer to endpoint fwnode_handle 989 1064 * @endpoint: pointer to the fwnode endpoint data structure
+18
include/linux/property.h
··· 13 13 #ifndef _LINUX_PROPERTY_H_ 14 14 #define _LINUX_PROPERTY_H_ 15 15 16 + #include <linux/bits.h> 16 17 #include <linux/fwnode.h> 17 18 #include <linux/types.h> 18 19 ··· 304 303 struct fwnode_handle * 305 304 fwnode_graph_get_remote_node(const struct fwnode_handle *fwnode, u32 port, 306 305 u32 endpoint); 306 + 307 + /* 308 + * Fwnode lookup flags 309 + * 310 + * @FWNODE_GRAPH_ENDPOINT_NEXT: In the case of no exact match, look for the 311 + * closest endpoint ID greater than the specified 312 + * one. 313 + * @FWNODE_GRAPH_DEVICE_DISABLED: That the device to which the remote 314 + * endpoint of the given endpoint belongs to, 315 + * may be disabled. 316 + */ 317 + #define FWNODE_GRAPH_ENDPOINT_NEXT BIT(0) 318 + #define FWNODE_GRAPH_DEVICE_DISABLED BIT(1) 319 + 320 + struct fwnode_handle * 321 + fwnode_graph_get_endpoint_by_id(const struct fwnode_handle *fwnode, 322 + u32 port, u32 endpoint, unsigned long flags); 307 323 308 324 #define fwnode_graph_for_each_endpoint(fwnode, child) \ 309 325 for (child = NULL; \