ср, 26 бер. 2025 р. о 17:01 Miquel Raynal <miquel.ray...@bootlin.com> пише: > > 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);
You may use dev_ofnode(dev) directly instead of node_source if you wish, but that is up to you. > + struct udevice *target = NULL; > + int ret; > + > + if (!ofnode_valid(node_dest)) > + return -EINVAL; > + > + ret = uclass_find_device_by_ofnode(class_id, node_dest, &target); You can use uclass_get_device_by_ofnode here and avoid using uclass_get_device_tail later. > + 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 >