blob: a483d6c8757ccd9c95d46fea3e3bc72c12e6bed4 [file] [log] [blame]
Simon Glass7581c012017-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 Glass2be282c2017-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 Glass7581c012017-06-18 22:08:58 -060015import copy
Simon Glass2be282c2017-06-18 22:08:59 -060016import sys
Simon Glass7581c012017-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 Glassfbdfd222017-08-29 14:15:48 -060041 fdt.TYPE_INT64: 'fdt64_t',
Simon Glass2be282c2017-06-18 22:08:59 -060042}
Simon Glass7581c012017-06-18 22:08:58 -060043
44STRUCT_PREFIX = 'dtd_'
45VAL_PREFIX = 'dtv_'
46
Simon Glass2be282c2017-06-18 22:08:59 -060047def conv_name_to_c(name):
Simon Glass7581c012017-06-18 22:08:58 -060048 """Convert a device-tree name to a C identifier
49
Simon Glass30107b02017-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 Glass7581c012017-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 Glass2be282c2017-06-18 22:08:59 -060058 new = name.replace('@', '_at_')
59 new = new.replace('-', '_')
60 new = new.replace(',', '_')
61 new = new.replace('.', '_')
Simon Glass2be282c2017-06-18 22:08:59 -060062 return new
Simon Glass7581c012017-06-18 22:08:58 -060063
Simon Glass2be282c2017-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 Glass7581c012017-06-18 22:08:58 -060066
Simon Glass2be282c2017-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 Glass56e0bbe2017-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 Glassfbdfd222017-08-29 14:15:48 -060099 elif ftype == fdt.TYPE_INT64:
100 return '%#x' % value
Simon Glass56e0bbe2017-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
Simon Glass56e0bbe2017-06-18 22:09:02 -0600119
Simon Glass2be282c2017-06-18 22:08:59 -0600120class DtbPlatdata(object):
Simon Glass7581c012017-06-18 22:08:58 -0600121 """Provide a means to convert device tree binary data to platform data
122
123 The output of this process is C structures which can be used in space-
124 constrained encvironments where the ~3KB code overhead of device tree
125 code is not affordable.
126
127 Properties:
Simon Glass2be282c2017-06-18 22:08:59 -0600128 _fdt: Fdt object, referencing the device tree
Simon Glass7581c012017-06-18 22:08:58 -0600129 _dtb_fname: Filename of the input device tree binary file
130 _valid_nodes: A list of Node object with compatible strings
Simon Glasse36024b2017-06-18 22:09:01 -0600131 _include_disabled: true to include nodes marked status = "disabled"
Simon Glass7581c012017-06-18 22:08:58 -0600132 _outfile: The current output file (sys.stdout or a real file)
133 _lines: Stashed list of output lines for outputting in the future
Simon Glass7581c012017-06-18 22:08:58 -0600134 """
Simon Glasse36024b2017-06-18 22:09:01 -0600135 def __init__(self, dtb_fname, include_disabled):
Simon Glass2be282c2017-06-18 22:08:59 -0600136 self._fdt = None
Simon Glass7581c012017-06-18 22:08:58 -0600137 self._dtb_fname = dtb_fname
138 self._valid_nodes = None
Simon Glasse36024b2017-06-18 22:09:01 -0600139 self._include_disabled = include_disabled
Simon Glass7581c012017-06-18 22:08:58 -0600140 self._outfile = None
141 self._lines = []
142 self._aliases = {}
143
Simon Glass2be282c2017-06-18 22:08:59 -0600144 def setup_output(self, fname):
Simon Glass7581c012017-06-18 22:08:58 -0600145 """Set up the output destination
146
Simon Glass2be282c2017-06-18 22:08:59 -0600147 Once this is done, future calls to self.out() will output to this
Simon Glass7581c012017-06-18 22:08:58 -0600148 file.
149
150 Args:
151 fname: Filename to send output to, or '-' for stdout
152 """
153 if fname == '-':
154 self._outfile = sys.stdout
155 else:
156 self._outfile = open(fname, 'w')
157
Simon Glass2be282c2017-06-18 22:08:59 -0600158 def out(self, line):
Simon Glass7581c012017-06-18 22:08:58 -0600159 """Output a string to the output file
160
161 Args:
Simon Glass2be282c2017-06-18 22:08:59 -0600162 line: String to output
Simon Glass7581c012017-06-18 22:08:58 -0600163 """
Simon Glass2be282c2017-06-18 22:08:59 -0600164 self._outfile.write(line)
Simon Glass7581c012017-06-18 22:08:58 -0600165
Simon Glass2be282c2017-06-18 22:08:59 -0600166 def buf(self, line):
Simon Glass7581c012017-06-18 22:08:58 -0600167 """Buffer up a string to send later
168
169 Args:
Simon Glass2be282c2017-06-18 22:08:59 -0600170 line: String to add to our 'buffer' list
Simon Glass7581c012017-06-18 22:08:58 -0600171 """
Simon Glass2be282c2017-06-18 22:08:59 -0600172 self._lines.append(line)
Simon Glass7581c012017-06-18 22:08:58 -0600173
Simon Glass2be282c2017-06-18 22:08:59 -0600174 def get_buf(self):
Simon Glass7581c012017-06-18 22:08:58 -0600175 """Get the contents of the output buffer, and clear it
176
177 Returns:
178 The output buffer, which is then cleared for future use
179 """
180 lines = self._lines
181 self._lines = []
182 return lines
183
Simon Glass2925c262017-08-29 14:15:54 -0600184 def is_phandle(self, prop):
185 """Check if a node contains phandles
186
187 We have no reliable way of detecting whether a node uses a phandle
188 or not. As an interim measure, use a list of known property names.
189
190 Args:
191 prop: Prop object to check
192 Return:
193 True if the object value contains phandles, else False
194 """
195 if prop.name in ['clocks']:
196 return True
197 return False
198
Simon Glass2be282c2017-06-18 22:08:59 -0600199 def scan_dtb(self):
Anatolij Gustschinf1a7ba12017-08-18 17:58:51 +0200200 """Scan the device tree to obtain a tree of nodes and properties
Simon Glass7581c012017-06-18 22:08:58 -0600201
Simon Glass2be282c2017-06-18 22:08:59 -0600202 Once this is done, self._fdt.GetRoot() can be called to obtain the
Simon Glass7581c012017-06-18 22:08:58 -0600203 device tree root node, and progress from there.
204 """
Simon Glass2be282c2017-06-18 22:08:59 -0600205 self._fdt = fdt.FdtScan(self._dtb_fname)
Simon Glass7581c012017-06-18 22:08:58 -0600206
Simon Glass2be282c2017-06-18 22:08:59 -0600207 def scan_node(self, root):
208 """Scan a node and subnodes to build a tree of node and phandle info
209
Simon Glass72ab7c52017-08-29 14:15:53 -0600210 This adds each node to self._valid_nodes.
Simon Glass2be282c2017-06-18 22:08:59 -0600211
212 Args:
213 root: Root node for scan
214 """
Simon Glass7581c012017-06-18 22:08:58 -0600215 for node in root.subnodes:
216 if 'compatible' in node.props:
217 status = node.props.get('status')
Simon Glasse36024b2017-06-18 22:09:01 -0600218 if (not self._include_disabled and not status or
Simon Glass2be282c2017-06-18 22:08:59 -0600219 status.value != 'disabled'):
Simon Glass7581c012017-06-18 22:08:58 -0600220 self._valid_nodes.append(node)
Simon Glass7581c012017-06-18 22:08:58 -0600221
222 # recurse to handle any subnodes
Simon Glass2be282c2017-06-18 22:08:59 -0600223 self.scan_node(node)
Simon Glass7581c012017-06-18 22:08:58 -0600224
Simon Glass2be282c2017-06-18 22:08:59 -0600225 def scan_tree(self):
Simon Glass7581c012017-06-18 22:08:58 -0600226 """Scan the device tree for useful information
227
228 This fills in the following properties:
Simon Glass7581c012017-06-18 22:08:58 -0600229 _valid_nodes: A list of nodes we wish to consider include in the
230 platform data
231 """
Simon Glass7581c012017-06-18 22:08:58 -0600232 self._valid_nodes = []
Simon Glass2be282c2017-06-18 22:08:59 -0600233 return self.scan_node(self._fdt.GetRoot())
Simon Glass7581c012017-06-18 22:08:58 -0600234
Simon Glassc20ee0e2017-08-29 14:15:50 -0600235 @staticmethod
236 def get_num_cells(node):
237 """Get the number of cells in addresses and sizes for this node
238
239 Args:
240 node: Node to check
241
242 Returns:
243 Tuple:
244 Number of address cells for this node
245 Number of size cells for this node
246 """
247 parent = node.parent
248 na, ns = 2, 2
249 if parent:
250 na_prop = parent.props.get('#address-cells')
251 ns_prop = parent.props.get('#size-cells')
252 if na_prop:
253 na = fdt_util.fdt32_to_cpu(na_prop.value)
254 if ns_prop:
255 ns = fdt_util.fdt32_to_cpu(ns_prop.value)
256 return na, ns
257
258 def scan_reg_sizes(self):
259 """Scan for 64-bit 'reg' properties and update the values
260
261 This finds 'reg' properties with 64-bit data and converts the value to
262 an array of 64-values. This allows it to be output in a way that the
263 C code can read.
264 """
265 for node in self._valid_nodes:
266 reg = node.props.get('reg')
267 if not reg:
268 continue
269 na, ns = self.get_num_cells(node)
270 total = na + ns
271
272 if reg.type != fdt.TYPE_INT:
273 raise ValueError("Node '%s' reg property is not an int")
274 if len(reg.value) % total:
275 raise ValueError("Node '%s' reg property has %d cells "
276 'which is not a multiple of na + ns = %d + %d)' %
277 (node.name, len(reg.value), na, ns))
278 reg.na = na
279 reg.ns = ns
280 if na != 1 or ns != 1:
281 reg.type = fdt.TYPE_INT64
282 i = 0
283 new_value = []
284 val = reg.value
285 if not isinstance(val, list):
286 val = [val]
287 while i < len(val):
288 addr = fdt_util.fdt_cells_to_cpu(val[i:], reg.na)
289 i += na
290 size = fdt_util.fdt_cells_to_cpu(val[i:], reg.ns)
291 i += ns
292 new_value += [addr, size]
293 reg.value = new_value
294
Simon Glass2be282c2017-06-18 22:08:59 -0600295 def scan_structs(self):
Simon Glass7581c012017-06-18 22:08:58 -0600296 """Scan the device tree building up the C structures we will use.
297
298 Build a dict keyed by C struct name containing a dict of Prop
299 object for each struct field (keyed by property name). Where the
300 same struct appears multiple times, try to use the 'widest'
301 property, i.e. the one with a type which can express all others.
302
303 Once the widest property is determined, all other properties are
304 updated to match that width.
305 """
306 structs = {}
307 for node in self._valid_nodes:
Simon Glass56e0bbe2017-06-18 22:09:02 -0600308 node_name, _ = get_compat_name(node)
Simon Glass7581c012017-06-18 22:08:58 -0600309 fields = {}
310
311 # Get a list of all the valid properties in this node.
312 for name, prop in node.props.items():
313 if name not in PROP_IGNORE_LIST and name[0] != '#':
314 fields[name] = copy.deepcopy(prop)
315
316 # If we've seen this node_name before, update the existing struct.
317 if node_name in structs:
318 struct = structs[node_name]
319 for name, prop in fields.items():
320 oldprop = struct.get(name)
321 if oldprop:
322 oldprop.Widen(prop)
323 else:
324 struct[name] = prop
325
326 # Otherwise store this as a new struct.
327 else:
328 structs[node_name] = fields
329
330 upto = 0
331 for node in self._valid_nodes:
Simon Glass56e0bbe2017-06-18 22:09:02 -0600332 node_name, _ = get_compat_name(node)
Simon Glass7581c012017-06-18 22:08:58 -0600333 struct = structs[node_name]
334 for name, prop in node.props.items():
335 if name not in PROP_IGNORE_LIST and name[0] != '#':
336 prop.Widen(struct[name])
337 upto += 1
338
Simon Glass56e0bbe2017-06-18 22:09:02 -0600339 struct_name, aliases = get_compat_name(node)
Simon Glass7581c012017-06-18 22:08:58 -0600340 for alias in aliases:
341 self._aliases[alias] = struct_name
342
343 return structs
344
Simon Glass2be282c2017-06-18 22:08:59 -0600345 def scan_phandles(self):
Simon Glass7581c012017-06-18 22:08:58 -0600346 """Figure out what phandles each node uses
347
348 We need to be careful when outputing nodes that use phandles since
349 they must come after the declaration of the phandles in the C file.
350 Otherwise we get a compiler error since the phandle struct is not yet
351 declared.
352
353 This function adds to each node a list of phandle nodes that the node
354 depends on. This allows us to output things in the right order.
355 """
356 for node in self._valid_nodes:
357 node.phandles = set()
358 for pname, prop in node.props.items():
359 if pname in PROP_IGNORE_LIST or pname[0] == '#':
360 continue
Simon Glass2be282c2017-06-18 22:08:59 -0600361 if isinstance(prop.value, list):
Simon Glass2925c262017-08-29 14:15:54 -0600362 if self.is_phandle(prop):
Simon Glass7581c012017-06-18 22:08:58 -0600363 # Process the list as pairs of (phandle, id)
Simon Glass2be282c2017-06-18 22:08:59 -0600364 value_it = iter(prop.value)
365 for phandle_cell, _ in zip(value_it, value_it):
Simon Glass7581c012017-06-18 22:08:58 -0600366 phandle = fdt_util.fdt32_to_cpu(phandle_cell)
Simon Glass72ab7c52017-08-29 14:15:53 -0600367 target_node = self._fdt.phandle_to_node[phandle]
Simon Glass7581c012017-06-18 22:08:58 -0600368 node.phandles.add(target_node)
369
370
Simon Glass2be282c2017-06-18 22:08:59 -0600371 def generate_structs(self, structs):
Simon Glass7581c012017-06-18 22:08:58 -0600372 """Generate struct defintions for the platform data
373
374 This writes out the body of a header file consisting of structure
375 definitions for node in self._valid_nodes. See the documentation in
376 README.of-plat for more information.
377 """
Simon Glass2be282c2017-06-18 22:08:59 -0600378 self.out('#include <stdbool.h>\n')
379 self.out('#include <libfdt.h>\n')
Simon Glass7581c012017-06-18 22:08:58 -0600380
381 # Output the struct definition
382 for name in sorted(structs):
Simon Glass2be282c2017-06-18 22:08:59 -0600383 self.out('struct %s%s {\n' % (STRUCT_PREFIX, name))
Simon Glass7581c012017-06-18 22:08:58 -0600384 for pname in sorted(structs[name]):
385 prop = structs[name][pname]
Simon Glass2925c262017-08-29 14:15:54 -0600386 if self.is_phandle(prop):
Simon Glass7581c012017-06-18 22:08:58 -0600387 # For phandles, include a reference to the target
Simon Glass2be282c2017-06-18 22:08:59 -0600388 self.out('\t%s%s[%d]' % (tab_to(2, 'struct phandle_2_cell'),
389 conv_name_to_c(prop.name),
Simon Glass7581c012017-06-18 22:08:58 -0600390 len(prop.value) / 2))
391 else:
392 ptype = TYPE_NAMES[prop.type]
Simon Glass2be282c2017-06-18 22:08:59 -0600393 self.out('\t%s%s' % (tab_to(2, ptype),
394 conv_name_to_c(prop.name)))
395 if isinstance(prop.value, list):
396 self.out('[%d]' % len(prop.value))
397 self.out(';\n')
398 self.out('};\n')
Simon Glass7581c012017-06-18 22:08:58 -0600399
400 for alias, struct_name in self._aliases.iteritems():
Simon Glass2be282c2017-06-18 22:08:59 -0600401 self.out('#define %s%s %s%s\n'% (STRUCT_PREFIX, alias,
Simon Glass7581c012017-06-18 22:08:58 -0600402 STRUCT_PREFIX, struct_name))
403
Simon Glass2be282c2017-06-18 22:08:59 -0600404 def output_node(self, node):
Simon Glass7581c012017-06-18 22:08:58 -0600405 """Output the C code for a node
406
407 Args:
408 node: node to output
409 """
Simon Glass56e0bbe2017-06-18 22:09:02 -0600410 struct_name, _ = get_compat_name(node)
Simon Glass2be282c2017-06-18 22:08:59 -0600411 var_name = conv_name_to_c(node.name)
412 self.buf('static struct %s%s %s%s = {\n' %
413 (STRUCT_PREFIX, struct_name, VAL_PREFIX, var_name))
Simon Glass7581c012017-06-18 22:08:58 -0600414 for pname, prop in node.props.items():
415 if pname in PROP_IGNORE_LIST or pname[0] == '#':
416 continue
Simon Glass2be282c2017-06-18 22:08:59 -0600417 member_name = conv_name_to_c(prop.name)
418 self.buf('\t%s= ' % tab_to(3, '.' + member_name))
Simon Glass7581c012017-06-18 22:08:58 -0600419
420 # Special handling for lists
Simon Glass2be282c2017-06-18 22:08:59 -0600421 if isinstance(prop.value, list):
422 self.buf('{')
Simon Glass7581c012017-06-18 22:08:58 -0600423 vals = []
424 # For phandles, output a reference to the platform data
425 # of the target node.
Simon Glass2925c262017-08-29 14:15:54 -0600426 if self.is_phandle(prop):
Simon Glass7581c012017-06-18 22:08:58 -0600427 # Process the list as pairs of (phandle, id)
Simon Glass2be282c2017-06-18 22:08:59 -0600428 value_it = iter(prop.value)
429 for phandle_cell, id_cell in zip(value_it, value_it):
Simon Glass7581c012017-06-18 22:08:58 -0600430 phandle = fdt_util.fdt32_to_cpu(phandle_cell)
Simon Glass2be282c2017-06-18 22:08:59 -0600431 id_num = fdt_util.fdt32_to_cpu(id_cell)
Simon Glass72ab7c52017-08-29 14:15:53 -0600432 target_node = self._fdt.phandle_to_node[phandle]
Simon Glass2be282c2017-06-18 22:08:59 -0600433 name = conv_name_to_c(target_node.name)
434 vals.append('{&%s%s, %d}' % (VAL_PREFIX, name, id_num))
Simon Glass7581c012017-06-18 22:08:58 -0600435 else:
436 for val in prop.value:
Simon Glass56e0bbe2017-06-18 22:09:02 -0600437 vals.append(get_value(prop.type, val))
Simon Glass21d54ac2017-08-29 14:15:49 -0600438
439 # Put 8 values per line to avoid very long lines.
440 for i in xrange(0, len(vals), 8):
441 if i:
442 self.buf(',\n\t\t')
443 self.buf(', '.join(vals[i:i + 8]))
Simon Glass2be282c2017-06-18 22:08:59 -0600444 self.buf('}')
Simon Glass7581c012017-06-18 22:08:58 -0600445 else:
Simon Glass56e0bbe2017-06-18 22:09:02 -0600446 self.buf(get_value(prop.type, prop.value))
Simon Glass2be282c2017-06-18 22:08:59 -0600447 self.buf(',\n')
448 self.buf('};\n')
Simon Glass7581c012017-06-18 22:08:58 -0600449
450 # Add a device declaration
Simon Glass2be282c2017-06-18 22:08:59 -0600451 self.buf('U_BOOT_DEVICE(%s) = {\n' % var_name)
452 self.buf('\t.name\t\t= "%s",\n' % struct_name)
453 self.buf('\t.platdata\t= &%s%s,\n' % (VAL_PREFIX, var_name))
454 self.buf('\t.platdata_size\t= sizeof(%s%s),\n' % (VAL_PREFIX, var_name))
455 self.buf('};\n')
456 self.buf('\n')
Simon Glass7581c012017-06-18 22:08:58 -0600457
Simon Glass2be282c2017-06-18 22:08:59 -0600458 self.out(''.join(self.get_buf()))
Simon Glass7581c012017-06-18 22:08:58 -0600459
Simon Glass2be282c2017-06-18 22:08:59 -0600460 def generate_tables(self):
Simon Glass7581c012017-06-18 22:08:58 -0600461 """Generate device defintions for the platform data
462
463 This writes out C platform data initialisation data and
464 U_BOOT_DEVICE() declarations for each valid node. Where a node has
465 multiple compatible strings, a #define is used to make them equivalent.
466
467 See the documentation in doc/driver-model/of-plat.txt for more
468 information.
469 """
Simon Glass2be282c2017-06-18 22:08:59 -0600470 self.out('#include <common.h>\n')
471 self.out('#include <dm.h>\n')
472 self.out('#include <dt-structs.h>\n')
473 self.out('\n')
Simon Glass7581c012017-06-18 22:08:58 -0600474 nodes_to_output = list(self._valid_nodes)
475
476 # Keep outputing nodes until there is none left
477 while nodes_to_output:
478 node = nodes_to_output[0]
479 # Output all the node's dependencies first
480 for req_node in node.phandles:
481 if req_node in nodes_to_output:
Simon Glass2be282c2017-06-18 22:08:59 -0600482 self.output_node(req_node)
Simon Glass7581c012017-06-18 22:08:58 -0600483 nodes_to_output.remove(req_node)
Simon Glass2be282c2017-06-18 22:08:59 -0600484 self.output_node(node)
Simon Glass7581c012017-06-18 22:08:58 -0600485 nodes_to_output.remove(node)
Simon Glassfa0ea5b2017-06-18 22:09:03 -0600486
487
488def run_steps(args, dtb_file, include_disabled, output):
489 """Run all the steps of the dtoc tool
490
491 Args:
492 args: List of non-option arguments provided to the problem
493 dtb_file: Filename of dtb file to process
494 include_disabled: True to include disabled nodes
495 output: Name of output file
496 """
497 if not args:
498 raise ValueError('Please specify a command: struct, platdata')
499
500 plat = DtbPlatdata(dtb_file, include_disabled)
501 plat.scan_dtb()
502 plat.scan_tree()
Simon Glassc20ee0e2017-08-29 14:15:50 -0600503 plat.scan_reg_sizes()
Simon Glassfa0ea5b2017-06-18 22:09:03 -0600504 plat.setup_output(output)
505 structs = plat.scan_structs()
506 plat.scan_phandles()
507
508 for cmd in args[0].split(','):
509 if cmd == 'struct':
510 plat.generate_structs(structs)
511 elif cmd == 'platdata':
512 plat.generate_tables()
513 else:
514 raise ValueError("Unknown command '%s': (use: struct, platdata)" %
515 cmd)