Merge remote-tracking branches 'asoc/fix/blackfin', 'asoc/fix/da9055', 'asoc/fix...
[firefly-linux-kernel-4.4.55.git] / drivers / of / base.c
index ff85450d568399b1dec3fe6bf892c974ca28bedd..10b51106c854f20fc1b73bf80d9b5c37d23d8545 100644 (file)
@@ -730,46 +730,64 @@ out:
 }
 EXPORT_SYMBOL(of_find_node_with_property);
 
-static
-const struct of_device_id *__of_match_node(const struct of_device_id *matches,
-                                          const struct device_node *node)
+static const struct of_device_id *
+of_match_compatible(const struct of_device_id *matches,
+                       const struct device_node *node)
 {
        const char *cp;
        int cplen, l;
-
-       if (!matches)
-               return NULL;
+       const struct of_device_id *m;
 
        cp = __of_get_property(node, "compatible", &cplen);
-       do {
-               const struct of_device_id *m = matches;
-
-               /* Check against matches with current compatible string */
+       while (cp && (cplen > 0)) {
+               m = matches;
                while (m->name[0] || m->type[0] || m->compatible[0]) {
-                       int match = 1;
-                       if (m->name[0])
-                               match &= node->name
-                                       && !strcmp(m->name, node->name);
-                       if (m->type[0])
-                               match &= node->type
-                                       && !strcmp(m->type, node->type);
-                       if (m->compatible[0])
-                               match &= cp
-                                       && !of_compat_cmp(m->compatible, cp,
-                                                       strlen(m->compatible));
-                       if (match)
+                       /* Only match for the entries without type and name */
+                       if (m->name[0] || m->type[0] ||
+                               of_compat_cmp(m->compatible, cp,
+                                        strlen(m->compatible)))
+                               m++;
+                       else
                                return m;
-                       m++;
                }
 
-               /* Get node's next compatible string */ 
-               if (cp) {
-                       l = strlen(cp) + 1;
-                       cp += l;
-                       cplen -= l;
-               }
-       } while (cp && (cplen > 0));
+               /* Get node's next compatible string */
+               l = strlen(cp) + 1;
+               cp += l;
+               cplen -= l;
+       }
+
+       return NULL;
+}
+
+static
+const struct of_device_id *__of_match_node(const struct of_device_id *matches,
+                                          const struct device_node *node)
+{
+       const struct of_device_id *m;
 
+       if (!matches)
+               return NULL;
+
+       m = of_match_compatible(matches, node);
+       if (m)
+               return m;
+
+       while (matches->name[0] || matches->type[0] || matches->compatible[0]) {
+               int match = 1;
+               if (matches->name[0])
+                       match &= node->name
+                               && !strcmp(matches->name, node->name);
+               if (matches->type[0])
+                       match &= node->type
+                               && !strcmp(matches->type, node->type);
+               if (matches->compatible[0])
+                       match &= __of_device_is_compatible(node,
+                                                          matches->compatible);
+               if (match)
+                       return matches;
+               matches++;
+       }
        return NULL;
 }
 
@@ -778,10 +796,12 @@ const struct of_device_id *__of_match_node(const struct of_device_id *matches,
  *     @matches:       array of of device match structures to search in
  *     @node:          the of device structure to match against
  *
- *     Low level utility function used by device matching. Matching order
- *     is to compare each of the node's compatibles with all given matches
- *     first. This implies node's compatible is sorted from specific to
- *     generic while matches can be in any order.
+ *     Low level utility function used by device matching. We have two ways
+ *     of matching:
+ *     - Try to find the best compatible match by comparing each compatible
+ *       string of device node with all the given matches respectively.
+ *     - If the above method failed, then try to match the compatible by using
+ *       __of_device_is_compatible() besides the match in type and name.
  */
 const struct of_device_id *of_match_node(const struct of_device_id *matches,
                                         const struct device_node *node)