diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-01 19:45:00 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-01 19:45:00 -0400 |
commit | c12e69c6aaf785fd307d05cb6f36ca0e7577ead7 (patch) | |
tree | d12feba57d1f42f8a2a1a382d3bea29603312d14 /drivers/of/base.c | |
parent | 158e0d3621683ee0cdfeeba56f0e5ddd97ae984f (diff) | |
parent | 94debda32429e1a348fec8543245f1190a92d68c (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.c | 151 |
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 | */ | ||
2026 | int 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 | } | ||
2048 | EXPORT_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 | */ | ||
2059 | struct 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 | } | ||
2122 | EXPORT_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 | */ | ||
2131 | struct 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 | } | ||
2148 | EXPORT_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 | */ | ||
2157 | struct 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 | } | ||
2167 | EXPORT_SYMBOL(of_graph_get_remote_port); | ||