blob: b0407937723e836b7a4f5fa04a8e32a9da77239e [file] [log] [blame]
Simon Glassfa8974d2016-07-04 11:58:08 -06001#!/usr/bin/python
Tom Rini10e47792018-05-06 17:58:06 -04002# SPDX-License-Identifier: GPL-2.0+
Simon Glassfa8974d2016-07-04 11:58:08 -06003#
4# Copyright (C) 2016 Google, Inc
5# Written by Simon Glass <sjg@chromium.org>
6#
Simon Glassfa8974d2016-07-04 11:58:08 -06007
Simon Glassfe599c72018-07-17 13:25:31 -06008# Utility functions for reading from a device tree. Once the upstream pylibfdt
9# implementation advances far enough, we should be able to drop these.
10
Simon Glassefc9bf62016-07-25 18:59:10 -060011import os
Simon Glassfa8974d2016-07-04 11:58:08 -060012import struct
Paul Burton307f1fa2016-09-27 16:03:57 +010013import sys
Simon Glassefc9bf62016-07-25 18:59:10 -060014import tempfile
15
Simon Glassa997ea52020-04-17 18:09:04 -060016from patman import command
17from patman import tools
Simon Glassfa8974d2016-07-04 11:58:08 -060018
Simon Glassfa8974d2016-07-04 11:58:08 -060019def fdt32_to_cpu(val):
20 """Convert a device tree cell to an integer
21
22 Args:
23 Value to convert (4-character string representing the cell value)
24
25 Return:
26 A native-endian integer value
27 """
Simon Glass29462c32016-07-25 18:59:17 -060028 return struct.unpack('>I', val)[0]
Simon Glassefc9bf62016-07-25 18:59:10 -060029
Simon Glassfc3ae9c2017-08-29 14:15:48 -060030def fdt_cells_to_cpu(val, cells):
31 """Convert one or two cells to a long integer
32
33 Args:
34 Value to convert (array of one or more 4-character strings)
35
36 Return:
Simon Glassc69b4502019-05-17 22:00:42 -060037 A native-endian integer value
Simon Glassfc3ae9c2017-08-29 14:15:48 -060038 """
Simon Glass1b1fe412017-08-29 14:15:50 -060039 if not cells:
40 return 0
Simon Glassc69b4502019-05-17 22:00:42 -060041 out = int(fdt32_to_cpu(val[0]))
Simon Glassfc3ae9c2017-08-29 14:15:48 -060042 if cells == 2:
43 out = out << 32 | fdt32_to_cpu(val[1])
44 return out
45
Simon Glassb8d2daa2019-07-20 12:23:49 -060046def EnsureCompiled(fname, tmpdir=None, capture_stderr=False):
Simon Glassefc9bf62016-07-25 18:59:10 -060047 """Compile an fdt .dts source file into a .dtb binary blob if needed.
48
49 Args:
50 fname: Filename (if .dts it will be compiled). It not it will be
51 left alone
Simon Glassb8d2daa2019-07-20 12:23:49 -060052 tmpdir: Temporary directory for output files, or None to use the
53 tools-module output directory
Simon Glassefc9bf62016-07-25 18:59:10 -060054
55 Returns:
56 Filename of resulting .dtb file
57 """
58 _, ext = os.path.splitext(fname)
59 if ext != '.dts':
60 return fname
61
Simon Glassb8d2daa2019-07-20 12:23:49 -060062 if tmpdir:
63 dts_input = os.path.join(tmpdir, 'source.dts')
64 dtb_output = os.path.join(tmpdir, 'source.dtb')
65 else:
66 dts_input = tools.GetOutputFilename('source.dts')
67 dtb_output = tools.GetOutputFilename('source.dtb')
Simon Glassefc9bf62016-07-25 18:59:10 -060068
69 search_paths = [os.path.join(os.getcwd(), 'include')]
70 root, _ = os.path.splitext(fname)
71 args = ['-E', '-P', '-x', 'assembler-with-cpp', '-D__ASSEMBLY__']
72 args += ['-Ulinux']
73 for path in search_paths:
74 args.extend(['-I', path])
75 args += ['-o', dts_input, fname]
76 command.Run('cc', *args)
77
78 # If we don't have a directory, put it in the tools tempdir
79 search_list = []
80 for path in search_paths:
81 search_list.extend(['-i', path])
Simon Glassc5c7b1a2017-11-12 21:52:09 -070082 args = ['-I', 'dts', '-o', dtb_output, '-O', 'dtb',
83 '-W', 'no-unit_address_vs_reg']
Simon Glassefc9bf62016-07-25 18:59:10 -060084 args.extend(search_list)
85 args.append(dts_input)
Simon Glassade2ef62017-12-24 12:12:07 -070086 dtc = os.environ.get('DTC') or 'dtc'
Simon Glass3bce93d2018-07-06 10:27:37 -060087 command.Run(dtc, *args, capture_stderr=capture_stderr)
Simon Glassefc9bf62016-07-25 18:59:10 -060088 return dtb_output
Simon Glass4066b312016-07-25 18:59:18 -060089
90def GetInt(node, propname, default=None):
Simon Glassfe599c72018-07-17 13:25:31 -060091 """Get an integer from a property
92
93 Args:
94 node: Node object to read from
95 propname: property name to read
96 default: Default value to use if the node/property do not exist
97
98 Returns:
99 Integer value read, or default if none
100 """
Simon Glass4066b312016-07-25 18:59:18 -0600101 prop = node.props.get(propname)
102 if not prop:
103 return default
Simon Glass9c526332018-07-06 10:27:28 -0600104 if isinstance(prop.value, list):
105 raise ValueError("Node '%s' property '%s' has list value: expecting "
Simon Glass4066b312016-07-25 18:59:18 -0600106 "a single integer" % (node.name, propname))
Simon Glass9c526332018-07-06 10:27:28 -0600107 value = fdt32_to_cpu(prop.value)
Simon Glass4066b312016-07-25 18:59:18 -0600108 return value
109
110def GetString(node, propname, default=None):
Simon Glassfe599c72018-07-17 13:25:31 -0600111 """Get a string from a property
112
113 Args:
114 node: Node object to read from
115 propname: property name to read
116 default: Default value to use if the node/property do not exist
117
118 Returns:
119 String value read, or default if none
120 """
Simon Glass4066b312016-07-25 18:59:18 -0600121 prop = node.props.get(propname)
122 if not prop:
123 return default
124 value = prop.value
Simon Glass9c526332018-07-06 10:27:28 -0600125 if isinstance(value, list):
126 raise ValueError("Node '%s' property '%s' has list value: expecting "
Simon Glass4066b312016-07-25 18:59:18 -0600127 "a single string" % (node.name, propname))
128 return value
129
130def GetBool(node, propname, default=False):
Simon Glassfe599c72018-07-17 13:25:31 -0600131 """Get an boolean from a property
132
133 Args:
134 node: Node object to read from
135 propname: property name to read
136 default: Default value to use if the node/property do not exist
137
138 Returns:
139 Boolean value read, or default if none (if you set this to True the
140 function will always return True)
141 """
Simon Glass4066b312016-07-25 18:59:18 -0600142 if propname in node.props:
143 return True
144 return default
Simon Glass91710b32018-07-17 13:25:32 -0600145
Simon Glass53f53992018-07-17 13:25:40 -0600146def GetByte(node, propname, default=None):
147 """Get an byte from a property
148
149 Args:
150 node: Node object to read from
151 propname: property name to read
152 default: Default value to use if the node/property do not exist
153
154 Returns:
155 Byte value read, or default if none
156 """
157 prop = node.props.get(propname)
158 if not prop:
159 return default
160 value = prop.value
161 if isinstance(value, list):
162 raise ValueError("Node '%s' property '%s' has list value: expecting "
163 "a single byte" % (node.name, propname))
164 if len(value) != 1:
165 raise ValueError("Node '%s' property '%s' has length %d, expecting %d" %
166 (node.name, propname, len(value), 1))
167 return ord(value[0])
168
Simon Glasse2d65282018-07-17 13:25:46 -0600169def GetPhandleList(node, propname):
170 """Get a list of phandles from a property
171
172 Args:
173 node: Node object to read from
174 propname: property name to read
175
176 Returns:
177 List of phandles read, each an integer
178 """
179 prop = node.props.get(propname)
180 if not prop:
181 return None
182 value = prop.value
183 if not isinstance(value, list):
184 value = [value]
185 return [fdt32_to_cpu(v) for v in value]
186
Simon Glass91710b32018-07-17 13:25:32 -0600187def GetDatatype(node, propname, datatype):
188 """Get a value of a given type from a property
189
190 Args:
191 node: Node object to read from
192 propname: property name to read
193 datatype: Type to read (str or int)
194
195 Returns:
196 value read, or None if none
197
198 Raises:
199 ValueError if datatype is not str or int
200 """
201 if datatype == str:
202 return GetString(node, propname)
203 elif datatype == int:
204 return GetInt(node, propname)
205 raise ValueError("fdt_util internal error: Unknown data type '%s'" %
206 datatype)