[PATCH] checks: Add unit address check if node is enabled

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]



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




[Index of Archives]     [Device Tree]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux