169f2ed77SSimon Glass#!/usr/bin/python 269f2ed77SSimon Glass# 369f2ed77SSimon Glass# Copyright (C) 2016 Google, Inc 469f2ed77SSimon Glass# Written by Simon Glass <sjg@chromium.org> 569f2ed77SSimon Glass# 669f2ed77SSimon Glass# SPDX-License-Identifier: GPL-2.0+ 769f2ed77SSimon Glass# 869f2ed77SSimon Glass 969f2ed77SSimon Glassimport copy 1069f2ed77SSimon Glassfrom optparse import OptionError, OptionParser 1169f2ed77SSimon Glassimport os 1258593115SSimon Glassimport struct 1369f2ed77SSimon Glassimport sys 1469f2ed77SSimon Glass 1569f2ed77SSimon Glass# Bring in the patman libraries 1669f2ed77SSimon Glassour_path = os.path.dirname(os.path.realpath(__file__)) 1769f2ed77SSimon Glasssys.path.append(os.path.join(our_path, '../patman')) 1869f2ed77SSimon Glass 19bc1dea36SSimon Glassimport fdt 20ba482585SSimon Glassimport fdt_util 2169f2ed77SSimon Glass 2269f2ed77SSimon Glass# When we see these properties we ignore them - i.e. do not create a structure member 2369f2ed77SSimon GlassPROP_IGNORE_LIST = [ 2469f2ed77SSimon Glass '#address-cells', 2569f2ed77SSimon Glass '#gpio-cells', 2669f2ed77SSimon Glass '#size-cells', 2769f2ed77SSimon Glass 'compatible', 2869f2ed77SSimon Glass 'linux,phandle', 2969f2ed77SSimon Glass "status", 3069f2ed77SSimon Glass 'phandle', 31efefe122SSimon Glass 'u-boot,dm-pre-reloc', 3227326c7eSHeiko Stübner 'u-boot,dm-tpl', 3327326c7eSHeiko Stübner 'u-boot,dm-spl', 3469f2ed77SSimon Glass] 3569f2ed77SSimon Glass 3669f2ed77SSimon Glass# C type declarations for the tyues we support 3769f2ed77SSimon GlassTYPE_NAMES = { 38bc1dea36SSimon Glass fdt.TYPE_INT: 'fdt32_t', 39bc1dea36SSimon Glass fdt.TYPE_BYTE: 'unsigned char', 40bc1dea36SSimon Glass fdt.TYPE_STRING: 'const char *', 41bc1dea36SSimon Glass fdt.TYPE_BOOL: 'bool', 4269f2ed77SSimon Glass}; 4369f2ed77SSimon Glass 4469f2ed77SSimon GlassSTRUCT_PREFIX = 'dtd_' 4569f2ed77SSimon GlassVAL_PREFIX = 'dtv_' 4669f2ed77SSimon Glass 4769f2ed77SSimon Glassdef Conv_name_to_c(name): 4869f2ed77SSimon Glass """Convert a device-tree name to a C identifier 4969f2ed77SSimon Glass 5069f2ed77SSimon Glass Args: 5169f2ed77SSimon Glass name: Name to convert 5269f2ed77SSimon Glass Return: 5369f2ed77SSimon Glass String containing the C version of this name 5469f2ed77SSimon Glass """ 5569f2ed77SSimon Glass str = name.replace('@', '_at_') 5669f2ed77SSimon Glass str = str.replace('-', '_') 5769f2ed77SSimon Glass str = str.replace(',', '_') 586b6024a3SSimon Glass str = str.replace('.', '_') 5969f2ed77SSimon Glass str = str.replace('/', '__') 6069f2ed77SSimon Glass return str 6169f2ed77SSimon Glass 6269f2ed77SSimon Glassdef TabTo(num_tabs, str): 6369f2ed77SSimon Glass if len(str) >= num_tabs * 8: 6469f2ed77SSimon Glass return str + ' ' 6534c38896SPaul Burton return str + '\t' * (num_tabs - len(str) // 8) 6669f2ed77SSimon Glass 6769f2ed77SSimon Glassclass DtbPlatdata: 6869f2ed77SSimon Glass """Provide a means to convert device tree binary data to platform data 6969f2ed77SSimon Glass 7069f2ed77SSimon Glass The output of this process is C structures which can be used in space- 7169f2ed77SSimon Glass constrained encvironments where the ~3KB code overhead of device tree 7269f2ed77SSimon Glass code is not affordable. 7369f2ed77SSimon Glass 7469f2ed77SSimon Glass Properties: 7569f2ed77SSimon Glass fdt: Fdt object, referencing the device tree 7669f2ed77SSimon Glass _dtb_fname: Filename of the input device tree binary file 7769f2ed77SSimon Glass _valid_nodes: A list of Node object with compatible strings 7869f2ed77SSimon Glass _options: Command-line options 7969f2ed77SSimon Glass _phandle_node: A dict of nodes indexed by phandle number (1, 2...) 8069f2ed77SSimon Glass _outfile: The current output file (sys.stdout or a real file) 8169f2ed77SSimon Glass _lines: Stashed list of output lines for outputting in the future 8269f2ed77SSimon Glass _phandle_node: A dict of Nodes indexed by phandle (an integer) 8369f2ed77SSimon Glass """ 8469f2ed77SSimon Glass def __init__(self, dtb_fname, options): 8569f2ed77SSimon Glass self._dtb_fname = dtb_fname 8669f2ed77SSimon Glass self._valid_nodes = None 8769f2ed77SSimon Glass self._options = options 8869f2ed77SSimon Glass self._phandle_node = {} 8969f2ed77SSimon Glass self._outfile = None 9069f2ed77SSimon Glass self._lines = [] 91*2cce5866SSimon Glass self._aliases = {} 9269f2ed77SSimon Glass 9369f2ed77SSimon Glass def SetupOutput(self, fname): 9469f2ed77SSimon Glass """Set up the output destination 9569f2ed77SSimon Glass 9669f2ed77SSimon Glass Once this is done, future calls to self.Out() will output to this 9769f2ed77SSimon Glass file. 9869f2ed77SSimon Glass 9969f2ed77SSimon Glass Args: 10069f2ed77SSimon Glass fname: Filename to send output to, or '-' for stdout 10169f2ed77SSimon Glass """ 10269f2ed77SSimon Glass if fname == '-': 10369f2ed77SSimon Glass self._outfile = sys.stdout 10469f2ed77SSimon Glass else: 10569f2ed77SSimon Glass self._outfile = open(fname, 'w') 10669f2ed77SSimon Glass 10769f2ed77SSimon Glass def Out(self, str): 10869f2ed77SSimon Glass """Output a string to the output file 10969f2ed77SSimon Glass 11069f2ed77SSimon Glass Args: 11169f2ed77SSimon Glass str: String to output 11269f2ed77SSimon Glass """ 11369f2ed77SSimon Glass self._outfile.write(str) 11469f2ed77SSimon Glass 11569f2ed77SSimon Glass def Buf(self, str): 11669f2ed77SSimon Glass """Buffer up a string to send later 11769f2ed77SSimon Glass 11869f2ed77SSimon Glass Args: 11969f2ed77SSimon Glass str: String to add to our 'buffer' list 12069f2ed77SSimon Glass """ 12169f2ed77SSimon Glass self._lines.append(str) 12269f2ed77SSimon Glass 12369f2ed77SSimon Glass def GetBuf(self): 12469f2ed77SSimon Glass """Get the contents of the output buffer, and clear it 12569f2ed77SSimon Glass 12669f2ed77SSimon Glass Returns: 12769f2ed77SSimon Glass The output buffer, which is then cleared for future use 12869f2ed77SSimon Glass """ 12969f2ed77SSimon Glass lines = self._lines 13069f2ed77SSimon Glass self._lines = [] 13169f2ed77SSimon Glass return lines 13269f2ed77SSimon Glass 13369f2ed77SSimon Glass def GetValue(self, type, value): 13469f2ed77SSimon Glass """Get a value as a C expression 13569f2ed77SSimon Glass 13669f2ed77SSimon Glass For integers this returns a byte-swapped (little-endian) hex string 13769f2ed77SSimon Glass For bytes this returns a hex string, e.g. 0x12 13869f2ed77SSimon Glass For strings this returns a literal string enclosed in quotes 13969f2ed77SSimon Glass For booleans this return 'true' 14069f2ed77SSimon Glass 14169f2ed77SSimon Glass Args: 14269f2ed77SSimon Glass type: Data type (fdt_util) 14369f2ed77SSimon Glass value: Data value, as a string of bytes 14469f2ed77SSimon Glass """ 145bc1dea36SSimon Glass if type == fdt.TYPE_INT: 14669f2ed77SSimon Glass return '%#x' % fdt_util.fdt32_to_cpu(value) 147bc1dea36SSimon Glass elif type == fdt.TYPE_BYTE: 14869f2ed77SSimon Glass return '%#x' % ord(value[0]) 149bc1dea36SSimon Glass elif type == fdt.TYPE_STRING: 15069f2ed77SSimon Glass return '"%s"' % value 151bc1dea36SSimon Glass elif type == fdt.TYPE_BOOL: 15269f2ed77SSimon Glass return 'true' 15369f2ed77SSimon Glass 15469f2ed77SSimon Glass def GetCompatName(self, node): 15569f2ed77SSimon Glass """Get a node's first compatible string as a C identifier 15669f2ed77SSimon Glass 15769f2ed77SSimon Glass Args: 15869f2ed77SSimon Glass node: Node object to check 15969f2ed77SSimon Glass Return: 16069f2ed77SSimon Glass C identifier for the first compatible string 16169f2ed77SSimon Glass """ 16269f2ed77SSimon Glass compat = node.props['compatible'].value 163*2cce5866SSimon Glass aliases = [] 16469f2ed77SSimon Glass if type(compat) == list: 165*2cce5866SSimon Glass compat, aliases = compat[0], compat[1:] 166*2cce5866SSimon Glass return Conv_name_to_c(compat), [Conv_name_to_c(a) for a in aliases] 16769f2ed77SSimon Glass 16869f2ed77SSimon Glass def ScanDtb(self): 16969f2ed77SSimon Glass """Scan the device tree to obtain a tree of notes and properties 17069f2ed77SSimon Glass 17169f2ed77SSimon Glass Once this is done, self.fdt.GetRoot() can be called to obtain the 17269f2ed77SSimon Glass device tree root node, and progress from there. 17369f2ed77SSimon Glass """ 17499ed4a2eSSimon Glass self.fdt = fdt.FdtScan(self._dtb_fname) 17569f2ed77SSimon Glass 17655bc080eSPhilipp Tomsich def ScanNode(self, root): 17755bc080eSPhilipp Tomsich for node in root.subnodes: 17855bc080eSPhilipp Tomsich if 'compatible' in node.props: 17955bc080eSPhilipp Tomsich status = node.props.get('status') 18055bc080eSPhilipp Tomsich if (not options.include_disabled and not status or 18155bc080eSPhilipp Tomsich status.value != 'disabled'): 18255bc080eSPhilipp Tomsich self._valid_nodes.append(node) 18355bc080eSPhilipp Tomsich phandle_prop = node.props.get('phandle') 18455bc080eSPhilipp Tomsich if phandle_prop: 18555bc080eSPhilipp Tomsich phandle = phandle_prop.GetPhandle() 18655bc080eSPhilipp Tomsich self._phandle_node[phandle] = node 18755bc080eSPhilipp Tomsich 18855bc080eSPhilipp Tomsich # recurse to handle any subnodes 18955bc080eSPhilipp Tomsich self.ScanNode(node); 19055bc080eSPhilipp Tomsich 19169f2ed77SSimon Glass def ScanTree(self): 19269f2ed77SSimon Glass """Scan the device tree for useful information 19369f2ed77SSimon Glass 19469f2ed77SSimon Glass This fills in the following properties: 19569f2ed77SSimon Glass _phandle_node: A dict of Nodes indexed by phandle (an integer) 19669f2ed77SSimon Glass _valid_nodes: A list of nodes we wish to consider include in the 19769f2ed77SSimon Glass platform data 19869f2ed77SSimon Glass """ 19969f2ed77SSimon Glass self._phandle_node = {} 20055bc080eSPhilipp Tomsich self._valid_nodes = [] 20155bc080eSPhilipp Tomsich return self.ScanNode(self.fdt.GetRoot()); 20255bc080eSPhilipp Tomsich 20369f2ed77SSimon Glass for node in self.fdt.GetRoot().subnodes: 20469f2ed77SSimon Glass if 'compatible' in node.props: 20569f2ed77SSimon Glass status = node.props.get('status') 20669f2ed77SSimon Glass if (not options.include_disabled and not status or 20769f2ed77SSimon Glass status.value != 'disabled'): 20869f2ed77SSimon Glass node_list.append(node) 20969f2ed77SSimon Glass phandle_prop = node.props.get('phandle') 21069f2ed77SSimon Glass if phandle_prop: 21169f2ed77SSimon Glass phandle = phandle_prop.GetPhandle() 21269f2ed77SSimon Glass self._phandle_node[phandle] = node 21369f2ed77SSimon Glass 21469f2ed77SSimon Glass self._valid_nodes = node_list 21569f2ed77SSimon Glass 21669f2ed77SSimon Glass def IsPhandle(self, prop): 21769f2ed77SSimon Glass """Check if a node contains phandles 21869f2ed77SSimon Glass 21969f2ed77SSimon Glass We have no reliable way of detecting whether a node uses a phandle 22069f2ed77SSimon Glass or not. As an interim measure, use a list of known property names. 22169f2ed77SSimon Glass 22269f2ed77SSimon Glass Args: 22369f2ed77SSimon Glass prop: Prop object to check 22469f2ed77SSimon Glass Return: 22569f2ed77SSimon Glass True if the object value contains phandles, else False 22669f2ed77SSimon Glass """ 22769f2ed77SSimon Glass if prop.name in ['clocks']: 22869f2ed77SSimon Glass return True 22969f2ed77SSimon Glass return False 23069f2ed77SSimon Glass 23169f2ed77SSimon Glass def ScanStructs(self): 23269f2ed77SSimon Glass """Scan the device tree building up the C structures we will use. 23369f2ed77SSimon Glass 23469f2ed77SSimon Glass Build a dict keyed by C struct name containing a dict of Prop 23569f2ed77SSimon Glass object for each struct field (keyed by property name). Where the 23669f2ed77SSimon Glass same struct appears multiple times, try to use the 'widest' 23769f2ed77SSimon Glass property, i.e. the one with a type which can express all others. 23869f2ed77SSimon Glass 23969f2ed77SSimon Glass Once the widest property is determined, all other properties are 24069f2ed77SSimon Glass updated to match that width. 24169f2ed77SSimon Glass """ 24269f2ed77SSimon Glass structs = {} 24369f2ed77SSimon Glass for node in self._valid_nodes: 244*2cce5866SSimon Glass node_name, _ = self.GetCompatName(node) 24569f2ed77SSimon Glass fields = {} 24669f2ed77SSimon Glass 24769f2ed77SSimon Glass # Get a list of all the valid properties in this node. 2484ae6549fSPaul Burton for name, prop in node.props.items(): 24969f2ed77SSimon Glass if name not in PROP_IGNORE_LIST and name[0] != '#': 25069f2ed77SSimon Glass fields[name] = copy.deepcopy(prop) 25169f2ed77SSimon Glass 25269f2ed77SSimon Glass # If we've seen this node_name before, update the existing struct. 25369f2ed77SSimon Glass if node_name in structs: 25469f2ed77SSimon Glass struct = structs[node_name] 2554ae6549fSPaul Burton for name, prop in fields.items(): 25669f2ed77SSimon Glass oldprop = struct.get(name) 25769f2ed77SSimon Glass if oldprop: 25869f2ed77SSimon Glass oldprop.Widen(prop) 25969f2ed77SSimon Glass else: 26069f2ed77SSimon Glass struct[name] = prop 26169f2ed77SSimon Glass 26269f2ed77SSimon Glass # Otherwise store this as a new struct. 26369f2ed77SSimon Glass else: 26469f2ed77SSimon Glass structs[node_name] = fields 26569f2ed77SSimon Glass 26669f2ed77SSimon Glass upto = 0 26769f2ed77SSimon Glass for node in self._valid_nodes: 268*2cce5866SSimon Glass node_name, _ = self.GetCompatName(node) 26969f2ed77SSimon Glass struct = structs[node_name] 2704ae6549fSPaul Burton for name, prop in node.props.items(): 27169f2ed77SSimon Glass if name not in PROP_IGNORE_LIST and name[0] != '#': 27269f2ed77SSimon Glass prop.Widen(struct[name]) 27369f2ed77SSimon Glass upto += 1 274*2cce5866SSimon Glass 275*2cce5866SSimon Glass struct_name, aliases = self.GetCompatName(node) 276*2cce5866SSimon Glass for alias in aliases: 277*2cce5866SSimon Glass self._aliases[alias] = struct_name 278*2cce5866SSimon Glass 27969f2ed77SSimon Glass return structs 28069f2ed77SSimon Glass 281439c947fSSimon Glass def ScanPhandles(self): 282439c947fSSimon Glass """Figure out what phandles each node uses 283439c947fSSimon Glass 284439c947fSSimon Glass We need to be careful when outputing nodes that use phandles since 285439c947fSSimon Glass they must come after the declaration of the phandles in the C file. 286439c947fSSimon Glass Otherwise we get a compiler error since the phandle struct is not yet 287439c947fSSimon Glass declared. 288439c947fSSimon Glass 289439c947fSSimon Glass This function adds to each node a list of phandle nodes that the node 290439c947fSSimon Glass depends on. This allows us to output things in the right order. 291439c947fSSimon Glass """ 292439c947fSSimon Glass for node in self._valid_nodes: 293439c947fSSimon Glass node.phandles = set() 294439c947fSSimon Glass for pname, prop in node.props.items(): 295439c947fSSimon Glass if pname in PROP_IGNORE_LIST or pname[0] == '#': 296439c947fSSimon Glass continue 297439c947fSSimon Glass if type(prop.value) == list: 298439c947fSSimon Glass if self.IsPhandle(prop): 299439c947fSSimon Glass # Process the list as pairs of (phandle, id) 300439c947fSSimon Glass it = iter(prop.value) 301439c947fSSimon Glass for phandle_cell, id_cell in zip(it, it): 302439c947fSSimon Glass phandle = fdt_util.fdt32_to_cpu(phandle_cell) 303439c947fSSimon Glass id = fdt_util.fdt32_to_cpu(id_cell) 304439c947fSSimon Glass target_node = self._phandle_node[phandle] 305439c947fSSimon Glass node.phandles.add(target_node) 306439c947fSSimon Glass 307439c947fSSimon Glass 30869f2ed77SSimon Glass def GenerateStructs(self, structs): 30969f2ed77SSimon Glass """Generate struct defintions for the platform data 31069f2ed77SSimon Glass 31169f2ed77SSimon Glass This writes out the body of a header file consisting of structure 31269f2ed77SSimon Glass definitions for node in self._valid_nodes. See the documentation in 31369f2ed77SSimon Glass README.of-plat for more information. 31469f2ed77SSimon Glass """ 31569f2ed77SSimon Glass self.Out('#include <stdbool.h>\n') 31669f2ed77SSimon Glass self.Out('#include <libfdt.h>\n') 31769f2ed77SSimon Glass 31869f2ed77SSimon Glass # Output the struct definition 31969f2ed77SSimon Glass for name in sorted(structs): 32069f2ed77SSimon Glass self.Out('struct %s%s {\n' % (STRUCT_PREFIX, name)); 32169f2ed77SSimon Glass for pname in sorted(structs[name]): 32269f2ed77SSimon Glass prop = structs[name][pname] 32369f2ed77SSimon Glass if self.IsPhandle(prop): 32469f2ed77SSimon Glass # For phandles, include a reference to the target 32569f2ed77SSimon Glass self.Out('\t%s%s[%d]' % (TabTo(2, 'struct phandle_2_cell'), 32669f2ed77SSimon Glass Conv_name_to_c(prop.name), 32769f2ed77SSimon Glass len(prop.value) / 2)) 32869f2ed77SSimon Glass else: 32969f2ed77SSimon Glass ptype = TYPE_NAMES[prop.type] 33069f2ed77SSimon Glass self.Out('\t%s%s' % (TabTo(2, ptype), 33169f2ed77SSimon Glass Conv_name_to_c(prop.name))) 33269f2ed77SSimon Glass if type(prop.value) == list: 33369f2ed77SSimon Glass self.Out('[%d]' % len(prop.value)) 33469f2ed77SSimon Glass self.Out(';\n') 33569f2ed77SSimon Glass self.Out('};\n') 33669f2ed77SSimon Glass 337*2cce5866SSimon Glass for alias, struct_name in self._aliases.iteritems(): 338*2cce5866SSimon Glass self.Out('#define %s%s %s%s\n'% (STRUCT_PREFIX, alias, 339*2cce5866SSimon Glass STRUCT_PREFIX, struct_name)) 340*2cce5866SSimon Glass 34149eec8c7SSimon Glass def OutputNode(self, node): 34249eec8c7SSimon Glass """Output the C code for a node 34369f2ed77SSimon Glass 34449eec8c7SSimon Glass Args: 34549eec8c7SSimon Glass node: node to output 34669f2ed77SSimon Glass """ 347*2cce5866SSimon Glass struct_name, _ = self.GetCompatName(node) 34869f2ed77SSimon Glass var_name = Conv_name_to_c(node.name) 34969f2ed77SSimon Glass self.Buf('static struct %s%s %s%s = {\n' % 35069f2ed77SSimon Glass (STRUCT_PREFIX, struct_name, VAL_PREFIX, var_name)) 3514ae6549fSPaul Burton for pname, prop in node.props.items(): 35269f2ed77SSimon Glass if pname in PROP_IGNORE_LIST or pname[0] == '#': 35369f2ed77SSimon Glass continue 35469f2ed77SSimon Glass ptype = TYPE_NAMES[prop.type] 35569f2ed77SSimon Glass member_name = Conv_name_to_c(prop.name) 35669f2ed77SSimon Glass self.Buf('\t%s= ' % TabTo(3, '.' + member_name)) 35769f2ed77SSimon Glass 35869f2ed77SSimon Glass # Special handling for lists 35969f2ed77SSimon Glass if type(prop.value) == list: 36069f2ed77SSimon Glass self.Buf('{') 36169f2ed77SSimon Glass vals = [] 36269f2ed77SSimon Glass # For phandles, output a reference to the platform data 36369f2ed77SSimon Glass # of the target node. 36469f2ed77SSimon Glass if self.IsPhandle(prop): 36569f2ed77SSimon Glass # Process the list as pairs of (phandle, id) 36669f2ed77SSimon Glass it = iter(prop.value) 36769f2ed77SSimon Glass for phandle_cell, id_cell in zip(it, it): 36869f2ed77SSimon Glass phandle = fdt_util.fdt32_to_cpu(phandle_cell) 36969f2ed77SSimon Glass id = fdt_util.fdt32_to_cpu(id_cell) 37069f2ed77SSimon Glass target_node = self._phandle_node[phandle] 37169f2ed77SSimon Glass name = Conv_name_to_c(target_node.name) 37269f2ed77SSimon Glass vals.append('{&%s%s, %d}' % (VAL_PREFIX, name, id)) 37369f2ed77SSimon Glass else: 37469f2ed77SSimon Glass for val in prop.value: 37569f2ed77SSimon Glass vals.append(self.GetValue(prop.type, val)) 37669f2ed77SSimon Glass self.Buf(', '.join(vals)) 37769f2ed77SSimon Glass self.Buf('}') 37869f2ed77SSimon Glass else: 37969f2ed77SSimon Glass self.Buf(self.GetValue(prop.type, prop.value)) 38069f2ed77SSimon Glass self.Buf(',\n') 38169f2ed77SSimon Glass self.Buf('};\n') 38269f2ed77SSimon Glass 38369f2ed77SSimon Glass # Add a device declaration 38469f2ed77SSimon Glass self.Buf('U_BOOT_DEVICE(%s) = {\n' % var_name) 38569f2ed77SSimon Glass self.Buf('\t.name\t\t= "%s",\n' % struct_name) 38669f2ed77SSimon Glass self.Buf('\t.platdata\t= &%s%s,\n' % (VAL_PREFIX, var_name)) 3879fa28190SSimon Glass self.Buf('\t.platdata_size\t= sizeof(%s%s),\n' % 3889fa28190SSimon Glass (VAL_PREFIX, var_name)) 38969f2ed77SSimon Glass self.Buf('};\n') 39069f2ed77SSimon Glass self.Buf('\n') 39169f2ed77SSimon Glass 392439c947fSSimon Glass self.Out(''.join(self.GetBuf())) 393439c947fSSimon Glass 39449eec8c7SSimon Glass def GenerateTables(self): 39549eec8c7SSimon Glass """Generate device defintions for the platform data 39649eec8c7SSimon Glass 39749eec8c7SSimon Glass This writes out C platform data initialisation data and 398*2cce5866SSimon Glass U_BOOT_DEVICE() declarations for each valid node. Where a node has 399*2cce5866SSimon Glass multiple compatible strings, a #define is used to make them equivalent. 400*2cce5866SSimon Glass 401*2cce5866SSimon Glass See the documentation in doc/driver-model/of-plat.txt for more 402*2cce5866SSimon Glass information. 40349eec8c7SSimon Glass """ 40449eec8c7SSimon Glass self.Out('#include <common.h>\n') 40549eec8c7SSimon Glass self.Out('#include <dm.h>\n') 40649eec8c7SSimon Glass self.Out('#include <dt-structs.h>\n') 40749eec8c7SSimon Glass self.Out('\n') 408439c947fSSimon Glass nodes_to_output = list(self._valid_nodes) 409439c947fSSimon Glass 410439c947fSSimon Glass # Keep outputing nodes until there is none left 411439c947fSSimon Glass while nodes_to_output: 412439c947fSSimon Glass node = nodes_to_output[0] 413439c947fSSimon Glass # Output all the node's dependencies first 414439c947fSSimon Glass for req_node in node.phandles: 415439c947fSSimon Glass if req_node in nodes_to_output: 416439c947fSSimon Glass self.OutputNode(req_node) 417439c947fSSimon Glass nodes_to_output.remove(req_node) 41849eec8c7SSimon Glass self.OutputNode(node) 419439c947fSSimon Glass nodes_to_output.remove(node) 42069f2ed77SSimon Glass 42169f2ed77SSimon Glass 42269f2ed77SSimon Glassif __name__ != "__main__": 42369f2ed77SSimon Glass pass 42469f2ed77SSimon Glass 42569f2ed77SSimon Glassparser = OptionParser() 42669f2ed77SSimon Glassparser.add_option('-d', '--dtb-file', action='store', 42769f2ed77SSimon Glass help='Specify the .dtb input file') 42869f2ed77SSimon Glassparser.add_option('--include-disabled', action='store_true', 42969f2ed77SSimon Glass help='Include disabled nodes') 43069f2ed77SSimon Glassparser.add_option('-o', '--output', action='store', default='-', 43169f2ed77SSimon Glass help='Select output filename') 43269f2ed77SSimon Glass(options, args) = parser.parse_args() 43369f2ed77SSimon Glass 43469f2ed77SSimon Glassif not args: 43569f2ed77SSimon Glass raise ValueError('Please specify a command: struct, platdata') 43669f2ed77SSimon Glass 43769f2ed77SSimon Glassplat = DtbPlatdata(options.dtb_file, options) 43869f2ed77SSimon Glassplat.ScanDtb() 43969f2ed77SSimon Glassplat.ScanTree() 44069f2ed77SSimon Glassplat.SetupOutput(options.output) 44169f2ed77SSimon Glassstructs = plat.ScanStructs() 442439c947fSSimon Glassplat.ScanPhandles() 44369f2ed77SSimon Glass 44469f2ed77SSimon Glassfor cmd in args[0].split(','): 44569f2ed77SSimon Glass if cmd == 'struct': 44669f2ed77SSimon Glass plat.GenerateStructs(structs) 44769f2ed77SSimon Glass elif cmd == 'platdata': 44869f2ed77SSimon Glass plat.GenerateTables() 44969f2ed77SSimon Glass else: 45069f2ed77SSimon Glass raise ValueError("Unknown command '%s': (use: struct, platdata)" % cmd) 451