17581c01aSSimon Glass#!/usr/bin/python 27581c01aSSimon Glass# 37581c01aSSimon Glass# Copyright (C) 2017 Google, Inc 47581c01aSSimon Glass# Written by Simon Glass <sjg@chromium.org> 57581c01aSSimon Glass# 67581c01aSSimon Glass# SPDX-License-Identifier: GPL-2.0+ 77581c01aSSimon Glass# 87581c01aSSimon Glass 92be282caSSimon Glass"""Device tree to platform data class 102be282caSSimon Glass 112be282caSSimon GlassThis supports converting device tree data to C structures definitions and 122be282caSSimon Glassstatic data. 132be282caSSimon Glass""" 142be282caSSimon Glass 157581c01aSSimon Glassimport copy 162be282caSSimon Glassimport sys 177581c01aSSimon Glass 187581c01aSSimon Glassimport fdt 197581c01aSSimon Glassimport fdt_util 207581c01aSSimon Glass 217581c01aSSimon Glass# When we see these properties we ignore them - i.e. do not create a structure member 227581c01aSSimon GlassPROP_IGNORE_LIST = [ 237581c01aSSimon Glass '#address-cells', 247581c01aSSimon Glass '#gpio-cells', 257581c01aSSimon Glass '#size-cells', 267581c01aSSimon Glass 'compatible', 277581c01aSSimon Glass 'linux,phandle', 287581c01aSSimon Glass "status", 297581c01aSSimon Glass 'phandle', 307581c01aSSimon Glass 'u-boot,dm-pre-reloc', 317581c01aSSimon Glass 'u-boot,dm-tpl', 327581c01aSSimon Glass 'u-boot,dm-spl', 337581c01aSSimon Glass] 347581c01aSSimon Glass 357581c01aSSimon Glass# C type declarations for the tyues we support 367581c01aSSimon GlassTYPE_NAMES = { 377581c01aSSimon Glass fdt.TYPE_INT: 'fdt32_t', 387581c01aSSimon Glass fdt.TYPE_BYTE: 'unsigned char', 397581c01aSSimon Glass fdt.TYPE_STRING: 'const char *', 407581c01aSSimon Glass fdt.TYPE_BOOL: 'bool', 412be282caSSimon Glass} 427581c01aSSimon Glass 437581c01aSSimon GlassSTRUCT_PREFIX = 'dtd_' 447581c01aSSimon GlassVAL_PREFIX = 'dtv_' 457581c01aSSimon Glass 462be282caSSimon Glassdef conv_name_to_c(name): 477581c01aSSimon Glass """Convert a device-tree name to a C identifier 487581c01aSSimon Glass 4930107b08SSimon Glass This uses multiple replace() calls instead of re.sub() since it is faster 5030107b08SSimon Glass (400ms for 1m calls versus 1000ms for the 're' version). 5130107b08SSimon Glass 527581c01aSSimon Glass Args: 537581c01aSSimon Glass name: Name to convert 547581c01aSSimon Glass Return: 557581c01aSSimon Glass String containing the C version of this name 567581c01aSSimon Glass """ 572be282caSSimon Glass new = name.replace('@', '_at_') 582be282caSSimon Glass new = new.replace('-', '_') 592be282caSSimon Glass new = new.replace(',', '_') 602be282caSSimon Glass new = new.replace('.', '_') 612be282caSSimon Glass return new 627581c01aSSimon Glass 632be282caSSimon Glassdef tab_to(num_tabs, line): 642be282caSSimon Glass """Append tabs to a line of text to reach a tab stop. 657581c01aSSimon Glass 662be282caSSimon Glass Args: 672be282caSSimon Glass num_tabs: Tab stop to obtain (0 = column 0, 1 = column 8, etc.) 682be282caSSimon Glass line: Line of text to append to 692be282caSSimon Glass 702be282caSSimon Glass Returns: 712be282caSSimon Glass line with the correct number of tabs appeneded. If the line already 722be282caSSimon Glass extends past that tab stop then a single space is appended. 732be282caSSimon Glass """ 742be282caSSimon Glass if len(line) >= num_tabs * 8: 752be282caSSimon Glass return line + ' ' 762be282caSSimon Glass return line + '\t' * (num_tabs - len(line) // 8) 772be282caSSimon Glass 7856e0bbe0SSimon Glassdef get_value(ftype, value): 7956e0bbe0SSimon Glass """Get a value as a C expression 8056e0bbe0SSimon Glass 8156e0bbe0SSimon Glass For integers this returns a byte-swapped (little-endian) hex string 8256e0bbe0SSimon Glass For bytes this returns a hex string, e.g. 0x12 8356e0bbe0SSimon Glass For strings this returns a literal string enclosed in quotes 8456e0bbe0SSimon Glass For booleans this return 'true' 8556e0bbe0SSimon Glass 8656e0bbe0SSimon Glass Args: 8756e0bbe0SSimon Glass type: Data type (fdt_util) 8856e0bbe0SSimon Glass value: Data value, as a string of bytes 8956e0bbe0SSimon Glass """ 9056e0bbe0SSimon Glass if ftype == fdt.TYPE_INT: 9156e0bbe0SSimon Glass return '%#x' % fdt_util.fdt32_to_cpu(value) 9256e0bbe0SSimon Glass elif ftype == fdt.TYPE_BYTE: 9356e0bbe0SSimon Glass return '%#x' % ord(value[0]) 9456e0bbe0SSimon Glass elif ftype == fdt.TYPE_STRING: 9556e0bbe0SSimon Glass return '"%s"' % value 9656e0bbe0SSimon Glass elif ftype == fdt.TYPE_BOOL: 9756e0bbe0SSimon Glass return 'true' 9856e0bbe0SSimon Glass 9956e0bbe0SSimon Glassdef get_compat_name(node): 10056e0bbe0SSimon Glass """Get a node's first compatible string as a C identifier 10156e0bbe0SSimon Glass 10256e0bbe0SSimon Glass Args: 10356e0bbe0SSimon Glass node: Node object to check 10456e0bbe0SSimon Glass Return: 10556e0bbe0SSimon Glass Tuple: 10656e0bbe0SSimon Glass C identifier for the first compatible string 10756e0bbe0SSimon Glass List of C identifiers for all the other compatible strings 10856e0bbe0SSimon Glass (possibly empty) 10956e0bbe0SSimon Glass """ 11056e0bbe0SSimon Glass compat = node.props['compatible'].value 11156e0bbe0SSimon Glass aliases = [] 11256e0bbe0SSimon Glass if isinstance(compat, list): 11356e0bbe0SSimon Glass compat, aliases = compat[0], compat[1:] 11456e0bbe0SSimon Glass return conv_name_to_c(compat), [conv_name_to_c(a) for a in aliases] 11556e0bbe0SSimon Glass 11656e0bbe0SSimon Glassdef is_phandle(prop): 11756e0bbe0SSimon Glass """Check if a node contains phandles 11856e0bbe0SSimon Glass 11956e0bbe0SSimon Glass We have no reliable way of detecting whether a node uses a phandle 12056e0bbe0SSimon Glass or not. As an interim measure, use a list of known property names. 12156e0bbe0SSimon Glass 12256e0bbe0SSimon Glass Args: 12356e0bbe0SSimon Glass prop: Prop object to check 12456e0bbe0SSimon Glass Return: 12556e0bbe0SSimon Glass True if the object value contains phandles, else False 12656e0bbe0SSimon Glass """ 12756e0bbe0SSimon Glass if prop.name in ['clocks']: 12856e0bbe0SSimon Glass return True 12956e0bbe0SSimon Glass return False 13056e0bbe0SSimon Glass 13156e0bbe0SSimon Glass 1322be282caSSimon Glassclass DtbPlatdata(object): 1337581c01aSSimon Glass """Provide a means to convert device tree binary data to platform data 1347581c01aSSimon Glass 1357581c01aSSimon Glass The output of this process is C structures which can be used in space- 1367581c01aSSimon Glass constrained encvironments where the ~3KB code overhead of device tree 1377581c01aSSimon Glass code is not affordable. 1387581c01aSSimon Glass 1397581c01aSSimon Glass Properties: 1402be282caSSimon Glass _fdt: Fdt object, referencing the device tree 1417581c01aSSimon Glass _dtb_fname: Filename of the input device tree binary file 1427581c01aSSimon Glass _valid_nodes: A list of Node object with compatible strings 143e36024b0SSimon Glass _include_disabled: true to include nodes marked status = "disabled" 1442be282caSSimon Glass _phandle_nodes: A dict of nodes indexed by phandle number (1, 2...) 1457581c01aSSimon Glass _outfile: The current output file (sys.stdout or a real file) 1467581c01aSSimon Glass _lines: Stashed list of output lines for outputting in the future 1472be282caSSimon Glass _phandle_nodes: A dict of Nodes indexed by phandle (an integer) 1487581c01aSSimon Glass """ 149e36024b0SSimon Glass def __init__(self, dtb_fname, include_disabled): 1502be282caSSimon Glass self._fdt = None 1517581c01aSSimon Glass self._dtb_fname = dtb_fname 1527581c01aSSimon Glass self._valid_nodes = None 153e36024b0SSimon Glass self._include_disabled = include_disabled 1542be282caSSimon Glass self._phandle_nodes = {} 1557581c01aSSimon Glass self._outfile = None 1567581c01aSSimon Glass self._lines = [] 1577581c01aSSimon Glass self._aliases = {} 1587581c01aSSimon Glass 1592be282caSSimon Glass def setup_output(self, fname): 1607581c01aSSimon Glass """Set up the output destination 1617581c01aSSimon Glass 1622be282caSSimon Glass Once this is done, future calls to self.out() will output to this 1637581c01aSSimon Glass file. 1647581c01aSSimon Glass 1657581c01aSSimon Glass Args: 1667581c01aSSimon Glass fname: Filename to send output to, or '-' for stdout 1677581c01aSSimon Glass """ 1687581c01aSSimon Glass if fname == '-': 1697581c01aSSimon Glass self._outfile = sys.stdout 1707581c01aSSimon Glass else: 1717581c01aSSimon Glass self._outfile = open(fname, 'w') 1727581c01aSSimon Glass 1732be282caSSimon Glass def out(self, line): 1747581c01aSSimon Glass """Output a string to the output file 1757581c01aSSimon Glass 1767581c01aSSimon Glass Args: 1772be282caSSimon Glass line: String to output 1787581c01aSSimon Glass """ 1792be282caSSimon Glass self._outfile.write(line) 1807581c01aSSimon Glass 1812be282caSSimon Glass def buf(self, line): 1827581c01aSSimon Glass """Buffer up a string to send later 1837581c01aSSimon Glass 1847581c01aSSimon Glass Args: 1852be282caSSimon Glass line: String to add to our 'buffer' list 1867581c01aSSimon Glass """ 1872be282caSSimon Glass self._lines.append(line) 1887581c01aSSimon Glass 1892be282caSSimon Glass def get_buf(self): 1907581c01aSSimon Glass """Get the contents of the output buffer, and clear it 1917581c01aSSimon Glass 1927581c01aSSimon Glass Returns: 1937581c01aSSimon Glass The output buffer, which is then cleared for future use 1947581c01aSSimon Glass """ 1957581c01aSSimon Glass lines = self._lines 1967581c01aSSimon Glass self._lines = [] 1977581c01aSSimon Glass return lines 1987581c01aSSimon Glass 1992be282caSSimon Glass def scan_dtb(self): 200*f1a7ba1dSAnatolij Gustschin """Scan the device tree to obtain a tree of nodes and properties 2017581c01aSSimon Glass 2022be282caSSimon Glass Once this is done, self._fdt.GetRoot() can be called to obtain the 2037581c01aSSimon Glass device tree root node, and progress from there. 2047581c01aSSimon Glass """ 2052be282caSSimon Glass self._fdt = fdt.FdtScan(self._dtb_fname) 2067581c01aSSimon Glass 2072be282caSSimon Glass def scan_node(self, root): 2082be282caSSimon Glass """Scan a node and subnodes to build a tree of node and phandle info 2092be282caSSimon Glass 2102be282caSSimon Glass This adds each node to self._valid_nodes and each phandle to 2112be282caSSimon Glass self._phandle_nodes. 2122be282caSSimon Glass 2132be282caSSimon Glass Args: 2142be282caSSimon Glass root: Root node for scan 2152be282caSSimon Glass """ 2167581c01aSSimon Glass for node in root.subnodes: 2177581c01aSSimon Glass if 'compatible' in node.props: 2187581c01aSSimon Glass status = node.props.get('status') 219e36024b0SSimon Glass if (not self._include_disabled and not status or 2207581c01aSSimon Glass status.value != 'disabled'): 2217581c01aSSimon Glass self._valid_nodes.append(node) 2227581c01aSSimon Glass phandle_prop = node.props.get('phandle') 2237581c01aSSimon Glass if phandle_prop: 2247581c01aSSimon Glass phandle = phandle_prop.GetPhandle() 2252be282caSSimon Glass self._phandle_nodes[phandle] = node 2267581c01aSSimon Glass 2277581c01aSSimon Glass # recurse to handle any subnodes 2282be282caSSimon Glass self.scan_node(node) 2297581c01aSSimon Glass 2302be282caSSimon Glass def scan_tree(self): 2317581c01aSSimon Glass """Scan the device tree for useful information 2327581c01aSSimon Glass 2337581c01aSSimon Glass This fills in the following properties: 2342be282caSSimon Glass _phandle_nodes: A dict of Nodes indexed by phandle (an integer) 2357581c01aSSimon Glass _valid_nodes: A list of nodes we wish to consider include in the 2367581c01aSSimon Glass platform data 2377581c01aSSimon Glass """ 2382be282caSSimon Glass self._phandle_nodes = {} 2397581c01aSSimon Glass self._valid_nodes = [] 2402be282caSSimon Glass return self.scan_node(self._fdt.GetRoot()) 2417581c01aSSimon Glass 2422be282caSSimon Glass def scan_structs(self): 2437581c01aSSimon Glass """Scan the device tree building up the C structures we will use. 2447581c01aSSimon Glass 2457581c01aSSimon Glass Build a dict keyed by C struct name containing a dict of Prop 2467581c01aSSimon Glass object for each struct field (keyed by property name). Where the 2477581c01aSSimon Glass same struct appears multiple times, try to use the 'widest' 2487581c01aSSimon Glass property, i.e. the one with a type which can express all others. 2497581c01aSSimon Glass 2507581c01aSSimon Glass Once the widest property is determined, all other properties are 2517581c01aSSimon Glass updated to match that width. 2527581c01aSSimon Glass """ 2537581c01aSSimon Glass structs = {} 2547581c01aSSimon Glass for node in self._valid_nodes: 25556e0bbe0SSimon Glass node_name, _ = get_compat_name(node) 2567581c01aSSimon Glass fields = {} 2577581c01aSSimon Glass 2587581c01aSSimon Glass # Get a list of all the valid properties in this node. 2597581c01aSSimon Glass for name, prop in node.props.items(): 2607581c01aSSimon Glass if name not in PROP_IGNORE_LIST and name[0] != '#': 2617581c01aSSimon Glass fields[name] = copy.deepcopy(prop) 2627581c01aSSimon Glass 2637581c01aSSimon Glass # If we've seen this node_name before, update the existing struct. 2647581c01aSSimon Glass if node_name in structs: 2657581c01aSSimon Glass struct = structs[node_name] 2667581c01aSSimon Glass for name, prop in fields.items(): 2677581c01aSSimon Glass oldprop = struct.get(name) 2687581c01aSSimon Glass if oldprop: 2697581c01aSSimon Glass oldprop.Widen(prop) 2707581c01aSSimon Glass else: 2717581c01aSSimon Glass struct[name] = prop 2727581c01aSSimon Glass 2737581c01aSSimon Glass # Otherwise store this as a new struct. 2747581c01aSSimon Glass else: 2757581c01aSSimon Glass structs[node_name] = fields 2767581c01aSSimon Glass 2777581c01aSSimon Glass upto = 0 2787581c01aSSimon Glass for node in self._valid_nodes: 27956e0bbe0SSimon Glass node_name, _ = get_compat_name(node) 2807581c01aSSimon Glass struct = structs[node_name] 2817581c01aSSimon Glass for name, prop in node.props.items(): 2827581c01aSSimon Glass if name not in PROP_IGNORE_LIST and name[0] != '#': 2837581c01aSSimon Glass prop.Widen(struct[name]) 2847581c01aSSimon Glass upto += 1 2857581c01aSSimon Glass 28656e0bbe0SSimon Glass struct_name, aliases = get_compat_name(node) 2877581c01aSSimon Glass for alias in aliases: 2887581c01aSSimon Glass self._aliases[alias] = struct_name 2897581c01aSSimon Glass 2907581c01aSSimon Glass return structs 2917581c01aSSimon Glass 2922be282caSSimon Glass def scan_phandles(self): 2937581c01aSSimon Glass """Figure out what phandles each node uses 2947581c01aSSimon Glass 2957581c01aSSimon Glass We need to be careful when outputing nodes that use phandles since 2967581c01aSSimon Glass they must come after the declaration of the phandles in the C file. 2977581c01aSSimon Glass Otherwise we get a compiler error since the phandle struct is not yet 2987581c01aSSimon Glass declared. 2997581c01aSSimon Glass 3007581c01aSSimon Glass This function adds to each node a list of phandle nodes that the node 3017581c01aSSimon Glass depends on. This allows us to output things in the right order. 3027581c01aSSimon Glass """ 3037581c01aSSimon Glass for node in self._valid_nodes: 3047581c01aSSimon Glass node.phandles = set() 3057581c01aSSimon Glass for pname, prop in node.props.items(): 3067581c01aSSimon Glass if pname in PROP_IGNORE_LIST or pname[0] == '#': 3077581c01aSSimon Glass continue 3082be282caSSimon Glass if isinstance(prop.value, list): 30956e0bbe0SSimon Glass if is_phandle(prop): 3107581c01aSSimon Glass # Process the list as pairs of (phandle, id) 3112be282caSSimon Glass value_it = iter(prop.value) 3122be282caSSimon Glass for phandle_cell, _ in zip(value_it, value_it): 3137581c01aSSimon Glass phandle = fdt_util.fdt32_to_cpu(phandle_cell) 3142be282caSSimon Glass target_node = self._phandle_nodes[phandle] 3157581c01aSSimon Glass node.phandles.add(target_node) 3167581c01aSSimon Glass 3177581c01aSSimon Glass 3182be282caSSimon Glass def generate_structs(self, structs): 3197581c01aSSimon Glass """Generate struct defintions for the platform data 3207581c01aSSimon Glass 3217581c01aSSimon Glass This writes out the body of a header file consisting of structure 3227581c01aSSimon Glass definitions for node in self._valid_nodes. See the documentation in 3237581c01aSSimon Glass README.of-plat for more information. 3247581c01aSSimon Glass """ 3252be282caSSimon Glass self.out('#include <stdbool.h>\n') 3262be282caSSimon Glass self.out('#include <libfdt.h>\n') 3277581c01aSSimon Glass 3287581c01aSSimon Glass # Output the struct definition 3297581c01aSSimon Glass for name in sorted(structs): 3302be282caSSimon Glass self.out('struct %s%s {\n' % (STRUCT_PREFIX, name)) 3317581c01aSSimon Glass for pname in sorted(structs[name]): 3327581c01aSSimon Glass prop = structs[name][pname] 33356e0bbe0SSimon Glass if is_phandle(prop): 3347581c01aSSimon Glass # For phandles, include a reference to the target 3352be282caSSimon Glass self.out('\t%s%s[%d]' % (tab_to(2, 'struct phandle_2_cell'), 3362be282caSSimon Glass conv_name_to_c(prop.name), 3377581c01aSSimon Glass len(prop.value) / 2)) 3387581c01aSSimon Glass else: 3397581c01aSSimon Glass ptype = TYPE_NAMES[prop.type] 3402be282caSSimon Glass self.out('\t%s%s' % (tab_to(2, ptype), 3412be282caSSimon Glass conv_name_to_c(prop.name))) 3422be282caSSimon Glass if isinstance(prop.value, list): 3432be282caSSimon Glass self.out('[%d]' % len(prop.value)) 3442be282caSSimon Glass self.out(';\n') 3452be282caSSimon Glass self.out('};\n') 3467581c01aSSimon Glass 3477581c01aSSimon Glass for alias, struct_name in self._aliases.iteritems(): 3482be282caSSimon Glass self.out('#define %s%s %s%s\n'% (STRUCT_PREFIX, alias, 3497581c01aSSimon Glass STRUCT_PREFIX, struct_name)) 3507581c01aSSimon Glass 3512be282caSSimon Glass def output_node(self, node): 3527581c01aSSimon Glass """Output the C code for a node 3537581c01aSSimon Glass 3547581c01aSSimon Glass Args: 3557581c01aSSimon Glass node: node to output 3567581c01aSSimon Glass """ 35756e0bbe0SSimon Glass struct_name, _ = get_compat_name(node) 3582be282caSSimon Glass var_name = conv_name_to_c(node.name) 3592be282caSSimon Glass self.buf('static struct %s%s %s%s = {\n' % 3607581c01aSSimon Glass (STRUCT_PREFIX, struct_name, VAL_PREFIX, var_name)) 3617581c01aSSimon Glass for pname, prop in node.props.items(): 3627581c01aSSimon Glass if pname in PROP_IGNORE_LIST or pname[0] == '#': 3637581c01aSSimon Glass continue 3642be282caSSimon Glass member_name = conv_name_to_c(prop.name) 3652be282caSSimon Glass self.buf('\t%s= ' % tab_to(3, '.' + member_name)) 3667581c01aSSimon Glass 3677581c01aSSimon Glass # Special handling for lists 3682be282caSSimon Glass if isinstance(prop.value, list): 3692be282caSSimon Glass self.buf('{') 3707581c01aSSimon Glass vals = [] 3717581c01aSSimon Glass # For phandles, output a reference to the platform data 3727581c01aSSimon Glass # of the target node. 37356e0bbe0SSimon Glass if is_phandle(prop): 3747581c01aSSimon Glass # Process the list as pairs of (phandle, id) 3752be282caSSimon Glass value_it = iter(prop.value) 3762be282caSSimon Glass for phandle_cell, id_cell in zip(value_it, value_it): 3777581c01aSSimon Glass phandle = fdt_util.fdt32_to_cpu(phandle_cell) 3782be282caSSimon Glass id_num = fdt_util.fdt32_to_cpu(id_cell) 3792be282caSSimon Glass target_node = self._phandle_nodes[phandle] 3802be282caSSimon Glass name = conv_name_to_c(target_node.name) 3812be282caSSimon Glass vals.append('{&%s%s, %d}' % (VAL_PREFIX, name, id_num)) 3827581c01aSSimon Glass else: 3837581c01aSSimon Glass for val in prop.value: 38456e0bbe0SSimon Glass vals.append(get_value(prop.type, val)) 3852be282caSSimon Glass self.buf(', '.join(vals)) 3862be282caSSimon Glass self.buf('}') 3877581c01aSSimon Glass else: 38856e0bbe0SSimon Glass self.buf(get_value(prop.type, prop.value)) 3892be282caSSimon Glass self.buf(',\n') 3902be282caSSimon Glass self.buf('};\n') 3917581c01aSSimon Glass 3927581c01aSSimon Glass # Add a device declaration 3932be282caSSimon Glass self.buf('U_BOOT_DEVICE(%s) = {\n' % var_name) 3942be282caSSimon Glass self.buf('\t.name\t\t= "%s",\n' % struct_name) 3952be282caSSimon Glass self.buf('\t.platdata\t= &%s%s,\n' % (VAL_PREFIX, var_name)) 3962be282caSSimon Glass self.buf('\t.platdata_size\t= sizeof(%s%s),\n' % (VAL_PREFIX, var_name)) 3972be282caSSimon Glass self.buf('};\n') 3982be282caSSimon Glass self.buf('\n') 3997581c01aSSimon Glass 4002be282caSSimon Glass self.out(''.join(self.get_buf())) 4017581c01aSSimon Glass 4022be282caSSimon Glass def generate_tables(self): 4037581c01aSSimon Glass """Generate device defintions for the platform data 4047581c01aSSimon Glass 4057581c01aSSimon Glass This writes out C platform data initialisation data and 4067581c01aSSimon Glass U_BOOT_DEVICE() declarations for each valid node. Where a node has 4077581c01aSSimon Glass multiple compatible strings, a #define is used to make them equivalent. 4087581c01aSSimon Glass 4097581c01aSSimon Glass See the documentation in doc/driver-model/of-plat.txt for more 4107581c01aSSimon Glass information. 4117581c01aSSimon Glass """ 4122be282caSSimon Glass self.out('#include <common.h>\n') 4132be282caSSimon Glass self.out('#include <dm.h>\n') 4142be282caSSimon Glass self.out('#include <dt-structs.h>\n') 4152be282caSSimon Glass self.out('\n') 4167581c01aSSimon Glass nodes_to_output = list(self._valid_nodes) 4177581c01aSSimon Glass 4187581c01aSSimon Glass # Keep outputing nodes until there is none left 4197581c01aSSimon Glass while nodes_to_output: 4207581c01aSSimon Glass node = nodes_to_output[0] 4217581c01aSSimon Glass # Output all the node's dependencies first 4227581c01aSSimon Glass for req_node in node.phandles: 4237581c01aSSimon Glass if req_node in nodes_to_output: 4242be282caSSimon Glass self.output_node(req_node) 4257581c01aSSimon Glass nodes_to_output.remove(req_node) 4262be282caSSimon Glass self.output_node(node) 4277581c01aSSimon Glass nodes_to_output.remove(node) 428fa0ea5b0SSimon Glass 429fa0ea5b0SSimon Glass 430fa0ea5b0SSimon Glassdef run_steps(args, dtb_file, include_disabled, output): 431fa0ea5b0SSimon Glass """Run all the steps of the dtoc tool 432fa0ea5b0SSimon Glass 433fa0ea5b0SSimon Glass Args: 434fa0ea5b0SSimon Glass args: List of non-option arguments provided to the problem 435fa0ea5b0SSimon Glass dtb_file: Filename of dtb file to process 436fa0ea5b0SSimon Glass include_disabled: True to include disabled nodes 437fa0ea5b0SSimon Glass output: Name of output file 438fa0ea5b0SSimon Glass """ 439fa0ea5b0SSimon Glass if not args: 440fa0ea5b0SSimon Glass raise ValueError('Please specify a command: struct, platdata') 441fa0ea5b0SSimon Glass 442fa0ea5b0SSimon Glass plat = DtbPlatdata(dtb_file, include_disabled) 443fa0ea5b0SSimon Glass plat.scan_dtb() 444fa0ea5b0SSimon Glass plat.scan_tree() 445fa0ea5b0SSimon Glass plat.setup_output(output) 446fa0ea5b0SSimon Glass structs = plat.scan_structs() 447fa0ea5b0SSimon Glass plat.scan_phandles() 448fa0ea5b0SSimon Glass 449fa0ea5b0SSimon Glass for cmd in args[0].split(','): 450fa0ea5b0SSimon Glass if cmd == 'struct': 451fa0ea5b0SSimon Glass plat.generate_structs(structs) 452fa0ea5b0SSimon Glass elif cmd == 'platdata': 453fa0ea5b0SSimon Glass plat.generate_tables() 454fa0ea5b0SSimon Glass else: 455fa0ea5b0SSimon Glass raise ValueError("Unknown command '%s': (use: struct, platdata)" % 456fa0ea5b0SSimon Glass cmd) 457