1291 lines · 38.2 KB · C
RawDownload
/* * property.c - Unified device property interface. * * Copyright (C) 2014, Intel Corporation * Authors: Rafael J. Wysocki <rafael.j.wysocki@intel.com> *          Mika Westerberg <mika.westerberg@linux.intel.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #include <linux/acpi.h>#include <linux/export.h>#include <linux/kernel.h>#include <linux/of.h>#include <linux/of_address.h>#include <linux/of_graph.h>#include <linux/property.h>#include <linux/etherdevice.h>#include <linux/phy.h> struct property_set {	struct fwnode_handle fwnode;	const struct property_entry *properties;}; static inline bool is_pset_node(struct fwnode_handle *fwnode){	return !IS_ERR_OR_NULL(fwnode) && fwnode->type == FWNODE_PDATA;} static inline struct property_set *to_pset_node(struct fwnode_handle *fwnode){	return is_pset_node(fwnode) ?		container_of(fwnode, struct property_set, fwnode) : NULL;} static const struct property_entry *pset_prop_get(struct property_set *pset,						  const char *name){	const 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 const void *pset_prop_find(struct property_set *pset,				  const char *propname, size_t length){	const struct property_entry *prop;	const void *pointer; 	prop = pset_prop_get(pset, propname);	if (!prop)		return ERR_PTR(-EINVAL);	if (prop->is_array)		pointer = prop->pointer.raw_data;	else		pointer = &prop->value.raw_data;	if (!pointer)		return ERR_PTR(-ENODATA);	if (length > prop->length)		return ERR_PTR(-EOVERFLOW);	return pointer;} static int pset_prop_read_u8_array(struct property_set *pset,				   const char *propname,				   u8 *values, size_t nval){	const void *pointer;	size_t length = nval * sizeof(*values); 	pointer = pset_prop_find(pset, propname, length);	if (IS_ERR(pointer))		return PTR_ERR(pointer); 	memcpy(values, pointer, length);	return 0;} static int pset_prop_read_u16_array(struct property_set *pset,				    const char *propname,				    u16 *values, size_t nval){	const void *pointer;	size_t length = nval * sizeof(*values); 	pointer = pset_prop_find(pset, propname, length);	if (IS_ERR(pointer))		return PTR_ERR(pointer); 	memcpy(values, pointer, length);	return 0;} static int pset_prop_read_u32_array(struct property_set *pset,				    const char *propname,				    u32 *values, size_t nval){	const void *pointer;	size_t length = nval * sizeof(*values); 	pointer = pset_prop_find(pset, propname, length);	if (IS_ERR(pointer))		return PTR_ERR(pointer); 	memcpy(values, pointer, length);	return 0;} static int pset_prop_read_u64_array(struct property_set *pset,				    const char *propname,				    u64 *values, size_t nval){	const void *pointer;	size_t length = nval * sizeof(*values); 	pointer = pset_prop_find(pset, propname, length);	if (IS_ERR(pointer))		return PTR_ERR(pointer); 	memcpy(values, pointer, length);	return 0;} static int pset_prop_count_elems_of_size(struct property_set *pset,					 const char *propname, size_t length){	const struct property_entry *prop; 	prop = pset_prop_get(pset, propname);	if (!prop)		return -EINVAL; 	return prop->length / length;} static int pset_prop_read_string_array(struct property_set *pset,				       const char *propname,				       const char **strings, size_t nval){	const struct property_entry *prop;	const void *pointer;	size_t array_len, length; 	/* Find out the array length. */	prop = pset_prop_get(pset, propname);	if (!prop)		return -EINVAL; 	if (!prop->is_array)		/* The array length for a non-array string property is 1. */		array_len = 1;	else		/* Find the length of an array. */		array_len = pset_prop_count_elems_of_size(pset, propname,							  sizeof(const char *)); 	/* Return how many there are if strings is NULL. */	if (!strings)		return array_len; 	array_len = min(nval, array_len);	length = array_len * sizeof(*strings); 	pointer = pset_prop_find(pset, propname, length);	if (IS_ERR(pointer))		return PTR_ERR(pointer); 	memcpy(strings, pointer, length); 	return array_len;} struct fwnode_handle *dev_fwnode(struct device *dev){	return IS_ENABLED(CONFIG_OF) && dev->of_node ?		&dev->of_node->fwnode : dev->fwnode;}EXPORT_SYMBOL_GPL(dev_fwnode); static bool pset_fwnode_property_present(struct fwnode_handle *fwnode,					 const char *propname){	return !!pset_prop_get(to_pset_node(fwnode), propname);} static int pset_fwnode_read_int_array(struct fwnode_handle *fwnode,				      const char *propname,				      unsigned int elem_size, void *val,				      size_t nval){	struct property_set *node = to_pset_node(fwnode); 	if (!val)		return pset_prop_count_elems_of_size(node, propname, elem_size); 	switch (elem_size) {	case sizeof(u8):		return pset_prop_read_u8_array(node, propname, val, nval);	case sizeof(u16):		return pset_prop_read_u16_array(node, propname, val, nval);	case sizeof(u32):		return pset_prop_read_u32_array(node, propname, val, nval);	case sizeof(u64):		return pset_prop_read_u64_array(node, propname, val, nval);	} 	return -ENXIO;} static int pset_fwnode_property_read_string_array(struct fwnode_handle *fwnode,						  const char *propname,						  const char **val, size_t nval){	return pset_prop_read_string_array(to_pset_node(fwnode), propname,					   val, nval);} static const struct fwnode_operations pset_fwnode_ops = {	.property_present = pset_fwnode_property_present,	.property_read_int_array = pset_fwnode_read_int_array,	.property_read_string_array = pset_fwnode_property_read_string_array,}; /** * device_property_present - check if a property of a device is present * @dev: Device whose property is being checked * @propname: Name of the property * * Check if property @propname is present in the device firmware description. */bool device_property_present(struct device *dev, const char *propname){	return fwnode_property_present(dev_fwnode(dev), propname);}EXPORT_SYMBOL_GPL(device_property_present); /** * fwnode_property_present - check if a property of a firmware node is present * @fwnode: Firmware node whose property to check * @propname: Name of the property */bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname){	bool ret; 	ret = fwnode_call_bool_op(fwnode, property_present, propname);	if (ret == false && !IS_ERR_OR_NULL(fwnode) &&	    !IS_ERR_OR_NULL(fwnode->secondary))		ret = fwnode_call_bool_op(fwnode->secondary, property_present,					 propname);	return ret;}EXPORT_SYMBOL_GPL(fwnode_property_present); /** * 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 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: 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, *	   %-EOVERFLOW if the size of the property is not as expected. *	   %-ENXIO if no suitable firmware interface is present. */int device_property_read_u8_array(struct device *dev, const char *propname,				  u8 *val, size_t nval){	return fwnode_property_read_u8_array(dev_fwnode(dev), propname, val, nval);}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 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: 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, *	   %-EOVERFLOW if the size of the property is not as expected. *	   %-ENXIO if no suitable firmware interface is present. */int device_property_read_u16_array(struct device *dev, const char *propname,				   u16 *val, size_t nval){	return fwnode_property_read_u16_array(dev_fwnode(dev), propname, val, nval);}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 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: 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, *	   %-EOVERFLOW if the size of the property is not as expected. *	   %-ENXIO if no suitable firmware interface is present. */int device_property_read_u32_array(struct device *dev, const char *propname,				   u32 *val, size_t nval){	return fwnode_property_read_u32_array(dev_fwnode(dev), propname, val, nval);}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 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: 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, *	   %-EOVERFLOW if the size of the property is not as expected. *	   %-ENXIO if no suitable firmware interface is present. */int device_property_read_u64_array(struct device *dev, const char *propname,				   u64 *val, size_t nval){	return fwnode_property_read_u64_array(dev_fwnode(dev), propname, val, nval);}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 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: number of values read on success if @val is non-NULL, *	   number of values available on success if @val is NULL, *	   %-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, *	   %-EOVERFLOW if the size of the property is not as expected. *	   %-ENXIO if no suitable firmware interface is present. */int device_property_read_string_array(struct device *dev, const char *propname,				      const char **val, size_t nval){	return fwnode_property_read_string_array(dev_fwnode(dev), propname, val, nval);}EXPORT_SYMBOL_GPL(device_property_read_string_array); /** * device_property_read_string - return a string property of a device * @dev: Device to get the property of * @propname: Name of the property * @val: The value is stored here * * Function reads property @propname from the device firmware description and * stores the value into @val if found. The value is checked to be a string. * * Return: %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 type is not a string. *	   %-ENXIO if no suitable firmware interface is present. */int device_property_read_string(struct device *dev, const char *propname,				const char **val){	return fwnode_property_read_string(dev_fwnode(dev), propname, val);}EXPORT_SYMBOL_GPL(device_property_read_string); /** * device_property_match_string - find a string in an array and return index * @dev: Device to get the property of * @propname: Name of the property holding the array * @string: String to look for * * Find a given string in a string array and if it is found return the * index back. * * Return: %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, *	   %-ENXIO if no suitable firmware interface is present. */int device_property_match_string(struct device *dev, const char *propname,				 const char *string){	return fwnode_property_match_string(dev_fwnode(dev), propname, string);}EXPORT_SYMBOL_GPL(device_property_match_string); static int fwnode_property_read_int_array(struct fwnode_handle *fwnode,					  const char *propname,					  unsigned int elem_size, void *val,					  size_t nval){	int ret; 	ret = fwnode_call_int_op(fwnode, property_read_int_array, propname,				 elem_size, val, nval);	if (ret == -EINVAL && !IS_ERR_OR_NULL(fwnode) &&	    !IS_ERR_OR_NULL(fwnode->secondary))		ret = fwnode_call_int_op(			fwnode->secondary, property_read_int_array, propname,			elem_size, val, nval); 	return ret;} /** * 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 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: 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, *	   %-EOVERFLOW if the size of the property is not as expected, *	   %-ENXIO if no suitable firmware interface is present. */int fwnode_property_read_u8_array(struct fwnode_handle *fwnode,				  const char *propname, u8 *val, size_t nval){	return fwnode_property_read_int_array(fwnode, propname, sizeof(u8),					      val, nval);}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 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: 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, *	   %-EOVERFLOW if the size of the property is not as expected, *	   %-ENXIO if no suitable firmware interface is present. */int fwnode_property_read_u16_array(struct fwnode_handle *fwnode,				   const char *propname, u16 *val, size_t nval){	return fwnode_property_read_int_array(fwnode, propname, sizeof(u16),					      val, nval);

Lines 1–500 of 1291.