From 846e661da1f8f72ac444495639b9a1582bf0d0af Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Fri, 1 May 2020 12:33:00 -0500 Subject: [PATCH 1/4] edtlib: populate standard properties for nodes without bindings If a devicetree node doesn't have a matching binding we will at least populate a common standard set of properties for that node. The list of standard properties is: compatible status reg reg-names label interrupt interrupts-extended interrupt-names interrupt-controller This allows us to handle cases like memory nodes that don't have any compatible property, we can still generate the reg values. We limit this to known properties as for any other property we can not fully determine the property type without a binding and thus we can't ensure the generation for that property is correct or may not change. Signed-off-by: Kumar Gala --- scripts/dts/edtlib.py | 40 ++++++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/scripts/dts/edtlib.py b/scripts/dts/edtlib.py index 1bfb90127b3c4..e440332027690 100644 --- a/scripts/dts/edtlib.py +++ b/scripts/dts/edtlib.py @@ -1087,15 +1087,43 @@ def _init_props(self): self.props = OrderedDict() - if not self._binding: - return + node = self._node + if self._binding: + binding_props = self._binding.get("properties") + else: + binding_props = None # Initialize self.props - if "properties" in self._binding: - for name, options in self._binding["properties"].items(): + if binding_props: + for name, options in binding_props.items(): self._init_prop(name, options) - - self._check_undeclared_props() + self._check_undeclared_props() + else: + common_prop_types = { + "compatible" : "string-array", + "status" : "string", + "reg" : "array", + "reg-names": "string-array", + "label" : "string", + "interrupt" : "array", + "interrupts-extended": "compound", + "interrupt-names": "string-array", + "interrupt-controller": "boolean", + } + + for name in node.props: + if name in common_prop_types: + prop_type = common_prop_types[name] + val = self._prop_val(name, prop_type, False, None) + prop = Property() + prop.node = self + prop.name = name + prop.description = None + prop.val = val + prop.type = prop_type + # We don't set enum_index for "compatible" + prop.enum_index = None + self.props[name] = prop def _init_prop(self, name, options): # _init_props() helper for initializing a single property From 0e6621a7b424c9c70b6684311456190886b296fe Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Tue, 28 Apr 2020 10:31:47 -0500 Subject: [PATCH 2/4] devicetree: gen_defines: Don't require matching compat to gen defines There are cases like having a reserved memory node that will not having a compatible string and thus will not match a binding. However we might set a chosen property like zephyr,sram or zephyr,ipc_shm to such a node. Thus we should generate defines for such nodes. Signed-off-by: Kumar Gala --- scripts/dts/gen_defines.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/scripts/dts/gen_defines.py b/scripts/dts/gen_defines.py index f86c2b9aa4c56..ffbfcbe134662 100755 --- a/scripts/dts/gen_defines.py +++ b/scripts/dts/gen_defines.py @@ -59,9 +59,6 @@ def main(): if not node.enabled: out_comment("No node macros: node is disabled") continue - if not node.matching_compat: - out_comment("No node macros: node has no matching binding") - continue write_idents_and_existence(node) write_bus(node) From ac2c66edee418073aa5f32d237f289a62a726f2f Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Wed, 6 May 2020 06:19:15 -0500 Subject: [PATCH 3/4] edtlib: change semantics of node.enabled Change node.enabled from being True unless status = "disabled", to True if no status, status = "okay", or status = "ok". Signed-off-by: Kumar Gala --- scripts/dts/edtlib.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/dts/edtlib.py b/scripts/dts/edtlib.py index e440332027690..513c50a18d546 100644 --- a/scripts/dts/edtlib.py +++ b/scripts/dts/edtlib.py @@ -771,7 +771,7 @@ class Node: A list with the nodes that the node directly depends on enabled: - True unless the node has 'status = "disabled"' + True if 'status = "okay"', 'status = "ok"', or no status property. read_only: True if the node has a 'read-only' property, and False otherwise @@ -914,7 +914,8 @@ def depends_on(self): def enabled(self): "See the class docstring" return "status" not in self._node.props or \ - self._node.props["status"].to_string() != "disabled" + self._node.props["status"].to_string() == "okay" or \ + self._node.props["status"].to_string() == "ok" @property def read_only(self): From f594580b18a5479b0f3697c7874f15fbda080423 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Wed, 6 May 2020 05:12:59 -0500 Subject: [PATCH 4/4] devicetree.h: Add DT_NODE_HAS_STATUS() This macro takes a node identifier and status value and returns 0 or 1 if the status property on the node referred to by the node identifier matches the status value passed. We also update DT_HAS_NODE_STATUS_OKAY to utilize DT_NODE_HAS_STATUS Signed-off-by: Kumar Gala --- doc/guides/dts/macros.bnf | 2 ++ include/devicetree.h | 34 +++++++++++++++++++++++++++++++- scripts/dts/gen_defines.py | 16 +++++++++++++++ tests/lib/devicetree/app.overlay | 7 +++++++ tests/lib/devicetree/src/main.c | 22 +++++++++++++++++++++ 5 files changed, 80 insertions(+), 1 deletion(-) diff --git a/doc/guides/dts/macros.bnf b/doc/guides/dts/macros.bnf index 828a6cd995171..e26dab1ee4546 100644 --- a/doc/guides/dts/macros.bnf +++ b/doc/guides/dts/macros.bnf @@ -43,6 +43,8 @@ node-macro =/ %s"DT_N" path-id %s"_IRQ_NAME_" dt-name node-macro =/ %s"DT_N" path-id %s"_COMPAT_MATCHES_" dt-name ; The node identifier for the node's parent in the devicetree. node-macro =/ %s"DT_N" path-id %s"_PARENT" +; The node identifier for the node's status +node-macro =/ %s"DT_N" path-id %s"_STATUS_" status ; -------------------------------------------------------------------- ; property-macro: a macro related to a node property diff --git a/include/devicetree.h b/include/devicetree.h index 5f72456afb0d8..68397c2be8b67 100644 --- a/include/devicetree.h +++ b/include/devicetree.h @@ -880,6 +880,38 @@ * @{ */ +/** @internal helper for DT_NODE_HAS_STATUS so we can additional + * macro expansion + */ +#define DT_NODE_HAS_STATUS_(node_id, status) \ + IS_ENABLED(DT_CAT(node_id, _STATUS_##status)) + +/** + * @brief Does a devicetree node match a status? + * + * Example devicetree fragment: + * + * n: node { + * compatible = "generic-device"; + * status = "okay"; + * } + * + * Example usages which evaluate to 1: + * + * DT_NODE_HAS_STATUS(DT_NODELABEL(n), okay) + * + * Example usages which evaluate to 0: + * + * DT_NODE_HAS_STATUS(DT_NODELABEL(n), disabled) + * + * @param node_id node identifier + * @param status status value to check for + * @return 1 if the node's status property matches status, + * 0 otherwise. + */ +#define DT_NODE_HAS_STATUS(node_id, status) \ + DT_NODE_HAS_STATUS_(node_id, status) + /** * @brief Does a node identifier refer to a usable node? * @@ -898,7 +930,7 @@ * @return 1 if the node identifier refers to a usable node, * 0 otherwise. */ -#define DT_HAS_NODE_STATUS_OKAY(node_id) IS_ENABLED(DT_CAT(node_id, _EXISTS)) +#define DT_HAS_NODE_STATUS_OKAY(node_id) DT_NODE_HAS_STATUS(node_id, okay) /** * @brief Does the devicetree have any usable nodes with a compatible? diff --git a/scripts/dts/gen_defines.py b/scripts/dts/gen_defines.py index ffbfcbe134662..55583a25e4a35 100755 --- a/scripts/dts/gen_defines.py +++ b/scripts/dts/gen_defines.py @@ -241,6 +241,7 @@ def write_special_props(node): write_regs(node) write_interrupts(node) write_compatibles(node) + write_status(node) def write_regs(node): @@ -356,6 +357,21 @@ def write_compatibles(node): f"{node.z_path_id}_COMPAT_MATCHES_{str2ident(compat)}", 1) +def write_status(node): + # Writes a macro that we can utilize to test the "status" of a node + # We normalize status = "ok" to "okay", and if there is no "status" + # property we treat that as "okay" + + if "status" in node.props: + status = node.props["status"].val + if status == "ok": + status = "okay" + else: + status = "okay" + + out_dt_define(f"{node.z_path_id}_STATUS_{status}", 1) + + def write_vanilla_props(node): # Writes macros for any and all properties defined in the # "properties" section of the binding for the node. diff --git a/tests/lib/devicetree/app.overlay b/tests/lib/devicetree/app.overlay index 9293918cf4f7a..54b1dfeffa952 100644 --- a/tests/lib/devicetree/app.overlay +++ b/tests/lib/devicetree/app.overlay @@ -75,6 +75,13 @@ status = "disabled"; }; + test_no_status: intc_no_status@0 { + compatible = "vnd,intc"; + reg = <0x0 0x1000>; + interrupt-controller; + #interrupt-cells = <2>; + }; + test_nodelabel: TEST_NODELABEL_ALLCAPS: test_gpio_1: gpio@deadbeef { compatible = "vnd,gpio"; gpio-controller; diff --git a/tests/lib/devicetree/src/main.c b/tests/lib/devicetree/src/main.c index 18c8e4cd16697..cf5d924f66794 100644 --- a/tests/lib/devicetree/src/main.c +++ b/tests/lib/devicetree/src/main.c @@ -200,6 +200,27 @@ static void test_has_compat(void) zassert_equal(compats, 0x3, "as bit array"); } +static void test_has_status(void) +{ + zassert_equal(DT_NODE_HAS_STATUS(DT_NODELABEL(test_gpio_1), okay), + 1, "vnd,gpio okay"); + zassert_equal(DT_NODE_HAS_STATUS(DT_NODELABEL(test_gpio_1), disabled), + 0, "vnd,gpio not disabled"); + + zassert_equal(DT_NODE_HAS_STATUS(DT_NODELABEL(test_no_status), okay), + 1, "vnd,gpio okay"); + zassert_equal(DT_NODE_HAS_STATUS(DT_NODELABEL(test_no_status), disabled), + 0, "vnd,gpio not disabled"); + +/* Disabled for now until we generate something for non-"enabled" nodes */ +#if 0 + zassert_equal(DT_NODE_HAS_STATUS(DT_NODELABEL(disabled_gpio), disabled), + 1, "vnd,disabled-compat disabled"); + zassert_equal(DT_NODE_HAS_STATUS(DT_NODELABEL(disabled_gpio), okay), + 0, "vnd,disabled-compat not okay"); +#endif +} + #define TEST_I2C_DEV DT_PATH(test, i2c_11112222, test_i2c_dev_10) #define TEST_I2C_BUS DT_BUS(TEST_I2C_DEV) @@ -1381,6 +1402,7 @@ void test_main(void) ztest_unit_test(test_inst_checks), ztest_unit_test(test_has_nodelabel), ztest_unit_test(test_has_compat), + ztest_unit_test(test_has_status), ztest_unit_test(test_bus), ztest_unit_test(test_reg), ztest_unit_test(test_irq),