diff --git a/scripts/dts/edtlib.py b/scripts/dts/edtlib.py index e5cbdf26e9ff..a0876423cf0f 100644 --- a/scripts/dts/edtlib.py +++ b/scripts/dts/edtlib.py @@ -65,7 +65,7 @@ # - 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,24 @@ class EDT: nodes: A list of Node objects for the nodes that appear in the devicetree + compat2nodes: + A collections.defaultdict that maps each 'compatible' string that appears + on some enabled Node to a list of enabled Nodes. + + For example, edt.compat2nodes["bar"] would include the 'first' and + 'second' nodes below. + + first { + compatible = "bar"; + status = "okay"; + ... + }; + second { + compatible = "foo", "bar", "baz"; + status = "okay"; + ... + }; + dts_path: The .dts path passed to __init__() @@ -128,6 +146,7 @@ def __init__(self, dts, bindings_dirs, warn_file=None): self._init_compat2binding(bindings_dirs) self._init_nodes() + self._init_compat2nodes() self._define_order() @@ -443,7 +462,6 @@ def _init_nodes(self): 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 +474,15 @@ def _init_nodes(self): node._init_interrupts() node._init_pinctrls() + def _init_compat2nodes(self): + # Creates self.compat2nodes + + self.compat2nodes = defaultdict(list) + for node in self.nodes: + if node.enabled: + for compat in node.compats: + self.compat2nodes[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 +716,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 @@ -1292,17 +1309,6 @@ def _named_cells(self, controller, data, basename): 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 06b7653fe198..a382afa82226 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,12 +58,10 @@ 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.compat2nodes): #define DT_COMPAT_ 1 - out("COMPAT_{}".format(str2ident(compat)), 1) + out("COMPAT_" + str2ident(compat), 1) # Derived from /chosen write_addr_size(edt, "zephyr,sram", "SRAM") @@ -266,7 +262,7 @@ def write_existence_flags(node): # These are flags for which devices exist. for compat in node.compats: - out("INST_{}_{}".format(node.instance_no[compat], + out("INST_{}_{}".format(node.edt.compat2nodes[compat].index(node), str2ident(compat)), 1) @@ -358,7 +354,8 @@ def dev_instance_aliases(node): # This is a list since a device can have multiple 'compatible' strings, # each with their own instance number. - return ["INST_{}_{}".format(node.instance_no[compat], str2ident(compat)) + return ["INST_{}_{}".format(node.edt.compat2nodes[compat].index(node), + str2ident(compat)) for compat in node.compats] diff --git a/scripts/dts/test.dts b/scripts/dts/test.dts index a19d13630cb0..1f49242f5a85 100644 --- a/scripts/dts/test.dts +++ b/scripts/dts/test.dts @@ -293,6 +293,31 @@ default-not-used = <234>; }; + // + // For testing EDT.compat2nodes + // + + compat2nodes { + foo-1 { + status = "okay"; + compatible = "compat2nodes"; + }; + foo-disabled { + status = "disabled"; + compatible = "compat2nodes"; + }; + foo-2 { + // No 'status', which is also treated as enabled + compatible = "compat2nodes"; + }; + // Should not create an entry in compat2nodes, since all nodes + // with the compatible are disabled + bar { + status = "disabled"; + compatible = "compat2nodes-disabled"; + }; + }; + // // For testing 'bus:' and 'on-bus:' // diff --git a/scripts/dts/testedtlib.py b/scripts/dts/testedtlib.py index 7dd89ef69127..cb9201f107b5 100755 --- a/scripts/dts/testedtlib.py +++ b/scripts/dts/testedtlib.py @@ -174,6 +174,15 @@ def verify_streq(actual, expected): verify_streq(edt.get_node("/deprecated/sub-node").props, "OrderedDict([('foos', , data: OrderedDict([('foo', 1), ('bar', 2)])>]>)])") + # + # Test EDT.compat2nodes + # + + verify_streq(edt.compat2nodes["compat2nodes"], "[, ]") + + if "compat2nodes-disabled" in edt.compat2nodes: + fail("'compat2nodes-disabled' should not appear in edt.compat2nodes") + # # Test Node.props (derived from DT and 'properties:' in the binding) # @@ -237,7 +246,6 @@ def verify_streq(actual, expected): verify_streq(edt.get_node("/in-dir-2").binding_path, "test-bindings-2/multidir.yaml") - # # Test dependency relations #