Commit 613e9721 authored by Adam Thomson's avatar Adam Thomson Committed by Mark Brown

device property: Add function to search for named child of device

For device nodes in both DT and ACPI, it possible to have named
child nodes which contain properties (an existing example being
gpio-leds). This adds a function to find a named child node for
a device which can be used by drivers for property retrieval.

For DT data node name matching, of_node_cmp() and similar functions
are made available outside of CONFIG_OF block so the new function
can reference these for DT and non-DT builds.

For ACPI data node name matching, a helper function is also added
which returns false if CONFIG_ACPI is not set, otherwise it
performs a string comparison on the data node name. This avoids
using the acpi_data_node struct for non CONFIG_ACPI builds,
which would otherwise cause a build failure.
Signed-off-by: default avatarAdam Thomson <Adam.Thomson.Opensource@diasemi.com>
Acked-by: default avatarSathyanarayana Nujella <sathyanarayana.nujella@intel.com>
Acked-by: default avatarRob Herring <robh@kernel.org>
Acked-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 1a695a90
...@@ -887,6 +887,34 @@ struct fwnode_handle *device_get_next_child_node(struct device *dev, ...@@ -887,6 +887,34 @@ struct fwnode_handle *device_get_next_child_node(struct device *dev,
} }
EXPORT_SYMBOL_GPL(device_get_next_child_node); EXPORT_SYMBOL_GPL(device_get_next_child_node);
/**
* device_get_named_child_node - Return first matching named child node handle
* @dev: Device to find the named child node for.
* @childname: String to match child node name against.
*/
struct fwnode_handle *device_get_named_child_node(struct device *dev,
const char *childname)
{
struct fwnode_handle *child;
/*
* Find first matching named child node of this device.
* For ACPI this will be a data only sub-node.
*/
device_for_each_child_node(dev, child) {
if (is_of_node(child)) {
if (!of_node_cmp(to_of_node(child)->name, childname))
return child;
} else if (is_acpi_data_node(child)) {
if (acpi_data_node_match(child, childname))
return child;
}
}
return NULL;
}
EXPORT_SYMBOL_GPL(device_get_named_child_node);
/** /**
* fwnode_handle_put - Drop reference to a device node * fwnode_handle_put - Drop reference to a device node
* @fwnode: Pointer to the device node to drop the reference to. * @fwnode: Pointer to the device node to drop the reference to.
......
...@@ -420,6 +420,13 @@ static inline struct acpi_data_node *to_acpi_data_node(struct fwnode_handle *fwn ...@@ -420,6 +420,13 @@ static inline struct acpi_data_node *to_acpi_data_node(struct fwnode_handle *fwn
container_of(fwnode, struct acpi_data_node, fwnode) : NULL; container_of(fwnode, struct acpi_data_node, fwnode) : NULL;
} }
static inline bool acpi_data_node_match(struct fwnode_handle *fwnode,
const char *name)
{
return is_acpi_data_node(fwnode) ?
(!strcmp(to_acpi_data_node(fwnode)->name, name)) : false;
}
static inline struct fwnode_handle *acpi_fwnode_handle(struct acpi_device *adev) static inline struct fwnode_handle *acpi_fwnode_handle(struct acpi_device *adev)
{ {
return &adev->fwnode; return &adev->fwnode;
......
...@@ -568,6 +568,12 @@ static inline struct acpi_data_node *to_acpi_data_node(struct fwnode_handle *fwn ...@@ -568,6 +568,12 @@ static inline struct acpi_data_node *to_acpi_data_node(struct fwnode_handle *fwn
return NULL; return NULL;
} }
static inline bool acpi_data_node_match(struct fwnode_handle *fwnode,
const char *name)
{
return false;
}
static inline struct fwnode_handle *acpi_fwnode_handle(struct acpi_device *adev) static inline struct fwnode_handle *acpi_fwnode_handle(struct acpi_device *adev)
{ {
return NULL; return NULL;
......
...@@ -238,13 +238,6 @@ static inline unsigned long of_read_ulong(const __be32 *cell, int size) ...@@ -238,13 +238,6 @@ static inline unsigned long of_read_ulong(const __be32 *cell, int size)
#define OF_ROOT_NODE_SIZE_CELLS_DEFAULT 1 #define OF_ROOT_NODE_SIZE_CELLS_DEFAULT 1
#endif #endif
/* Default string compare functions, Allow arch asm/prom.h to override */
#if !defined(of_compat_cmp)
#define of_compat_cmp(s1, s2, l) strcasecmp((s1), (s2))
#define of_prop_cmp(s1, s2) strcmp((s1), (s2))
#define of_node_cmp(s1, s2) strcasecmp((s1), (s2))
#endif
#define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags) #define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags)
#define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags) #define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags)
...@@ -726,6 +719,13 @@ static inline void of_property_clear_flag(struct property *p, unsigned long flag ...@@ -726,6 +719,13 @@ static inline void of_property_clear_flag(struct property *p, unsigned long flag
#define of_match_node(_matches, _node) NULL #define of_match_node(_matches, _node) NULL
#endif /* CONFIG_OF */ #endif /* CONFIG_OF */
/* Default string compare functions, Allow arch asm/prom.h to override */
#if !defined(of_compat_cmp)
#define of_compat_cmp(s1, s2, l) strcasecmp((s1), (s2))
#define of_prop_cmp(s1, s2) strcmp((s1), (s2))
#define of_node_cmp(s1, s2) strcasecmp((s1), (s2))
#endif
#if defined(CONFIG_OF) && defined(CONFIG_NUMA) #if defined(CONFIG_OF) && defined(CONFIG_NUMA)
extern int of_node_to_nid(struct device_node *np); extern int of_node_to_nid(struct device_node *np);
#else #else
......
...@@ -77,6 +77,9 @@ struct fwnode_handle *device_get_next_child_node(struct device *dev, ...@@ -77,6 +77,9 @@ struct fwnode_handle *device_get_next_child_node(struct device *dev,
for (child = device_get_next_child_node(dev, NULL); child; \ for (child = device_get_next_child_node(dev, NULL); child; \
child = device_get_next_child_node(dev, child)) child = device_get_next_child_node(dev, child))
struct fwnode_handle *device_get_named_child_node(struct device *dev,
const char *childname);
void fwnode_handle_put(struct fwnode_handle *fwnode); void fwnode_handle_put(struct fwnode_handle *fwnode);
unsigned int device_get_child_node_count(struct device *dev); unsigned int device_get_child_node_count(struct device *dev);
......
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