summaryrefslogtreecommitdiffstats
path: root/drivers/of/property.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/of/property.c')
-rw-r--r--drivers/of/property.c83
1 files changed, 65 insertions, 18 deletions
diff --git a/drivers/of/property.c b/drivers/of/property.c
index 9eb45f69db2f..fbb72116e9d4 100644
--- a/drivers/of/property.c
+++ b/drivers/of/property.c
@@ -707,6 +707,15 @@ struct device_node *of_graph_get_port_parent(struct device_node *node)
{
unsigned int depth;
+ if (!node)
+ return NULL;
+
+ /*
+ * Preserve usecount for passed in node as of_get_next_parent()
+ * will do of_node_put() on it.
+ */
+ of_node_get(node);
+
/* Walk 3 levels up only if there is 'ports' node. */
for (depth = 3; depth && node; depth--) {
node = of_get_next_parent(node);
@@ -727,12 +736,16 @@ EXPORT_SYMBOL(of_graph_get_port_parent);
struct device_node *of_graph_get_remote_port_parent(
const struct device_node *node)
{
- struct device_node *np;
+ struct device_node *np, *pp;
/* Get remote endpoint node. */
np = of_graph_get_remote_endpoint(node);
- return of_graph_get_port_parent(np);
+ pp = of_graph_get_port_parent(np);
+
+ of_node_put(np);
+
+ return pp;
}
EXPORT_SYMBOL(of_graph_get_remote_port_parent);
@@ -814,23 +827,23 @@ static void of_fwnode_put(struct fwnode_handle *fwnode)
of_node_put(to_of_node(fwnode));
}
-static bool of_fwnode_device_is_available(struct fwnode_handle *fwnode)
+static bool of_fwnode_device_is_available(const struct fwnode_handle *fwnode)
{
return of_device_is_available(to_of_node(fwnode));
}
-static bool of_fwnode_property_present(struct fwnode_handle *fwnode,
+static bool of_fwnode_property_present(const 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,
+static int of_fwnode_property_read_int_array(const struct fwnode_handle *fwnode,
const char *propname,
unsigned int elem_size, void *val,
size_t nval)
{
- struct device_node *node = to_of_node(fwnode);
+ const struct device_node *node = to_of_node(fwnode);
if (!val)
return of_property_count_elems_of_size(node, propname,
@@ -850,24 +863,26 @@ static int of_fwnode_property_read_int_array(struct fwnode_handle *fwnode,
return -ENXIO;
}
-static int of_fwnode_property_read_string_array(struct fwnode_handle *fwnode,
- const char *propname,
- const char **val, size_t nval)
+static int
+of_fwnode_property_read_string_array(const struct fwnode_handle *fwnode,
+ const char *propname, const char **val,
+ size_t nval)
{
- struct device_node *node = to_of_node(fwnode);
+ const 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)
+static struct fwnode_handle *
+of_fwnode_get_parent(const 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,
+of_fwnode_get_next_child_node(const struct fwnode_handle *fwnode,
struct fwnode_handle *child)
{
return of_fwnode_handle(of_get_next_available_child(to_of_node(fwnode),
@@ -875,10 +890,10 @@ of_fwnode_get_next_child_node(struct fwnode_handle *fwnode,
}
static struct fwnode_handle *
-of_fwnode_get_named_child_node(struct fwnode_handle *fwnode,
+of_fwnode_get_named_child_node(const struct fwnode_handle *fwnode,
const char *childname)
{
- struct device_node *node = to_of_node(fwnode);
+ const struct device_node *node = to_of_node(fwnode);
struct device_node *child;
for_each_available_child_of_node(node, child)
@@ -888,8 +903,38 @@ of_fwnode_get_named_child_node(struct fwnode_handle *fwnode,
return NULL;
}
+static int
+of_fwnode_get_reference_args(const struct fwnode_handle *fwnode,
+ const char *prop, const char *nargs_prop,
+ unsigned int nargs, unsigned int index,
+ struct fwnode_reference_args *args)
+{
+ struct of_phandle_args of_args;
+ unsigned int i;
+ int ret;
+
+ if (nargs_prop)
+ ret = of_parse_phandle_with_args(to_of_node(fwnode), prop,
+ nargs_prop, index, &of_args);
+ else
+ ret = of_parse_phandle_with_fixed_args(to_of_node(fwnode), prop,
+ nargs, index, &of_args);
+ if (ret < 0)
+ return ret;
+ if (!args)
+ return 0;
+
+ args->nargs = of_args.args_count;
+ args->fwnode = of_fwnode_handle(of_args.np);
+
+ for (i = 0; i < NR_FWNODE_REFERENCE_ARGS; i++)
+ args->args[i] = i < of_args.args_count ? of_args.args[i] : 0;
+
+ return 0;
+}
+
static struct fwnode_handle *
-of_fwnode_graph_get_next_endpoint(struct fwnode_handle *fwnode,
+of_fwnode_graph_get_next_endpoint(const struct fwnode_handle *fwnode,
struct fwnode_handle *prev)
{
return of_fwnode_handle(of_graph_get_next_endpoint(to_of_node(fwnode),
@@ -897,7 +942,7 @@ of_fwnode_graph_get_next_endpoint(struct fwnode_handle *fwnode,
}
static struct fwnode_handle *
-of_fwnode_graph_get_remote_endpoint(struct fwnode_handle *fwnode)
+of_fwnode_graph_get_remote_endpoint(const struct fwnode_handle *fwnode)
{
return of_fwnode_handle(
of_graph_get_remote_endpoint(to_of_node(fwnode)));
@@ -920,10 +965,10 @@ of_fwnode_graph_get_port_parent(struct fwnode_handle *fwnode)
return of_fwnode_handle(of_get_next_parent(np));
}
-static int of_fwnode_graph_parse_endpoint(struct fwnode_handle *fwnode,
+static int of_fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode,
struct fwnode_endpoint *endpoint)
{
- struct device_node *node = to_of_node(fwnode);
+ const struct device_node *node = to_of_node(fwnode);
struct device_node *port_node = of_get_parent(node);
endpoint->local_fwnode = fwnode;
@@ -946,8 +991,10 @@ const struct fwnode_operations of_fwnode_ops = {
.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,
+ .get_reference_args = of_fwnode_get_reference_args,
.graph_get_next_endpoint = of_fwnode_graph_get_next_endpoint,
.graph_get_remote_endpoint = of_fwnode_graph_get_remote_endpoint,
.graph_get_port_parent = of_fwnode_graph_get_port_parent,
.graph_parse_endpoint = of_fwnode_graph_parse_endpoint,
};
+EXPORT_SYMBOL_GPL(of_fwnode_ops);