aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/of/fdt.c76
-rw-r--r--include/linux/of_fdt.h3
2 files changed, 79 insertions, 0 deletions
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 6bb7cf2de556..585b1a67cfbe 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -543,6 +543,82 @@ int __init of_flat_dt_match(unsigned long node, const char *const *compat)
543 return of_fdt_match(initial_boot_params, node, compat); 543 return of_fdt_match(initial_boot_params, node, compat);
544} 544}
545 545
546struct fdt_scan_status {
547 const char *name;
548 int namelen;
549 int depth;
550 int found;
551 int (*iterator)(unsigned long node, const char *uname, int depth, void *data);
552 void *data;
553};
554
555/**
556 * fdt_scan_node_by_path - iterator for of_scan_flat_dt_by_path function
557 */
558static int __init fdt_scan_node_by_path(unsigned long node, const char *uname,
559 int depth, void *data)
560{
561 struct fdt_scan_status *st = data;
562
563 /*
564 * if scan at the requested fdt node has been completed,
565 * return -ENXIO to abort further scanning
566 */
567 if (depth <= st->depth)
568 return -ENXIO;
569
570 /* requested fdt node has been found, so call iterator function */
571 if (st->found)
572 return st->iterator(node, uname, depth, st->data);
573
574 /* check if scanning automata is entering next level of fdt nodes */
575 if (depth == st->depth + 1 &&
576 strncmp(st->name, uname, st->namelen) == 0 &&
577 uname[st->namelen] == 0) {
578 st->depth += 1;
579 if (st->name[st->namelen] == 0) {
580 st->found = 1;
581 } else {
582 const char *next = st->name + st->namelen + 1;
583 st->name = next;
584 st->namelen = strcspn(next, "/");
585 }
586 return 0;
587 }
588
589 /* scan next fdt node */
590 return 0;
591}
592
593/**
594 * of_scan_flat_dt_by_path - scan flattened tree blob and call callback on each
595 * child of the given path.
596 * @path: path to start searching for children
597 * @it: callback function
598 * @data: context data pointer
599 *
600 * This function is used to scan the flattened device-tree starting from the
601 * node given by path. It is used to extract information (like reserved
602 * memory), which is required on ealy boot before we can unflatten the tree.
603 */
604int __init of_scan_flat_dt_by_path(const char *path,
605 int (*it)(unsigned long node, const char *name, int depth, void *data),
606 void *data)
607{
608 struct fdt_scan_status st = {path, 0, -1, 0, it, data};
609 int ret = 0;
610
611 if (initial_boot_params)
612 ret = of_scan_flat_dt(fdt_scan_node_by_path, &st);
613
614 if (!st.found)
615 return -ENOENT;
616 else if (ret == -ENXIO) /* scan has been completed */
617 return 0;
618 else
619 return ret;
620}
621
546#ifdef CONFIG_BLK_DEV_INITRD 622#ifdef CONFIG_BLK_DEV_INITRD
547/** 623/**
548 * early_init_dt_check_for_initrd - Decode initrd location from flat tree 624 * early_init_dt_check_for_initrd - Decode initrd location from flat tree
diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h
index ed136ad698ce..19f26f8d2202 100644
--- a/include/linux/of_fdt.h
+++ b/include/linux/of_fdt.h
@@ -90,6 +90,9 @@ extern void *of_get_flat_dt_prop(unsigned long node, const char *name,
90extern int of_flat_dt_is_compatible(unsigned long node, const char *name); 90extern int of_flat_dt_is_compatible(unsigned long node, const char *name);
91extern int of_flat_dt_match(unsigned long node, const char *const *matches); 91extern int of_flat_dt_match(unsigned long node, const char *const *matches);
92extern unsigned long of_get_flat_dt_root(void); 92extern unsigned long of_get_flat_dt_root(void);
93extern int of_scan_flat_dt_by_path(const char *path,
94 int (*it)(unsigned long node, const char *name, int depth, void *data),
95 void *data);
93 96
94extern int early_init_dt_scan_chosen(unsigned long node, const char *uname, 97extern int early_init_dt_scan_chosen(unsigned long node, const char *uname,
95 int depth, void *data); 98 int depth, void *data);