blob: 46e2725a86c5cb7473554f2380c57b7f7353a9a5 [file] [log] [blame]
Simon Glass7581c012017-06-18 22:08:58 -06001#!/usr/bin/python
Tom Rini83d290c2018-05-06 17:58:06 -04002# SPDX-License-Identifier: GPL-2.0+
Simon Glass7581c012017-06-18 22:08:58 -06003#
4# Copyright (C) 2017 Google, Inc
5# Written by Simon Glass <sjg@chromium.org>
6#
Simon Glass7581c012017-06-18 22:08:58 -06007
Simon Glass2be282c2017-06-18 22:08:59 -06008"""Device tree to platform data class
9
10This supports converting device tree data to C structures definitions and
11static data.
Simon Glass9b330382020-11-08 20:36:21 -070012
13See doc/driver-model/of-plat.rst for more informaiton
Simon Glass2be282c2017-06-18 22:08:59 -060014"""
15
Simon Glass8fed2eb2017-08-29 14:15:55 -060016import collections
Simon Glass7581c012017-06-18 22:08:58 -060017import copy
Simon Glassbe44f272020-12-28 20:34:51 -070018from enum import IntEnum
Walter Lozanodac82282020-07-03 08:07:17 -030019import os
20import re
Simon Glass2be282c2017-06-18 22:08:59 -060021import sys
Simon Glass7581c012017-06-18 22:08:58 -060022
Simon Glassbf776672020-04-17 18:09:04 -060023from dtoc import fdt
24from dtoc import fdt_util
Simon Glassa542a702020-12-28 20:35:06 -070025from dtoc import src_scan
26from dtoc.src_scan import conv_name_to_c
Simon Glass7581c012017-06-18 22:08:58 -060027
Simon Glass9b330382020-11-08 20:36:21 -070028# When we see these properties we ignore them - i.e. do not create a structure
29# member
Simon Glass7581c012017-06-18 22:08:58 -060030PROP_IGNORE_LIST = [
31 '#address-cells',
32 '#gpio-cells',
33 '#size-cells',
34 'compatible',
35 'linux,phandle',
36 "status",
37 'phandle',
38 'u-boot,dm-pre-reloc',
39 'u-boot,dm-tpl',
40 'u-boot,dm-spl',
41]
42
Simon Glass5ea9dcc2020-11-08 20:36:17 -070043# C type declarations for the types we support
Simon Glass7581c012017-06-18 22:08:58 -060044TYPE_NAMES = {
Simon Glass5ea9dcc2020-11-08 20:36:17 -070045 fdt.Type.INT: 'fdt32_t',
46 fdt.Type.BYTE: 'unsigned char',
47 fdt.Type.STRING: 'const char *',
48 fdt.Type.BOOL: 'bool',
49 fdt.Type.INT64: 'fdt64_t',
Simon Glass2be282c2017-06-18 22:08:59 -060050}
Simon Glass7581c012017-06-18 22:08:58 -060051
52STRUCT_PREFIX = 'dtd_'
53VAL_PREFIX = 'dtv_'
54
Simon Glassbe44f272020-12-28 20:34:51 -070055class Ftype(IntEnum):
56 SOURCE, HEADER = range(2)
57
58
59# This holds information about each type of output file dtoc can create
60# type: Type of file (Ftype)
Simon Glassd1055d62020-12-28 20:35:00 -070061# fname: Filename excluding directory, e.g. 'dt-plat.c'
62# hdr_comment: Comment explaining the purpose of the file
63OutputFile = collections.namedtuple('OutputFile',
Simon Glassa7d5f962020-12-28 20:35:02 -070064 ['ftype', 'fname', 'method', 'hdr_comment'])
Simon Glassbe44f272020-12-28 20:34:51 -070065
Simon Glass8fed2eb2017-08-29 14:15:55 -060066# This holds information about a property which includes phandles.
67#
68# max_args: integer: Maximum number or arguments that any phandle uses (int).
69# args: Number of args for each phandle in the property. The total number of
70# phandles is len(args). This is a list of integers.
71PhandleInfo = collections.namedtuple('PhandleInfo', ['max_args', 'args'])
72
Simon Glass97136eb2020-10-03 09:25:19 -060073# Holds a single phandle link, allowing a C struct value to be assigned to point
74# to a device
75#
76# var_node: C variable to assign (e.g. 'dtv_mmc.clocks[0].node')
77# dev_name: Name of device to assign to (e.g. 'clock')
78PhandleLink = collections.namedtuple('PhandleLink', ['var_node', 'dev_name'])
79
Simon Glass8fed2eb2017-08-29 14:15:55 -060080
Simon Glass2be282c2017-06-18 22:08:59 -060081def tab_to(num_tabs, line):
82 """Append tabs to a line of text to reach a tab stop.
Simon Glass7581c012017-06-18 22:08:58 -060083
Simon Glass2be282c2017-06-18 22:08:59 -060084 Args:
Simon Glass9b330382020-11-08 20:36:21 -070085 num_tabs (int): Tab stop to obtain (0 = column 0, 1 = column 8, etc.)
86 line (str): Line of text to append to
Simon Glass2be282c2017-06-18 22:08:59 -060087
88 Returns:
Simon Glass9b330382020-11-08 20:36:21 -070089 str: line with the correct number of tabs appeneded. If the line already
Simon Glass2be282c2017-06-18 22:08:59 -060090 extends past that tab stop then a single space is appended.
91 """
92 if len(line) >= num_tabs * 8:
93 return line + ' '
94 return line + '\t' * (num_tabs - len(line) // 8)
95
Simon Glass56e0bbe2017-06-18 22:09:02 -060096def get_value(ftype, value):
97 """Get a value as a C expression
98
99 For integers this returns a byte-swapped (little-endian) hex string
100 For bytes this returns a hex string, e.g. 0x12
101 For strings this returns a literal string enclosed in quotes
102 For booleans this return 'true'
103
104 Args:
Simon Glass9b330382020-11-08 20:36:21 -0700105 ftype (fdt.Type): Data type (fdt_util)
106 value (bytes): Data value, as a string of bytes
107
108 Returns:
109 str: String representation of the value
Simon Glass56e0bbe2017-06-18 22:09:02 -0600110 """
Simon Glass5ea9dcc2020-11-08 20:36:17 -0700111 if ftype == fdt.Type.INT:
Simon Glassccc3da72020-12-23 08:11:19 -0700112 val = '%#x' % fdt_util.fdt32_to_cpu(value)
Simon Glass5ea9dcc2020-11-08 20:36:17 -0700113 elif ftype == fdt.Type.BYTE:
Simon Glass78128d52020-12-03 16:55:16 -0700114 char = value[0]
Simon Glassccc3da72020-12-23 08:11:19 -0700115 val = '%#x' % (ord(char) if isinstance(char, str) else char)
Simon Glass5ea9dcc2020-11-08 20:36:17 -0700116 elif ftype == fdt.Type.STRING:
Simon Glassf02d0eb2020-07-07 21:32:06 -0600117 # Handle evil ACPI backslashes by adding another backslash before them.
118 # So "\\_SB.GPO0" in the device tree effectively stays like that in C
Simon Glassccc3da72020-12-23 08:11:19 -0700119 val = '"%s"' % value.replace('\\', '\\\\')
Simon Glass5ea9dcc2020-11-08 20:36:17 -0700120 elif ftype == fdt.Type.BOOL:
Simon Glassccc3da72020-12-23 08:11:19 -0700121 val = 'true'
Simon Glass9b330382020-11-08 20:36:21 -0700122 else: # ftype == fdt.Type.INT64:
Simon Glassccc3da72020-12-23 08:11:19 -0700123 val = '%#x' % value
124 return val
Simon Glass56e0bbe2017-06-18 22:09:02 -0600125
Simon Glass56e0bbe2017-06-18 22:09:02 -0600126
Simon Glassccc3da72020-12-23 08:11:19 -0700127class DtbPlatdata():
Simon Glass7581c012017-06-18 22:08:58 -0600128 """Provide a means to convert device tree binary data to platform data
129
130 The output of this process is C structures which can be used in space-
131 constrained encvironments where the ~3KB code overhead of device tree
132 code is not affordable.
133
134 Properties:
Simon Glassa542a702020-12-28 20:35:06 -0700135 _scan: Scan object, for scanning and reporting on useful information
136 from the U-Boot source code
Simon Glass2be282c2017-06-18 22:08:59 -0600137 _fdt: Fdt object, referencing the device tree
Simon Glass7581c012017-06-18 22:08:58 -0600138 _dtb_fname: Filename of the input device tree binary file
Simon Glass074197a2021-02-03 06:01:09 -0700139 _valid_nodes_unsorted: A list of Node object with compatible strings,
140 ordered by devicetree node order
141 _valid_nodes: A list of Node object with compatible strings, ordered by
142 conv_name_to_c(node.name)
Simon Glasse36024b2017-06-18 22:09:01 -0600143 _include_disabled: true to include nodes marked status = "disabled"
Simon Glass7581c012017-06-18 22:08:58 -0600144 _outfile: The current output file (sys.stdout or a real file)
145 _lines: Stashed list of output lines for outputting in the future
Simon Glassbe44f272020-12-28 20:34:51 -0700146 _dirname: Directory to hold output files, or None for none (all files
147 go to stdout)
Simon Glassa7d5f962020-12-28 20:35:02 -0700148 _struct_data (dict): OrderedDict of dtplat structures to output
149 key (str): Node name, as a C identifier
150 value: dict containing structure fields:
151 key (str): Field name
152 value: Prop object with field information
Simon Glass1e0f3f42020-12-28 20:35:03 -0700153 _basedir (str): Base directory of source tree
Simon Glass337d6972021-02-03 06:01:10 -0700154 _valid_uclasses (list of src_scan.Uclass): List of uclasses needed for
155 the selected devices (see _valid_node), in alphabetical order
Simon Glass4a092352021-02-03 06:01:12 -0700156 _instantiate: Instantiate devices so they don't need to be bound at
157 run-time
Simon Glass7581c012017-06-18 22:08:58 -0600158 """
Simon Glass4a092352021-02-03 06:01:12 -0700159 def __init__(self, scan, dtb_fname, include_disabled, instantiate=False):
Simon Glassa542a702020-12-28 20:35:06 -0700160 self._scan = scan
Simon Glass2be282c2017-06-18 22:08:59 -0600161 self._fdt = None
Simon Glass7581c012017-06-18 22:08:58 -0600162 self._dtb_fname = dtb_fname
163 self._valid_nodes = None
Simon Glass074197a2021-02-03 06:01:09 -0700164 self._valid_nodes_unsorted = None
Simon Glasse36024b2017-06-18 22:09:01 -0600165 self._include_disabled = include_disabled
Simon Glass7581c012017-06-18 22:08:58 -0600166 self._outfile = None
167 self._lines = []
Simon Glassbe44f272020-12-28 20:34:51 -0700168 self._dirnames = [None] * len(Ftype)
Simon Glassa7d5f962020-12-28 20:35:02 -0700169 self._struct_data = collections.OrderedDict()
Simon Glass1e0f3f42020-12-28 20:35:03 -0700170 self._basedir = None
Simon Glass337d6972021-02-03 06:01:10 -0700171 self._valid_uclasses = None
Simon Glass4a092352021-02-03 06:01:12 -0700172 self._instantiate = instantiate
Walter Lozanodac82282020-07-03 08:07:17 -0300173
Simon Glassbe44f272020-12-28 20:34:51 -0700174 def setup_output_dirs(self, output_dirs):
175 """Set up the output directories
176
177 This should be done before setup_output() is called
178
179 Args:
180 output_dirs (tuple of str):
181 Directory to use for C output files.
182 Use None to write files relative current directory
183 Directory to use for H output files.
184 Defaults to the C output dir
185 """
186 def process_dir(ftype, dirname):
187 if dirname:
188 os.makedirs(dirname, exist_ok=True)
189 self._dirnames[ftype] = dirname
190
191 if output_dirs:
192 c_dirname = output_dirs[0]
193 h_dirname = output_dirs[1] if len(output_dirs) > 1 else c_dirname
194 process_dir(Ftype.SOURCE, c_dirname)
195 process_dir(Ftype.HEADER, h_dirname)
196
197 def setup_output(self, ftype, fname):
Simon Glass7581c012017-06-18 22:08:58 -0600198 """Set up the output destination
199
Simon Glass2be282c2017-06-18 22:08:59 -0600200 Once this is done, future calls to self.out() will output to this
Simon Glassbe44f272020-12-28 20:34:51 -0700201 file. The file used is as follows:
202
203 self._dirnames[ftype] is None: output to fname, or stdout if None
204 self._dirnames[ftype] is not None: output to fname in that directory
205
206 Calling this function multiple times will close the old file and open
207 the new one. If they are the same file, nothing happens and output will
208 continue to the same file.
Simon Glass7581c012017-06-18 22:08:58 -0600209
210 Args:
Simon Glassbe44f272020-12-28 20:34:51 -0700211 ftype (str): Type of file to create ('c' or 'h')
212 fname (str): Filename to send output to. If there is a directory in
213 self._dirnames for this file type, it will be put in that
214 directory
Simon Glass7581c012017-06-18 22:08:58 -0600215 """
Simon Glassbe44f272020-12-28 20:34:51 -0700216 dirname = self._dirnames[ftype]
217 if dirname:
218 pathname = os.path.join(dirname, fname)
219 if self._outfile:
220 self._outfile.close()
221 self._outfile = open(pathname, 'w')
222 elif fname:
223 if not self._outfile:
224 self._outfile = open(fname, 'w')
Simon Glassf62cea02020-12-28 20:34:48 -0700225 else:
226 self._outfile = sys.stdout
Simon Glass7581c012017-06-18 22:08:58 -0600227
Simon Glassbe44f272020-12-28 20:34:51 -0700228 def finish_output(self):
229 """Finish outputing to a file
230
231 This closes the output file, if one is in use
232 """
233 if self._outfile != sys.stdout:
234 self._outfile.close()
235
Simon Glass2be282c2017-06-18 22:08:59 -0600236 def out(self, line):
Simon Glass7581c012017-06-18 22:08:58 -0600237 """Output a string to the output file
238
239 Args:
Simon Glass9b330382020-11-08 20:36:21 -0700240 line (str): String to output
Simon Glass7581c012017-06-18 22:08:58 -0600241 """
Simon Glass2be282c2017-06-18 22:08:59 -0600242 self._outfile.write(line)
Simon Glass7581c012017-06-18 22:08:58 -0600243
Simon Glass2be282c2017-06-18 22:08:59 -0600244 def buf(self, line):
Simon Glass7581c012017-06-18 22:08:58 -0600245 """Buffer up a string to send later
246
247 Args:
Simon Glass9b330382020-11-08 20:36:21 -0700248 line (str): String to add to our 'buffer' list
Simon Glass7581c012017-06-18 22:08:58 -0600249 """
Simon Glass2be282c2017-06-18 22:08:59 -0600250 self._lines.append(line)
Simon Glass7581c012017-06-18 22:08:58 -0600251
Simon Glass2be282c2017-06-18 22:08:59 -0600252 def get_buf(self):
Simon Glass7581c012017-06-18 22:08:58 -0600253 """Get the contents of the output buffer, and clear it
254
255 Returns:
Simon Glass9b330382020-11-08 20:36:21 -0700256 list(str): The output buffer, which is then cleared for future use
Simon Glass7581c012017-06-18 22:08:58 -0600257 """
258 lines = self._lines
259 self._lines = []
260 return lines
261
Simon Glassd1055d62020-12-28 20:35:00 -0700262 def out_header(self, outfile):
263 """Output a message indicating that this is an auto-generated file
264
265 Args:
266 outfile: OutputFile describing the file being generated
267 """
Simon Glassd5031142017-08-29 14:16:01 -0600268 self.out('''/*
269 * DO NOT MODIFY
270 *
Simon Glassd1055d62020-12-28 20:35:00 -0700271 * %s.
272 * This was generated by dtoc from a .dtb (device tree binary) file.
Simon Glassd5031142017-08-29 14:16:01 -0600273 */
274
Simon Glassd1055d62020-12-28 20:35:00 -0700275''' % outfile.hdr_comment)
Simon Glassd5031142017-08-29 14:16:01 -0600276
Simon Glass8fed2eb2017-08-29 14:15:55 -0600277 def get_phandle_argc(self, prop, node_name):
278 """Check if a node contains phandles
Simon Glass2925c262017-08-29 14:15:54 -0600279
Simon Glass8fed2eb2017-08-29 14:15:55 -0600280 We have no reliable way of detecting whether a node uses a phandle
281 or not. As an interim measure, use a list of known property names.
Simon Glass2925c262017-08-29 14:15:54 -0600282
Simon Glass8fed2eb2017-08-29 14:15:55 -0600283 Args:
Simon Glass9b330382020-11-08 20:36:21 -0700284 prop (fdt.Prop): Prop object to check
285 node_name (str): Node name, only used for raising an error
286 Returns:
287 int or None: Number of argument cells is this is a phandle,
288 else None
289 Raises:
290 ValueError: if the phandle cannot be parsed or the required property
291 is not present
Simon Glass8fed2eb2017-08-29 14:15:55 -0600292 """
Walter Lozanoad340172020-06-25 01:10:16 -0300293 if prop.name in ['clocks', 'cd-gpios']:
Simon Glass760b7172018-07-06 10:27:31 -0600294 if not isinstance(prop.value, list):
295 prop.value = [prop.value]
Simon Glass8fed2eb2017-08-29 14:15:55 -0600296 val = prop.value
Simon Glass8fed2eb2017-08-29 14:15:55 -0600297 i = 0
298
299 max_args = 0
300 args = []
301 while i < len(val):
302 phandle = fdt_util.fdt32_to_cpu(val[i])
Simon Glass760b7172018-07-06 10:27:31 -0600303 # If we get to the end of the list, stop. This can happen
304 # since some nodes have more phandles in the list than others,
305 # but we allocate enough space for the largest list. So those
306 # nodes with shorter lists end up with zeroes at the end.
307 if not phandle:
308 break
Simon Glass8fed2eb2017-08-29 14:15:55 -0600309 target = self._fdt.phandle_to_node.get(phandle)
310 if not target:
311 raise ValueError("Cannot parse '%s' in node '%s'" %
312 (prop.name, node_name))
Walter Lozanoad340172020-06-25 01:10:16 -0300313 cells = None
314 for prop_name in ['#clock-cells', '#gpio-cells']:
315 cells = target.props.get(prop_name)
316 if cells:
317 break
Simon Glass8fed2eb2017-08-29 14:15:55 -0600318 if not cells:
Walter Lozanoad340172020-06-25 01:10:16 -0300319 raise ValueError("Node '%s' has no cells property" %
Simon Glass9b330382020-11-08 20:36:21 -0700320 (target.name))
Simon Glass8fed2eb2017-08-29 14:15:55 -0600321 num_args = fdt_util.fdt32_to_cpu(cells.value)
322 max_args = max(max_args, num_args)
323 args.append(num_args)
324 i += 1 + num_args
325 return PhandleInfo(max_args, args)
326 return None
Simon Glass2925c262017-08-29 14:15:54 -0600327
Simon Glass2be282c2017-06-18 22:08:59 -0600328 def scan_dtb(self):
Anatolij Gustschinf1a7ba12017-08-18 17:58:51 +0200329 """Scan the device tree to obtain a tree of nodes and properties
Simon Glass7581c012017-06-18 22:08:58 -0600330
Simon Glass2be282c2017-06-18 22:08:59 -0600331 Once this is done, self._fdt.GetRoot() can be called to obtain the
Simon Glass7581c012017-06-18 22:08:58 -0600332 device tree root node, and progress from there.
333 """
Simon Glass2be282c2017-06-18 22:08:59 -0600334 self._fdt = fdt.FdtScan(self._dtb_fname)
Simon Glass7581c012017-06-18 22:08:58 -0600335
Simon Glass074197a2021-02-03 06:01:09 -0700336 def scan_node(self, node, valid_nodes):
Simon Glass2be282c2017-06-18 22:08:59 -0600337 """Scan a node and subnodes to build a tree of node and phandle info
338
Simon Glass074197a2021-02-03 06:01:09 -0700339 This adds each subnode to self._valid_nodes if it is enabled and has a
340 compatible string.
Simon Glass2be282c2017-06-18 22:08:59 -0600341
342 Args:
Simon Glass074197a2021-02-03 06:01:09 -0700343 node (Node): Node for scan for subnodes
Simon Glassccc3da72020-12-23 08:11:19 -0700344 valid_nodes (list of Node): List of Node objects to add to
Simon Glass2be282c2017-06-18 22:08:59 -0600345 """
Simon Glass074197a2021-02-03 06:01:09 -0700346 for subnode in node.subnodes:
347 if 'compatible' in subnode.props:
348 status = subnode.props.get('status')
Simon Glasse36024b2017-06-18 22:09:01 -0600349 if (not self._include_disabled and not status or
Simon Glass2be282c2017-06-18 22:08:59 -0600350 status.value != 'disabled'):
Simon Glass074197a2021-02-03 06:01:09 -0700351 valid_nodes.append(subnode)
Simon Glass7581c012017-06-18 22:08:58 -0600352
353 # recurse to handle any subnodes
Simon Glass074197a2021-02-03 06:01:09 -0700354 self.scan_node(subnode, valid_nodes)
Simon Glass7581c012017-06-18 22:08:58 -0600355
Simon Glass50aae3e2021-02-03 06:01:11 -0700356 def scan_tree(self, add_root):
Simon Glass7581c012017-06-18 22:08:58 -0600357 """Scan the device tree for useful information
358
359 This fills in the following properties:
Simon Glass074197a2021-02-03 06:01:09 -0700360 _valid_nodes_unsorted: A list of nodes we wish to consider include
361 in the platform data (in devicetree node order)
362 _valid_nodes: Sorted version of _valid_nodes_unsorted
Simon Glass50aae3e2021-02-03 06:01:11 -0700363
364 Args:
365 add_root: True to add the root node also (which wouldn't normally
366 be added as it may not have a compatible string)
Simon Glass7581c012017-06-18 22:08:58 -0600367 """
Simon Glass074197a2021-02-03 06:01:09 -0700368 root = self._fdt.GetRoot()
Simon Glass1b272732020-10-03 11:31:25 -0600369 valid_nodes = []
Simon Glass50aae3e2021-02-03 06:01:11 -0700370 if add_root:
371 valid_nodes.append(root)
Simon Glass074197a2021-02-03 06:01:09 -0700372 self.scan_node(root, valid_nodes)
373 self._valid_nodes_unsorted = valid_nodes
Simon Glass1b272732020-10-03 11:31:25 -0600374 self._valid_nodes = sorted(valid_nodes,
375 key=lambda x: conv_name_to_c(x.name))
Simon Glass51d5d052021-02-03 06:00:58 -0700376
377 def prepare_nodes(self):
378 """Add extra properties to the nodes we are using
379
380 The following properties are added for use by dtoc:
381 idx: Index number of this node (0=first, etc.)
382 struct_name: Name of the struct dtd used by this node
383 var_name: C name for this node
384 child_devs: List of child devices for this node, each a None
385 child_refs: Dict of references for each child:
386 key: Position in child list (-1=head, 0=first, 1=second, ...
387 n-1=last, n=head)
388 seq: Sequence number of the device (unique within its uclass), or
389 -1 not not known yet
390 dev_ref: Reference to this device, e.g. 'DM_DEVICE_REF(serial)'
391 driver: Driver record for this node, or None if not known
392 uclass: Uclass record for this node, or None if not known
393 uclass_seq: Position of this device within the uclass list (0=first,
394 n-1=last)
395 parent_seq: Position of this device within it siblings (0=first,
396 n-1=last)
397 parent_driver: Driver record of the node's parent, or None if none.
398 We don't use node.parent.driver since node.parent may not be in
399 the list of valid nodes
400 """
Simon Glass1b272732020-10-03 11:31:25 -0600401 for idx, node in enumerate(self._valid_nodes):
402 node.idx = idx
Simon Glass51d5d052021-02-03 06:00:58 -0700403 node.struct_name, _ = self._scan.get_normalized_compat_name(node)
404 node.var_name = conv_name_to_c(node.name)
405 node.child_devs = []
406 node.child_refs = {}
407 node.seq = -1
408 node.dev_ref = None
409 node.driver = None
410 node.uclass = None
411 node.uclass_seq = None
412 node.parent_seq = None
413 node.parent_driver = None
Simon Glass7581c012017-06-18 22:08:58 -0600414
Simon Glassc20ee0e2017-08-29 14:15:50 -0600415 @staticmethod
416 def get_num_cells(node):
417 """Get the number of cells in addresses and sizes for this node
418
419 Args:
Simon Glass9b330382020-11-08 20:36:21 -0700420 node (fdt.None): Node to check
Simon Glassc20ee0e2017-08-29 14:15:50 -0600421
422 Returns:
423 Tuple:
424 Number of address cells for this node
425 Number of size cells for this node
426 """
427 parent = node.parent
Simon Glass78128d52020-12-03 16:55:16 -0700428 num_addr, num_size = 2, 2
Simon Glassc20ee0e2017-08-29 14:15:50 -0600429 if parent:
Simon Glass78128d52020-12-03 16:55:16 -0700430 addr_prop = parent.props.get('#address-cells')
431 size_prop = parent.props.get('#size-cells')
432 if addr_prop:
433 num_addr = fdt_util.fdt32_to_cpu(addr_prop.value)
434 if size_prop:
435 num_size = fdt_util.fdt32_to_cpu(size_prop.value)
436 return num_addr, num_size
Simon Glassc20ee0e2017-08-29 14:15:50 -0600437
438 def scan_reg_sizes(self):
439 """Scan for 64-bit 'reg' properties and update the values
440
441 This finds 'reg' properties with 64-bit data and converts the value to
442 an array of 64-values. This allows it to be output in a way that the
443 C code can read.
444 """
445 for node in self._valid_nodes:
446 reg = node.props.get('reg')
447 if not reg:
448 continue
Simon Glass78128d52020-12-03 16:55:16 -0700449 num_addr, num_size = self.get_num_cells(node)
450 total = num_addr + num_size
Simon Glassc20ee0e2017-08-29 14:15:50 -0600451
Simon Glass5ea9dcc2020-11-08 20:36:17 -0700452 if reg.type != fdt.Type.INT:
Simon Glassdfe5f5b2018-07-06 10:27:32 -0600453 raise ValueError("Node '%s' reg property is not an int" %
454 node.name)
Simon Glassc20ee0e2017-08-29 14:15:50 -0600455 if len(reg.value) % total:
Simon Glass9b330382020-11-08 20:36:21 -0700456 raise ValueError(
457 "Node '%s' reg property has %d cells "
458 'which is not a multiple of na + ns = %d + %d)' %
Simon Glass78128d52020-12-03 16:55:16 -0700459 (node.name, len(reg.value), num_addr, num_size))
460 reg.num_addr = num_addr
461 reg.num_size = num_size
462 if num_addr != 1 or num_size != 1:
Simon Glass5ea9dcc2020-11-08 20:36:17 -0700463 reg.type = fdt.Type.INT64
Simon Glassc20ee0e2017-08-29 14:15:50 -0600464 i = 0
465 new_value = []
466 val = reg.value
467 if not isinstance(val, list):
468 val = [val]
469 while i < len(val):
Simon Glass78128d52020-12-03 16:55:16 -0700470 addr = fdt_util.fdt_cells_to_cpu(val[i:], reg.num_addr)
471 i += num_addr
472 size = fdt_util.fdt_cells_to_cpu(val[i:], reg.num_size)
473 i += num_size
Simon Glassc20ee0e2017-08-29 14:15:50 -0600474 new_value += [addr, size]
475 reg.value = new_value
476
Simon Glass2be282c2017-06-18 22:08:59 -0600477 def scan_structs(self):
Simon Glass7581c012017-06-18 22:08:58 -0600478 """Scan the device tree building up the C structures we will use.
479
480 Build a dict keyed by C struct name containing a dict of Prop
481 object for each struct field (keyed by property name). Where the
482 same struct appears multiple times, try to use the 'widest'
483 property, i.e. the one with a type which can express all others.
484
485 Once the widest property is determined, all other properties are
486 updated to match that width.
Simon Glasse4fb5fa2020-10-03 11:31:24 -0600487
Simon Glassa7d5f962020-12-28 20:35:02 -0700488 The results are written to self._struct_data
Simon Glass7581c012017-06-18 22:08:58 -0600489 """
Simon Glassa7d5f962020-12-28 20:35:02 -0700490 structs = self._struct_data
Simon Glass7581c012017-06-18 22:08:58 -0600491 for node in self._valid_nodes:
Simon Glass7581c012017-06-18 22:08:58 -0600492 fields = {}
493
494 # Get a list of all the valid properties in this node.
495 for name, prop in node.props.items():
496 if name not in PROP_IGNORE_LIST and name[0] != '#':
497 fields[name] = copy.deepcopy(prop)
498
Simon Glasse525fea2021-02-03 06:00:59 -0700499 # If we've seen this struct_name before, update the existing struct
500 if node.struct_name in structs:
501 struct = structs[node.struct_name]
Simon Glass7581c012017-06-18 22:08:58 -0600502 for name, prop in fields.items():
503 oldprop = struct.get(name)
504 if oldprop:
505 oldprop.Widen(prop)
506 else:
507 struct[name] = prop
508
509 # Otherwise store this as a new struct.
510 else:
Simon Glasse525fea2021-02-03 06:00:59 -0700511 structs[node.struct_name] = fields
Simon Glass7581c012017-06-18 22:08:58 -0600512
Simon Glass7581c012017-06-18 22:08:58 -0600513 for node in self._valid_nodes:
Simon Glasse525fea2021-02-03 06:00:59 -0700514 struct = structs[node.struct_name]
Simon Glass7581c012017-06-18 22:08:58 -0600515 for name, prop in node.props.items():
516 if name not in PROP_IGNORE_LIST and name[0] != '#':
517 prop.Widen(struct[name])
Simon Glass7581c012017-06-18 22:08:58 -0600518
Simon Glass2be282c2017-06-18 22:08:59 -0600519 def scan_phandles(self):
Simon Glass7581c012017-06-18 22:08:58 -0600520 """Figure out what phandles each node uses
521
522 We need to be careful when outputing nodes that use phandles since
523 they must come after the declaration of the phandles in the C file.
524 Otherwise we get a compiler error since the phandle struct is not yet
525 declared.
526
527 This function adds to each node a list of phandle nodes that the node
528 depends on. This allows us to output things in the right order.
529 """
530 for node in self._valid_nodes:
531 node.phandles = set()
532 for pname, prop in node.props.items():
533 if pname in PROP_IGNORE_LIST or pname[0] == '#':
534 continue
Simon Glass8fed2eb2017-08-29 14:15:55 -0600535 info = self.get_phandle_argc(prop, node.name)
536 if info:
Simon Glass8fed2eb2017-08-29 14:15:55 -0600537 # Process the list as pairs of (phandle, id)
Simon Glass634eba42017-08-29 14:15:59 -0600538 pos = 0
539 for args in info.args:
540 phandle_cell = prop.value[pos]
Simon Glass8fed2eb2017-08-29 14:15:55 -0600541 phandle = fdt_util.fdt32_to_cpu(phandle_cell)
542 target_node = self._fdt.phandle_to_node[phandle]
543 node.phandles.add(target_node)
Simon Glass634eba42017-08-29 14:15:59 -0600544 pos += 1 + args
Simon Glass7581c012017-06-18 22:08:58 -0600545
546
Simon Glassa7d5f962020-12-28 20:35:02 -0700547 def generate_structs(self):
Simon Glass7581c012017-06-18 22:08:58 -0600548 """Generate struct defintions for the platform data
549
550 This writes out the body of a header file consisting of structure
551 definitions for node in self._valid_nodes. See the documentation in
Heinrich Schuchardt2799a692020-02-25 21:35:39 +0100552 doc/driver-model/of-plat.rst for more information.
Simon Glass7581c012017-06-18 22:08:58 -0600553 """
Simon Glassa7d5f962020-12-28 20:35:02 -0700554 structs = self._struct_data
Simon Glass2be282c2017-06-18 22:08:59 -0600555 self.out('#include <stdbool.h>\n')
Masahiro Yamadab08c8c42018-03-05 01:20:11 +0900556 self.out('#include <linux/libfdt.h>\n')
Simon Glass7581c012017-06-18 22:08:58 -0600557
558 # Output the struct definition
559 for name in sorted(structs):
Simon Glass2be282c2017-06-18 22:08:59 -0600560 self.out('struct %s%s {\n' % (STRUCT_PREFIX, name))
Simon Glass7581c012017-06-18 22:08:58 -0600561 for pname in sorted(structs[name]):
562 prop = structs[name][pname]
Simon Glass8fed2eb2017-08-29 14:15:55 -0600563 info = self.get_phandle_argc(prop, structs[name])
564 if info:
Simon Glass7581c012017-06-18 22:08:58 -0600565 # For phandles, include a reference to the target
Simon Glass0d154632017-08-29 14:15:56 -0600566 struct_name = 'struct phandle_%d_arg' % info.max_args
567 self.out('\t%s%s[%d]' % (tab_to(2, struct_name),
Simon Glass2be282c2017-06-18 22:08:59 -0600568 conv_name_to_c(prop.name),
Simon Glass634eba42017-08-29 14:15:59 -0600569 len(info.args)))
Simon Glass7581c012017-06-18 22:08:58 -0600570 else:
571 ptype = TYPE_NAMES[prop.type]
Simon Glass2be282c2017-06-18 22:08:59 -0600572 self.out('\t%s%s' % (tab_to(2, ptype),
573 conv_name_to_c(prop.name)))
574 if isinstance(prop.value, list):
575 self.out('[%d]' % len(prop.value))
576 self.out(';\n')
577 self.out('};\n')
Simon Glass7581c012017-06-18 22:08:58 -0600578
Simon Glassabf0c802020-12-23 08:11:20 -0700579 def _output_list(self, node, prop):
580 """Output the C code for a devicetree property that holds a list
581
582 Args:
583 node (fdt.Node): Node to output
584 prop (fdt.Prop): Prop to output
585 """
586 self.buf('{')
587 vals = []
588 # For phandles, output a reference to the platform data
589 # of the target node.
590 info = self.get_phandle_argc(prop, node.name)
591 if info:
592 # Process the list as pairs of (phandle, id)
593 pos = 0
594 for args in info.args:
595 phandle_cell = prop.value[pos]
596 phandle = fdt_util.fdt32_to_cpu(phandle_cell)
597 target_node = self._fdt.phandle_to_node[phandle]
598 arg_values = []
599 for i in range(args):
600 arg_values.append(
601 str(fdt_util.fdt32_to_cpu(prop.value[pos + 1 + i])))
602 pos += 1 + args
603 vals.append('\t{%d, {%s}}' % (target_node.idx,
604 ', '.join(arg_values)))
605 for val in vals:
606 self.buf('\n\t\t%s,' % val)
607 else:
608 for val in prop.value:
609 vals.append(get_value(prop.type, val))
610
611 # Put 8 values per line to avoid very long lines.
612 for i in range(0, len(vals), 8):
613 if i:
614 self.buf(',\n\t\t')
615 self.buf(', '.join(vals[i:i + 8]))
616 self.buf('}')
617
Simon Glasse525fea2021-02-03 06:00:59 -0700618 def _declare_device(self, node):
Simon Glass221ddc12020-12-23 08:11:21 -0700619 """Add a device declaration to the output
620
Simon Glass20e442a2020-12-28 20:34:54 -0700621 This declares a U_BOOT_DRVINFO() for the device being processed
Simon Glass221ddc12020-12-23 08:11:21 -0700622
623 Args:
Simon Glasse525fea2021-02-03 06:00:59 -0700624 node: Node to process
Simon Glass221ddc12020-12-23 08:11:21 -0700625 """
Simon Glasse525fea2021-02-03 06:00:59 -0700626 self.buf('U_BOOT_DRVINFO(%s) = {\n' % node.var_name)
627 self.buf('\t.name\t\t= "%s",\n' % node.struct_name)
628 self.buf('\t.plat\t= &%s%s,\n' % (VAL_PREFIX, node.var_name))
629 self.buf('\t.plat_size\t= sizeof(%s%s),\n' %
630 (VAL_PREFIX, node.var_name))
Simon Glass221ddc12020-12-23 08:11:21 -0700631 idx = -1
Simon Glasse525fea2021-02-03 06:00:59 -0700632 if node.parent and node.parent in self._valid_nodes:
633 idx = node.parent.idx
Simon Glass221ddc12020-12-23 08:11:21 -0700634 self.buf('\t.parent_idx\t= %d,\n' % idx)
635 self.buf('};\n')
636 self.buf('\n')
637
Simon Glass161dac12020-12-23 08:11:22 -0700638 def _output_prop(self, node, prop):
639 """Output a line containing the value of a struct member
640
641 Args:
642 node (Node): Node being output
643 prop (Prop): Prop object to output
644 """
645 if prop.name in PROP_IGNORE_LIST or prop.name[0] == '#':
646 return
647 member_name = conv_name_to_c(prop.name)
648 self.buf('\t%s= ' % tab_to(3, '.' + member_name))
649
650 # Special handling for lists
651 if isinstance(prop.value, list):
652 self._output_list(node, prop)
653 else:
654 self.buf(get_value(prop.type, prop.value))
655 self.buf(',\n')
656
Simon Glasse525fea2021-02-03 06:00:59 -0700657 def _output_values(self, node):
Simon Glass161dac12020-12-23 08:11:22 -0700658 """Output the definition of a device's struct values
659
660 Args:
Simon Glasse525fea2021-02-03 06:00:59 -0700661 node (Node): Node to output
Simon Glass161dac12020-12-23 08:11:22 -0700662 """
663 self.buf('static struct %s%s %s%s = {\n' %
Simon Glasse525fea2021-02-03 06:00:59 -0700664 (STRUCT_PREFIX, node.struct_name, VAL_PREFIX, node.var_name))
Simon Glass161dac12020-12-23 08:11:22 -0700665 for pname in sorted(node.props):
666 self._output_prop(node, node.props[pname])
667 self.buf('};\n')
668
Simon Glass05953522021-02-03 06:01:07 -0700669 def read_aliases(self):
670 """Read the aliases and attach the information to self._alias
671
672 Raises:
673 ValueError: The alias path is not found
674 """
675 alias_node = self._fdt.GetNode('/aliases')
676 if not alias_node:
677 return
678 re_num = re.compile('(^[a-z0-9-]+[a-z]+)([0-9]+)$')
679 for prop in alias_node.props.values():
680 m_alias = re_num.match(prop.name)
681 if not m_alias:
682 raise ValueError("Cannot decode alias '%s'" % prop.name)
683 name, num = m_alias.groups()
684 node = self._fdt.GetNode(prop.value)
685 result = self._scan.add_uclass_alias(name, num, node)
686 if result is None:
687 raise ValueError("Alias '%s' path '%s' not found" %
688 (prop.name, prop.value))
689 elif result is False:
690 print("Could not find uclass for alias '%s'" % prop.name)
691
Simon Glass337d6972021-02-03 06:01:10 -0700692 def assign_seqs(self):
Simon Glass074197a2021-02-03 06:01:09 -0700693 """Assign a sequence number to each node"""
694 for node in self._valid_nodes_unsorted:
Simon Glass337d6972021-02-03 06:01:10 -0700695 seq = self._scan.assign_seq(node)
696 if seq is not None:
697 node.seq = seq
Simon Glass074197a2021-02-03 06:01:09 -0700698
Simon Glassfd471e22021-02-03 06:01:00 -0700699 def process_nodes(self, need_drivers):
700 nodes_to_output = list(self._valid_nodes)
701
Simon Glassb9319c42021-02-03 06:01:01 -0700702 # Figure out which drivers we actually use
703 self._scan.mark_used(nodes_to_output)
704
Simon Glassfd471e22021-02-03 06:01:00 -0700705 for node in nodes_to_output:
706 node.dev_ref = 'DM_DEVICE_REF(%s)' % node.var_name
707 driver = self._scan.get_driver(node.struct_name)
708 if not driver:
709 if not need_drivers:
710 continue
711 raise ValueError("Cannot parse/find driver for '%s'" %
712 node.struct_name)
713 node.driver = driver
Simon Glass337d6972021-02-03 06:01:10 -0700714 uclass = self._scan._uclass.get(driver.uclass_id)
715 if not uclass:
716 raise ValueError("Cannot parse/find uclass '%s' for driver '%s'" %
717 (driver.uclass_id, node.struct_name))
718 node.uclass = uclass
719 node.uclass_seq = len(node.uclass.devs)
720 node.uclass.devs.append(node)
721 uclass.node_refs[node.uclass_seq] = \
722 '&%s->uclass_node' % node.dev_ref
723
Simon Glassfd471e22021-02-03 06:01:00 -0700724 parent_driver = None
725 if node.parent in self._valid_nodes:
726 parent_driver = self._scan.get_driver(node.parent.struct_name)
727 if not parent_driver:
728 if not need_drivers:
729 continue
730 raise ValueError(
731 "Cannot parse/find parent driver '%s' for '%s'" %
732 (node.parent.struct_name, node.struct_name))
733 node.parent_seq = len(node.parent.child_devs)
734 node.parent.child_devs.append(node)
735 node.parent.child_refs[node.parent_seq] = \
736 '&%s->sibling_node' % node.dev_ref
737 node.parent_driver = parent_driver
738
739 for node in nodes_to_output:
740 ref = '&%s->child_head' % node.dev_ref
741 node.child_refs[-1] = ref
742 node.child_refs[len(node.child_devs)] = ref
743
Simon Glass337d6972021-02-03 06:01:10 -0700744 uclass_set = set()
745 for driver in self._scan._drivers.values():
746 if driver.used and driver.uclass:
747 uclass_set.add(driver.uclass)
748 self._valid_uclasses = sorted(list(uclass_set),
749 key=lambda uc: uc.uclass_id)
750
751 for seq, uclass in enumerate(uclass_set):
752 ref = '&DM_UCLASS_REF(%s)->dev_head' % uclass.name
753 uclass.node_refs[-1] = ref
754 uclass.node_refs[len(uclass.devs)] = ref
755
Simon Glass2be282c2017-06-18 22:08:59 -0600756 def output_node(self, node):
Simon Glass7581c012017-06-18 22:08:58 -0600757 """Output the C code for a node
758
759 Args:
Simon Glass9b330382020-11-08 20:36:21 -0700760 node (fdt.Node): node to output
Simon Glass7581c012017-06-18 22:08:58 -0600761 """
Simon Glass1b272732020-10-03 11:31:25 -0600762 self.buf('/* Node %s index %d */\n' % (node.path, node.idx))
Simon Glass7581c012017-06-18 22:08:58 -0600763
Simon Glasse525fea2021-02-03 06:00:59 -0700764 self._output_values(node)
765 self._declare_device(node)
Simon Glass7581c012017-06-18 22:08:58 -0600766
Simon Glass2be282c2017-06-18 22:08:59 -0600767 self.out(''.join(self.get_buf()))
Simon Glass7581c012017-06-18 22:08:58 -0600768
Simon Glassa7d5f962020-12-28 20:35:02 -0700769 def generate_plat(self):
Simon Glass7581c012017-06-18 22:08:58 -0600770 """Generate device defintions for the platform data
771
772 This writes out C platform data initialisation data and
Simon Glass20e442a2020-12-28 20:34:54 -0700773 U_BOOT_DRVINFO() declarations for each valid node. Where a node has
Simon Glass7581c012017-06-18 22:08:58 -0600774 multiple compatible strings, a #define is used to make them equivalent.
775
Heinrich Schuchardt2799a692020-02-25 21:35:39 +0100776 See the documentation in doc/driver-model/of-plat.rst for more
Simon Glass7581c012017-06-18 22:08:58 -0600777 information.
778 """
Simon Glass20e442a2020-12-28 20:34:54 -0700779 self.out('/* Allow use of U_BOOT_DRVINFO() in this file */\n')
Simon Glassf31fa992020-12-28 20:35:01 -0700780 self.out('#define DT_PLAT_C\n')
Simon Glasscb43ac12020-10-03 11:31:41 -0600781 self.out('\n')
Simon Glass2be282c2017-06-18 22:08:59 -0600782 self.out('#include <common.h>\n')
783 self.out('#include <dm.h>\n')
784 self.out('#include <dt-structs.h>\n')
785 self.out('\n')
Simon Glass7581c012017-06-18 22:08:58 -0600786
Simon Glass9eca08d2020-12-28 20:35:04 -0700787 for node in self._valid_nodes:
Simon Glass2be282c2017-06-18 22:08:59 -0600788 self.output_node(node)
Simon Glassfa0ea5b2017-06-18 22:09:03 -0600789
Walter Lozano51f12632020-06-25 01:10:13 -0300790 self.out(''.join(self.get_buf()))
Simon Glassfa0ea5b2017-06-18 22:09:03 -0600791
Simon Glass192c1112020-12-28 20:34:50 -0700792
Simon Glassbe44f272020-12-28 20:34:51 -0700793# Types of output file we understand
794# key: Command used to generate this file
795# value: OutputFile for this command
796OUTPUT_FILES = {
Simon Glassd1055d62020-12-28 20:35:00 -0700797 'struct':
798 OutputFile(Ftype.HEADER, 'dt-structs-gen.h',
Simon Glassa7d5f962020-12-28 20:35:02 -0700799 DtbPlatdata.generate_structs,
Simon Glassd1055d62020-12-28 20:35:00 -0700800 'Defines the structs used to hold devicetree data'),
801 'platdata':
Simon Glassa7d5f962020-12-28 20:35:02 -0700802 OutputFile(Ftype.SOURCE, 'dt-plat.c', DtbPlatdata.generate_plat,
Simon Glassd1055d62020-12-28 20:35:00 -0700803 'Declares the U_BOOT_DRIVER() records and platform data'),
Simon Glassbe44f272020-12-28 20:34:51 -0700804 }
805
806
Simon Glassb00f0062021-02-03 06:01:02 -0700807def run_steps(args, dtb_file, include_disabled, output, output_dirs, phase,
Simon Glass4a092352021-02-03 06:01:12 -0700808 instantiate, warning_disabled=False, drivers_additional=None,
809 basedir=None, scan=None):
Simon Glassfa0ea5b2017-06-18 22:09:03 -0600810 """Run all the steps of the dtoc tool
811
812 Args:
Simon Glass9b330382020-11-08 20:36:21 -0700813 args (list): List of non-option arguments provided to the problem
814 dtb_file (str): Filename of dtb file to process
815 include_disabled (bool): True to include disabled nodes
Simon Glassf62cea02020-12-28 20:34:48 -0700816 output (str): Name of output file (None for stdout)
Simon Glass192c1112020-12-28 20:34:50 -0700817 output_dirs (tuple of str):
818 Directory to put C output files
819 Directory to put H output files
Simon Glassb00f0062021-02-03 06:01:02 -0700820 phase: The phase of U-Boot that we are generating data for, e.g. 'spl'
821 or 'tpl'. None if not known
Simon Glass4a092352021-02-03 06:01:12 -0700822 instantiate: Instantiate devices so they don't need to be bound at
823 run-time
Simon Glass78128d52020-12-03 16:55:16 -0700824 warning_disabled (bool): True to avoid showing warnings about missing
825 drivers
Simon Glassccc3da72020-12-23 08:11:19 -0700826 drivers_additional (list): List of additional drivers to use during
Simon Glass78128d52020-12-03 16:55:16 -0700827 scanning
Simon Glass1e0f3f42020-12-28 20:35:03 -0700828 basedir (str): Base directory of U-Boot source code. Defaults to the
829 grandparent of this file's directory
Simon Glassa32eb7d2021-02-03 06:00:51 -0700830 scan (src_src.Scanner): Scanner from a previous run. This can help speed
831 up tests. Use None for normal operation
832
Simon Glass05953522021-02-03 06:01:07 -0700833 Returns:
834 DtbPlatdata object
835
Simon Glass9b330382020-11-08 20:36:21 -0700836 Raises:
837 ValueError: if args has no command, or an unknown command
Simon Glassfa0ea5b2017-06-18 22:09:03 -0600838 """
839 if not args:
Simon Glassbe44f272020-12-28 20:34:51 -0700840 raise ValueError('Please specify a command: struct, platdata, all')
841 if output and output_dirs and any(output_dirs):
842 raise ValueError('Must specify either output or output_dirs, not both')
Simon Glassfa0ea5b2017-06-18 22:09:03 -0600843
Simon Glassa32eb7d2021-02-03 06:00:51 -0700844 if not scan:
Simon Glassb00f0062021-02-03 06:01:02 -0700845 scan = src_scan.Scanner(basedir, warning_disabled, drivers_additional,
846 phase)
Simon Glassa32eb7d2021-02-03 06:00:51 -0700847 scan.scan_drivers()
Simon Glassfd471e22021-02-03 06:01:00 -0700848 do_process = True
849 else:
850 do_process = False
Simon Glass4a092352021-02-03 06:01:12 -0700851 plat = DtbPlatdata(scan, dtb_file, include_disabled, instantiate)
Simon Glassfa0ea5b2017-06-18 22:09:03 -0600852 plat.scan_dtb()
Simon Glass4a092352021-02-03 06:01:12 -0700853 plat.scan_tree(add_root=instantiate)
Simon Glass51d5d052021-02-03 06:00:58 -0700854 plat.prepare_nodes()
Simon Glassc20ee0e2017-08-29 14:15:50 -0600855 plat.scan_reg_sizes()
Simon Glassbe44f272020-12-28 20:34:51 -0700856 plat.setup_output_dirs(output_dirs)
Simon Glassa7d5f962020-12-28 20:35:02 -0700857 plat.scan_structs()
Simon Glassfa0ea5b2017-06-18 22:09:03 -0600858 plat.scan_phandles()
Simon Glass4a092352021-02-03 06:01:12 -0700859 plat.process_nodes(instantiate)
Simon Glass05953522021-02-03 06:01:07 -0700860 plat.read_aliases()
Simon Glass337d6972021-02-03 06:01:10 -0700861 plat.assign_seqs()
Simon Glassfa0ea5b2017-06-18 22:09:03 -0600862
Simon Glass10cbd3b2020-12-28 20:34:52 -0700863 cmds = args[0].split(',')
864 if 'all' in cmds:
865 cmds = sorted(OUTPUT_FILES.keys())
866 for cmd in cmds:
Simon Glassbe44f272020-12-28 20:34:51 -0700867 outfile = OUTPUT_FILES.get(cmd)
868 if not outfile:
869 raise ValueError("Unknown command '%s': (use: %s)" %
Simon Glass10cbd3b2020-12-28 20:34:52 -0700870 (cmd, ', '.join(sorted(OUTPUT_FILES.keys()))))
Simon Glassbe44f272020-12-28 20:34:51 -0700871 plat.setup_output(outfile.ftype,
872 outfile.fname if output_dirs else output)
Simon Glassd1055d62020-12-28 20:35:00 -0700873 plat.out_header(outfile)
Simon Glassa7d5f962020-12-28 20:35:02 -0700874 outfile.method(plat)
Simon Glassbe44f272020-12-28 20:34:51 -0700875 plat.finish_output()
Simon Glass05953522021-02-03 06:01:07 -0700876 return plat