diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/of/base.c | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/drivers/of/base.c b/drivers/of/base.c index 6b6dfcc5652..9377f3bc410 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -20,6 +20,8 @@ #include <linux/of.h> #include <linux/spinlock.h> +struct device_node *allnodes; + /* use when traversing tree through the allnext, child, sibling, * or parent members of struct device_node. */ @@ -158,3 +160,116 @@ struct device_node *of_get_next_child(const struct device_node *node, return next; } EXPORT_SYMBOL(of_get_next_child); + +/** + * of_find_node_by_path - Find a node matching a full OF path + * @path: The full path to match + * + * Returns a node pointer with refcount incremented, use + * of_node_put() on it when done. + */ +struct device_node *of_find_node_by_path(const char *path) +{ + struct device_node *np = allnodes; + + read_lock(&devtree_lock); + for (; np; np = np->allnext) { + if (np->full_name && (of_node_cmp(np->full_name, path) == 0) + && of_node_get(np)) + break; + } + read_unlock(&devtree_lock); + return np; +} +EXPORT_SYMBOL(of_find_node_by_path); + +/** + * of_find_node_by_name - Find a node by its "name" property + * @from: The node to start searching from or NULL, the node + * you pass will not be searched, only the next one + * will; typically, you pass what the previous call + * returned. of_node_put() will be called on it + * @name: The name string to match against + * + * Returns a node pointer with refcount incremented, use + * of_node_put() on it when done. + */ +struct device_node *of_find_node_by_name(struct device_node *from, + const char *name) +{ + struct device_node *np; + + read_lock(&devtree_lock); + np = from ? from->allnext : allnodes; + for (; np; np = np->allnext) + if (np->name && (of_node_cmp(np->name, name) == 0) + && of_node_get(np)) + break; + of_node_put(from); + read_unlock(&devtree_lock); + return np; +} +EXPORT_SYMBOL(of_find_node_by_name); + +/** + * of_find_node_by_type - Find a node by its "device_type" property + * @from: The node to start searching from, or NULL to start searching + * the entire device tree. The node you pass will not be + * searched, only the next one will; typically, you pass + * what the previous call returned. of_node_put() will be + * called on from for you. + * @type: The type string to match against + * + * Returns a node pointer with refcount incremented, use + * of_node_put() on it when done. + */ +struct device_node *of_find_node_by_type(struct device_node *from, + const char *type) +{ + struct device_node *np; + + read_lock(&devtree_lock); + np = from ? from->allnext : allnodes; + for (; np; np = np->allnext) + if (np->type && (of_node_cmp(np->type, type) == 0) + && of_node_get(np)) + break; + of_node_put(from); + read_unlock(&devtree_lock); + return np; +} +EXPORT_SYMBOL(of_find_node_by_type); + +/** + * of_find_compatible_node - Find a node based on type and one of the + * tokens in its "compatible" property + * @from: The node to start searching from or NULL, the node + * you pass will not be searched, only the next one + * will; typically, you pass what the previous call + * returned. of_node_put() will be called on it + * @type: The type string to match "device_type" or NULL to ignore + * @compatible: The string to match to one of the tokens in the device + * "compatible" list. + * + * Returns a node pointer with refcount incremented, use + * of_node_put() on it when done. + */ +struct device_node *of_find_compatible_node(struct device_node *from, + const char *type, const char *compatible) +{ + struct device_node *np; + + read_lock(&devtree_lock); + np = from ? from->allnext : allnodes; + for (; np; np = np->allnext) { + if (type + && !(np->type && (of_node_cmp(np->type, type) == 0))) + continue; + if (of_device_is_compatible(np, compatible) && of_node_get(np)) + break; + } + of_node_put(from); + read_unlock(&devtree_lock); + return np; +} +EXPORT_SYMBOL(of_find_compatible_node); |