Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3708184a authored by Sakari Ailus's avatar Sakari Ailus Committed by Rafael J. Wysocki
Browse files

device property: Move FW type specific functionality to FW specific files



The device and fwnode property API supports Devicetree, ACPI and pset
properties. The implementation of this functionality for each firmware
type was embedded in the fwnode property core. Move it out to firmware
type specific locations, making it easier to maintain.

Depends-on: ("of: Move OF property and graph API from base.c to property.c")
Signed-off-by: default avatarSakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: default avatarMika Westerberg <mika.westerberg@linux.intel.com>
Acked-by: default avatarRob Herring <robh@kernel.org>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent cde1f95f
Loading
Loading
Loading
Loading
+68 −0
Original line number Original line Diff line number Diff line
@@ -57,6 +57,7 @@ static bool acpi_nondev_subnode_extract(const union acpi_object *desc,


	dn->name = link->package.elements[0].string.pointer;
	dn->name = link->package.elements[0].string.pointer;
	dn->fwnode.type = FWNODE_ACPI_DATA;
	dn->fwnode.type = FWNODE_ACPI_DATA;
	dn->fwnode.ops = &acpi_fwnode_ops;
	dn->parent = parent;
	dn->parent = parent;
	INIT_LIST_HEAD(&dn->data.subnodes);
	INIT_LIST_HEAD(&dn->data.subnodes);


@@ -1119,3 +1120,70 @@ int acpi_graph_get_remote_endpoint(struct fwnode_handle *fwnode,


	return 0;
	return 0;
}
}

static bool acpi_fwnode_property_present(struct fwnode_handle *fwnode,
					 const char *propname)
{
	return !acpi_node_prop_get(fwnode, propname, NULL);
}

static int acpi_fwnode_property_read_int_array(struct fwnode_handle *fwnode,
					       const char *propname,
					       unsigned int elem_size,
					       void *val, size_t nval)
{
	enum dev_prop_type type;

	switch (elem_size) {
	case sizeof(u8):
		type = DEV_PROP_U8;
		break;
	case sizeof(u16):
		type = DEV_PROP_U16;
		break;
	case sizeof(u32):
		type = DEV_PROP_U32;
		break;
	case sizeof(u64):
		type = DEV_PROP_U64;
		break;
	default:
		return -ENXIO;
	}

	return acpi_node_prop_read(fwnode, propname, type, val, nval);
}

static int acpi_fwnode_property_read_string_array(struct fwnode_handle *fwnode,
						  const char *propname,
						  const char **val, size_t nval)
{
	return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING,
				   val, nval);
}

static struct fwnode_handle *
acpi_fwnode_get_named_child_node(struct fwnode_handle *fwnode,
				 const char *childname)
{
	struct fwnode_handle *child;

	/*
	 * Find first matching named child node of this fwnode.
	 * For ACPI this will be a data only sub-node.
	 */
	fwnode_for_each_child_node(fwnode, child)
		if (acpi_data_node_match(child, childname))
			return child;

	return NULL;
}

const struct fwnode_operations acpi_fwnode_ops = {
	.property_present = acpi_fwnode_property_present,
	.property_read_int_array = acpi_fwnode_property_read_int_array,
	.property_read_string_array = acpi_fwnode_property_read_string_array,
	.get_parent = acpi_node_get_parent,
	.get_next_child_node = acpi_get_next_subnode,
	.get_named_child_node = acpi_fwnode_get_named_child_node,
};
+1 −0
Original line number Original line Diff line number Diff line
@@ -1436,6 +1436,7 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
	device->handle = handle;
	device->handle = handle;
	device->parent = acpi_bus_get_parent(handle);
	device->parent = acpi_bus_get_parent(handle);
	device->fwnode.type = FWNODE_ACPI;
	device->fwnode.type = FWNODE_ACPI;
	device->fwnode.ops = &acpi_fwnode_ops;
	acpi_set_device_status(device, sta);
	acpi_set_device_status(device, sta);
	acpi_device_get_busid(device);
	acpi_device_get_busid(device);
	acpi_set_pnp_ids(handle, &device->pnp, type);
	acpi_set_pnp_ids(handle, &device->pnp, type);
+83 −125
Original line number Original line Diff line number Diff line
@@ -187,6 +187,50 @@ struct fwnode_handle *dev_fwnode(struct device *dev)
}
}
EXPORT_SYMBOL_GPL(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
 * device_property_present - check if a property of a device is present
 * @dev: Device whose property is being checked
 * @dev: Device whose property is being checked
@@ -200,18 +244,6 @@ bool device_property_present(struct device *dev, const char *propname)
}
}
EXPORT_SYMBOL_GPL(device_property_present);
EXPORT_SYMBOL_GPL(device_property_present);


static bool __fwnode_property_present(struct fwnode_handle *fwnode,
				      const char *propname)
{
	if (is_of_node(fwnode))
		return of_property_read_bool(to_of_node(fwnode), propname);
	else if (is_acpi_node(fwnode))
		return !acpi_node_prop_get(fwnode, propname, NULL);
	else if (is_pset_node(fwnode))
		return !!pset_prop_get(to_pset_node(fwnode), propname);
	return false;
}

/**
/**
 * fwnode_property_present - check if a property of a firmware node is present
 * fwnode_property_present - check if a property of a firmware node is present
 * @fwnode: Firmware node whose property to check
 * @fwnode: Firmware node whose property to check
@@ -221,10 +253,11 @@ bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname)
{
{
	bool ret;
	bool ret;


	ret = __fwnode_property_present(fwnode, propname);
	ret = fwnode_call_int_op(fwnode, property_present, propname);
	if (ret == false && !IS_ERR_OR_NULL(fwnode) &&
	if (ret == false && !IS_ERR_OR_NULL(fwnode) &&
	    !IS_ERR_OR_NULL(fwnode->secondary))
	    !IS_ERR_OR_NULL(fwnode->secondary))
		ret = __fwnode_property_present(fwnode->secondary, propname);
		ret = fwnode_call_int_op(fwnode->secondary, property_present,
					 propname);
	return ret;
	return ret;
}
}
EXPORT_SYMBOL_GPL(fwnode_property_present);
EXPORT_SYMBOL_GPL(fwnode_property_present);
@@ -398,42 +431,23 @@ int device_property_match_string(struct device *dev, const char *propname,
}
}
EXPORT_SYMBOL_GPL(device_property_match_string);
EXPORT_SYMBOL_GPL(device_property_match_string);


#define OF_DEV_PROP_READ_ARRAY(node, propname, type, val, nval)				\
static int fwnode_property_read_int_array(struct fwnode_handle *fwnode,
	(val) ? of_property_read_##type##_array((node), (propname), (val), (nval))	\
					  const char *propname,
	      : of_property_count_elems_of_size((node), (propname), sizeof(type))
					  unsigned int elem_size, void *val,

					  size_t nval)
#define PSET_PROP_READ_ARRAY(node, propname, type, val, nval)				\
{
	(val) ? pset_prop_read_##type##_array((node), (propname), (val), (nval))	\
	int ret;
	      : pset_prop_count_elems_of_size((node), (propname), sizeof(type))


	ret = fwnode_call_int_op(fwnode, property_read_int_array, propname,
#define FWNODE_PROP_READ(_fwnode_, _propname_, _type_, _proptype_, _val_, _nval_)	\
				 elem_size, val, nval);
({											\
	if (ret == -EINVAL && !IS_ERR_OR_NULL(fwnode) &&
	int _ret_;									\
	    !IS_ERR_OR_NULL(fwnode->secondary))
	if (is_of_node(_fwnode_))							\
		ret = fwnode_call_int_op(
		_ret_ = OF_DEV_PROP_READ_ARRAY(to_of_node(_fwnode_), _propname_,	\
			fwnode->secondary, property_read_int_array, propname,
					       _type_, _val_, _nval_);			\
			elem_size, val, nval);
	else if (is_acpi_node(_fwnode_))						\

		_ret_ = acpi_node_prop_read(_fwnode_, _propname_, _proptype_,		\
	return ret;
					    _val_, _nval_);				\
}
	else if (is_pset_node(_fwnode_)) 						\
		_ret_ = PSET_PROP_READ_ARRAY(to_pset_node(_fwnode_), _propname_,	\
					     _type_, _val_, _nval_);			\
	else										\
		_ret_ = -ENXIO;								\
	_ret_;										\
})

#define FWNODE_PROP_READ_ARRAY(_fwnode_, _propname_, _type_, _proptype_, _val_, _nval_)	\
({											\
	int _ret_;									\
	_ret_ = FWNODE_PROP_READ(_fwnode_, _propname_, _type_, _proptype_,		\
				 _val_, _nval_);					\
	if (_ret_ == -EINVAL && !IS_ERR_OR_NULL(_fwnode_) &&				\
	    !IS_ERR_OR_NULL(_fwnode_->secondary))					\
		_ret_ = FWNODE_PROP_READ(_fwnode_->secondary, _propname_, _type_,	\
				_proptype_, _val_, _nval_);				\
	_ret_;										\
})


/**
/**
 * fwnode_property_read_u8_array - return a u8 array property of firmware node
 * fwnode_property_read_u8_array - return a u8 array property of firmware node
@@ -456,7 +470,7 @@ EXPORT_SYMBOL_GPL(device_property_match_string);
int fwnode_property_read_u8_array(struct fwnode_handle *fwnode,
int fwnode_property_read_u8_array(struct fwnode_handle *fwnode,
				  const char *propname, u8 *val, size_t nval)
				  const char *propname, u8 *val, size_t nval)
{
{
	return FWNODE_PROP_READ_ARRAY(fwnode, propname, u8, DEV_PROP_U8,
	return fwnode_property_read_int_array(fwnode, propname, sizeof(u8),
					      val, nval);
					      val, nval);
}
}
EXPORT_SYMBOL_GPL(fwnode_property_read_u8_array);
EXPORT_SYMBOL_GPL(fwnode_property_read_u8_array);
@@ -482,7 +496,7 @@ EXPORT_SYMBOL_GPL(fwnode_property_read_u8_array);
int fwnode_property_read_u16_array(struct fwnode_handle *fwnode,
int fwnode_property_read_u16_array(struct fwnode_handle *fwnode,
				   const char *propname, u16 *val, size_t nval)
				   const char *propname, u16 *val, size_t nval)
{
{
	return FWNODE_PROP_READ_ARRAY(fwnode, propname, u16, DEV_PROP_U16,
	return fwnode_property_read_int_array(fwnode, propname, sizeof(u16),
					      val, nval);
					      val, nval);
}
}
EXPORT_SYMBOL_GPL(fwnode_property_read_u16_array);
EXPORT_SYMBOL_GPL(fwnode_property_read_u16_array);
@@ -508,7 +522,7 @@ EXPORT_SYMBOL_GPL(fwnode_property_read_u16_array);
int fwnode_property_read_u32_array(struct fwnode_handle *fwnode,
int fwnode_property_read_u32_array(struct fwnode_handle *fwnode,
				   const char *propname, u32 *val, size_t nval)
				   const char *propname, u32 *val, size_t nval)
{
{
	return FWNODE_PROP_READ_ARRAY(fwnode, propname, u32, DEV_PROP_U32,
	return fwnode_property_read_int_array(fwnode, propname, sizeof(u32),
					      val, nval);
					      val, nval);
}
}
EXPORT_SYMBOL_GPL(fwnode_property_read_u32_array);
EXPORT_SYMBOL_GPL(fwnode_property_read_u32_array);
@@ -534,29 +548,11 @@ EXPORT_SYMBOL_GPL(fwnode_property_read_u32_array);
int fwnode_property_read_u64_array(struct fwnode_handle *fwnode,
int fwnode_property_read_u64_array(struct fwnode_handle *fwnode,
				   const char *propname, u64 *val, size_t nval)
				   const char *propname, u64 *val, size_t nval)
{
{
	return FWNODE_PROP_READ_ARRAY(fwnode, propname, u64, DEV_PROP_U64,
	return fwnode_property_read_int_array(fwnode, propname, sizeof(u64),
					      val, nval);
					      val, nval);
}
}
EXPORT_SYMBOL_GPL(fwnode_property_read_u64_array);
EXPORT_SYMBOL_GPL(fwnode_property_read_u64_array);


static int __fwnode_property_read_string_array(struct fwnode_handle *fwnode,
					       const char *propname,
					       const char **val, size_t nval)
{
	if (is_of_node(fwnode))
		return val ?
			of_property_read_string_array(to_of_node(fwnode),
						      propname, val, nval) :
			of_property_count_strings(to_of_node(fwnode), propname);
	else if (is_acpi_node(fwnode))
		return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING,
					   val, nval);
	else if (is_pset_node(fwnode))
		return pset_prop_read_string_array(to_pset_node(fwnode),
						   propname, val, nval);
	return -ENXIO;
}

/**
/**
 * fwnode_property_read_string_array - return string array property of a node
 * fwnode_property_read_string_array - return string array property of a node
 * @fwnode: Firmware node to get the property of
 * @fwnode: Firmware node to get the property of
@@ -581,11 +577,13 @@ int fwnode_property_read_string_array(struct fwnode_handle *fwnode,
{
{
	int ret;
	int ret;


	ret = __fwnode_property_read_string_array(fwnode, propname, val, nval);
	ret = fwnode_call_int_op(fwnode, property_read_string_array, propname,
				 val, nval);
	if (ret == -EINVAL && !IS_ERR_OR_NULL(fwnode) &&
	if (ret == -EINVAL && !IS_ERR_OR_NULL(fwnode) &&
	    !IS_ERR_OR_NULL(fwnode->secondary))
	    !IS_ERR_OR_NULL(fwnode->secondary))
		ret = __fwnode_property_read_string_array(fwnode->secondary,
		ret = fwnode_call_int_op(fwnode->secondary,
							  propname, val, nval);
					 property_read_string_array, propname,
					 val, nval);
	return ret;
	return ret;
}
}
EXPORT_SYMBOL_GPL(fwnode_property_read_string_array);
EXPORT_SYMBOL_GPL(fwnode_property_read_string_array);
@@ -903,6 +901,7 @@ int device_add_properties(struct device *dev,
		return PTR_ERR(p);
		return PTR_ERR(p);


	p->fwnode.type = FWNODE_PDATA;
	p->fwnode.type = FWNODE_PDATA;
	p->fwnode.ops = &pset_fwnode_ops;
	set_secondary_fwnode(dev, &p->fwnode);
	set_secondary_fwnode(dev, &p->fwnode);
	return 0;
	return 0;
}
}
@@ -938,19 +937,7 @@ EXPORT_SYMBOL_GPL(fwnode_get_next_parent);
 */
 */
struct fwnode_handle *fwnode_get_parent(struct fwnode_handle *fwnode)
struct fwnode_handle *fwnode_get_parent(struct fwnode_handle *fwnode)
{
{
	struct fwnode_handle *parent = NULL;
	return fwnode_call_ptr_op(fwnode, get_parent);

	if (is_of_node(fwnode)) {
		struct device_node *node;

		node = of_get_parent(to_of_node(fwnode));
		if (node)
			parent = &node->fwnode;
	} else if (is_acpi_node(fwnode)) {
		parent = acpi_node_get_parent(fwnode);
	}

	return parent;
}
}
EXPORT_SYMBOL_GPL(fwnode_get_parent);
EXPORT_SYMBOL_GPL(fwnode_get_parent);


@@ -962,18 +949,7 @@ EXPORT_SYMBOL_GPL(fwnode_get_parent);
struct fwnode_handle *fwnode_get_next_child_node(struct fwnode_handle *fwnode,
struct fwnode_handle *fwnode_get_next_child_node(struct fwnode_handle *fwnode,
						 struct fwnode_handle *child)
						 struct fwnode_handle *child)
{
{
	if (is_of_node(fwnode)) {
	return fwnode_call_ptr_op(fwnode, get_next_child_node, child);
		struct device_node *node;

		node = of_get_next_available_child(to_of_node(fwnode),
						   to_of_node(child));
		if (node)
			return &node->fwnode;
	} else if (is_acpi_node(fwnode)) {
		return acpi_get_next_subnode(fwnode, child);
	}

	return NULL;
}
}
EXPORT_SYMBOL_GPL(fwnode_get_next_child_node);
EXPORT_SYMBOL_GPL(fwnode_get_next_child_node);


@@ -1005,23 +981,7 @@ EXPORT_SYMBOL_GPL(device_get_next_child_node);
struct fwnode_handle *fwnode_get_named_child_node(struct fwnode_handle *fwnode,
struct fwnode_handle *fwnode_get_named_child_node(struct fwnode_handle *fwnode,
						  const char *childname)
						  const char *childname)
{
{
	struct fwnode_handle *child;
	return fwnode_call_ptr_op(fwnode, get_named_child_node, childname);

	/*
	 * Find first matching named child node of this fwnode.
	 * For ACPI this will be a data only sub-node.
	 */
	fwnode_for_each_child_node(fwnode, child) {
		if (is_of_node(child)) {
			if (!of_node_cmp(to_of_node(child)->name, childname))
				return child;
		} else if (is_acpi_data_node(child)) {
			if (acpi_data_node_match(child, childname))
				return child;
		}
	}

	return NULL;
}
}
EXPORT_SYMBOL_GPL(fwnode_get_named_child_node);
EXPORT_SYMBOL_GPL(fwnode_get_named_child_node);


@@ -1043,8 +1003,7 @@ EXPORT_SYMBOL_GPL(device_get_named_child_node);
 */
 */
void fwnode_handle_get(struct fwnode_handle *fwnode)
void fwnode_handle_get(struct fwnode_handle *fwnode)
{
{
	if (is_of_node(fwnode))
	fwnode_call_void_op(fwnode, get);
		of_node_get(to_of_node(fwnode));
}
}
EXPORT_SYMBOL_GPL(fwnode_handle_get);
EXPORT_SYMBOL_GPL(fwnode_handle_get);


@@ -1058,8 +1017,7 @@ EXPORT_SYMBOL_GPL(fwnode_handle_get);
 */
 */
void fwnode_handle_put(struct fwnode_handle *fwnode)
void fwnode_handle_put(struct fwnode_handle *fwnode)
{
{
	if (is_of_node(fwnode))
	fwnode_call_void_op(fwnode, put);
		of_node_put(to_of_node(fwnode));
}
}
EXPORT_SYMBOL_GPL(fwnode_handle_put);
EXPORT_SYMBOL_GPL(fwnode_handle_put);


+90 −0
Original line number Original line Diff line number Diff line
@@ -764,3 +764,93 @@ struct device_node *of_graph_get_remote_node(const struct device_node *node,
	return remote;
	return remote;
}
}
EXPORT_SYMBOL(of_graph_get_remote_node);
EXPORT_SYMBOL(of_graph_get_remote_node);

static void of_fwnode_get(struct fwnode_handle *fwnode)
{
	of_node_get(to_of_node(fwnode));
}

static void of_fwnode_put(struct fwnode_handle *fwnode)
{
	of_node_put(to_of_node(fwnode));
}

static bool of_fwnode_property_present(struct fwnode_handle *fwnode,
				       const char *propname)
{
	return of_property_read_bool(to_of_node(fwnode), propname);
}

static int of_fwnode_property_read_int_array(struct fwnode_handle *fwnode,
					     const char *propname,
					     unsigned int elem_size, void *val,
					     size_t nval)
{
	struct device_node *node = to_of_node(fwnode);

	if (!val)
		return of_property_count_elems_of_size(node, propname,
						       elem_size);

	switch (elem_size) {
	case sizeof(u8):
		return of_property_read_u8_array(node, propname, val, nval);
	case sizeof(u16):
		return of_property_read_u16_array(node, propname, val, nval);
	case sizeof(u32):
		return of_property_read_u32_array(node, propname, val, nval);
	case sizeof(u64):
		return of_property_read_u64_array(node, propname, val, nval);
	}

	return -ENXIO;
}

static int of_fwnode_property_read_string_array(struct fwnode_handle *fwnode,
						const char *propname,
						const char **val, size_t nval)
{
	struct device_node *node = to_of_node(fwnode);

	return val ?
		of_property_read_string_array(node, propname, val, nval) :
		of_property_count_strings(node, propname);
}

static struct fwnode_handle *of_fwnode_get_parent(struct fwnode_handle *fwnode)
{
	return of_fwnode_handle(of_get_parent(to_of_node(fwnode)));
}

static struct fwnode_handle *
of_fwnode_get_next_child_node(struct fwnode_handle *fwnode,
			      struct fwnode_handle *child)
{
	return of_fwnode_handle(of_get_next_available_child(to_of_node(fwnode),
							    to_of_node(child)));
}

static struct fwnode_handle *
of_fwnode_get_named_child_node(struct fwnode_handle *fwnode,
			       const char *childname)
{
	struct device_node *node = to_of_node(fwnode);
	struct device_node *child;

	for_each_available_child_of_node(node, child)
		if (!of_node_cmp(child->name, childname))
			return of_fwnode_handle(child);

	return NULL;
}

const struct fwnode_operations of_fwnode_ops = {
	.get = of_fwnode_get,
	.put = of_fwnode_put,
	.property_present = of_fwnode_property_present,
	.property_read_int_array = of_fwnode_property_read_int_array,
	.property_read_string_array = of_fwnode_property_read_string_array,
	.get_parent = of_fwnode_get_parent,
	.get_next_child_node = of_fwnode_get_next_child_node,
	.get_named_child_node = of_fwnode_get_named_child_node,
};
+4 −0
Original line number Original line Diff line number Diff line
@@ -56,6 +56,9 @@ static inline acpi_handle acpi_device_handle(struct acpi_device *adev)
	acpi_fwnode_handle(adev) : NULL)
	acpi_fwnode_handle(adev) : NULL)
#define ACPI_HANDLE(dev)		acpi_device_handle(ACPI_COMPANION(dev))
#define ACPI_HANDLE(dev)		acpi_device_handle(ACPI_COMPANION(dev))



extern const struct fwnode_operations acpi_fwnode_ops;

static inline struct fwnode_handle *acpi_alloc_fwnode_static(void)
static inline struct fwnode_handle *acpi_alloc_fwnode_static(void)
{
{
	struct fwnode_handle *fwnode;
	struct fwnode_handle *fwnode;
@@ -65,6 +68,7 @@ static inline struct fwnode_handle *acpi_alloc_fwnode_static(void)
		return NULL;
		return NULL;


	fwnode->type = FWNODE_ACPI_STATIC;
	fwnode->type = FWNODE_ACPI_STATIC;
	fwnode->ops = &acpi_fwnode_ops;


	return fwnode;
	return fwnode;
}
}
Loading