watchdog: mpc8xxx_wdt convert to watchdog core
[cascardo/linux.git] / drivers / of / base.c
index f807d0e..ff85450 100644 (file)
@@ -415,6 +415,9 @@ static int __of_device_is_available(const struct device_node *device)
        const char *status;
        int statlen;
 
+       if (!device)
+               return 0;
+
        status = __of_get_property(device, "status", &statlen);
        if (status == NULL)
                return 1;
@@ -731,24 +734,42 @@ static
 const struct of_device_id *__of_match_node(const struct of_device_id *matches,
                                           const struct device_node *node)
 {
+       const char *cp;
+       int cplen, l;
+
        if (!matches)
                return NULL;
 
-       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++;
-       }
+       cp = __of_get_property(node, "compatible", &cplen);
+       do {
+               const struct of_device_id *m = matches;
+
+               /* Check against matches with current compatible string */
+               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)
+                               return m;
+                       m++;
+               }
+
+               /* Get node's next compatible string */ 
+               if (cp) {
+                       l = strlen(cp) + 1;
+                       cp += l;
+                       cplen -= l;
+               }
+       } while (cp && (cplen > 0));
+
        return NULL;
 }
 
@@ -757,7 +778,10 @@ 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.
+ *     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.
  */
 const struct of_device_id *of_match_node(const struct of_device_id *matches,
                                         const struct device_node *node)