diff options
Diffstat (limited to 'drivers/of/base.c')
-rw-r--r-- | drivers/of/base.c | 128 |
1 files changed, 107 insertions, 21 deletions
diff --git a/drivers/of/base.c b/drivers/of/base.c index af3b22ac7627..538e3cfad23e 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c | |||
@@ -45,7 +45,8 @@ struct alias_prop { | |||
45 | 45 | ||
46 | static LIST_HEAD(aliases_lookup); | 46 | static LIST_HEAD(aliases_lookup); |
47 | 47 | ||
48 | struct device_node *allnodes; | 48 | struct device_node *of_allnodes; |
49 | EXPORT_SYMBOL(of_allnodes); | ||
49 | struct device_node *of_chosen; | 50 | struct device_node *of_chosen; |
50 | struct device_node *of_aliases; | 51 | struct device_node *of_aliases; |
51 | 52 | ||
@@ -199,7 +200,7 @@ struct device_node *of_find_all_nodes(struct device_node *prev) | |||
199 | struct device_node *np; | 200 | struct device_node *np; |
200 | 201 | ||
201 | read_lock(&devtree_lock); | 202 | read_lock(&devtree_lock); |
202 | np = prev ? prev->allnext : allnodes; | 203 | np = prev ? prev->allnext : of_allnodes; |
203 | for (; np != NULL; np = np->allnext) | 204 | for (; np != NULL; np = np->allnext) |
204 | if (of_node_get(np)) | 205 | if (of_node_get(np)) |
205 | break; | 206 | break; |
@@ -422,7 +423,7 @@ EXPORT_SYMBOL(of_get_child_by_name); | |||
422 | */ | 423 | */ |
423 | struct device_node *of_find_node_by_path(const char *path) | 424 | struct device_node *of_find_node_by_path(const char *path) |
424 | { | 425 | { |
425 | struct device_node *np = allnodes; | 426 | struct device_node *np = of_allnodes; |
426 | 427 | ||
427 | read_lock(&devtree_lock); | 428 | read_lock(&devtree_lock); |
428 | for (; np; np = np->allnext) { | 429 | for (; np; np = np->allnext) { |
@@ -452,7 +453,7 @@ struct device_node *of_find_node_by_name(struct device_node *from, | |||
452 | struct device_node *np; | 453 | struct device_node *np; |
453 | 454 | ||
454 | read_lock(&devtree_lock); | 455 | read_lock(&devtree_lock); |
455 | np = from ? from->allnext : allnodes; | 456 | np = from ? from->allnext : of_allnodes; |
456 | for (; np; np = np->allnext) | 457 | for (; np; np = np->allnext) |
457 | if (np->name && (of_node_cmp(np->name, name) == 0) | 458 | if (np->name && (of_node_cmp(np->name, name) == 0) |
458 | && of_node_get(np)) | 459 | && of_node_get(np)) |
@@ -481,7 +482,7 @@ struct device_node *of_find_node_by_type(struct device_node *from, | |||
481 | struct device_node *np; | 482 | struct device_node *np; |
482 | 483 | ||
483 | read_lock(&devtree_lock); | 484 | read_lock(&devtree_lock); |
484 | np = from ? from->allnext : allnodes; | 485 | np = from ? from->allnext : of_allnodes; |
485 | for (; np; np = np->allnext) | 486 | for (; np; np = np->allnext) |
486 | if (np->type && (of_node_cmp(np->type, type) == 0) | 487 | if (np->type && (of_node_cmp(np->type, type) == 0) |
487 | && of_node_get(np)) | 488 | && of_node_get(np)) |
@@ -512,7 +513,7 @@ struct device_node *of_find_compatible_node(struct device_node *from, | |||
512 | struct device_node *np; | 513 | struct device_node *np; |
513 | 514 | ||
514 | read_lock(&devtree_lock); | 515 | read_lock(&devtree_lock); |
515 | np = from ? from->allnext : allnodes; | 516 | np = from ? from->allnext : of_allnodes; |
516 | for (; np; np = np->allnext) { | 517 | for (; np; np = np->allnext) { |
517 | if (type | 518 | if (type |
518 | && !(np->type && (of_node_cmp(np->type, type) == 0))) | 519 | && !(np->type && (of_node_cmp(np->type, type) == 0))) |
@@ -545,7 +546,7 @@ struct device_node *of_find_node_with_property(struct device_node *from, | |||
545 | struct property *pp; | 546 | struct property *pp; |
546 | 547 | ||
547 | read_lock(&devtree_lock); | 548 | read_lock(&devtree_lock); |
548 | np = from ? from->allnext : allnodes; | 549 | np = from ? from->allnext : of_allnodes; |
549 | for (; np; np = np->allnext) { | 550 | for (; np; np = np->allnext) { |
550 | for (pp = np->properties; pp; pp = pp->next) { | 551 | for (pp = np->properties; pp; pp = pp->next) { |
551 | if (of_prop_cmp(pp->name, prop_name) == 0) { | 552 | if (of_prop_cmp(pp->name, prop_name) == 0) { |
@@ -594,27 +595,35 @@ const struct of_device_id *of_match_node(const struct of_device_id *matches, | |||
594 | EXPORT_SYMBOL(of_match_node); | 595 | EXPORT_SYMBOL(of_match_node); |
595 | 596 | ||
596 | /** | 597 | /** |
597 | * of_find_matching_node - Find a node based on an of_device_id match | 598 | * of_find_matching_node_and_match - Find a node based on an of_device_id |
598 | * table. | 599 | * match table. |
599 | * @from: The node to start searching from or NULL, the node | 600 | * @from: The node to start searching from or NULL, the node |
600 | * you pass will not be searched, only the next one | 601 | * you pass will not be searched, only the next one |
601 | * will; typically, you pass what the previous call | 602 | * will; typically, you pass what the previous call |
602 | * returned. of_node_put() will be called on it | 603 | * returned. of_node_put() will be called on it |
603 | * @matches: array of of device match structures to search in | 604 | * @matches: array of of device match structures to search in |
605 | * @match Updated to point at the matches entry which matched | ||
604 | * | 606 | * |
605 | * Returns a node pointer with refcount incremented, use | 607 | * Returns a node pointer with refcount incremented, use |
606 | * of_node_put() on it when done. | 608 | * of_node_put() on it when done. |
607 | */ | 609 | */ |
608 | struct device_node *of_find_matching_node(struct device_node *from, | 610 | struct device_node *of_find_matching_node_and_match(struct device_node *from, |
609 | const struct of_device_id *matches) | 611 | const struct of_device_id *matches, |
612 | const struct of_device_id **match) | ||
610 | { | 613 | { |
611 | struct device_node *np; | 614 | struct device_node *np; |
612 | 615 | ||
616 | if (match) | ||
617 | *match = NULL; | ||
618 | |||
613 | read_lock(&devtree_lock); | 619 | read_lock(&devtree_lock); |
614 | np = from ? from->allnext : allnodes; | 620 | np = from ? from->allnext : of_allnodes; |
615 | for (; np; np = np->allnext) { | 621 | for (; np; np = np->allnext) { |
616 | if (of_match_node(matches, np) && of_node_get(np)) | 622 | if (of_match_node(matches, np) && of_node_get(np)) { |
623 | if (match) | ||
624 | *match = matches; | ||
617 | break; | 625 | break; |
626 | } | ||
618 | } | 627 | } |
619 | of_node_put(from); | 628 | of_node_put(from); |
620 | read_unlock(&devtree_lock); | 629 | read_unlock(&devtree_lock); |
@@ -661,7 +670,7 @@ struct device_node *of_find_node_by_phandle(phandle handle) | |||
661 | struct device_node *np; | 670 | struct device_node *np; |
662 | 671 | ||
663 | read_lock(&devtree_lock); | 672 | read_lock(&devtree_lock); |
664 | for (np = allnodes; np; np = np->allnext) | 673 | for (np = of_allnodes; np; np = np->allnext) |
665 | if (np->phandle == handle) | 674 | if (np->phandle == handle) |
666 | break; | 675 | break; |
667 | of_node_get(np); | 676 | of_node_get(np); |
@@ -671,12 +680,89 @@ struct device_node *of_find_node_by_phandle(phandle handle) | |||
671 | EXPORT_SYMBOL(of_find_node_by_phandle); | 680 | EXPORT_SYMBOL(of_find_node_by_phandle); |
672 | 681 | ||
673 | /** | 682 | /** |
683 | * of_property_read_u8_array - Find and read an array of u8 from a property. | ||
684 | * | ||
685 | * @np: device node from which the property value is to be read. | ||
686 | * @propname: name of the property to be searched. | ||
687 | * @out_value: pointer to return value, modified only if return value is 0. | ||
688 | * @sz: number of array elements to read | ||
689 | * | ||
690 | * Search for a property in a device node and read 8-bit value(s) from | ||
691 | * it. Returns 0 on success, -EINVAL if the property does not exist, | ||
692 | * -ENODATA if property does not have a value, and -EOVERFLOW if the | ||
693 | * property data isn't large enough. | ||
694 | * | ||
695 | * dts entry of array should be like: | ||
696 | * property = /bits/ 8 <0x50 0x60 0x70>; | ||
697 | * | ||
698 | * The out_value is modified only if a valid u8 value can be decoded. | ||
699 | */ | ||
700 | int of_property_read_u8_array(const struct device_node *np, | ||
701 | const char *propname, u8 *out_values, size_t sz) | ||
702 | { | ||
703 | struct property *prop = of_find_property(np, propname, NULL); | ||
704 | const u8 *val; | ||
705 | |||
706 | if (!prop) | ||
707 | return -EINVAL; | ||
708 | if (!prop->value) | ||
709 | return -ENODATA; | ||
710 | if ((sz * sizeof(*out_values)) > prop->length) | ||
711 | return -EOVERFLOW; | ||
712 | |||
713 | val = prop->value; | ||
714 | while (sz--) | ||
715 | *out_values++ = *val++; | ||
716 | return 0; | ||
717 | } | ||
718 | EXPORT_SYMBOL_GPL(of_property_read_u8_array); | ||
719 | |||
720 | /** | ||
721 | * of_property_read_u16_array - Find and read an array of u16 from a property. | ||
722 | * | ||
723 | * @np: device node from which the property value is to be read. | ||
724 | * @propname: name of the property to be searched. | ||
725 | * @out_value: pointer to return value, modified only if return value is 0. | ||
726 | * @sz: number of array elements to read | ||
727 | * | ||
728 | * Search for a property in a device node and read 16-bit value(s) from | ||
729 | * it. Returns 0 on success, -EINVAL if the property does not exist, | ||
730 | * -ENODATA if property does not have a value, and -EOVERFLOW if the | ||
731 | * property data isn't large enough. | ||
732 | * | ||
733 | * dts entry of array should be like: | ||
734 | * property = /bits/ 16 <0x5000 0x6000 0x7000>; | ||
735 | * | ||
736 | * The out_value is modified only if a valid u16 value can be decoded. | ||
737 | */ | ||
738 | int of_property_read_u16_array(const struct device_node *np, | ||
739 | const char *propname, u16 *out_values, size_t sz) | ||
740 | { | ||
741 | struct property *prop = of_find_property(np, propname, NULL); | ||
742 | const __be16 *val; | ||
743 | |||
744 | if (!prop) | ||
745 | return -EINVAL; | ||
746 | if (!prop->value) | ||
747 | return -ENODATA; | ||
748 | if ((sz * sizeof(*out_values)) > prop->length) | ||
749 | return -EOVERFLOW; | ||
750 | |||
751 | val = prop->value; | ||
752 | while (sz--) | ||
753 | *out_values++ = be16_to_cpup(val++); | ||
754 | return 0; | ||
755 | } | ||
756 | EXPORT_SYMBOL_GPL(of_property_read_u16_array); | ||
757 | |||
758 | /** | ||
674 | * of_property_read_u32_array - Find and read an array of 32 bit integers | 759 | * of_property_read_u32_array - Find and read an array of 32 bit integers |
675 | * from a property. | 760 | * from a property. |
676 | * | 761 | * |
677 | * @np: device node from which the property value is to be read. | 762 | * @np: device node from which the property value is to be read. |
678 | * @propname: name of the property to be searched. | 763 | * @propname: name of the property to be searched. |
679 | * @out_value: pointer to return value, modified only if return value is 0. | 764 | * @out_value: pointer to return value, modified only if return value is 0. |
765 | * @sz: number of array elements to read | ||
680 | * | 766 | * |
681 | * Search for a property in a device node and read 32-bit value(s) from | 767 | * Search for a property in a device node and read 32-bit value(s) from |
682 | * it. Returns 0 on success, -EINVAL if the property does not exist, | 768 | * it. Returns 0 on success, -EINVAL if the property does not exist, |
@@ -893,8 +979,8 @@ EXPORT_SYMBOL_GPL(of_property_count_strings); | |||
893 | * Returns the device_node pointer with refcount incremented. Use | 979 | * Returns the device_node pointer with refcount incremented. Use |
894 | * of_node_put() on it when done. | 980 | * of_node_put() on it when done. |
895 | */ | 981 | */ |
896 | struct device_node * | 982 | struct device_node *of_parse_phandle(const struct device_node *np, |
897 | of_parse_phandle(struct device_node *np, const char *phandle_name, int index) | 983 | const char *phandle_name, int index) |
898 | { | 984 | { |
899 | const __be32 *phandle; | 985 | const __be32 *phandle; |
900 | int size; | 986 | int size; |
@@ -1169,9 +1255,9 @@ void of_attach_node(struct device_node *np) | |||
1169 | 1255 | ||
1170 | write_lock_irqsave(&devtree_lock, flags); | 1256 | write_lock_irqsave(&devtree_lock, flags); |
1171 | np->sibling = np->parent->child; | 1257 | np->sibling = np->parent->child; |
1172 | np->allnext = allnodes; | 1258 | np->allnext = of_allnodes; |
1173 | np->parent->child = np; | 1259 | np->parent->child = np; |
1174 | allnodes = np; | 1260 | of_allnodes = np; |
1175 | write_unlock_irqrestore(&devtree_lock, flags); | 1261 | write_unlock_irqrestore(&devtree_lock, flags); |
1176 | } | 1262 | } |
1177 | 1263 | ||
@@ -1192,11 +1278,11 @@ void of_detach_node(struct device_node *np) | |||
1192 | if (!parent) | 1278 | if (!parent) |
1193 | goto out_unlock; | 1279 | goto out_unlock; |
1194 | 1280 | ||
1195 | if (allnodes == np) | 1281 | if (of_allnodes == np) |
1196 | allnodes = np->allnext; | 1282 | of_allnodes = np->allnext; |
1197 | else { | 1283 | else { |
1198 | struct device_node *prev; | 1284 | struct device_node *prev; |
1199 | for (prev = allnodes; | 1285 | for (prev = of_allnodes; |
1200 | prev->allnext != np; | 1286 | prev->allnext != np; |
1201 | prev = prev->allnext) | 1287 | prev = prev->allnext) |
1202 | ; | 1288 | ; |