blob: 4a74c6ff88c640718194d394b1632b9876fec572 [file] [log] [blame]
Kumar Gala87915cd2018-11-15 11:51:50 -06001# Copyright (c) 2018-2019 Linaro
Carles Cufifa26ef02019-01-30 17:54:21 +01002# Copyright (c) 2019 Nordic Semiconductor ASA
Kumar Gala87915cd2018-11-15 11:51:50 -06003#
4# SPDX-License-Identifier: Apache-2.0
5
Keith Shortdf0942f2023-03-24 15:22:42 -06006import inspect
Kumar Gala87915cd2018-11-15 11:51:50 -06007import os
Martí Bolívar269f3502020-07-01 12:17:02 -07008import pickle
Kumar Gala57353972019-08-28 09:30:23 -05009import sys
Henrik Brix Andersenc6b30942022-05-18 17:35:23 +020010from pathlib import Path
Kumar Gala57353972019-08-28 09:30:23 -050011
Henrik Brix Andersenc6b30942022-05-18 17:35:23 +020012ZEPHYR_BASE = str(Path(__file__).resolve().parents[2])
Martí Bolívar53328472021-03-26 16:18:58 -070013sys.path.insert(0, os.path.join(ZEPHYR_BASE, "scripts", "dts",
14 "python-devicetree", "src"))
Kumar Gala57353972019-08-28 09:30:23 -050015
Kumar Gala87915cd2018-11-15 11:51:50 -060016# Types we support
17# 'string', 'int', 'hex', 'bool'
18
Carles Cufifa26ef02019-01-30 17:54:21 +010019doc_mode = os.environ.get('KCONFIG_DOC_MODE') == "1"
Sebastian Bøecd435432019-02-11 15:57:34 +010020
Ulf Magnussonba312fe2019-03-20 19:30:29 +010021if not doc_mode:
Martí Bolívar269f3502020-07-01 12:17:02 -070022 EDT_PICKLE = os.environ.get("EDT_PICKLE")
Kumar Gala9aefdaf2020-04-15 10:32:41 -050023
Martí Bolívar269f3502020-07-01 12:17:02 -070024 # The "if" handles a missing dts.
25 if EDT_PICKLE is not None and os.path.isfile(EDT_PICKLE):
26 with open(EDT_PICKLE, 'rb') as f:
27 edt = pickle.load(f)
Keith Shortdf0942f2023-03-24 15:22:42 -060028 edtlib = inspect.getmodule(edt)
Kumar Gala57353972019-08-28 09:30:23 -050029 else:
30 edt = None
31
Kumar Gala1baf2f32019-09-04 14:14:26 -050032
33def _warn(kconf, msg):
34 print("{}:{}: WARNING: {}".format(kconf.filename, kconf.linenr, msg))
35
36
Kumar Gala87915cd2018-11-15 11:51:50 -060037def _dt_units_to_scale(unit):
38 if not unit:
39 return 0
40 if unit in {'k', 'K'}:
41 return 10
42 if unit in {'m', 'M'}:
43 return 20
44 if unit in {'g', 'G'}:
45 return 30
Daniel DeGrasse6064da82022-05-25 17:38:59 -050046 if unit in {'kb', 'Kb'}:
47 return 13
48 if unit in {'mb', 'Mb'}:
49 return 23
50 if unit in {'gb', 'Gb'}:
51 return 33
Kumar Gala87915cd2018-11-15 11:51:50 -060052
Kumar Gala57353972019-08-28 09:30:23 -050053
54def dt_chosen_label(kconf, _, chosen):
55 """
56 This function takes a 'chosen' property and treats that property as a path
Ulf Magnusson73ac1462019-09-23 05:14:18 +020057 to an EDT node. If it finds an EDT node, it will look to see if that node
Martí Bolívarb3151bc2022-08-18 16:13:50 -070058 has a "label" property and return the value of that "label". If not, we
59 return the node's name in the devicetree.
Kumar Gala57353972019-08-28 09:30:23 -050060 """
61 if doc_mode or edt is None:
62 return ""
63
Ulf Magnusson73ac1462019-09-23 05:14:18 +020064 node = edt.chosen_node(chosen)
65 if not node:
Kumar Gala57353972019-08-28 09:30:23 -050066 return ""
67
Ulf Magnusson73ac1462019-09-23 05:14:18 +020068 if "label" not in node.props:
Kumar Gala57538262022-08-04 11:23:13 -050069 return node.name
Kumar Gala57353972019-08-28 09:30:23 -050070
Ulf Magnusson73ac1462019-09-23 05:14:18 +020071 return node.props["label"].val
Kumar Gala57353972019-08-28 09:30:23 -050072
73
Kumar Gala07e5d892019-11-04 10:20:59 -060074def dt_chosen_enabled(kconf, _, chosen):
75 """
76 This function returns "y" if /chosen contains a property named 'chosen'
77 that points to an enabled node, and "n" otherwise
78 """
79 if doc_mode or edt is None:
80 return "n"
81
82 node = edt.chosen_node(chosen)
Martí Bolívar81650082020-10-05 20:02:13 -070083 return "y" if node and node.status == "okay" else "n"
Kumar Gala07e5d892019-11-04 10:20:59 -060084
Kumar Gala0353d222020-02-13 23:43:42 -060085
Martí Bolívar7ff3ebc2020-04-23 12:28:06 -070086def dt_chosen_path(kconf, _, chosen):
87 """
88 This function takes a /chosen node property and returns the path
89 to the node in the property value, or the empty string.
90 """
91 if doc_mode or edt is None:
92 return "n"
93
94 node = edt.chosen_node(chosen)
95
96 return node.path if node else ""
97
Daniel DeGrassefbefc502022-04-11 11:53:03 -050098def dt_chosen_has_compat(kconf, _, chosen, compat):
99 """
100 This function takes a /chosen node property and returns 'y' if the
101 chosen node has the provided compatible string 'compat'
102 """
103 if doc_mode or edt is None:
104 return "n"
105
106 node = edt.chosen_node(chosen)
107
108 if node is None:
109 return "n"
110
111 if compat in node.compats:
112 return "y"
113
114 return "n"
Martí Bolívar7ff3ebc2020-04-23 12:28:06 -0700115
Martí Bolívar24677f92020-04-28 16:52:35 -0700116def dt_node_enabled(kconf, name, node):
117 """
118 This function is used to test if a node is enabled (has status
119 'okay') or not.
120
121 The 'node' argument is a string which is either a path or an
122 alias, or both, depending on 'name'.
123
124 If 'name' is 'dt_path_enabled', 'node' is an alias or a path. If
125 'name' is 'dt_alias_enabled, 'node' is an alias.
126 """
127
128 if doc_mode or edt is None:
129 return "n"
130
131 if name == "dt_alias_enabled":
132 if node.startswith("/"):
133 # EDT.get_node() works with either aliases or paths. If we
134 # are specifically being asked about an alias, reject paths.
135 return "n"
136 else:
137 # Make sure this is being called appropriately.
138 assert name == "dt_path_enabled"
139
140 try:
141 node = edt.get_node(node)
142 except edtlib.EDTError:
143 return "n"
144
Martí Bolívar81650082020-10-05 20:02:13 -0700145 return "y" if node and node.status == "okay" else "n"
Martí Bolívar24677f92020-04-28 16:52:35 -0700146
147
Kumar Gala0353d222020-02-13 23:43:42 -0600148def dt_nodelabel_enabled(kconf, _, label):
149 """
Martí Bolívar24677f92020-04-28 16:52:35 -0700150 This function is like dt_node_enabled(), but the 'label' argument
151 should be a node label, like "foo" is here:
152
153 foo: some-node { ... };
Kumar Gala0353d222020-02-13 23:43:42 -0600154 """
155 if doc_mode or edt is None:
156 return "n"
157
Martí Bolívar0682c462020-04-22 17:59:23 -0700158 node = edt.label2node.get(label)
Kumar Gala0353d222020-02-13 23:43:42 -0600159
Martí Bolívar81650082020-10-05 20:02:13 -0700160 return "y" if node and node.status == "okay" else "n"
Kumar Gala0353d222020-02-13 23:43:42 -0600161
162
Ulf Magnusson73ac1462019-09-23 05:14:18 +0200163def _node_reg_addr(node, index, unit):
164 if not node:
Kumar Gala22e74492019-10-23 15:15:59 -0500165 return 0
Kumar Gala57353972019-08-28 09:30:23 -0500166
Ulf Magnusson73ac1462019-09-23 05:14:18 +0200167 if not node.regs:
Kumar Gala22e74492019-10-23 15:15:59 -0500168 return 0
Kumar Gala57353972019-08-28 09:30:23 -0500169
Ulf Magnusson73ac1462019-09-23 05:14:18 +0200170 if int(index) >= len(node.regs):
Kumar Gala22e74492019-10-23 15:15:59 -0500171 return 0
Kumar Gala57353972019-08-28 09:30:23 -0500172
Kumar Gala8af311a2020-03-13 12:43:56 -0500173 if node.regs[int(index)].addr is None:
174 return 0
175
Kumar Gala22e74492019-10-23 15:15:59 -0500176 return node.regs[int(index)].addr >> _dt_units_to_scale(unit)
Kumar Gala57353972019-08-28 09:30:23 -0500177
178
Ulf Magnusson73ac1462019-09-23 05:14:18 +0200179def _node_reg_size(node, index, unit):
180 if not node:
Kumar Gala22e74492019-10-23 15:15:59 -0500181 return 0
Kumar Gala57353972019-08-28 09:30:23 -0500182
Ulf Magnusson73ac1462019-09-23 05:14:18 +0200183 if not node.regs:
Kumar Gala22e74492019-10-23 15:15:59 -0500184 return 0
Kumar Gala57353972019-08-28 09:30:23 -0500185
Ulf Magnusson73ac1462019-09-23 05:14:18 +0200186 if int(index) >= len(node.regs):
Kumar Gala22e74492019-10-23 15:15:59 -0500187 return 0
Kumar Gala57353972019-08-28 09:30:23 -0500188
Kumar Gala8af311a2020-03-13 12:43:56 -0500189 if node.regs[int(index)].size is None:
190 return 0
191
Kumar Gala22e74492019-10-23 15:15:59 -0500192 return node.regs[int(index)].size >> _dt_units_to_scale(unit)
Kumar Gala57353972019-08-28 09:30:23 -0500193
194
David Leach1e5a8302021-11-08 23:24:22 -0600195def _node_int_prop(node, prop, unit=None):
196 """
197 This function takes a 'node' and will look to see if that 'node' has a
198 property called 'prop' and if that 'prop' is an integer type will return
199 the value of the property 'prop' as either a string int or string hex
200 value, if not we return 0.
201
202 The function will divide the value based on 'unit':
203 None No division
204 'k' or 'K' divide by 1024 (1 << 10)
205 'm' or 'M' divide by 1,048,576 (1 << 20)
206 'g' or 'G' divide by 1,073,741,824 (1 << 30)
Daniel DeGrasse6064da82022-05-25 17:38:59 -0500207 'kb' or 'Kb' divide by 8192 (1 << 13)
208 'mb' or 'Mb' divide by 8,388,608 (1 << 23)
209 'gb' or 'Gb' divide by 8,589,934,592 (1 << 33)
David Leach1e5a8302021-11-08 23:24:22 -0600210 """
Kumar Gala338b43192020-04-03 05:02:35 -0500211 if not node:
212 return 0
213
214 if prop not in node.props:
215 return 0
216
217 if node.props[prop].type != "int":
218 return 0
219
David Leach1e5a8302021-11-08 23:24:22 -0600220 return node.props[prop].val >> _dt_units_to_scale(unit)
Kumar Gala338b43192020-04-03 05:02:35 -0500221
222
Eivind Jølsgard3865e082022-03-18 10:50:00 +0100223def _node_array_prop(node, prop, index=0, unit=None):
224 """
225 This function takes a 'node' and will look to see if that 'node' has a
226 property called 'prop' and if that 'prop' is an array type will return
227 the value of the property 'prop' at the given 'index' as either a string int
228 or string hex value. If the property 'prop' is not found or the given 'index'
229 is out of range it will return 0.
230
231 The function will divide the value based on 'unit':
232 None No division
233 'k' or 'K' divide by 1024 (1 << 10)
234 'm' or 'M' divide by 1,048,576 (1 << 20)
235 'g' or 'G' divide by 1,073,741,824 (1 << 30)
236 """
237 if not node:
238 return 0
239
240 if prop not in node.props:
241 return 0
242 if node.props[prop].type != "array":
243 return 0
244 if int(index) >= len(node.props[prop].val):
245 return 0
246 return node.props[prop].val[int(index)] >> _dt_units_to_scale(unit)
247
Erwan Gourioua59e01d2023-12-18 12:03:43 +0100248def _node_ph_array_prop(node, prop, index, cell, unit=None):
249 """
250 This function takes a 'node', a property name ('prop'), index ('index') and
251 a cell ('cell') and it will look to see if that node has a property
252 called 'prop' and if that 'prop' is an phandle-array type.
253 Then it will check if that phandle array has a cell matching the given index
254 and then return the value of the cell named 'cell' in this array index.
255 If not found it will return 0.
256
257 The function will divide the value based on 'unit':
258 None No division
259 'k' or 'K' divide by 1024 (1 << 10)
260 'm' or 'M' divide by 1,048,576 (1 << 20)
261 'g' or 'G' divide by 1,073,741,824 (1 << 30)
262 """
263 if not node:
264 return 0
265
266 if prop not in node.props:
267 return 0
268 if node.props[prop].type != "phandle-array":
269 return 0
270 if int(index) >= len(node.props[prop].val):
271 return 0
272 if cell not in node.props[prop].val[int(index)].data.keys():
273 return 0
274 return node.props[prop].val[int(index)].data[cell] >> _dt_units_to_scale(unit)
Eivind Jølsgard3865e082022-03-18 10:50:00 +0100275
Kumar Gala22e74492019-10-23 15:15:59 -0500276def _dt_chosen_reg_addr(kconf, chosen, index=0, unit=None):
Kumar Gala57353972019-08-28 09:30:23 -0500277 """
278 This function takes a 'chosen' property and treats that property as a path
Ulf Magnusson73ac1462019-09-23 05:14:18 +0200279 to an EDT node. If it finds an EDT node, it will look to see if that
Nazar Kazakovf483b1b2022-03-16 21:07:43 +0000280 node has a register at the given 'index' and return the address value of
Kumar Gala57353972019-08-28 09:30:23 -0500281 that reg, if not we return 0.
282
283 The function will divide the value based on 'unit':
284 None No division
285 'k' or 'K' divide by 1024 (1 << 10)
286 'm' or 'M' divide by 1,048,576 (1 << 20)
287 'g' or 'G' divide by 1,073,741,824 (1 << 30)
Daniel DeGrasse6064da82022-05-25 17:38:59 -0500288 'kb' or 'Kb' divide by 8192 (1 << 13)
289 'mb' or 'Mb' divide by 8,388,608 (1 << 23)
290 'gb' or 'Gb' divide by 8,589,934,592 (1 << 33)
Kumar Gala57353972019-08-28 09:30:23 -0500291 """
292 if doc_mode or edt is None:
Kumar Gala22e74492019-10-23 15:15:59 -0500293 return 0
Kumar Gala57353972019-08-28 09:30:23 -0500294
Ulf Magnusson73ac1462019-09-23 05:14:18 +0200295 node = edt.chosen_node(chosen)
Kumar Gala57353972019-08-28 09:30:23 -0500296
Ulf Magnusson73ac1462019-09-23 05:14:18 +0200297 return _node_reg_addr(node, index, unit)
Kumar Gala57353972019-08-28 09:30:23 -0500298
299
Kumar Gala22e74492019-10-23 15:15:59 -0500300def _dt_chosen_reg_size(kconf, chosen, index=0, unit=None):
Kumar Gala57353972019-08-28 09:30:23 -0500301 """
302 This function takes a 'chosen' property and treats that property as a path
Ulf Magnusson73ac1462019-09-23 05:14:18 +0200303 to an EDT node. If it finds an EDT node, it will look to see if that node
304 has a register at the given 'index' and return the size value of that reg,
305 if not we return 0.
Kumar Gala57353972019-08-28 09:30:23 -0500306
307 The function will divide the value based on 'unit':
308 None No division
309 'k' or 'K' divide by 1024 (1 << 10)
310 'm' or 'M' divide by 1,048,576 (1 << 20)
311 'g' or 'G' divide by 1,073,741,824 (1 << 30)
Daniel DeGrasse6064da82022-05-25 17:38:59 -0500312 'kb' or 'Kb' divide by 8192 (1 << 13)
313 'mb' or 'Mb' divide by 8,388,608 (1 << 23)
314 'gb' or 'Gb' divide by 8,589,934,592 (1 << 33)
Kumar Gala57353972019-08-28 09:30:23 -0500315 """
316 if doc_mode or edt is None:
Kumar Gala22e74492019-10-23 15:15:59 -0500317 return 0
Kumar Gala57353972019-08-28 09:30:23 -0500318
Ulf Magnusson73ac1462019-09-23 05:14:18 +0200319 node = edt.chosen_node(chosen)
Kumar Gala57353972019-08-28 09:30:23 -0500320
Ulf Magnusson73ac1462019-09-23 05:14:18 +0200321 return _node_reg_size(node, index, unit)
Kumar Gala57353972019-08-28 09:30:23 -0500322
323
Kumar Gala22e74492019-10-23 15:15:59 -0500324def dt_chosen_reg(kconf, name, chosen, index=0, unit=None):
325 """
326 This function just routes to the proper function and converts
327 the result to either a string int or string hex value.
328 """
329 if name == "dt_chosen_reg_size_int":
330 return str(_dt_chosen_reg_size(kconf, chosen, index, unit))
331 if name == "dt_chosen_reg_size_hex":
332 return hex(_dt_chosen_reg_size(kconf, chosen, index, unit))
333 if name == "dt_chosen_reg_addr_int":
334 return str(_dt_chosen_reg_addr(kconf, chosen, index, unit))
335 if name == "dt_chosen_reg_addr_hex":
336 return hex(_dt_chosen_reg_addr(kconf, chosen, index, unit))
337
338
339def _dt_node_reg_addr(kconf, path, index=0, unit=None):
Kumar Gala57353972019-08-28 09:30:23 -0500340 """
Ulf Magnusson73ac1462019-09-23 05:14:18 +0200341 This function takes a 'path' and looks for an EDT node at that path. If it
342 finds an EDT node, it will look to see if that node has a register at the
343 given 'index' and return the address value of that reg, if not we return 0.
Kumar Gala57353972019-08-28 09:30:23 -0500344
345 The function will divide the value based on 'unit':
346 None No division
347 'k' or 'K' divide by 1024 (1 << 10)
348 'm' or 'M' divide by 1,048,576 (1 << 20)
349 'g' or 'G' divide by 1,073,741,824 (1 << 30)
Daniel DeGrasse6064da82022-05-25 17:38:59 -0500350 'kb' or 'Kb' divide by 8192 (1 << 13)
351 'mb' or 'Mb' divide by 8,388,608 (1 << 23)
352 'gb' or 'Gb' divide by 8,589,934,592 (1 << 33)
Kumar Gala57353972019-08-28 09:30:23 -0500353 """
354 if doc_mode or edt is None:
Kumar Gala22e74492019-10-23 15:15:59 -0500355 return 0
Kumar Gala57353972019-08-28 09:30:23 -0500356
357 try:
Ulf Magnusson73ac1462019-09-23 05:14:18 +0200358 node = edt.get_node(path)
Kumar Gala57353972019-08-28 09:30:23 -0500359 except edtlib.EDTError:
Kumar Gala22e74492019-10-23 15:15:59 -0500360 return 0
Kumar Gala57353972019-08-28 09:30:23 -0500361
Ulf Magnusson73ac1462019-09-23 05:14:18 +0200362 return _node_reg_addr(node, index, unit)
Kumar Gala57353972019-08-28 09:30:23 -0500363
364
Kumar Gala22e74492019-10-23 15:15:59 -0500365def _dt_node_reg_size(kconf, path, index=0, unit=None):
Kumar Gala57353972019-08-28 09:30:23 -0500366 """
Ulf Magnusson73ac1462019-09-23 05:14:18 +0200367 This function takes a 'path' and looks for an EDT node at that path. If it
368 finds an EDT node, it will look to see if that node has a register at the
369 given 'index' and return the size value of that reg, if not we return 0.
Kumar Gala57353972019-08-28 09:30:23 -0500370
371 The function will divide the value based on 'unit':
372 None No division
373 'k' or 'K' divide by 1024 (1 << 10)
374 'm' or 'M' divide by 1,048,576 (1 << 20)
375 'g' or 'G' divide by 1,073,741,824 (1 << 30)
Daniel DeGrasse6064da82022-05-25 17:38:59 -0500376 'kb' or 'Kb' divide by 8192 (1 << 13)
377 'mb' or 'Mb' divide by 8,388,608 (1 << 23)
378 'gb' or 'Gb' divide by 8,589,934,592 (1 << 33)
Kumar Gala57353972019-08-28 09:30:23 -0500379 """
380 if doc_mode or edt is None:
Kumar Gala22e74492019-10-23 15:15:59 -0500381 return 0
Kumar Gala57353972019-08-28 09:30:23 -0500382
383 try:
Ulf Magnusson73ac1462019-09-23 05:14:18 +0200384 node = edt.get_node(path)
Kumar Gala57353972019-08-28 09:30:23 -0500385 except edtlib.EDTError:
Kumar Gala22e74492019-10-23 15:15:59 -0500386 return 0
Kumar Gala57353972019-08-28 09:30:23 -0500387
Ulf Magnusson73ac1462019-09-23 05:14:18 +0200388 return _node_reg_size(node, index, unit)
Kumar Gala57353972019-08-28 09:30:23 -0500389
390
Kumar Gala22e74492019-10-23 15:15:59 -0500391def dt_node_reg(kconf, name, path, index=0, unit=None):
392 """
393 This function just routes to the proper function and converts
394 the result to either a string int or string hex value.
395 """
396 if name == "dt_node_reg_size_int":
397 return str(_dt_node_reg_size(kconf, path, index, unit))
398 if name == "dt_node_reg_size_hex":
399 return hex(_dt_node_reg_size(kconf, path, index, unit))
400 if name == "dt_node_reg_addr_int":
401 return str(_dt_node_reg_addr(kconf, path, index, unit))
402 if name == "dt_node_reg_addr_hex":
403 return hex(_dt_node_reg_addr(kconf, path, index, unit))
404
Jordan Yates999afdc2023-07-30 13:33:33 +1000405def dt_nodelabel_reg(kconf, name, label, index=0, unit=None):
406 """
407 This function is like dt_node_reg(), but the 'label' argument
408 should be a node label, like "foo" is here:
409
410 foo: some-node { ... };
411 """
412 if doc_mode or edt is None:
413 node = None
414 else:
415 node = edt.label2node.get(label)
416
417 if name == "dt_nodelabel_reg_size_int":
418 return str(_dt_node_reg_size(kconf, node.path, index, unit)) if node else "0"
419 if name == "dt_nodelabel_reg_size_hex":
420 return hex(_dt_node_reg_size(kconf, node.path, index, unit)) if node else "0x0"
421 if name == "dt_nodelabel_reg_addr_int":
422 return str(_dt_node_reg_addr(kconf, node.path, index, unit)) if node else "0"
423 if name == "dt_nodelabel_reg_addr_hex":
424 return hex(_dt_node_reg_addr(kconf, node.path, index, unit)) if node else "0x0"
425
426
Michał Barnaśa1ab8da2022-03-08 17:44:04 +0100427def _dt_node_bool_prop_generic(node_search_function, search_arg, prop):
Kumar Gala57353972019-08-28 09:30:23 -0500428 """
Michał Barnaśa1ab8da2022-03-08 17:44:04 +0100429 This function takes the 'node_search_function' and uses it to search for
430 a node with 'search_arg' and if node exists, checks if 'prop' exists
431 inside the node and is a boolean, if it is true, returns "y".
432 Otherwise, it returns "n".
Kumar Gala57353972019-08-28 09:30:23 -0500433 """
Kumar Gala57353972019-08-28 09:30:23 -0500434 try:
Michał Barnaśa1ab8da2022-03-08 17:44:04 +0100435 node = node_search_function(search_arg)
Kumar Gala57353972019-08-28 09:30:23 -0500436 except edtlib.EDTError:
437 return "n"
438
Andrzej Głąbek23994332022-03-23 14:45:11 +0100439 if node is None:
440 return "n"
441
Ulf Magnusson73ac1462019-09-23 05:14:18 +0200442 if prop not in node.props:
Kumar Gala57353972019-08-28 09:30:23 -0500443 return "n"
444
Ulf Magnusson73ac1462019-09-23 05:14:18 +0200445 if node.props[prop].type != "boolean":
Kumar Gala57353972019-08-28 09:30:23 -0500446 return "n"
447
Ulf Magnusson73ac1462019-09-23 05:14:18 +0200448 if node.props[prop].val:
Kumar Gala57353972019-08-28 09:30:23 -0500449 return "y"
450
451 return "n"
452
Michał Barnaśa1ab8da2022-03-08 17:44:04 +0100453def dt_node_bool_prop(kconf, _, path, prop):
Erwan Gourioub7110282021-01-07 12:06:31 +0100454 """
Michał Barnaśa1ab8da2022-03-08 17:44:04 +0100455 This function takes a 'path' and looks for an EDT node at that path. If it
456 finds an EDT node, it will look to see if that node has a boolean property
Erwan Gourioub7110282021-01-07 12:06:31 +0100457 by the name of 'prop'. If the 'prop' exists it will return "y" otherwise
458 we return "n".
459 """
Erwan Gourioub7110282021-01-07 12:06:31 +0100460 if doc_mode or edt is None:
461 return "n"
462
Michał Barnaśa1ab8da2022-03-08 17:44:04 +0100463 return _dt_node_bool_prop_generic(edt.get_node, path, prop)
464
465def dt_nodelabel_bool_prop(kconf, _, label, prop):
466 """
467 This function takes a 'label' and looks for an EDT node with that label.
468 If it finds an EDT node, it will look to see if that node has a boolean
469 property by the name of 'prop'. If the 'prop' exists it will return "y"
470 otherwise we return "n".
471 """
472 if doc_mode or edt is None:
473 return "n"
474
475 return _dt_node_bool_prop_generic(edt.label2node.get, label, prop)
476
Stephen Stautsd4b8db72022-12-27 11:40:17 +0100477def dt_chosen_bool_prop(kconf, _, chosen, prop):
478 """
479 This function takes a /chosen node property named 'chosen', and
480 looks for the chosen node. If that node exists and has a boolean
481 property 'prop', it returns "y". Otherwise, it returns "n".
482 """
483 if doc_mode or edt is None:
484 return "n"
485
486 return _dt_node_bool_prop_generic(edt.chosen_node, chosen, prop)
487
Michał Barnaśa1ab8da2022-03-08 17:44:04 +0100488def _dt_node_has_prop_generic(node_search_function, search_arg, prop):
489 """
490 This function takes the 'node_search_function' and uses it to search for
491 a node with 'search_arg' and if node exists, then checks if 'prop'
492 exists inside the node and returns "y". Otherwise, it returns "n".
493 """
Erwan Gourioub7110282021-01-07 12:06:31 +0100494 try:
Michał Barnaśa1ab8da2022-03-08 17:44:04 +0100495 node = node_search_function(search_arg)
Erwan Gourioub7110282021-01-07 12:06:31 +0100496 except edtlib.EDTError:
497 return "n"
498
499 if node is None:
500 return "n"
501
502 if prop in node.props:
503 return "y"
504
505 return "n"
Kumar Gala57353972019-08-28 09:30:23 -0500506
Michał Barnaśa1ab8da2022-03-08 17:44:04 +0100507def dt_node_has_prop(kconf, _, path, prop):
508 """
509 This function takes a 'path' and looks for an EDT node at that path. If it
510 finds an EDT node, it will look to see if that node has a property
511 by the name of 'prop'. If the 'prop' exists it will return "y" otherwise
512 it returns "n".
513 """
514 if doc_mode or edt is None:
515 return "n"
516
517 return _dt_node_has_prop_generic(edt.get_node, path, prop)
518
519def dt_nodelabel_has_prop(kconf, _, label, prop):
520 """
521 This function takes a 'label' and looks for an EDT node with that label.
522 If it finds an EDT node, it will look to see if that node has a property
523 by the name of 'prop'. If the 'prop' exists it will return "y" otherwise
524 it returns "n".
525 """
526 if doc_mode or edt is None:
527 return "n"
528
529 return _dt_node_has_prop_generic(edt.label2node.get, label, prop)
530
David Leach1e5a8302021-11-08 23:24:22 -0600531def dt_node_int_prop(kconf, name, path, prop, unit=None):
Kumar Gala338b43192020-04-03 05:02:35 -0500532 """
533 This function takes a 'path' and property name ('prop') looks for an EDT
534 node at that path. If it finds an EDT node, it will look to see if that
535 node has a property called 'prop' and if that 'prop' is an integer type
536 will return the value of the property 'prop' as either a string int or
537 string hex value, if not we return 0.
Kumar Gala338b43192020-04-03 05:02:35 -0500538
David Leach1e5a8302021-11-08 23:24:22 -0600539 The function will divide the value based on 'unit':
540 None No division
541 'k' or 'K' divide by 1024 (1 << 10)
542 'm' or 'M' divide by 1,048,576 (1 << 20)
543 'g' or 'G' divide by 1,073,741,824 (1 << 30)
Daniel DeGrasse6064da82022-05-25 17:38:59 -0500544 'kb' or 'Kb' divide by 8192 (1 << 13)
545 'mb' or 'Mb' divide by 8,388,608 (1 << 23)
546 'gb' or 'Gb' divide by 8,589,934,592 (1 << 33)
David Leach1e5a8302021-11-08 23:24:22 -0600547 """
Kumar Gala338b43192020-04-03 05:02:35 -0500548 if doc_mode or edt is None:
549 return "0"
550
551 try:
552 node = edt.get_node(path)
553 except edtlib.EDTError:
554 return "0"
555
556 if name == "dt_node_int_prop_int":
David Leach1e5a8302021-11-08 23:24:22 -0600557 return str(_node_int_prop(node, prop, unit))
Kumar Gala338b43192020-04-03 05:02:35 -0500558 if name == "dt_node_int_prop_hex":
David Leach1e5a8302021-11-08 23:24:22 -0600559 return hex(_node_int_prop(node, prop, unit))
Kumar Gala338b43192020-04-03 05:02:35 -0500560
Eivind Jølsgard3865e082022-03-18 10:50:00 +0100561
562def dt_node_array_prop(kconf, name, path, prop, index, unit=None):
563 """
564 This function takes a 'path', property name ('prop') and index ('index')
565 and looks for an EDT node at that path. If it finds an EDT node, it will
566 look to see if that node has a property called 'prop' and if that 'prop'
567 is an array type will return the value of the property 'prop' at the given
568 'index' as either a string int or string hex value. If not found we return 0.
569
570 The function will divide the value based on 'unit':
571 None No division
572 'k' or 'K' divide by 1024 (1 << 10)
573 'm' or 'M' divide by 1,048,576 (1 << 20)
574 'g' or 'G' divide by 1,073,741,824 (1 << 30)
575 """
576 if doc_mode or edt is None:
577 return "0"
578
579 try:
580 node = edt.get_node(path)
581 except edtlib.EDTError:
582 return "0"
583 if name == "dt_node_array_prop_int":
584 return str(_node_array_prop(node, prop, index, unit))
585 if name == "dt_node_array_prop_hex":
586 return hex(_node_array_prop(node, prop, index, unit))
587
588
Erwan Gourioua59e01d2023-12-18 12:03:43 +0100589def dt_node_ph_array_prop(kconf, name, path, prop, index, cell, unit=None):
590 """
591 This function takes a 'path', property name ('prop'), index ('index') and
592 a cell ('cell') and looks for an EDT node at that path.
593 If it finds an EDT node, it will look to see if that node has a property
594 called 'prop' and if that 'prop' is an phandle-array type.
595 Then it will check if that phandle array has a cell matching the given index
596 and ten return the value of the cell named 'cell' in this array index as
597 either a string int or string hex value. If not found we return 0.
598
599 The function will divide the value based on 'unit':
600 None No division
601 'k' or 'K' divide by 1024 (1 << 10)
602 'm' or 'M' divide by 1,048,576 (1 << 20)
603 'g' or 'G' divide by 1,073,741,824 (1 << 30)
604 """
605 if doc_mode or edt is None:
606 return "0"
607
608 try:
609 node = edt.get_node(path)
610 except edtlib.EDTError:
611 return "0"
612 if name == "dt_node_ph_array_prop_int":
613 return str(_node_ph_array_prop(node, prop, index, cell, unit))
614 if name == "dt_node_ph_array_prop_hex":
615 return hex(_node_ph_array_prop(node, prop, index, cell, unit))
616
Johann Fischer73199f22021-11-18 17:12:23 +0100617def dt_node_str_prop_equals(kconf, _, path, prop, val):
618 """
619 This function takes a 'path' and property name ('prop') looks for an EDT
620 node at that path. If it finds an EDT node, it will look to see if that
621 node has a property 'prop' of type string. If that 'prop' is equal to 'val'
622 it will return "y" otherwise return "n".
623 """
624
625 if doc_mode or edt is None:
626 return "n"
627
628 try:
629 node = edt.get_node(path)
630 except edtlib.EDTError:
631 return "n"
632
633 if prop not in node.props:
634 return "n"
635
636 if node.props[prop].type != "string":
637 return "n"
638
639 if node.props[prop].val == val:
640 return "y"
641
642 return "n"
Kumar Gala338b43192020-04-03 05:02:35 -0500643
Andrzej Głąbek9f2a27b2022-03-15 14:08:21 +0100644
645def dt_has_compat(kconf, _, compat):
646 """
647 This function takes a 'compat' and returns "y" if any compatible node
648 can be found in the EDT, otherwise it returns "n".
649 """
650 if doc_mode or edt is None:
651 return "n"
652
653 return "y" if compat in edt.compat2nodes else "n"
654
655
Kumar Gala57353972019-08-28 09:30:23 -0500656def dt_compat_enabled(kconf, _, compat):
657 """
Martí Bolívar81650082020-10-05 20:02:13 -0700658 This function takes a 'compat' and returns "y" if we find a status "okay"
Ulf Magnusson73ac1462019-09-23 05:14:18 +0200659 compatible node in the EDT otherwise we return "n"
Kumar Gala57353972019-08-28 09:30:23 -0500660 """
661 if doc_mode or edt is None:
662 return "n"
663
Martí Bolívar81650082020-10-05 20:02:13 -0700664 return "y" if compat in edt.compat2okay else "n"
Kumar Gala57353972019-08-28 09:30:23 -0500665
666
Martí Bolívar3cd4f6c2020-04-10 15:37:58 -0700667def dt_compat_on_bus(kconf, _, compat, bus):
668 """
669 This function takes a 'compat' and returns "y" if we find an "enabled"
670 compatible node in the EDT which is on bus 'bus'. It returns "n" otherwise.
671 """
672 if doc_mode or edt is None:
673 return "n"
674
Andrzej Głąbekf9c1f892021-02-03 13:53:48 +0100675 if compat in edt.compat2okay:
676 for node in edt.compat2okay[compat]:
Daniel Leung418c9152022-08-26 10:52:32 -0700677 if node.on_buses is not None and bus in node.on_buses:
Andrzej Głąbekf9c1f892021-02-03 13:53:48 +0100678 return "y"
Martí Bolívar3cd4f6c2020-04-10 15:37:58 -0700679
680 return "n"
681
682
Andrzej Głąbek3331a202020-02-14 11:53:21 +0100683def dt_nodelabel_has_compat(kconf, _, label, compat):
684 """
Andrzej Głąbekcd00a3a2022-03-28 12:16:51 +0200685 This function takes a 'label' and looks for an EDT node with that label.
686 If it finds such node, it returns "y" if this node is compatible with
687 the provided 'compat'. Otherwise, it return "n" .
688 """
689 if doc_mode or edt is None:
690 return "n"
691
692 node = edt.label2node.get(label)
693
694 if node and compat in node.compats:
695 return "y"
696
697 return "n"
698
Daniel DeGrasse6aa71942022-08-26 12:12:24 -0500699def dt_node_has_compat(kconf, _, path, compat):
700 """
701 This function takes a 'path' and looks for an EDT node at that path. If it
702 finds an EDT node, it returns "y" if this node is compatible with
703 the provided 'compat'. Otherwise, it return "n" .
704 """
705
706 if doc_mode or edt is None:
707 return "n"
708
709 try:
710 node = edt.get_node(path)
711 except edtlib.EDTError:
712 return "n"
713
714 if node and compat in node.compats:
715 return "y"
716
717 return "n"
Andrzej Głąbekcd00a3a2022-03-28 12:16:51 +0200718
719def dt_nodelabel_enabled_with_compat(kconf, _, label, compat):
720 """
Andrzej Głąbek3331a202020-02-14 11:53:21 +0100721 This function takes a 'label' and returns "y" if an "enabled" node with
722 such label can be found in the EDT and that node is compatible with the
723 provided 'compat', otherwise it returns "n".
724 """
725 if doc_mode or edt is None:
726 return "n"
727
Andrzej Głąbekf9c1f892021-02-03 13:53:48 +0100728 if compat in edt.compat2okay:
729 for node in edt.compat2okay[compat]:
730 if label in node.labels:
731 return "y"
Andrzej Głąbek3331a202020-02-14 11:53:21 +0100732
733 return "n"
734
735
Stephen Stautsd4b8db72022-12-27 11:40:17 +0100736def dt_nodelabel_array_prop_has_val(kconf, _, label, prop, val):
737 """
738 This function looks for a node with node label 'label'.
739 If the node exists, it checks if the node node has a property
740 'prop' with type "array". If so, and the property contains
741 an element equal to the integer 'val', it returns "y".
742 Otherwise, it returns "n".
743 """
744 if doc_mode or edt is None:
745 return "n"
746
747 node = edt.label2node.get(label)
748
749 if not node or (prop not in node.props) or (node.props[prop].type != "array"):
750 return "n"
751 else:
752 return "y" if int(val, base=0) in node.props[prop].val else "n"
753
754
Martí Bolívar1fff2352020-04-22 18:06:18 -0700755def dt_nodelabel_path(kconf, _, label):
756 """
757 This function takes a node label (not a label property) and
758 returns the path to the node which has that label, or an empty
759 string if there is no such node.
760 """
761 if doc_mode or edt is None:
762 return ""
763
764 node = edt.label2node.get(label)
765
766 return node.path if node else ""
767
Daniel DeGrassedb9bcd92022-08-26 12:10:14 -0500768def dt_node_parent(kconf, _, path):
769 """
770 This function takes a 'path' and looks for an EDT node at that path. If it
771 finds an EDT node, it will look for the parent of that node. If the parent
772 exists, it will return the path to that parent. Otherwise, an empty string
773 will be returned.
774 """
775 if doc_mode or edt is None:
776 return ""
777
778 try:
779 node = edt.get_node(path)
780 except edtlib.EDTError:
781 return ""
782
783 if node is None:
784 return ""
785
786 return node.parent.path if node.parent else ""
Martí Bolívar1fff2352020-04-22 18:06:18 -0700787
Henrik Brix Andersenfba6c7f2023-01-18 17:43:02 +0100788def dt_gpio_hogs_enabled(kconf, _):
789 """
790 Return "y" if any GPIO hog node is enabled. Otherwise, return "n".
791 """
792 if doc_mode or edt is None:
793 return "n"
794
795 for node in edt.nodes:
796 if node.gpio_hogs and node.status == "okay":
797 return "y"
798
799 return "n"
800
Erwan Gouriou17537c72019-11-22 10:06:57 +0100801def shields_list_contains(kconf, _, shield):
802 """
803 Return "n" if cmake environment variable 'SHIELD_AS_LIST' doesn't exist.
804 Return "y" if 'shield' is present list obtained after 'SHIELD_AS_LIST'
805 has been split using ";" as a separator and "n" otherwise.
806 """
807 try:
808 list = os.environ['SHIELD_AS_LIST']
809 except KeyError:
810 return "n"
811
812 return "y" if shield in list.split(";") else "n"
813
814
Martí Bolívar006319f2020-07-21 15:20:18 -0700815# Keys in this dict are the function names as they appear
816# in Kconfig files. The values are tuples in this form:
817#
818# (python_function, minimum_number_of_args, maximum_number_of_args)
819#
820# Each python function is given a kconf object and its name in the
821# Kconfig file, followed by arguments from the Kconfig file.
822#
823# See the kconfiglib documentation for more details.
Kumar Gala87915cd2018-11-15 11:51:50 -0600824functions = {
Andrzej Głąbek9f2a27b2022-03-15 14:08:21 +0100825 "dt_has_compat": (dt_has_compat, 1, 1),
Kumar Gala57353972019-08-28 09:30:23 -0500826 "dt_compat_enabled": (dt_compat_enabled, 1, 1),
Martí Bolívar3cd4f6c2020-04-10 15:37:58 -0700827 "dt_compat_on_bus": (dt_compat_on_bus, 2, 2),
Kumar Gala57353972019-08-28 09:30:23 -0500828 "dt_chosen_label": (dt_chosen_label, 1, 1),
Kumar Gala07e5d892019-11-04 10:20:59 -0600829 "dt_chosen_enabled": (dt_chosen_enabled, 1, 1),
Martí Bolívar7ff3ebc2020-04-23 12:28:06 -0700830 "dt_chosen_path": (dt_chosen_path, 1, 1),
Daniel DeGrassefbefc502022-04-11 11:53:03 -0500831 "dt_chosen_has_compat": (dt_chosen_has_compat, 2, 2),
Martí Bolívar24677f92020-04-28 16:52:35 -0700832 "dt_path_enabled": (dt_node_enabled, 1, 1),
833 "dt_alias_enabled": (dt_node_enabled, 1, 1),
Kumar Gala0353d222020-02-13 23:43:42 -0600834 "dt_nodelabel_enabled": (dt_nodelabel_enabled, 1, 1),
Andrzej Głąbekcd00a3a2022-03-28 12:16:51 +0200835 "dt_nodelabel_enabled_with_compat": (dt_nodelabel_enabled_with_compat, 2, 2),
Ulf Magnussonb4e18072019-12-23 11:07:27 +0100836 "dt_chosen_reg_addr_int": (dt_chosen_reg, 1, 3),
837 "dt_chosen_reg_addr_hex": (dt_chosen_reg, 1, 3),
838 "dt_chosen_reg_size_int": (dt_chosen_reg, 1, 3),
839 "dt_chosen_reg_size_hex": (dt_chosen_reg, 1, 3),
840 "dt_node_reg_addr_int": (dt_node_reg, 1, 3),
841 "dt_node_reg_addr_hex": (dt_node_reg, 1, 3),
842 "dt_node_reg_size_int": (dt_node_reg, 1, 3),
843 "dt_node_reg_size_hex": (dt_node_reg, 1, 3),
Jordan Yates999afdc2023-07-30 13:33:33 +1000844 "dt_nodelabel_reg_addr_int": (dt_nodelabel_reg, 1, 3),
845 "dt_nodelabel_reg_addr_hex": (dt_nodelabel_reg, 1, 3),
846 "dt_nodelabel_reg_size_int": (dt_nodelabel_reg, 1, 3),
847 "dt_nodelabel_reg_size_hex": (dt_nodelabel_reg, 1, 3),
Michał Barnaśa1ab8da2022-03-08 17:44:04 +0100848 "dt_node_bool_prop": (dt_node_bool_prop, 2, 2),
849 "dt_nodelabel_bool_prop": (dt_nodelabel_bool_prop, 2, 2),
Stephen Stautsd4b8db72022-12-27 11:40:17 +0100850 "dt_chosen_bool_prop": (dt_chosen_bool_prop, 2, 2),
Erwan Gourioub7110282021-01-07 12:06:31 +0100851 "dt_node_has_prop": (dt_node_has_prop, 2, 2),
Michał Barnaśa1ab8da2022-03-08 17:44:04 +0100852 "dt_nodelabel_has_prop": (dt_nodelabel_has_prop, 2, 2),
David Leach1e5a8302021-11-08 23:24:22 -0600853 "dt_node_int_prop_int": (dt_node_int_prop, 2, 3),
854 "dt_node_int_prop_hex": (dt_node_int_prop, 2, 3),
Eivind Jølsgard3865e082022-03-18 10:50:00 +0100855 "dt_node_array_prop_int": (dt_node_array_prop, 3, 4),
856 "dt_node_array_prop_hex": (dt_node_array_prop, 3, 4),
Erwan Gourioua59e01d2023-12-18 12:03:43 +0100857 "dt_node_ph_array_prop_int": (dt_node_ph_array_prop, 4, 5),
858 "dt_node_ph_array_prop_hex": (dt_node_ph_array_prop, 4, 5),
Johann Fischer73199f22021-11-18 17:12:23 +0100859 "dt_node_str_prop_equals": (dt_node_str_prop_equals, 3, 3),
Andrzej Głąbek3331a202020-02-14 11:53:21 +0100860 "dt_nodelabel_has_compat": (dt_nodelabel_has_compat, 2, 2),
Daniel DeGrasse6aa71942022-08-26 12:12:24 -0500861 "dt_node_has_compat": (dt_node_has_compat, 2, 2),
Martí Bolívar1fff2352020-04-22 18:06:18 -0700862 "dt_nodelabel_path": (dt_nodelabel_path, 1, 1),
Daniel DeGrassedb9bcd92022-08-26 12:10:14 -0500863 "dt_node_parent": (dt_node_parent, 1, 1),
Stephen Stautsd4b8db72022-12-27 11:40:17 +0100864 "dt_nodelabel_array_prop_has_val": (dt_nodelabel_array_prop_has_val, 3, 3),
Henrik Brix Andersenfba6c7f2023-01-18 17:43:02 +0100865 "dt_gpio_hogs_enabled": (dt_gpio_hogs_enabled, 0, 0),
Erwan Gouriou17537c72019-11-22 10:06:57 +0100866 "shields_list_contains": (shields_list_contains, 1, 1),
Kumar Gala87915cd2018-11-15 11:51:50 -0600867}