xref: /rk3399_rockchip-uboot/tools/dtoc/dtoc.py (revision 2cce586651bbeb0489c6cc6f04489f65bd039b9e)
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