diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/dtoc/dtb_platdata.py | 46 | ||||
-rw-r--r-- | tools/dtoc/src_scan.py | 45 | ||||
-rwxr-xr-x | tools/dtoc/test_dtoc.py | 29 | ||||
-rw-r--r-- | tools/dtoc/test_src_scan.py | 17 |
4 files changed, 119 insertions, 18 deletions
diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py index 9e99c63ae70..af21156659b 100644 --- a/tools/dtoc/dtb_platdata.py +++ b/tools/dtoc/dtb_platdata.py @@ -151,6 +151,8 @@ class DtbPlatdata(): key (str): Field name value: Prop object with field information _basedir (str): Base directory of source tree + _valid_uclasses (list of src_scan.Uclass): List of uclasses needed for + the selected devices (see _valid_node), in alphabetical order """ def __init__(self, scan, dtb_fname, include_disabled): self._scan = scan @@ -164,6 +166,7 @@ class DtbPlatdata(): self._dirnames = [None] * len(Ftype) self._struct_data = collections.OrderedDict() self._basedir = None + self._valid_uclasses = None def setup_output_dirs(self, output_dirs): """Set up the output directories @@ -677,23 +680,12 @@ class DtbPlatdata(): elif result is False: print("Could not find uclass for alias '%s'" % prop.name) - def assign_seq(self): + def assign_seqs(self): """Assign a sequence number to each node""" for node in self._valid_nodes_unsorted: - if node.driver and node.seq == -1 and node.uclass: - uclass = node.uclass - num = uclass.alias_path_to_num.get(node.path) - if num is not None: - node.seq = num - else: - # Dynamically allocate the next available value after all - # existing ones - for seq in range(1000): - if seq not in uclass.alias_num_to_node: - break - node.seq = seq - uclass.alias_path_to_num[node.path] = seq - uclass.alias_num_to_node[seq] = node + seq = self._scan.assign_seq(node) + if seq is not None: + node.seq = seq def process_nodes(self, need_drivers): nodes_to_output = list(self._valid_nodes) @@ -710,6 +702,16 @@ class DtbPlatdata(): raise ValueError("Cannot parse/find driver for '%s'" % node.struct_name) node.driver = driver + uclass = self._scan._uclass.get(driver.uclass_id) + if not uclass: + raise ValueError("Cannot parse/find uclass '%s' for driver '%s'" % + (driver.uclass_id, node.struct_name)) + node.uclass = uclass + node.uclass_seq = len(node.uclass.devs) + node.uclass.devs.append(node) + uclass.node_refs[node.uclass_seq] = \ + '&%s->uclass_node' % node.dev_ref + parent_driver = None if node.parent in self._valid_nodes: parent_driver = self._scan.get_driver(node.parent.struct_name) @@ -730,6 +732,18 @@ class DtbPlatdata(): node.child_refs[-1] = ref node.child_refs[len(node.child_devs)] = ref + uclass_set = set() + for driver in self._scan._drivers.values(): + if driver.used and driver.uclass: + uclass_set.add(driver.uclass) + self._valid_uclasses = sorted(list(uclass_set), + key=lambda uc: uc.uclass_id) + + for seq, uclass in enumerate(uclass_set): + ref = '&DM_UCLASS_REF(%s)->dev_head' % uclass.name + uclass.node_refs[-1] = ref + uclass.node_refs[len(uclass.devs)] = ref + def output_node(self, node): """Output the C code for a node @@ -833,7 +847,7 @@ def run_steps(args, dtb_file, include_disabled, output, output_dirs, phase, plat.scan_phandles() plat.process_nodes(False) plat.read_aliases() - plat.assign_seq() + plat.assign_seqs() cmds = args[0].split(',') if 'all' in cmds: diff --git a/tools/dtoc/src_scan.py b/tools/dtoc/src_scan.py index bb22b0b64ff..8619206a8d4 100644 --- a/tools/dtoc/src_scan.py +++ b/tools/dtoc/src_scan.py @@ -74,6 +74,7 @@ class Driver: found after this one warn_dups (bool): True if the duplicates are not distinguisble using the phase + uclass (Uclass): uclass for this driver """ def __init__(self, name, fname): self.name = name @@ -89,6 +90,7 @@ class Driver: self.headers = [] self.dups = [] self.warn_dups = False + self.uclass = None def __eq__(self, other): return (self.name == other.name and @@ -123,6 +125,10 @@ class UclassDriver: alias_path_to_num (dict): Convert a path to an alias number key (str): Full path to node (e.g. '/soc/pci') seq (int): Alias number, e.g. 2 for "pci2" + devs (list): List of devices in this uclass, each a Node + node_refs (dict): References in the linked list of devices: + key (int): Sequence number (0=first, n-1=last, -1=head, n=tail) + value (str): Reference to the device at that position """ def __init__(self, name): self.name = name @@ -134,6 +140,8 @@ class UclassDriver: self.per_child_plat = '' self.alias_num_to_node = {} self.alias_path_to_num = {} + self.devs = [] + self.node_refs = {} def __eq__(self, other): return (self.name == other.name and @@ -639,6 +647,12 @@ class Scanner: else: self.scan_driver(self._basedir + '/' + fname) + # Get the uclass for each driver + # TODO: Can we just get the uclass for the ones we use, e.g. in + # mark_used()? + for driver in self._drivers.values(): + driver.uclass = self._uclass.get(driver.uclass_id) + def mark_used(self, nodes): """Mark the drivers associated with a list of nodes as 'used' @@ -682,3 +696,34 @@ class Scanner: uclass.alias_path_to_num[node.path] = int(num) return True return False + + def assign_seq(self, node): + """Figure out the sequence number for a node + + This looks in the node's uclass and assigns a sequence number if needed, + based on the aliases and other nodes in that uclass. + + It updates the uclass alias_path_to_num and alias_num_to_node + + Args: + node (Node): Node object to look up + """ + if node.driver and node.seq == -1 and node.uclass: + uclass = node.uclass + num = uclass.alias_path_to_num.get(node.path) + if num is not None: + return num + else: + # Dynamically allocate the next available value after all + # existing ones + if uclass.alias_num_to_node: + start = max(uclass.alias_num_to_node.keys()) + else: + start = -1 + for seq in range(start + 1, 1000): + if seq not in uclass.alias_num_to_node: + break + uclass.alias_path_to_num[node.path] = seq + uclass.alias_num_to_node[seq] = node + return seq + return None diff --git a/tools/dtoc/test_dtoc.py b/tools/dtoc/test_dtoc.py index b4c0a042a9f..b077cf0e76d 100755 --- a/tools/dtoc/test_dtoc.py +++ b/tools/dtoc/test_dtoc.py @@ -141,6 +141,8 @@ class TestDtoc(unittest.TestCase): Returns: DtbPlatdata object """ + # Make a copy of the 'scan' object, since it includes uclasses and + # drivers, which get updated during execution. return dtb_platdata.run_steps(args, dtb_file, False, output, [], None, warning_disabled=True, scan=copy_scan()) @@ -1033,6 +1035,16 @@ U_BOOT_DRVINFO(spl_test2) = { self.assertIn("Cannot parse/find driver for 'sandbox_pmic", str(exc.exception)) + def test_process_nodes_bad_uclass(self): + plat, scan = self.setup_process_test() + + self.assertIn('UCLASS_I2C', scan._uclass) + del scan._uclass['UCLASS_I2C'] + with self.assertRaises(ValueError) as exc: + plat.process_nodes(True) + self.assertIn("Cannot parse/find uclass 'UCLASS_I2C' for driver 'sandbox_i2c'", + str(exc.exception)) + def test_process_nodes_used(self): """Test processing nodes to add various info""" plat, scan = self.setup_process_test() @@ -1052,10 +1064,13 @@ U_BOOT_DRVINFO(spl_test2) = { scan = plat._scan testfdt_node = plat._fdt.GetNode('/some-bus/test') + test0_node = plat._fdt.GetNode('/some-bus/test0') self.assertIn('UCLASS_TEST_FDT', scan._uclass) uc = scan._uclass['UCLASS_TEST_FDT'] - self.assertEqual({1: testfdt_node}, uc.alias_num_to_node) - self.assertEqual({'/some-bus/test': 1}, uc.alias_path_to_num) + self.assertEqual({1: testfdt_node, 2: test0_node}, + uc.alias_num_to_node) + self.assertEqual({'/some-bus/test': 1, '/some-bus/test0': 2}, + uc.alias_path_to_num) # Try adding an alias that doesn't exist self.assertFalse(scan.add_uclass_alias('fred', 3, None)) @@ -1098,3 +1113,13 @@ U_BOOT_DRVINFO(spl_test2) = { dtb_file = get_dtb_file('dtoc_test_inst.dts') output = tools.GetOutputFilename('output') plat = self.run_test(['struct'], dtb_file, output) + + scan = plat._scan + testfdt = plat._fdt.GetNode('/some-bus/test') + self.assertEqual(1, testfdt.seq) + i2c = plat._fdt.GetNode('/i2c') + + # For now this uclass is not compiled in, so no sequence is assigned + self.assertEqual(4, i2c.seq) + spl = plat._fdt.GetNode('/spl-test') + self.assertEqual(0, spl.seq) diff --git a/tools/dtoc/test_src_scan.py b/tools/dtoc/test_src_scan.py index 598ff256a60..d32aa58400f 100644 --- a/tools/dtoc/test_src_scan.py +++ b/tools/dtoc/test_src_scan.py @@ -466,3 +466,20 @@ U_BOOT_DRIVER(%s) = { with test_util.capture_sys_output() as (stdout, _): scan.mark_used([node]) self.assertEqual('', stdout.getvalue().strip()) + + def test_sequence(self): + """Test assignment of sequence numnbers""" + scan = src_scan.Scanner(None, False, None, '') + node = FakeNode() + uc = src_scan.UclassDriver('UCLASS_I2C') + node.uclass = uc + node.driver = True + node.seq = -1 + node.path = 'mypath' + uc.alias_num_to_node[2] = node + + # This should assign 3 (after the 2 that exists) + seq = scan.assign_seq(node) + self.assertEqual(3, seq) + self.assertEqual({'mypath': 3}, uc.alias_path_to_num) + self.assertEqual({2: node, 3: node}, uc.alias_num_to_node) |