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

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
......@@ -57,6 +57,7 @@ static bool acpi_nondev_subnode_extract(const union acpi_object *desc,
dn->name = link->package.elements[0].string.pointer;
dn->fwnode.type = FWNODE_ACPI_DATA;
dn->fwnode.ops = &acpi_fwnode_ops;
dn->parent = parent;
INIT_LIST_HEAD(&dn->data.subnodes);
......@@ -1119,3 +1120,70 @@ int acpi_graph_get_remote_endpoint(struct fwnode_handle *fwnode,
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,
};
......@@ -1436,6 +1436,7 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
device->handle = handle;
device->parent = acpi_bus_get_parent(handle);
device->fwnode.type = FWNODE_ACPI;
device->fwnode.ops = &acpi_fwnode_ops;
acpi_set_device_status(device, sta);
acpi_device_get_busid(device);
acpi_set_pnp_ids(handle, &device->pnp, type);
......
This diff is collapsed.
......@@ -764,3 +764,93 @@ struct device_node *of_graph_get_remote_node(const struct device_node *node,
return remote;
}
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,
};
......@@ -56,6 +56,9 @@ static inline acpi_handle acpi_device_handle(struct acpi_device *adev)
acpi_fwnode_handle(adev) : NULL)
#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)
{
struct fwnode_handle *fwnode;
......@@ -65,6 +68,7 @@ static inline struct fwnode_handle *acpi_alloc_fwnode_static(void)
return NULL;
fwnode->type = FWNODE_ACPI_STATIC;
fwnode->ops = &acpi_fwnode_ops;
return fwnode;
}
......
......@@ -12,6 +12,8 @@
#ifndef _LINUX_FWNODE_H_
#define _LINUX_FWNODE_H_
#include <linux/types.h>
enum fwnode_type {
FWNODE_INVALID = 0,
FWNODE_OF,
......@@ -22,9 +24,12 @@ enum fwnode_type {
FWNODE_IRQCHIP
};
struct fwnode_operations;
struct fwnode_handle {
enum fwnode_type type;
struct fwnode_handle *secondary;
const struct fwnode_operations *ops;
};
/**
......@@ -39,4 +44,53 @@ struct fwnode_endpoint {
const struct fwnode_handle *local_fwnode;
};
/**
* struct fwnode_operations - Operations for fwnode interface
* @get: Get a reference to an fwnode.
* @put: Put a reference to an fwnode.
* @property_present: Return true if a property is present.
* @property_read_integer_array: Read an array of integer properties. Return
* zero on success, a negative error code
* otherwise.
* @property_read_string_array: Read an array of string properties. Return zero
* on success, a negative error code otherwise.
* @get_parent: Return the parent of an fwnode.
* @get_next_child_node: Return the next child node in an iteration.
* @get_named_child_node: Return a child node with a given name.
*/
struct fwnode_operations {
void (*get)(struct fwnode_handle *fwnode);
void (*put)(struct fwnode_handle *fwnode);
bool (*property_present)(struct fwnode_handle *fwnode,
const char *propname);
int (*property_read_int_array)(struct fwnode_handle *fwnode,
const char *propname,
unsigned int elem_size, void *val,
size_t nval);
int (*property_read_string_array)(struct fwnode_handle *fwnode_handle,
const char *propname,
const char **val, size_t nval);
struct fwnode_handle *(*get_parent)(struct fwnode_handle *fwnode);
struct fwnode_handle *
(*get_next_child_node)(struct fwnode_handle *fwnode,
struct fwnode_handle *child);
struct fwnode_handle *
(*get_named_child_node)(struct fwnode_handle *fwnode, const char *name);
};
#define fwnode_has_op(fwnode, op) \
((fwnode) && (fwnode)->ops && (fwnode)->ops->op)
#define fwnode_call_int_op(fwnode, op, ...) \
(fwnode ? (fwnode_has_op(fwnode, op) ? \
(fwnode)->ops->op(fwnode, ## __VA_ARGS__) : -ENXIO) : \
-EINVAL)
#define fwnode_call_ptr_op(fwnode, op, ...) \
(fwnode_has_op(fwnode, op) ? \
(fwnode)->ops->op(fwnode, ## __VA_ARGS__) : NULL)
#define fwnode_call_void_op(fwnode, op, ...) \
do { \
if (fwnode_has_op(fwnode, op)) \
(fwnode)->ops->op(fwnode, ## __VA_ARGS__); \
} while (false)
#endif
......@@ -100,10 +100,12 @@ struct of_reconfig_data {
/* initialize a node */
extern struct kobj_type of_node_ktype;
extern const struct fwnode_operations of_fwnode_ops;
static inline void of_node_init(struct device_node *node)
{
kobject_init(&node->kobj, &of_node_ktype);
node->fwnode.type = FWNODE_OF;
node->fwnode.ops = &of_fwnode_ops;
}
/* true when node is initialized */
......
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