diff options
Diffstat (limited to 'drivers/of/base.c')
-rw-r--r-- | drivers/of/base.c | 150 |
1 files changed, 74 insertions, 76 deletions
diff --git a/drivers/of/base.c b/drivers/of/base.c index 10b51106c854..89e888a78899 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c | |||
@@ -342,27 +342,72 @@ struct device_node *of_get_cpu_node(int cpu, unsigned int *thread) | |||
342 | } | 342 | } |
343 | EXPORT_SYMBOL(of_get_cpu_node); | 343 | EXPORT_SYMBOL(of_get_cpu_node); |
344 | 344 | ||
345 | /** Checks if the given "compat" string matches one of the strings in | 345 | /** |
346 | * the device's "compatible" property | 346 | * __of_device_is_compatible() - Check if the node matches given constraints |
347 | * @device: pointer to node | ||
348 | * @compat: required compatible string, NULL or "" for any match | ||
349 | * @type: required device_type value, NULL or "" for any match | ||
350 | * @name: required node name, NULL or "" for any match | ||
351 | * | ||
352 | * Checks if the given @compat, @type and @name strings match the | ||
353 | * properties of the given @device. A constraints can be skipped by | ||
354 | * passing NULL or an empty string as the constraint. | ||
355 | * | ||
356 | * Returns 0 for no match, and a positive integer on match. The return | ||
357 | * value is a relative score with larger values indicating better | ||
358 | * matches. The score is weighted for the most specific compatible value | ||
359 | * to get the highest score. Matching type is next, followed by matching | ||
360 | * name. Practically speaking, this results in the following priority | ||
361 | * order for matches: | ||
362 | * | ||
363 | * 1. specific compatible && type && name | ||
364 | * 2. specific compatible && type | ||
365 | * 3. specific compatible && name | ||
366 | * 4. specific compatible | ||
367 | * 5. general compatible && type && name | ||
368 | * 6. general compatible && type | ||
369 | * 7. general compatible && name | ||
370 | * 8. general compatible | ||
371 | * 9. type && name | ||
372 | * 10. type | ||
373 | * 11. name | ||
347 | */ | 374 | */ |
348 | static int __of_device_is_compatible(const struct device_node *device, | 375 | static int __of_device_is_compatible(const struct device_node *device, |
349 | const char *compat) | 376 | const char *compat, const char *type, const char *name) |
350 | { | 377 | { |
351 | const char* cp; | 378 | struct property *prop; |
352 | int cplen, l; | 379 | const char *cp; |
380 | int index = 0, score = 0; | ||
381 | |||
382 | /* Compatible match has highest priority */ | ||
383 | if (compat && compat[0]) { | ||
384 | prop = __of_find_property(device, "compatible", NULL); | ||
385 | for (cp = of_prop_next_string(prop, NULL); cp; | ||
386 | cp = of_prop_next_string(prop, cp), index++) { | ||
387 | if (of_compat_cmp(cp, compat, strlen(compat)) == 0) { | ||
388 | score = INT_MAX/2 - (index << 2); | ||
389 | break; | ||
390 | } | ||
391 | } | ||
392 | if (!score) | ||
393 | return 0; | ||
394 | } | ||
353 | 395 | ||
354 | cp = __of_get_property(device, "compatible", &cplen); | 396 | /* Matching type is better than matching name */ |
355 | if (cp == NULL) | 397 | if (type && type[0]) { |
356 | return 0; | 398 | if (!device->type || of_node_cmp(type, device->type)) |
357 | while (cplen > 0) { | 399 | return 0; |
358 | if (of_compat_cmp(cp, compat, strlen(compat)) == 0) | 400 | score += 2; |
359 | return 1; | ||
360 | l = strlen(cp) + 1; | ||
361 | cp += l; | ||
362 | cplen -= l; | ||
363 | } | 401 | } |
364 | 402 | ||
365 | return 0; | 403 | /* Matching name is a bit better than not */ |
404 | if (name && name[0]) { | ||
405 | if (!device->name || of_node_cmp(name, device->name)) | ||
406 | return 0; | ||
407 | score++; | ||
408 | } | ||
409 | |||
410 | return score; | ||
366 | } | 411 | } |
367 | 412 | ||
368 | /** Checks if the given "compat" string matches one of the strings in | 413 | /** Checks if the given "compat" string matches one of the strings in |
@@ -375,7 +420,7 @@ int of_device_is_compatible(const struct device_node *device, | |||
375 | int res; | 420 | int res; |
376 | 421 | ||
377 | raw_spin_lock_irqsave(&devtree_lock, flags); | 422 | raw_spin_lock_irqsave(&devtree_lock, flags); |
378 | res = __of_device_is_compatible(device, compat); | 423 | res = __of_device_is_compatible(device, compat, NULL, NULL); |
379 | raw_spin_unlock_irqrestore(&devtree_lock, flags); | 424 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
380 | return res; | 425 | return res; |
381 | } | 426 | } |
@@ -681,10 +726,7 @@ struct device_node *of_find_compatible_node(struct device_node *from, | |||
681 | raw_spin_lock_irqsave(&devtree_lock, flags); | 726 | raw_spin_lock_irqsave(&devtree_lock, flags); |
682 | np = from ? from->allnext : of_allnodes; | 727 | np = from ? from->allnext : of_allnodes; |
683 | for (; np; np = np->allnext) { | 728 | for (; np; np = np->allnext) { |
684 | if (type | 729 | if (__of_device_is_compatible(np, compatible, type, NULL) && |
685 | && !(np->type && (of_node_cmp(np->type, type) == 0))) | ||
686 | continue; | ||
687 | if (__of_device_is_compatible(np, compatible) && | ||
688 | of_node_get(np)) | 730 | of_node_get(np)) |
689 | break; | 731 | break; |
690 | } | 732 | } |
@@ -730,65 +772,26 @@ out: | |||
730 | } | 772 | } |
731 | EXPORT_SYMBOL(of_find_node_with_property); | 773 | EXPORT_SYMBOL(of_find_node_with_property); |
732 | 774 | ||
733 | static const struct of_device_id * | ||
734 | of_match_compatible(const struct of_device_id *matches, | ||
735 | const struct device_node *node) | ||
736 | { | ||
737 | const char *cp; | ||
738 | int cplen, l; | ||
739 | const struct of_device_id *m; | ||
740 | |||
741 | cp = __of_get_property(node, "compatible", &cplen); | ||
742 | while (cp && (cplen > 0)) { | ||
743 | m = matches; | ||
744 | while (m->name[0] || m->type[0] || m->compatible[0]) { | ||
745 | /* Only match for the entries without type and name */ | ||
746 | if (m->name[0] || m->type[0] || | ||
747 | of_compat_cmp(m->compatible, cp, | ||
748 | strlen(m->compatible))) | ||
749 | m++; | ||
750 | else | ||
751 | return m; | ||
752 | } | ||
753 | |||
754 | /* Get node's next compatible string */ | ||
755 | l = strlen(cp) + 1; | ||
756 | cp += l; | ||
757 | cplen -= l; | ||
758 | } | ||
759 | |||
760 | return NULL; | ||
761 | } | ||
762 | |||
763 | static | 775 | static |
764 | const struct of_device_id *__of_match_node(const struct of_device_id *matches, | 776 | const struct of_device_id *__of_match_node(const struct of_device_id *matches, |
765 | const struct device_node *node) | 777 | const struct device_node *node) |
766 | { | 778 | { |
767 | const struct of_device_id *m; | 779 | const struct of_device_id *best_match = NULL; |
780 | int score, best_score = 0; | ||
768 | 781 | ||
769 | if (!matches) | 782 | if (!matches) |
770 | return NULL; | 783 | return NULL; |
771 | 784 | ||
772 | m = of_match_compatible(matches, node); | 785 | for (; matches->name[0] || matches->type[0] || matches->compatible[0]; matches++) { |
773 | if (m) | 786 | score = __of_device_is_compatible(node, matches->compatible, |
774 | return m; | 787 | matches->type, matches->name); |
775 | 788 | if (score > best_score) { | |
776 | while (matches->name[0] || matches->type[0] || matches->compatible[0]) { | 789 | best_match = matches; |
777 | int match = 1; | 790 | best_score = score; |
778 | if (matches->name[0]) | 791 | } |
779 | match &= node->name | ||
780 | && !strcmp(matches->name, node->name); | ||
781 | if (matches->type[0]) | ||
782 | match &= node->type | ||
783 | && !strcmp(matches->type, node->type); | ||
784 | if (matches->compatible[0]) | ||
785 | match &= __of_device_is_compatible(node, | ||
786 | matches->compatible); | ||
787 | if (match) | ||
788 | return matches; | ||
789 | matches++; | ||
790 | } | 792 | } |
791 | return NULL; | 793 | |
794 | return best_match; | ||
792 | } | 795 | } |
793 | 796 | ||
794 | /** | 797 | /** |
@@ -796,12 +799,7 @@ const struct of_device_id *__of_match_node(const struct of_device_id *matches, | |||
796 | * @matches: array of of device match structures to search in | 799 | * @matches: array of of device match structures to search in |
797 | * @node: the of device structure to match against | 800 | * @node: the of device structure to match against |
798 | * | 801 | * |
799 | * Low level utility function used by device matching. We have two ways | 802 | * Low level utility function used by device matching. |
800 | * of matching: | ||
801 | * - Try to find the best compatible match by comparing each compatible | ||
802 | * string of device node with all the given matches respectively. | ||
803 | * - If the above method failed, then try to match the compatible by using | ||
804 | * __of_device_is_compatible() besides the match in type and name. | ||
805 | */ | 803 | */ |
806 | const struct of_device_id *of_match_node(const struct of_device_id *matches, | 804 | const struct of_device_id *of_match_node(const struct of_device_id *matches, |
807 | const struct device_node *node) | 805 | const struct device_node *node) |