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._output_prop(node, node.props[pname]) | ||||||
|         self.buf('};\n') |         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): |     def output_node(self, node): | ||||||
|         """Output the C code for a 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: |     if not scan: | ||||||
|         scan = src_scan.Scanner(basedir, warning_disabled, drivers_additional) |         scan = src_scan.Scanner(basedir, warning_disabled, drivers_additional) | ||||||
|         scan.scan_drivers() |         scan.scan_drivers() | ||||||
|  |         do_process = True | ||||||
|  |     else: | ||||||
|  |         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() | ||||||
| @@ -739,6 +774,8 @@ def run_steps(args, dtb_file, include_disabled, output, output_dirs, | |||||||
|     plat.setup_output_dirs(output_dirs) |     plat.setup_output_dirs(output_dirs) | ||||||
|     plat.scan_structs() |     plat.scan_structs() | ||||||
|     plat.scan_phandles() |     plat.scan_phandles() | ||||||
|  |     if do_process: | ||||||
|  |         plat.process_nodes(False) | ||||||
|  |  | ||||||
|     cmds = args[0].split(',') |     cmds = args[0].split(',') | ||||||
|     if 'all' in cmds: |     if 'all' in cmds: | ||||||
|   | |||||||
| @@ -188,6 +188,17 @@ class Scanner: | |||||||
|         self._uclass = {} |         self._uclass = {} | ||||||
|         self._structs = {} |         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): |     def get_normalized_compat_name(self, node): | ||||||
|         """Get a node's normalized compat name |         """Get a node's normalized compat name | ||||||
|  |  | ||||||
|   | |||||||
| @@ -953,3 +953,79 @@ U_BOOT_DRVINFO(spl_test2) = { | |||||||
|         self.assertEqual( |         self.assertEqual( | ||||||
|             {'dt-structs-gen.h', 'source.dts', 'dt-plat.c', 'source.dtb'}, |             {'dt-structs-gen.h', 'source.dts', 'dt-plat.c', 'source.dtb'}, | ||||||
|             leafs) |             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