aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/base/property.c75
-rw-r--r--include/linux/property.h18
2 files changed, 93 insertions, 0 deletions
diff --git a/drivers/base/property.c b/drivers/base/property.c
index 8b91ab380d14..348b37e64944 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -984,6 +984,81 @@ fwnode_graph_get_remote_node(const struct fwnode_handle *fwnode, u32 port_id,
984EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_node); 984EXPORT_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 */
1006struct fwnode_handle *
1007fwnode_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}
1059EXPORT_SYMBOL_GPL(fwnode_graph_get_endpoint_by_id);
1060
1061/**
987 * fwnode_graph_parse_endpoint - parse common endpoint node properties 1062 * fwnode_graph_parse_endpoint - parse common endpoint node properties
988 * @fwnode: pointer to endpoint fwnode_handle 1063 * @fwnode: pointer to endpoint fwnode_handle
989 * @endpoint: pointer to the fwnode endpoint data structure 1064 * @endpoint: pointer to the fwnode endpoint data structure
diff --git a/include/linux/property.h b/include/linux/property.h
index 65d3420dd5d1..a29369c89e6e 100644
--- a/include/linux/property.h
+++ b/include/linux/property.h
@@ -13,6 +13,7 @@
13#ifndef _LINUX_PROPERTY_H_ 13#ifndef _LINUX_PROPERTY_H_
14#define _LINUX_PROPERTY_H_ 14#define _LINUX_PROPERTY_H_
15 15
16#include <linux/bits.h>
16#include <linux/fwnode.h> 17#include <linux/fwnode.h>
17#include <linux/types.h> 18#include <linux/types.h>
18 19
@@ -304,6 +305,23 @@ struct fwnode_handle *
304fwnode_graph_get_remote_node(const struct fwnode_handle *fwnode, u32 port, 305fwnode_graph_get_remote_node(const struct fwnode_handle *fwnode, u32 port,
305 u32 endpoint); 306 u32 endpoint);
306 307
308/*
309 * Fwnode lookup flags
310 *
311 * @FWNODE_GRAPH_ENDPOINT_NEXT: In the case of no exact match, look for the
312 * closest endpoint ID greater than the specified
313 * one.
314 * @FWNODE_GRAPH_DEVICE_DISABLED: That the device to which the remote
315 * endpoint of the given endpoint belongs to,
316 * may be disabled.
317 */
318#define FWNODE_GRAPH_ENDPOINT_NEXT BIT(0)
319#define FWNODE_GRAPH_DEVICE_DISABLED BIT(1)
320
321struct fwnode_handle *
322fwnode_graph_get_endpoint_by_id(const struct fwnode_handle *fwnode,
323 u32 port, u32 endpoint, unsigned long flags);
324
307#define fwnode_graph_for_each_endpoint(fwnode, child) \ 325#define fwnode_graph_for_each_endpoint(fwnode, child) \
308 for (child = NULL; \ 326 for (child = NULL; \
309 (child = fwnode_graph_get_next_endpoint(fwnode, child)); ) 327 (child = fwnode_graph_get_next_endpoint(fwnode, child)); )