OSDN Git Service

Merge branch 'for-v3.12' of git://git.linaro.org/people/mszyprowski/linux-dma-mapping
[sagit-ice-cold/kernel_xiaomi_msm8998.git] / drivers / of / fdt.c
index b10ba00..4fb06f3 100644 (file)
@@ -545,6 +545,82 @@ int __init of_flat_dt_match(unsigned long node, const char *const *compat)
        return of_fdt_match(initial_boot_params, node, compat);
 }
 
+struct fdt_scan_status {
+       const char *name;
+       int namelen;
+       int depth;
+       int found;
+       int (*iterator)(unsigned long node, const char *uname, int depth, void *data);
+       void *data;
+};
+
+/**
+ * fdt_scan_node_by_path - iterator for of_scan_flat_dt_by_path function
+ */
+static int __init fdt_scan_node_by_path(unsigned long node, const char *uname,
+                                       int depth, void *data)
+{
+       struct fdt_scan_status *st = data;
+
+       /*
+        * if scan at the requested fdt node has been completed,
+        * return -ENXIO to abort further scanning
+        */
+       if (depth <= st->depth)
+               return -ENXIO;
+
+       /* requested fdt node has been found, so call iterator function */
+       if (st->found)
+               return st->iterator(node, uname, depth, st->data);
+
+       /* check if scanning automata is entering next level of fdt nodes */
+       if (depth == st->depth + 1 &&
+           strncmp(st->name, uname, st->namelen) == 0 &&
+           uname[st->namelen] == 0) {
+               st->depth += 1;
+               if (st->name[st->namelen] == 0) {
+                       st->found = 1;
+               } else {
+                       const char *next = st->name + st->namelen + 1;
+                       st->name = next;
+                       st->namelen = strcspn(next, "/");
+               }
+               return 0;
+       }
+
+       /* scan next fdt node */
+       return 0;
+}
+
+/**
+ * of_scan_flat_dt_by_path - scan flattened tree blob and call callback on each
+ *                          child of the given path.
+ * @path: path to start searching for children
+ * @it: callback function
+ * @data: context data pointer
+ *
+ * This function is used to scan the flattened device-tree starting from the
+ * node given by path. It is used to extract information (like reserved
+ * memory), which is required on ealy boot before we can unflatten the tree.
+ */
+int __init of_scan_flat_dt_by_path(const char *path,
+       int (*it)(unsigned long node, const char *name, int depth, void *data),
+       void *data)
+{
+       struct fdt_scan_status st = {path, 0, -1, 0, it, data};
+       int ret = 0;
+
+       if (initial_boot_params)
+                ret = of_scan_flat_dt(fdt_scan_node_by_path, &st);
+
+       if (!st.found)
+               return -ENOENT;
+       else if (ret == -ENXIO) /* scan has been completed */
+               return 0;
+       else
+               return ret;
+}
+
 #ifdef CONFIG_BLK_DEV_INITRD
 /**
  * early_init_dt_check_for_initrd - Decode initrd location from flat tree