diff options
-rw-r--r-- | drivers/of/fdt.c | 76 | ||||
-rw-r--r-- | include/linux/of_fdt.h | 3 |
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 | ||
546 | struct 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 | */ | ||
558 | static 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 | */ | ||
604 | int __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, | |||
90 | extern int of_flat_dt_is_compatible(unsigned long node, const char *name); | 90 | extern int of_flat_dt_is_compatible(unsigned long node, const char *name); |
91 | extern int of_flat_dt_match(unsigned long node, const char *const *matches); | 91 | extern int of_flat_dt_match(unsigned long node, const char *const *matches); |
92 | extern unsigned long of_get_flat_dt_root(void); | 92 | extern unsigned long of_get_flat_dt_root(void); |
93 | extern 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 | ||
94 | extern int early_init_dt_scan_chosen(unsigned long node, const char *uname, | 97 | extern int early_init_dt_scan_chosen(unsigned long node, const char *uname, |
95 | int depth, void *data); | 98 | int depth, void *data); |