From fd9fdb78a9bf85b94fb2190c82ff280c8f8375cc Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Mon, 10 Feb 2014 22:01:48 +0100 Subject: [media] of: move graph helpers from drivers/media/v4l2-core to drivers/of This patch moves the parsing helpers used to parse connected graphs in the device tree, like the video interface bindings documented in Documentation/devicetree/bindings/media/video-interfaces.txt, from drivers/media/v4l2-core/v4l2-of.c into drivers/of/base.c. This allows to reuse the same parser code from outside the V4L2 framework, most importantly from display drivers. The functions v4l2_of_get_next_endpoint, v4l2_of_get_remote_port, and v4l2_of_get_remote_port_parent are moved. They are renamed to of_graph_get_next_endpoint, of_graph_get_remote_port, and of_graph_get_remote_port_parent, respectively. Since there are not that many current users yet, switch all of them to the new functions right away. Signed-off-by: Philipp Zabel Acked-by: Tomi Valkeinen Acked-by: Mauro Carvalho Chehab Acked-by: Sylwester Nawrocki --- drivers/of/base.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) (limited to 'drivers/of/base.c') diff --git a/drivers/of/base.c b/drivers/of/base.c index 89e888a78899..b2f223fa47e9 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -1982,3 +1983,120 @@ struct device_node *of_find_next_cache_node(const struct device_node *np) return NULL; } + +/** + * 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 + * + * Return: An 'endpoint' node pointer with refcount incremented. Refcount + * of the passed @prev node is not decremented, the caller have to use + * of_node_put() on it when done. + */ +struct device_node *of_graph_get_next_endpoint(const struct device_node *parent, + struct device_node *prev) +{ + struct device_node *endpoint; + struct device_node *port = NULL; + + if (!parent) + return NULL; + + if (!prev) { + struct device_node *node; + /* + * It's the first call, we have to find a port subnode + * within this node or within an optional 'ports' node. + */ + node = of_get_child_by_name(parent, "ports"); + if (node) + parent = node; + + port = of_get_child_by_name(parent, "port"); + + if (port) { + /* Found a port, get an endpoint. */ + endpoint = of_get_next_child(port, NULL); + of_node_put(port); + } else { + endpoint = NULL; + } + + if (!endpoint) + pr_err("%s(): no endpoint nodes specified for %s\n", + __func__, parent->full_name); + of_node_put(node); + } else { + port = of_get_parent(prev); + if (!port) + /* Hm, has someone given us the root node ?... */ + return NULL; + + /* Avoid dropping prev node refcount to 0. */ + of_node_get(prev); + endpoint = of_get_next_child(port, prev); + if (endpoint) { + of_node_put(port); + return endpoint; + } + + /* No more endpoints under this port, try the next one. */ + do { + port = of_get_next_child(parent, port); + if (!port) + return NULL; + } while (of_node_cmp(port->name, "port")); + + /* Pick up the first endpoint in this port. */ + endpoint = of_get_next_child(port, NULL); + of_node_put(port); + } + + return endpoint; +} +EXPORT_SYMBOL(of_graph_get_next_endpoint); + +/** + * of_graph_get_remote_port_parent() - get remote port's parent node + * @node: pointer to a local endpoint device_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_port_parent( + const struct device_node *node) +{ + struct device_node *np; + unsigned int depth; + + /* Get remote endpoint node. */ + np = of_parse_phandle(node, "remote-endpoint", 0); + + /* Walk 3 levels up only if there is 'ports' node. */ + for (depth = 3; depth && np; depth--) { + np = of_get_next_parent(np); + if (depth == 2 && of_node_cmp(np->name, "ports")) + break; + } + return np; +} +EXPORT_SYMBOL(of_graph_get_remote_port_parent); + +/** + * of_graph_get_remote_port() - get remote port node + * @node: pointer to a local endpoint device_node + * + * Return: Remote port node associated with remote endpoint node linked + * to @node. Use of_node_put() on it when done. + */ +struct device_node *of_graph_get_remote_port(const struct device_node *node) +{ + struct device_node *np; + + /* Get remote endpoint node. */ + np = of_parse_phandle(node, "remote-endpoint", 0); + if (!np) + return NULL; + return of_get_next_parent(np); +} +EXPORT_SYMBOL(of_graph_get_remote_port); -- cgit v1.2.3 From 6ff60d397b172bd89955433bd9e74be4627d7b9e Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Wed, 26 Feb 2014 20:41:09 +0100 Subject: of: Warn if of_graph_get_next_endpoint is called with the root node If of_graph_get_next_endpoint is given a parentless node instead of an endpoint node, it is clearly a bug. Signed-off-by: Philipp Zabel Acked-by: Tomi Valkeinen Acked-by: Mauro Carvalho Chehab Acked-by: Sylwester Nawrocki --- drivers/of/base.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/of/base.c') diff --git a/drivers/of/base.c b/drivers/of/base.c index b2f223fa47e9..b5e690bd6e9c 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -2028,8 +2028,8 @@ struct device_node *of_graph_get_next_endpoint(const struct device_node *parent, of_node_put(node); } else { port = of_get_parent(prev); - if (!port) - /* Hm, has someone given us the root node ?... */ + if (WARN_ONCE(!port, "%s(): endpoint %s has no parent node\n", + __func__, prev->full_name)) return NULL; /* Avoid dropping prev node refcount to 0. */ -- cgit v1.2.3 From 4329b93b283cce828967c01bc3827fdff51c8d7e Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Wed, 26 Feb 2014 20:43:42 +0100 Subject: of: Reduce indentation in of_graph_get_next_endpoint A 'return endpoint;' at the end of the (!prev) case allows to reduce the indentation level of the (prev) case. Signed-off-by: Philipp Zabel Acked-by: Tomi Valkeinen Acked-by: Mauro Carvalho Chehab Acked-by: Sylwester Nawrocki --- drivers/of/base.c | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) (limited to 'drivers/of/base.c') diff --git a/drivers/of/base.c b/drivers/of/base.c index b5e690bd6e9c..a8e47d37cc7f 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -2026,32 +2026,34 @@ struct device_node *of_graph_get_next_endpoint(const struct device_node *parent, pr_err("%s(): no endpoint nodes specified for %s\n", __func__, parent->full_name); of_node_put(node); - } else { - port = of_get_parent(prev); - if (WARN_ONCE(!port, "%s(): endpoint %s has no parent node\n", - __func__, prev->full_name)) - return NULL; - /* Avoid dropping prev node refcount to 0. */ - of_node_get(prev); - endpoint = of_get_next_child(port, prev); - if (endpoint) { - of_node_put(port); - return endpoint; - } + return endpoint; + } - /* No more endpoints under this port, try the next one. */ - do { - port = of_get_next_child(parent, port); - if (!port) - return NULL; - } while (of_node_cmp(port->name, "port")); + port = of_get_parent(prev); + if (WARN_ONCE(!port, "%s(): endpoint %s has no parent node\n", + __func__, prev->full_name)) + return NULL; - /* Pick up the first endpoint in this port. */ - endpoint = of_get_next_child(port, NULL); + /* Avoid dropping prev node refcount to 0. */ + of_node_get(prev); + endpoint = of_get_next_child(port, prev); + if (endpoint) { of_node_put(port); + return endpoint; } + /* No more endpoints under this port, try the next one. */ + do { + port = of_get_next_child(parent, port); + if (!port) + return NULL; + } while (of_node_cmp(port->name, "port")); + + /* Pick up the first endpoint in this port. */ + endpoint = of_get_next_child(port, NULL); + of_node_put(port); + return endpoint; } EXPORT_SYMBOL(of_graph_get_next_endpoint); -- cgit v1.2.3 From f2a575f67695dcba9062acd666ae5aab2380b95c Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Fri, 14 Feb 2014 11:53:56 +0100 Subject: [media] of: move common endpoint parsing to drivers/of This patch adds a new struct of_endpoint which is then embedded in struct v4l2_of_endpoint and contains the endpoint properties that are not V4L2 (or even media) specific: the port number, endpoint id, local device tree node and remote endpoint phandle. of_graph_parse_endpoint parses those properties and is used by v4l2_of_parse_endpoint, which just adds the V4L2 MBUS information to the containing v4l2_of_endpoint structure. Signed-off-by: Philipp Zabel Acked-by: Tomi Valkeinen Acked-by: Mauro Carvalho Chehab Acked-by: Sylwester Nawrocki --- drivers/of/base.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'drivers/of/base.c') diff --git a/drivers/of/base.c b/drivers/of/base.c index a8e47d37cc7f..715144af3a83 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1984,6 +1984,34 @@ struct device_node *of_find_next_cache_node(const struct device_node *np) return NULL; } +/** + * of_graph_parse_endpoint() - parse common endpoint node properties + * @node: pointer to endpoint device_node + * @endpoint: pointer to the OF endpoint data structure + * + * The caller should hold a reference to @node. + */ +int of_graph_parse_endpoint(const struct device_node *node, + struct of_endpoint *endpoint) +{ + struct device_node *port_node = of_get_parent(node); + + memset(endpoint, 0, sizeof(*endpoint)); + + endpoint->local_node = node; + /* + * It doesn't matter whether the two calls below succeed. + * If they don't then the default value 0 is used. + */ + of_property_read_u32(port_node, "reg", &endpoint->port); + of_property_read_u32(node, "reg", &endpoint->id); + + of_node_put(port_node); + + return 0; +} +EXPORT_SYMBOL(of_graph_parse_endpoint); + /** * of_graph_get_next_endpoint() - get next endpoint node * @parent: pointer to the parent device node -- cgit v1.2.3 From d484700a36952c6675aa47dec4d7a536929aa922 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Tue, 4 Mar 2014 12:31:24 +0100 Subject: of: Warn if of_graph_parse_endpoint is called with the root node If of_graph_parse_endpoint is given a parentless node instead of an endpoint node, it is clearly a bug. Signed-off-by: Philipp Zabel Acked-by: Tomi Valkeinen Acked-by: Mauro Carvalho Chehab Acked-by: Sylwester Nawrocki --- drivers/of/base.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/of/base.c') diff --git a/drivers/of/base.c b/drivers/of/base.c index 715144af3a83..fd4b9c2eaa15 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1996,6 +1996,9 @@ int of_graph_parse_endpoint(const struct device_node *node, { struct device_node *port_node = of_get_parent(node); + WARN_ONCE(!port_node, "%s(): endpoint %s has no parent node\n", + __func__, node->full_name); + memset(endpoint, 0, sizeof(*endpoint)); endpoint->local_node = node; -- cgit v1.2.3