From 105353145eafb3ea919f5cdeb652a9d8f270228e Mon Sep 17 00:00:00 2001 From: Sebastian Hesselbarth Date: Tue, 3 Dec 2013 14:52:00 +0100 Subject: OF: base: match each node compatible against all given matches first Currently, of_match_node compares each given match against all node's compatible strings with of_device_is_compatible. To achieve multiple compatible strings per node with ordering from specific to generic, this requires given matches to be ordered from specific to generic. For most of the drivers this is not true and also an alphabetical ordering is more sane there. Therefore, this patch modifies of_match_node to match each of the node's compatible strings against all given matches first, before checking the next compatible string. This implies that node's compatibles are ordered from specific to generic while given matches can be in any order. Signed-off-by: Sebastian Hesselbarth Tested-by: Meelis Roos Signed-off-by: Rob Herring --- drivers/of/base.c | 53 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/of/base.c b/drivers/of/base.c index f807d0edabf3..8d007d8b8c78 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -731,24 +731,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 +775,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) -- cgit v1.2.3 From bf49be02d6f92b95c2462e5027fc90b98f62e324 Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Wed, 27 Nov 2013 23:26:13 -0800 Subject: of: irq: Ignore disabled interrupt controllers When searching the system for interrupt controllers, skip over any that are explicitly disabled. This makes interrupt controllers consistent with regular devices, which can be marked as do-not-probe via the status = "disabled" dts property. Signed-off-by: Peter Crosthwaite Acked-by: Michal Simek Signed-off-by: Rob Herring --- drivers/of/irq.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 786b0b47fae4..9876963ed7b3 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -438,7 +438,8 @@ void __init of_irq_init(const struct of_device_id *matches) INIT_LIST_HEAD(&intc_parent_list); for_each_matching_node(np, matches) { - if (!of_find_property(np, "interrupt-controller", NULL)) + if (!of_find_property(np, "interrupt-controller", NULL) || + !of_device_is_available(np)) continue; /* * Here, we allocate and populate an intc_desc with the node -- cgit v1.2.3 From 1ca56e7dcadd865ae2c235789cbdbfebae719ffb Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Wed, 27 Nov 2013 23:26:12 -0800 Subject: of: irq: Ignore disabled intc's when searching map When searching the interrupt map, if a matched parent is disabled, just ignore it and move on with the search. This allows for specifying connection of a single device IRQ to multiple interrupt controllers via the interrupt map schema. This change allows for selection of the active interrupt controller via the already existing status = "disabled" mechanism. Signed-off-by: Peter Crosthwaite Acked-by: Michal Simek Signed-off-by: Rob Herring --- drivers/of/irq.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 9876963ed7b3..bf8026895c5e 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -217,6 +217,9 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq) goto fail; } + if (!of_device_is_available(newpar)) + match = 0; + /* Get #interrupt-cells and #address-cells of new * parent */ -- cgit v1.2.3 From 42ccd781bb206804501ff490fd771bb940ca9969 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Mon, 13 Jan 2014 11:07:28 +0800 Subject: of: Fix __of_device_is_available check From IEEE 1275, there defined a standard 'status' property indicating the operational status of one device. The 'status' property has four possible values: 'okay/ok', 'disabled', 'fail' and 'fail-xxx'. If it is absent, that means the status of the device is unknown or okay. The __of_device_is_available checks the state of the 'status' property of a device. If the property is absent or set to 'okay/ok', it returns 1. Otherwise it returns 0. While in __of_device_is_available: > status = of_get_property(device, "status", &statlen); > if (status == NULL) > return 1; The status value returned from 'of_get_property()' will be NULL in two cases: Firstly: the 'device' value (device node) is NULL. Secondly: the 'status' property is actaully not exist. If the device node is NULL, the __of_device_is_available will return true, that will mean the absent state of the 'status' property. So this add the device node check before checking the 'status' property's state, and if the device node is not exist, 0 will be returned. Signed-off-by: Xiubo Li Signed-off-by: Grant Likely --- drivers/of/base.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/of/base.c b/drivers/of/base.c index f807d0edabf3..ba195fbce4c6 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -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; -- cgit v1.2.3