]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - drivers/of/property.c
Merge tag 'devicetree-for-4.14' of git://git.kernel.org/pub/scm/linux/kernel/git...
[mirror_ubuntu-bionic-kernel.git] / drivers / of / property.c
index 9eb45f69db2fe0b68fa952b1c9289f28f28e9510..fbb72116e9d456b8a08672391de9e2cc144ed171 100644 (file)
@@ -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);