diff options
author | Arnd Bergmann <arnd@arndb.de> | 2014-03-17 15:17:07 +0100 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2014-03-17 15:17:07 +0100 |
commit | 38edc2da5014e70e46a724d97c3ef3dde106331b (patch) | |
tree | 590499bacd062e8dd74c6f05a7d811dd714a2d70 /drivers/of/base.c | |
parent | 937b5991ca7717ceba99014f2ad3f51c85cdb9ad (diff) | |
parent | 28b191118c11719bb27db621425a70be28a40e08 (diff) |
Merge tag 'omap-for-v3.15/dt-overo-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap into next/dt
Updates to the .dts files to support more Gumstix boards.
These are sent separately from the rest of the .dts changes
as these depend on the fixes merged into v3.14-rc4, and
needed a bit more time to get updated on the fixes.
* tag 'omap-for-v3.15/dt-overo-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap:
ARM: dts: Add support for the Overo Summit
ARM: dts: Add support for the Overo Chestnut43
ARM: dts: Add support for the Overo Alto35
ARM: dts: Add support for the Overo Gallop43
ARM: dts: Add support for the Overo Palo43
ARM: dts: overo: Add LIS33DE accelerometer
ARM: dts: overo: Create a file for common Gumstix peripherals
ARM: dts: overo: Push uart3 pinmux down to expansion board
ARM: dts: omap3-tobi: Add AT24C01 EEPROM
ARM: dts: omap3-tobi: Use include file omap-gpmc-smsc9221
ARM: dts: omap: Add common file for SMSC9221
ARM: dts: omap3-overo: Add HSUSB PHY
ARM: dts: omap3-overo: Enable WiFi/BT combo
ARM: dts: omap3-overo: Add missing pinctrl
ARM: dts: omap3-tobi: Add missing pinctrl
ARM: dts: overo: reorganize include files
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Conflicts:
arch/arm/boot/dts/omap3-overo.dtsi
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 10b51106c85..89e888a7889 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) } EXPORT_SYMBOL(of_get_cpu_node); -/** Checks if the given "compat" string matches one of the strings in - * the device's "compatible" property +/** + * __of_device_is_compatible() - Check if the node matches given constraints + * @device: pointer to node + * @compat: required compatible string, NULL or "" for any match + * @type: required device_type value, NULL or "" for any match + * @name: required node name, NULL or "" for any match + * + * Checks if the given @compat, @type and @name strings match the + * properties of the given @device. A constraints can be skipped by + * passing NULL or an empty string as the constraint. + * + * Returns 0 for no match, and a positive integer on match. The return + * value is a relative score with larger values indicating better + * matches. The score is weighted for the most specific compatible value + * to get the highest score. Matching type is next, followed by matching + * name. Practically speaking, this results in the following priority + * order for matches: + * + * 1. specific compatible && type && name + * 2. specific compatible && type + * 3. specific compatible && name + * 4. specific compatible + * 5. general compatible && type && name + * 6. general compatible && type + * 7. general compatible && name + * 8. general compatible + * 9. type && name + * 10. type + * 11. name */ static int __of_device_is_compatible(const struct device_node *device, - const char *compat) + const char *compat, const char *type, const char *name) { - const char* cp; - int cplen, l; + struct property *prop; + const char *cp; + int index = 0, score = 0; + + /* Compatible match has highest priority */ + if (compat && compat[0]) { + prop = __of_find_property(device, "compatible", NULL); + for (cp = of_prop_next_string(prop, NULL); cp; + cp = of_prop_next_string(prop, cp), index++) { + if (of_compat_cmp(cp, compat, strlen(compat)) == 0) { + score = INT_MAX/2 - (index << 2); + break; + } + } + if (!score) + return 0; + } - cp = __of_get_property(device, "compatible", &cplen); - if (cp == NULL) - return 0; - while (cplen > 0) { - if (of_compat_cmp(cp, compat, strlen(compat)) == 0) - return 1; - l = strlen(cp) + 1; - cp += l; - cplen -= l; + /* Matching type is better than matching name */ + if (type && type[0]) { + if (!device->type || of_node_cmp(type, device->type)) + return 0; + score += 2; } - return 0; + /* Matching name is a bit better than not */ + if (name && name[0]) { + if (!device->name || of_node_cmp(name, device->name)) + return 0; + score++; + } + + return score; } /** 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, int res; raw_spin_lock_irqsave(&devtree_lock, flags); - res = __of_device_is_compatible(device, compat); + res = __of_device_is_compatible(device, compat, NULL, NULL); raw_spin_unlock_irqrestore(&devtree_lock, flags); return res; } @@ -681,10 +726,7 @@ struct device_node *of_find_compatible_node(struct device_node *from, raw_spin_lock_irqsave(&devtree_lock, flags); np = from ? from->allnext : of_allnodes; for (; np; np = np->allnext) { - if (type - && !(np->type && (of_node_cmp(np->type, type) == 0))) - continue; - if (__of_device_is_compatible(np, compatible) && + if (__of_device_is_compatible(np, compatible, type, NULL) && of_node_get(np)) break; } @@ -730,65 +772,26 @@ out: } EXPORT_SYMBOL(of_find_node_with_property); -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; - const struct of_device_id *m; - - cp = __of_get_property(node, "compatible", &cplen); - while (cp && (cplen > 0)) { - m = matches; - while (m->name[0] || m->type[0] || m->compatible[0]) { - /* 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; - } - - /* 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; + const struct of_device_id *best_match = NULL; + int score, best_score = 0; 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++; + for (; matches->name[0] || matches->type[0] || matches->compatible[0]; matches++) { + score = __of_device_is_compatible(node, matches->compatible, + matches->type, matches->name); + if (score > best_score) { + best_match = matches; + best_score = score; + } } - return NULL; + + return best_match; } /** @@ -796,12 +799,7 @@ 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. 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. + * Low level utility function used by device matching. */ const struct of_device_id *of_match_node(const struct of_device_id *matches, const struct device_node *node) |