When the device node do have a compatible property, we definitely prefer the compatible match besides the type and name. Only if there is no such a match, we then consider the candidate which doesn't have compatible entry but do match the type or name with the device node. This is based on a patch from Sebastian Hesselbarth. http://patchwork.ozlabs.org/patch/319434/ I did some code refactoring and also fixed a bug in the original patch. Cc: Sebastian Hesselbarth <sebastian.hesselbarth@xxxxxxxxx> Signed-off-by: Kevin Hao <haokexin@xxxxxxxxx> --- drivers/of/base.c | 55 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/drivers/of/base.c b/drivers/of/base.c index ff85450d5683..9d655df458bd 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -730,32 +730,45 @@ out: } EXPORT_SYMBOL(of_find_node_with_property); +static int of_match_type_or_name(const struct device_node *node, + const struct of_device_id *m) +{ + 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); + + return match; +} + 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; + const struct of_device_id *m; + int match; if (!matches) return NULL; cp = __of_get_property(node, "compatible", &cplen); - do { - const struct of_device_id *m = matches; + while (cp && (cplen > 0)) { + 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, + if (!m->compatible[0]) { + m++; + continue; + } + + match = of_match_type_or_name(node, m); + match &= cp && !of_compat_cmp(m->compatible, cp, strlen(m->compatible)); if (match) return m; @@ -763,12 +776,18 @@ const struct of_device_id *__of_match_node(const struct of_device_id *matches, } /* Get node's next compatible string */ - if (cp) { - l = strlen(cp) + 1; - cp += l; - cplen -= l; - } - } while (cp && (cplen > 0)); + l = strlen(cp) + 1; + cp += l; + cplen -= l; + } + + m = matches; + /* Check against matches without compatible string */ + while (m->name[0] || m->type[0] || m->compatible[0]) { + if (!m->compatible[0] && of_match_type_or_name(node, m)) + return m; + m++; + } return NULL; } -- 1.8.5.3 -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html