diff options
Diffstat (limited to 'drivers/of/base.c')
-rw-r--r-- | drivers/of/base.c | 111 |
1 files changed, 76 insertions, 35 deletions
diff --git a/drivers/of/base.c b/drivers/of/base.c index 321d3ef05006..c6443de58fb0 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c | |||
@@ -746,6 +746,64 @@ struct device_node *of_find_node_by_phandle(phandle handle) | |||
746 | EXPORT_SYMBOL(of_find_node_by_phandle); | 746 | EXPORT_SYMBOL(of_find_node_by_phandle); |
747 | 747 | ||
748 | /** | 748 | /** |
749 | * of_find_property_value_of_size | ||
750 | * | ||
751 | * @np: device node from which the property value is to be read. | ||
752 | * @propname: name of the property to be searched. | ||
753 | * @len: requested length of property value | ||
754 | * | ||
755 | * Search for a property in a device node and valid the requested size. | ||
756 | * Returns the property value on success, -EINVAL if the property does not | ||
757 | * exist, -ENODATA if property does not have a value, and -EOVERFLOW if the | ||
758 | * property data isn't large enough. | ||
759 | * | ||
760 | */ | ||
761 | static void *of_find_property_value_of_size(const struct device_node *np, | ||
762 | const char *propname, u32 len) | ||
763 | { | ||
764 | struct property *prop = of_find_property(np, propname, NULL); | ||
765 | |||
766 | if (!prop) | ||
767 | return ERR_PTR(-EINVAL); | ||
768 | if (!prop->value) | ||
769 | return ERR_PTR(-ENODATA); | ||
770 | if (len > prop->length) | ||
771 | return ERR_PTR(-EOVERFLOW); | ||
772 | |||
773 | return prop->value; | ||
774 | } | ||
775 | |||
776 | /** | ||
777 | * of_property_read_u32_index - Find and read a u32 from a multi-value property. | ||
778 | * | ||
779 | * @np: device node from which the property value is to be read. | ||
780 | * @propname: name of the property to be searched. | ||
781 | * @index: index of the u32 in the list of values | ||
782 | * @out_value: pointer to return value, modified only if no error. | ||
783 | * | ||
784 | * Search for a property in a device node and read nth 32-bit value from | ||
785 | * it. Returns 0 on success, -EINVAL if the property does not exist, | ||
786 | * -ENODATA if property does not have a value, and -EOVERFLOW if the | ||
787 | * property data isn't large enough. | ||
788 | * | ||
789 | * The out_value is modified only if a valid u32 value can be decoded. | ||
790 | */ | ||
791 | int of_property_read_u32_index(const struct device_node *np, | ||
792 | const char *propname, | ||
793 | u32 index, u32 *out_value) | ||
794 | { | ||
795 | const u32 *val = of_find_property_value_of_size(np, propname, | ||
796 | ((index + 1) * sizeof(*out_value))); | ||
797 | |||
798 | if (IS_ERR(val)) | ||
799 | return PTR_ERR(val); | ||
800 | |||
801 | *out_value = be32_to_cpup(((__be32 *)val) + index); | ||
802 | return 0; | ||
803 | } | ||
804 | EXPORT_SYMBOL_GPL(of_property_read_u32_index); | ||
805 | |||
806 | /** | ||
749 | * of_property_read_u8_array - Find and read an array of u8 from a property. | 807 | * of_property_read_u8_array - Find and read an array of u8 from a property. |
750 | * | 808 | * |
751 | * @np: device node from which the property value is to be read. | 809 | * @np: device node from which the property value is to be read. |
@@ -766,17 +824,12 @@ EXPORT_SYMBOL(of_find_node_by_phandle); | |||
766 | int of_property_read_u8_array(const struct device_node *np, | 824 | int of_property_read_u8_array(const struct device_node *np, |
767 | const char *propname, u8 *out_values, size_t sz) | 825 | const char *propname, u8 *out_values, size_t sz) |
768 | { | 826 | { |
769 | struct property *prop = of_find_property(np, propname, NULL); | 827 | const u8 *val = of_find_property_value_of_size(np, propname, |
770 | const u8 *val; | 828 | (sz * sizeof(*out_values))); |
771 | 829 | ||
772 | if (!prop) | 830 | if (IS_ERR(val)) |
773 | return -EINVAL; | 831 | return PTR_ERR(val); |
774 | if (!prop->value) | ||
775 | return -ENODATA; | ||
776 | if ((sz * sizeof(*out_values)) > prop->length) | ||
777 | return -EOVERFLOW; | ||
778 | 832 | ||
779 | val = prop->value; | ||
780 | while (sz--) | 833 | while (sz--) |
781 | *out_values++ = *val++; | 834 | *out_values++ = *val++; |
782 | return 0; | 835 | return 0; |
@@ -804,17 +857,12 @@ EXPORT_SYMBOL_GPL(of_property_read_u8_array); | |||
804 | int of_property_read_u16_array(const struct device_node *np, | 857 | int of_property_read_u16_array(const struct device_node *np, |
805 | const char *propname, u16 *out_values, size_t sz) | 858 | const char *propname, u16 *out_values, size_t sz) |
806 | { | 859 | { |
807 | struct property *prop = of_find_property(np, propname, NULL); | 860 | const __be16 *val = of_find_property_value_of_size(np, propname, |
808 | const __be16 *val; | 861 | (sz * sizeof(*out_values))); |
809 | 862 | ||
810 | if (!prop) | 863 | if (IS_ERR(val)) |
811 | return -EINVAL; | 864 | return PTR_ERR(val); |
812 | if (!prop->value) | ||
813 | return -ENODATA; | ||
814 | if ((sz * sizeof(*out_values)) > prop->length) | ||
815 | return -EOVERFLOW; | ||
816 | 865 | ||
817 | val = prop->value; | ||
818 | while (sz--) | 866 | while (sz--) |
819 | *out_values++ = be16_to_cpup(val++); | 867 | *out_values++ = be16_to_cpup(val++); |
820 | return 0; | 868 | return 0; |
@@ -841,17 +889,12 @@ int of_property_read_u32_array(const struct device_node *np, | |||
841 | const char *propname, u32 *out_values, | 889 | const char *propname, u32 *out_values, |
842 | size_t sz) | 890 | size_t sz) |
843 | { | 891 | { |
844 | struct property *prop = of_find_property(np, propname, NULL); | 892 | const __be32 *val = of_find_property_value_of_size(np, propname, |
845 | const __be32 *val; | 893 | (sz * sizeof(*out_values))); |
846 | 894 | ||
847 | if (!prop) | 895 | if (IS_ERR(val)) |
848 | return -EINVAL; | 896 | return PTR_ERR(val); |
849 | if (!prop->value) | ||
850 | return -ENODATA; | ||
851 | if ((sz * sizeof(*out_values)) > prop->length) | ||
852 | return -EOVERFLOW; | ||
853 | 897 | ||
854 | val = prop->value; | ||
855 | while (sz--) | 898 | while (sz--) |
856 | *out_values++ = be32_to_cpup(val++); | 899 | *out_values++ = be32_to_cpup(val++); |
857 | return 0; | 900 | return 0; |
@@ -874,15 +917,13 @@ EXPORT_SYMBOL_GPL(of_property_read_u32_array); | |||
874 | int of_property_read_u64(const struct device_node *np, const char *propname, | 917 | int of_property_read_u64(const struct device_node *np, const char *propname, |
875 | u64 *out_value) | 918 | u64 *out_value) |
876 | { | 919 | { |
877 | struct property *prop = of_find_property(np, propname, NULL); | 920 | const __be32 *val = of_find_property_value_of_size(np, propname, |
921 | sizeof(*out_value)); | ||
878 | 922 | ||
879 | if (!prop) | 923 | if (IS_ERR(val)) |
880 | return -EINVAL; | 924 | return PTR_ERR(val); |
881 | if (!prop->value) | 925 | |
882 | return -ENODATA; | 926 | *out_value = of_read_number(val, 2); |
883 | if (sizeof(*out_value) > prop->length) | ||
884 | return -EOVERFLOW; | ||
885 | *out_value = of_read_number(prop->value, 2); | ||
886 | return 0; | 927 | return 0; |
887 | } | 928 | } |
888 | EXPORT_SYMBOL_GPL(of_property_read_u64); | 929 | EXPORT_SYMBOL_GPL(of_property_read_u64); |