diff options
author | Kumar Gala <kumar.gala@linaro.org> | 2018-12-13 13:30:14 -0600 |
---|---|---|
committer | David Gibson <david@gibson.dropbear.id.au> | 2018-12-15 18:47:55 +1100 |
commit | 7cbc550f903b23f2291c7ca5d347ae0236ce27b6 (patch) | |
tree | 458f9eff940e601e74017b95d92d192f6a1f69b4 /checks.c | |
parent | f267e674d1452d381bb2f180695801454d3549ad (diff) | |
download | dtc-7cbc550f903b23f2291c7ca5d347ae0236ce27b6.zip dtc-7cbc550f903b23f2291c7ca5d347ae0236ce27b6.tar.gz dtc-7cbc550f903b23f2291c7ca5d347ae0236ce27b6.tar.bz2 |
checks: Add unit address check if node is enabled
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@linaro.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'checks.c')
-rw-r--r-- | checks.c | 41 |
1 files changed, 39 insertions, 2 deletions
@@ -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, |