diff options
Diffstat (limited to 'drivers/base/property.c')
| -rw-r--r-- | drivers/base/property.c | 200 | 
1 files changed, 145 insertions, 55 deletions
| diff --git a/drivers/base/property.c b/drivers/base/property.c index c45845874d4f..1d0b116cae95 100644 --- a/drivers/base/property.c +++ b/drivers/base/property.c @@ -10,10 +10,102 @@   * published by the Free Software Foundation.   */ -#include <linux/property.h> -#include <linux/export.h>  #include <linux/acpi.h> +#include <linux/export.h> +#include <linux/kernel.h>  #include <linux/of.h> +#include <linux/property.h> + +/** + * device_add_property_set - Add a collection of properties to a device object. + * @dev: Device to add properties to. + * @pset: Collection of properties to add. + * + * Associate a collection of device properties represented by @pset with @dev + * as its secondary firmware node. + */ +void device_add_property_set(struct device *dev, struct property_set *pset) +{ +	if (pset) +		pset->fwnode.type = FWNODE_PDATA; + +	set_secondary_fwnode(dev, &pset->fwnode); +} +EXPORT_SYMBOL_GPL(device_add_property_set); + +static inline bool is_pset(struct fwnode_handle *fwnode) +{ +	return fwnode && fwnode->type == FWNODE_PDATA; +} + +static inline struct property_set *to_pset(struct fwnode_handle *fwnode) +{ +	return is_pset(fwnode) ? +		container_of(fwnode, struct property_set, fwnode) : NULL; +} + +static struct property_entry *pset_prop_get(struct property_set *pset, +					    const char *name) +{ +	struct property_entry *prop; + +	if (!pset || !pset->properties) +		return NULL; + +	for (prop = pset->properties; prop->name; prop++) +		if (!strcmp(name, prop->name)) +			return prop; + +	return NULL; +} + +static int pset_prop_read_array(struct property_set *pset, const char *name, +				enum dev_prop_type type, void *val, size_t nval) +{ +	struct property_entry *prop; +	unsigned int item_size; + +	prop = pset_prop_get(pset, name); +	if (!prop) +		return -ENODATA; + +	if (prop->type != type) +		return -EPROTO; + +	if (!val) +		return prop->nval; + +	if (prop->nval < nval) +		return -EOVERFLOW; + +	switch (type) { +	case DEV_PROP_U8: +		item_size = sizeof(u8); +		break; +	case DEV_PROP_U16: +		item_size = sizeof(u16); +		break; +	case DEV_PROP_U32: +		item_size = sizeof(u32); +		break; +	case DEV_PROP_U64: +		item_size = sizeof(u64); +		break; +	case DEV_PROP_STRING: +		item_size = sizeof(const char *); +		break; +	default: +		return -EINVAL; +	} +	memcpy(val, prop->value.raw_data, nval * item_size); +	return 0; +} + +static inline struct fwnode_handle *dev_fwnode(struct device *dev) +{ +	return IS_ENABLED(CONFIG_OF) && dev->of_node ? +		&dev->of_node->fwnode : dev->fwnode; +}  /**   * device_property_present - check if a property of a device is present @@ -24,10 +116,7 @@   */  bool device_property_present(struct device *dev, const char *propname)  { -	if (IS_ENABLED(CONFIG_OF) && dev->of_node) -		return of_property_read_bool(dev->of_node, propname); - -	return !acpi_dev_prop_get(ACPI_COMPANION(dev), propname, NULL); +	return fwnode_property_present(dev_fwnode(dev), propname);  }  EXPORT_SYMBOL_GPL(device_property_present); @@ -43,32 +132,22 @@ bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname)  	else if (is_acpi_node(fwnode))  		return !acpi_dev_prop_get(acpi_node(fwnode), propname, NULL); -	return false; +	return !!pset_prop_get(to_pset(fwnode), propname);  }  EXPORT_SYMBOL_GPL(fwnode_property_present); -#define OF_DEV_PROP_READ_ARRAY(node, propname, type, val, nval) \ -	(val) ? of_property_read_##type##_array((node), (propname), (val), (nval)) \ -	      : of_property_count_elems_of_size((node), (propname), sizeof(type)) - -#define DEV_PROP_READ_ARRAY(_dev_, _propname_, _type_, _proptype_, _val_, _nval_) \ -	IS_ENABLED(CONFIG_OF) && _dev_->of_node ? \ -		(OF_DEV_PROP_READ_ARRAY(_dev_->of_node, _propname_, _type_, \ -					_val_, _nval_)) : \ -		acpi_dev_prop_read(ACPI_COMPANION(_dev_), _propname_, \ -				   _proptype_, _val_, _nval_) -  /**   * device_property_read_u8_array - return a u8 array property of a device   * @dev: Device to get the property of   * @propname: Name of the property - * @val: The values are stored here + * @val: The values are stored here or %NULL to return the number of values   * @nval: Size of the @val array   *   * Function reads an array of u8 properties with @propname from the device   * firmware description and stores them to @val if found.   * - * Return: %0 if the property was found (success), + * Return: number of values if @val was %NULL, + *         %0 if the property was found (success),   *	   %-EINVAL if given arguments are not valid,   *	   %-ENODATA if the property does not have a value,   *	   %-EPROTO if the property is not an array of numbers, @@ -77,7 +156,7 @@ EXPORT_SYMBOL_GPL(fwnode_property_present);  int device_property_read_u8_array(struct device *dev, const char *propname,  				  u8 *val, size_t nval)  { -	return DEV_PROP_READ_ARRAY(dev, propname, u8, DEV_PROP_U8, val, nval); +	return fwnode_property_read_u8_array(dev_fwnode(dev), propname, val, nval);  }  EXPORT_SYMBOL_GPL(device_property_read_u8_array); @@ -85,13 +164,14 @@ EXPORT_SYMBOL_GPL(device_property_read_u8_array);   * device_property_read_u16_array - return a u16 array property of a device   * @dev: Device to get the property of   * @propname: Name of the property - * @val: The values are stored here + * @val: The values are stored here or %NULL to return the number of values   * @nval: Size of the @val array   *   * Function reads an array of u16 properties with @propname from the device   * firmware description and stores them to @val if found.   * - * Return: %0 if the property was found (success), + * Return: number of values if @val was %NULL, + *         %0 if the property was found (success),   *	   %-EINVAL if given arguments are not valid,   *	   %-ENODATA if the property does not have a value,   *	   %-EPROTO if the property is not an array of numbers, @@ -100,7 +180,7 @@ EXPORT_SYMBOL_GPL(device_property_read_u8_array);  int device_property_read_u16_array(struct device *dev, const char *propname,  				   u16 *val, size_t nval)  { -	return DEV_PROP_READ_ARRAY(dev, propname, u16, DEV_PROP_U16, val, nval); +	return fwnode_property_read_u16_array(dev_fwnode(dev), propname, val, nval);  }  EXPORT_SYMBOL_GPL(device_property_read_u16_array); @@ -108,13 +188,14 @@ EXPORT_SYMBOL_GPL(device_property_read_u16_array);   * device_property_read_u32_array - return a u32 array property of a device   * @dev: Device to get the property of   * @propname: Name of the property - * @val: The values are stored here + * @val: The values are stored here or %NULL to return the number of values   * @nval: Size of the @val array   *   * Function reads an array of u32 properties with @propname from the device   * firmware description and stores them to @val if found.   * - * Return: %0 if the property was found (success), + * Return: number of values if @val was %NULL, + *         %0 if the property was found (success),   *	   %-EINVAL if given arguments are not valid,   *	   %-ENODATA if the property does not have a value,   *	   %-EPROTO if the property is not an array of numbers, @@ -123,7 +204,7 @@ EXPORT_SYMBOL_GPL(device_property_read_u16_array);  int device_property_read_u32_array(struct device *dev, const char *propname,  				   u32 *val, size_t nval)  { -	return DEV_PROP_READ_ARRAY(dev, propname, u32, DEV_PROP_U32, val, nval); +	return fwnode_property_read_u32_array(dev_fwnode(dev), propname, val, nval);  }  EXPORT_SYMBOL_GPL(device_property_read_u32_array); @@ -131,13 +212,14 @@ EXPORT_SYMBOL_GPL(device_property_read_u32_array);   * device_property_read_u64_array - return a u64 array property of a device   * @dev: Device to get the property of   * @propname: Name of the property - * @val: The values are stored here + * @val: The values are stored here or %NULL to return the number of values   * @nval: Size of the @val array   *   * Function reads an array of u64 properties with @propname from the device   * firmware description and stores them to @val if found.   * - * Return: %0 if the property was found (success), + * Return: number of values if @val was %NULL, + *         %0 if the property was found (success),   *	   %-EINVAL if given arguments are not valid,   *	   %-ENODATA if the property does not have a value,   *	   %-EPROTO if the property is not an array of numbers, @@ -146,7 +228,7 @@ EXPORT_SYMBOL_GPL(device_property_read_u32_array);  int device_property_read_u64_array(struct device *dev, const char *propname,  				   u64 *val, size_t nval)  { -	return DEV_PROP_READ_ARRAY(dev, propname, u64, DEV_PROP_U64, val, nval); +	return fwnode_property_read_u64_array(dev_fwnode(dev), propname, val, nval);  }  EXPORT_SYMBOL_GPL(device_property_read_u64_array); @@ -154,13 +236,14 @@ EXPORT_SYMBOL_GPL(device_property_read_u64_array);   * device_property_read_string_array - return a string array property of device   * @dev: Device to get the property of   * @propname: Name of the property - * @val: The values are stored here + * @val: The values are stored here or %NULL to return the number of values   * @nval: Size of the @val array   *   * Function reads an array of string properties with @propname from the device   * firmware description and stores them to @val if found.   * - * Return: %0 if the property was found (success), + * Return: number of values if @val was %NULL, + *         %0 if the property was found (success),   *	   %-EINVAL if given arguments are not valid,   *	   %-ENODATA if the property does not have a value,   *	   %-EPROTO or %-EILSEQ if the property is not an array of strings, @@ -169,10 +252,7 @@ EXPORT_SYMBOL_GPL(device_property_read_u64_array);  int device_property_read_string_array(struct device *dev, const char *propname,  				      const char **val, size_t nval)  { -	return IS_ENABLED(CONFIG_OF) && dev->of_node ? -		of_property_read_string_array(dev->of_node, propname, val, nval) : -		acpi_dev_prop_read(ACPI_COMPANION(dev), propname, -				   DEV_PROP_STRING, val, nval); +	return fwnode_property_read_string_array(dev_fwnode(dev), propname, val, nval);  }  EXPORT_SYMBOL_GPL(device_property_read_string_array); @@ -193,13 +273,14 @@ EXPORT_SYMBOL_GPL(device_property_read_string_array);  int device_property_read_string(struct device *dev, const char *propname,  				const char **val)  { -	return IS_ENABLED(CONFIG_OF) && dev->of_node ? -		of_property_read_string(dev->of_node, propname, val) : -		acpi_dev_prop_read(ACPI_COMPANION(dev), propname, -				   DEV_PROP_STRING, val, 1); +	return fwnode_property_read_string(dev_fwnode(dev), propname, val);  }  EXPORT_SYMBOL_GPL(device_property_read_string); +#define OF_DEV_PROP_READ_ARRAY(node, propname, type, val, nval) \ +	(val) ? of_property_read_##type##_array((node), (propname), (val), (nval)) \ +	      : of_property_count_elems_of_size((node), (propname), sizeof(type)) +  #define FWNODE_PROP_READ_ARRAY(_fwnode_, _propname_, _type_, _proptype_, _val_, _nval_) \  ({ \  	int _ret_; \ @@ -210,7 +291,8 @@ EXPORT_SYMBOL_GPL(device_property_read_string);  		_ret_ = acpi_dev_prop_read(acpi_node(_fwnode_), _propname_, \  					   _proptype_, _val_, _nval_); \  	else \ -		_ret_ = -ENXIO; \ +		_ret_ = pset_prop_read_array(to_pset(_fwnode_), _propname_, \ +					     _proptype_, _val_, _nval_); \  	_ret_; \  }) @@ -218,13 +300,14 @@ EXPORT_SYMBOL_GPL(device_property_read_string);   * fwnode_property_read_u8_array - return a u8 array property of firmware node   * @fwnode: Firmware node to get the property of   * @propname: Name of the property - * @val: The values are stored here + * @val: The values are stored here or %NULL to return the number of values   * @nval: Size of the @val array   *   * Read an array of u8 properties with @propname from @fwnode and stores them to   * @val if found.   * - * Return: %0 if the property was found (success), + * Return: number of values if @val was %NULL, + *         %0 if the property was found (success),   *	   %-EINVAL if given arguments are not valid,   *	   %-ENODATA if the property does not have a value,   *	   %-EPROTO if the property is not an array of numbers, @@ -243,13 +326,14 @@ EXPORT_SYMBOL_GPL(fwnode_property_read_u8_array);   * fwnode_property_read_u16_array - return a u16 array property of firmware node   * @fwnode: Firmware node to get the property of   * @propname: Name of the property - * @val: The values are stored here + * @val: The values are stored here or %NULL to return the number of values   * @nval: Size of the @val array   *   * Read an array of u16 properties with @propname from @fwnode and store them to   * @val if found.   * - * Return: %0 if the property was found (success), + * Return: number of values if @val was %NULL, + *         %0 if the property was found (success),   *	   %-EINVAL if given arguments are not valid,   *	   %-ENODATA if the property does not have a value,   *	   %-EPROTO if the property is not an array of numbers, @@ -268,13 +352,14 @@ EXPORT_SYMBOL_GPL(fwnode_property_read_u16_array);   * fwnode_property_read_u32_array - return a u32 array property of firmware node   * @fwnode: Firmware node to get the property of   * @propname: Name of the property - * @val: The values are stored here + * @val: The values are stored here or %NULL to return the number of values   * @nval: Size of the @val array   *   * Read an array of u32 properties with @propname from @fwnode store them to   * @val if found.   * - * Return: %0 if the property was found (success), + * Return: number of values if @val was %NULL, + *         %0 if the property was found (success),   *	   %-EINVAL if given arguments are not valid,   *	   %-ENODATA if the property does not have a value,   *	   %-EPROTO if the property is not an array of numbers, @@ -293,13 +378,14 @@ EXPORT_SYMBOL_GPL(fwnode_property_read_u32_array);   * fwnode_property_read_u64_array - return a u64 array property firmware node   * @fwnode: Firmware node to get the property of   * @propname: Name of the property - * @val: The values are stored here + * @val: The values are stored here or %NULL to return the number of values   * @nval: Size of the @val array   *   * Read an array of u64 properties with @propname from @fwnode and store them to   * @val if found.   * - * Return: %0 if the property was found (success), + * Return: number of values if @val was %NULL, + *         %0 if the property was found (success),   *	   %-EINVAL if given arguments are not valid,   *	   %-ENODATA if the property does not have a value,   *	   %-EPROTO if the property is not an array of numbers, @@ -318,13 +404,14 @@ EXPORT_SYMBOL_GPL(fwnode_property_read_u64_array);   * fwnode_property_read_string_array - return string array property of a node   * @fwnode: Firmware node to get the property of   * @propname: Name of the property - * @val: The values are stored here + * @val: The values are stored here or %NULL to return the number of values   * @nval: Size of the @val array   *   * Read an string list property @propname from the given firmware node and store   * them to @val if found.   * - * Return: %0 if the property was found (success), + * Return: number of values if @val was %NULL, + *         %0 if the property was found (success),   *	   %-EINVAL if given arguments are not valid,   *	   %-ENODATA if the property does not have a value,   *	   %-EPROTO if the property is not an array of strings, @@ -336,13 +423,16 @@ int fwnode_property_read_string_array(struct fwnode_handle *fwnode,  				      size_t nval)  {  	if (is_of_node(fwnode)) -		return of_property_read_string_array(of_node(fwnode), propname, -						     val, nval); +		return val ? +			of_property_read_string_array(of_node(fwnode), propname, +						      val, nval) : +			of_property_count_strings(of_node(fwnode), propname);  	else if (is_acpi_node(fwnode))  		return acpi_dev_prop_read(acpi_node(fwnode), propname,  					  DEV_PROP_STRING, val, nval); -	return -ENXIO; +	return pset_prop_read_array(to_pset(fwnode), propname, +				    DEV_PROP_STRING, val, nval);  }  EXPORT_SYMBOL_GPL(fwnode_property_read_string_array); @@ -365,7 +455,7 @@ int fwnode_property_read_string(struct fwnode_handle *fwnode,  				const char *propname, const char **val)  {  	if (is_of_node(fwnode)) -		return of_property_read_string(of_node(fwnode),propname, val); +		return of_property_read_string(of_node(fwnode), propname, val);  	else if (is_acpi_node(fwnode))  		return acpi_dev_prop_read(acpi_node(fwnode), propname,  					  DEV_PROP_STRING, val, 1); |