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 321d3ef0500..c6443de58fb 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)  EXPORT_SYMBOL(of_find_node_by_phandle);  /** + * of_find_property_value_of_size + * + * @np:		device node from which the property value is to be read. + * @propname:	name of the property to be searched. + * @len:	requested length of property value + * + * Search for a property in a device node and valid the requested size. + * Returns the property value on success, -EINVAL if the property does not + *  exist, -ENODATA if property does not have a value, and -EOVERFLOW if the + * property data isn't large enough. + * + */ +static void *of_find_property_value_of_size(const struct device_node *np, +			const char *propname, u32 len) +{ +	struct property *prop = of_find_property(np, propname, NULL); + +	if (!prop) +		return ERR_PTR(-EINVAL); +	if (!prop->value) +		return ERR_PTR(-ENODATA); +	if (len > prop->length) +		return ERR_PTR(-EOVERFLOW); + +	return prop->value; +} + +/** + * of_property_read_u32_index - Find and read a u32 from a multi-value property. + * + * @np:		device node from which the property value is to be read. + * @propname:	name of the property to be searched. + * @index:	index of the u32 in the list of values + * @out_value:	pointer to return value, modified only if no error. + * + * Search for a property in a device node and read nth 32-bit value from + * it. Returns 0 on success, -EINVAL if the property does not exist, + * -ENODATA if property does not have a value, and -EOVERFLOW if the + * property data isn't large enough. + * + * The out_value is modified only if a valid u32 value can be decoded. + */ +int of_property_read_u32_index(const struct device_node *np, +				       const char *propname, +				       u32 index, u32 *out_value) +{ +	const u32 *val = of_find_property_value_of_size(np, propname, +					((index + 1) * sizeof(*out_value))); + +	if (IS_ERR(val)) +		return PTR_ERR(val); + +	*out_value = be32_to_cpup(((__be32 *)val) + index); +	return 0; +} +EXPORT_SYMBOL_GPL(of_property_read_u32_index); + +/**   * of_property_read_u8_array - Find and read an array of u8 from a property.   *   * @np:		device node from which the property value is to be read. @@ -766,17 +824,12 @@ EXPORT_SYMBOL(of_find_node_by_phandle);  int of_property_read_u8_array(const struct device_node *np,  			const char *propname, u8 *out_values, size_t sz)  { -	struct property *prop = of_find_property(np, propname, NULL); -	const u8 *val; +	const u8 *val = of_find_property_value_of_size(np, propname, +						(sz * sizeof(*out_values))); -	if (!prop) -		return -EINVAL; -	if (!prop->value) -		return -ENODATA; -	if ((sz * sizeof(*out_values)) > prop->length) -		return -EOVERFLOW; +	if (IS_ERR(val)) +		return PTR_ERR(val); -	val = prop->value;  	while (sz--)  		*out_values++ = *val++;  	return 0; @@ -804,17 +857,12 @@ EXPORT_SYMBOL_GPL(of_property_read_u8_array);  int of_property_read_u16_array(const struct device_node *np,  			const char *propname, u16 *out_values, size_t sz)  { -	struct property *prop = of_find_property(np, propname, NULL); -	const __be16 *val; +	const __be16 *val = of_find_property_value_of_size(np, propname, +						(sz * sizeof(*out_values))); -	if (!prop) -		return -EINVAL; -	if (!prop->value) -		return -ENODATA; -	if ((sz * sizeof(*out_values)) > prop->length) -		return -EOVERFLOW; +	if (IS_ERR(val)) +		return PTR_ERR(val); -	val = prop->value;  	while (sz--)  		*out_values++ = be16_to_cpup(val++);  	return 0; @@ -841,17 +889,12 @@ int of_property_read_u32_array(const struct device_node *np,  			       const char *propname, u32 *out_values,  			       size_t sz)  { -	struct property *prop = of_find_property(np, propname, NULL); -	const __be32 *val; +	const __be32 *val = of_find_property_value_of_size(np, propname, +						(sz * sizeof(*out_values))); -	if (!prop) -		return -EINVAL; -	if (!prop->value) -		return -ENODATA; -	if ((sz * sizeof(*out_values)) > prop->length) -		return -EOVERFLOW; +	if (IS_ERR(val)) +		return PTR_ERR(val); -	val = prop->value;  	while (sz--)  		*out_values++ = be32_to_cpup(val++);  	return 0; @@ -874,15 +917,13 @@ EXPORT_SYMBOL_GPL(of_property_read_u32_array);  int of_property_read_u64(const struct device_node *np, const char *propname,  			 u64 *out_value)  { -	struct property *prop = of_find_property(np, propname, NULL); +	const __be32 *val = of_find_property_value_of_size(np, propname, +						sizeof(*out_value)); -	if (!prop) -		return -EINVAL; -	if (!prop->value) -		return -ENODATA; -	if (sizeof(*out_value) > prop->length) -		return -EOVERFLOW; -	*out_value = of_read_number(prop->value, 2); +	if (IS_ERR(val)) +		return PTR_ERR(val); + +	*out_value = of_read_number(val, 2);  	return 0;  }  EXPORT_SYMBOL_GPL(of_property_read_u64);  |