diff options
Diffstat (limited to 'drivers/of/base.c')
-rw-r--r-- | drivers/of/base.c | 91 |
1 files changed, 70 insertions, 21 deletions
diff --git a/drivers/of/base.c b/drivers/of/base.c index 960ae5bf3ddc..16ee7a08e044 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c | |||
@@ -164,16 +164,14 @@ void of_node_put(struct device_node *node) | |||
164 | EXPORT_SYMBOL(of_node_put); | 164 | EXPORT_SYMBOL(of_node_put); |
165 | #endif /* CONFIG_OF_DYNAMIC */ | 165 | #endif /* CONFIG_OF_DYNAMIC */ |
166 | 166 | ||
167 | struct property *of_find_property(const struct device_node *np, | 167 | static struct property *__of_find_property(const struct device_node *np, |
168 | const char *name, | 168 | const char *name, int *lenp) |
169 | int *lenp) | ||
170 | { | 169 | { |
171 | struct property *pp; | 170 | struct property *pp; |
172 | 171 | ||
173 | if (!np) | 172 | if (!np) |
174 | return NULL; | 173 | return NULL; |
175 | 174 | ||
176 | read_lock(&devtree_lock); | ||
177 | for (pp = np->properties; pp; pp = pp->next) { | 175 | for (pp = np->properties; pp; pp = pp->next) { |
178 | if (of_prop_cmp(pp->name, name) == 0) { | 176 | if (of_prop_cmp(pp->name, name) == 0) { |
179 | if (lenp) | 177 | if (lenp) |
@@ -181,6 +179,18 @@ struct property *of_find_property(const struct device_node *np, | |||
181 | break; | 179 | break; |
182 | } | 180 | } |
183 | } | 181 | } |
182 | |||
183 | return pp; | ||
184 | } | ||
185 | |||
186 | struct property *of_find_property(const struct device_node *np, | ||
187 | const char *name, | ||
188 | int *lenp) | ||
189 | { | ||
190 | struct property *pp; | ||
191 | |||
192 | read_lock(&devtree_lock); | ||
193 | pp = __of_find_property(np, name, lenp); | ||
184 | read_unlock(&devtree_lock); | 194 | read_unlock(&devtree_lock); |
185 | 195 | ||
186 | return pp; | 196 | return pp; |
@@ -214,8 +224,20 @@ EXPORT_SYMBOL(of_find_all_nodes); | |||
214 | * Find a property with a given name for a given node | 224 | * Find a property with a given name for a given node |
215 | * and return the value. | 225 | * and return the value. |
216 | */ | 226 | */ |
227 | static const void *__of_get_property(const struct device_node *np, | ||
228 | const char *name, int *lenp) | ||
229 | { | ||
230 | struct property *pp = __of_find_property(np, name, lenp); | ||
231 | |||
232 | return pp ? pp->value : NULL; | ||
233 | } | ||
234 | |||
235 | /* | ||
236 | * Find a property with a given name for a given node | ||
237 | * and return the value. | ||
238 | */ | ||
217 | const void *of_get_property(const struct device_node *np, const char *name, | 239 | const void *of_get_property(const struct device_node *np, const char *name, |
218 | int *lenp) | 240 | int *lenp) |
219 | { | 241 | { |
220 | struct property *pp = of_find_property(np, name, lenp); | 242 | struct property *pp = of_find_property(np, name, lenp); |
221 | 243 | ||
@@ -226,13 +248,13 @@ EXPORT_SYMBOL(of_get_property); | |||
226 | /** Checks if the given "compat" string matches one of the strings in | 248 | /** Checks if the given "compat" string matches one of the strings in |
227 | * the device's "compatible" property | 249 | * the device's "compatible" property |
228 | */ | 250 | */ |
229 | int of_device_is_compatible(const struct device_node *device, | 251 | static int __of_device_is_compatible(const struct device_node *device, |
230 | const char *compat) | 252 | const char *compat) |
231 | { | 253 | { |
232 | const char* cp; | 254 | const char* cp; |
233 | int cplen, l; | 255 | int cplen, l; |
234 | 256 | ||
235 | cp = of_get_property(device, "compatible", &cplen); | 257 | cp = __of_get_property(device, "compatible", &cplen); |
236 | if (cp == NULL) | 258 | if (cp == NULL) |
237 | return 0; | 259 | return 0; |
238 | while (cplen > 0) { | 260 | while (cplen > 0) { |
@@ -245,6 +267,20 @@ int of_device_is_compatible(const struct device_node *device, | |||
245 | 267 | ||
246 | return 0; | 268 | return 0; |
247 | } | 269 | } |
270 | |||
271 | /** Checks if the given "compat" string matches one of the strings in | ||
272 | * the device's "compatible" property | ||
273 | */ | ||
274 | int of_device_is_compatible(const struct device_node *device, | ||
275 | const char *compat) | ||
276 | { | ||
277 | int res; | ||
278 | |||
279 | read_lock(&devtree_lock); | ||
280 | res = __of_device_is_compatible(device, compat); | ||
281 | read_unlock(&devtree_lock); | ||
282 | return res; | ||
283 | } | ||
248 | EXPORT_SYMBOL(of_device_is_compatible); | 284 | EXPORT_SYMBOL(of_device_is_compatible); |
249 | 285 | ||
250 | /** | 286 | /** |
@@ -518,7 +554,8 @@ struct device_node *of_find_compatible_node(struct device_node *from, | |||
518 | if (type | 554 | if (type |
519 | && !(np->type && (of_node_cmp(np->type, type) == 0))) | 555 | && !(np->type && (of_node_cmp(np->type, type) == 0))) |
520 | continue; | 556 | continue; |
521 | if (of_device_is_compatible(np, compatible) && of_node_get(np)) | 557 | if (__of_device_is_compatible(np, compatible) && |
558 | of_node_get(np)) | ||
522 | break; | 559 | break; |
523 | } | 560 | } |
524 | of_node_put(from); | 561 | of_node_put(from); |
@@ -562,15 +599,9 @@ out: | |||
562 | } | 599 | } |
563 | EXPORT_SYMBOL(of_find_node_with_property); | 600 | EXPORT_SYMBOL(of_find_node_with_property); |
564 | 601 | ||
565 | /** | 602 | static |
566 | * of_match_node - Tell if an device_node has a matching of_match structure | 603 | const struct of_device_id *__of_match_node(const struct of_device_id *matches, |
567 | * @matches: array of of device match structures to search in | 604 | const struct device_node *node) |
568 | * @node: the of device structure to match against | ||
569 | * | ||
570 | * Low level utility function used by device matching. | ||
571 | */ | ||
572 | const struct of_device_id *of_match_node(const struct of_device_id *matches, | ||
573 | const struct device_node *node) | ||
574 | { | 605 | { |
575 | if (!matches) | 606 | if (!matches) |
576 | return NULL; | 607 | return NULL; |
@@ -584,14 +615,32 @@ const struct of_device_id *of_match_node(const struct of_device_id *matches, | |||
584 | match &= node->type | 615 | match &= node->type |
585 | && !strcmp(matches->type, node->type); | 616 | && !strcmp(matches->type, node->type); |
586 | if (matches->compatible[0]) | 617 | if (matches->compatible[0]) |
587 | match &= of_device_is_compatible(node, | 618 | match &= __of_device_is_compatible(node, |
588 | matches->compatible); | 619 | matches->compatible); |
589 | if (match) | 620 | if (match) |
590 | return matches; | 621 | return matches; |
591 | matches++; | 622 | matches++; |
592 | } | 623 | } |
593 | return NULL; | 624 | return NULL; |
594 | } | 625 | } |
626 | |||
627 | /** | ||
628 | * of_match_node - Tell if an device_node has a matching of_match structure | ||
629 | * @matches: array of of device match structures to search in | ||
630 | * @node: the of device structure to match against | ||
631 | * | ||
632 | * Low level utility function used by device matching. | ||
633 | */ | ||
634 | const struct of_device_id *of_match_node(const struct of_device_id *matches, | ||
635 | const struct device_node *node) | ||
636 | { | ||
637 | const struct of_device_id *match; | ||
638 | |||
639 | read_lock(&devtree_lock); | ||
640 | match = __of_match_node(matches, node); | ||
641 | read_unlock(&devtree_lock); | ||
642 | return match; | ||
643 | } | ||
595 | EXPORT_SYMBOL(of_match_node); | 644 | EXPORT_SYMBOL(of_match_node); |
596 | 645 | ||
597 | /** | 646 | /** |
@@ -620,7 +669,7 @@ struct device_node *of_find_matching_node_and_match(struct device_node *from, | |||
620 | read_lock(&devtree_lock); | 669 | read_lock(&devtree_lock); |
621 | np = from ? from->allnext : of_allnodes; | 670 | np = from ? from->allnext : of_allnodes; |
622 | for (; np; np = np->allnext) { | 671 | for (; np; np = np->allnext) { |
623 | m = of_match_node(matches, np); | 672 | m = __of_match_node(matches, np); |
624 | if (m && of_node_get(np)) { | 673 | if (m && of_node_get(np)) { |
625 | if (match) | 674 | if (match) |
626 | *match = m; | 675 | *match = m; |