Commit e64b674b authored by Dmitry Torokhov's avatar Dmitry Torokhov Committed by Rafael J. Wysocki
Browse files

software node: implement reference properties



It is possible to store references to software nodes in the same fashion as
other static properties, so that users do not need to define separate
structures:

static const struct software_node gpio_bank_b_node = {
	.name = "B",
};

static const struct property_entry simone_key_enter_props[] = {
	PROPERTY_ENTRY_U32("linux,code", KEY_ENTER),
	PROPERTY_ENTRY_STRING("label", "enter"),
	PROPERTY_ENTRY_REF("gpios", &gpio_bank_b_node, 123, GPIO_ACTIVE_LOW),
	{ }
};

Signed-off-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 996b0830
Loading
Loading
Loading
Loading
+41 −8
Original line number Diff line number Diff line
@@ -246,6 +246,13 @@ static int property_entry_copy_data(struct property_entry *dst,
	if (!src->is_inline && !src->length)
		return -ENODATA;

	/*
	 * Reference properties are never stored inline as
	 * they are too big.
	 */
	if (src->type == DEV_PROP_REF && src->is_inline)
		return -EINVAL;

	if (src->length <= sizeof(dst->value)) {
		dst_ptr = &dst->value;
		dst->is_inline = true;
@@ -473,13 +480,36 @@ software_node_get_reference_args(const struct fwnode_handle *fwnode,
{
	struct swnode *swnode = to_swnode(fwnode);
	const struct software_node_reference *ref;
	const struct software_node_ref_args *ref_array;
	const struct software_node_ref_args *ref_args;
	const struct property_entry *prop;
	struct fwnode_handle *refnode;
	u32 nargs_prop_val;
	int error;
	int i;

	if (!swnode || !swnode->node->references)
	if (!swnode)
		return -ENOENT;

	prop = property_entry_get(swnode->node->properties, propname);
	if (prop) {
		if (prop->type != DEV_PROP_REF)
			return -EINVAL;

		/*
		 * We expect that references are never stored inline, even
		 * single ones, as they are too big.
		 */
		if (prop->is_inline)
			return -EINVAL;

		if (index * sizeof(*ref_args) >= prop->length)
			return -ENOENT;

		ref_array = prop->pointer;
		ref_args = &ref_array[index];
	} else {
		if (!swnode->node->references)
			return -ENOENT;

		for (ref = swnode->node->references; ref->name; ref++)
@@ -489,7 +519,10 @@ software_node_get_reference_args(const struct fwnode_handle *fwnode,
		if (!ref->name || index > (ref->nrefs - 1))
			return -ENOENT;

	refnode = software_node_fwnode(ref->refs[index].node);
		ref_args = &ref->refs[index];
	}

	refnode = software_node_fwnode(ref_args->node);
	if (!refnode)
		return -ENOENT;

@@ -510,7 +543,7 @@ software_node_get_reference_args(const struct fwnode_handle *fwnode,
	args->nargs = nargs;

	for (i = 0; i < nargs; i++)
		args->args[i] = ref->refs[index].args[i];
		args->args[i] = ref_args->args[i];

	return 0;
}
+41 −16
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ enum dev_prop_type {
	DEV_PROP_U32,
	DEV_PROP_U64,
	DEV_PROP_STRING,
	DEV_PROP_REF,
};

enum dev_dma_attr {
@@ -223,6 +224,20 @@ static inline int fwnode_property_count_u64(const struct fwnode_handle *fwnode,
	return fwnode_property_read_u64_array(fwnode, propname, NULL, 0);
}

struct software_node;

/**
 * struct software_node_ref_args - Reference property with additional arguments
 * @node: Reference to a software node
 * @nargs: Number of elements in @args array
 * @args: Integer arguments
 */
struct software_node_ref_args {
	const struct software_node *node;
	unsigned int nargs;
	u64 args[NR_FWNODE_REFERENCE_ARGS];
};

/**
 * struct property_entry - "Built-in" device property representation.
 * @name: Name of the property.
@@ -258,14 +273,20 @@ struct property_entry {
#define __PROPERTY_ENTRY_ELEMENT_SIZE(_elem_)				\
	sizeof(((struct property_entry *)NULL)->value._elem_[0])

#define __PROPERTY_ENTRY_ARRAY_LEN(_name_, _elem_, _Type_, _val_, _len_)\
#define __PROPERTY_ENTRY_ARRAY_ELSIZE_LEN(_name_, _elsize_, _Type_,	\
					  _val_, _len_)			\
(struct property_entry) {						\
	.name = _name_,							\
	.length = (_len_) * __PROPERTY_ENTRY_ELEMENT_SIZE(_elem_),	\
	.length = (_len_) * (_elsize_),					\
	.type = DEV_PROP_##_Type_,					\
	{ .pointer = _val_ },						\
}

#define __PROPERTY_ENTRY_ARRAY_LEN(_name_, _elem_, _Type_, _val_, _len_)\
	__PROPERTY_ENTRY_ARRAY_ELSIZE_LEN(_name_,			\
				__PROPERTY_ENTRY_ELEMENT_SIZE(_elem_),	\
				_Type_, _val_, _len_)

#define PROPERTY_ENTRY_U8_ARRAY_LEN(_name_, _val_, _len_)		\
	__PROPERTY_ENTRY_ARRAY_LEN(_name_, u8_data, U8, _val_, _len_)
#define PROPERTY_ENTRY_U16_ARRAY_LEN(_name_, _val_, _len_)		\
@@ -276,6 +297,10 @@ struct property_entry {
	__PROPERTY_ENTRY_ARRAY_LEN(_name_, u64_data, U64, _val_, _len_)
#define PROPERTY_ENTRY_STRING_ARRAY_LEN(_name_, _val_, _len_)		\
	__PROPERTY_ENTRY_ARRAY_LEN(_name_, str, STRING, _val_, _len_)
#define PROPERTY_ENTRY_REF_ARRAY_LEN(_name_, _val_, _len_)		\
	__PROPERTY_ENTRY_ARRAY_ELSIZE_LEN(_name_,			\
				sizeof(struct software_node_ref_args),	\
				REF, _val_, _len_)

#define PROPERTY_ENTRY_U8_ARRAY(_name_, _val_)				\
	PROPERTY_ENTRY_U8_ARRAY_LEN(_name_, _val_, ARRAY_SIZE(_val_))
@@ -287,6 +312,8 @@ struct property_entry {
	PROPERTY_ENTRY_U64_ARRAY_LEN(_name_, _val_, ARRAY_SIZE(_val_))
#define PROPERTY_ENTRY_STRING_ARRAY(_name_, _val_)			\
	PROPERTY_ENTRY_STRING_ARRAY_LEN(_name_, _val_, ARRAY_SIZE(_val_))
#define PROPERTY_ENTRY_REF_ARRAY(_name_, _val_)			\
	PROPERTY_ENTRY_REF_ARRAY_LEN(_name_, _val_, ARRAY_SIZE(_val_))

#define __PROPERTY_ENTRY_ELEMENT(_name_, _elem_, _Type_, _val_)		\
(struct property_entry) {						\
@@ -314,6 +341,18 @@ struct property_entry {
	.is_inline = true,			\
}

#define PROPERTY_ENTRY_REF(_name_, _ref_, ...)				\
(struct property_entry) {						\
	.name = _name_,							\
	.length = sizeof(struct software_node_ref_args),		\
	.type = DEV_PROP_REF,						\
	{ .pointer = &(const struct software_node_ref_args) {		\
		.node = _ref_,						\
		.nargs = ARRAY_SIZE(((u64[]){ 0, ##__VA_ARGS__ })) - 1,	\
		.args = { __VA_ARGS__ },				\
	} },								\
}

struct property_entry *
property_entries_dup(const struct property_entry *properties);

@@ -377,20 +416,6 @@ int fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode,
/* -------------------------------------------------------------------------- */
/* Software fwnode support - when HW description is incomplete or missing */

struct software_node;

/**
 * struct software_node_ref_args - Reference with additional arguments
 * @node: Reference to a software node
 * @nargs: Number of elements in @args array
 * @args: Integer arguments
 */
struct software_node_ref_args {
	const struct software_node *node;
	unsigned int nargs;
	u64 args[NR_FWNODE_REFERENCE_ARGS];
};

/**
 * struct software_node_reference - Named software node reference property
 * @name: Name of the property