There are various SoCs that have 2 different peripheral blocks at the same register offset. However, we might have one block marked as status = "disabled" and the other status = "ok". In such cases we shouldn't warn about duplicate unit-address. Here's a cut down example that we would warning about before: /dts-v1/; / { #address-cells = <0x01>; #size-cells = <0x01>; soc { #address-cells = <0x01>; #size-cells = <0x01>; compatible = "simple-bus"; ranges; i2c0: i2c@40003000 { compatible = "nordic,nrf-i2c"; reg = <0x40003000 0x1000>; status = "ok"; }; spi0: spi@40003000 { compatible = "nordic,nrf-spi"; reg = <0x40003000 0x1000>; status = "disabled"; }; }; }; We introduce 'unique_unit_address_if_enabled' check that is disabled by default. Signed-off-by: Kumar Gala <kumar.gala@xxxxxxxxxx> --- This is a rework of my original patch that changed check_unique_unit_address checks.c | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/checks.c b/checks.c index 4834e44..c0ed45e 100644 --- a/checks.c +++ b/checks.c @@ -1212,8 +1212,24 @@ static void check_avoid_unnecessary_addr_size(struct check *c, struct dt_info *d } WARNING(avoid_unnecessary_addr_size, check_avoid_unnecessary_addr_size, NULL, &avoid_default_addr_size); -static void check_unique_unit_address(struct check *c, struct dt_info *dti, - struct node *node) +static bool node_is_disabled(struct node *node) +{ + struct property *prop; + + prop = get_property(node, "status"); + if (prop) { + char *str = prop->val.val; + if (streq("disabled", str)) + return true; + } + + return false; +} + +static void check_unique_unit_address_common(struct check *c, + struct dt_info *dti, + struct node *node, + bool disable_check) { struct node *childa; @@ -1230,18 +1246,38 @@ static void check_unique_unit_address(struct check *c, struct dt_info *dti, if (!strlen(addr_a)) continue; + if (disable_check && node_is_disabled(childa)) + continue; + for_each_child(node, childb) { const char *addr_b = get_unitname(childb); if (childa == childb) break; + if (disable_check && node_is_disabled(childb)) + continue; + if (streq(addr_a, addr_b)) FAIL(c, dti, childb, "duplicate unit-address (also used in node %s)", childa->fullpath); } } } + +static void check_unique_unit_address(struct check *c, struct dt_info *dti, + struct node *node) +{ + check_unique_unit_address_common(c, dti, node, false); +} WARNING(unique_unit_address, check_unique_unit_address, NULL, &avoid_default_addr_size); +static void check_unique_unit_address_if_enabled(struct check *c, struct dt_info *dti, + struct node *node) +{ + check_unique_unit_address_common(c, dti, node, true); +} +CHECK_ENTRY(unique_unit_address_if_enabled, check_unique_unit_address_if_enabled, + NULL, false, false, &avoid_default_addr_size); + static void check_obsolete_chosen_interrupt_controller(struct check *c, struct dt_info *dti, struct node *node) @@ -1769,6 +1805,7 @@ static struct check *check_table[] = { &avoid_default_addr_size, &avoid_unnecessary_addr_size, &unique_unit_address, + &unique_unit_address_if_enabled, &obsolete_chosen_interrupt_controller, &chosen_node_is_root, &chosen_node_bootargs, &chosen_node_stdout_path, -- 2.19.2