summaryrefslogtreecommitdiffstats
path: root/drivers/of/base.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-04-01 19:45:00 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-04-01 19:45:00 -0400
commitc12e69c6aaf785fd307d05cb6f36ca0e7577ead7 (patch)
treed12feba57d1f42f8a2a1a382d3bea29603312d14 /drivers/of/base.c
parent158e0d3621683ee0cdfeeba56f0e5ddd97ae984f (diff)
parent94debda32429e1a348fec8543245f1190a92d68c (diff)
Merge tag 'staging-3.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging
Pull staging driver updates from Greg KH: "Here's the huge drivers/staging/ update for 3.15-rc1. Loads of cleanup fixes, a few drivers removed, and some new ones added. All have been in linux-next for a while" * tag 'staging-3.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (1375 commits) staging: xillybus: XILLYBUS_PCIE depends on PCI_MSI staging: xillybus: Added "select CRC32" for XILLYBUS in Kconfig staging: comedi: poc: remove obsolete driver staging: unisys: replace kzalloc/kfree with UISMALLOC/UISFREE staging: octeon-usb: prevent memory corruption staging: usbip: fix line over 80 characters staging: usbip: fix quoted string split across lines Staging: unisys: Remove RETINT macro Staging: unisys: Remove FAIL macro Staging: unisys: Remove RETVOID macro Staging: unisys: Remove RETPTR macro Staging: unisys: Remove RETBOOL macro Staging: unisys: Remove FAIL_WPOSTCODE_1 macro Staging: unisys: Cleanup macros to get rid of goto statements Staging: unisys: include: Remove unused macros from timskmod.h staging: dgap: fix the rest of the checkpatch warnings in dgap.c Staging: bcm: Remove unnecessary parentheses staging: wlags49_h2: Delete unnecessary braces staging: wlags49_h2: Do not use assignment in if condition staging: wlags49_h2: Enclose macro in a do-while loop ...
Diffstat (limited to 'drivers/of/base.c')
-rw-r--r--drivers/of/base.c151
1 files changed, 151 insertions, 0 deletions
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 1b95a405628f..5f81bfea5246 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -21,6 +21,7 @@
21#include <linux/cpu.h> 21#include <linux/cpu.h>
22#include <linux/module.h> 22#include <linux/module.h>
23#include <linux/of.h> 23#include <linux/of.h>
24#include <linux/of_graph.h>
24#include <linux/spinlock.h> 25#include <linux/spinlock.h>
25#include <linux/slab.h> 26#include <linux/slab.h>
26#include <linux/proc_fs.h> 27#include <linux/proc_fs.h>
@@ -2014,3 +2015,153 @@ struct device_node *of_find_next_cache_node(const struct device_node *np)
2014 2015
2015 return NULL; 2016 return NULL;
2016} 2017}
2018
2019/**
2020 * of_graph_parse_endpoint() - parse common endpoint node properties
2021 * @node: pointer to endpoint device_node
2022 * @endpoint: pointer to the OF endpoint data structure
2023 *
2024 * The caller should hold a reference to @node.
2025 */
2026int of_graph_parse_endpoint(const struct device_node *node,
2027 struct of_endpoint *endpoint)
2028{
2029 struct device_node *port_node = of_get_parent(node);
2030
2031 WARN_ONCE(!port_node, "%s(): endpoint %s has no parent node\n",
2032 __func__, node->full_name);
2033
2034 memset(endpoint, 0, sizeof(*endpoint));
2035
2036 endpoint->local_node = node;
2037 /*
2038 * It doesn't matter whether the two calls below succeed.
2039 * If they don't then the default value 0 is used.
2040 */
2041 of_property_read_u32(port_node, "reg", &endpoint->port);
2042 of_property_read_u32(node, "reg", &endpoint->id);
2043
2044 of_node_put(port_node);
2045
2046 return 0;
2047}
2048EXPORT_SYMBOL(of_graph_parse_endpoint);
2049
2050/**
2051 * of_graph_get_next_endpoint() - get next endpoint node
2052 * @parent: pointer to the parent device node
2053 * @prev: previous endpoint node, or NULL to get first
2054 *
2055 * Return: An 'endpoint' node pointer with refcount incremented. Refcount
2056 * of the passed @prev node is not decremented, the caller have to use
2057 * of_node_put() on it when done.
2058 */
2059struct device_node *of_graph_get_next_endpoint(const struct device_node *parent,
2060 struct device_node *prev)
2061{
2062 struct device_node *endpoint;
2063 struct device_node *port = NULL;
2064
2065 if (!parent)
2066 return NULL;
2067
2068 if (!prev) {
2069 struct device_node *node;
2070 /*
2071 * It's the first call, we have to find a port subnode
2072 * within this node or within an optional 'ports' node.
2073 */
2074 node = of_get_child_by_name(parent, "ports");
2075 if (node)
2076 parent = node;
2077
2078 port = of_get_child_by_name(parent, "port");
2079
2080 if (port) {
2081 /* Found a port, get an endpoint. */
2082 endpoint = of_get_next_child(port, NULL);
2083 of_node_put(port);
2084 } else {
2085 endpoint = NULL;
2086 }
2087
2088 if (!endpoint)
2089 pr_err("%s(): no endpoint nodes specified for %s\n",
2090 __func__, parent->full_name);
2091 of_node_put(node);
2092
2093 return endpoint;
2094 }
2095
2096 port = of_get_parent(prev);
2097 if (WARN_ONCE(!port, "%s(): endpoint %s has no parent node\n",
2098 __func__, prev->full_name))
2099 return NULL;
2100
2101 /* Avoid dropping prev node refcount to 0. */
2102 of_node_get(prev);
2103 endpoint = of_get_next_child(port, prev);
2104 if (endpoint) {
2105 of_node_put(port);
2106 return endpoint;
2107 }
2108
2109 /* No more endpoints under this port, try the next one. */
2110 do {
2111 port = of_get_next_child(parent, port);
2112 if (!port)
2113 return NULL;
2114 } while (of_node_cmp(port->name, "port"));
2115
2116 /* Pick up the first endpoint in this port. */
2117 endpoint = of_get_next_child(port, NULL);
2118 of_node_put(port);
2119
2120 return endpoint;
2121}
2122EXPORT_SYMBOL(of_graph_get_next_endpoint);
2123
2124/**
2125 * of_graph_get_remote_port_parent() - get remote port's parent node
2126 * @node: pointer to a local endpoint device_node
2127 *
2128 * Return: Remote device node associated with remote endpoint node linked
2129 * to @node. Use of_node_put() on it when done.
2130 */
2131struct device_node *of_graph_get_remote_port_parent(
2132 const struct device_node *node)
2133{
2134 struct device_node *np;
2135 unsigned int depth;
2136
2137 /* Get remote endpoint node. */
2138 np = of_parse_phandle(node, "remote-endpoint", 0);
2139
2140 /* Walk 3 levels up only if there is 'ports' node. */
2141 for (depth = 3; depth && np; depth--) {
2142 np = of_get_next_parent(np);
2143 if (depth == 2 && of_node_cmp(np->name, "ports"))
2144 break;
2145 }
2146 return np;
2147}
2148EXPORT_SYMBOL(of_graph_get_remote_port_parent);
2149
2150/**
2151 * of_graph_get_remote_port() - get remote port node
2152 * @node: pointer to a local endpoint device_node
2153 *
2154 * Return: Remote port node associated with remote endpoint node linked
2155 * to @node. Use of_node_put() on it when done.
2156 */
2157struct device_node *of_graph_get_remote_port(const struct device_node *node)
2158{
2159 struct device_node *np;
2160
2161 /* Get remote endpoint node. */
2162 np = of_parse_phandle(node, "remote-endpoint", 0);
2163 if (!np)
2164 return NULL;
2165 return of_get_next_parent(np);
2166}
2167EXPORT_SYMBOL(of_graph_get_remote_port);