diff options
author | Sakari Ailus <sakari.ailus@linux.intel.com> | 2017-07-21 08:11:49 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2017-07-21 18:04:51 -0400 |
commit | 3e3119d3088f41106f3581d39e7694a50ca3fc02 (patch) | |
tree | b7215757dd95eda454860929de50319ca5f5d432 | |
parent | 37ba983cfb47cc7b353146422c437468fcb29c61 (diff) |
device property: Introduce fwnode_property_get_reference_args
The new fwnode_property_get_reference_args() interface amends the fwnode
property API with the functionality of both of_parse_phandle_with_args()
and __acpi_node_get_property_reference().
The semantics is slightly different: the cells property is ignored on ACPI
as the number of arguments can be explicitly obtained from the firmware
interface.
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r-- | drivers/acpi/property.c | 27 | ||||
-rw-r--r-- | drivers/base/property.c | 28 | ||||
-rw-r--r-- | drivers/of/property.c | 31 | ||||
-rw-r--r-- | include/linux/fwnode.h | 19 | ||||
-rw-r--r-- | include/linux/property.h | 4 |
5 files changed, 109 insertions, 0 deletions
diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c index f8d60051efb8..681a84312dee 100644 --- a/drivers/acpi/property.c +++ b/drivers/acpi/property.c | |||
@@ -1195,6 +1195,32 @@ acpi_fwnode_get_named_child_node(const struct fwnode_handle *fwnode, | |||
1195 | return NULL; | 1195 | return NULL; |
1196 | } | 1196 | } |
1197 | 1197 | ||
1198 | static int | ||
1199 | acpi_fwnode_get_reference_args(const struct fwnode_handle *fwnode, | ||
1200 | const char *prop, const char *nargs_prop, | ||
1201 | unsigned int args_count, unsigned int index, | ||
1202 | struct fwnode_reference_args *args) | ||
1203 | { | ||
1204 | struct acpi_reference_args acpi_args; | ||
1205 | unsigned int i; | ||
1206 | int ret; | ||
1207 | |||
1208 | ret = __acpi_node_get_property_reference(fwnode, prop, index, | ||
1209 | args_count, &acpi_args); | ||
1210 | if (ret < 0) | ||
1211 | return ret; | ||
1212 | if (!args) | ||
1213 | return 0; | ||
1214 | |||
1215 | args->nargs = acpi_args.nargs; | ||
1216 | args->fwnode = acpi_fwnode_handle(acpi_args.adev); | ||
1217 | |||
1218 | for (i = 0; i < NR_FWNODE_REFERENCE_ARGS; i++) | ||
1219 | args->args[i] = i < acpi_args.nargs ? acpi_args.args[i] : 0; | ||
1220 | |||
1221 | return 0; | ||
1222 | } | ||
1223 | |||
1198 | static struct fwnode_handle * | 1224 | static struct fwnode_handle * |
1199 | acpi_fwnode_graph_get_next_endpoint(const struct fwnode_handle *fwnode, | 1225 | acpi_fwnode_graph_get_next_endpoint(const struct fwnode_handle *fwnode, |
1200 | struct fwnode_handle *prev) | 1226 | struct fwnode_handle *prev) |
@@ -1248,6 +1274,7 @@ static int acpi_fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode, | |||
1248 | .get_parent = acpi_node_get_parent, \ | 1274 | .get_parent = acpi_node_get_parent, \ |
1249 | .get_next_child_node = acpi_get_next_subnode, \ | 1275 | .get_next_child_node = acpi_get_next_subnode, \ |
1250 | .get_named_child_node = acpi_fwnode_get_named_child_node, \ | 1276 | .get_named_child_node = acpi_fwnode_get_named_child_node, \ |
1277 | .get_reference_args = acpi_fwnode_get_reference_args, \ | ||
1251 | .graph_get_next_endpoint = \ | 1278 | .graph_get_next_endpoint = \ |
1252 | acpi_fwnode_graph_get_next_endpoint, \ | 1279 | acpi_fwnode_graph_get_next_endpoint, \ |
1253 | .graph_get_remote_endpoint = \ | 1280 | .graph_get_remote_endpoint = \ |
diff --git a/drivers/base/property.c b/drivers/base/property.c index 673e2353a2fb..d0b65bbe7e15 100644 --- a/drivers/base/property.c +++ b/drivers/base/property.c | |||
@@ -665,6 +665,34 @@ out: | |||
665 | } | 665 | } |
666 | EXPORT_SYMBOL_GPL(fwnode_property_match_string); | 666 | EXPORT_SYMBOL_GPL(fwnode_property_match_string); |
667 | 667 | ||
668 | /** | ||
669 | * fwnode_property_get_reference_args() - Find a reference with arguments | ||
670 | * @fwnode: Firmware node where to look for the reference | ||
671 | * @prop: The name of the property | ||
672 | * @nargs_prop: The name of the property telling the number of | ||
673 | * arguments in the referred node. NULL if @nargs is known, | ||
674 | * otherwise @nargs is ignored. Only relevant on OF. | ||
675 | * @nargs: Number of arguments. Ignored if @nargs_prop is non-NULL. | ||
676 | * @index: Index of the reference, from zero onwards. | ||
677 | * @args: Result structure with reference and integer arguments. | ||
678 | * | ||
679 | * Obtain a reference based on a named property in an fwnode, with | ||
680 | * integer arguments. | ||
681 | * | ||
682 | * Caller is responsible to call fwnode_handle_put() on the returned | ||
683 | * args->fwnode pointer. | ||
684 | * | ||
685 | */ | ||
686 | int fwnode_property_get_reference_args(const struct fwnode_handle *fwnode, | ||
687 | const char *prop, const char *nargs_prop, | ||
688 | unsigned int nargs, unsigned int index, | ||
689 | struct fwnode_reference_args *args) | ||
690 | { | ||
691 | return fwnode_call_int_op(fwnode, get_reference_args, prop, nargs_prop, | ||
692 | nargs, index, args); | ||
693 | } | ||
694 | EXPORT_SYMBOL_GPL(fwnode_property_get_reference_args); | ||
695 | |||
668 | static int property_copy_string_array(struct property_entry *dst, | 696 | static int property_copy_string_array(struct property_entry *dst, |
669 | const struct property_entry *src) | 697 | const struct property_entry *src) |
670 | { | 698 | { |
diff --git a/drivers/of/property.c b/drivers/of/property.c index ae46a6f0ea36..3868400972b8 100644 --- a/drivers/of/property.c +++ b/drivers/of/property.c | |||
@@ -891,6 +891,36 @@ of_fwnode_get_named_child_node(const struct fwnode_handle *fwnode, | |||
891 | return NULL; | 891 | return NULL; |
892 | } | 892 | } |
893 | 893 | ||
894 | static int | ||
895 | of_fwnode_get_reference_args(const struct fwnode_handle *fwnode, | ||
896 | const char *prop, const char *nargs_prop, | ||
897 | unsigned int nargs, unsigned int index, | ||
898 | struct fwnode_reference_args *args) | ||
899 | { | ||
900 | struct of_phandle_args of_args; | ||
901 | unsigned int i; | ||
902 | int ret; | ||
903 | |||
904 | if (nargs_prop) | ||
905 | ret = of_parse_phandle_with_args(to_of_node(fwnode), prop, | ||
906 | nargs_prop, index, &of_args); | ||
907 | else | ||
908 | ret = of_parse_phandle_with_fixed_args(to_of_node(fwnode), prop, | ||
909 | nargs, index, &of_args); | ||
910 | if (ret < 0) | ||
911 | return ret; | ||
912 | if (!args) | ||
913 | return 0; | ||
914 | |||
915 | args->nargs = of_args.args_count; | ||
916 | args->fwnode = of_fwnode_handle(of_args.np); | ||
917 | |||
918 | for (i = 0; i < NR_FWNODE_REFERENCE_ARGS; i++) | ||
919 | args->args[i] = i < of_args.args_count ? of_args.args[i] : 0; | ||
920 | |||
921 | return 0; | ||
922 | } | ||
923 | |||
894 | static struct fwnode_handle * | 924 | static struct fwnode_handle * |
895 | of_fwnode_graph_get_next_endpoint(const struct fwnode_handle *fwnode, | 925 | of_fwnode_graph_get_next_endpoint(const struct fwnode_handle *fwnode, |
896 | struct fwnode_handle *prev) | 926 | struct fwnode_handle *prev) |
@@ -949,6 +979,7 @@ const struct fwnode_operations of_fwnode_ops = { | |||
949 | .get_parent = of_fwnode_get_parent, | 979 | .get_parent = of_fwnode_get_parent, |
950 | .get_next_child_node = of_fwnode_get_next_child_node, | 980 | .get_next_child_node = of_fwnode_get_next_child_node, |
951 | .get_named_child_node = of_fwnode_get_named_child_node, | 981 | .get_named_child_node = of_fwnode_get_named_child_node, |
982 | .get_reference_args = of_fwnode_get_reference_args, | ||
952 | .graph_get_next_endpoint = of_fwnode_graph_get_next_endpoint, | 983 | .graph_get_next_endpoint = of_fwnode_graph_get_next_endpoint, |
953 | .graph_get_remote_endpoint = of_fwnode_graph_get_remote_endpoint, | 984 | .graph_get_remote_endpoint = of_fwnode_graph_get_remote_endpoint, |
954 | .graph_get_port_parent = of_fwnode_graph_get_port_parent, | 985 | .graph_get_port_parent = of_fwnode_graph_get_port_parent, |
diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h index 7b50ee4edcfc..0c35b6caf0f6 100644 --- a/include/linux/fwnode.h +++ b/include/linux/fwnode.h | |||
@@ -33,6 +33,20 @@ struct fwnode_endpoint { | |||
33 | const struct fwnode_handle *local_fwnode; | 33 | const struct fwnode_handle *local_fwnode; |
34 | }; | 34 | }; |
35 | 35 | ||
36 | #define NR_FWNODE_REFERENCE_ARGS 8 | ||
37 | |||
38 | /** | ||
39 | * struct fwnode_reference_args - Fwnode reference with additional arguments | ||
40 | * @fwnode:- A reference to the base fwnode | ||
41 | * @nargs: Number of elements in @args array | ||
42 | * @args: Integer arguments on the fwnode | ||
43 | */ | ||
44 | struct fwnode_reference_args { | ||
45 | struct fwnode_handle *fwnode; | ||
46 | unsigned int nargs; | ||
47 | unsigned int args[NR_FWNODE_REFERENCE_ARGS]; | ||
48 | }; | ||
49 | |||
36 | /** | 50 | /** |
37 | * struct fwnode_operations - Operations for fwnode interface | 51 | * struct fwnode_operations - Operations for fwnode interface |
38 | * @get: Get a reference to an fwnode. | 52 | * @get: Get a reference to an fwnode. |
@@ -46,6 +60,7 @@ struct fwnode_endpoint { | |||
46 | * @get_parent: Return the parent of an fwnode. | 60 | * @get_parent: Return the parent of an fwnode. |
47 | * @get_next_child_node: Return the next child node in an iteration. | 61 | * @get_next_child_node: Return the next child node in an iteration. |
48 | * @get_named_child_node: Return a child node with a given name. | 62 | * @get_named_child_node: Return a child node with a given name. |
63 | * @get_reference_args: Return a reference pointed to by a property, with args | ||
49 | * @graph_get_next_endpoint: Return an endpoint node in an iteration. | 64 | * @graph_get_next_endpoint: Return an endpoint node in an iteration. |
50 | * @graph_get_remote_endpoint: Return the remote endpoint node of a local | 65 | * @graph_get_remote_endpoint: Return the remote endpoint node of a local |
51 | * endpoint node. | 66 | * endpoint node. |
@@ -73,6 +88,10 @@ struct fwnode_operations { | |||
73 | struct fwnode_handle * | 88 | struct fwnode_handle * |
74 | (*get_named_child_node)(const struct fwnode_handle *fwnode, | 89 | (*get_named_child_node)(const struct fwnode_handle *fwnode, |
75 | const char *name); | 90 | const char *name); |
91 | int (*get_reference_args)(const struct fwnode_handle *fwnode, | ||
92 | const char *prop, const char *nargs_prop, | ||
93 | unsigned int nargs, unsigned int index, | ||
94 | struct fwnode_reference_args *args); | ||
76 | struct fwnode_handle * | 95 | struct fwnode_handle * |
77 | (*graph_get_next_endpoint)(const struct fwnode_handle *fwnode, | 96 | (*graph_get_next_endpoint)(const struct fwnode_handle *fwnode, |
78 | struct fwnode_handle *prev); | 97 | struct fwnode_handle *prev); |
diff --git a/include/linux/property.h b/include/linux/property.h index edff3f89e755..6bebee13c5e0 100644 --- a/include/linux/property.h +++ b/include/linux/property.h | |||
@@ -73,6 +73,10 @@ int fwnode_property_read_string(const struct fwnode_handle *fwnode, | |||
73 | const char *propname, const char **val); | 73 | const char *propname, const char **val); |
74 | int fwnode_property_match_string(const struct fwnode_handle *fwnode, | 74 | int fwnode_property_match_string(const struct fwnode_handle *fwnode, |
75 | const char *propname, const char *string); | 75 | const char *propname, const char *string); |
76 | int fwnode_property_get_reference_args(const struct fwnode_handle *fwnode, | ||
77 | const char *prop, const char *nargs_prop, | ||
78 | unsigned int nargs, unsigned int index, | ||
79 | struct fwnode_reference_args *args); | ||
76 | 80 | ||
77 | struct fwnode_handle *fwnode_get_parent(const struct fwnode_handle *fwnode); | 81 | struct fwnode_handle *fwnode_get_parent(const struct fwnode_handle *fwnode); |
78 | struct fwnode_handle *fwnode_get_next_parent( | 82 | struct fwnode_handle *fwnode_get_next_parent( |