Skip to content

dts: edtlib: Turn Node.instance_no into more flexible EDT.compat2nodes #21592

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 29 additions & 23 deletions scripts/dts/edtlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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__()

Expand Down Expand Up @@ -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()

Expand Down Expand Up @@ -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
Expand All @@ -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().
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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:
"""
Expand Down
15 changes: 6 additions & 9 deletions scripts/dts/gen_defines.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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_<COMPAT> 1
out("COMPAT_{}".format(str2ident(compat)), 1)
out("COMPAT_" + str2ident(compat), 1)

# Derived from /chosen
write_addr_size(edt, "zephyr,sram", "SRAM")
Expand Down Expand Up @@ -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)


Expand Down Expand Up @@ -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]


Expand Down
25 changes: 25 additions & 0 deletions scripts/dts/test.dts
Original file line number Diff line number Diff line change
Expand Up @@ -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:'
//
Expand Down
10 changes: 9 additions & 1 deletion scripts/dts/testedtlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,15 @@ def verify_streq(actual, expected):
verify_streq(edt.get_node("/deprecated/sub-node").props,
"OrderedDict([('foos', <Property, name: foos, type: phandle-array, value: [<ControllerAndData, controller: <Node /deprecated in 'test.dts', binding test-bindings/deprecated.yaml>, data: OrderedDict([('foo', 1), ('bar', 2)])>]>)])")

#
# Test EDT.compat2nodes
#

verify_streq(edt.compat2nodes["compat2nodes"], "[<Node /compat2nodes/foo-1 in 'test.dts', no binding>, <Node /compat2nodes/foo-2 in 'test.dts', no binding>]")

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)
#
Expand Down Expand Up @@ -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
#
Expand Down