diff --git a/scripts/dts/edtlib.py b/scripts/dts/edtlib.py index 24ff5ff77de..abddf937c71 100644 --- a/scripts/dts/edtlib.py +++ b/scripts/dts/edtlib.py @@ -65,7 +65,7 @@ a .dts file to parse and a list of paths to directories containing bindings. # - Please use ""-quoted strings instead of ''-quoted strings, just to make # things consistent (''-quoting is more common otherwise in Python) -from collections import OrderedDict +from collections import OrderedDict, defaultdict import os import re import sys @@ -96,6 +96,25 @@ class EDT: nodes: A list of Node objects for the nodes that appear in the devicetree + compat2enabled: + A collections.defaultdict that maps each 'compatible' string that appears + on some enabled Node to a list of enabled Nodes. + + For example, edt.compat2enabled["bar"] would include the 'foo' and 'bar' + nodes below. + + foo { + compatible = "bar"; + status = "okay"; + ... + }; + bar { + compatible = "foo", "bar", "baz"; + status = "okay"; + ... + }; + + dts_path: The .dts path passed to __init__() @@ -128,6 +147,7 @@ class EDT: self._init_compat2binding(bindings_dirs) self._init_nodes() + self._init_compat2enabled() self._define_order() @@ -443,7 +463,6 @@ class EDT: node.bus_node = node._bus_node() node._init_binding() node._init_regs() - node._set_instance_no() self.nodes.append(node) self._node2enode[dt_node] = node @@ -456,6 +475,15 @@ class EDT: node._init_interrupts() node._init_pinctrls() + def _init_compat2enabled(self): + # Creates self.compat2enabled + + self.compat2enabled = defaultdict(list) + for node in self.nodes: + if node.enabled: + for compat in node.compats: + self.compat2enabled[compat].append(node) + def _check_binding(self, binding, binding_path): # Does sanity checking on 'binding'. Only takes 'self' for the sake of # self._warn(). @@ -689,16 +717,6 @@ class Node: read_only: True if the node has a 'read-only' property, and False otherwise - instance_no: - Dictionary that maps each 'compatible' string for the node to a unique - index among all nodes that have that 'compatible' string. - - As an example, 'instance_no["foo,led"] == 3' can be read as "this is the - fourth foo,led node". - - Only enabled nodes (status != "disabled") are counted. 'instance_no' is - meaningless for disabled nodes. - matching_compat: The 'compatible' string for the binding that matched the node, or None if the node has no binding @@ -1297,17 +1315,6 @@ class Node: return OrderedDict(zip(cell_names, data_list)) - def _set_instance_no(self): - # Initializes self.instance_no - - self.instance_no = {} - - for compat in self.compats: - self.instance_no[compat] = 0 - for other_node in self.edt.nodes: - if compat in other_node.compats and other_node.enabled: - self.instance_no[compat] += 1 - class Register: """ diff --git a/scripts/dts/gen_defines.py b/scripts/dts/gen_defines.py index eb07229aaf0..049dd6c032c 100755 --- a/scripts/dts/gen_defines.py +++ b/scripts/dts/gen_defines.py @@ -42,8 +42,6 @@ def main(): write_top_comment(edt) - active_compats = set() - for node in edt.nodes: if node.enabled and node.matching_compat: # Skip 'fixed-partitions' devices since they are handled by @@ -60,10 +58,8 @@ def main(): write_bus(node) write_existence_flags(node) - active_compats.update(node.compats) - - out_comment("Active compatibles (mentioned in DTS + binding found)") - for compat in sorted(active_compats): + out_comment("Compatibles appearing on enabled nodes") + for compat in sorted(edt.compat2enabled): #define DT_COMPAT_ 1 out(f"COMPAT_{str2ident(compat)}", 1) @@ -272,12 +268,13 @@ def write_bus(node): def write_existence_flags(node): # Generate #defines of the form # - # #define DT_INST__ 1 + # #define DT_INST__ 1 # - # These are flags for which devices exist. + # for enabled nodes. These are flags for which devices exist. for compat in node.compats: - out(f"INST_{node.instance_no[compat]}_{str2ident(compat)}", 1) + instance_no = node.edt.compat2enabled[compat].index(node) + out(f"INST_{instance_no}_{str2ident(compat)}", 1) def node_ident(node): @@ -337,8 +334,11 @@ def node_instance_aliases(node): # This is a list since a node can have multiple 'compatible' strings, each # with their own instance number. - return [f"INST_{node.instance_no[compat]}_{str2ident(compat)}" - for compat in node.compats] + res = [] + for compat in node.compats: + instance_no = node.edt.compat2enabled[compat].index(node) + res.append(f"INST_{instance_no}_{str2ident(compat)}") + return res def write_addr_size(edt, prop_name, prefix): diff --git a/scripts/dts/test.dts b/scripts/dts/test.dts index ea171852bfc..695f925cfe2 100644 --- a/scripts/dts/test.dts +++ b/scripts/dts/test.dts @@ -294,6 +294,31 @@ default-not-used = <234>; }; + // + // For testing EDT.compat2enabled + // + + compat2enabled { + foo-1 { + status = "okay"; + compatible = "compat2enabled"; + }; + foo-disabled { + status = "disabled"; + compatible = "compat2enabled"; + }; + foo-2 { + // No 'status', which is also treated as enabled + compatible = "compat2enabled"; + }; + // Should not create an entry in compat2enabled, since all nodes + // with the compatible are disabled + bar { + status = "disabled"; + compatible = "compat2enabled-disabled"; + }; + }; + // // For testing 'bus:' and 'on-bus:' // diff --git a/scripts/dts/testedtlib.py b/scripts/dts/testedtlib.py index 8de07ecd19f..4d14209ee65 100755 --- a/scripts/dts/testedtlib.py +++ b/scripts/dts/testedtlib.py @@ -164,6 +164,15 @@ warning: "#cells:" in test-bindings/deprecated.yaml is deprecated and will be re verify_streq(edt.get_node("/deprecated/sub-node").props, "OrderedDict([('foos', , data: OrderedDict([('foo', 1), ('bar', 2)])>]>)])") + # + # Test EDT.compat2enabled + # + + verify_streq(edt.compat2enabled["compat2enabled"], "[, ]") + + if "compat2enabled-disabled" in edt.compat2enabled: + fail("'compat2enabled-disabled' should not appear in edt.compat2enabled") + # # Test Node.props (derived from DT and 'properties:' in the binding) #