diff options
author | Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | 2024-10-24 04:20:06 +0200 |
---|---|---|
committer | Rob Herring (Arm) <robh@kernel.org> | 2024-10-24 23:35:48 +0200 |
commit | 58fe47d6ac7413172e1fa88324fb1b4c0eb2c0a2 (patch) | |
tree | a156377ee92748b0d71162fef42d5af4b4cf011f /drivers/of | |
parent | of: property: add of_graph_get_next_port() (diff) | |
download | linux-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.c | 27 |
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 |