diff options
Diffstat (limited to 'drivers/of/base.c')
-rw-r--r-- | drivers/of/base.c | 52 |
1 files changed, 43 insertions, 9 deletions
diff --git a/drivers/of/base.c b/drivers/of/base.c index d9bfd49b1935..d4a1c9a043e1 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c | |||
@@ -173,9 +173,9 @@ struct property *of_find_property(const struct device_node *np, | |||
173 | return NULL; | 173 | return NULL; |
174 | 174 | ||
175 | read_lock(&devtree_lock); | 175 | read_lock(&devtree_lock); |
176 | for (pp = np->properties; pp != 0; pp = pp->next) { | 176 | for (pp = np->properties; pp; pp = pp->next) { |
177 | if (of_prop_cmp(pp->name, name) == 0) { | 177 | if (of_prop_cmp(pp->name, name) == 0) { |
178 | if (lenp != 0) | 178 | if (lenp) |
179 | *lenp = pp->length; | 179 | *lenp = pp->length; |
180 | break; | 180 | break; |
181 | } | 181 | } |
@@ -364,6 +364,33 @@ struct device_node *of_get_next_child(const struct device_node *node, | |||
364 | EXPORT_SYMBOL(of_get_next_child); | 364 | EXPORT_SYMBOL(of_get_next_child); |
365 | 365 | ||
366 | /** | 366 | /** |
367 | * of_get_next_available_child - Find the next available child node | ||
368 | * @node: parent node | ||
369 | * @prev: previous child of the parent node, or NULL to get first | ||
370 | * | ||
371 | * This function is like of_get_next_child(), except that it | ||
372 | * automatically skips any disabled nodes (i.e. status = "disabled"). | ||
373 | */ | ||
374 | struct device_node *of_get_next_available_child(const struct device_node *node, | ||
375 | struct device_node *prev) | ||
376 | { | ||
377 | struct device_node *next; | ||
378 | |||
379 | read_lock(&devtree_lock); | ||
380 | next = prev ? prev->sibling : node->child; | ||
381 | for (; next; next = next->sibling) { | ||
382 | if (!of_device_is_available(next)) | ||
383 | continue; | ||
384 | if (of_node_get(next)) | ||
385 | break; | ||
386 | } | ||
387 | of_node_put(prev); | ||
388 | read_unlock(&devtree_lock); | ||
389 | return next; | ||
390 | } | ||
391 | EXPORT_SYMBOL(of_get_next_available_child); | ||
392 | |||
393 | /** | ||
367 | * of_find_node_by_path - Find a node matching a full OF path | 394 | * of_find_node_by_path - Find a node matching a full OF path |
368 | * @path: The full path to match | 395 | * @path: The full path to match |
369 | * | 396 | * |
@@ -497,7 +524,7 @@ struct device_node *of_find_node_with_property(struct device_node *from, | |||
497 | read_lock(&devtree_lock); | 524 | read_lock(&devtree_lock); |
498 | np = from ? from->allnext : allnodes; | 525 | np = from ? from->allnext : allnodes; |
499 | for (; np; np = np->allnext) { | 526 | for (; np; np = np->allnext) { |
500 | for (pp = np->properties; pp != 0; pp = pp->next) { | 527 | for (pp = np->properties; pp; pp = pp->next) { |
501 | if (of_prop_cmp(pp->name, prop_name) == 0) { | 528 | if (of_prop_cmp(pp->name, prop_name) == 0) { |
502 | of_node_get(np); | 529 | of_node_get(np); |
503 | goto out; | 530 | goto out; |
@@ -902,7 +929,7 @@ int of_parse_phandle_with_args(struct device_node *np, const char *list_name, | |||
902 | /* Retrieve the phandle list property */ | 929 | /* Retrieve the phandle list property */ |
903 | list = of_get_property(np, list_name, &size); | 930 | list = of_get_property(np, list_name, &size); |
904 | if (!list) | 931 | if (!list) |
905 | return -EINVAL; | 932 | return -ENOENT; |
906 | list_end = list + size / sizeof(*list); | 933 | list_end = list + size / sizeof(*list); |
907 | 934 | ||
908 | /* Loop over the phandles until all the requested entry is found */ | 935 | /* Loop over the phandles until all the requested entry is found */ |
@@ -1051,7 +1078,8 @@ int prom_remove_property(struct device_node *np, struct property *prop) | |||
1051 | } | 1078 | } |
1052 | 1079 | ||
1053 | /* | 1080 | /* |
1054 | * prom_update_property - Update a property in a node. | 1081 | * prom_update_property - Update a property in a node, if the property does |
1082 | * not exist, add it. | ||
1055 | * | 1083 | * |
1056 | * Note that we don't actually remove it, since we have given out | 1084 | * Note that we don't actually remove it, since we have given out |
1057 | * who-knows-how-many pointers to the data using get-property. | 1085 | * who-knows-how-many pointers to the data using get-property. |
@@ -1059,13 +1087,19 @@ int prom_remove_property(struct device_node *np, struct property *prop) | |||
1059 | * and add the new property to the property list | 1087 | * and add the new property to the property list |
1060 | */ | 1088 | */ |
1061 | int prom_update_property(struct device_node *np, | 1089 | int prom_update_property(struct device_node *np, |
1062 | struct property *newprop, | 1090 | struct property *newprop) |
1063 | struct property *oldprop) | ||
1064 | { | 1091 | { |
1065 | struct property **next; | 1092 | struct property **next, *oldprop; |
1066 | unsigned long flags; | 1093 | unsigned long flags; |
1067 | int found = 0; | 1094 | int found = 0; |
1068 | 1095 | ||
1096 | if (!newprop->name) | ||
1097 | return -EINVAL; | ||
1098 | |||
1099 | oldprop = of_find_property(np, newprop->name, NULL); | ||
1100 | if (!oldprop) | ||
1101 | return prom_add_property(np, newprop); | ||
1102 | |||
1069 | write_lock_irqsave(&devtree_lock, flags); | 1103 | write_lock_irqsave(&devtree_lock, flags); |
1070 | next = &np->properties; | 1104 | next = &np->properties; |
1071 | while (*next) { | 1105 | while (*next) { |
@@ -1173,7 +1207,7 @@ static void of_alias_add(struct alias_prop *ap, struct device_node *np, | |||
1173 | ap->stem[stem_len] = 0; | 1207 | ap->stem[stem_len] = 0; |
1174 | list_add_tail(&ap->link, &aliases_lookup); | 1208 | list_add_tail(&ap->link, &aliases_lookup); |
1175 | pr_debug("adding DT alias:%s: stem=%s id=%i node=%s\n", | 1209 | pr_debug("adding DT alias:%s: stem=%s id=%i node=%s\n", |
1176 | ap->alias, ap->stem, ap->id, np ? np->full_name : NULL); | 1210 | ap->alias, ap->stem, ap->id, of_node_full_name(np)); |
1177 | } | 1211 | } |
1178 | 1212 | ||
1179 | /** | 1213 | /** |