dtoc: Handle nodes with phandles that depend on the same

At present dtoc assumes that nodes which are phandles do not themselves
reference other phandle nodes. Unfortunately this is not necessarilly
true. As a result we can currently output C code which does not compile
because a node declaration can be referenced before it is declared.

Adjust the code to explicitly output all phandle nodes needed by node
before the node itself is output.

This fixes building with the latest rk3399-firefly.dts from Linux, which
has reordered the nodes.

Signed-off-by: Simon Glass <sjg@chromium.org>
Tested-by: Kever Yang <kever.yang@rock-chips.com>
master
Simon Glass 7 years ago
parent 49eec8c7f1
commit 439c947f32
  1. 55
      tools/dtoc/dtoc.py

@ -272,6 +272,33 @@ class DtbPlatdata:
upto += 1
return structs
def ScanPhandles(self):
"""Figure out what phandles each node uses
We need to be careful when outputing nodes that use phandles since
they must come after the declaration of the phandles in the C file.
Otherwise we get a compiler error since the phandle struct is not yet
declared.
This function adds to each node a list of phandle nodes that the node
depends on. This allows us to output things in the right order.
"""
for node in self._valid_nodes:
node.phandles = set()
for pname, prop in node.props.items():
if pname in PROP_IGNORE_LIST or pname[0] == '#':
continue
if type(prop.value) == list:
if self.IsPhandle(prop):
# Process the list as pairs of (phandle, id)
it = iter(prop.value)
for phandle_cell, id_cell in zip(it, it):
phandle = fdt_util.fdt32_to_cpu(phandle_cell)
id = fdt_util.fdt32_to_cpu(id_cell)
target_node = self._phandle_node[phandle]
node.phandles.add(target_node)
def GenerateStructs(self, structs):
"""Generate struct defintions for the platform data
@ -352,6 +379,8 @@ class DtbPlatdata:
self.Buf('};\n')
self.Buf('\n')
self.Out(''.join(self.GetBuf()))
def GenerateTables(self):
"""Generate device defintions for the platform data
@ -363,21 +392,18 @@ class DtbPlatdata:
self.Out('#include <dm.h>\n')
self.Out('#include <dt-structs.h>\n')
self.Out('\n')
node_txt_list = []
for node in self._valid_nodes:
nodes_to_output = list(self._valid_nodes)
# Keep outputing nodes until there is none left
while nodes_to_output:
node = nodes_to_output[0]
# Output all the node's dependencies first
for req_node in node.phandles:
if req_node in nodes_to_output:
self.OutputNode(req_node)
nodes_to_output.remove(req_node)
self.OutputNode(node)
# Output phandle target nodes first, since they may be referenced
# by others
if 'phandle' in node.props:
self.Out(''.join(self.GetBuf()))
else:
node_txt_list.append(self.GetBuf())
# Output all the nodes which are not phandle targets themselves, but
# may reference them. This avoids the need for forward declarations.
for node_txt in node_txt_list:
self.Out(''.join(node_txt))
nodes_to_output.remove(node)
if __name__ != "__main__":
@ -400,6 +426,7 @@ plat.ScanDtb()
plat.ScanTree()
plat.SetupOutput(options.output)
structs = plat.ScanStructs()
plat.ScanPhandles()
for cmd in args[0].split(','):
if cmd == 'struct':

Loading…
Cancel
Save