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); |
