Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus
[cascardo/linux.git] / drivers / of / base.c
index 3823edf..36536b6 100644 (file)
 
 LIST_HEAD(aliases_lookup);
 
-struct device_node *of_allnodes;
-EXPORT_SYMBOL(of_allnodes);
+struct device_node *of_root;
+EXPORT_SYMBOL(of_root);
 struct device_node *of_chosen;
 struct device_node *of_aliases;
 struct device_node *of_stdout;
+static const char *of_stdout_options;
 
 struct kset *of_kset;
 
@@ -48,7 +49,7 @@ struct kset *of_kset;
  */
 DEFINE_MUTEX(of_mutex);
 
-/* use when traversing tree through the allnext, child, sibling,
+/* use when traversing tree through the child, sibling,
  * or parent members of struct device_node.
  */
 DEFINE_RAW_SPINLOCK(devtree_lock);
@@ -204,7 +205,7 @@ static int __init of_init(void)
        mutex_unlock(&of_mutex);
 
        /* Symlink in /proc as required by userspace ABI */
-       if (of_allnodes)
+       if (of_root)
                proc_symlink("device-tree", NULL, "/sys/firmware/devicetree/base");
 
        return 0;
@@ -245,6 +246,23 @@ struct property *of_find_property(const struct device_node *np,
 }
 EXPORT_SYMBOL(of_find_property);
 
+struct device_node *__of_find_all_nodes(struct device_node *prev)
+{
+       struct device_node *np;
+       if (!prev) {
+               np = of_root;
+       } else if (prev->child) {
+               np = prev->child;
+       } else {
+               /* Walk back up looking for a sibling, or the end of the structure */
+               np = prev;
+               while (np->parent && !np->sibling)
+                       np = np->parent;
+               np = np->sibling; /* Might be null at the end of the tree */
+       }
+       return np;
+}
+
 /**
  * of_find_all_nodes - Get next node in global list
  * @prev:      Previous node or NULL to start iteration
@@ -259,10 +277,8 @@ struct device_node *of_find_all_nodes(struct device_node *prev)
        unsigned long flags;
 
        raw_spin_lock_irqsave(&devtree_lock, flags);
-       np = prev ? prev->allnext : of_allnodes;
-       for (; np != NULL; np = np->allnext)
-               if (of_node_get(np))
-                       break;
+       np = __of_find_all_nodes(prev);
+       of_node_get(np);
        of_node_put(prev);
        raw_spin_unlock_irqrestore(&devtree_lock, flags);
        return np;
@@ -485,7 +501,7 @@ EXPORT_SYMBOL(of_device_is_compatible);
  * of_machine_is_compatible - Test root of device tree for a given compatible value
  * @compat: compatible string to look for in root node's compatible property.
  *
- * Returns true if the root node has the given value in its
+ * Returns a positive integer if the root node has the given value in its
  * compatible property.
  */
 int of_machine_is_compatible(const char *compat)
@@ -507,27 +523,27 @@ EXPORT_SYMBOL(of_machine_is_compatible);
  *
  *  @device: Node to check for availability, with locks already held
  *
- *  Returns 1 if the status property is absent or set to "okay" or "ok",
- *  0 otherwise
+ *  Returns true if the status property is absent or set to "okay" or "ok",
+ *  false otherwise
  */
-static int __of_device_is_available(const struct device_node *device)
+static bool __of_device_is_available(const struct device_node *device)
 {
        const char *status;
        int statlen;
 
        if (!device)
-               return 0;
+               return false;
 
        status = __of_get_property(device, "status", &statlen);
        if (status == NULL)
-               return 1;
+               return true;
 
        if (statlen > 0) {
                if (!strcmp(status, "okay") || !strcmp(status, "ok"))
-                       return 1;
+                       return true;
        }
 
-       return 0;
+       return false;
 }
 
 /**
@@ -535,13 +551,13 @@ static int __of_device_is_available(const struct device_node *device)
  *
  *  @device: Node to check for availability
  *
- *  Returns 1 if the status property is absent or set to "okay" or "ok",
- *  0 otherwise
+ *  Returns true if the status property is absent or set to "okay" or "ok",
+ *  false otherwise
  */
-int of_device_is_available(const struct device_node *device)
+bool of_device_is_available(const struct device_node *device)
 {
        unsigned long flags;
-       int res;
+       bool res;
 
        raw_spin_lock_irqsave(&devtree_lock, flags);
        res = __of_device_is_available(device);
@@ -577,9 +593,9 @@ EXPORT_SYMBOL(of_get_parent);
  *     of_get_next_parent - Iterate to a node's parent
  *     @node:  Node to get parent of
  *
- *     This is like of_get_parent() except that it drops the
- *     refcount on the passed node, making it suitable for iterating
- *     through a node's parents.
+ *     This is like of_get_parent() except that it drops the
+ *     refcount on the passed node, making it suitable for iterating
+ *     through a node's parents.
  *
  *     Returns a node pointer with refcount incremented, use
  *     of_node_put() on it when done.
@@ -699,10 +715,15 @@ static struct device_node *__of_find_node_by_path(struct device_node *parent,
 {
        struct device_node *child;
        int len = strchrnul(path, '/') - path;
+       int term;
 
        if (!len)
                return NULL;
 
+       term = strchrnul(path, ':') - path;
+       if (term < len)
+               len = term;
+
        __for_each_child_of_node(parent, child) {
                const char *name = strrchr(child->full_name, '/');
                if (WARN(!name, "malformed device_node %s\n", child->full_name))
@@ -715,11 +736,14 @@ static struct device_node *__of_find_node_by_path(struct device_node *parent,
 }
 
 /**
- *     of_find_node_by_path - Find a node matching a full OF path
+ *     of_find_node_opts_by_path - Find a node matching a full OF path
  *     @path: Either the full path to match, or if the path does not
  *            start with '/', the name of a property of the /aliases
  *            node (an alias).  In the case of an alias, the node
  *            matching the alias' value will be returned.
+ *     @opts: Address of a pointer into which to store the start of
+ *            an options string appended to the end of the path with
+ *            a ':' separator.
  *
  *     Valid paths:
  *             /foo/bar        Full path
@@ -729,19 +753,23 @@ static struct device_node *__of_find_node_by_path(struct device_node *parent,
  *     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 *of_find_node_opts_by_path(const char *path, const char **opts)
 {
        struct device_node *np = NULL;
        struct property *pp;
        unsigned long flags;
+       const char *separator = strchr(path, ':');
+
+       if (opts)
+               *opts = separator ? separator + 1 : NULL;
 
        if (strcmp(path, "/") == 0)
-               return of_node_get(of_allnodes);
+               return of_node_get(of_root);
 
        /* The path could begin with an alias */
        if (*path != '/') {
                char *p = strchrnul(path, '/');
-               int len = p - path;
+               int len = separator ? separator - path : p - path;
 
                /* of_aliases must not be NULL */
                if (!of_aliases)
@@ -761,7 +789,7 @@ struct device_node *of_find_node_by_path(const char *path)
        /* Step down the tree matching path components */
        raw_spin_lock_irqsave(&devtree_lock, flags);
        if (!np)
-               np = of_node_get(of_allnodes);
+               np = of_node_get(of_root);
        while (np && *path == '/') {
                path++; /* Increment past '/' delimiter */
                np = __of_find_node_by_path(np, path);
@@ -770,7 +798,7 @@ struct device_node *of_find_node_by_path(const char *path)
        raw_spin_unlock_irqrestore(&devtree_lock, flags);
        return np;
 }
-EXPORT_SYMBOL(of_find_node_by_path);
+EXPORT_SYMBOL(of_find_node_opts_by_path);
 
 /**
  *     of_find_node_by_name - Find a node by its "name" property
@@ -790,8 +818,7 @@ struct device_node *of_find_node_by_name(struct device_node *from,
        unsigned long flags;
 
        raw_spin_lock_irqsave(&devtree_lock, flags);
-       np = from ? from->allnext : of_allnodes;
-       for (; np; np = np->allnext)
+       for_each_of_allnodes_from(from, np)
                if (np->name && (of_node_cmp(np->name, name) == 0)
                    && of_node_get(np))
                        break;
@@ -820,8 +847,7 @@ struct device_node *of_find_node_by_type(struct device_node *from,
        unsigned long flags;
 
        raw_spin_lock_irqsave(&devtree_lock, flags);
-       np = from ? from->allnext : of_allnodes;
-       for (; np; np = np->allnext)
+       for_each_of_allnodes_from(from, np)
                if (np->type && (of_node_cmp(np->type, type) == 0)
                    && of_node_get(np))
                        break;
@@ -852,12 +878,10 @@ struct device_node *of_find_compatible_node(struct device_node *from,
        unsigned long flags;
 
        raw_spin_lock_irqsave(&devtree_lock, flags);
-       np = from ? from->allnext : of_allnodes;
-       for (; np; np = np->allnext) {
+       for_each_of_allnodes_from(from, np)
                if (__of_device_is_compatible(np, compatible, type, NULL) &&
                    of_node_get(np))
                        break;
-       }
        of_node_put(from);
        raw_spin_unlock_irqrestore(&devtree_lock, flags);
        return np;
@@ -884,8 +908,7 @@ struct device_node *of_find_node_with_property(struct device_node *from,
        unsigned long flags;
 
        raw_spin_lock_irqsave(&devtree_lock, flags);
-       np = from ? from->allnext : of_allnodes;
-       for (; np; np = np->allnext) {
+       for_each_of_allnodes_from(from, np) {
                for (pp = np->properties; pp; pp = pp->next) {
                        if (of_prop_cmp(pp->name, prop_name) == 0) {
                                of_node_get(np);
@@ -923,7 +946,7 @@ const struct of_device_id *__of_match_node(const struct of_device_id *matches,
 }
 
 /**
- * of_match_node - Tell if an device_node has a matching of_match structure
+ * of_match_node - Tell if a device_node has a matching of_match structure
  *     @matches:       array of of device match structures to search in
  *     @node:          the of device structure to match against
  *
@@ -967,8 +990,7 @@ struct device_node *of_find_matching_node_and_match(struct device_node *from,
                *match = NULL;
 
        raw_spin_lock_irqsave(&devtree_lock, flags);
-       np = from ? from->allnext : of_allnodes;
-       for (; np; np = np->allnext) {
+       for_each_of_allnodes_from(from, np) {
                m = __of_match_node(matches, np);
                if (m && of_node_get(np)) {
                        if (match)
@@ -1025,7 +1047,7 @@ struct device_node *of_find_node_by_phandle(phandle handle)
                return NULL;
 
        raw_spin_lock_irqsave(&devtree_lock, flags);
-       for (np = of_allnodes; np; np = np->allnext)
+       for_each_of_allnodes(np)
                if (np->phandle == handle)
                        break;
        of_node_get(np);
@@ -1249,6 +1271,39 @@ int of_property_read_u64(const struct device_node *np, const char *propname,
 }
 EXPORT_SYMBOL_GPL(of_property_read_u64);
 
+/**
+ * of_property_read_u64_array - Find and read an array of 64 bit integers
+ * from a property.
+ *
+ * @np:                device node from which the property value is to be read.
+ * @propname:  name of the property to be searched.
+ * @out_values:        pointer to return value, modified only if return value is 0.
+ * @sz:                number of array elements to read
+ *
+ * Search for a property in a device node and read 64-bit value(s) from
+ * it. Returns 0 on success, -EINVAL if the property does not exist,
+ * -ENODATA if property does not have a value, and -EOVERFLOW if the
+ * property data isn't large enough.
+ *
+ * The out_values is modified only if a valid u64 value can be decoded.
+ */
+int of_property_read_u64_array(const struct device_node *np,
+                              const char *propname, u64 *out_values,
+                              size_t sz)
+{
+       const __be32 *val = of_find_property_value_of_size(np, propname,
+                                               (sz * sizeof(*out_values)));
+
+       if (IS_ERR(val))
+               return PTR_ERR(val);
+
+       while (sz--) {
+               *out_values++ = of_read_number(val, 2);
+               val += 2;
+       }
+       return 0;
+}
+
 /**
  * of_property_read_string - Find and read a string from a property
  * @np:                device node from which the property value is to be read.
@@ -1317,7 +1372,7 @@ int of_property_match_string(struct device_node *np, const char *propname,
 EXPORT_SYMBOL_GPL(of_property_match_string);
 
 /**
- * of_property_read_string_util() - Utility helper for parsing string properties
+ * of_property_read_string_helper() - Utility helper for parsing string properties
  * @np:                device node from which the property value is to be read.
  * @propname:  name of the property to be searched.
  * @out_strs:  output array of string pointers.
@@ -1516,21 +1571,21 @@ EXPORT_SYMBOL(of_parse_phandle);
  * Returns 0 on success and fills out_args, on error returns appropriate
  * errno value.
  *
- * Caller is responsible to call of_node_put() on the returned out_args->node
+ * Caller is responsible to call of_node_put() on the returned out_args->np
  * pointer.
  *
  * Example:
  *
  * phandle1: node1 {
- *     #list-cells = <2>;
+ *     #list-cells = <2>;
  * }
  *
  * phandle2: node2 {
- *     #list-cells = <1>;
+ *     #list-cells = <1>;
  * }
  *
  * node3 {
- *     list = <&phandle1 1 2 &phandle2 3>;
+ *     list = <&phandle1 1 2 &phandle2 3>;
  * }
  *
  * To get a device_node of the `node2' node you may call this:
@@ -1559,7 +1614,7 @@ EXPORT_SYMBOL(of_parse_phandle_with_args);
  * Returns 0 on success and fills out_args, on error returns appropriate
  * errno value.
  *
- * Caller is responsible to call of_node_put() on the returned out_args->node
+ * Caller is responsible to call of_node_put() on the returned out_args->np
  * pointer.
  *
  * Example:
@@ -1571,7 +1626,7 @@ EXPORT_SYMBOL(of_parse_phandle_with_args);
  * }
  *
  * node3 {
- *     list = <&phandle1 0 2 &phandle2 2 3>;
+ *     list = <&phandle1 0 2 &phandle2 2 3>;
  * }
  *
  * To get a device_node of the `node2' node you may call this:
@@ -1805,14 +1860,14 @@ static void of_alias_add(struct alias_prop *ap, struct device_node *np,
 }
 
 /**
- * of_alias_scan - Scan all properties of 'aliases' node
+ * of_alias_scan - Scan all properties of the 'aliases' node
  *
- * The function scans all the properties of 'aliases' node and populate
- * the the global lookup table with the properties.  It returns the
- * number of alias_prop found, or error code in error case.
+ * The function scans all the properties of the 'aliases' node and populates
+ * the global lookup table with the properties.  It returns the
+ * number of alias properties found, or an error code in case of failure.
  *
  * @dt_alloc:  An allocator that provides a virtual address to memory
- *             for the resulting tree
+ *             for storing the resulting tree
  */
 void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
 {
@@ -1831,7 +1886,7 @@ void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
                if (IS_ENABLED(CONFIG_PPC) && !name)
                        name = of_get_property(of_aliases, "stdout", NULL);
                if (name)
-                       of_stdout = of_find_node_by_path(name);
+                       of_stdout = of_find_node_opts_by_path(name, &of_stdout_options);
        }
 
        if (!of_aliases)
@@ -1957,7 +2012,8 @@ bool of_console_check(struct device_node *dn, char *name, int index)
 {
        if (!dn || dn != of_stdout || console_set_on_cmdline)
                return false;
-       return !add_preferred_console(name, index, NULL);
+       return !add_preferred_console(name, index,
+                                     kstrdup(of_stdout_options, GFP_KERNEL));
 }
 EXPORT_SYMBOL_GPL(of_console_check);