aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/of/base.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/of/base.c')
-rw-r--r--drivers/of/base.c111
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)
746EXPORT_SYMBOL(of_find_node_by_phandle); 746EXPORT_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 */
761static 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 */
791int 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}
804EXPORT_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);
766int of_property_read_u8_array(const struct device_node *np, 824int 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);
804int of_property_read_u16_array(const struct device_node *np, 857int 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);
874int of_property_read_u64(const struct device_node *np, const char *propname, 917int 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}
888EXPORT_SYMBOL_GPL(of_property_read_u64); 929EXPORT_SYMBOL_GPL(of_property_read_u64);