There are already several helpers to find a udevice based on its
position in a device tree, like getting a child or a node pointed by a
phandle, but there was no support for graph endpoints, which are very
common in display pipelines.

Add a new helper, named uclass_get_device_by_endpoint() which enters the
child graph reprensentation, looks for a specific port, then follows the
remote endpoint, and finally retrieves the first parent of the given
uclass_id.

This is a very handy and straightforward way to get a bridge or a panel
handle.

Reviewed-by: Simon Glass <s...@chromium.org>
Signed-off-by: Miquel Raynal <miquel.ray...@bootlin.com>
---
 drivers/core/uclass.c | 19 +++++++++++++++++++
 include/dm/uclass.h   | 24 ++++++++++++++++++++++++
 2 files changed, 43 insertions(+)

diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index 
f846a35d6b2537bab56bca158cedfb134b37f477..ce5e61bbaa63a181a1ea6781ad6a7f06be67c7e0
 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -16,6 +16,7 @@
 #include <dm/device.h>
 #include <dm/device-internal.h>
 #include <dm/lists.h>
+#include <dm/ofnode_graph.h>
 #include <dm/uclass.h>
 #include <dm/uclass-internal.h>
 #include <dm/util.h>
@@ -582,6 +583,24 @@ int uclass_get_device_by_phandle(enum uclass_id id, struct 
udevice *parent,
        ret = uclass_find_device_by_phandle(id, parent, name, &dev);
        return uclass_get_device_tail(dev, ret, devp);
 }
+
+int uclass_get_device_by_endpoint(enum uclass_id class_id, struct udevice *dev,
+                                 int port_idx, int ep_idx, struct udevice 
**devp)
+{
+       ofnode node_source = dev_ofnode(dev);
+       ofnode node_dest = ofnode_graph_get_remote_node(node_source, port_idx, 
ep_idx);
+       struct udevice *target = NULL;
+       int ret;
+
+       if (!ofnode_valid(node_dest))
+               return -EINVAL;
+
+       ret = uclass_find_device_by_ofnode(class_id, node_dest, &target);
+       if (ret)
+               return -ENODEV;
+
+       return uclass_get_device_tail(target, 0, devp);
+}
 #endif
 
 /*
diff --git a/include/dm/uclass.h b/include/dm/uclass.h
index 
c279304092352200d5297ad2d17f527173ec506b..8fdd72725119aae6ad2b62f4b0c38866a910389c
 100644
--- a/include/dm/uclass.h
+++ b/include/dm/uclass.h
@@ -333,6 +333,30 @@ int uclass_get_device_by_phandle(enum uclass_id id, struct 
udevice *parent,
 int uclass_get_device_by_driver(enum uclass_id id, const struct driver *drv,
                                struct udevice **devp);
 
+/**
+ * uclass_get_device_by_endpoint() - Get a uclass device for a remote endpoint
+ *
+ * This searches through the parents of the specified remote endpoint
+ * for the first device matching the uclass. Said otherwise, this helper
+ * goes through the graph (endpoint) representation and searches for
+ * matching devices. Endpoints can be subnodes of the "port" node or
+ * subnodes of ports identified with a reg property, themselves in a
+ * "ports" container.
+ *
+ * The device is probed to activate it ready for use.
+ *
+ * @class_id: uclass ID to look up
+ * @dev: Device to start from
+ * @port_idx: Index of the port to follow, -1 if there is a single 'port'
+ *            node without reg.
+ * @ep_idx: Index of the endpoint to follow, -1 if there is a single 'endpoint'
+ *          node without reg.
+ * @target: Returns pointer to the first device matching the expected uclass.
+ * Return: 0 if OK, -ve on error
+ */
+int uclass_get_device_by_endpoint(enum uclass_id class_id, struct udevice *dev,
+                                 int port_idx, int ep_idx, struct udevice 
**target);
+
 /**
  * uclass_first_device() - Get the first device in a uclass
  *

-- 
2.48.1

Reply via email to