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