On Mon, Dec 6, 2021 at 11:49 PM Jagan Teki <jagan@xxxxxxxxxxxxxxxxxxxx> wrote: > > Add of_get_non_port_child() helper that can be used to lookup > non port child nodes. > > Some OF graphs don't require 'ports' to represent the next output > instead, it simply adds a child node on a given parent node. This > helper lookup that child node, however that child node is not a > 'port' on given parent as 'port' based nodes are looked up via > of_graph_get_remote_node(). > > Example OF graph representation of DSI host, which doesn't > have 'ports'. This seems pretty specific to DSI and also can't handle there being more than 1 non-port node. That's allowed for DSI too, but I don't think I've ever seen a case. Anyways, I'd just move this to DRM rather than common DT code. One comment on the implementation that will shrink it. > > dsi { > #address-cells = <1>; > #size-cells = <0>; > > port { > dsi_in_tcon0: endpoint { > remote-endpoint = <tcon0_out_dsi>; > }; > > panel@0 { > reg = <0>; > }; > }; > > Signed-off-by: Jagan Teki <jagan@xxxxxxxxxxxxxxxxxxxx> > --- > drivers/of/base.c | 29 +++++++++++++++++++++++++++++ > include/linux/of.h | 6 ++++++ > 2 files changed, 35 insertions(+) > > diff --git a/drivers/of/base.c b/drivers/of/base.c > index 61de453b885c..31bbf885b0f8 100644 > --- a/drivers/of/base.c > +++ b/drivers/of/base.c > @@ -854,6 +854,35 @@ struct device_node *of_get_compatible_child(const struct device_node *parent, > } > EXPORT_SYMBOL(of_get_compatible_child); > > +/** > + * of_get_non_port_child - Find the non port child node for a given parent > + * @node: parent node > + * > + * This function looks for child node which is not port child for given parent. > + * > + * Return: A node pointer if found, with refcount incremented, use > + * of_node_put() on it when done. > + * Returns NULL if node is not found. > + */ > +struct device_node *of_get_non_port_child(const struct device_node *parent) > +{ > + struct device_node *child; > + > + for_each_child_of_node(parent, child) { for_each_available_child_of_node > + if (of_node_name_eq(child, "port")) > + continue; > + > + if (!of_device_is_available(child)) { > + of_node_put(child); > + continue; > + } > + break; > + } > + > + return child; > +} > +EXPORT_SYMBOL(of_get_non_port_child); > + > /** > * of_get_child_by_name - Find the child node by name for a given parent > * @node: parent node > diff --git a/include/linux/of.h b/include/linux/of.h > index ff143a027abc..3e699becef82 100644 > --- a/include/linux/of.h > +++ b/include/linux/of.h > @@ -290,6 +290,7 @@ extern struct device_node *of_get_next_child(const struct device_node *node, > extern struct device_node *of_get_next_available_child( > const struct device_node *node, struct device_node *prev); > > +extern struct device_node *of_get_non_port_child(const struct device_node *parent); > extern struct device_node *of_get_compatible_child(const struct device_node *parent, > const char *compatible); > extern struct device_node *of_get_child_by_name(const struct device_node *node, > @@ -678,6 +679,11 @@ static inline bool of_have_populated_dt(void) > return false; > } > > +static inline struct device_node *of_get_non_port_child(const struct device_node *parent) > +{ > + return NULL; > +} > + > static inline struct device_node *of_get_compatible_child(const struct device_node *parent, > const char *compatible) > { > -- > 2.25.1 >