xref: /rk3399_rockchip-uboot/tools/dtoc/dtb_platdata.py (revision 12a972efaa3df3275d89be656f68daf89c9d80c5)
17581c01aSSimon Glass#!/usr/bin/python
27581c01aSSimon Glass#
37581c01aSSimon Glass# Copyright (C) 2017 Google, Inc
47581c01aSSimon Glass# Written by Simon Glass <sjg@chromium.org>
57581c01aSSimon Glass#
67581c01aSSimon Glass# SPDX-License-Identifier:	GPL-2.0+
77581c01aSSimon Glass#
87581c01aSSimon Glass
92be282caSSimon Glass"""Device tree to platform data class
102be282caSSimon Glass
112be282caSSimon GlassThis supports converting device tree data to C structures definitions and
122be282caSSimon Glassstatic data.
132be282caSSimon Glass"""
142be282caSSimon Glass
157581c01aSSimon Glassimport copy
162be282caSSimon Glassimport sys
177581c01aSSimon Glass
187581c01aSSimon Glassimport fdt
197581c01aSSimon Glassimport fdt_util
207581c01aSSimon Glass
217581c01aSSimon Glass# When we see these properties we ignore them - i.e. do not create a structure member
227581c01aSSimon GlassPROP_IGNORE_LIST = [
237581c01aSSimon Glass    '#address-cells',
247581c01aSSimon Glass    '#gpio-cells',
257581c01aSSimon Glass    '#size-cells',
267581c01aSSimon Glass    'compatible',
277581c01aSSimon Glass    'linux,phandle',
287581c01aSSimon Glass    "status",
297581c01aSSimon Glass    'phandle',
307581c01aSSimon Glass    'u-boot,dm-pre-reloc',
317581c01aSSimon Glass    'u-boot,dm-tpl',
327581c01aSSimon Glass    'u-boot,dm-spl',
337581c01aSSimon Glass]
347581c01aSSimon Glass
357581c01aSSimon Glass# C type declarations for the tyues we support
367581c01aSSimon GlassTYPE_NAMES = {
377581c01aSSimon Glass    fdt.TYPE_INT: 'fdt32_t',
387581c01aSSimon Glass    fdt.TYPE_BYTE: 'unsigned char',
397581c01aSSimon Glass    fdt.TYPE_STRING: 'const char *',
407581c01aSSimon Glass    fdt.TYPE_BOOL: 'bool',
41ef2715f4SSimon Glass    fdt.TYPE_INT64: 'fdt64_t',
422be282caSSimon Glass}
437581c01aSSimon Glass
447581c01aSSimon GlassSTRUCT_PREFIX = 'dtd_'
457581c01aSSimon GlassVAL_PREFIX = 'dtv_'
467581c01aSSimon Glass
472be282caSSimon Glassdef conv_name_to_c(name):
487581c01aSSimon Glass    """Convert a device-tree name to a C identifier
497581c01aSSimon Glass
5030107b08SSimon Glass    This uses multiple replace() calls instead of re.sub() since it is faster
5130107b08SSimon Glass    (400ms for 1m calls versus 1000ms for the 're' version).
5230107b08SSimon Glass
537581c01aSSimon Glass    Args:
547581c01aSSimon Glass        name:   Name to convert
557581c01aSSimon Glass    Return:
567581c01aSSimon Glass        String containing the C version of this name
577581c01aSSimon Glass    """
582be282caSSimon Glass    new = name.replace('@', '_at_')
592be282caSSimon Glass    new = new.replace('-', '_')
602be282caSSimon Glass    new = new.replace(',', '_')
612be282caSSimon Glass    new = new.replace('.', '_')
622be282caSSimon Glass    return new
637581c01aSSimon Glass
642be282caSSimon Glassdef tab_to(num_tabs, line):
652be282caSSimon Glass    """Append tabs to a line of text to reach a tab stop.
667581c01aSSimon Glass
672be282caSSimon Glass    Args:
682be282caSSimon Glass        num_tabs: Tab stop to obtain (0 = column 0, 1 = column 8, etc.)
692be282caSSimon Glass        line: Line of text to append to
702be282caSSimon Glass
712be282caSSimon Glass    Returns:
722be282caSSimon Glass        line with the correct number of tabs appeneded. If the line already
732be282caSSimon Glass        extends past that tab stop then a single space is appended.
742be282caSSimon Glass    """
752be282caSSimon Glass    if len(line) >= num_tabs * 8:
762be282caSSimon Glass        return line + ' '
772be282caSSimon Glass    return line + '\t' * (num_tabs - len(line) // 8)
782be282caSSimon Glass
7956e0bbe0SSimon Glassdef get_value(ftype, value):
8056e0bbe0SSimon Glass    """Get a value as a C expression
8156e0bbe0SSimon Glass
8256e0bbe0SSimon Glass    For integers this returns a byte-swapped (little-endian) hex string
8356e0bbe0SSimon Glass    For bytes this returns a hex string, e.g. 0x12
8456e0bbe0SSimon Glass    For strings this returns a literal string enclosed in quotes
8556e0bbe0SSimon Glass    For booleans this return 'true'
8656e0bbe0SSimon Glass
8756e0bbe0SSimon Glass    Args:
8856e0bbe0SSimon Glass        type: Data type (fdt_util)
8956e0bbe0SSimon Glass        value: Data value, as a string of bytes
9056e0bbe0SSimon Glass    """
9156e0bbe0SSimon Glass    if ftype == fdt.TYPE_INT:
9256e0bbe0SSimon Glass        return '%#x' % fdt_util.fdt32_to_cpu(value)
9356e0bbe0SSimon Glass    elif ftype == fdt.TYPE_BYTE:
9456e0bbe0SSimon Glass        return '%#x' % ord(value[0])
9556e0bbe0SSimon Glass    elif ftype == fdt.TYPE_STRING:
9656e0bbe0SSimon Glass        return '"%s"' % value
9756e0bbe0SSimon Glass    elif ftype == fdt.TYPE_BOOL:
9856e0bbe0SSimon Glass        return 'true'
99ef2715f4SSimon Glass    elif ftype == fdt.TYPE_INT64:
100ef2715f4SSimon Glass        return '%#x' % value
10156e0bbe0SSimon Glass
10256e0bbe0SSimon Glassdef get_compat_name(node):
10356e0bbe0SSimon Glass    """Get a node's first compatible string as a C identifier
10456e0bbe0SSimon Glass
10556e0bbe0SSimon Glass    Args:
10656e0bbe0SSimon Glass        node: Node object to check
10756e0bbe0SSimon Glass    Return:
10856e0bbe0SSimon Glass        Tuple:
10956e0bbe0SSimon Glass            C identifier for the first compatible string
11056e0bbe0SSimon Glass            List of C identifiers for all the other compatible strings
11156e0bbe0SSimon Glass                (possibly empty)
11256e0bbe0SSimon Glass    """
11356e0bbe0SSimon Glass    compat = node.props['compatible'].value
11456e0bbe0SSimon Glass    aliases = []
11556e0bbe0SSimon Glass    if isinstance(compat, list):
11656e0bbe0SSimon Glass        compat, aliases = compat[0], compat[1:]
11756e0bbe0SSimon Glass    return conv_name_to_c(compat), [conv_name_to_c(a) for a in aliases]
11856e0bbe0SSimon Glass
11956e0bbe0SSimon Glassdef is_phandle(prop):
12056e0bbe0SSimon Glass    """Check if a node contains phandles
12156e0bbe0SSimon Glass
12256e0bbe0SSimon Glass    We have no reliable way of detecting whether a node uses a phandle
12356e0bbe0SSimon Glass    or not. As an interim measure, use a list of known property names.
12456e0bbe0SSimon Glass
12556e0bbe0SSimon Glass    Args:
12656e0bbe0SSimon Glass        prop: Prop object to check
12756e0bbe0SSimon Glass    Return:
12856e0bbe0SSimon Glass        True if the object value contains phandles, else False
12956e0bbe0SSimon Glass    """
13056e0bbe0SSimon Glass    if prop.name in ['clocks']:
13156e0bbe0SSimon Glass        return True
13256e0bbe0SSimon Glass    return False
13356e0bbe0SSimon Glass
13456e0bbe0SSimon Glass
1352be282caSSimon Glassclass DtbPlatdata(object):
1367581c01aSSimon Glass    """Provide a means to convert device tree binary data to platform data
1377581c01aSSimon Glass
1387581c01aSSimon Glass    The output of this process is C structures which can be used in space-
1397581c01aSSimon Glass    constrained encvironments where the ~3KB code overhead of device tree
1407581c01aSSimon Glass    code is not affordable.
1417581c01aSSimon Glass
1427581c01aSSimon Glass    Properties:
1432be282caSSimon Glass        _fdt: Fdt object, referencing the device tree
1447581c01aSSimon Glass        _dtb_fname: Filename of the input device tree binary file
1457581c01aSSimon Glass        _valid_nodes: A list of Node object with compatible strings
146e36024b0SSimon Glass        _include_disabled: true to include nodes marked status = "disabled"
1472be282caSSimon Glass        _phandle_nodes: A dict of nodes indexed by phandle number (1, 2...)
1487581c01aSSimon Glass        _outfile: The current output file (sys.stdout or a real file)
1497581c01aSSimon Glass        _lines: Stashed list of output lines for outputting in the future
1502be282caSSimon Glass        _phandle_nodes: A dict of Nodes indexed by phandle (an integer)
1517581c01aSSimon Glass    """
152e36024b0SSimon Glass    def __init__(self, dtb_fname, include_disabled):
1532be282caSSimon Glass        self._fdt = None
1547581c01aSSimon Glass        self._dtb_fname = dtb_fname
1557581c01aSSimon Glass        self._valid_nodes = None
156e36024b0SSimon Glass        self._include_disabled = include_disabled
1572be282caSSimon Glass        self._phandle_nodes = {}
1587581c01aSSimon Glass        self._outfile = None
1597581c01aSSimon Glass        self._lines = []
1607581c01aSSimon Glass        self._aliases = {}
1617581c01aSSimon Glass
1622be282caSSimon Glass    def setup_output(self, fname):
1637581c01aSSimon Glass        """Set up the output destination
1647581c01aSSimon Glass
1652be282caSSimon Glass        Once this is done, future calls to self.out() will output to this
1667581c01aSSimon Glass        file.
1677581c01aSSimon Glass
1687581c01aSSimon Glass        Args:
1697581c01aSSimon Glass            fname: Filename to send output to, or '-' for stdout
1707581c01aSSimon Glass        """
1717581c01aSSimon Glass        if fname == '-':
1727581c01aSSimon Glass            self._outfile = sys.stdout
1737581c01aSSimon Glass        else:
1747581c01aSSimon Glass            self._outfile = open(fname, 'w')
1757581c01aSSimon Glass
1762be282caSSimon Glass    def out(self, line):
1777581c01aSSimon Glass        """Output a string to the output file
1787581c01aSSimon Glass
1797581c01aSSimon Glass        Args:
1802be282caSSimon Glass            line: String to output
1817581c01aSSimon Glass        """
1822be282caSSimon Glass        self._outfile.write(line)
1837581c01aSSimon Glass
1842be282caSSimon Glass    def buf(self, line):
1857581c01aSSimon Glass        """Buffer up a string to send later
1867581c01aSSimon Glass
1877581c01aSSimon Glass        Args:
1882be282caSSimon Glass            line: String to add to our 'buffer' list
1897581c01aSSimon Glass        """
1902be282caSSimon Glass        self._lines.append(line)
1917581c01aSSimon Glass
1922be282caSSimon Glass    def get_buf(self):
1937581c01aSSimon Glass        """Get the contents of the output buffer, and clear it
1947581c01aSSimon Glass
1957581c01aSSimon Glass        Returns:
1967581c01aSSimon Glass            The output buffer, which is then cleared for future use
1977581c01aSSimon Glass        """
1987581c01aSSimon Glass        lines = self._lines
1997581c01aSSimon Glass        self._lines = []
2007581c01aSSimon Glass        return lines
2017581c01aSSimon Glass
2022be282caSSimon Glass    def scan_dtb(self):
203f1a7ba1dSAnatolij Gustschin        """Scan the device tree to obtain a tree of nodes and properties
2047581c01aSSimon Glass
2052be282caSSimon Glass        Once this is done, self._fdt.GetRoot() can be called to obtain the
2067581c01aSSimon Glass        device tree root node, and progress from there.
2077581c01aSSimon Glass        """
2082be282caSSimon Glass        self._fdt = fdt.FdtScan(self._dtb_fname)
2097581c01aSSimon Glass
2102be282caSSimon Glass    def scan_node(self, root):
2112be282caSSimon Glass        """Scan a node and subnodes to build a tree of node and phandle info
2122be282caSSimon Glass
2132be282caSSimon Glass        This adds each node to self._valid_nodes and each phandle to
2142be282caSSimon Glass        self._phandle_nodes.
2152be282caSSimon Glass
2162be282caSSimon Glass        Args:
2172be282caSSimon Glass            root: Root node for scan
2182be282caSSimon Glass        """
2197581c01aSSimon Glass        for node in root.subnodes:
2207581c01aSSimon Glass            if 'compatible' in node.props:
2217581c01aSSimon Glass                status = node.props.get('status')
222e36024b0SSimon Glass                if (not self._include_disabled and not status or
2237581c01aSSimon Glass                        status.value != 'disabled'):
2247581c01aSSimon Glass                    self._valid_nodes.append(node)
2257581c01aSSimon Glass                    phandle_prop = node.props.get('phandle')
2267581c01aSSimon Glass                    if phandle_prop:
2277581c01aSSimon Glass                        phandle = phandle_prop.GetPhandle()
2282be282caSSimon Glass                        self._phandle_nodes[phandle] = node
2297581c01aSSimon Glass
2307581c01aSSimon Glass            # recurse to handle any subnodes
2312be282caSSimon Glass            self.scan_node(node)
2327581c01aSSimon Glass
2332be282caSSimon Glass    def scan_tree(self):
2347581c01aSSimon Glass        """Scan the device tree for useful information
2357581c01aSSimon Glass
2367581c01aSSimon Glass        This fills in the following properties:
2372be282caSSimon Glass            _phandle_nodes: A dict of Nodes indexed by phandle (an integer)
2387581c01aSSimon Glass            _valid_nodes: A list of nodes we wish to consider include in the
2397581c01aSSimon Glass                platform data
2407581c01aSSimon Glass        """
2412be282caSSimon Glass        self._phandle_nodes = {}
2427581c01aSSimon Glass        self._valid_nodes = []
2432be282caSSimon Glass        return self.scan_node(self._fdt.GetRoot())
2447581c01aSSimon Glass
2452be282caSSimon Glass    def scan_structs(self):
2467581c01aSSimon Glass        """Scan the device tree building up the C structures we will use.
2477581c01aSSimon Glass
2487581c01aSSimon Glass        Build a dict keyed by C struct name containing a dict of Prop
2497581c01aSSimon Glass        object for each struct field (keyed by property name). Where the
2507581c01aSSimon Glass        same struct appears multiple times, try to use the 'widest'
2517581c01aSSimon Glass        property, i.e. the one with a type which can express all others.
2527581c01aSSimon Glass
2537581c01aSSimon Glass        Once the widest property is determined, all other properties are
2547581c01aSSimon Glass        updated to match that width.
2557581c01aSSimon Glass        """
2567581c01aSSimon Glass        structs = {}
2577581c01aSSimon Glass        for node in self._valid_nodes:
25856e0bbe0SSimon Glass            node_name, _ = get_compat_name(node)
2597581c01aSSimon Glass            fields = {}
2607581c01aSSimon Glass
2617581c01aSSimon Glass            # Get a list of all the valid properties in this node.
2627581c01aSSimon Glass            for name, prop in node.props.items():
2637581c01aSSimon Glass                if name not in PROP_IGNORE_LIST and name[0] != '#':
2647581c01aSSimon Glass                    fields[name] = copy.deepcopy(prop)
2657581c01aSSimon Glass
2667581c01aSSimon Glass            # If we've seen this node_name before, update the existing struct.
2677581c01aSSimon Glass            if node_name in structs:
2687581c01aSSimon Glass                struct = structs[node_name]
2697581c01aSSimon Glass                for name, prop in fields.items():
2707581c01aSSimon Glass                    oldprop = struct.get(name)
2717581c01aSSimon Glass                    if oldprop:
2727581c01aSSimon Glass                        oldprop.Widen(prop)
2737581c01aSSimon Glass                    else:
2747581c01aSSimon Glass                        struct[name] = prop
2757581c01aSSimon Glass
2767581c01aSSimon Glass            # Otherwise store this as a new struct.
2777581c01aSSimon Glass            else:
2787581c01aSSimon Glass                structs[node_name] = fields
2797581c01aSSimon Glass
2807581c01aSSimon Glass        upto = 0
2817581c01aSSimon Glass        for node in self._valid_nodes:
28256e0bbe0SSimon Glass            node_name, _ = get_compat_name(node)
2837581c01aSSimon Glass            struct = structs[node_name]
2847581c01aSSimon Glass            for name, prop in node.props.items():
2857581c01aSSimon Glass                if name not in PROP_IGNORE_LIST and name[0] != '#':
2867581c01aSSimon Glass                    prop.Widen(struct[name])
2877581c01aSSimon Glass            upto += 1
2887581c01aSSimon Glass
28956e0bbe0SSimon Glass            struct_name, aliases = get_compat_name(node)
2907581c01aSSimon Glass            for alias in aliases:
2917581c01aSSimon Glass                self._aliases[alias] = struct_name
2927581c01aSSimon Glass
2937581c01aSSimon Glass        return structs
2947581c01aSSimon Glass
2952be282caSSimon Glass    def scan_phandles(self):
2967581c01aSSimon Glass        """Figure out what phandles each node uses
2977581c01aSSimon Glass
2987581c01aSSimon Glass        We need to be careful when outputing nodes that use phandles since
2997581c01aSSimon Glass        they must come after the declaration of the phandles in the C file.
3007581c01aSSimon Glass        Otherwise we get a compiler error since the phandle struct is not yet
3017581c01aSSimon Glass        declared.
3027581c01aSSimon Glass
3037581c01aSSimon Glass        This function adds to each node a list of phandle nodes that the node
3047581c01aSSimon Glass        depends on. This allows us to output things in the right order.
3057581c01aSSimon Glass        """
3067581c01aSSimon Glass        for node in self._valid_nodes:
3077581c01aSSimon Glass            node.phandles = set()
3087581c01aSSimon Glass            for pname, prop in node.props.items():
3097581c01aSSimon Glass                if pname in PROP_IGNORE_LIST or pname[0] == '#':
3107581c01aSSimon Glass                    continue
3112be282caSSimon Glass                if isinstance(prop.value, list):
31256e0bbe0SSimon Glass                    if is_phandle(prop):
3137581c01aSSimon Glass                        # Process the list as pairs of (phandle, id)
3142be282caSSimon Glass                        value_it = iter(prop.value)
3152be282caSSimon Glass                        for phandle_cell, _ in zip(value_it, value_it):
3167581c01aSSimon Glass                            phandle = fdt_util.fdt32_to_cpu(phandle_cell)
3172be282caSSimon Glass                            target_node = self._phandle_nodes[phandle]
3187581c01aSSimon Glass                            node.phandles.add(target_node)
3197581c01aSSimon Glass
3207581c01aSSimon Glass
3212be282caSSimon Glass    def generate_structs(self, structs):
3227581c01aSSimon Glass        """Generate struct defintions for the platform data
3237581c01aSSimon Glass
3247581c01aSSimon Glass        This writes out the body of a header file consisting of structure
3257581c01aSSimon Glass        definitions for node in self._valid_nodes. See the documentation in
3267581c01aSSimon Glass        README.of-plat for more information.
3277581c01aSSimon Glass        """
3282be282caSSimon Glass        self.out('#include <stdbool.h>\n')
3292be282caSSimon Glass        self.out('#include <libfdt.h>\n')
3307581c01aSSimon Glass
3317581c01aSSimon Glass        # Output the struct definition
3327581c01aSSimon Glass        for name in sorted(structs):
3332be282caSSimon Glass            self.out('struct %s%s {\n' % (STRUCT_PREFIX, name))
3347581c01aSSimon Glass            for pname in sorted(structs[name]):
3357581c01aSSimon Glass                prop = structs[name][pname]
33656e0bbe0SSimon Glass                if is_phandle(prop):
3377581c01aSSimon Glass                    # For phandles, include a reference to the target
3382be282caSSimon Glass                    self.out('\t%s%s[%d]' % (tab_to(2, 'struct phandle_2_cell'),
3392be282caSSimon Glass                                             conv_name_to_c(prop.name),
3407581c01aSSimon Glass                                             len(prop.value) / 2))
3417581c01aSSimon Glass                else:
3427581c01aSSimon Glass                    ptype = TYPE_NAMES[prop.type]
3432be282caSSimon Glass                    self.out('\t%s%s' % (tab_to(2, ptype),
3442be282caSSimon Glass                                         conv_name_to_c(prop.name)))
3452be282caSSimon Glass                    if isinstance(prop.value, list):
3462be282caSSimon Glass                        self.out('[%d]' % len(prop.value))
3472be282caSSimon Glass                self.out(';\n')
3482be282caSSimon Glass            self.out('};\n')
3497581c01aSSimon Glass
3507581c01aSSimon Glass        for alias, struct_name in self._aliases.iteritems():
3512be282caSSimon Glass            self.out('#define %s%s %s%s\n'% (STRUCT_PREFIX, alias,
3527581c01aSSimon Glass                                             STRUCT_PREFIX, struct_name))
3537581c01aSSimon Glass
3542be282caSSimon Glass    def output_node(self, node):
3557581c01aSSimon Glass        """Output the C code for a node
3567581c01aSSimon Glass
3577581c01aSSimon Glass        Args:
3587581c01aSSimon Glass            node: node to output
3597581c01aSSimon Glass        """
36056e0bbe0SSimon Glass        struct_name, _ = get_compat_name(node)
3612be282caSSimon Glass        var_name = conv_name_to_c(node.name)
3622be282caSSimon Glass        self.buf('static struct %s%s %s%s = {\n' %
3637581c01aSSimon Glass                 (STRUCT_PREFIX, struct_name, VAL_PREFIX, var_name))
3647581c01aSSimon Glass        for pname, prop in node.props.items():
3657581c01aSSimon Glass            if pname in PROP_IGNORE_LIST or pname[0] == '#':
3667581c01aSSimon Glass                continue
3672be282caSSimon Glass            member_name = conv_name_to_c(prop.name)
3682be282caSSimon Glass            self.buf('\t%s= ' % tab_to(3, '.' + member_name))
3697581c01aSSimon Glass
3707581c01aSSimon Glass            # Special handling for lists
3712be282caSSimon Glass            if isinstance(prop.value, list):
3722be282caSSimon Glass                self.buf('{')
3737581c01aSSimon Glass                vals = []
3747581c01aSSimon Glass                # For phandles, output a reference to the platform data
3757581c01aSSimon Glass                # of the target node.
37656e0bbe0SSimon Glass                if is_phandle(prop):
3777581c01aSSimon Glass                    # Process the list as pairs of (phandle, id)
3782be282caSSimon Glass                    value_it = iter(prop.value)
3792be282caSSimon Glass                    for phandle_cell, id_cell in zip(value_it, value_it):
3807581c01aSSimon Glass                        phandle = fdt_util.fdt32_to_cpu(phandle_cell)
3812be282caSSimon Glass                        id_num = fdt_util.fdt32_to_cpu(id_cell)
3822be282caSSimon Glass                        target_node = self._phandle_nodes[phandle]
3832be282caSSimon Glass                        name = conv_name_to_c(target_node.name)
3842be282caSSimon Glass                        vals.append('{&%s%s, %d}' % (VAL_PREFIX, name, id_num))
3857581c01aSSimon Glass                else:
3867581c01aSSimon Glass                    for val in prop.value:
38756e0bbe0SSimon Glass                        vals.append(get_value(prop.type, val))
388*12a972efSSimon Glass
389*12a972efSSimon Glass                # Put 8 values per line to avoid very long lines.
390*12a972efSSimon Glass                for i in xrange(0, len(vals), 8):
391*12a972efSSimon Glass                    if i:
392*12a972efSSimon Glass                        self.buf(',\n\t\t')
393*12a972efSSimon Glass                    self.buf(', '.join(vals[i:i + 8]))
3942be282caSSimon Glass                self.buf('}')
3957581c01aSSimon Glass            else:
39656e0bbe0SSimon Glass                self.buf(get_value(prop.type, prop.value))
3972be282caSSimon Glass            self.buf(',\n')
3982be282caSSimon Glass        self.buf('};\n')
3997581c01aSSimon Glass
4007581c01aSSimon Glass        # Add a device declaration
4012be282caSSimon Glass        self.buf('U_BOOT_DEVICE(%s) = {\n' % var_name)
4022be282caSSimon Glass        self.buf('\t.name\t\t= "%s",\n' % struct_name)
4032be282caSSimon Glass        self.buf('\t.platdata\t= &%s%s,\n' % (VAL_PREFIX, var_name))
4042be282caSSimon Glass        self.buf('\t.platdata_size\t= sizeof(%s%s),\n' % (VAL_PREFIX, var_name))
4052be282caSSimon Glass        self.buf('};\n')
4062be282caSSimon Glass        self.buf('\n')
4077581c01aSSimon Glass
4082be282caSSimon Glass        self.out(''.join(self.get_buf()))
4097581c01aSSimon Glass
4102be282caSSimon Glass    def generate_tables(self):
4117581c01aSSimon Glass        """Generate device defintions for the platform data
4127581c01aSSimon Glass
4137581c01aSSimon Glass        This writes out C platform data initialisation data and
4147581c01aSSimon Glass        U_BOOT_DEVICE() declarations for each valid node. Where a node has
4157581c01aSSimon Glass        multiple compatible strings, a #define is used to make them equivalent.
4167581c01aSSimon Glass
4177581c01aSSimon Glass        See the documentation in doc/driver-model/of-plat.txt for more
4187581c01aSSimon Glass        information.
4197581c01aSSimon Glass        """
4202be282caSSimon Glass        self.out('#include <common.h>\n')
4212be282caSSimon Glass        self.out('#include <dm.h>\n')
4222be282caSSimon Glass        self.out('#include <dt-structs.h>\n')
4232be282caSSimon Glass        self.out('\n')
4247581c01aSSimon Glass        nodes_to_output = list(self._valid_nodes)
4257581c01aSSimon Glass
4267581c01aSSimon Glass        # Keep outputing nodes until there is none left
4277581c01aSSimon Glass        while nodes_to_output:
4287581c01aSSimon Glass            node = nodes_to_output[0]
4297581c01aSSimon Glass            # Output all the node's dependencies first
4307581c01aSSimon Glass            for req_node in node.phandles:
4317581c01aSSimon Glass                if req_node in nodes_to_output:
4322be282caSSimon Glass                    self.output_node(req_node)
4337581c01aSSimon Glass                    nodes_to_output.remove(req_node)
4342be282caSSimon Glass            self.output_node(node)
4357581c01aSSimon Glass            nodes_to_output.remove(node)
436fa0ea5b0SSimon Glass
437fa0ea5b0SSimon Glass
438fa0ea5b0SSimon Glassdef run_steps(args, dtb_file, include_disabled, output):
439fa0ea5b0SSimon Glass    """Run all the steps of the dtoc tool
440fa0ea5b0SSimon Glass
441fa0ea5b0SSimon Glass    Args:
442fa0ea5b0SSimon Glass        args: List of non-option arguments provided to the problem
443fa0ea5b0SSimon Glass        dtb_file: Filename of dtb file to process
444fa0ea5b0SSimon Glass        include_disabled: True to include disabled nodes
445fa0ea5b0SSimon Glass        output: Name of output file
446fa0ea5b0SSimon Glass    """
447fa0ea5b0SSimon Glass    if not args:
448fa0ea5b0SSimon Glass        raise ValueError('Please specify a command: struct, platdata')
449fa0ea5b0SSimon Glass
450fa0ea5b0SSimon Glass    plat = DtbPlatdata(dtb_file, include_disabled)
451fa0ea5b0SSimon Glass    plat.scan_dtb()
452fa0ea5b0SSimon Glass    plat.scan_tree()
453fa0ea5b0SSimon Glass    plat.setup_output(output)
454fa0ea5b0SSimon Glass    structs = plat.scan_structs()
455fa0ea5b0SSimon Glass    plat.scan_phandles()
456fa0ea5b0SSimon Glass
457fa0ea5b0SSimon Glass    for cmd in args[0].split(','):
458fa0ea5b0SSimon Glass        if cmd == 'struct':
459fa0ea5b0SSimon Glass            plat.generate_structs(structs)
460fa0ea5b0SSimon Glass        elif cmd == 'platdata':
461fa0ea5b0SSimon Glass            plat.generate_tables()
462fa0ea5b0SSimon Glass        else:
463fa0ea5b0SSimon Glass            raise ValueError("Unknown command '%s': (use: struct, platdata)" %
464fa0ea5b0SSimon Glass                             cmd)
465