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 9*14f5acfcSSimon Glass"""Device tree to C tool 10*14f5acfcSSimon Glass 11*14f5acfcSSimon GlassThis tool converts a device tree binary file (.dtb) into two C files. The 12*14f5acfcSSimon Glassindent is to allow a C program to access data from the device tree without 13*14f5acfcSSimon Glasshaving to link against libfdt. By putting the data from the device tree into 14*14f5acfcSSimon GlassC structures, normal C code can be used. This helps to reduce the size of the 15*14f5acfcSSimon Glasscompiled program. 16*14f5acfcSSimon Glass 17*14f5acfcSSimon GlassDtoc produces two output files: 18*14f5acfcSSimon Glass 19*14f5acfcSSimon Glass dt-structs.h - contains struct definitions 20*14f5acfcSSimon Glass dt-platdata.c - contains data from the device tree using the struct 21*14f5acfcSSimon Glass definitions, as well as U-Boot driver definitions. 22*14f5acfcSSimon Glass 23*14f5acfcSSimon GlassThis tool is used in U-Boot to provide device tree data to SPL without 24*14f5acfcSSimon Glassincreasing the code size of SPL. This supports the CONFIG_SPL_OF_PLATDATA 25*14f5acfcSSimon Glassoptions. For more information about the use of this options and tool please 26*14f5acfcSSimon Glasssee doc/driver-model/of-plat.txt 27*14f5acfcSSimon Glass""" 28*14f5acfcSSimon Glass 2969f2ed77SSimon Glassimport copy 3069f2ed77SSimon Glassfrom optparse import OptionError, OptionParser 3169f2ed77SSimon Glassimport os 3258593115SSimon Glassimport struct 3369f2ed77SSimon Glassimport sys 3469f2ed77SSimon Glass 3569f2ed77SSimon Glass# Bring in the patman libraries 3669f2ed77SSimon Glassour_path = os.path.dirname(os.path.realpath(__file__)) 3769f2ed77SSimon Glasssys.path.append(os.path.join(our_path, '../patman')) 3869f2ed77SSimon Glass 39bc1dea36SSimon Glassimport fdt 40ba482585SSimon Glassimport fdt_util 4169f2ed77SSimon Glass 4269f2ed77SSimon Glass# When we see these properties we ignore them - i.e. do not create a structure member 4369f2ed77SSimon GlassPROP_IGNORE_LIST = [ 4469f2ed77SSimon Glass '#address-cells', 4569f2ed77SSimon Glass '#gpio-cells', 4669f2ed77SSimon Glass '#size-cells', 4769f2ed77SSimon Glass 'compatible', 4869f2ed77SSimon Glass 'linux,phandle', 4969f2ed77SSimon Glass "status", 5069f2ed77SSimon Glass 'phandle', 51efefe122SSimon Glass 'u-boot,dm-pre-reloc', 5227326c7eSHeiko Stübner 'u-boot,dm-tpl', 5327326c7eSHeiko Stübner 'u-boot,dm-spl', 5469f2ed77SSimon Glass] 5569f2ed77SSimon Glass 5669f2ed77SSimon Glass# C type declarations for the tyues we support 5769f2ed77SSimon GlassTYPE_NAMES = { 58bc1dea36SSimon Glass fdt.TYPE_INT: 'fdt32_t', 59bc1dea36SSimon Glass fdt.TYPE_BYTE: 'unsigned char', 60bc1dea36SSimon Glass fdt.TYPE_STRING: 'const char *', 61bc1dea36SSimon Glass fdt.TYPE_BOOL: 'bool', 6269f2ed77SSimon Glass}; 6369f2ed77SSimon Glass 6469f2ed77SSimon GlassSTRUCT_PREFIX = 'dtd_' 6569f2ed77SSimon GlassVAL_PREFIX = 'dtv_' 6669f2ed77SSimon Glass 6769f2ed77SSimon Glassdef Conv_name_to_c(name): 6869f2ed77SSimon Glass """Convert a device-tree name to a C identifier 6969f2ed77SSimon Glass 7069f2ed77SSimon Glass Args: 7169f2ed77SSimon Glass name: Name to convert 7269f2ed77SSimon Glass Return: 7369f2ed77SSimon Glass String containing the C version of this name 7469f2ed77SSimon Glass """ 7569f2ed77SSimon Glass str = name.replace('@', '_at_') 7669f2ed77SSimon Glass str = str.replace('-', '_') 7769f2ed77SSimon Glass str = str.replace(',', '_') 786b6024a3SSimon Glass str = str.replace('.', '_') 7969f2ed77SSimon Glass str = str.replace('/', '__') 8069f2ed77SSimon Glass return str 8169f2ed77SSimon Glass 8269f2ed77SSimon Glassdef TabTo(num_tabs, str): 8369f2ed77SSimon Glass if len(str) >= num_tabs * 8: 8469f2ed77SSimon Glass return str + ' ' 8534c38896SPaul Burton return str + '\t' * (num_tabs - len(str) // 8) 8669f2ed77SSimon Glass 8769f2ed77SSimon Glassclass DtbPlatdata: 8869f2ed77SSimon Glass """Provide a means to convert device tree binary data to platform data 8969f2ed77SSimon Glass 9069f2ed77SSimon Glass The output of this process is C structures which can be used in space- 9169f2ed77SSimon Glass constrained encvironments where the ~3KB code overhead of device tree 9269f2ed77SSimon Glass code is not affordable. 9369f2ed77SSimon Glass 9469f2ed77SSimon Glass Properties: 9569f2ed77SSimon Glass fdt: Fdt object, referencing the device tree 9669f2ed77SSimon Glass _dtb_fname: Filename of the input device tree binary file 9769f2ed77SSimon Glass _valid_nodes: A list of Node object with compatible strings 9869f2ed77SSimon Glass _options: Command-line options 9969f2ed77SSimon Glass _phandle_node: A dict of nodes indexed by phandle number (1, 2...) 10069f2ed77SSimon Glass _outfile: The current output file (sys.stdout or a real file) 10169f2ed77SSimon Glass _lines: Stashed list of output lines for outputting in the future 10269f2ed77SSimon Glass _phandle_node: A dict of Nodes indexed by phandle (an integer) 10369f2ed77SSimon Glass """ 10469f2ed77SSimon Glass def __init__(self, dtb_fname, options): 10569f2ed77SSimon Glass self._dtb_fname = dtb_fname 10669f2ed77SSimon Glass self._valid_nodes = None 10769f2ed77SSimon Glass self._options = options 10869f2ed77SSimon Glass self._phandle_node = {} 10969f2ed77SSimon Glass self._outfile = None 11069f2ed77SSimon Glass self._lines = [] 1112cce5866SSimon Glass self._aliases = {} 11269f2ed77SSimon Glass 11369f2ed77SSimon Glass def SetupOutput(self, fname): 11469f2ed77SSimon Glass """Set up the output destination 11569f2ed77SSimon Glass 11669f2ed77SSimon Glass Once this is done, future calls to self.Out() will output to this 11769f2ed77SSimon Glass file. 11869f2ed77SSimon Glass 11969f2ed77SSimon Glass Args: 12069f2ed77SSimon Glass fname: Filename to send output to, or '-' for stdout 12169f2ed77SSimon Glass """ 12269f2ed77SSimon Glass if fname == '-': 12369f2ed77SSimon Glass self._outfile = sys.stdout 12469f2ed77SSimon Glass else: 12569f2ed77SSimon Glass self._outfile = open(fname, 'w') 12669f2ed77SSimon Glass 12769f2ed77SSimon Glass def Out(self, str): 12869f2ed77SSimon Glass """Output a string to the output file 12969f2ed77SSimon Glass 13069f2ed77SSimon Glass Args: 13169f2ed77SSimon Glass str: String to output 13269f2ed77SSimon Glass """ 13369f2ed77SSimon Glass self._outfile.write(str) 13469f2ed77SSimon Glass 13569f2ed77SSimon Glass def Buf(self, str): 13669f2ed77SSimon Glass """Buffer up a string to send later 13769f2ed77SSimon Glass 13869f2ed77SSimon Glass Args: 13969f2ed77SSimon Glass str: String to add to our 'buffer' list 14069f2ed77SSimon Glass """ 14169f2ed77SSimon Glass self._lines.append(str) 14269f2ed77SSimon Glass 14369f2ed77SSimon Glass def GetBuf(self): 14469f2ed77SSimon Glass """Get the contents of the output buffer, and clear it 14569f2ed77SSimon Glass 14669f2ed77SSimon Glass Returns: 14769f2ed77SSimon Glass The output buffer, which is then cleared for future use 14869f2ed77SSimon Glass """ 14969f2ed77SSimon Glass lines = self._lines 15069f2ed77SSimon Glass self._lines = [] 15169f2ed77SSimon Glass return lines 15269f2ed77SSimon Glass 15369f2ed77SSimon Glass def GetValue(self, type, value): 15469f2ed77SSimon Glass """Get a value as a C expression 15569f2ed77SSimon Glass 15669f2ed77SSimon Glass For integers this returns a byte-swapped (little-endian) hex string 15769f2ed77SSimon Glass For bytes this returns a hex string, e.g. 0x12 15869f2ed77SSimon Glass For strings this returns a literal string enclosed in quotes 15969f2ed77SSimon Glass For booleans this return 'true' 16069f2ed77SSimon Glass 16169f2ed77SSimon Glass Args: 16269f2ed77SSimon Glass type: Data type (fdt_util) 16369f2ed77SSimon Glass value: Data value, as a string of bytes 16469f2ed77SSimon Glass """ 165bc1dea36SSimon Glass if type == fdt.TYPE_INT: 16669f2ed77SSimon Glass return '%#x' % fdt_util.fdt32_to_cpu(value) 167bc1dea36SSimon Glass elif type == fdt.TYPE_BYTE: 16869f2ed77SSimon Glass return '%#x' % ord(value[0]) 169bc1dea36SSimon Glass elif type == fdt.TYPE_STRING: 17069f2ed77SSimon Glass return '"%s"' % value 171bc1dea36SSimon Glass elif type == fdt.TYPE_BOOL: 17269f2ed77SSimon Glass return 'true' 17369f2ed77SSimon Glass 17469f2ed77SSimon Glass def GetCompatName(self, node): 17569f2ed77SSimon Glass """Get a node's first compatible string as a C identifier 17669f2ed77SSimon Glass 17769f2ed77SSimon Glass Args: 17869f2ed77SSimon Glass node: Node object to check 17969f2ed77SSimon Glass Return: 18069f2ed77SSimon Glass C identifier for the first compatible string 18169f2ed77SSimon Glass """ 18269f2ed77SSimon Glass compat = node.props['compatible'].value 1832cce5866SSimon Glass aliases = [] 18469f2ed77SSimon Glass if type(compat) == list: 1852cce5866SSimon Glass compat, aliases = compat[0], compat[1:] 1862cce5866SSimon Glass return Conv_name_to_c(compat), [Conv_name_to_c(a) for a in aliases] 18769f2ed77SSimon Glass 18869f2ed77SSimon Glass def ScanDtb(self): 18969f2ed77SSimon Glass """Scan the device tree to obtain a tree of notes and properties 19069f2ed77SSimon Glass 19169f2ed77SSimon Glass Once this is done, self.fdt.GetRoot() can be called to obtain the 19269f2ed77SSimon Glass device tree root node, and progress from there. 19369f2ed77SSimon Glass """ 19499ed4a2eSSimon Glass self.fdt = fdt.FdtScan(self._dtb_fname) 19569f2ed77SSimon Glass 19655bc080eSPhilipp Tomsich def ScanNode(self, root): 19755bc080eSPhilipp Tomsich for node in root.subnodes: 19855bc080eSPhilipp Tomsich if 'compatible' in node.props: 19955bc080eSPhilipp Tomsich status = node.props.get('status') 200418355cbSSimon Glass if (not self._options.include_disabled and not status or 20155bc080eSPhilipp Tomsich status.value != 'disabled'): 20255bc080eSPhilipp Tomsich self._valid_nodes.append(node) 20355bc080eSPhilipp Tomsich phandle_prop = node.props.get('phandle') 20455bc080eSPhilipp Tomsich if phandle_prop: 20555bc080eSPhilipp Tomsich phandle = phandle_prop.GetPhandle() 20655bc080eSPhilipp Tomsich self._phandle_node[phandle] = node 20755bc080eSPhilipp Tomsich 20855bc080eSPhilipp Tomsich # recurse to handle any subnodes 20955bc080eSPhilipp Tomsich self.ScanNode(node); 21055bc080eSPhilipp Tomsich 21169f2ed77SSimon Glass def ScanTree(self): 21269f2ed77SSimon Glass """Scan the device tree for useful information 21369f2ed77SSimon Glass 21469f2ed77SSimon Glass This fills in the following properties: 21569f2ed77SSimon Glass _phandle_node: A dict of Nodes indexed by phandle (an integer) 21669f2ed77SSimon Glass _valid_nodes: A list of nodes we wish to consider include in the 21769f2ed77SSimon Glass platform data 21869f2ed77SSimon Glass """ 21969f2ed77SSimon Glass self._phandle_node = {} 22055bc080eSPhilipp Tomsich self._valid_nodes = [] 22155bc080eSPhilipp Tomsich return self.ScanNode(self.fdt.GetRoot()); 22255bc080eSPhilipp Tomsich 22369f2ed77SSimon Glass for node in self.fdt.GetRoot().subnodes: 22469f2ed77SSimon Glass if 'compatible' in node.props: 22569f2ed77SSimon Glass status = node.props.get('status') 226418355cbSSimon Glass if (not self._options.include_disabled and not status or 22769f2ed77SSimon Glass status.value != 'disabled'): 22869f2ed77SSimon Glass node_list.append(node) 22969f2ed77SSimon Glass phandle_prop = node.props.get('phandle') 23069f2ed77SSimon Glass if phandle_prop: 23169f2ed77SSimon Glass phandle = phandle_prop.GetPhandle() 23269f2ed77SSimon Glass self._phandle_node[phandle] = node 23369f2ed77SSimon Glass 23469f2ed77SSimon Glass self._valid_nodes = node_list 23569f2ed77SSimon Glass 23669f2ed77SSimon Glass def IsPhandle(self, prop): 23769f2ed77SSimon Glass """Check if a node contains phandles 23869f2ed77SSimon Glass 23969f2ed77SSimon Glass We have no reliable way of detecting whether a node uses a phandle 24069f2ed77SSimon Glass or not. As an interim measure, use a list of known property names. 24169f2ed77SSimon Glass 24269f2ed77SSimon Glass Args: 24369f2ed77SSimon Glass prop: Prop object to check 24469f2ed77SSimon Glass Return: 24569f2ed77SSimon Glass True if the object value contains phandles, else False 24669f2ed77SSimon Glass """ 24769f2ed77SSimon Glass if prop.name in ['clocks']: 24869f2ed77SSimon Glass return True 24969f2ed77SSimon Glass return False 25069f2ed77SSimon Glass 25169f2ed77SSimon Glass def ScanStructs(self): 25269f2ed77SSimon Glass """Scan the device tree building up the C structures we will use. 25369f2ed77SSimon Glass 25469f2ed77SSimon Glass Build a dict keyed by C struct name containing a dict of Prop 25569f2ed77SSimon Glass object for each struct field (keyed by property name). Where the 25669f2ed77SSimon Glass same struct appears multiple times, try to use the 'widest' 25769f2ed77SSimon Glass property, i.e. the one with a type which can express all others. 25869f2ed77SSimon Glass 25969f2ed77SSimon Glass Once the widest property is determined, all other properties are 26069f2ed77SSimon Glass updated to match that width. 26169f2ed77SSimon Glass """ 26269f2ed77SSimon Glass structs = {} 26369f2ed77SSimon Glass for node in self._valid_nodes: 2642cce5866SSimon Glass node_name, _ = self.GetCompatName(node) 26569f2ed77SSimon Glass fields = {} 26669f2ed77SSimon Glass 26769f2ed77SSimon Glass # Get a list of all the valid properties in this node. 2684ae6549fSPaul Burton for name, prop in node.props.items(): 26969f2ed77SSimon Glass if name not in PROP_IGNORE_LIST and name[0] != '#': 27069f2ed77SSimon Glass fields[name] = copy.deepcopy(prop) 27169f2ed77SSimon Glass 27269f2ed77SSimon Glass # If we've seen this node_name before, update the existing struct. 27369f2ed77SSimon Glass if node_name in structs: 27469f2ed77SSimon Glass struct = structs[node_name] 2754ae6549fSPaul Burton for name, prop in fields.items(): 27669f2ed77SSimon Glass oldprop = struct.get(name) 27769f2ed77SSimon Glass if oldprop: 27869f2ed77SSimon Glass oldprop.Widen(prop) 27969f2ed77SSimon Glass else: 28069f2ed77SSimon Glass struct[name] = prop 28169f2ed77SSimon Glass 28269f2ed77SSimon Glass # Otherwise store this as a new struct. 28369f2ed77SSimon Glass else: 28469f2ed77SSimon Glass structs[node_name] = fields 28569f2ed77SSimon Glass 28669f2ed77SSimon Glass upto = 0 28769f2ed77SSimon Glass for node in self._valid_nodes: 2882cce5866SSimon Glass node_name, _ = self.GetCompatName(node) 28969f2ed77SSimon Glass struct = structs[node_name] 2904ae6549fSPaul Burton for name, prop in node.props.items(): 29169f2ed77SSimon Glass if name not in PROP_IGNORE_LIST and name[0] != '#': 29269f2ed77SSimon Glass prop.Widen(struct[name]) 29369f2ed77SSimon Glass upto += 1 2942cce5866SSimon Glass 2952cce5866SSimon Glass struct_name, aliases = self.GetCompatName(node) 2962cce5866SSimon Glass for alias in aliases: 2972cce5866SSimon Glass self._aliases[alias] = struct_name 2982cce5866SSimon Glass 29969f2ed77SSimon Glass return structs 30069f2ed77SSimon Glass 301439c947fSSimon Glass def ScanPhandles(self): 302439c947fSSimon Glass """Figure out what phandles each node uses 303439c947fSSimon Glass 304439c947fSSimon Glass We need to be careful when outputing nodes that use phandles since 305439c947fSSimon Glass they must come after the declaration of the phandles in the C file. 306439c947fSSimon Glass Otherwise we get a compiler error since the phandle struct is not yet 307439c947fSSimon Glass declared. 308439c947fSSimon Glass 309439c947fSSimon Glass This function adds to each node a list of phandle nodes that the node 310439c947fSSimon Glass depends on. This allows us to output things in the right order. 311439c947fSSimon Glass """ 312439c947fSSimon Glass for node in self._valid_nodes: 313439c947fSSimon Glass node.phandles = set() 314439c947fSSimon Glass for pname, prop in node.props.items(): 315439c947fSSimon Glass if pname in PROP_IGNORE_LIST or pname[0] == '#': 316439c947fSSimon Glass continue 317439c947fSSimon Glass if type(prop.value) == list: 318439c947fSSimon Glass if self.IsPhandle(prop): 319439c947fSSimon Glass # Process the list as pairs of (phandle, id) 320439c947fSSimon Glass it = iter(prop.value) 321439c947fSSimon Glass for phandle_cell, id_cell in zip(it, it): 322439c947fSSimon Glass phandle = fdt_util.fdt32_to_cpu(phandle_cell) 323439c947fSSimon Glass id = fdt_util.fdt32_to_cpu(id_cell) 324439c947fSSimon Glass target_node = self._phandle_node[phandle] 325439c947fSSimon Glass node.phandles.add(target_node) 326439c947fSSimon Glass 327439c947fSSimon Glass 32869f2ed77SSimon Glass def GenerateStructs(self, structs): 32969f2ed77SSimon Glass """Generate struct defintions for the platform data 33069f2ed77SSimon Glass 33169f2ed77SSimon Glass This writes out the body of a header file consisting of structure 33269f2ed77SSimon Glass definitions for node in self._valid_nodes. See the documentation in 33369f2ed77SSimon Glass README.of-plat for more information. 33469f2ed77SSimon Glass """ 33569f2ed77SSimon Glass self.Out('#include <stdbool.h>\n') 33669f2ed77SSimon Glass self.Out('#include <libfdt.h>\n') 33769f2ed77SSimon Glass 33869f2ed77SSimon Glass # Output the struct definition 33969f2ed77SSimon Glass for name in sorted(structs): 34069f2ed77SSimon Glass self.Out('struct %s%s {\n' % (STRUCT_PREFIX, name)); 34169f2ed77SSimon Glass for pname in sorted(structs[name]): 34269f2ed77SSimon Glass prop = structs[name][pname] 34369f2ed77SSimon Glass if self.IsPhandle(prop): 34469f2ed77SSimon Glass # For phandles, include a reference to the target 34569f2ed77SSimon Glass self.Out('\t%s%s[%d]' % (TabTo(2, 'struct phandle_2_cell'), 34669f2ed77SSimon Glass Conv_name_to_c(prop.name), 34769f2ed77SSimon Glass len(prop.value) / 2)) 34869f2ed77SSimon Glass else: 34969f2ed77SSimon Glass ptype = TYPE_NAMES[prop.type] 35069f2ed77SSimon Glass self.Out('\t%s%s' % (TabTo(2, ptype), 35169f2ed77SSimon Glass Conv_name_to_c(prop.name))) 35269f2ed77SSimon Glass if type(prop.value) == list: 35369f2ed77SSimon Glass self.Out('[%d]' % len(prop.value)) 35469f2ed77SSimon Glass self.Out(';\n') 35569f2ed77SSimon Glass self.Out('};\n') 35669f2ed77SSimon Glass 3572cce5866SSimon Glass for alias, struct_name in self._aliases.iteritems(): 3582cce5866SSimon Glass self.Out('#define %s%s %s%s\n'% (STRUCT_PREFIX, alias, 3592cce5866SSimon Glass STRUCT_PREFIX, struct_name)) 3602cce5866SSimon Glass 36149eec8c7SSimon Glass def OutputNode(self, node): 36249eec8c7SSimon Glass """Output the C code for a node 36369f2ed77SSimon Glass 36449eec8c7SSimon Glass Args: 36549eec8c7SSimon Glass node: node to output 36669f2ed77SSimon Glass """ 3672cce5866SSimon Glass struct_name, _ = self.GetCompatName(node) 36869f2ed77SSimon Glass var_name = Conv_name_to_c(node.name) 36969f2ed77SSimon Glass self.Buf('static struct %s%s %s%s = {\n' % 37069f2ed77SSimon Glass (STRUCT_PREFIX, struct_name, VAL_PREFIX, var_name)) 3714ae6549fSPaul Burton for pname, prop in node.props.items(): 37269f2ed77SSimon Glass if pname in PROP_IGNORE_LIST or pname[0] == '#': 37369f2ed77SSimon Glass continue 37469f2ed77SSimon Glass ptype = TYPE_NAMES[prop.type] 37569f2ed77SSimon Glass member_name = Conv_name_to_c(prop.name) 37669f2ed77SSimon Glass self.Buf('\t%s= ' % TabTo(3, '.' + member_name)) 37769f2ed77SSimon Glass 37869f2ed77SSimon Glass # Special handling for lists 37969f2ed77SSimon Glass if type(prop.value) == list: 38069f2ed77SSimon Glass self.Buf('{') 38169f2ed77SSimon Glass vals = [] 38269f2ed77SSimon Glass # For phandles, output a reference to the platform data 38369f2ed77SSimon Glass # of the target node. 38469f2ed77SSimon Glass if self.IsPhandle(prop): 38569f2ed77SSimon Glass # Process the list as pairs of (phandle, id) 38669f2ed77SSimon Glass it = iter(prop.value) 38769f2ed77SSimon Glass for phandle_cell, id_cell in zip(it, it): 38869f2ed77SSimon Glass phandle = fdt_util.fdt32_to_cpu(phandle_cell) 38969f2ed77SSimon Glass id = fdt_util.fdt32_to_cpu(id_cell) 39069f2ed77SSimon Glass target_node = self._phandle_node[phandle] 39169f2ed77SSimon Glass name = Conv_name_to_c(target_node.name) 39269f2ed77SSimon Glass vals.append('{&%s%s, %d}' % (VAL_PREFIX, name, id)) 39369f2ed77SSimon Glass else: 39469f2ed77SSimon Glass for val in prop.value: 39569f2ed77SSimon Glass vals.append(self.GetValue(prop.type, val)) 39669f2ed77SSimon Glass self.Buf(', '.join(vals)) 39769f2ed77SSimon Glass self.Buf('}') 39869f2ed77SSimon Glass else: 39969f2ed77SSimon Glass self.Buf(self.GetValue(prop.type, prop.value)) 40069f2ed77SSimon Glass self.Buf(',\n') 40169f2ed77SSimon Glass self.Buf('};\n') 40269f2ed77SSimon Glass 40369f2ed77SSimon Glass # Add a device declaration 40469f2ed77SSimon Glass self.Buf('U_BOOT_DEVICE(%s) = {\n' % var_name) 40569f2ed77SSimon Glass self.Buf('\t.name\t\t= "%s",\n' % struct_name) 40669f2ed77SSimon Glass self.Buf('\t.platdata\t= &%s%s,\n' % (VAL_PREFIX, var_name)) 4079fa28190SSimon Glass self.Buf('\t.platdata_size\t= sizeof(%s%s),\n' % 4089fa28190SSimon Glass (VAL_PREFIX, var_name)) 40969f2ed77SSimon Glass self.Buf('};\n') 41069f2ed77SSimon Glass self.Buf('\n') 41169f2ed77SSimon Glass 412439c947fSSimon Glass self.Out(''.join(self.GetBuf())) 413439c947fSSimon Glass 41449eec8c7SSimon Glass def GenerateTables(self): 41549eec8c7SSimon Glass """Generate device defintions for the platform data 41649eec8c7SSimon Glass 41749eec8c7SSimon Glass This writes out C platform data initialisation data and 4182cce5866SSimon Glass U_BOOT_DEVICE() declarations for each valid node. Where a node has 4192cce5866SSimon Glass multiple compatible strings, a #define is used to make them equivalent. 4202cce5866SSimon Glass 4212cce5866SSimon Glass See the documentation in doc/driver-model/of-plat.txt for more 4222cce5866SSimon Glass information. 42349eec8c7SSimon Glass """ 42449eec8c7SSimon Glass self.Out('#include <common.h>\n') 42549eec8c7SSimon Glass self.Out('#include <dm.h>\n') 42649eec8c7SSimon Glass self.Out('#include <dt-structs.h>\n') 42749eec8c7SSimon Glass self.Out('\n') 428439c947fSSimon Glass nodes_to_output = list(self._valid_nodes) 429439c947fSSimon Glass 430439c947fSSimon Glass # Keep outputing nodes until there is none left 431439c947fSSimon Glass while nodes_to_output: 432439c947fSSimon Glass node = nodes_to_output[0] 433439c947fSSimon Glass # Output all the node's dependencies first 434439c947fSSimon Glass for req_node in node.phandles: 435439c947fSSimon Glass if req_node in nodes_to_output: 436439c947fSSimon Glass self.OutputNode(req_node) 437439c947fSSimon Glass nodes_to_output.remove(req_node) 43849eec8c7SSimon Glass self.OutputNode(node) 439439c947fSSimon Glass nodes_to_output.remove(node) 44069f2ed77SSimon Glass 44169f2ed77SSimon Glass 44269f2ed77SSimon Glassif __name__ != "__main__": 44369f2ed77SSimon Glass pass 44469f2ed77SSimon Glass 44569f2ed77SSimon Glassparser = OptionParser() 44669f2ed77SSimon Glassparser.add_option('-d', '--dtb-file', action='store', 44769f2ed77SSimon Glass help='Specify the .dtb input file') 44869f2ed77SSimon Glassparser.add_option('--include-disabled', action='store_true', 44969f2ed77SSimon Glass help='Include disabled nodes') 45069f2ed77SSimon Glassparser.add_option('-o', '--output', action='store', default='-', 45169f2ed77SSimon Glass help='Select output filename') 45269f2ed77SSimon Glass(options, args) = parser.parse_args() 45369f2ed77SSimon Glass 45469f2ed77SSimon Glassif not args: 45569f2ed77SSimon Glass raise ValueError('Please specify a command: struct, platdata') 45669f2ed77SSimon Glass 45769f2ed77SSimon Glassplat = DtbPlatdata(options.dtb_file, options) 45869f2ed77SSimon Glassplat.ScanDtb() 45969f2ed77SSimon Glassplat.ScanTree() 46069f2ed77SSimon Glassplat.SetupOutput(options.output) 46169f2ed77SSimon Glassstructs = plat.ScanStructs() 462439c947fSSimon Glassplat.ScanPhandles() 46369f2ed77SSimon Glass 46469f2ed77SSimon Glassfor cmd in args[0].split(','): 46569f2ed77SSimon Glass if cmd == 'struct': 46669f2ed77SSimon Glass plat.GenerateStructs(structs) 46769f2ed77SSimon Glass elif cmd == 'platdata': 46869f2ed77SSimon Glass plat.GenerateTables() 46969f2ed77SSimon Glass else: 47069f2ed77SSimon Glass raise ValueError("Unknown command '%s': (use: struct, platdata)" % cmd) 471