mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-22 14:41:27 +00:00
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: Dmitry Torokhov <dmitry.torokhov@gmail.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
parent
996b0830f9
commit
e64b674bc9
2 changed files with 82 additions and 24 deletions
|
@ -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,
|
||||||
{
|
{
|
||||||
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;
|
||||||
|
|
||||||
refnode = software_node_fwnode(ref->refs[index].node);
|
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_args->node);
|
||||||
if (!refnode)
|
if (!refnode)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
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,
|
||||||
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 {
|
||||||
#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 {
|
||||||
__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 {
|
||||||
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 {
|
||||||
.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,
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* 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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue