summaryrefslogtreecommitdiffstats
path: root/drivers/of
diff options
context:
space:
mode:
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>2024-10-24 04:20:06 +0200
committerRob Herring (Arm) <robh@kernel.org>2024-10-24 23:35:48 +0200
commit58fe47d6ac7413172e1fa88324fb1b4c0eb2c0a2 (patch)
treea156377ee92748b0d71162fef42d5af4b4cf011f /drivers/of
parentof: property: add of_graph_get_next_port() (diff)
downloadlinux-58fe47d6ac7413172e1fa88324fb1b4c0eb2c0a2.tar.xz
linux-58fe47d6ac7413172e1fa88324fb1b4c0eb2c0a2.zip
of: property: add of_graph_get_next_port_endpoint()
We already have of_graph_get_next_endpoint(), but it is not intuitive to use in some case. (X) node { (Y) ports { (P0) port@0 { endpoint { remote-endpoint = ...; };}; (P10) port@1 { endpoint { remote-endpoint = ...; }; (P11) endpoint { remote-endpoint = ...; };}; (P2) port@2 { endpoint { remote-endpoint = ...; };}; }; }; For example, if I want to handle port@1's 2 endpoints (= P10, P11), I want to use like below P10 = of_graph_get_next_endpoint(port1, NULL); P11 = of_graph_get_next_endpoint(port1, P10); But 1st one will be error, because of_graph_get_next_endpoint() requested 1st parameter is "node" (X) or "ports" (Y), not but "port". Below works well, but it will get P0 P0 = of_graph_get_next_endpoint(node, NULL); P0 = of_graph_get_next_endpoint(ports, NULL); In other words, we can't handle P10/P11 directly via of_graph_get_next_endpoint(). There is another non intuitive behavior on of_graph_get_next_endpoint(). In case of if I could get P10 pointer for some way, and if I want to handle port@1 things by loop, I would like use it like below /* * "ep" is now P10, and handle port1 things here, * but we don't know how many endpoints port1 have. * * Because "ep" is non NULL now, we can use port1 * as of_graph_get_next_endpoint(port1, xxx) */ do { /* do something for port1 specific things here */ } while (ep = of_graph_get_next_endpoint(port1, ep)) But it also not worked as I expected. I expect it will be P10 -> P11 -> NULL, but it will be P10 -> P11 -> P2, because of_graph_get_next_endpoint() will fetch "endpoint" beyond the "port". It is not useful for generic driver. To handle endpoint more intuitive, create of_graph_get_next_port_endpoint() of_graph_get_next_port_endpoint(port1, NULL); // P10 of_graph_get_next_port_endpoint(port1, P10); // P11 of_graph_get_next_port_endpoint(port1, P11); // NULL Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Link: https://lore.kernel.org/r/87jzdyb5t5.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Rob Herring (Arm) <robh@kernel.org>
Diffstat (limited to 'drivers/of')
-rw-r--r--drivers/of/property.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/drivers/of/property.c b/drivers/of/property.c
index 6dd5461ea359..ce0e08176fca 100644
--- a/drivers/of/property.c
+++ b/drivers/of/property.c
@@ -668,6 +668,33 @@ struct device_node *of_graph_get_next_port(const struct device_node *parent,
EXPORT_SYMBOL(of_graph_get_next_port);
/**
+ * of_graph_get_next_port_endpoint() - get next endpoint node in port.
+ * If it reached to end of the port, it will return NULL.
+ * @port: pointer to the target port node
+ * @prev: previous endpoint node, or NULL to get first
+ *
+ * Return: An 'endpoint' node pointer with refcount incremented. Refcount
+ * of the passed @prev node is decremented.
+ */
+struct device_node *of_graph_get_next_port_endpoint(const struct device_node *port,
+ struct device_node *prev)
+{
+ while (1) {
+ prev = of_get_next_child(port, prev);
+ if (!prev)
+ break;
+ if (WARN(!of_node_name_eq(prev, "endpoint"),
+ "non endpoint node is used (%pOF)", prev))
+ continue;
+
+ break;
+ }
+
+ return prev;
+}
+EXPORT_SYMBOL(of_graph_get_next_port_endpoint);
+
+/**
* of_graph_get_next_endpoint() - get next endpoint node
* @parent: pointer to the parent device node
* @prev: previous endpoint node, or NULL to get first