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

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
...@@ -246,6 +246,13 @@ static int property_entry_copy_data(struct property_entry *dst, ...@@ -246,6 +246,13 @@ static int property_entry_copy_data(struct property_entry *dst,
if (!src->is_inline && !src->length) if (!src->is_inline && !src->length)
return -ENODATA; 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)) { if (src->length <= sizeof(dst->value)) {
dst_ptr = &dst->value; dst_ptr = &dst->value;
dst->is_inline = true; dst->is_inline = true;
...@@ -473,23 +480,49 @@ software_node_get_reference_args(const struct fwnode_handle *fwnode, ...@@ -473,23 +480,49 @@ software_node_get_reference_args(const struct fwnode_handle *fwnode,
{ {
struct swnode *swnode = to_swnode(fwnode); struct swnode *swnode = to_swnode(fwnode);
const struct software_node_reference *ref; 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; const struct property_entry *prop;
struct fwnode_handle *refnode; struct fwnode_handle *refnode;
u32 nargs_prop_val; u32 nargs_prop_val;
int error; int error;
int i; int i;
if (!swnode || !swnode->node->references) if (!swnode)
return -ENOENT; return -ENOENT;
for (ref = swnode->node->references; ref->name; ref++) prop = property_entry_get(swnode->node->properties, propname);
if (!strcmp(ref->name, propname)) if (prop) {
break; if (prop->type != DEV_PROP_REF)
return -EINVAL;
if (!ref->name || index > (ref->nrefs - 1)) /*
return -ENOENT; * 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++)
if (!strcmp(ref->name, propname))
break;
if (!ref->name || index > (ref->nrefs - 1))
return -ENOENT;
ref_args = &ref->refs[index];
}
refnode = software_node_fwnode(ref->refs[index].node); refnode = software_node_fwnode(ref_args->node);
if (!refnode) if (!refnode)
return -ENOENT; return -ENOENT;
...@@ -510,7 +543,7 @@ software_node_get_reference_args(const struct fwnode_handle *fwnode, ...@@ -510,7 +543,7 @@ software_node_get_reference_args(const struct fwnode_handle *fwnode,
args->nargs = nargs; args->nargs = nargs;
for (i = 0; i < nargs; i++) for (i = 0; i < nargs; i++)
args->args[i] = ref->refs[index].args[i]; args->args[i] = ref_args->args[i];
return 0; return 0;
} }
......
...@@ -22,6 +22,7 @@ enum dev_prop_type { ...@@ -22,6 +22,7 @@ enum dev_prop_type {
DEV_PROP_U32, DEV_PROP_U32,
DEV_PROP_U64, DEV_PROP_U64,
DEV_PROP_STRING, DEV_PROP_STRING,
DEV_PROP_REF,
}; };
enum dev_dma_attr { enum dev_dma_attr {
...@@ -223,6 +224,20 @@ static inline int fwnode_property_count_u64(const struct fwnode_handle *fwnode, ...@@ -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); 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. * struct property_entry - "Built-in" device property representation.
* @name: Name of the property. * @name: Name of the property.
...@@ -258,14 +273,20 @@ struct property_entry { ...@@ -258,14 +273,20 @@ struct property_entry {
#define __PROPERTY_ENTRY_ELEMENT_SIZE(_elem_) \ #define __PROPERTY_ENTRY_ELEMENT_SIZE(_elem_) \
sizeof(((struct property_entry *)NULL)->value._elem_[0]) 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) { \ (struct property_entry) { \
.name = _name_, \ .name = _name_, \
.length = (_len_) * __PROPERTY_ENTRY_ELEMENT_SIZE(_elem_), \ .length = (_len_) * (_elsize_), \
.type = DEV_PROP_##_Type_, \ .type = DEV_PROP_##_Type_, \
{ .pointer = _val_ }, \ { .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_) \ #define PROPERTY_ENTRY_U8_ARRAY_LEN(_name_, _val_, _len_) \
__PROPERTY_ENTRY_ARRAY_LEN(_name_, u8_data, U8, _val_, _len_) __PROPERTY_ENTRY_ARRAY_LEN(_name_, u8_data, U8, _val_, _len_)
#define PROPERTY_ENTRY_U16_ARRAY_LEN(_name_, _val_, _len_) \ #define PROPERTY_ENTRY_U16_ARRAY_LEN(_name_, _val_, _len_) \
...@@ -276,6 +297,10 @@ struct property_entry { ...@@ -276,6 +297,10 @@ struct property_entry {
__PROPERTY_ENTRY_ARRAY_LEN(_name_, u64_data, U64, _val_, _len_) __PROPERTY_ENTRY_ARRAY_LEN(_name_, u64_data, U64, _val_, _len_)
#define PROPERTY_ENTRY_STRING_ARRAY_LEN(_name_, _val_, _len_) \ #define PROPERTY_ENTRY_STRING_ARRAY_LEN(_name_, _val_, _len_) \
__PROPERTY_ENTRY_ARRAY_LEN(_name_, str, STRING, _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_) \ #define PROPERTY_ENTRY_U8_ARRAY(_name_, _val_) \
PROPERTY_ENTRY_U8_ARRAY_LEN(_name_, _val_, ARRAY_SIZE(_val_)) PROPERTY_ENTRY_U8_ARRAY_LEN(_name_, _val_, ARRAY_SIZE(_val_))
...@@ -287,6 +312,8 @@ struct property_entry { ...@@ -287,6 +312,8 @@ struct property_entry {
PROPERTY_ENTRY_U64_ARRAY_LEN(_name_, _val_, ARRAY_SIZE(_val_)) PROPERTY_ENTRY_U64_ARRAY_LEN(_name_, _val_, ARRAY_SIZE(_val_))
#define PROPERTY_ENTRY_STRING_ARRAY(_name_, _val_) \ #define PROPERTY_ENTRY_STRING_ARRAY(_name_, _val_) \
PROPERTY_ENTRY_STRING_ARRAY_LEN(_name_, _val_, ARRAY_SIZE(_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_) \ #define __PROPERTY_ENTRY_ELEMENT(_name_, _elem_, _Type_, _val_) \
(struct property_entry) { \ (struct property_entry) { \
...@@ -314,6 +341,18 @@ struct property_entry { ...@@ -314,6 +341,18 @@ struct property_entry {
.is_inline = true, \ .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 * struct property_entry *
property_entries_dup(const struct property_entry *properties); property_entries_dup(const struct property_entry *properties);
...@@ -377,20 +416,6 @@ int fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode, ...@@ -377,20 +416,6 @@ int fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode,
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
/* Software fwnode support - when HW description is incomplete or missing */ /* 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 * struct software_node_reference - Named software node reference property
* @name: Name of the property * @name: Name of the property
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment