diff options
author | Grant Likely <grant.likely@secretlab.ca> | 2013-02-10 17:57:21 -0500 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2013-02-13 05:09:31 -0500 |
commit | bd69f73f2c81eed9a398708b8c4bb3409ba1b0f9 (patch) | |
tree | 0be6f0ee561d13d01b6c44478b693cc60453ff6d /drivers/of | |
parent | 23ce04c0734e33b1042273b0ed11a8e4f7f988ca (diff) |
of: Create function for counting number of phandles in a property
This patch creates of_count_phandle_with_args(), a new function for
counting the number of phandle+argument tuples in a given property. This
is better than the existing method of parsing each phandle individually
until parsing fails which is a horribly slow way to do the count.
Tested on ARM using the selftest code.
v3: - Rebased on top of selftest code cleanup patch
v2: - fix bug where of_parse_phandle_with_args() could behave like _count_.
- made of_gpio_named_count() into a static inline regardless of CONFIG_OF_GPIO
Tested-by: Andreas Larsson <andreas@gaisler.com>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: Rob Herring <rob.herring@calxeda.com>
Diffstat (limited to 'drivers/of')
-rw-r--r-- | drivers/of/base.c | 41 | ||||
-rw-r--r-- | drivers/of/selftest.c | 15 |
2 files changed, 52 insertions, 4 deletions
diff --git a/drivers/of/base.c b/drivers/of/base.c index c5572cb87a88..321d3ef05006 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c | |||
@@ -1091,9 +1091,10 @@ EXPORT_SYMBOL(of_parse_phandle); | |||
1091 | * To get a device_node of the `node2' node you may call this: | 1091 | * To get a device_node of the `node2' node you may call this: |
1092 | * of_parse_phandle_with_args(node3, "list", "#list-cells", 1, &args); | 1092 | * of_parse_phandle_with_args(node3, "list", "#list-cells", 1, &args); |
1093 | */ | 1093 | */ |
1094 | int of_parse_phandle_with_args(const struct device_node *np, const char *list_name, | 1094 | static int __of_parse_phandle_with_args(const struct device_node *np, |
1095 | const char *cells_name, int index, | 1095 | const char *list_name, |
1096 | struct of_phandle_args *out_args) | 1096 | const char *cells_name, int index, |
1097 | struct of_phandle_args *out_args) | ||
1097 | { | 1098 | { |
1098 | const __be32 *list, *list_end; | 1099 | const __be32 *list, *list_end; |
1099 | int rc = 0, size, cur_index = 0; | 1100 | int rc = 0, size, cur_index = 0; |
@@ -1183,15 +1184,47 @@ int of_parse_phandle_with_args(const struct device_node *np, const char *list_na | |||
1183 | * Unlock node before returning result; will be one of: | 1184 | * Unlock node before returning result; will be one of: |
1184 | * -ENOENT : index is for empty phandle | 1185 | * -ENOENT : index is for empty phandle |
1185 | * -EINVAL : parsing error on data | 1186 | * -EINVAL : parsing error on data |
1187 | * [1..n] : Number of phandle (count mode; when index = -1) | ||
1186 | */ | 1188 | */ |
1187 | rc = -ENOENT; | 1189 | rc = index < 0 ? cur_index : -ENOENT; |
1188 | err: | 1190 | err: |
1189 | if (node) | 1191 | if (node) |
1190 | of_node_put(node); | 1192 | of_node_put(node); |
1191 | return rc; | 1193 | return rc; |
1192 | } | 1194 | } |
1195 | |||
1196 | int of_parse_phandle_with_args(const struct device_node *np, const char *list_name, | ||
1197 | const char *cells_name, int index, | ||
1198 | struct of_phandle_args *out_args) | ||
1199 | { | ||
1200 | if (index < 0) | ||
1201 | return -EINVAL; | ||
1202 | return __of_parse_phandle_with_args(np, list_name, cells_name, index, out_args); | ||
1203 | } | ||
1193 | EXPORT_SYMBOL(of_parse_phandle_with_args); | 1204 | EXPORT_SYMBOL(of_parse_phandle_with_args); |
1194 | 1205 | ||
1206 | /** | ||
1207 | * of_count_phandle_with_args() - Find the number of phandles references in a property | ||
1208 | * @np: pointer to a device tree node containing a list | ||
1209 | * @list_name: property name that contains a list | ||
1210 | * @cells_name: property name that specifies phandles' arguments count | ||
1211 | * | ||
1212 | * Returns the number of phandle + argument tuples within a property. It | ||
1213 | * is a typical pattern to encode a list of phandle and variable | ||
1214 | * arguments into a single property. The number of arguments is encoded | ||
1215 | * by a property in the phandle-target node. For example, a gpios | ||
1216 | * property would contain a list of GPIO specifies consisting of a | ||
1217 | * phandle and 1 or more arguments. The number of arguments are | ||
1218 | * determined by the #gpio-cells property in the node pointed to by the | ||
1219 | * phandle. | ||
1220 | */ | ||
1221 | int of_count_phandle_with_args(const struct device_node *np, const char *list_name, | ||
1222 | const char *cells_name) | ||
1223 | { | ||
1224 | return __of_parse_phandle_with_args(np, list_name, cells_name, -1, NULL); | ||
1225 | } | ||
1226 | EXPORT_SYMBOL(of_count_phandle_with_args); | ||
1227 | |||
1195 | #if defined(CONFIG_OF_DYNAMIC) | 1228 | #if defined(CONFIG_OF_DYNAMIC) |
1196 | static int of_property_notify(int action, struct device_node *np, | 1229 | static int of_property_notify(int action, struct device_node *np, |
1197 | struct property *prop) | 1230 | struct property *prop) |
diff --git a/drivers/of/selftest.c b/drivers/of/selftest.c index 01b4174a3b46..0eb5c38b4e07 100644 --- a/drivers/of/selftest.c +++ b/drivers/of/selftest.c | |||
@@ -36,6 +36,9 @@ static void __init of_selftest_parse_phandle_with_args(void) | |||
36 | return; | 36 | return; |
37 | } | 37 | } |
38 | 38 | ||
39 | rc = of_count_phandle_with_args(np, "phandle-list", "#phandle-cells"); | ||
40 | selftest(rc == 7, "of_count_phandle_with_args() returned %i, expected 7\n", rc); | ||
41 | |||
39 | for (i = 0; i < 8; i++) { | 42 | for (i = 0; i < 8; i++) { |
40 | bool passed = true; | 43 | bool passed = true; |
41 | rc = of_parse_phandle_with_args(np, "phandle-list", | 44 | rc = of_parse_phandle_with_args(np, "phandle-list", |
@@ -94,21 +97,33 @@ static void __init of_selftest_parse_phandle_with_args(void) | |||
94 | rc = of_parse_phandle_with_args(np, "phandle-list-missing", | 97 | rc = of_parse_phandle_with_args(np, "phandle-list-missing", |
95 | "#phandle-cells", 0, &args); | 98 | "#phandle-cells", 0, &args); |
96 | selftest(rc == -ENOENT, "expected:%i got:%i\n", -ENOENT, rc); | 99 | selftest(rc == -ENOENT, "expected:%i got:%i\n", -ENOENT, rc); |
100 | rc = of_count_phandle_with_args(np, "phandle-list-missing", | ||
101 | "#phandle-cells"); | ||
102 | selftest(rc == -ENOENT, "expected:%i got:%i\n", -ENOENT, rc); | ||
97 | 103 | ||
98 | /* Check for missing cells property */ | 104 | /* Check for missing cells property */ |
99 | rc = of_parse_phandle_with_args(np, "phandle-list", | 105 | rc = of_parse_phandle_with_args(np, "phandle-list", |
100 | "#phandle-cells-missing", 0, &args); | 106 | "#phandle-cells-missing", 0, &args); |
101 | selftest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); | 107 | selftest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); |
108 | rc = of_count_phandle_with_args(np, "phandle-list", | ||
109 | "#phandle-cells-missing"); | ||
110 | selftest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); | ||
102 | 111 | ||
103 | /* Check for bad phandle in list */ | 112 | /* Check for bad phandle in list */ |
104 | rc = of_parse_phandle_with_args(np, "phandle-list-bad-phandle", | 113 | rc = of_parse_phandle_with_args(np, "phandle-list-bad-phandle", |
105 | "#phandle-cells", 0, &args); | 114 | "#phandle-cells", 0, &args); |
106 | selftest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); | 115 | selftest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); |
116 | rc = of_count_phandle_with_args(np, "phandle-list-bad-phandle", | ||
117 | "#phandle-cells"); | ||
118 | selftest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); | ||
107 | 119 | ||
108 | /* Check for incorrectly formed argument list */ | 120 | /* Check for incorrectly formed argument list */ |
109 | rc = of_parse_phandle_with_args(np, "phandle-list-bad-args", | 121 | rc = of_parse_phandle_with_args(np, "phandle-list-bad-args", |
110 | "#phandle-cells", 1, &args); | 122 | "#phandle-cells", 1, &args); |
111 | selftest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); | 123 | selftest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); |
124 | rc = of_count_phandle_with_args(np, "phandle-list-bad-args", | ||
125 | "#phandle-cells"); | ||
126 | selftest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); | ||
112 | } | 127 | } |
113 | 128 | ||
114 | static void __init of_selftest_property_match_string(void) | 129 | static void __init of_selftest_property_match_string(void) |