* [PATCH 1/5] of: fix of_get_next_child() for prev->parent != node
2024-09-25 14:01 [PATCH 0/5] of-graph fixes Sascha Hauer
@ 2024-09-25 14:01 ` Sascha Hauer
2024-09-25 14:01 ` [PATCH 2/5] of: fix of_graph_get_next_endpoint() Sascha Hauer
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Sascha Hauer @ 2024-09-25 14:01 UTC (permalink / raw)
To: open list:BAREBOX
of_get_next_child() is supposed to return the next sibling of 'prev' and
the function does exactly that. It expects that 'node' is always the
same parent node. of_graph_get_next_endpoint() breaks this expectation,
it walks further down the tree and then calls of_get_next_child() with
'node' being some subnode of the original node. Fix this by retrieving
'node' always from 'prev' and use 'node' only on initial entry when
'prev' is NULL.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/of/base.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 62d84786ae..6fd69e7d7d 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -2054,6 +2054,9 @@ EXPORT_SYMBOL(of_get_next_available_child);
struct device_node *of_get_next_child(const struct device_node *node,
struct device_node *prev)
{
+ if (prev)
+ node = prev->parent;
+
prev = list_prepare_entry(prev, &node->children, parent_list);
list_for_each_entry_continue(prev, &node->children, parent_list)
return prev;
--
2.39.5
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 2/5] of: fix of_graph_get_next_endpoint()
2024-09-25 14:01 [PATCH 0/5] of-graph fixes Sascha Hauer
2024-09-25 14:01 ` [PATCH 1/5] of: fix of_get_next_child() for prev->parent != node Sascha Hauer
@ 2024-09-25 14:01 ` Sascha Hauer
2024-09-25 14:01 ` [PATCH 3/5] of: of_graph: honour ports subnode Sascha Hauer
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Sascha Hauer @ 2024-09-25 14:01 UTC (permalink / raw)
To: open list:BAREBOX
of_get_child_by_name() behaves differently than the corresponding Linux
function. The barebox version matches the full name of the node whereas
the Linux version skips the part after the '@' in the node.
of_graph_get_next_endpoint() explicitly needs the Linux behaviour.
As of_get_child_by_name() is heavily used in barebox and some call sites
might depend on the different behaviour, do not alter
of_get_child_by_name(), but instead introduce a new function that has
the Linux behaviour and use that in of_graph_get_next_endpoint().
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/of/base.c | 26 ++++++++++++++++++++++++--
include/of.h | 8 ++++++++
2 files changed, 32 insertions(+), 2 deletions(-)
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 6fd69e7d7d..fbbc3316fc 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -2139,7 +2139,7 @@ EXPORT_SYMBOL(of_get_compatible_child);
* @node: parent node
* @name: child name to look for.
*
- * This function looks for child node for given matching name
+ * This function looks for child node for given matching full name
*
* Returns a node pointer if found or NULL.
*/
@@ -2156,6 +2156,28 @@ struct device_node *of_get_child_by_name(const struct device_node *node,
}
EXPORT_SYMBOL(of_get_child_by_name);
+/**
+ * of_get_child_by_name_stem - Find the child node by name for a given parent
+ * @node: parent node
+ * @name: child name to look for.
+ *
+ * This function looks for child node for given matching name excluding the
+ * unit address
+ *
+ * Returns a node pointer if found or NULL.
+ */
+struct device_node *of_get_child_by_name_stem(const struct device_node *node,
+ const char *name)
+{
+ struct device_node *child;
+
+ for_each_child_of_node(node, child)
+ if (of_node_name_eq(child, name))
+ break;
+ return child;
+}
+EXPORT_SYMBOL(of_get_child_by_name_stem);
+
/**
* of_property_read_string_helper() - Utility helper for parsing string properties
* @np: device node from which the property value is to be read.
@@ -3296,7 +3318,7 @@ struct device_node *of_graph_get_next_endpoint(const struct device_node *parent,
if (node)
parent = node;
- port = of_get_child_by_name(parent, "port");
+ port = of_get_child_by_name_stem(parent, "port");
if (!port) {
pr_err("%s(): no port node found in %pOF\n",
__func__, parent);
diff --git a/include/of.h b/include/of.h
index 55f2c0cbde..05e92d41b9 100644
--- a/include/of.h
+++ b/include/of.h
@@ -218,6 +218,8 @@ extern struct device_node *of_get_compatible_child(const struct device_node *par
const char *compatible);
extern struct device_node *of_get_child_by_name(const struct device_node *node,
const char *name);
+extern struct device_node *of_get_child_by_name_stem(const struct device_node *node,
+ const char *name);
extern char *of_get_reproducible_name(struct device_node *node);
extern struct device_node *of_get_node_by_reproducible_name(struct device_node *dstroot,
struct device_node *srcnp);
@@ -560,6 +562,12 @@ static inline struct device_node *of_get_child_by_name(
return NULL;
}
+static inline struct device_node *of_get_child_by_name_stem(
+ const struct device_node *node, const char *name)
+{
+ return NULL;
+}
+
static inline char *of_get_reproducible_name(struct device_node *node)
{
return NULL;
--
2.39.5
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 3/5] of: of_graph: honour ports subnode
2024-09-25 14:01 [PATCH 0/5] of-graph fixes Sascha Hauer
2024-09-25 14:01 ` [PATCH 1/5] of: fix of_get_next_child() for prev->parent != node Sascha Hauer
2024-09-25 14:01 ` [PATCH 2/5] of: fix of_graph_get_next_endpoint() Sascha Hauer
@ 2024-09-25 14:01 ` Sascha Hauer
2024-09-25 14:01 ` [PATCH 4/5] of: of_graph: fix of_graph_get_next_endpoint() Sascha Hauer
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Sascha Hauer @ 2024-09-25 14:01 UTC (permalink / raw)
To: open list:BAREBOX
The of_graph ports of a node nowadays are usually collected under a
'ports' subnode instead of being directly under the devices node.
Handle this case correctly.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/of/base.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/of/base.c b/drivers/of/base.c
index fbbc3316fc..398e39340f 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -3271,11 +3271,14 @@ EXPORT_SYMBOL(of_graph_parse_endpoint);
*
* Return: A 'port' node pointer with refcount incremented.
*/
-struct device_node *of_graph_get_port_by_id(struct device_node *node, u32 id)
+struct device_node *of_graph_get_port_by_id(struct device_node *parent, u32 id)
{
- struct device_node *port;
+ struct device_node *port, *node = of_get_child_by_name(parent, "ports");
+
+ if (node)
+ parent = node;
- for_each_child_of_node(node, port) {
+ for_each_child_of_node(parent, port) {
u32 port_id = 0;
if (strncmp(port->name, "port", 4) != 0)
--
2.39.5
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 4/5] of: of_graph: fix of_graph_get_next_endpoint()
2024-09-25 14:01 [PATCH 0/5] of-graph fixes Sascha Hauer
` (2 preceding siblings ...)
2024-09-25 14:01 ` [PATCH 3/5] of: of_graph: honour ports subnode Sascha Hauer
@ 2024-09-25 14:01 ` Sascha Hauer
2024-09-25 14:01 ` [PATCH 5/5] of: of_graph: add missing functions Sascha Hauer
2024-09-27 10:39 ` [PATCH 0/5] of-graph fixes Sascha Hauer
5 siblings, 0 replies; 7+ messages in thread
From: Sascha Hauer @ 2024-09-25 14:01 UTC (permalink / raw)
To: open list:BAREBOX
of_node_cmp() compares the whole node name for matching whereas
of_node_name_eq() only compares the part before the '@' sign. For
of_graph_get_next_endpoint() we need the latter. Fix this.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/of/base.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 398e39340f..5981650f2a 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -3353,7 +3353,7 @@ struct device_node *of_graph_get_next_endpoint(const struct device_node *parent,
port = of_get_next_child(parent, port);
if (!port)
return NULL;
- } while (of_node_cmp(port->name, "port"));
+ } while (port->name && !of_node_name_eq(port, "port"));
}
}
EXPORT_SYMBOL(of_graph_get_next_endpoint);
--
2.39.5
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 5/5] of: of_graph: add missing functions
2024-09-25 14:01 [PATCH 0/5] of-graph fixes Sascha Hauer
` (3 preceding siblings ...)
2024-09-25 14:01 ` [PATCH 4/5] of: of_graph: fix of_graph_get_next_endpoint() Sascha Hauer
@ 2024-09-25 14:01 ` Sascha Hauer
2024-09-27 10:39 ` [PATCH 0/5] of-graph fixes Sascha Hauer
5 siblings, 0 replies; 7+ messages in thread
From: Sascha Hauer @ 2024-09-25 14:01 UTC (permalink / raw)
To: open list:BAREBOX
This adds of_graph_get_endpoint_by_regs() and of_graph_get_remote_node()
as-is from Linux.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/of/base.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
include/of_graph.h | 4 ++++
2 files changed, 68 insertions(+)
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 5981650f2a..960a9327ae 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -3358,6 +3358,32 @@ struct device_node *of_graph_get_next_endpoint(const struct device_node *parent,
}
EXPORT_SYMBOL(of_graph_get_next_endpoint);
+/**
+ * of_graph_get_endpoint_by_regs() - get endpoint node of specific identifiers
+ * @parent: pointer to the parent device node
+ * @port_reg: identifier (value of reg property) of the parent port node
+ * @reg: identifier (value of reg property) of the endpoint node
+ *
+ * Return: An 'endpoint' node pointer which is identified by reg and at the same
+ * is the child of a port node identified by port_reg. reg and port_reg are
+ * ignored when they are -1. Use of_node_put() on the pointer when done.
+ */
+struct device_node *of_graph_get_endpoint_by_regs(
+ const struct device_node *parent, int port_reg, int reg)
+{
+ struct of_endpoint endpoint;
+ struct device_node *node = NULL;
+
+ for_each_endpoint_of_node(parent, node) {
+ of_graph_parse_endpoint(node, &endpoint);
+ if (((port_reg == -1) || (endpoint.port == port_reg)) &&
+ ((reg == -1) || (endpoint.id == reg)))
+ return node;
+ }
+ return NULL;
+}
+EXPORT_SYMBOL(of_graph_get_endpoint_by_regs);
+
/**
* of_graph_get_remote_port_parent() - get remote port's parent node
* @node: pointer to a local endpoint device_node
@@ -3403,6 +3429,44 @@ struct device_node *of_graph_get_remote_port(const struct device_node *node)
}
EXPORT_SYMBOL(of_graph_get_remote_port);
+/**
+ * of_graph_get_remote_node() - get remote parent device_node for given port/endpoint
+ * @node: pointer to parent device_node containing graph port/endpoint
+ * @port: identifier (value of reg property) of the parent port node
+ * @endpoint: identifier (value of reg property) of the endpoint node
+ *
+ * Return: Remote device node associated with remote endpoint node linked
+ * to @node. Use of_node_put() on it when done.
+ */
+struct device_node *of_graph_get_remote_node(const struct device_node *node,
+ u32 port, u32 endpoint)
+{
+ struct device_node *endpoint_node, *remote;
+
+ endpoint_node = of_graph_get_endpoint_by_regs(node, port, endpoint);
+ if (!endpoint_node) {
+ pr_debug("no valid endpoint (%d, %d) for node %pOF\n",
+ port, endpoint, node);
+ return NULL;
+ }
+
+ remote = of_graph_get_remote_port_parent(endpoint_node);
+ of_node_put(endpoint_node);
+ if (!remote) {
+ pr_debug("no valid remote node\n");
+ return NULL;
+ }
+
+ if (!of_device_is_available(remote)) {
+ pr_debug("not available for remote node\n");
+ of_node_put(remote);
+ return NULL;
+ }
+
+ return remote;
+}
+EXPORT_SYMBOL(of_graph_get_remote_node);
+
int of_graph_port_is_available(struct device_node *node)
{
struct device_node *endpoint;
diff --git a/include/of_graph.h b/include/of_graph.h
index ef3fb8b94a..bd25643e25 100644
--- a/include/of_graph.h
+++ b/include/of_graph.h
@@ -43,5 +43,9 @@ struct device_node *of_graph_get_remote_port_parent(
const struct device_node *node);
struct device_node *of_graph_get_remote_port(const struct device_node *node);
int of_graph_port_is_available(struct device_node *node);
+struct device_node *of_graph_get_remote_node(const struct device_node *node,
+ u32 port, u32 endpoint);
+struct device_node *of_graph_get_endpoint_by_regs(
+ const struct device_node *parent, int port_reg, int reg);
#endif /* __LINUX_OF_GRAPH_H */
--
2.39.5
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 0/5] of-graph fixes
2024-09-25 14:01 [PATCH 0/5] of-graph fixes Sascha Hauer
` (4 preceding siblings ...)
2024-09-25 14:01 ` [PATCH 5/5] of: of_graph: add missing functions Sascha Hauer
@ 2024-09-27 10:39 ` Sascha Hauer
5 siblings, 0 replies; 7+ messages in thread
From: Sascha Hauer @ 2024-09-27 10:39 UTC (permalink / raw)
To: open list:BAREBOX, Sascha Hauer
On Wed, 25 Sep 2024 16:01:10 +0200, Sascha Hauer wrote:
> Upcoming Rockchip VOP2 support makes use of of-graph which uncovered
> some bugs in the existing code. This series contains fixes for it and
> adds some missing functions.
>
>
Applied, thanks!
[1/5] of: fix of_get_next_child() for prev->parent != node
https://git.pengutronix.de/cgit/barebox/commit/?id=c07ce9b0678c (link may not be stable)
[2/5] of: fix of_graph_get_next_endpoint()
https://git.pengutronix.de/cgit/barebox/commit/?id=c8c506a779dd (link may not be stable)
[3/5] of: of_graph: honour ports subnode
https://git.pengutronix.de/cgit/barebox/commit/?id=2a5d0ab7dc64 (link may not be stable)
[4/5] of: of_graph: fix of_graph_get_next_endpoint()
https://git.pengutronix.de/cgit/barebox/commit/?id=09fb886aa387 (link may not be stable)
[5/5] of: of_graph: add missing functions
https://git.pengutronix.de/cgit/barebox/commit/?id=52dd0d4c8a75 (link may not be stable)
Best regards,
--
Sascha Hauer <s.hauer@pengutronix.de>
^ permalink raw reply [flat|nested] 7+ messages in thread