mirror of
				https://xff.cz/git/u-boot/
				synced 2025-10-31 02:15:45 +01:00 
			
		
		
		
	dtoc: Process nodes to set up required properties
Add logic to assign property values to nodes as required by dtoc. The references allow nodes to refer to each other in C code. The macros used by dtoc are not yet defined in driver model. They will be added along with the actual driver model implementation. Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
		| @@ -647,6 +647,38 @@ class DtbPlatdata(): | ||||
|             self._output_prop(node, node.props[pname]) | ||||
|         self.buf('};\n') | ||||
|  | ||||
|     def process_nodes(self, need_drivers): | ||||
|         nodes_to_output = list(self._valid_nodes) | ||||
|  | ||||
|         for node in nodes_to_output: | ||||
|             node.dev_ref = 'DM_DEVICE_REF(%s)' % node.var_name | ||||
|             driver = self._scan.get_driver(node.struct_name) | ||||
|             if not driver: | ||||
|                 if not need_drivers: | ||||
|                     continue | ||||
|                 raise ValueError("Cannot parse/find driver for '%s'" % | ||||
|                                  node.struct_name) | ||||
|             node.driver = driver | ||||
|             parent_driver = None | ||||
|             if node.parent in self._valid_nodes: | ||||
|                 parent_driver = self._scan.get_driver(node.parent.struct_name) | ||||
|                 if not parent_driver: | ||||
|                     if not need_drivers: | ||||
|                         continue | ||||
|                     raise ValueError( | ||||
|                         "Cannot parse/find parent driver '%s' for '%s'" % | ||||
|                         (node.parent.struct_name, node.struct_name)) | ||||
|                 node.parent_seq = len(node.parent.child_devs) | ||||
|                 node.parent.child_devs.append(node) | ||||
|                 node.parent.child_refs[node.parent_seq] = \ | ||||
|                     '&%s->sibling_node' % node.dev_ref | ||||
|                 node.parent_driver = parent_driver | ||||
|  | ||||
|         for node in nodes_to_output: | ||||
|             ref = '&%s->child_head' % node.dev_ref | ||||
|             node.child_refs[-1] = ref | ||||
|             node.child_refs[len(node.child_devs)] = ref | ||||
|  | ||||
|     def output_node(self, node): | ||||
|         """Output the C code for a node | ||||
|  | ||||
| @@ -731,6 +763,9 @@ def run_steps(args, dtb_file, include_disabled, output, output_dirs, | ||||
|     if not scan: | ||||
|         scan = src_scan.Scanner(basedir, warning_disabled, drivers_additional) | ||||
|         scan.scan_drivers() | ||||
|         do_process = True | ||||
|     else: | ||||
|         do_process = False | ||||
|     plat = DtbPlatdata(scan, dtb_file, include_disabled) | ||||
|     plat.scan_dtb() | ||||
|     plat.scan_tree() | ||||
| @@ -739,6 +774,8 @@ def run_steps(args, dtb_file, include_disabled, output, output_dirs, | ||||
|     plat.setup_output_dirs(output_dirs) | ||||
|     plat.scan_structs() | ||||
|     plat.scan_phandles() | ||||
|     if do_process: | ||||
|         plat.process_nodes(False) | ||||
|  | ||||
|     cmds = args[0].split(',') | ||||
|     if 'all' in cmds: | ||||
|   | ||||
| @@ -188,6 +188,17 @@ class Scanner: | ||||
|         self._uclass = {} | ||||
|         self._structs = {} | ||||
|  | ||||
|     def get_driver(self, name): | ||||
|         """Get a driver given its name | ||||
|  | ||||
|         Args: | ||||
|             name (str): Driver name | ||||
|  | ||||
|         Returns: | ||||
|             Driver: Driver or None if not found | ||||
|         """ | ||||
|         return self._drivers.get(name) | ||||
|  | ||||
|     def get_normalized_compat_name(self, node): | ||||
|         """Get a node's normalized compat name | ||||
|  | ||||
|   | ||||
| @@ -953,3 +953,79 @@ U_BOOT_DRVINFO(spl_test2) = { | ||||
|         self.assertEqual( | ||||
|             {'dt-structs-gen.h', 'source.dts', 'dt-plat.c', 'source.dtb'}, | ||||
|             leafs) | ||||
|  | ||||
|     def setup_process_test(self): | ||||
|         """Set up a test of process_nodes() | ||||
|  | ||||
|         This uses saved_scan but returns a deep copy of it, so it is safe to | ||||
|         modify it in these tests | ||||
|  | ||||
|         Returns: | ||||
|             tuple: | ||||
|                 DtbPlatdata: object to test | ||||
|                 Scanner: scanner to use | ||||
|         """ | ||||
|         dtb_file = get_dtb_file('dtoc_test_simple.dts') | ||||
|         output = tools.GetOutputFilename('output') | ||||
|  | ||||
|         # Take a copy before messing with it | ||||
|         scan = copy.deepcopy(saved_scan) | ||||
|         plat = dtb_platdata.DtbPlatdata(scan, dtb_file, False) | ||||
|         plat.scan_dtb() | ||||
|         plat.scan_tree() | ||||
|         plat.prepare_nodes() | ||||
|         return plat, scan | ||||
|  | ||||
|     def test_process_nodes(self): | ||||
|         """Test processing nodes to add various info""" | ||||
|         plat, scan = self.setup_process_test() | ||||
|         plat.process_nodes(True) | ||||
|  | ||||
|         i2c_node = plat._fdt.GetNode('/i2c@0') | ||||
|         pmic_node = plat._fdt.GetNode('/i2c@0/pmic@9') | ||||
|         pmic = scan._drivers['sandbox_pmic'] | ||||
|         i2c = scan._drivers['sandbox_i2c'] | ||||
|         self.assertEqual('DM_DEVICE_REF(pmic_at_9)', pmic_node.dev_ref) | ||||
|         self.assertEqual(pmic, pmic_node.driver) | ||||
|         self.assertEqual(i2c_node, pmic_node.parent) | ||||
|         self.assertEqual(i2c, pmic_node.parent_driver) | ||||
|  | ||||
|         # The pmic is the only child | ||||
|         self.assertEqual(pmic_node.parent_seq, 0) | ||||
|         self.assertEqual([pmic_node], i2c_node.child_devs) | ||||
|  | ||||
|         # Start and end of the list should be the child_head | ||||
|         ref = '&DM_DEVICE_REF(i2c_at_0)->child_head' | ||||
|         self.assertEqual( | ||||
|             {-1: ref, 0: '&DM_DEVICE_REF(pmic_at_9)->sibling_node', 1: ref}, | ||||
|             i2c_node.child_refs) | ||||
|  | ||||
|     def test_process_nodes_bad_parent(self): | ||||
|         # Pretend that i2c has a parent (the pmic) and delete that driver | ||||
|         plat, scan = self.setup_process_test() | ||||
|  | ||||
|         i2c_node = plat._fdt.GetNode('/i2c@0') | ||||
|         pmic_node = plat._fdt.GetNode('/i2c@0/pmic@9') | ||||
|         del scan._drivers['sandbox_pmic'] | ||||
|         i2c_node.parent = pmic_node | ||||
|  | ||||
|         # Process twice, the second time to generate an exception | ||||
|         plat.process_nodes(False) | ||||
|         with self.assertRaises(ValueError) as exc: | ||||
|             plat.process_nodes(True) | ||||
|         self.assertIn( | ||||
|             "Cannot parse/find parent driver 'sandbox_pmic' for 'sandbox_i2c", | ||||
|             str(exc.exception)) | ||||
|  | ||||
|     def test_process_nodes_bad_node(self): | ||||
|         plat, scan = self.setup_process_test() | ||||
|  | ||||
|         # Now remove the pmic driver | ||||
|         del scan._drivers['sandbox_pmic'] | ||||
|  | ||||
|         # Process twice, the second time to generate an exception | ||||
|         plat.process_nodes(False) | ||||
|         with self.assertRaises(ValueError) as exc: | ||||
|             plat.process_nodes(True) | ||||
|         self.assertIn("Cannot parse/find driver for 'sandbox_pmic", | ||||
|                       str(exc.exception)) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user