mirror of
https://xff.cz/git/u-boot/
synced 2025-09-04 02:02:08 +02: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