blob: 0c719310b102ee93428c2fcbbe76d8c1ce73ce03 [file] [log] [blame]
Simon Glassd570dec2017-06-18 22:08:58 -06001#!/usr/bin/python
2#
3# Copyright (C) 2017 Google, Inc
4# Written by Simon Glass <sjg@chromium.org>
5#
6# SPDX-License-Identifier: GPL-2.0+
7#
8
Simon Glass1f730c82017-06-18 22:08:59 -06009"""Device tree to platform data class
10
11This supports converting device tree data to C structures definitions and
12static data.
13"""
14
Simon Glassd570dec2017-06-18 22:08:58 -060015import copy
Simon Glass1f730c82017-06-18 22:08:59 -060016import sys
Simon Glassd570dec2017-06-18 22:08:58 -060017
18import fdt
19import fdt_util
20
21# When we see these properties we ignore them - i.e. do not create a structure member
22PROP_IGNORE_LIST = [
23 '#address-cells',
24 '#gpio-cells',
25 '#size-cells',
26 'compatible',
27 'linux,phandle',
28 "status",
29 'phandle',
30 'u-boot,dm-pre-reloc',
31 'u-boot,dm-tpl',
32 'u-boot,dm-spl',
33]
34
35# C type declarations for the tyues we support
36TYPE_NAMES = {
37 fdt.TYPE_INT: 'fdt32_t',
38 fdt.TYPE_BYTE: 'unsigned char',
39 fdt.TYPE_STRING: 'const char *',
40 fdt.TYPE_BOOL: 'bool',
Simon Glassfc3ae9c2017-08-29 14:15:48 -060041 fdt.TYPE_INT64: 'fdt64_t',
Simon Glass1f730c82017-06-18 22:08:59 -060042}
Simon Glassd570dec2017-06-18 22:08:58 -060043
44STRUCT_PREFIX = 'dtd_'
45VAL_PREFIX = 'dtv_'
46
Simon Glass1f730c82017-06-18 22:08:59 -060047def conv_name_to_c(name):
Simon Glassd570dec2017-06-18 22:08:58 -060048 """Convert a device-tree name to a C identifier
49
Simon Glass2e0bf3f2017-06-18 22:09:04 -060050 This uses multiple replace() calls instead of re.sub() since it is faster
51 (400ms for 1m calls versus 1000ms for the 're' version).
52
Simon Glassd570dec2017-06-18 22:08:58 -060053 Args:
54 name: Name to convert
55 Return:
56 String containing the C version of this name
57 """
Simon Glass1f730c82017-06-18 22:08:59 -060058 new = name.replace('@', '_at_')
59 new = new.replace('-', '_')
60 new = new.replace(',', '_')
61 new = new.replace('.', '_')
Simon Glass1f730c82017-06-18 22:08:59 -060062 return new
Simon Glassd570dec2017-06-18 22:08:58 -060063
Simon Glass1f730c82017-06-18 22:08:59 -060064def tab_to(num_tabs, line):
65 """Append tabs to a line of text to reach a tab stop.
Simon Glassd570dec2017-06-18 22:08:58 -060066
Simon Glass1f730c82017-06-18 22:08:59 -060067 Args:
68 num_tabs: Tab stop to obtain (0 = column 0, 1 = column 8, etc.)
69 line: Line of text to append to
70
71 Returns:
72 line with the correct number of tabs appeneded. If the line already
73 extends past that tab stop then a single space is appended.
74 """
75 if len(line) >= num_tabs * 8:
76 return line + ' '
77 return line + '\t' * (num_tabs - len(line) // 8)
78
Simon Glass7a2add12017-06-18 22:09:02 -060079def get_value(ftype, value):
80 """Get a value as a C expression
81
82 For integers this returns a byte-swapped (little-endian) hex string
83 For bytes this returns a hex string, e.g. 0x12
84 For strings this returns a literal string enclosed in quotes
85 For booleans this return 'true'
86
87 Args:
88 type: Data type (fdt_util)
89 value: Data value, as a string of bytes
90 """
91 if ftype == fdt.TYPE_INT:
92 return '%#x' % fdt_util.fdt32_to_cpu(value)
93 elif ftype == fdt.TYPE_BYTE:
94 return '%#x' % ord(value[0])
95 elif ftype == fdt.TYPE_STRING:
96 return '"%s"' % value
97 elif ftype == fdt.TYPE_BOOL:
98 return 'true'
Simon Glassfc3ae9c2017-08-29 14:15:48 -060099 elif ftype == fdt.TYPE_INT64:
100 return '%#x' % value
Simon Glass7a2add12017-06-18 22:09:02 -0600101
102def get_compat_name(node):
103 """Get a node's first compatible string as a C identifier
104
105 Args:
106 node: Node object to check
107 Return:
108 Tuple:
109 C identifier for the first compatible string
110 List of C identifiers for all the other compatible strings
111 (possibly empty)
112 """
113 compat = node.props['compatible'].value
114 aliases = []
115 if isinstance(compat, list):
116 compat, aliases = compat[0], compat[1:]
117 return conv_name_to_c(compat), [conv_name_to_c(a) for a in aliases]
118
119def is_phandle(prop):
120 """Check if a node contains phandles
121
122 We have no reliable way of detecting whether a node uses a phandle
123 or not. As an interim measure, use a list of known property names.
124
125 Args:
126 prop: Prop object to check
127 Return:
128 True if the object value contains phandles, else False
129 """
130 if prop.name in ['clocks']:
131 return True
132 return False
133
134
Simon Glass1f730c82017-06-18 22:08:59 -0600135class DtbPlatdata(object):
Simon Glassd570dec2017-06-18 22:08:58 -0600136 """Provide a means to convert device tree binary data to platform data
137
138 The output of this process is C structures which can be used in space-
139 constrained encvironments where the ~3KB code overhead of device tree
140 code is not affordable.
141
142 Properties:
Simon Glass1f730c82017-06-18 22:08:59 -0600143 _fdt: Fdt object, referencing the device tree
Simon Glassd570dec2017-06-18 22:08:58 -0600144 _dtb_fname: Filename of the input device tree binary file
145 _valid_nodes: A list of Node object with compatible strings
Simon Glasseab3f622017-06-18 22:09:01 -0600146 _include_disabled: true to include nodes marked status = "disabled"
Simon Glass1f730c82017-06-18 22:08:59 -0600147 _phandle_nodes: A dict of nodes indexed by phandle number (1, 2...)
Simon Glassd570dec2017-06-18 22:08:58 -0600148 _outfile: The current output file (sys.stdout or a real file)
149 _lines: Stashed list of output lines for outputting in the future
Simon Glass1f730c82017-06-18 22:08:59 -0600150 _phandle_nodes: A dict of Nodes indexed by phandle (an integer)
Simon Glassd570dec2017-06-18 22:08:58 -0600151 """
Simon Glasseab3f622017-06-18 22:09:01 -0600152 def __init__(self, dtb_fname, include_disabled):
Simon Glass1f730c82017-06-18 22:08:59 -0600153 self._fdt = None
Simon Glassd570dec2017-06-18 22:08:58 -0600154 self._dtb_fname = dtb_fname
155 self._valid_nodes = None
Simon Glasseab3f622017-06-18 22:09:01 -0600156 self._include_disabled = include_disabled
Simon Glass1f730c82017-06-18 22:08:59 -0600157 self._phandle_nodes = {}
Simon Glassd570dec2017-06-18 22:08:58 -0600158 self._outfile = None
159 self._lines = []
160 self._aliases = {}
161
Simon Glass1f730c82017-06-18 22:08:59 -0600162 def setup_output(self, fname):
Simon Glassd570dec2017-06-18 22:08:58 -0600163 """Set up the output destination
164
Simon Glass1f730c82017-06-18 22:08:59 -0600165 Once this is done, future calls to self.out() will output to this
Simon Glassd570dec2017-06-18 22:08:58 -0600166 file.
167
168 Args:
169 fname: Filename to send output to, or '-' for stdout
170 """
171 if fname == '-':
172 self._outfile = sys.stdout
173 else:
174 self._outfile = open(fname, 'w')
175
Simon Glass1f730c82017-06-18 22:08:59 -0600176 def out(self, line):
Simon Glassd570dec2017-06-18 22:08:58 -0600177 """Output a string to the output file
178
179 Args:
Simon Glass1f730c82017-06-18 22:08:59 -0600180 line: String to output
Simon Glassd570dec2017-06-18 22:08:58 -0600181 """
Simon Glass1f730c82017-06-18 22:08:59 -0600182 self._outfile.write(line)
Simon Glassd570dec2017-06-18 22:08:58 -0600183
Simon Glass1f730c82017-06-18 22:08:59 -0600184 def buf(self, line):
Simon Glassd570dec2017-06-18 22:08:58 -0600185 """Buffer up a string to send later
186
187 Args:
Simon Glass1f730c82017-06-18 22:08:59 -0600188 line: String to add to our 'buffer' list
Simon Glassd570dec2017-06-18 22:08:58 -0600189 """
Simon Glass1f730c82017-06-18 22:08:59 -0600190 self._lines.append(line)
Simon Glassd570dec2017-06-18 22:08:58 -0600191
Simon Glass1f730c82017-06-18 22:08:59 -0600192 def get_buf(self):
Simon Glassd570dec2017-06-18 22:08:58 -0600193 """Get the contents of the output buffer, and clear it
194
195 Returns:
196 The output buffer, which is then cleared for future use
197 """
198 lines = self._lines
199 self._lines = []
200 return lines
201
Simon Glass1f730c82017-06-18 22:08:59 -0600202 def scan_dtb(self):
Anatolij Gustschinda707d42017-08-18 17:58:51 +0200203 """Scan the device tree to obtain a tree of nodes and properties
Simon Glassd570dec2017-06-18 22:08:58 -0600204
Simon Glass1f730c82017-06-18 22:08:59 -0600205 Once this is done, self._fdt.GetRoot() can be called to obtain the
Simon Glassd570dec2017-06-18 22:08:58 -0600206 device tree root node, and progress from there.
207 """
Simon Glass1f730c82017-06-18 22:08:59 -0600208 self._fdt = fdt.FdtScan(self._dtb_fname)
209
210 def scan_node(self, root):
211 """Scan a node and subnodes to build a tree of node and phandle info
Simon Glassd570dec2017-06-18 22:08:58 -0600212
Simon Glass1f730c82017-06-18 22:08:59 -0600213 This adds each node to self._valid_nodes and each phandle to
214 self._phandle_nodes.
215
216 Args:
217 root: Root node for scan
218 """
Simon Glassd570dec2017-06-18 22:08:58 -0600219 for node in root.subnodes:
220 if 'compatible' in node.props:
221 status = node.props.get('status')
Simon Glasseab3f622017-06-18 22:09:01 -0600222 if (not self._include_disabled and not status or
Simon Glass1f730c82017-06-18 22:08:59 -0600223 status.value != 'disabled'):
Simon Glassd570dec2017-06-18 22:08:58 -0600224 self._valid_nodes.append(node)
225 phandle_prop = node.props.get('phandle')
226 if phandle_prop:
227 phandle = phandle_prop.GetPhandle()
Simon Glass1f730c82017-06-18 22:08:59 -0600228 self._phandle_nodes[phandle] = node
Simon Glassd570dec2017-06-18 22:08:58 -0600229
230 # recurse to handle any subnodes
Simon Glass1f730c82017-06-18 22:08:59 -0600231 self.scan_node(node)
Simon Glassd570dec2017-06-18 22:08:58 -0600232
Simon Glass1f730c82017-06-18 22:08:59 -0600233 def scan_tree(self):
Simon Glassd570dec2017-06-18 22:08:58 -0600234 """Scan the device tree for useful information
235
236 This fills in the following properties:
Simon Glass1f730c82017-06-18 22:08:59 -0600237 _phandle_nodes: A dict of Nodes indexed by phandle (an integer)
Simon Glassd570dec2017-06-18 22:08:58 -0600238 _valid_nodes: A list of nodes we wish to consider include in the
239 platform data
240 """
Simon Glass1f730c82017-06-18 22:08:59 -0600241 self._phandle_nodes = {}
Simon Glassd570dec2017-06-18 22:08:58 -0600242 self._valid_nodes = []
Simon Glass1f730c82017-06-18 22:08:59 -0600243 return self.scan_node(self._fdt.GetRoot())
Simon Glassd570dec2017-06-18 22:08:58 -0600244
Simon Glass1b1fe412017-08-29 14:15:50 -0600245 @staticmethod
246 def get_num_cells(node):
247 """Get the number of cells in addresses and sizes for this node
248
249 Args:
250 node: Node to check
251
252 Returns:
253 Tuple:
254 Number of address cells for this node
255 Number of size cells for this node
256 """
257 parent = node.parent
258 na, ns = 2, 2
259 if parent:
260 na_prop = parent.props.get('#address-cells')
261 ns_prop = parent.props.get('#size-cells')
262 if na_prop:
263 na = fdt_util.fdt32_to_cpu(na_prop.value)
264 if ns_prop:
265 ns = fdt_util.fdt32_to_cpu(ns_prop.value)
266 return na, ns
267
268 def scan_reg_sizes(self):
269 """Scan for 64-bit 'reg' properties and update the values
270
271 This finds 'reg' properties with 64-bit data and converts the value to
272 an array of 64-values. This allows it to be output in a way that the
273 C code can read.
274 """
275 for node in self._valid_nodes:
276 reg = node.props.get('reg')
277 if not reg:
278 continue
279 na, ns = self.get_num_cells(node)
280 total = na + ns
281
282 if reg.type != fdt.TYPE_INT:
283 raise ValueError("Node '%s' reg property is not an int")
284 if len(reg.value) % total:
285 raise ValueError("Node '%s' reg property has %d cells "
286 'which is not a multiple of na + ns = %d + %d)' %
287 (node.name, len(reg.value), na, ns))
288 reg.na = na
289 reg.ns = ns
290 if na != 1 or ns != 1:
291 reg.type = fdt.TYPE_INT64
292 i = 0
293 new_value = []
294 val = reg.value
295 if not isinstance(val, list):
296 val = [val]
297 while i < len(val):
298 addr = fdt_util.fdt_cells_to_cpu(val[i:], reg.na)
299 i += na
300 size = fdt_util.fdt_cells_to_cpu(val[i:], reg.ns)
301 i += ns
302 new_value += [addr, size]
303 reg.value = new_value
304
Simon Glass1f730c82017-06-18 22:08:59 -0600305 def scan_structs(self):
Simon Glassd570dec2017-06-18 22:08:58 -0600306 """Scan the device tree building up the C structures we will use.
307
308 Build a dict keyed by C struct name containing a dict of Prop
309 object for each struct field (keyed by property name). Where the
310 same struct appears multiple times, try to use the 'widest'
311 property, i.e. the one with a type which can express all others.
312
313 Once the widest property is determined, all other properties are
314 updated to match that width.
315 """
316 structs = {}
317 for node in self._valid_nodes:
Simon Glass7a2add12017-06-18 22:09:02 -0600318 node_name, _ = get_compat_name(node)
Simon Glassd570dec2017-06-18 22:08:58 -0600319 fields = {}
320
321 # Get a list of all the valid properties in this node.
322 for name, prop in node.props.items():
323 if name not in PROP_IGNORE_LIST and name[0] != '#':
324 fields[name] = copy.deepcopy(prop)
325
326 # If we've seen this node_name before, update the existing struct.
327 if node_name in structs:
328 struct = structs[node_name]
329 for name, prop in fields.items():
330 oldprop = struct.get(name)
331 if oldprop:
332 oldprop.Widen(prop)
333 else:
334 struct[name] = prop
335
336 # Otherwise store this as a new struct.
337 else:
338 structs[node_name] = fields
339
340 upto = 0
341 for node in self._valid_nodes:
Simon Glass7a2add12017-06-18 22:09:02 -0600342 node_name, _ = get_compat_name(node)
Simon Glassd570dec2017-06-18 22:08:58 -0600343 struct = structs[node_name]
344 for name, prop in node.props.items():
345 if name not in PROP_IGNORE_LIST and name[0] != '#':
346 prop.Widen(struct[name])
347 upto += 1
348
Simon Glass7a2add12017-06-18 22:09:02 -0600349 struct_name, aliases = get_compat_name(node)
Simon Glassd570dec2017-06-18 22:08:58 -0600350 for alias in aliases:
351 self._aliases[alias] = struct_name
352
353 return structs
354
Simon Glass1f730c82017-06-18 22:08:59 -0600355 def scan_phandles(self):
Simon Glassd570dec2017-06-18 22:08:58 -0600356 """Figure out what phandles each node uses
357
358 We need to be careful when outputing nodes that use phandles since
359 they must come after the declaration of the phandles in the C file.
360 Otherwise we get a compiler error since the phandle struct is not yet
361 declared.
362
363 This function adds to each node a list of phandle nodes that the node
364 depends on. This allows us to output things in the right order.
365 """
366 for node in self._valid_nodes:
367 node.phandles = set()
368 for pname, prop in node.props.items():
369 if pname in PROP_IGNORE_LIST or pname[0] == '#':
370 continue
Simon Glass1f730c82017-06-18 22:08:59 -0600371 if isinstance(prop.value, list):
Simon Glass7a2add12017-06-18 22:09:02 -0600372 if is_phandle(prop):
Simon Glassd570dec2017-06-18 22:08:58 -0600373 # Process the list as pairs of (phandle, id)
Simon Glass1f730c82017-06-18 22:08:59 -0600374 value_it = iter(prop.value)
375 for phandle_cell, _ in zip(value_it, value_it):
Simon Glassd570dec2017-06-18 22:08:58 -0600376 phandle = fdt_util.fdt32_to_cpu(phandle_cell)
Simon Glass1f730c82017-06-18 22:08:59 -0600377 target_node = self._phandle_nodes[phandle]
Simon Glassd570dec2017-06-18 22:08:58 -0600378 node.phandles.add(target_node)
379
380
Simon Glass1f730c82017-06-18 22:08:59 -0600381 def generate_structs(self, structs):
Simon Glassd570dec2017-06-18 22:08:58 -0600382 """Generate struct defintions for the platform data
383
384 This writes out the body of a header file consisting of structure
385 definitions for node in self._valid_nodes. See the documentation in
386 README.of-plat for more information.
387 """
Simon Glass1f730c82017-06-18 22:08:59 -0600388 self.out('#include <stdbool.h>\n')
389 self.out('#include <libfdt.h>\n')
Simon Glassd570dec2017-06-18 22:08:58 -0600390
391 # Output the struct definition
392 for name in sorted(structs):
Simon Glass1f730c82017-06-18 22:08:59 -0600393 self.out('struct %s%s {\n' % (STRUCT_PREFIX, name))
Simon Glassd570dec2017-06-18 22:08:58 -0600394 for pname in sorted(structs[name]):
395 prop = structs[name][pname]
Simon Glass7a2add12017-06-18 22:09:02 -0600396 if is_phandle(prop):
Simon Glassd570dec2017-06-18 22:08:58 -0600397 # For phandles, include a reference to the target
Simon Glass1f730c82017-06-18 22:08:59 -0600398 self.out('\t%s%s[%d]' % (tab_to(2, 'struct phandle_2_cell'),
399 conv_name_to_c(prop.name),
Simon Glassd570dec2017-06-18 22:08:58 -0600400 len(prop.value) / 2))
401 else:
402 ptype = TYPE_NAMES[prop.type]
Simon Glass1f730c82017-06-18 22:08:59 -0600403 self.out('\t%s%s' % (tab_to(2, ptype),
404 conv_name_to_c(prop.name)))
405 if isinstance(prop.value, list):
406 self.out('[%d]' % len(prop.value))
407 self.out(';\n')
408 self.out('};\n')
Simon Glassd570dec2017-06-18 22:08:58 -0600409
410 for alias, struct_name in self._aliases.iteritems():
Simon Glass1f730c82017-06-18 22:08:59 -0600411 self.out('#define %s%s %s%s\n'% (STRUCT_PREFIX, alias,
Simon Glassd570dec2017-06-18 22:08:58 -0600412 STRUCT_PREFIX, struct_name))
413
Simon Glass1f730c82017-06-18 22:08:59 -0600414 def output_node(self, node):
Simon Glassd570dec2017-06-18 22:08:58 -0600415 """Output the C code for a node
416
417 Args:
418 node: node to output
419 """
Simon Glass7a2add12017-06-18 22:09:02 -0600420 struct_name, _ = get_compat_name(node)
Simon Glass1f730c82017-06-18 22:08:59 -0600421 var_name = conv_name_to_c(node.name)
422 self.buf('static struct %s%s %s%s = {\n' %
423 (STRUCT_PREFIX, struct_name, VAL_PREFIX, var_name))
Simon Glassd570dec2017-06-18 22:08:58 -0600424 for pname, prop in node.props.items():
425 if pname in PROP_IGNORE_LIST or pname[0] == '#':
426 continue
Simon Glass1f730c82017-06-18 22:08:59 -0600427 member_name = conv_name_to_c(prop.name)
428 self.buf('\t%s= ' % tab_to(3, '.' + member_name))
Simon Glassd570dec2017-06-18 22:08:58 -0600429
430 # Special handling for lists
Simon Glass1f730c82017-06-18 22:08:59 -0600431 if isinstance(prop.value, list):
432 self.buf('{')
Simon Glassd570dec2017-06-18 22:08:58 -0600433 vals = []
434 # For phandles, output a reference to the platform data
435 # of the target node.
Simon Glass7a2add12017-06-18 22:09:02 -0600436 if is_phandle(prop):
Simon Glassd570dec2017-06-18 22:08:58 -0600437 # Process the list as pairs of (phandle, id)
Simon Glass1f730c82017-06-18 22:08:59 -0600438 value_it = iter(prop.value)
439 for phandle_cell, id_cell in zip(value_it, value_it):
Simon Glassd570dec2017-06-18 22:08:58 -0600440 phandle = fdt_util.fdt32_to_cpu(phandle_cell)
Simon Glass1f730c82017-06-18 22:08:59 -0600441 id_num = fdt_util.fdt32_to_cpu(id_cell)
442 target_node = self._phandle_nodes[phandle]
443 name = conv_name_to_c(target_node.name)
444 vals.append('{&%s%s, %d}' % (VAL_PREFIX, name, id_num))
Simon Glassd570dec2017-06-18 22:08:58 -0600445 else:
446 for val in prop.value:
Simon Glass7a2add12017-06-18 22:09:02 -0600447 vals.append(get_value(prop.type, val))
Simon Glass131e0b02017-08-29 14:15:49 -0600448
449 # Put 8 values per line to avoid very long lines.
450 for i in xrange(0, len(vals), 8):
451 if i:
452 self.buf(',\n\t\t')
453 self.buf(', '.join(vals[i:i + 8]))
Simon Glass1f730c82017-06-18 22:08:59 -0600454 self.buf('}')
Simon Glassd570dec2017-06-18 22:08:58 -0600455 else:
Simon Glass7a2add12017-06-18 22:09:02 -0600456 self.buf(get_value(prop.type, prop.value))
Simon Glass1f730c82017-06-18 22:08:59 -0600457 self.buf(',\n')
458 self.buf('};\n')
Simon Glassd570dec2017-06-18 22:08:58 -0600459
460 # Add a device declaration
Simon Glass1f730c82017-06-18 22:08:59 -0600461 self.buf('U_BOOT_DEVICE(%s) = {\n' % var_name)
462 self.buf('\t.name\t\t= "%s",\n' % struct_name)
463 self.buf('\t.platdata\t= &%s%s,\n' % (VAL_PREFIX, var_name))
464 self.buf('\t.platdata_size\t= sizeof(%s%s),\n' % (VAL_PREFIX, var_name))
465 self.buf('};\n')
466 self.buf('\n')
Simon Glassd570dec2017-06-18 22:08:58 -0600467
Simon Glass1f730c82017-06-18 22:08:59 -0600468 self.out(''.join(self.get_buf()))
Simon Glassd570dec2017-06-18 22:08:58 -0600469
Simon Glass1f730c82017-06-18 22:08:59 -0600470 def generate_tables(self):
Simon Glassd570dec2017-06-18 22:08:58 -0600471 """Generate device defintions for the platform data
472
473 This writes out C platform data initialisation data and
474 U_BOOT_DEVICE() declarations for each valid node. Where a node has
475 multiple compatible strings, a #define is used to make them equivalent.
476
477 See the documentation in doc/driver-model/of-plat.txt for more
478 information.
479 """
Simon Glass1f730c82017-06-18 22:08:59 -0600480 self.out('#include <common.h>\n')
481 self.out('#include <dm.h>\n')
482 self.out('#include <dt-structs.h>\n')
483 self.out('\n')
Simon Glassd570dec2017-06-18 22:08:58 -0600484 nodes_to_output = list(self._valid_nodes)
485
486 # Keep outputing nodes until there is none left
487 while nodes_to_output:
488 node = nodes_to_output[0]
489 # Output all the node's dependencies first
490 for req_node in node.phandles:
491 if req_node in nodes_to_output:
Simon Glass1f730c82017-06-18 22:08:59 -0600492 self.output_node(req_node)
Simon Glassd570dec2017-06-18 22:08:58 -0600493 nodes_to_output.remove(req_node)
Simon Glass1f730c82017-06-18 22:08:59 -0600494 self.output_node(node)
Simon Glassd570dec2017-06-18 22:08:58 -0600495 nodes_to_output.remove(node)
Simon Glass3fa797a2017-06-18 22:09:03 -0600496
497
498def run_steps(args, dtb_file, include_disabled, output):
499 """Run all the steps of the dtoc tool
500
501 Args:
502 args: List of non-option arguments provided to the problem
503 dtb_file: Filename of dtb file to process
504 include_disabled: True to include disabled nodes
505 output: Name of output file
506 """
507 if not args:
508 raise ValueError('Please specify a command: struct, platdata')
509
510 plat = DtbPlatdata(dtb_file, include_disabled)
511 plat.scan_dtb()
512 plat.scan_tree()
Simon Glass1b1fe412017-08-29 14:15:50 -0600513 plat.scan_reg_sizes()
Simon Glass3fa797a2017-06-18 22:09:03 -0600514 plat.setup_output(output)
515 structs = plat.scan_structs()
516 plat.scan_phandles()
517
518 for cmd in args[0].split(','):
519 if cmd == 'struct':
520 plat.generate_structs(structs)
521 elif cmd == 'platdata':
522 plat.generate_tables()
523 else:
524 raise ValueError("Unknown command '%s': (use: struct, platdata)" %
525 cmd)