1*7581c01aSSimon Glass#!/usr/bin/python 2*7581c01aSSimon Glass# 3*7581c01aSSimon Glass# Copyright (C) 2017 Google, Inc 4*7581c01aSSimon Glass# Written by Simon Glass <sjg@chromium.org> 5*7581c01aSSimon Glass# 6*7581c01aSSimon Glass# SPDX-License-Identifier: GPL-2.0+ 7*7581c01aSSimon Glass# 8*7581c01aSSimon Glass 9*7581c01aSSimon Glassimport copy 10*7581c01aSSimon Glass 11*7581c01aSSimon Glassimport fdt 12*7581c01aSSimon Glassimport fdt_util 13*7581c01aSSimon Glass 14*7581c01aSSimon Glass# When we see these properties we ignore them - i.e. do not create a structure member 15*7581c01aSSimon GlassPROP_IGNORE_LIST = [ 16*7581c01aSSimon Glass '#address-cells', 17*7581c01aSSimon Glass '#gpio-cells', 18*7581c01aSSimon Glass '#size-cells', 19*7581c01aSSimon Glass 'compatible', 20*7581c01aSSimon Glass 'linux,phandle', 21*7581c01aSSimon Glass "status", 22*7581c01aSSimon Glass 'phandle', 23*7581c01aSSimon Glass 'u-boot,dm-pre-reloc', 24*7581c01aSSimon Glass 'u-boot,dm-tpl', 25*7581c01aSSimon Glass 'u-boot,dm-spl', 26*7581c01aSSimon Glass] 27*7581c01aSSimon Glass 28*7581c01aSSimon Glass# C type declarations for the tyues we support 29*7581c01aSSimon GlassTYPE_NAMES = { 30*7581c01aSSimon Glass fdt.TYPE_INT: 'fdt32_t', 31*7581c01aSSimon Glass fdt.TYPE_BYTE: 'unsigned char', 32*7581c01aSSimon Glass fdt.TYPE_STRING: 'const char *', 33*7581c01aSSimon Glass fdt.TYPE_BOOL: 'bool', 34*7581c01aSSimon Glass}; 35*7581c01aSSimon Glass 36*7581c01aSSimon GlassSTRUCT_PREFIX = 'dtd_' 37*7581c01aSSimon GlassVAL_PREFIX = 'dtv_' 38*7581c01aSSimon Glass 39*7581c01aSSimon Glassdef Conv_name_to_c(name): 40*7581c01aSSimon Glass """Convert a device-tree name to a C identifier 41*7581c01aSSimon Glass 42*7581c01aSSimon Glass Args: 43*7581c01aSSimon Glass name: Name to convert 44*7581c01aSSimon Glass Return: 45*7581c01aSSimon Glass String containing the C version of this name 46*7581c01aSSimon Glass """ 47*7581c01aSSimon Glass str = name.replace('@', '_at_') 48*7581c01aSSimon Glass str = str.replace('-', '_') 49*7581c01aSSimon Glass str = str.replace(',', '_') 50*7581c01aSSimon Glass str = str.replace('.', '_') 51*7581c01aSSimon Glass str = str.replace('/', '__') 52*7581c01aSSimon Glass return str 53*7581c01aSSimon Glass 54*7581c01aSSimon Glassdef TabTo(num_tabs, str): 55*7581c01aSSimon Glass if len(str) >= num_tabs * 8: 56*7581c01aSSimon Glass return str + ' ' 57*7581c01aSSimon Glass return str + '\t' * (num_tabs - len(str) // 8) 58*7581c01aSSimon Glass 59*7581c01aSSimon Glassclass DtbPlatdata: 60*7581c01aSSimon Glass """Provide a means to convert device tree binary data to platform data 61*7581c01aSSimon Glass 62*7581c01aSSimon Glass The output of this process is C structures which can be used in space- 63*7581c01aSSimon Glass constrained encvironments where the ~3KB code overhead of device tree 64*7581c01aSSimon Glass code is not affordable. 65*7581c01aSSimon Glass 66*7581c01aSSimon Glass Properties: 67*7581c01aSSimon Glass fdt: Fdt object, referencing the device tree 68*7581c01aSSimon Glass _dtb_fname: Filename of the input device tree binary file 69*7581c01aSSimon Glass _valid_nodes: A list of Node object with compatible strings 70*7581c01aSSimon Glass _options: Command-line options 71*7581c01aSSimon Glass _phandle_node: A dict of nodes indexed by phandle number (1, 2...) 72*7581c01aSSimon Glass _outfile: The current output file (sys.stdout or a real file) 73*7581c01aSSimon Glass _lines: Stashed list of output lines for outputting in the future 74*7581c01aSSimon Glass _phandle_node: A dict of Nodes indexed by phandle (an integer) 75*7581c01aSSimon Glass """ 76*7581c01aSSimon Glass def __init__(self, dtb_fname, options): 77*7581c01aSSimon Glass self._dtb_fname = dtb_fname 78*7581c01aSSimon Glass self._valid_nodes = None 79*7581c01aSSimon Glass self._options = options 80*7581c01aSSimon Glass self._phandle_node = {} 81*7581c01aSSimon Glass self._outfile = None 82*7581c01aSSimon Glass self._lines = [] 83*7581c01aSSimon Glass self._aliases = {} 84*7581c01aSSimon Glass 85*7581c01aSSimon Glass def SetupOutput(self, fname): 86*7581c01aSSimon Glass """Set up the output destination 87*7581c01aSSimon Glass 88*7581c01aSSimon Glass Once this is done, future calls to self.Out() will output to this 89*7581c01aSSimon Glass file. 90*7581c01aSSimon Glass 91*7581c01aSSimon Glass Args: 92*7581c01aSSimon Glass fname: Filename to send output to, or '-' for stdout 93*7581c01aSSimon Glass """ 94*7581c01aSSimon Glass if fname == '-': 95*7581c01aSSimon Glass self._outfile = sys.stdout 96*7581c01aSSimon Glass else: 97*7581c01aSSimon Glass self._outfile = open(fname, 'w') 98*7581c01aSSimon Glass 99*7581c01aSSimon Glass def Out(self, str): 100*7581c01aSSimon Glass """Output a string to the output file 101*7581c01aSSimon Glass 102*7581c01aSSimon Glass Args: 103*7581c01aSSimon Glass str: String to output 104*7581c01aSSimon Glass """ 105*7581c01aSSimon Glass self._outfile.write(str) 106*7581c01aSSimon Glass 107*7581c01aSSimon Glass def Buf(self, str): 108*7581c01aSSimon Glass """Buffer up a string to send later 109*7581c01aSSimon Glass 110*7581c01aSSimon Glass Args: 111*7581c01aSSimon Glass str: String to add to our 'buffer' list 112*7581c01aSSimon Glass """ 113*7581c01aSSimon Glass self._lines.append(str) 114*7581c01aSSimon Glass 115*7581c01aSSimon Glass def GetBuf(self): 116*7581c01aSSimon Glass """Get the contents of the output buffer, and clear it 117*7581c01aSSimon Glass 118*7581c01aSSimon Glass Returns: 119*7581c01aSSimon Glass The output buffer, which is then cleared for future use 120*7581c01aSSimon Glass """ 121*7581c01aSSimon Glass lines = self._lines 122*7581c01aSSimon Glass self._lines = [] 123*7581c01aSSimon Glass return lines 124*7581c01aSSimon Glass 125*7581c01aSSimon Glass def GetValue(self, type, value): 126*7581c01aSSimon Glass """Get a value as a C expression 127*7581c01aSSimon Glass 128*7581c01aSSimon Glass For integers this returns a byte-swapped (little-endian) hex string 129*7581c01aSSimon Glass For bytes this returns a hex string, e.g. 0x12 130*7581c01aSSimon Glass For strings this returns a literal string enclosed in quotes 131*7581c01aSSimon Glass For booleans this return 'true' 132*7581c01aSSimon Glass 133*7581c01aSSimon Glass Args: 134*7581c01aSSimon Glass type: Data type (fdt_util) 135*7581c01aSSimon Glass value: Data value, as a string of bytes 136*7581c01aSSimon Glass """ 137*7581c01aSSimon Glass if type == fdt.TYPE_INT: 138*7581c01aSSimon Glass return '%#x' % fdt_util.fdt32_to_cpu(value) 139*7581c01aSSimon Glass elif type == fdt.TYPE_BYTE: 140*7581c01aSSimon Glass return '%#x' % ord(value[0]) 141*7581c01aSSimon Glass elif type == fdt.TYPE_STRING: 142*7581c01aSSimon Glass return '"%s"' % value 143*7581c01aSSimon Glass elif type == fdt.TYPE_BOOL: 144*7581c01aSSimon Glass return 'true' 145*7581c01aSSimon Glass 146*7581c01aSSimon Glass def GetCompatName(self, node): 147*7581c01aSSimon Glass """Get a node's first compatible string as a C identifier 148*7581c01aSSimon Glass 149*7581c01aSSimon Glass Args: 150*7581c01aSSimon Glass node: Node object to check 151*7581c01aSSimon Glass Return: 152*7581c01aSSimon Glass C identifier for the first compatible string 153*7581c01aSSimon Glass """ 154*7581c01aSSimon Glass compat = node.props['compatible'].value 155*7581c01aSSimon Glass aliases = [] 156*7581c01aSSimon Glass if type(compat) == list: 157*7581c01aSSimon Glass compat, aliases = compat[0], compat[1:] 158*7581c01aSSimon Glass return Conv_name_to_c(compat), [Conv_name_to_c(a) for a in aliases] 159*7581c01aSSimon Glass 160*7581c01aSSimon Glass def ScanDtb(self): 161*7581c01aSSimon Glass """Scan the device tree to obtain a tree of notes and properties 162*7581c01aSSimon Glass 163*7581c01aSSimon Glass Once this is done, self.fdt.GetRoot() can be called to obtain the 164*7581c01aSSimon Glass device tree root node, and progress from there. 165*7581c01aSSimon Glass """ 166*7581c01aSSimon Glass self.fdt = fdt.FdtScan(self._dtb_fname) 167*7581c01aSSimon Glass 168*7581c01aSSimon Glass def ScanNode(self, root): 169*7581c01aSSimon Glass for node in root.subnodes: 170*7581c01aSSimon Glass if 'compatible' in node.props: 171*7581c01aSSimon Glass status = node.props.get('status') 172*7581c01aSSimon Glass if (not self._options.include_disabled and not status or 173*7581c01aSSimon Glass status.value != 'disabled'): 174*7581c01aSSimon Glass self._valid_nodes.append(node) 175*7581c01aSSimon Glass phandle_prop = node.props.get('phandle') 176*7581c01aSSimon Glass if phandle_prop: 177*7581c01aSSimon Glass phandle = phandle_prop.GetPhandle() 178*7581c01aSSimon Glass self._phandle_node[phandle] = node 179*7581c01aSSimon Glass 180*7581c01aSSimon Glass # recurse to handle any subnodes 181*7581c01aSSimon Glass self.ScanNode(node); 182*7581c01aSSimon Glass 183*7581c01aSSimon Glass def ScanTree(self): 184*7581c01aSSimon Glass """Scan the device tree for useful information 185*7581c01aSSimon Glass 186*7581c01aSSimon Glass This fills in the following properties: 187*7581c01aSSimon Glass _phandle_node: A dict of Nodes indexed by phandle (an integer) 188*7581c01aSSimon Glass _valid_nodes: A list of nodes we wish to consider include in the 189*7581c01aSSimon Glass platform data 190*7581c01aSSimon Glass """ 191*7581c01aSSimon Glass self._phandle_node = {} 192*7581c01aSSimon Glass self._valid_nodes = [] 193*7581c01aSSimon Glass return self.ScanNode(self.fdt.GetRoot()); 194*7581c01aSSimon Glass 195*7581c01aSSimon Glass for node in self.fdt.GetRoot().subnodes: 196*7581c01aSSimon Glass if 'compatible' in node.props: 197*7581c01aSSimon Glass status = node.props.get('status') 198*7581c01aSSimon Glass if (not self._options.include_disabled and not status or 199*7581c01aSSimon Glass status.value != 'disabled'): 200*7581c01aSSimon Glass node_list.append(node) 201*7581c01aSSimon Glass phandle_prop = node.props.get('phandle') 202*7581c01aSSimon Glass if phandle_prop: 203*7581c01aSSimon Glass phandle = phandle_prop.GetPhandle() 204*7581c01aSSimon Glass self._phandle_node[phandle] = node 205*7581c01aSSimon Glass 206*7581c01aSSimon Glass self._valid_nodes = node_list 207*7581c01aSSimon Glass 208*7581c01aSSimon Glass def IsPhandle(self, prop): 209*7581c01aSSimon Glass """Check if a node contains phandles 210*7581c01aSSimon Glass 211*7581c01aSSimon Glass We have no reliable way of detecting whether a node uses a phandle 212*7581c01aSSimon Glass or not. As an interim measure, use a list of known property names. 213*7581c01aSSimon Glass 214*7581c01aSSimon Glass Args: 215*7581c01aSSimon Glass prop: Prop object to check 216*7581c01aSSimon Glass Return: 217*7581c01aSSimon Glass True if the object value contains phandles, else False 218*7581c01aSSimon Glass """ 219*7581c01aSSimon Glass if prop.name in ['clocks']: 220*7581c01aSSimon Glass return True 221*7581c01aSSimon Glass return False 222*7581c01aSSimon Glass 223*7581c01aSSimon Glass def ScanStructs(self): 224*7581c01aSSimon Glass """Scan the device tree building up the C structures we will use. 225*7581c01aSSimon Glass 226*7581c01aSSimon Glass Build a dict keyed by C struct name containing a dict of Prop 227*7581c01aSSimon Glass object for each struct field (keyed by property name). Where the 228*7581c01aSSimon Glass same struct appears multiple times, try to use the 'widest' 229*7581c01aSSimon Glass property, i.e. the one with a type which can express all others. 230*7581c01aSSimon Glass 231*7581c01aSSimon Glass Once the widest property is determined, all other properties are 232*7581c01aSSimon Glass updated to match that width. 233*7581c01aSSimon Glass """ 234*7581c01aSSimon Glass structs = {} 235*7581c01aSSimon Glass for node in self._valid_nodes: 236*7581c01aSSimon Glass node_name, _ = self.GetCompatName(node) 237*7581c01aSSimon Glass fields = {} 238*7581c01aSSimon Glass 239*7581c01aSSimon Glass # Get a list of all the valid properties in this node. 240*7581c01aSSimon Glass for name, prop in node.props.items(): 241*7581c01aSSimon Glass if name not in PROP_IGNORE_LIST and name[0] != '#': 242*7581c01aSSimon Glass fields[name] = copy.deepcopy(prop) 243*7581c01aSSimon Glass 244*7581c01aSSimon Glass # If we've seen this node_name before, update the existing struct. 245*7581c01aSSimon Glass if node_name in structs: 246*7581c01aSSimon Glass struct = structs[node_name] 247*7581c01aSSimon Glass for name, prop in fields.items(): 248*7581c01aSSimon Glass oldprop = struct.get(name) 249*7581c01aSSimon Glass if oldprop: 250*7581c01aSSimon Glass oldprop.Widen(prop) 251*7581c01aSSimon Glass else: 252*7581c01aSSimon Glass struct[name] = prop 253*7581c01aSSimon Glass 254*7581c01aSSimon Glass # Otherwise store this as a new struct. 255*7581c01aSSimon Glass else: 256*7581c01aSSimon Glass structs[node_name] = fields 257*7581c01aSSimon Glass 258*7581c01aSSimon Glass upto = 0 259*7581c01aSSimon Glass for node in self._valid_nodes: 260*7581c01aSSimon Glass node_name, _ = self.GetCompatName(node) 261*7581c01aSSimon Glass struct = structs[node_name] 262*7581c01aSSimon Glass for name, prop in node.props.items(): 263*7581c01aSSimon Glass if name not in PROP_IGNORE_LIST and name[0] != '#': 264*7581c01aSSimon Glass prop.Widen(struct[name]) 265*7581c01aSSimon Glass upto += 1 266*7581c01aSSimon Glass 267*7581c01aSSimon Glass struct_name, aliases = self.GetCompatName(node) 268*7581c01aSSimon Glass for alias in aliases: 269*7581c01aSSimon Glass self._aliases[alias] = struct_name 270*7581c01aSSimon Glass 271*7581c01aSSimon Glass return structs 272*7581c01aSSimon Glass 273*7581c01aSSimon Glass def ScanPhandles(self): 274*7581c01aSSimon Glass """Figure out what phandles each node uses 275*7581c01aSSimon Glass 276*7581c01aSSimon Glass We need to be careful when outputing nodes that use phandles since 277*7581c01aSSimon Glass they must come after the declaration of the phandles in the C file. 278*7581c01aSSimon Glass Otherwise we get a compiler error since the phandle struct is not yet 279*7581c01aSSimon Glass declared. 280*7581c01aSSimon Glass 281*7581c01aSSimon Glass This function adds to each node a list of phandle nodes that the node 282*7581c01aSSimon Glass depends on. This allows us to output things in the right order. 283*7581c01aSSimon Glass """ 284*7581c01aSSimon Glass for node in self._valid_nodes: 285*7581c01aSSimon Glass node.phandles = set() 286*7581c01aSSimon Glass for pname, prop in node.props.items(): 287*7581c01aSSimon Glass if pname in PROP_IGNORE_LIST or pname[0] == '#': 288*7581c01aSSimon Glass continue 289*7581c01aSSimon Glass if type(prop.value) == list: 290*7581c01aSSimon Glass if self.IsPhandle(prop): 291*7581c01aSSimon Glass # Process the list as pairs of (phandle, id) 292*7581c01aSSimon Glass it = iter(prop.value) 293*7581c01aSSimon Glass for phandle_cell, id_cell in zip(it, it): 294*7581c01aSSimon Glass phandle = fdt_util.fdt32_to_cpu(phandle_cell) 295*7581c01aSSimon Glass id = fdt_util.fdt32_to_cpu(id_cell) 296*7581c01aSSimon Glass target_node = self._phandle_node[phandle] 297*7581c01aSSimon Glass node.phandles.add(target_node) 298*7581c01aSSimon Glass 299*7581c01aSSimon Glass 300*7581c01aSSimon Glass def GenerateStructs(self, structs): 301*7581c01aSSimon Glass """Generate struct defintions for the platform data 302*7581c01aSSimon Glass 303*7581c01aSSimon Glass This writes out the body of a header file consisting of structure 304*7581c01aSSimon Glass definitions for node in self._valid_nodes. See the documentation in 305*7581c01aSSimon Glass README.of-plat for more information. 306*7581c01aSSimon Glass """ 307*7581c01aSSimon Glass self.Out('#include <stdbool.h>\n') 308*7581c01aSSimon Glass self.Out('#include <libfdt.h>\n') 309*7581c01aSSimon Glass 310*7581c01aSSimon Glass # Output the struct definition 311*7581c01aSSimon Glass for name in sorted(structs): 312*7581c01aSSimon Glass self.Out('struct %s%s {\n' % (STRUCT_PREFIX, name)); 313*7581c01aSSimon Glass for pname in sorted(structs[name]): 314*7581c01aSSimon Glass prop = structs[name][pname] 315*7581c01aSSimon Glass if self.IsPhandle(prop): 316*7581c01aSSimon Glass # For phandles, include a reference to the target 317*7581c01aSSimon Glass self.Out('\t%s%s[%d]' % (TabTo(2, 'struct phandle_2_cell'), 318*7581c01aSSimon Glass Conv_name_to_c(prop.name), 319*7581c01aSSimon Glass len(prop.value) / 2)) 320*7581c01aSSimon Glass else: 321*7581c01aSSimon Glass ptype = TYPE_NAMES[prop.type] 322*7581c01aSSimon Glass self.Out('\t%s%s' % (TabTo(2, ptype), 323*7581c01aSSimon Glass Conv_name_to_c(prop.name))) 324*7581c01aSSimon Glass if type(prop.value) == list: 325*7581c01aSSimon Glass self.Out('[%d]' % len(prop.value)) 326*7581c01aSSimon Glass self.Out(';\n') 327*7581c01aSSimon Glass self.Out('};\n') 328*7581c01aSSimon Glass 329*7581c01aSSimon Glass for alias, struct_name in self._aliases.iteritems(): 330*7581c01aSSimon Glass self.Out('#define %s%s %s%s\n'% (STRUCT_PREFIX, alias, 331*7581c01aSSimon Glass STRUCT_PREFIX, struct_name)) 332*7581c01aSSimon Glass 333*7581c01aSSimon Glass def OutputNode(self, node): 334*7581c01aSSimon Glass """Output the C code for a node 335*7581c01aSSimon Glass 336*7581c01aSSimon Glass Args: 337*7581c01aSSimon Glass node: node to output 338*7581c01aSSimon Glass """ 339*7581c01aSSimon Glass struct_name, _ = self.GetCompatName(node) 340*7581c01aSSimon Glass var_name = Conv_name_to_c(node.name) 341*7581c01aSSimon Glass self.Buf('static struct %s%s %s%s = {\n' % 342*7581c01aSSimon Glass (STRUCT_PREFIX, struct_name, VAL_PREFIX, var_name)) 343*7581c01aSSimon Glass for pname, prop in node.props.items(): 344*7581c01aSSimon Glass if pname in PROP_IGNORE_LIST or pname[0] == '#': 345*7581c01aSSimon Glass continue 346*7581c01aSSimon Glass ptype = TYPE_NAMES[prop.type] 347*7581c01aSSimon Glass member_name = Conv_name_to_c(prop.name) 348*7581c01aSSimon Glass self.Buf('\t%s= ' % TabTo(3, '.' + member_name)) 349*7581c01aSSimon Glass 350*7581c01aSSimon Glass # Special handling for lists 351*7581c01aSSimon Glass if type(prop.value) == list: 352*7581c01aSSimon Glass self.Buf('{') 353*7581c01aSSimon Glass vals = [] 354*7581c01aSSimon Glass # For phandles, output a reference to the platform data 355*7581c01aSSimon Glass # of the target node. 356*7581c01aSSimon Glass if self.IsPhandle(prop): 357*7581c01aSSimon Glass # Process the list as pairs of (phandle, id) 358*7581c01aSSimon Glass it = iter(prop.value) 359*7581c01aSSimon Glass for phandle_cell, id_cell in zip(it, it): 360*7581c01aSSimon Glass phandle = fdt_util.fdt32_to_cpu(phandle_cell) 361*7581c01aSSimon Glass id = fdt_util.fdt32_to_cpu(id_cell) 362*7581c01aSSimon Glass target_node = self._phandle_node[phandle] 363*7581c01aSSimon Glass name = Conv_name_to_c(target_node.name) 364*7581c01aSSimon Glass vals.append('{&%s%s, %d}' % (VAL_PREFIX, name, id)) 365*7581c01aSSimon Glass else: 366*7581c01aSSimon Glass for val in prop.value: 367*7581c01aSSimon Glass vals.append(self.GetValue(prop.type, val)) 368*7581c01aSSimon Glass self.Buf(', '.join(vals)) 369*7581c01aSSimon Glass self.Buf('}') 370*7581c01aSSimon Glass else: 371*7581c01aSSimon Glass self.Buf(self.GetValue(prop.type, prop.value)) 372*7581c01aSSimon Glass self.Buf(',\n') 373*7581c01aSSimon Glass self.Buf('};\n') 374*7581c01aSSimon Glass 375*7581c01aSSimon Glass # Add a device declaration 376*7581c01aSSimon Glass self.Buf('U_BOOT_DEVICE(%s) = {\n' % var_name) 377*7581c01aSSimon Glass self.Buf('\t.name\t\t= "%s",\n' % struct_name) 378*7581c01aSSimon Glass self.Buf('\t.platdata\t= &%s%s,\n' % (VAL_PREFIX, var_name)) 379*7581c01aSSimon Glass self.Buf('\t.platdata_size\t= sizeof(%s%s),\n' % 380*7581c01aSSimon Glass (VAL_PREFIX, var_name)) 381*7581c01aSSimon Glass self.Buf('};\n') 382*7581c01aSSimon Glass self.Buf('\n') 383*7581c01aSSimon Glass 384*7581c01aSSimon Glass self.Out(''.join(self.GetBuf())) 385*7581c01aSSimon Glass 386*7581c01aSSimon Glass def GenerateTables(self): 387*7581c01aSSimon Glass """Generate device defintions for the platform data 388*7581c01aSSimon Glass 389*7581c01aSSimon Glass This writes out C platform data initialisation data and 390*7581c01aSSimon Glass U_BOOT_DEVICE() declarations for each valid node. Where a node has 391*7581c01aSSimon Glass multiple compatible strings, a #define is used to make them equivalent. 392*7581c01aSSimon Glass 393*7581c01aSSimon Glass See the documentation in doc/driver-model/of-plat.txt for more 394*7581c01aSSimon Glass information. 395*7581c01aSSimon Glass """ 396*7581c01aSSimon Glass self.Out('#include <common.h>\n') 397*7581c01aSSimon Glass self.Out('#include <dm.h>\n') 398*7581c01aSSimon Glass self.Out('#include <dt-structs.h>\n') 399*7581c01aSSimon Glass self.Out('\n') 400*7581c01aSSimon Glass nodes_to_output = list(self._valid_nodes) 401*7581c01aSSimon Glass 402*7581c01aSSimon Glass # Keep outputing nodes until there is none left 403*7581c01aSSimon Glass while nodes_to_output: 404*7581c01aSSimon Glass node = nodes_to_output[0] 405*7581c01aSSimon Glass # Output all the node's dependencies first 406*7581c01aSSimon Glass for req_node in node.phandles: 407*7581c01aSSimon Glass if req_node in nodes_to_output: 408*7581c01aSSimon Glass self.OutputNode(req_node) 409*7581c01aSSimon Glass nodes_to_output.remove(req_node) 410*7581c01aSSimon Glass self.OutputNode(node) 411*7581c01aSSimon Glass nodes_to_output.remove(node) 412