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>
This commit is contained in:
Kumar Gala 2018-12-13 13:30:14 -06:00 committed by David Gibson
parent f267e674d1
commit 7cbc550f90

View file

@ -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,