summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-11-04 14:03:59 +0100
committerMax Krummenacher <max.krummenacher@toradex.com>2015-12-26 14:42:52 +0100
commit883f5669962964580e8eada414c6b0d0c93cb005 (patch)
tree8fbf0ce1b02967667aa1850e34c82ba025c36dde /include
parentcb05cdc190621ef4f51800f717af0fa4c49e4adb (diff)
Driver core: Unified interface for firmware node properties
Add new generic routines are provided for retrieving properties from device description objects in the platform firmware in case there are no struct device objects for them (either those objects have not been created yet or they do not exist at all). The following functions are provided: fwnode_property_present() fwnode_property_read_u8() fwnode_property_read_u16() fwnode_property_read_u32() fwnode_property_read_u64() fwnode_property_read_string() fwnode_property_read_u8_array() fwnode_property_read_u16_array() fwnode_property_read_u32_array() fwnode_property_read_u64_array() fwnode_property_read_string_array() in analogy with the corresponding functions for struct device added previously. For all of them, the first argument is a pointer to struct fwnode_handle (new type) that allows a device description object (depending on what platform firmware interface is in use) to be obtained. Add a new macro device_for_each_child_node() for iterating over the children of the device description object associated with a given device and a new function device_get_child_node_count() returning the number of a given device's child nodes. The interface covers both ACPI and Device Trees. Suggested-by: Grant Likely <grant.likely@linaro.org> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Acked-by: Grant Likely <grant.likely@linaro.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> (cherry picked from commit 8a0662d9ed2968e1186208336a8e1fab3fdfea63)
Diffstat (limited to 'include')
-rw-r--r--include/acpi/acpi_bus.h17
-rw-r--r--include/linux/acpi.h26
-rw-r--r--include/linux/of.h43
-rw-r--r--include/linux/property.h70
4 files changed, 155 insertions, 1 deletions
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index 2c95aadbdfb2..46c786eb75d0 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -27,6 +27,7 @@
#define __ACPI_BUS_H__
#include <linux/device.h>
+#include <linux/property.h>
/* TBD: Make dynamic */
#define ACPI_MAX_HANDLES 10
@@ -322,6 +323,7 @@ struct acpi_device_data {
struct acpi_device {
int device_type;
acpi_handle handle; /* no handle for fixed hardware */
+ struct fwnode_handle fwnode;
struct acpi_device *parent;
struct list_head children;
struct list_head node;
@@ -345,6 +347,21 @@ struct acpi_device {
void (*remove)(struct acpi_device *);
};
+static inline bool is_acpi_node(struct fwnode_handle *fwnode)
+{
+ return fwnode && fwnode->type == FWNODE_ACPI;
+}
+
+static inline struct acpi_device *acpi_node(struct fwnode_handle *fwnode)
+{
+ return fwnode ? container_of(fwnode, struct acpi_device, fwnode) : NULL;
+}
+
+static inline struct fwnode_handle *acpi_fwnode_handle(struct acpi_device *adev)
+{
+ return &adev->fwnode;
+}
+
static inline void *acpi_driver_data(struct acpi_device *d)
{
return d->driver_data;
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index d0e959094c33..8f8c5ecec3a3 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -432,6 +432,23 @@ int acpi_device_modalias(struct device *, char *, int);
#define ACPI_COMPANION_SET(dev, adev) do { } while (0)
#define ACPI_HANDLE(dev) (NULL)
+struct fwnode_handle;
+
+static inline bool is_acpi_node(struct fwnode_handle *fwnode)
+{
+ return false;
+}
+
+static inline struct acpi_device *acpi_node(struct fwnode_handle *fwnode)
+{
+ return NULL;
+}
+
+static inline struct fwnode_handle *acpi_fwnode_handle(struct acpi_device *adev)
+{
+ return NULL;
+}
+
static inline const char *acpi_dev_name(struct acpi_device *adev)
{
return NULL;
@@ -670,6 +687,9 @@ int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname,
enum dev_prop_type proptype, void *val);
int acpi_dev_prop_read(struct acpi_device *adev, const char *propname,
enum dev_prop_type proptype, void *val, size_t nval);
+
+struct acpi_device *acpi_get_next_child(struct device *dev,
+ struct acpi_device *child);
#else
static inline int acpi_dev_get_property(struct acpi_device *adev,
const char *name, acpi_object_type type,
@@ -714,6 +734,12 @@ static inline int acpi_dev_prop_read(struct acpi_device *adev,
return -ENXIO;
}
+static inline struct acpi_device *acpi_get_next_child(struct device *dev,
+ struct acpi_device *child)
+{
+ return NULL;
+}
+
#endif
#endif /*_LINUX_ACPI_H*/
diff --git a/include/linux/of.h b/include/linux/of.h
index 42a5443091d1..ca34c3ca2613 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -49,6 +49,7 @@ struct device_node {
const char *type;
phandle phandle;
const char *full_name;
+ struct fwnode_handle fwnode;
struct property *properties;
struct property *deadprops; /* removed properties */
@@ -75,6 +76,26 @@ struct of_phandle_args {
uint32_t args[MAX_PHANDLE_ARGS];
};
+/* initialize a node */
+extern struct kobj_type of_node_ktype;
+static inline void of_node_init(struct device_node *node)
+{
+ kobject_init(&node->kobj, &of_node_ktype);
+ node->fwnode.type = FWNODE_OF;
+}
+
+/* true when node is initialized */
+static inline int of_node_is_initialized(struct device_node *node)
+{
+ return node && node->kobj.state_initialized;
+}
+
+/* true when node is attached (i.e. present on sysfs) */
+static inline int of_node_is_attached(struct device_node *node)
+{
+ return node && node->kobj.state_in_sysfs;
+}
+
#ifdef CONFIG_OF_DYNAMIC
extern struct device_node *of_node_get(struct device_node *node);
extern void of_node_put(struct device_node *node);
@@ -95,6 +116,16 @@ extern struct device_node *of_chosen;
extern struct device_node *of_aliases;
extern raw_spinlock_t devtree_lock;
+static inline bool is_of_node(struct fwnode_handle *fwnode)
+{
+ return fwnode && fwnode->type == FWNODE_OF;
+}
+
+static inline struct device_node *of_node(struct fwnode_handle *fwnode)
+{
+ return fwnode ? container_of(fwnode, struct device_node, fwnode) : NULL;
+}
+
static inline bool of_have_populated_dt(void)
{
return of_allnodes != NULL;
@@ -310,7 +341,17 @@ int of_device_is_stdout_path(struct device_node *dn);
#else /* CONFIG_OF */
-static inline const char* of_node_full_name(struct device_node *np)
+static inline bool is_of_node(struct fwnode_handle *fwnode)
+{
+ return false;
+}
+
+static inline struct device_node *of_node(struct fwnode_handle *fwnode)
+{
+ return NULL;
+}
+
+static inline const char* of_node_full_name(const struct device_node *np)
{
return "<no-node>";
}
diff --git a/include/linux/property.h b/include/linux/property.h
index 9242fb0221ba..a6a3d98bd7e9 100644
--- a/include/linux/property.h
+++ b/include/linux/property.h
@@ -40,6 +40,46 @@ int device_property_read_string_array(struct device *dev, const char *propname,
int device_property_read_string(struct device *dev, const char *propname,
const char **val);
+enum fwnode_type {
+ FWNODE_INVALID = 0,
+ FWNODE_OF,
+ FWNODE_ACPI,
+};
+
+struct fwnode_handle {
+ enum fwnode_type type;
+};
+
+bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname);
+int fwnode_property_read_u8_array(struct fwnode_handle *fwnode,
+ const char *propname, u8 *val,
+ size_t nval);
+int fwnode_property_read_u16_array(struct fwnode_handle *fwnode,
+ const char *propname, u16 *val,
+ size_t nval);
+int fwnode_property_read_u32_array(struct fwnode_handle *fwnode,
+ const char *propname, u32 *val,
+ size_t nval);
+int fwnode_property_read_u64_array(struct fwnode_handle *fwnode,
+ const char *propname, u64 *val,
+ size_t nval);
+int fwnode_property_read_string_array(struct fwnode_handle *fwnode,
+ const char *propname, const char **val,
+ size_t nval);
+int fwnode_property_read_string(struct fwnode_handle *fwnode,
+ const char *propname, const char **val);
+
+struct fwnode_handle *device_get_next_child_node(struct device *dev,
+ struct fwnode_handle *child);
+
+#define device_for_each_child_node(dev, child) \
+ for (child = device_get_next_child_node(dev, NULL); child; \
+ child = device_get_next_child_node(dev, child))
+
+void fwnode_handle_put(struct fwnode_handle *fwnode);
+
+unsigned int device_get_child_node_count(struct device *dev);
+
static inline bool device_property_read_bool(struct device *dev,
const char *propname)
{
@@ -70,4 +110,34 @@ static inline int device_property_read_u64(struct device *dev,
return device_property_read_u64_array(dev, propname, val, 1);
}
+static inline bool fwnode_property_read_bool(struct fwnode_handle *fwnode,
+ const char *propname)
+{
+ return fwnode_property_present(fwnode, propname);
+}
+
+static inline int fwnode_property_read_u8(struct fwnode_handle *fwnode,
+ const char *propname, u8 *val)
+{
+ return fwnode_property_read_u8_array(fwnode, propname, val, 1);
+}
+
+static inline int fwnode_property_read_u16(struct fwnode_handle *fwnode,
+ const char *propname, u16 *val)
+{
+ return fwnode_property_read_u16_array(fwnode, propname, val, 1);
+}
+
+static inline int fwnode_property_read_u32(struct fwnode_handle *fwnode,
+ const char *propname, u32 *val)
+{
+ return fwnode_property_read_u32_array(fwnode, propname, val, 1);
+}
+
+static inline int fwnode_property_read_u64(struct fwnode_handle *fwnode,
+ const char *propname, u64 *val)
+{
+ return fwnode_property_read_u64_array(fwnode, propname, val, 1);
+}
+
#endif /* _LINUX_PROPERTY_H_ */