dtoc: Support processing the root node

The device for the root node is normally bound by driver model on init.
With devices being instantiated at build time, we must handle the root
device also.

Add support for processing the root node, which may not have a compatible
string.

Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
Simon Glass
2021-02-03 06:01:11 -07:00
parent 337d6972f5
commit 50aae3e62d
4 changed files with 58 additions and 19 deletions

View File

@@ -350,16 +350,22 @@ class DtbPlatdata():
# recurse to handle any subnodes # recurse to handle any subnodes
self.scan_node(subnode, valid_nodes) self.scan_node(subnode, valid_nodes)
def scan_tree(self): def scan_tree(self, add_root):
"""Scan the device tree for useful information """Scan the device tree for useful information
This fills in the following properties: This fills in the following properties:
_valid_nodes_unsorted: A list of nodes we wish to consider include _valid_nodes_unsorted: A list of nodes we wish to consider include
in the platform data (in devicetree node order) in the platform data (in devicetree node order)
_valid_nodes: Sorted version of _valid_nodes_unsorted _valid_nodes: Sorted version of _valid_nodes_unsorted
Args:
add_root: True to add the root node also (which wouldn't normally
be added as it may not have a compatible string)
""" """
root = self._fdt.GetRoot() root = self._fdt.GetRoot()
valid_nodes = [] valid_nodes = []
if add_root:
valid_nodes.append(root)
self.scan_node(root, valid_nodes) self.scan_node(root, valid_nodes)
self._valid_nodes_unsorted = valid_nodes self._valid_nodes_unsorted = valid_nodes
self._valid_nodes = sorted(valid_nodes, self._valid_nodes = sorted(valid_nodes,
@@ -839,7 +845,7 @@ def run_steps(args, dtb_file, include_disabled, output, output_dirs, phase,
do_process = False do_process = False
plat = DtbPlatdata(scan, dtb_file, include_disabled) plat = DtbPlatdata(scan, dtb_file, include_disabled)
plat.scan_dtb() plat.scan_dtb()
plat.scan_tree() plat.scan_tree(add_root=False)
plat.prepare_nodes() plat.prepare_nodes()
plat.scan_reg_sizes() plat.scan_reg_sizes()
plat.setup_output_dirs(output_dirs) plat.setup_output_dirs(output_dirs)

View File

@@ -33,6 +33,8 @@ def conv_name_to_c(name):
new = new.replace('-', '_') new = new.replace('-', '_')
new = new.replace(',', '_') new = new.replace(',', '_')
new = new.replace('.', '_') new = new.replace('.', '_')
if new == '/':
return 'root'
return new return new
def get_compat_name(node): def get_compat_name(node):
@@ -250,7 +252,10 @@ class Scanner:
In case of no match found, the return will be the same as In case of no match found, the return will be the same as
get_compat_name() get_compat_name()
""" """
compat_list_c = get_compat_name(node) if not node.parent:
compat_list_c = ['root_driver']
else:
compat_list_c = get_compat_name(node)
for compat_c in compat_list_c: for compat_c in compat_list_c:
if not compat_c in self._drivers.keys(): if not compat_c in self._drivers.keys():
@@ -509,21 +514,23 @@ class Scanner:
elif m_hdr: elif m_hdr:
driver.headers.append(m_hdr.group(1)) driver.headers.append(m_hdr.group(1))
elif '};' in line: elif '};' in line:
if driver.uclass_id and compat: is_root = driver.name == 'root_driver'
if compat not in of_match: if driver.uclass_id and (compat or is_root):
raise ValueError( if not is_root:
"%s: Unknown compatible var '%s' (found: %s)" % if compat not in of_match:
(fname, compat, ','.join(of_match.keys()))) raise ValueError(
driver.compat = of_match[compat] "%s: Unknown compatible var '%s' (found: %s)" %
(fname, compat, ','.join(of_match.keys())))
driver.compat = of_match[compat]
# This needs to be deterministic, since a driver may # This needs to be deterministic, since a driver may
# have multiple compatible strings pointing to it. # have multiple compatible strings pointing to it.
# We record the one earliest in the alphabet so it # We record the one earliest in the alphabet so it
# will produce the same result on all machines. # will produce the same result on all machines.
for compat_id in of_match[compat]: for compat_id in of_match[compat]:
old = self._compat_to_driver.get(compat_id) old = self._compat_to_driver.get(compat_id)
if not old or driver.name < old.name: if not old or driver.name < old.name:
self._compat_to_driver[compat_id] = driver self._compat_to_driver[compat_id] = driver
drivers[driver.name] = driver drivers[driver.name] = driver
else: else:
# The driver does not have a uclass or compat string. # The driver does not have a uclass or compat string.

View File

@@ -974,10 +974,10 @@ U_BOOT_DRVINFO(spl_test2) = {
output = tools.GetOutputFilename('output') output = tools.GetOutputFilename('output')
# Take a copy before messing with it # Take a copy before messing with it
scan = copy.deepcopy(saved_scan) scan = copy_scan()
plat = dtb_platdata.DtbPlatdata(scan, dtb_file, False) plat = dtb_platdata.DtbPlatdata(scan, dtb_file, False)
plat.scan_dtb() plat.scan_dtb()
plat.scan_tree() plat.scan_tree(False)
plat.prepare_nodes() plat.prepare_nodes()
return plat, scan return plat, scan
@@ -1123,3 +1123,22 @@ U_BOOT_DRVINFO(spl_test2) = {
self.assertEqual(4, i2c.seq) self.assertEqual(4, i2c.seq)
spl = plat._fdt.GetNode('/spl-test') spl = plat._fdt.GetNode('/spl-test')
self.assertEqual(0, spl.seq) self.assertEqual(0, spl.seq)
def test_process_root(self):
"""Test assignment of sequence numnbers"""
dtb_file = get_dtb_file('dtoc_test_simple.dts')
output = tools.GetOutputFilename('output')
# Take a copy before messing with it
scan = copy_scan()
plat = dtb_platdata.DtbPlatdata(scan, dtb_file, False)
plat.scan_dtb()
root = plat._fdt.GetRoot()
plat.scan_tree(False)
self.assertNotIn(root, plat._valid_nodes)
plat.scan_tree(True)
self.assertIn(root, plat._valid_nodes)
self.assertEqual('root_driver',
scan.get_normalized_compat_name(root)[0])

View File

@@ -161,6 +161,10 @@ class TestSrcScan(unittest.TestCase):
prop.value = 'rockchip,rk3288-grf' prop.value = 'rockchip,rk3288-grf'
node = FakeNode() node = FakeNode()
node.props = {'compatible': prop} node.props = {'compatible': prop}
# get_normalized_compat_name() uses this to check for root node
node.parent = FakeNode()
scan = src_scan.Scanner(None, False, None) scan = src_scan.Scanner(None, False, None)
with test_util.capture_sys_output() as (stdout, _): with test_util.capture_sys_output() as (stdout, _):
name, aliases = scan.get_normalized_compat_name(node) name, aliases = scan.get_normalized_compat_name(node)
@@ -419,6 +423,9 @@ U_BOOT_DRIVER(%s) = {
node.name = 'testing' node.name = 'testing'
node.props = {'compatible': prop} node.props = {'compatible': prop}
# get_normalized_compat_name() uses this to check for root node
node.parent = FakeNode()
return scan, drv1, driver2, node return scan, drv1, driver2, node
def test_dup_drivers(self): def test_dup_drivers(self):