]> nv-tegra.nvidia Code Review - linux-3.10.git/blobdiff - drivers/of/base.c
[media] DT: export of_get_next_parent() for use by modules: fix modular V4L2
[linux-3.10.git] / drivers / of / base.c
index 41c5dfd853586704d0ac75fee8b23068466fa9d8..1733081eb87310172eddc17b9e691d385ff95926 100644 (file)
@@ -9,34 +9,47 @@
  *
  *  Adapted for sparc and sparc64 by David S. Miller davem@davemloft.net
  *
- *  Reconsolidated from arch/x/kernel/prom.c by Stephen Rothwell.
+ *  Reconsolidated from arch/x/kernel/prom.c by Stephen Rothwell and
+ *  Grant Likely.
  *
  *      This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
  *      as published by the Free Software Foundation; either version
  *      2 of the License, or (at your option) any later version.
  */
+#include <linux/ctype.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
 
-struct device_node *allnodes;
+#include "of_private.h"
+
+LIST_HEAD(aliases_lookup);
+
+struct device_node *of_allnodes;
+EXPORT_SYMBOL(of_allnodes);
+struct device_node *of_chosen;
+struct device_node *of_aliases;
+
+DEFINE_MUTEX(of_aliases_mutex);
 
 /* use when traversing tree through the allnext, child, sibling,
  * or parent members of struct device_node.
  */
-DEFINE_RWLOCK(devtree_lock);
+DEFINE_RAW_SPINLOCK(devtree_lock);
 
 int of_n_addr_cells(struct device_node *np)
 {
-       const int *ip;
+       const __be32 *ip;
 
        do {
                if (np->parent)
                        np = np->parent;
                ip = of_get_property(np, "#address-cells", NULL);
                if (ip)
-                       return *ip;
+                       return be32_to_cpup(ip);
        } while (np->parent);
        /* No #address-cells property for the root node */
        return OF_ROOT_NODE_ADDR_CELLS_DEFAULT;
@@ -45,49 +58,170 @@ EXPORT_SYMBOL(of_n_addr_cells);
 
 int of_n_size_cells(struct device_node *np)
 {
-       const int *ip;
+       const __be32 *ip;
 
        do {
                if (np->parent)
                        np = np->parent;
                ip = of_get_property(np, "#size-cells", NULL);
                if (ip)
-                       return *ip;
+                       return be32_to_cpup(ip);
        } while (np->parent);
        /* No #size-cells property for the root node */
        return OF_ROOT_NODE_SIZE_CELLS_DEFAULT;
 }
 EXPORT_SYMBOL(of_n_size_cells);
 
-struct property *of_find_property(const struct device_node *np,
-                                 const char *name,
-                                 int *lenp)
+#if defined(CONFIG_OF_DYNAMIC)
+/**
+ *     of_node_get - Increment refcount of a node
+ *     @node:  Node to inc refcount, NULL is supported to
+ *             simplify writing of callers
+ *
+ *     Returns node.
+ */
+struct device_node *of_node_get(struct device_node *node)
+{
+       if (node)
+               kref_get(&node->kref);
+       return node;
+}
+EXPORT_SYMBOL(of_node_get);
+
+static inline struct device_node *kref_to_device_node(struct kref *kref)
+{
+       return container_of(kref, struct device_node, kref);
+}
+
+/**
+ *     of_node_release - release a dynamically allocated node
+ *     @kref:  kref element of the node to be released
+ *
+ *     In of_node_put() this function is passed to kref_put()
+ *     as the destructor.
+ */
+static void of_node_release(struct kref *kref)
+{
+       struct device_node *node = kref_to_device_node(kref);
+       struct property *prop = node->properties;
+
+       /* We should never be releasing nodes that haven't been detached. */
+       if (!of_node_check_flag(node, OF_DETACHED)) {
+               pr_err("ERROR: Bad of_node_put() on %s\n", node->full_name);
+               dump_stack();
+               kref_init(&node->kref);
+               return;
+       }
+
+       if (!of_node_check_flag(node, OF_DYNAMIC))
+               return;
+
+       while (prop) {
+               struct property *next = prop->next;
+               kfree(prop->name);
+               kfree(prop->value);
+               kfree(prop);
+               prop = next;
+
+               if (!prop) {
+                       prop = node->deadprops;
+                       node->deadprops = NULL;
+               }
+       }
+       kfree(node->full_name);
+       kfree(node->data);
+       kfree(node);
+}
+
+/**
+ *     of_node_put - Decrement refcount of a node
+ *     @node:  Node to dec refcount, NULL is supported to
+ *             simplify writing of callers
+ *
+ */
+void of_node_put(struct device_node *node)
+{
+       if (node)
+               kref_put(&node->kref, of_node_release);
+}
+EXPORT_SYMBOL(of_node_put);
+#endif /* CONFIG_OF_DYNAMIC */
+
+static struct property *__of_find_property(const struct device_node *np,
+                                          const char *name, int *lenp)
 {
        struct property *pp;
 
        if (!np)
                return NULL;
 
-       read_lock(&devtree_lock);
-       for (pp = np->properties; pp != 0; pp = pp->next) {
+       for (pp = np->properties; pp; pp = pp->next) {
                if (of_prop_cmp(pp->name, name) == 0) {
-                       if (lenp != 0)
+                       if (lenp)
                                *lenp = pp->length;
                        break;
                }
        }
-       read_unlock(&devtree_lock);
+
+       return pp;
+}
+
+struct property *of_find_property(const struct device_node *np,
+                                 const char *name,
+                                 int *lenp)
+{
+       struct property *pp;
+       unsigned long flags;
+
+       raw_spin_lock_irqsave(&devtree_lock, flags);
+       pp = __of_find_property(np, name, lenp);
+       raw_spin_unlock_irqrestore(&devtree_lock, flags);
 
        return pp;
 }
 EXPORT_SYMBOL(of_find_property);
 
+/**
+ * of_find_all_nodes - Get next node in global list
+ * @prev:      Previous node or NULL to start iteration
+ *             of_node_put() will be called on it
+ *
+ * Returns a node pointer with refcount incremented, use
+ * of_node_put() on it when done.
+ */
+struct device_node *of_find_all_nodes(struct device_node *prev)
+{
+       struct device_node *np;
+
+       raw_spin_lock(&devtree_lock);
+       np = prev ? prev->allnext : of_allnodes;
+       for (; np != NULL; np = np->allnext)
+               if (of_node_get(np))
+                       break;
+       of_node_put(prev);
+       raw_spin_unlock(&devtree_lock);
+       return np;
+}
+EXPORT_SYMBOL(of_find_all_nodes);
+
+/*
+ * Find a property with a given name for a given node
+ * and return the value.
+ */
+static const void *__of_get_property(const struct device_node *np,
+                                    const char *name, int *lenp)
+{
+       struct property *pp = __of_find_property(np, name, lenp);
+
+       return pp ? pp->value : NULL;
+}
+
 /*
  * Find a property with a given name for a given node
  * and return the value.
  */
 const void *of_get_property(const struct device_node *np, const char *name,
-                        int *lenp)
+                           int *lenp)
 {
        struct property *pp = of_find_property(np, name, lenp);
 
@@ -98,13 +232,13 @@ EXPORT_SYMBOL(of_get_property);
 /** Checks if the given "compat" string matches one of the strings in
  * the device's "compatible" property
  */
-int of_device_is_compatible(const struct device_node *device,
-               const char *compat)
+static int __of_device_is_compatible(const struct device_node *device,
+                                    const char *compat)
 {
        const char* cp;
        int cplen, l;
 
-       cp = of_get_property(device, "compatible", &cplen);
+       cp = __of_get_property(device, "compatible", &cplen);
        if (cp == NULL)
                return 0;
        while (cplen > 0) {
@@ -117,22 +251,58 @@ int of_device_is_compatible(const struct device_node *device,
 
        return 0;
 }
+
+/** Checks if the given "compat" string matches one of the strings in
+ * the device's "compatible" property
+ */
+int of_device_is_compatible(const struct device_node *device,
+               const char *compat)
+{
+       unsigned long flags;
+       int res;
+
+       raw_spin_lock_irqsave(&devtree_lock, flags);
+       res = __of_device_is_compatible(device, compat);
+       raw_spin_unlock_irqrestore(&devtree_lock, flags);
+       return res;
+}
 EXPORT_SYMBOL(of_device_is_compatible);
 
 /**
- *  of_device_is_available - check if a device is available for use
+ * 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.
  *
- *  @device: Node to check for availability
+ * Returns true if the root node has the given value in its
+ * compatible property.
+ */
+int of_machine_is_compatible(const char *compat)
+{
+       struct device_node *root;
+       int rc = 0;
+
+       root = of_find_node_by_path("/");
+       if (root) {
+               rc = of_device_is_compatible(root, compat);
+               of_node_put(root);
+       }
+       return rc;
+}
+EXPORT_SYMBOL(of_machine_is_compatible);
+
+/**
+ *  __of_device_is_available - check if a device is available for use
+ *
+ *  @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
  */
-int of_device_is_available(const struct device_node *device)
+static int __of_device_is_available(const struct device_node *device)
 {
        const char *status;
        int statlen;
 
-       status = of_get_property(device, "status", &statlen);
+       status = __of_get_property(device, "status", &statlen);
        if (status == NULL)
                return 1;
 
@@ -143,6 +313,26 @@ int of_device_is_available(const struct device_node *device)
 
        return 0;
 }
+
+/**
+ *  of_device_is_available - check if a device is available for use
+ *
+ *  @device: Node to check for availability
+ *
+ *  Returns 1 if the status property is absent or set to "okay" or "ok",
+ *  0 otherwise
+ */
+int of_device_is_available(const struct device_node *device)
+{
+       unsigned long flags;
+       int res;
+
+       raw_spin_lock_irqsave(&devtree_lock, flags);
+       res = __of_device_is_available(device);
+       raw_spin_unlock_irqrestore(&devtree_lock, flags);
+       return res;
+
+}
 EXPORT_SYMBOL(of_device_is_available);
 
 /**
@@ -155,13 +345,14 @@ EXPORT_SYMBOL(of_device_is_available);
 struct device_node *of_get_parent(const struct device_node *node)
 {
        struct device_node *np;
+       unsigned long flags;
 
        if (!node)
                return NULL;
 
-       read_lock(&devtree_lock);
+       raw_spin_lock_irqsave(&devtree_lock, flags);
        np = of_node_get(node->parent);
-       read_unlock(&devtree_lock);
+       raw_spin_unlock_irqrestore(&devtree_lock, flags);
        return np;
 }
 EXPORT_SYMBOL(of_get_parent);
@@ -180,16 +371,18 @@ EXPORT_SYMBOL(of_get_parent);
 struct device_node *of_get_next_parent(struct device_node *node)
 {
        struct device_node *parent;
+       unsigned long flags;
 
        if (!node)
                return NULL;
 
-       read_lock(&devtree_lock);
+       raw_spin_lock_irqsave(&devtree_lock, flags);
        parent = of_node_get(node->parent);
        of_node_put(node);
-       read_unlock(&devtree_lock);
+       raw_spin_unlock_irqrestore(&devtree_lock, flags);
        return parent;
 }
+EXPORT_SYMBOL(of_get_next_parent);
 
 /**
  *     of_get_next_child - Iterate a node childs
@@ -203,18 +396,69 @@ struct device_node *of_get_next_child(const struct device_node *node,
        struct device_node *prev)
 {
        struct device_node *next;
+       unsigned long flags;
 
-       read_lock(&devtree_lock);
+       raw_spin_lock_irqsave(&devtree_lock, flags);
        next = prev ? prev->sibling : node->child;
        for (; next; next = next->sibling)
                if (of_node_get(next))
                        break;
        of_node_put(prev);
-       read_unlock(&devtree_lock);
+       raw_spin_unlock_irqrestore(&devtree_lock, flags);
        return next;
 }
 EXPORT_SYMBOL(of_get_next_child);
 
+/**
+ *     of_get_next_available_child - Find the next available child node
+ *     @node:  parent node
+ *     @prev:  previous child of the parent node, or NULL to get first
+ *
+ *      This function is like of_get_next_child(), except that it
+ *      automatically skips any disabled nodes (i.e. status = "disabled").
+ */
+struct device_node *of_get_next_available_child(const struct device_node *node,
+       struct device_node *prev)
+{
+       struct device_node *next;
+
+       raw_spin_lock(&devtree_lock);
+       next = prev ? prev->sibling : node->child;
+       for (; next; next = next->sibling) {
+               if (!__of_device_is_available(next))
+                       continue;
+               if (of_node_get(next))
+                       break;
+       }
+       of_node_put(prev);
+       raw_spin_unlock(&devtree_lock);
+       return next;
+}
+EXPORT_SYMBOL(of_get_next_available_child);
+
+/**
+ *     of_get_child_by_name - Find the child node by name for a given parent
+ *     @node:  parent node
+ *     @name:  child name to look for.
+ *
+ *      This function looks for child node for given matching name
+ *
+ *     Returns a node pointer if found, with refcount incremented, use
+ *     of_node_put() on it when done.
+ *     Returns NULL if node is not found.
+ */
+struct device_node *of_get_child_by_name(const struct device_node *node,
+                               const char *name)
+{
+       struct device_node *child;
+
+       for_each_child_of_node(node, child)
+               if (child->name && (of_node_cmp(child->name, name) == 0))
+                       break;
+       return child;
+}
+EXPORT_SYMBOL(of_get_child_by_name);
+
 /**
  *     of_find_node_by_path - Find a node matching a full OF path
  *     @path:  The full path to match
@@ -224,15 +468,16 @@ EXPORT_SYMBOL(of_get_next_child);
  */
 struct device_node *of_find_node_by_path(const char *path)
 {
-       struct device_node *np = allnodes;
+       struct device_node *np = of_allnodes;
+       unsigned long flags;
 
-       read_lock(&devtree_lock);
+       raw_spin_lock_irqsave(&devtree_lock, flags);
        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);
+       raw_spin_unlock_irqrestore(&devtree_lock, flags);
        return np;
 }
 EXPORT_SYMBOL(of_find_node_by_path);
@@ -252,15 +497,16 @@ struct device_node *of_find_node_by_name(struct device_node *from,
        const char *name)
 {
        struct device_node *np;
+       unsigned long flags;
 
-       read_lock(&devtree_lock);
-       np = from ? from->allnext : allnodes;
+       raw_spin_lock_irqsave(&devtree_lock, flags);
+       np = from ? from->allnext : of_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);
+       raw_spin_unlock_irqrestore(&devtree_lock, flags);
        return np;
 }
 EXPORT_SYMBOL(of_find_node_by_name);
@@ -281,15 +527,16 @@ struct device_node *of_find_node_by_type(struct device_node *from,
        const char *type)
 {
        struct device_node *np;
+       unsigned long flags;
 
-       read_lock(&devtree_lock);
-       np = from ? from->allnext : allnodes;
+       raw_spin_lock_irqsave(&devtree_lock, flags);
+       np = from ? from->allnext : of_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);
+       raw_spin_unlock_irqrestore(&devtree_lock, flags);
        return np;
 }
 EXPORT_SYMBOL(of_find_node_by_type);
@@ -312,18 +559,20 @@ struct device_node *of_find_compatible_node(struct device_node *from,
        const char *type, const char *compatible)
 {
        struct device_node *np;
+       unsigned long flags;
 
-       read_lock(&devtree_lock);
-       np = from ? from->allnext : allnodes;
+       raw_spin_lock_irqsave(&devtree_lock, flags);
+       np = from ? from->allnext : of_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))
+               if (__of_device_is_compatible(np, compatible) &&
+                   of_node_get(np))
                        break;
        }
        of_node_put(from);
-       read_unlock(&devtree_lock);
+       raw_spin_unlock_irqrestore(&devtree_lock, flags);
        return np;
 }
 EXPORT_SYMBOL(of_find_compatible_node);
@@ -345,11 +594,12 @@ struct device_node *of_find_node_with_property(struct device_node *from,
 {
        struct device_node *np;
        struct property *pp;
+       unsigned long flags;
 
-       read_lock(&devtree_lock);
-       np = from ? from->allnext : allnodes;
+       raw_spin_lock_irqsave(&devtree_lock, flags);
+       np = from ? from->allnext : of_allnodes;
        for (; np; np = np->allnext) {
-               for (pp = np->properties; pp != 0; pp = pp->next) {
+               for (pp = np->properties; pp; pp = pp->next) {
                        if (of_prop_cmp(pp->name, prop_name) == 0) {
                                of_node_get(np);
                                goto out;
@@ -358,21 +608,18 @@ struct device_node *of_find_node_with_property(struct device_node *from,
        }
 out:
        of_node_put(from);
-       read_unlock(&devtree_lock);
+       raw_spin_unlock_irqrestore(&devtree_lock, flags);
        return np;
 }
 EXPORT_SYMBOL(of_find_node_with_property);
 
-/**
- * of_match_node - Tell if an 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
- *
- *     Low level utility function used by device matching.
- */
-const struct of_device_id *of_match_node(const struct of_device_id *matches,
-                                        const struct device_node *node)
+static
+const struct of_device_id *__of_match_node(const struct of_device_id *matches,
+                                          const struct device_node *node)
 {
+       if (!matches)
+               return NULL;
+
        while (matches->name[0] || matches->type[0] || matches->compatible[0]) {
                int match = 1;
                if (matches->name[0])
@@ -382,130 +629,451 @@ const struct of_device_id *of_match_node(const struct of_device_id *matches,
                        match &= node->type
                                && !strcmp(matches->type, node->type);
                if (matches->compatible[0])
-                       match &= of_device_is_compatible(node,
-                                               matches->compatible);
+                       match &= __of_device_is_compatible(node,
+                                                          matches->compatible);
                if (match)
                        return matches;
                matches++;
        }
        return NULL;
 }
+
+/**
+ * of_match_node - Tell if an 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
+ *
+ *     Low level utility function used by device matching.
+ */
+const struct of_device_id *of_match_node(const struct of_device_id *matches,
+                                        const struct device_node *node)
+{
+       const struct of_device_id *match;
+       unsigned long flags;
+
+       raw_spin_lock_irqsave(&devtree_lock, flags);
+       match = __of_match_node(matches, node);
+       raw_spin_unlock_irqrestore(&devtree_lock, flags);
+       return match;
+}
 EXPORT_SYMBOL(of_match_node);
 
 /**
- *     of_find_matching_node - Find a node based on an of_device_id match
- *                             table.
+ *     of_find_matching_node_and_match - Find a node based on an of_device_id
+ *                                       match table.
  *     @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
  *     @matches:       array of of device match structures to search in
+ *     @match          Updated to point at the matches entry which matched
  *
  *     Returns a node pointer with refcount incremented, use
  *     of_node_put() on it when done.
  */
-struct device_node *of_find_matching_node(struct device_node *from,
-                                         const struct of_device_id *matches)
+struct device_node *of_find_matching_node_and_match(struct device_node *from,
+                                       const struct of_device_id *matches,
+                                       const struct of_device_id **match)
 {
        struct device_node *np;
+       const struct of_device_id *m;
+       unsigned long flags;
 
-       read_lock(&devtree_lock);
-       np = from ? from->allnext : allnodes;
+       if (match)
+               *match = NULL;
+
+       raw_spin_lock_irqsave(&devtree_lock, flags);
+       np = from ? from->allnext : of_allnodes;
        for (; np; np = np->allnext) {
-               if (of_match_node(matches, np) && of_node_get(np))
+               m = __of_match_node(matches, np);
+               if (m && of_node_get(np)) {
+                       if (match)
+                               *match = m;
                        break;
+               }
        }
        of_node_put(from);
-       read_unlock(&devtree_lock);
+       raw_spin_unlock_irqrestore(&devtree_lock, flags);
        return np;
 }
-EXPORT_SYMBOL(of_find_matching_node);
+EXPORT_SYMBOL(of_find_matching_node_and_match);
 
 /**
- * of_modalias_table: Table of explicit compatible ==> modalias mappings
+ * of_modalias_node - Lookup appropriate modalias for a device node
+ * @node:      pointer to a device tree node
+ * @modalias:  Pointer to buffer that modalias value will be copied into
+ * @len:       Length of modalias value
  *
- * This table allows particulare compatible property values to be mapped
- * to modalias strings.  This is useful for busses which do not directly
- * understand the OF device tree but are populated based on data contained
- * within the device tree.  SPI and I2C are the two current users of this
- * table.
+ * Based on the value of the compatible property, this routine will attempt
+ * to choose an appropriate modalias value for a particular device tree node.
+ * It does this by stripping the manufacturer prefix (as delimited by a ',')
+ * from the first entry in the compatible list property.
  *
- * In most cases, devices do not need to be listed in this table because
- * the modalias value can be derived directly from the compatible table.
- * However, if for any reason a value cannot be derived, then this table
- * provides a method to override the implicit derivation.
+ * This routine returns 0 on success, <0 on failure.
+ */
+int of_modalias_node(struct device_node *node, char *modalias, int len)
+{
+       const char *compatible, *p;
+       int cplen;
+
+       compatible = of_get_property(node, "compatible", &cplen);
+       if (!compatible || strlen(compatible) > cplen)
+               return -ENODEV;
+       p = strchr(compatible, ',');
+       strlcpy(modalias, p ? p + 1 : compatible, len);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(of_modalias_node);
+
+/**
+ * of_find_node_by_phandle - Find a node given a phandle
+ * @handle:    phandle of the node to find
  *
- * At the moment, a single table is used for all bus types because it is
- * assumed that the data size is small and that the compatible values
- * should already be distinct enough to differentiate between SPI, I2C
- * and other devices.
+ * Returns a node pointer with refcount incremented, use
+ * of_node_put() on it when done.
  */
-struct of_modalias_table {
-       char *of_device;
-       char *modalias;
-};
-static struct of_modalias_table of_modalias_table[] = {
-       { "fsl,mcu-mpc8349emitx", "mcu-mpc8349emitx" },
-       { "mmc-spi-slot", "mmc_spi" },
-};
+struct device_node *of_find_node_by_phandle(phandle handle)
+{
+       struct device_node *np;
+
+       raw_spin_lock(&devtree_lock);
+       for (np = of_allnodes; np; np = np->allnext)
+               if (np->phandle == handle)
+                       break;
+       of_node_get(np);
+       raw_spin_unlock(&devtree_lock);
+       return np;
+}
+EXPORT_SYMBOL(of_find_node_by_phandle);
 
 /**
- * of_modalias_node - Lookup appropriate modalias for a device node
- * @node:      pointer to a device tree node
- * @modalias:  Pointer to buffer that modalias value will be copied into
- * @len:       Length of modalias value
+ * of_property_read_u8_array - Find and read an array of u8 from a property.
+ *
+ * @np:                device node from which the property value is to be read.
+ * @propname:  name of the property to be searched.
+ * @out_value: pointer to return value, modified only if return value is 0.
+ * @sz:                number of array elements to read
  *
- * Based on the value of the compatible property, this routine will determine
- * an appropriate modalias value for a particular device tree node.  Two
- * separate methods are attempted to derive a modalias value.
+ * Search for a property in a device node and read 8-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.
  *
- * First method is to lookup the compatible value in of_modalias_table.
- * Second is to strip off the manufacturer prefix from the first
- * compatible entry and use the remainder as modalias
+ * dts entry of array should be like:
+ *     property = /bits/ 8 <0x50 0x60 0x70>;
  *
- * This routine returns 0 on success
+ * The out_value is modified only if a valid u8 value can be decoded.
  */
-int of_modalias_node(struct device_node *node, char *modalias, int len)
+int of_property_read_u8_array(const struct device_node *np,
+                       const char *propname, u8 *out_values, size_t sz)
+{
+       struct property *prop = of_find_property(np, propname, NULL);
+       const u8 *val;
+
+       if (!prop)
+               return -EINVAL;
+       if (!prop->value)
+               return -ENODATA;
+       if ((sz * sizeof(*out_values)) > prop->length)
+               return -EOVERFLOW;
+
+       val = prop->value;
+       while (sz--)
+               *out_values++ = *val++;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(of_property_read_u8_array);
+
+/**
+ * of_property_read_u16_array - Find and read an array of u16 from a property.
+ *
+ * @np:                device node from which the property value is to be read.
+ * @propname:  name of the property to be searched.
+ * @out_value: 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 16-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.
+ *
+ * dts entry of array should be like:
+ *     property = /bits/ 16 <0x5000 0x6000 0x7000>;
+ *
+ * The out_value is modified only if a valid u16 value can be decoded.
+ */
+int of_property_read_u16_array(const struct device_node *np,
+                       const char *propname, u16 *out_values, size_t sz)
+{
+       struct property *prop = of_find_property(np, propname, NULL);
+       const __be16 *val;
+
+       if (!prop)
+               return -EINVAL;
+       if (!prop->value)
+               return -ENODATA;
+       if ((sz * sizeof(*out_values)) > prop->length)
+               return -EOVERFLOW;
+
+       val = prop->value;
+       while (sz--)
+               *out_values++ = be16_to_cpup(val++);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(of_property_read_u16_array);
+
+/**
+ * of_property_read_u32_array - Find and read an array of 32 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_value: 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 32-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_value is modified only if a valid u32 value can be decoded.
+ */
+int of_property_read_u32_array(const struct device_node *np,
+                              const char *propname, u32 *out_values,
+                              size_t sz)
 {
-       int i, cplen;
-       const char *compatible;
+       struct property *prop = of_find_property(np, propname, NULL);
+       const __be32 *val;
+
+       if (!prop)
+               return -EINVAL;
+       if (!prop->value)
+               return -ENODATA;
+       if ((sz * sizeof(*out_values)) > prop->length)
+               return -EOVERFLOW;
+
+       val = prop->value;
+       while (sz--)
+               *out_values++ = be32_to_cpup(val++);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(of_property_read_u32_array);
+
+/**
+ * of_property_read_u64 - Find and read a 64 bit integer from a property
+ * @np:                device node from which the property value is to be read.
+ * @propname:  name of the property to be searched.
+ * @out_value: pointer to return value, modified only if return value is 0.
+ *
+ * Search for a property in a device node and read a 64-bit value 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_value is modified only if a valid u64 value can be decoded.
+ */
+int of_property_read_u64(const struct device_node *np, const char *propname,
+                        u64 *out_value)
+{
+       struct property *prop = of_find_property(np, propname, NULL);
+
+       if (!prop)
+               return -EINVAL;
+       if (!prop->value)
+               return -ENODATA;
+       if (sizeof(*out_value) > prop->length)
+               return -EOVERFLOW;
+       *out_value = of_read_number(prop->value, 2);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(of_property_read_u64);
+
+/**
+ * of_property_read_string - Find and read a string from a property
+ * @np:                device node from which the property value is to be read.
+ * @propname:  name of the property to be searched.
+ * @out_string:        pointer to null terminated return string, modified only if
+ *             return value is 0.
+ *
+ * Search for a property in a device tree node and retrieve a null
+ * terminated string value (pointer to data, not a copy). Returns 0 on
+ * success, -EINVAL if the property does not exist, -ENODATA if property
+ * does not have a value, and -EILSEQ if the string is not null-terminated
+ * within the length of the property data.
+ *
+ * The out_string pointer is modified only if a valid string can be decoded.
+ */
+int of_property_read_string(struct device_node *np, const char *propname,
+                               const char **out_string)
+{
+       struct property *prop = of_find_property(np, propname, NULL);
+       if (!prop)
+               return -EINVAL;
+       if (!prop->value)
+               return -ENODATA;
+       if (strnlen(prop->value, prop->length) >= prop->length)
+               return -EILSEQ;
+       *out_string = prop->value;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(of_property_read_string);
+
+/**
+ * of_property_read_string_index - Find and read a string from a multiple
+ * strings property.
+ * @np:                device node from which the property value is to be read.
+ * @propname:  name of the property to be searched.
+ * @index:     index of the string in the list of strings
+ * @out_string:        pointer to null terminated return string, modified only if
+ *             return value is 0.
+ *
+ * Search for a property in a device tree node and retrieve a null
+ * terminated string value (pointer to data, not a copy) in the list of strings
+ * contained in that property.
+ * Returns 0 on success, -EINVAL if the property does not exist, -ENODATA if
+ * property does not have a value, and -EILSEQ if the string is not
+ * null-terminated within the length of the property data.
+ *
+ * The out_string pointer is modified only if a valid string can be decoded.
+ */
+int of_property_read_string_index(struct device_node *np, const char *propname,
+                                 int index, const char **output)
+{
+       struct property *prop = of_find_property(np, propname, NULL);
+       int i = 0;
+       size_t l = 0, total = 0;
        const char *p;
 
-       /* 1. search for exception list entry */
-       for (i = 0; i < ARRAY_SIZE(of_modalias_table); i++) {
-               compatible = of_modalias_table[i].of_device;
-               if (!of_device_is_compatible(node, compatible))
-                       continue;
-               strlcpy(modalias, of_modalias_table[i].modalias, len);
-               return 0;
+       if (!prop)
+               return -EINVAL;
+       if (!prop->value)
+               return -ENODATA;
+       if (strnlen(prop->value, prop->length) >= prop->length)
+               return -EILSEQ;
+
+       p = prop->value;
+
+       for (i = 0; total < prop->length; total += l, p += l) {
+               l = strlen(p) + 1;
+               if (i++ == index) {
+                       *output = p;
+                       return 0;
+               }
        }
+       return -ENODATA;
+}
+EXPORT_SYMBOL_GPL(of_property_read_string_index);
 
-       compatible = of_get_property(node, "compatible", &cplen);
-       if (!compatible)
-               return -ENODEV;
+/**
+ * of_property_match_string() - Find string in a list and return index
+ * @np: pointer to node containing string list property
+ * @propname: string list property name
+ * @string: pointer to string to search for in string list
+ *
+ * This function searches a string list property and returns the index
+ * of a specific string value.
+ */
+int of_property_match_string(struct device_node *np, const char *propname,
+                            const char *string)
+{
+       struct property *prop = of_find_property(np, propname, NULL);
+       size_t l;
+       int i;
+       const char *p, *end;
 
-       /* 2. take first compatible entry and strip manufacturer */
-       p = strchr(compatible, ',');
-       if (!p)
-               return -ENODEV;
-       p++;
-       strlcpy(modalias, p, len);
-       return 0;
+       if (!prop)
+               return -EINVAL;
+       if (!prop->value)
+               return -ENODATA;
+
+       p = prop->value;
+       end = p + prop->length;
+
+       for (i = 0; p < end; i++, p += l) {
+               l = strlen(p) + 1;
+               if (p + l > end)
+                       return -EILSEQ;
+               pr_debug("comparing %s with %s\n", string, p);
+               if (strcmp(string, p) == 0)
+                       return i; /* Found it; return index */
+       }
+       return -ENODATA;
 }
-EXPORT_SYMBOL_GPL(of_modalias_node);
+EXPORT_SYMBOL_GPL(of_property_match_string);
 
 /**
- * of_parse_phandles_with_args - Find a node pointed by phandle in a list
+ * of_property_count_strings - Find and return the number of strings from a
+ * multiple strings property.
+ * @np:                device node from which the property value is to be read.
+ * @propname:  name of the property to be searched.
+ *
+ * Search for a property in a device tree node and retrieve the number of null
+ * terminated string contain in it. Returns the number of strings on
+ * success, -EINVAL if the property does not exist, -ENODATA if property
+ * does not have a value, and -EILSEQ if the string is not null-terminated
+ * within the length of the property data.
+ */
+int of_property_count_strings(struct device_node *np, const char *propname)
+{
+       struct property *prop = of_find_property(np, propname, NULL);
+       int i = 0;
+       size_t l = 0, total = 0;
+       const char *p;
+
+       if (!prop)
+               return -EINVAL;
+       if (!prop->value)
+               return -ENODATA;
+       if (strnlen(prop->value, prop->length) >= prop->length)
+               return -EILSEQ;
+
+       p = prop->value;
+
+       for (i = 0; total < prop->length; total += l, p += l, i++)
+               l = strlen(p) + 1;
+
+       return i;
+}
+EXPORT_SYMBOL_GPL(of_property_count_strings);
+
+/**
+ * of_parse_phandle - Resolve a phandle property to a device_node pointer
+ * @np: Pointer to device node holding phandle property
+ * @phandle_name: Name of property holding a phandle value
+ * @index: For properties holding a table of phandles, this is the index into
+ *         the table
+ *
+ * Returns the device_node pointer with refcount incremented.  Use
+ * of_node_put() on it when done.
+ */
+struct device_node *of_parse_phandle(const struct device_node *np,
+                                    const char *phandle_name, int index)
+{
+       const __be32 *phandle;
+       int size;
+
+       phandle = of_get_property(np, phandle_name, &size);
+       if ((!phandle) || (size < sizeof(*phandle) * (index + 1)))
+               return NULL;
+
+       return of_find_node_by_phandle(be32_to_cpup(phandle + index));
+}
+EXPORT_SYMBOL(of_parse_phandle);
+
+/**
+ * of_parse_phandle_with_args() - Find a node pointed by phandle in a list
  * @np:                pointer to a device tree node containing a list
  * @list_name: property name that contains a list
  * @cells_name:        property name that specifies phandles' arguments count
  * @index:     index of a phandle to parse out
- * @out_node:  optional pointer to device_node struct pointer (will be filled)
- * @out_args:  optional pointer to arguments pointer (will be filled)
+ * @out_args:  optional pointer to output arguments structure (will be filled)
  *
  * This function is useful to parse lists of phandles and their arguments.
- * Returns 0 on success and fills out_node and out_args, on error returns
- * appropriate errno value.
+ * 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
+ * pointer.
  *
  * Example:
  *
@@ -522,91 +1090,581 @@ EXPORT_SYMBOL_GPL(of_modalias_node);
  * }
  *
  * To get a device_node of the `node2' node you may call this:
- * of_parse_phandles_with_args(node3, "list", "#list-cells", 2, &node2, &args);
+ * of_parse_phandle_with_args(node3, "list", "#list-cells", 1, &args);
  */
-int of_parse_phandles_with_args(struct device_node *np, const char *list_name,
-                               const char *cells_name, int index,
-                               struct device_node **out_node,
-                               const void **out_args)
+static int __of_parse_phandle_with_args(const struct device_node *np,
+                                       const char *list_name,
+                                       const char *cells_name, int index,
+                                       struct of_phandle_args *out_args)
 {
-       int ret = -EINVAL;
-       const u32 *list;
-       const u32 *list_end;
-       int size;
-       int cur_index = 0;
+       const __be32 *list, *list_end;
+       int rc = 0, size, cur_index = 0;
+       uint32_t count = 0;
        struct device_node *node = NULL;
-       const void *args = NULL;
+       phandle phandle;
 
+       /* Retrieve the phandle list property */
        list = of_get_property(np, list_name, &size);
-       if (!list) {
-               ret = -ENOENT;
-               goto err0;
-       }
+       if (!list)
+               return -ENOENT;
        list_end = list + size / sizeof(*list);
 
+       /* Loop over the phandles until all the requested entry is found */
        while (list < list_end) {
-               const u32 *cells;
-               const phandle *phandle;
-
-               phandle = list++;
-               args = list;
+               rc = -EINVAL;
+               count = 0;
 
-               /* one cell hole in the list = <>; */
-               if (!*phandle)
-                       goto next;
+               /*
+                * If phandle is 0, then it is an empty entry with no
+                * arguments.  Skip forward to the next entry.
+                */
+               phandle = be32_to_cpup(list++);
+               if (phandle) {
+                       /*
+                        * Find the provider node and parse the #*-cells
+                        * property to determine the argument length
+                        */
+                       node = of_find_node_by_phandle(phandle);
+                       if (!node) {
+                               pr_err("%s: could not find phandle\n",
+                                        np->full_name);
+                               goto err;
+                       }
+                       if (of_property_read_u32(node, cells_name, &count)) {
+                               pr_err("%s: could not get %s for %s\n",
+                                        np->full_name, cells_name,
+                                        node->full_name);
+                               goto err;
+                       }
 
-               node = of_find_node_by_phandle(*phandle);
-               if (!node) {
-                       pr_debug("%s: could not find phandle\n",
-                                np->full_name);
-                       goto err0;
+                       /*
+                        * Make sure that the arguments actually fit in the
+                        * remaining property data length
+                        */
+                       if (list + count > list_end) {
+                               pr_err("%s: arguments longer than property\n",
+                                        np->full_name);
+                               goto err;
+                       }
                }
 
-               cells = of_get_property(node, cells_name, &size);
-               if (!cells || size != sizeof(*cells)) {
-                       pr_debug("%s: could not get %s for %s\n",
-                                np->full_name, cells_name, node->full_name);
-                       goto err1;
-               }
+               /*
+                * All of the error cases above bail out of the loop, so at
+                * this point, the parsing is successful. If the requested
+                * index matches, then fill the out_args structure and return,
+                * or return -ENOENT for an empty entry.
+                */
+               rc = -ENOENT;
+               if (cur_index == index) {
+                       if (!phandle)
+                               goto err;
 
-               list += *cells;
-               if (list > list_end) {
-                       pr_debug("%s: insufficient arguments length\n",
-                                np->full_name);
-                       goto err1;
+                       if (out_args) {
+                               int i;
+                               if (WARN_ON(count > MAX_PHANDLE_ARGS))
+                                       count = MAX_PHANDLE_ARGS;
+                               out_args->np = node;
+                               out_args->args_count = count;
+                               for (i = 0; i < count; i++)
+                                       out_args->args[i] = be32_to_cpup(list++);
+                       }
+
+                       /* Found it! return success */
+                       if (node)
+                               of_node_put(node);
+                       return 0;
                }
-next:
-               if (cur_index == index)
-                       break;
 
                of_node_put(node);
                node = NULL;
-               args = NULL;
+               list += count;
                cur_index++;
        }
 
-       if (!node) {
-               /*
-                * args w/o node indicates that the loop above has stopped at
-                * the 'hole' cell. Report this differently.
-                */
-               if (args)
-                       ret = -EEXIST;
-               else
-                       ret = -ENOENT;
-               goto err0;
+       /*
+        * Unlock node before returning result; will be one of:
+        * -ENOENT : index is for empty phandle
+        * -EINVAL : parsing error on data
+        * [1..n]  : Number of phandle (count mode; when index = -1)
+        */
+       rc = index < 0 ? cur_index : -ENOENT;
+ err:
+       if (node)
+               of_node_put(node);
+       return rc;
+}
+
+int of_parse_phandle_with_args(const struct device_node *np, const char *list_name,
+                               const char *cells_name, int index,
+                               struct of_phandle_args *out_args)
+{
+       if (index < 0)
+               return -EINVAL;
+       return __of_parse_phandle_with_args(np, list_name, cells_name, index, out_args);
+}
+EXPORT_SYMBOL(of_parse_phandle_with_args);
+
+/**
+ * of_count_phandle_with_args() - Find the number of phandles references in a property
+ * @np:                pointer to a device tree node containing a list
+ * @list_name: property name that contains a list
+ * @cells_name:        property name that specifies phandles' arguments count
+ *
+ * Returns the number of phandle + argument tuples within a property. It
+ * is a typical pattern to encode a list of phandle and variable
+ * arguments into a single property. The number of arguments is encoded
+ * by a property in the phandle-target node. For example, a gpios
+ * property would contain a list of GPIO specifies consisting of a
+ * phandle and 1 or more arguments. The number of arguments are
+ * determined by the #gpio-cells property in the node pointed to by the
+ * phandle.
+ */
+int of_count_phandle_with_args(const struct device_node *np, const char *list_name,
+                               const char *cells_name)
+{
+       return __of_parse_phandle_with_args(np, list_name, cells_name, -1, NULL);
+}
+EXPORT_SYMBOL(of_count_phandle_with_args);
+
+#if defined(CONFIG_OF_DYNAMIC)
+static int of_property_notify(int action, struct device_node *np,
+                             struct property *prop)
+{
+       struct of_prop_reconfig pr;
+
+       pr.dn = np;
+       pr.prop = prop;
+       return of_reconfig_notify(action, &pr);
+}
+#else
+static int of_property_notify(int action, struct device_node *np,
+                             struct property *prop)
+{
+       return 0;
+}
+#endif
+
+/**
+ * of_add_property - Add a property to a node
+ */
+int of_add_property(struct device_node *np, struct property *prop)
+{
+       struct property **next;
+       unsigned long flags;
+       int rc;
+
+       rc = of_property_notify(OF_RECONFIG_ADD_PROPERTY, np, prop);
+       if (rc)
+               return rc;
+
+       prop->next = NULL;
+       raw_spin_lock_irqsave(&devtree_lock, flags);
+       next = &np->properties;
+       while (*next) {
+               if (strcmp(prop->name, (*next)->name) == 0) {
+                       /* duplicate ! don't insert it */
+                       raw_spin_unlock_irqrestore(&devtree_lock, flags);
+                       return -1;
+               }
+               next = &(*next)->next;
        }
+       *next = prop;
+       raw_spin_unlock_irqrestore(&devtree_lock, flags);
 
-       if (out_node)
-               *out_node = node;
-       if (out_args)
-               *out_args = args;
+#ifdef CONFIG_PROC_DEVICETREE
+       /* try to add to proc as well if it was initialized */
+       if (np->pde)
+               proc_device_tree_add_prop(np->pde, prop);
+#endif /* CONFIG_PROC_DEVICETREE */
 
        return 0;
-err1:
-       of_node_put(node);
-err0:
-       pr_debug("%s failed with status %d\n", __func__, ret);
-       return ret;
 }
-EXPORT_SYMBOL(of_parse_phandles_with_args);
+
+/**
+ * of_remove_property - Remove a property from a node.
+ *
+ * Note that we don't actually remove it, since we have given out
+ * who-knows-how-many pointers to the data using get-property.
+ * Instead we just move the property to the "dead properties"
+ * list, so it won't be found any more.
+ */
+int of_remove_property(struct device_node *np, struct property *prop)
+{
+       struct property **next;
+       unsigned long flags;
+       int found = 0;
+       int rc;
+
+       rc = of_property_notify(OF_RECONFIG_REMOVE_PROPERTY, np, prop);
+       if (rc)
+               return rc;
+
+       raw_spin_lock_irqsave(&devtree_lock, flags);
+       next = &np->properties;
+       while (*next) {
+               if (*next == prop) {
+                       /* found the node */
+                       *next = prop->next;
+                       prop->next = np->deadprops;
+                       np->deadprops = prop;
+                       found = 1;
+                       break;
+               }
+               next = &(*next)->next;
+       }
+       raw_spin_unlock_irqrestore(&devtree_lock, flags);
+
+       if (!found)
+               return -ENODEV;
+
+#ifdef CONFIG_PROC_DEVICETREE
+       /* try to remove the proc node as well */
+       if (np->pde)
+               proc_device_tree_remove_prop(np->pde, prop);
+#endif /* CONFIG_PROC_DEVICETREE */
+
+       return 0;
+}
+
+/*
+ * of_update_property - Update a property in a node, if the property does
+ * not exist, add it.
+ *
+ * Note that we don't actually remove it, since we have given out
+ * who-knows-how-many pointers to the data using get-property.
+ * Instead we just move the property to the "dead properties" list,
+ * and add the new property to the property list
+ */
+int of_update_property(struct device_node *np, struct property *newprop)
+{
+       struct property **next, *oldprop;
+       unsigned long flags;
+       int rc, found = 0;
+
+       rc = of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop);
+       if (rc)
+               return rc;
+
+       if (!newprop->name)
+               return -EINVAL;
+
+       oldprop = of_find_property(np, newprop->name, NULL);
+       if (!oldprop)
+               return of_add_property(np, newprop);
+
+       raw_spin_lock_irqsave(&devtree_lock, flags);
+       next = &np->properties;
+       while (*next) {
+               if (*next == oldprop) {
+                       /* found the node */
+                       newprop->next = oldprop->next;
+                       *next = newprop;
+                       oldprop->next = np->deadprops;
+                       np->deadprops = oldprop;
+                       found = 1;
+                       break;
+               }
+               next = &(*next)->next;
+       }
+       raw_spin_unlock_irqrestore(&devtree_lock, flags);
+
+       if (!found)
+               return -ENODEV;
+
+#ifdef CONFIG_PROC_DEVICETREE
+       /* try to add to proc as well if it was initialized */
+       if (np->pde)
+               proc_device_tree_update_prop(np->pde, newprop, oldprop);
+#endif /* CONFIG_PROC_DEVICETREE */
+
+       return 0;
+}
+
+#if defined(CONFIG_OF_DYNAMIC)
+/*
+ * Support for dynamic device trees.
+ *
+ * On some platforms, the device tree can be manipulated at runtime.
+ * The routines in this section support adding, removing and changing
+ * device tree nodes.
+ */
+
+static BLOCKING_NOTIFIER_HEAD(of_reconfig_chain);
+
+int of_reconfig_notifier_register(struct notifier_block *nb)
+{
+       return blocking_notifier_chain_register(&of_reconfig_chain, nb);
+}
+EXPORT_SYMBOL_GPL(of_reconfig_notifier_register);
+
+int of_reconfig_notifier_unregister(struct notifier_block *nb)
+{
+       return blocking_notifier_chain_unregister(&of_reconfig_chain, nb);
+}
+EXPORT_SYMBOL_GPL(of_reconfig_notifier_unregister);
+
+int of_reconfig_notify(unsigned long action, void *p)
+{
+       int rc;
+
+       rc = blocking_notifier_call_chain(&of_reconfig_chain, action, p);
+       return notifier_to_errno(rc);
+}
+
+#ifdef CONFIG_PROC_DEVICETREE
+static void of_add_proc_dt_entry(struct device_node *dn)
+{
+       struct proc_dir_entry *ent;
+
+       ent = proc_mkdir(strrchr(dn->full_name, '/') + 1, dn->parent->pde);
+       if (ent)
+               proc_device_tree_add_node(dn, ent);
+}
+#else
+static void of_add_proc_dt_entry(struct device_node *dn)
+{
+       return;
+}
+#endif
+
+/**
+ * of_attach_node - Plug a device node into the tree and global list.
+ */
+int of_attach_node(struct device_node *np)
+{
+       unsigned long flags;
+       int rc;
+
+       rc = of_reconfig_notify(OF_RECONFIG_ATTACH_NODE, np);
+       if (rc)
+               return rc;
+
+       raw_spin_lock_irqsave(&devtree_lock, flags);
+       np->sibling = np->parent->child;
+       np->allnext = of_allnodes;
+       np->parent->child = np;
+       of_allnodes = np;
+       raw_spin_unlock_irqrestore(&devtree_lock, flags);
+
+       of_add_proc_dt_entry(np);
+       return 0;
+}
+
+#ifdef CONFIG_PROC_DEVICETREE
+static void of_remove_proc_dt_entry(struct device_node *dn)
+{
+       struct device_node *parent = dn->parent;
+       struct property *prop = dn->properties;
+
+       while (prop) {
+               remove_proc_entry(prop->name, dn->pde);
+               prop = prop->next;
+       }
+
+       if (dn->pde)
+               remove_proc_entry(dn->pde->name, parent->pde);
+}
+#else
+static void of_remove_proc_dt_entry(struct device_node *dn)
+{
+       return;
+}
+#endif
+
+/**
+ * of_detach_node - "Unplug" a node from the device tree.
+ *
+ * The caller must hold a reference to the node.  The memory associated with
+ * the node is not freed until its refcount goes to zero.
+ */
+int of_detach_node(struct device_node *np)
+{
+       struct device_node *parent;
+       unsigned long flags;
+       int rc = 0;
+
+       rc = of_reconfig_notify(OF_RECONFIG_DETACH_NODE, np);
+       if (rc)
+               return rc;
+
+       raw_spin_lock_irqsave(&devtree_lock, flags);
+
+       if (of_node_check_flag(np, OF_DETACHED)) {
+               /* someone already detached it */
+               raw_spin_unlock_irqrestore(&devtree_lock, flags);
+               return rc;
+       }
+
+       parent = np->parent;
+       if (!parent) {
+               raw_spin_unlock_irqrestore(&devtree_lock, flags);
+               return rc;
+       }
+
+       if (of_allnodes == np)
+               of_allnodes = np->allnext;
+       else {
+               struct device_node *prev;
+               for (prev = of_allnodes;
+                    prev->allnext != np;
+                    prev = prev->allnext)
+                       ;
+               prev->allnext = np->allnext;
+       }
+
+       if (parent->child == np)
+               parent->child = np->sibling;
+       else {
+               struct device_node *prevsib;
+               for (prevsib = np->parent->child;
+                    prevsib->sibling != np;
+                    prevsib = prevsib->sibling)
+                       ;
+               prevsib->sibling = np->sibling;
+       }
+
+       of_node_set_flag(np, OF_DETACHED);
+       raw_spin_unlock_irqrestore(&devtree_lock, flags);
+
+       of_remove_proc_dt_entry(np);
+       return rc;
+}
+#endif /* defined(CONFIG_OF_DYNAMIC) */
+
+static void of_alias_add(struct alias_prop *ap, struct device_node *np,
+                        int id, const char *stem, int stem_len)
+{
+       ap->np = np;
+       ap->id = id;
+       strncpy(ap->stem, stem, stem_len);
+       ap->stem[stem_len] = 0;
+       list_add_tail(&ap->link, &aliases_lookup);
+       pr_debug("adding DT alias:%s: stem=%s id=%i node=%s\n",
+                ap->alias, ap->stem, ap->id, of_node_full_name(np));
+}
+
+/**
+ * of_alias_scan - Scan all properties of '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.
+ *
+ * @dt_alloc:  An allocator that provides a virtual address to memory
+ *             for the resulting tree
+ */
+void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
+{
+       struct property *pp;
+
+       of_chosen = of_find_node_by_path("/chosen");
+       if (of_chosen == NULL)
+               of_chosen = of_find_node_by_path("/chosen@0");
+       of_aliases = of_find_node_by_path("/aliases");
+       if (!of_aliases)
+               return;
+
+       for_each_property_of_node(of_aliases, pp) {
+               const char *start = pp->name;
+               const char *end = start + strlen(start);
+               struct device_node *np;
+               struct alias_prop *ap;
+               int id, len;
+
+               /* Skip those we do not want to proceed */
+               if (!strcmp(pp->name, "name") ||
+                   !strcmp(pp->name, "phandle") ||
+                   !strcmp(pp->name, "linux,phandle"))
+                       continue;
+
+               np = of_find_node_by_path(pp->value);
+               if (!np)
+                       continue;
+
+               /* walk the alias backwards to extract the id and work out
+                * the 'stem' string */
+               while (isdigit(*(end-1)) && end > start)
+                       end--;
+               len = end - start;
+
+               if (kstrtoint(end, 10, &id) < 0)
+                       continue;
+
+               /* Allocate an alias_prop with enough space for the stem */
+               ap = dt_alloc(sizeof(*ap) + len + 1, 4);
+               if (!ap)
+                       continue;
+               ap->alias = start;
+               of_alias_add(ap, np, id, start, len);
+       }
+}
+
+/**
+ * of_alias_get_id - Get alias id for the given device_node
+ * @np:                Pointer to the given device_node
+ * @stem:      Alias stem of the given device_node
+ *
+ * The function travels the lookup table to get alias id for the given
+ * device_node and alias stem.  It returns the alias id if find it.
+ */
+int of_alias_get_id(struct device_node *np, const char *stem)
+{
+       struct alias_prop *app;
+       int id = -ENODEV;
+
+       mutex_lock(&of_aliases_mutex);
+       list_for_each_entry(app, &aliases_lookup, link) {
+               if (strcmp(app->stem, stem) != 0)
+                       continue;
+
+               if (np == app->np) {
+                       id = app->id;
+                       break;
+               }
+       }
+       mutex_unlock(&of_aliases_mutex);
+
+       return id;
+}
+EXPORT_SYMBOL_GPL(of_alias_get_id);
+
+const __be32 *of_prop_next_u32(struct property *prop, const __be32 *cur,
+                              u32 *pu)
+{
+       const void *curv = cur;
+
+       if (!prop)
+               return NULL;
+
+       if (!cur) {
+               curv = prop->value;
+               goto out_val;
+       }
+
+       curv += sizeof(*cur);
+       if (curv >= prop->value + prop->length)
+               return NULL;
+
+out_val:
+       *pu = be32_to_cpup(curv);
+       return curv;
+}
+EXPORT_SYMBOL_GPL(of_prop_next_u32);
+
+const char *of_prop_next_string(struct property *prop, const char *cur)
+{
+       const void *curv = cur;
+
+       if (!prop)
+               return NULL;
+
+       if (!cur)
+               return prop->value;
+
+       curv += strlen(cur) + 1;
+       if (curv >= prop->value + prop->length)
+               return NULL;
+
+       return curv;
+}
+EXPORT_SYMBOL_GPL(of_prop_next_string);