blob: 621ec3cb3a8bdc6f1b0b119f8ba69ba03d349254 [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
248
Kumar Gala22e74492019-10-23 15:15:59 -0500249def _dt_chosen_reg_addr(kconf, chosen, index=0, unit=None):
Kumar Gala57353972019-08-28 09:30:23 -0500250 """
251 This function takes a 'chosen' property and treats that property as a path
Ulf Magnusson73ac1462019-09-23 05:14:18 +0200252 to an EDT node. If it finds an EDT node, it will look to see if that
Nazar Kazakovf483b1b2022-03-16 21:07:43 +0000253 node has a register at the given 'index' and return the address value of
Kumar Gala57353972019-08-28 09:30:23 -0500254 that reg, if not we return 0.
255
256 The function will divide the value based on 'unit':
257 None No division
258 'k' or 'K' divide by 1024 (1 << 10)
259 'm' or 'M' divide by 1,048,576 (1 << 20)
260 'g' or 'G' divide by 1,073,741,824 (1 << 30)
Daniel DeGrasse6064da82022-05-25 17:38:59 -0500261 'kb' or 'Kb' divide by 8192 (1 << 13)
262 'mb' or 'Mb' divide by 8,388,608 (1 << 23)
263 'gb' or 'Gb' divide by 8,589,934,592 (1 << 33)
Kumar Gala57353972019-08-28 09:30:23 -0500264 """
265 if doc_mode or edt is None:
Kumar Gala22e74492019-10-23 15:15:59 -0500266 return 0
Kumar Gala57353972019-08-28 09:30:23 -0500267
Ulf Magnusson73ac1462019-09-23 05:14:18 +0200268 node = edt.chosen_node(chosen)
Kumar Gala57353972019-08-28 09:30:23 -0500269
Ulf Magnusson73ac1462019-09-23 05:14:18 +0200270 return _node_reg_addr(node, index, unit)
Kumar Gala57353972019-08-28 09:30:23 -0500271
272
Kumar Gala22e74492019-10-23 15:15:59 -0500273def _dt_chosen_reg_size(kconf, chosen, index=0, unit=None):
Kumar Gala57353972019-08-28 09:30:23 -0500274 """
275 This function takes a 'chosen' property and treats that property as a path
Ulf Magnusson73ac1462019-09-23 05:14:18 +0200276 to an EDT node. If it finds an EDT node, it will look to see if that node
277 has a register at the given 'index' and return the size value of that reg,
278 if not we return 0.
Kumar Gala57353972019-08-28 09:30:23 -0500279
280 The function will divide the value based on 'unit':
281 None No division
282 'k' or 'K' divide by 1024 (1 << 10)
283 'm' or 'M' divide by 1,048,576 (1 << 20)
284 'g' or 'G' divide by 1,073,741,824 (1 << 30)
Daniel DeGrasse6064da82022-05-25 17:38:59 -0500285 'kb' or 'Kb' divide by 8192 (1 << 13)
286 'mb' or 'Mb' divide by 8,388,608 (1 << 23)
287 'gb' or 'Gb' divide by 8,589,934,592 (1 << 33)
Kumar Gala57353972019-08-28 09:30:23 -0500288 """
289 if doc_mode or edt is None:
Kumar Gala22e74492019-10-23 15:15:59 -0500290 return 0
Kumar Gala57353972019-08-28 09:30:23 -0500291
Ulf Magnusson73ac1462019-09-23 05:14:18 +0200292 node = edt.chosen_node(chosen)
Kumar Gala57353972019-08-28 09:30:23 -0500293
Ulf Magnusson73ac1462019-09-23 05:14:18 +0200294 return _node_reg_size(node, index, unit)
Kumar Gala57353972019-08-28 09:30:23 -0500295
296
Kumar Gala22e74492019-10-23 15:15:59 -0500297def dt_chosen_reg(kconf, name, chosen, index=0, unit=None):
298 """
299 This function just routes to the proper function and converts
300 the result to either a string int or string hex value.
301 """
302 if name == "dt_chosen_reg_size_int":
303 return str(_dt_chosen_reg_size(kconf, chosen, index, unit))
304 if name == "dt_chosen_reg_size_hex":
305 return hex(_dt_chosen_reg_size(kconf, chosen, index, unit))
306 if name == "dt_chosen_reg_addr_int":
307 return str(_dt_chosen_reg_addr(kconf, chosen, index, unit))
308 if name == "dt_chosen_reg_addr_hex":
309 return hex(_dt_chosen_reg_addr(kconf, chosen, index, unit))
310
311
312def _dt_node_reg_addr(kconf, path, index=0, unit=None):
Kumar Gala57353972019-08-28 09:30:23 -0500313 """
Ulf Magnusson73ac1462019-09-23 05:14:18 +0200314 This function takes a 'path' and looks for an EDT node at that path. If it
315 finds an EDT node, it will look to see if that node has a register at the
316 given 'index' and return the address value of that reg, if not we return 0.
Kumar Gala57353972019-08-28 09:30:23 -0500317
318 The function will divide the value based on 'unit':
319 None No division
320 'k' or 'K' divide by 1024 (1 << 10)
321 'm' or 'M' divide by 1,048,576 (1 << 20)
322 'g' or 'G' divide by 1,073,741,824 (1 << 30)
Daniel DeGrasse6064da82022-05-25 17:38:59 -0500323 'kb' or 'Kb' divide by 8192 (1 << 13)
324 'mb' or 'Mb' divide by 8,388,608 (1 << 23)
325 'gb' or 'Gb' divide by 8,589,934,592 (1 << 33)
Kumar Gala57353972019-08-28 09:30:23 -0500326 """
327 if doc_mode or edt is None:
Kumar Gala22e74492019-10-23 15:15:59 -0500328 return 0
Kumar Gala57353972019-08-28 09:30:23 -0500329
330 try:
Ulf Magnusson73ac1462019-09-23 05:14:18 +0200331 node = edt.get_node(path)
Kumar Gala57353972019-08-28 09:30:23 -0500332 except edtlib.EDTError:
Kumar Gala22e74492019-10-23 15:15:59 -0500333 return 0
Kumar Gala57353972019-08-28 09:30:23 -0500334
Ulf Magnusson73ac1462019-09-23 05:14:18 +0200335 return _node_reg_addr(node, index, unit)
Kumar Gala57353972019-08-28 09:30:23 -0500336
337
Kumar Gala22e74492019-10-23 15:15:59 -0500338def _dt_node_reg_size(kconf, path, index=0, unit=None):
Kumar Gala57353972019-08-28 09:30:23 -0500339 """
Ulf Magnusson73ac1462019-09-23 05:14:18 +0200340 This function takes a 'path' and looks for an EDT node at that path. If it
341 finds an EDT node, it will look to see if that node has a register at the
342 given 'index' and return the size value of that reg, if not we return 0.
Kumar Gala57353972019-08-28 09:30:23 -0500343
344 The function will divide the value based on 'unit':
345 None No division
346 'k' or 'K' divide by 1024 (1 << 10)
347 'm' or 'M' divide by 1,048,576 (1 << 20)
348 'g' or 'G' divide by 1,073,741,824 (1 << 30)
Daniel DeGrasse6064da82022-05-25 17:38:59 -0500349 'kb' or 'Kb' divide by 8192 (1 << 13)
350 'mb' or 'Mb' divide by 8,388,608 (1 << 23)
351 'gb' or 'Gb' divide by 8,589,934,592 (1 << 33)
Kumar Gala57353972019-08-28 09:30:23 -0500352 """
353 if doc_mode or edt is None:
Kumar Gala22e74492019-10-23 15:15:59 -0500354 return 0
Kumar Gala57353972019-08-28 09:30:23 -0500355
356 try:
Ulf Magnusson73ac1462019-09-23 05:14:18 +0200357 node = edt.get_node(path)
Kumar Gala57353972019-08-28 09:30:23 -0500358 except edtlib.EDTError:
Kumar Gala22e74492019-10-23 15:15:59 -0500359 return 0
Kumar Gala57353972019-08-28 09:30:23 -0500360
Ulf Magnusson73ac1462019-09-23 05:14:18 +0200361 return _node_reg_size(node, index, unit)
Kumar Gala57353972019-08-28 09:30:23 -0500362
363
Kumar Gala22e74492019-10-23 15:15:59 -0500364def dt_node_reg(kconf, name, path, index=0, unit=None):
365 """
366 This function just routes to the proper function and converts
367 the result to either a string int or string hex value.
368 """
369 if name == "dt_node_reg_size_int":
370 return str(_dt_node_reg_size(kconf, path, index, unit))
371 if name == "dt_node_reg_size_hex":
372 return hex(_dt_node_reg_size(kconf, path, index, unit))
373 if name == "dt_node_reg_addr_int":
374 return str(_dt_node_reg_addr(kconf, path, index, unit))
375 if name == "dt_node_reg_addr_hex":
376 return hex(_dt_node_reg_addr(kconf, path, index, unit))
377
Jordan Yates999afdc2023-07-30 13:33:33 +1000378def dt_nodelabel_reg(kconf, name, label, index=0, unit=None):
379 """
380 This function is like dt_node_reg(), but the 'label' argument
381 should be a node label, like "foo" is here:
382
383 foo: some-node { ... };
384 """
385 if doc_mode or edt is None:
386 node = None
387 else:
388 node = edt.label2node.get(label)
389
390 if name == "dt_nodelabel_reg_size_int":
391 return str(_dt_node_reg_size(kconf, node.path, index, unit)) if node else "0"
392 if name == "dt_nodelabel_reg_size_hex":
393 return hex(_dt_node_reg_size(kconf, node.path, index, unit)) if node else "0x0"
394 if name == "dt_nodelabel_reg_addr_int":
395 return str(_dt_node_reg_addr(kconf, node.path, index, unit)) if node else "0"
396 if name == "dt_nodelabel_reg_addr_hex":
397 return hex(_dt_node_reg_addr(kconf, node.path, index, unit)) if node else "0x0"
398
399
Michał Barnaśa1ab8da2022-03-08 17:44:04 +0100400def _dt_node_bool_prop_generic(node_search_function, search_arg, prop):
Kumar Gala57353972019-08-28 09:30:23 -0500401 """
Michał Barnaśa1ab8da2022-03-08 17:44:04 +0100402 This function takes the 'node_search_function' and uses it to search for
403 a node with 'search_arg' and if node exists, checks if 'prop' exists
404 inside the node and is a boolean, if it is true, returns "y".
405 Otherwise, it returns "n".
Kumar Gala57353972019-08-28 09:30:23 -0500406 """
Kumar Gala57353972019-08-28 09:30:23 -0500407 try:
Michał Barnaśa1ab8da2022-03-08 17:44:04 +0100408 node = node_search_function(search_arg)
Kumar Gala57353972019-08-28 09:30:23 -0500409 except edtlib.EDTError:
410 return "n"
411
Andrzej Głąbek23994332022-03-23 14:45:11 +0100412 if node is None:
413 return "n"
414
Ulf Magnusson73ac1462019-09-23 05:14:18 +0200415 if prop not in node.props:
Kumar Gala57353972019-08-28 09:30:23 -0500416 return "n"
417
Ulf Magnusson73ac1462019-09-23 05:14:18 +0200418 if node.props[prop].type != "boolean":
Kumar Gala57353972019-08-28 09:30:23 -0500419 return "n"
420
Ulf Magnusson73ac1462019-09-23 05:14:18 +0200421 if node.props[prop].val:
Kumar Gala57353972019-08-28 09:30:23 -0500422 return "y"
423
424 return "n"
425
Michał Barnaśa1ab8da2022-03-08 17:44:04 +0100426def dt_node_bool_prop(kconf, _, path, prop):
Erwan Gourioub7110282021-01-07 12:06:31 +0100427 """
Michał Barnaśa1ab8da2022-03-08 17:44:04 +0100428 This function takes a 'path' and looks for an EDT node at that path. If it
429 finds an EDT node, it will look to see if that node has a boolean property
Erwan Gourioub7110282021-01-07 12:06:31 +0100430 by the name of 'prop'. If the 'prop' exists it will return "y" otherwise
431 we return "n".
432 """
Erwan Gourioub7110282021-01-07 12:06:31 +0100433 if doc_mode or edt is None:
434 return "n"
435
Michał Barnaśa1ab8da2022-03-08 17:44:04 +0100436 return _dt_node_bool_prop_generic(edt.get_node, path, prop)
437
438def dt_nodelabel_bool_prop(kconf, _, label, prop):
439 """
440 This function takes a 'label' and looks for an EDT node with that label.
441 If it finds an EDT node, it will look to see if that node has a boolean
442 property by the name of 'prop'. If the 'prop' exists it will return "y"
443 otherwise we return "n".
444 """
445 if doc_mode or edt is None:
446 return "n"
447
448 return _dt_node_bool_prop_generic(edt.label2node.get, label, prop)
449
Stephen Stautsd4b8db72022-12-27 11:40:17 +0100450def dt_chosen_bool_prop(kconf, _, chosen, prop):
451 """
452 This function takes a /chosen node property named 'chosen', and
453 looks for the chosen node. If that node exists and has a boolean
454 property 'prop', it returns "y". Otherwise, it returns "n".
455 """
456 if doc_mode or edt is None:
457 return "n"
458
459 return _dt_node_bool_prop_generic(edt.chosen_node, chosen, prop)
460
Michał Barnaśa1ab8da2022-03-08 17:44:04 +0100461def _dt_node_has_prop_generic(node_search_function, search_arg, prop):
462 """
463 This function takes the 'node_search_function' and uses it to search for
464 a node with 'search_arg' and if node exists, then checks if 'prop'
465 exists inside the node and returns "y". Otherwise, it returns "n".
466 """
Erwan Gourioub7110282021-01-07 12:06:31 +0100467 try:
Michał Barnaśa1ab8da2022-03-08 17:44:04 +0100468 node = node_search_function(search_arg)
Erwan Gourioub7110282021-01-07 12:06:31 +0100469 except edtlib.EDTError:
470 return "n"
471
472 if node is None:
473 return "n"
474
475 if prop in node.props:
476 return "y"
477
478 return "n"
Kumar Gala57353972019-08-28 09:30:23 -0500479
Michał Barnaśa1ab8da2022-03-08 17:44:04 +0100480def dt_node_has_prop(kconf, _, path, prop):
481 """
482 This function takes a 'path' and looks for an EDT node at that path. If it
483 finds an EDT node, it will look to see if that node has a property
484 by the name of 'prop'. If the 'prop' exists it will return "y" otherwise
485 it returns "n".
486 """
487 if doc_mode or edt is None:
488 return "n"
489
490 return _dt_node_has_prop_generic(edt.get_node, path, prop)
491
492def dt_nodelabel_has_prop(kconf, _, label, prop):
493 """
494 This function takes a 'label' and looks for an EDT node with that label.
495 If it finds an EDT node, it will look to see if that node has a property
496 by the name of 'prop'. If the 'prop' exists it will return "y" otherwise
497 it returns "n".
498 """
499 if doc_mode or edt is None:
500 return "n"
501
502 return _dt_node_has_prop_generic(edt.label2node.get, label, prop)
503
David Leach1e5a8302021-11-08 23:24:22 -0600504def dt_node_int_prop(kconf, name, path, prop, unit=None):
Kumar Gala338b43192020-04-03 05:02:35 -0500505 """
506 This function takes a 'path' and property name ('prop') looks for an EDT
507 node at that path. If it finds an EDT node, it will look to see if that
508 node has a property called 'prop' and if that 'prop' is an integer type
509 will return the value of the property 'prop' as either a string int or
510 string hex value, if not we return 0.
Kumar Gala338b43192020-04-03 05:02:35 -0500511
David Leach1e5a8302021-11-08 23:24:22 -0600512 The function will divide the value based on 'unit':
513 None No division
514 'k' or 'K' divide by 1024 (1 << 10)
515 'm' or 'M' divide by 1,048,576 (1 << 20)
516 'g' or 'G' divide by 1,073,741,824 (1 << 30)
Daniel DeGrasse6064da82022-05-25 17:38:59 -0500517 'kb' or 'Kb' divide by 8192 (1 << 13)
518 'mb' or 'Mb' divide by 8,388,608 (1 << 23)
519 'gb' or 'Gb' divide by 8,589,934,592 (1 << 33)
David Leach1e5a8302021-11-08 23:24:22 -0600520 """
Kumar Gala338b43192020-04-03 05:02:35 -0500521 if doc_mode or edt is None:
522 return "0"
523
524 try:
525 node = edt.get_node(path)
526 except edtlib.EDTError:
527 return "0"
528
529 if name == "dt_node_int_prop_int":
David Leach1e5a8302021-11-08 23:24:22 -0600530 return str(_node_int_prop(node, prop, unit))
Kumar Gala338b43192020-04-03 05:02:35 -0500531 if name == "dt_node_int_prop_hex":
David Leach1e5a8302021-11-08 23:24:22 -0600532 return hex(_node_int_prop(node, prop, unit))
Kumar Gala338b43192020-04-03 05:02:35 -0500533
Eivind Jølsgard3865e082022-03-18 10:50:00 +0100534
535def dt_node_array_prop(kconf, name, path, prop, index, unit=None):
536 """
537 This function takes a 'path', property name ('prop') and index ('index')
538 and looks for an EDT node at that path. If it finds an EDT node, it will
539 look to see if that node has a property called 'prop' and if that 'prop'
540 is an array type will return the value of the property 'prop' at the given
541 'index' as either a string int or string hex value. If not found we return 0.
542
543 The function will divide the value based on 'unit':
544 None No division
545 'k' or 'K' divide by 1024 (1 << 10)
546 'm' or 'M' divide by 1,048,576 (1 << 20)
547 'g' or 'G' divide by 1,073,741,824 (1 << 30)
548 """
549 if doc_mode or edt is None:
550 return "0"
551
552 try:
553 node = edt.get_node(path)
554 except edtlib.EDTError:
555 return "0"
556 if name == "dt_node_array_prop_int":
557 return str(_node_array_prop(node, prop, index, unit))
558 if name == "dt_node_array_prop_hex":
559 return hex(_node_array_prop(node, prop, index, unit))
560
561
Johann Fischer73199f22021-11-18 17:12:23 +0100562def dt_node_str_prop_equals(kconf, _, path, prop, val):
563 """
564 This function takes a 'path' and property name ('prop') looks for an EDT
565 node at that path. If it finds an EDT node, it will look to see if that
566 node has a property 'prop' of type string. If that 'prop' is equal to 'val'
567 it will return "y" otherwise return "n".
568 """
569
570 if doc_mode or edt is None:
571 return "n"
572
573 try:
574 node = edt.get_node(path)
575 except edtlib.EDTError:
576 return "n"
577
578 if prop not in node.props:
579 return "n"
580
581 if node.props[prop].type != "string":
582 return "n"
583
584 if node.props[prop].val == val:
585 return "y"
586
587 return "n"
Kumar Gala338b43192020-04-03 05:02:35 -0500588
Andrzej Głąbek9f2a27b2022-03-15 14:08:21 +0100589
590def dt_has_compat(kconf, _, compat):
591 """
592 This function takes a 'compat' and returns "y" if any compatible node
593 can be found in the EDT, otherwise it returns "n".
594 """
595 if doc_mode or edt is None:
596 return "n"
597
598 return "y" if compat in edt.compat2nodes else "n"
599
600
Kumar Gala57353972019-08-28 09:30:23 -0500601def dt_compat_enabled(kconf, _, compat):
602 """
Martí Bolívar81650082020-10-05 20:02:13 -0700603 This function takes a 'compat' and returns "y" if we find a status "okay"
Ulf Magnusson73ac1462019-09-23 05:14:18 +0200604 compatible node in the EDT otherwise we return "n"
Kumar Gala57353972019-08-28 09:30:23 -0500605 """
606 if doc_mode or edt is None:
607 return "n"
608
Martí Bolívar81650082020-10-05 20:02:13 -0700609 return "y" if compat in edt.compat2okay else "n"
Kumar Gala57353972019-08-28 09:30:23 -0500610
611
Martí Bolívar3cd4f6c2020-04-10 15:37:58 -0700612def dt_compat_on_bus(kconf, _, compat, bus):
613 """
614 This function takes a 'compat' and returns "y" if we find an "enabled"
615 compatible node in the EDT which is on bus 'bus'. It returns "n" otherwise.
616 """
617 if doc_mode or edt is None:
618 return "n"
619
Andrzej Głąbekf9c1f892021-02-03 13:53:48 +0100620 if compat in edt.compat2okay:
621 for node in edt.compat2okay[compat]:
Daniel Leung418c9152022-08-26 10:52:32 -0700622 if node.on_buses is not None and bus in node.on_buses:
Andrzej Głąbekf9c1f892021-02-03 13:53:48 +0100623 return "y"
Martí Bolívar3cd4f6c2020-04-10 15:37:58 -0700624
625 return "n"
626
627
Andrzej Głąbek3331a202020-02-14 11:53:21 +0100628def dt_nodelabel_has_compat(kconf, _, label, compat):
629 """
Andrzej Głąbekcd00a3a2022-03-28 12:16:51 +0200630 This function takes a 'label' and looks for an EDT node with that label.
631 If it finds such node, it returns "y" if this node is compatible with
632 the provided 'compat'. Otherwise, it return "n" .
633 """
634 if doc_mode or edt is None:
635 return "n"
636
637 node = edt.label2node.get(label)
638
639 if node and compat in node.compats:
640 return "y"
641
642 return "n"
643
Daniel DeGrasse6aa71942022-08-26 12:12:24 -0500644def dt_node_has_compat(kconf, _, path, compat):
645 """
646 This function takes a 'path' and looks for an EDT node at that path. If it
647 finds an EDT node, it returns "y" if this node is compatible with
648 the provided 'compat'. Otherwise, it return "n" .
649 """
650
651 if doc_mode or edt is None:
652 return "n"
653
654 try:
655 node = edt.get_node(path)
656 except edtlib.EDTError:
657 return "n"
658
659 if node and compat in node.compats:
660 return "y"
661
662 return "n"
Andrzej Głąbekcd00a3a2022-03-28 12:16:51 +0200663
664def dt_nodelabel_enabled_with_compat(kconf, _, label, compat):
665 """
Andrzej Głąbek3331a202020-02-14 11:53:21 +0100666 This function takes a 'label' and returns "y" if an "enabled" node with
667 such label can be found in the EDT and that node is compatible with the
668 provided 'compat', otherwise it returns "n".
669 """
670 if doc_mode or edt is None:
671 return "n"
672
Andrzej Głąbekf9c1f892021-02-03 13:53:48 +0100673 if compat in edt.compat2okay:
674 for node in edt.compat2okay[compat]:
675 if label in node.labels:
676 return "y"
Andrzej Głąbek3331a202020-02-14 11:53:21 +0100677
678 return "n"
679
680
Stephen Stautsd4b8db72022-12-27 11:40:17 +0100681def dt_nodelabel_array_prop_has_val(kconf, _, label, prop, val):
682 """
683 This function looks for a node with node label 'label'.
684 If the node exists, it checks if the node node has a property
685 'prop' with type "array". If so, and the property contains
686 an element equal to the integer 'val', it returns "y".
687 Otherwise, it returns "n".
688 """
689 if doc_mode or edt is None:
690 return "n"
691
692 node = edt.label2node.get(label)
693
694 if not node or (prop not in node.props) or (node.props[prop].type != "array"):
695 return "n"
696 else:
697 return "y" if int(val, base=0) in node.props[prop].val else "n"
698
699
Martí Bolívar1fff2352020-04-22 18:06:18 -0700700def dt_nodelabel_path(kconf, _, label):
701 """
702 This function takes a node label (not a label property) and
703 returns the path to the node which has that label, or an empty
704 string if there is no such node.
705 """
706 if doc_mode or edt is None:
707 return ""
708
709 node = edt.label2node.get(label)
710
711 return node.path if node else ""
712
Daniel DeGrassedb9bcd92022-08-26 12:10:14 -0500713def dt_node_parent(kconf, _, path):
714 """
715 This function takes a 'path' and looks for an EDT node at that path. If it
716 finds an EDT node, it will look for the parent of that node. If the parent
717 exists, it will return the path to that parent. Otherwise, an empty string
718 will be returned.
719 """
720 if doc_mode or edt is None:
721 return ""
722
723 try:
724 node = edt.get_node(path)
725 except edtlib.EDTError:
726 return ""
727
728 if node is None:
729 return ""
730
731 return node.parent.path if node.parent else ""
Martí Bolívar1fff2352020-04-22 18:06:18 -0700732
Henrik Brix Andersenfba6c7f2023-01-18 17:43:02 +0100733def dt_gpio_hogs_enabled(kconf, _):
734 """
735 Return "y" if any GPIO hog node is enabled. Otherwise, return "n".
736 """
737 if doc_mode or edt is None:
738 return "n"
739
740 for node in edt.nodes:
741 if node.gpio_hogs and node.status == "okay":
742 return "y"
743
744 return "n"
745
Erwan Gouriou17537c72019-11-22 10:06:57 +0100746def shields_list_contains(kconf, _, shield):
747 """
748 Return "n" if cmake environment variable 'SHIELD_AS_LIST' doesn't exist.
749 Return "y" if 'shield' is present list obtained after 'SHIELD_AS_LIST'
750 has been split using ";" as a separator and "n" otherwise.
751 """
752 try:
753 list = os.environ['SHIELD_AS_LIST']
754 except KeyError:
755 return "n"
756
757 return "y" if shield in list.split(";") else "n"
758
759
Martí Bolívar006319f2020-07-21 15:20:18 -0700760# Keys in this dict are the function names as they appear
761# in Kconfig files. The values are tuples in this form:
762#
763# (python_function, minimum_number_of_args, maximum_number_of_args)
764#
765# Each python function is given a kconf object and its name in the
766# Kconfig file, followed by arguments from the Kconfig file.
767#
768# See the kconfiglib documentation for more details.
Kumar Gala87915cd2018-11-15 11:51:50 -0600769functions = {
Andrzej Głąbek9f2a27b2022-03-15 14:08:21 +0100770 "dt_has_compat": (dt_has_compat, 1, 1),
Kumar Gala57353972019-08-28 09:30:23 -0500771 "dt_compat_enabled": (dt_compat_enabled, 1, 1),
Martí Bolívar3cd4f6c2020-04-10 15:37:58 -0700772 "dt_compat_on_bus": (dt_compat_on_bus, 2, 2),
Kumar Gala57353972019-08-28 09:30:23 -0500773 "dt_chosen_label": (dt_chosen_label, 1, 1),
Kumar Gala07e5d892019-11-04 10:20:59 -0600774 "dt_chosen_enabled": (dt_chosen_enabled, 1, 1),
Martí Bolívar7ff3ebc2020-04-23 12:28:06 -0700775 "dt_chosen_path": (dt_chosen_path, 1, 1),
Daniel DeGrassefbefc502022-04-11 11:53:03 -0500776 "dt_chosen_has_compat": (dt_chosen_has_compat, 2, 2),
Martí Bolívar24677f92020-04-28 16:52:35 -0700777 "dt_path_enabled": (dt_node_enabled, 1, 1),
778 "dt_alias_enabled": (dt_node_enabled, 1, 1),
Kumar Gala0353d222020-02-13 23:43:42 -0600779 "dt_nodelabel_enabled": (dt_nodelabel_enabled, 1, 1),
Andrzej Głąbekcd00a3a2022-03-28 12:16:51 +0200780 "dt_nodelabel_enabled_with_compat": (dt_nodelabel_enabled_with_compat, 2, 2),
Ulf Magnussonb4e18072019-12-23 11:07:27 +0100781 "dt_chosen_reg_addr_int": (dt_chosen_reg, 1, 3),
782 "dt_chosen_reg_addr_hex": (dt_chosen_reg, 1, 3),
783 "dt_chosen_reg_size_int": (dt_chosen_reg, 1, 3),
784 "dt_chosen_reg_size_hex": (dt_chosen_reg, 1, 3),
785 "dt_node_reg_addr_int": (dt_node_reg, 1, 3),
786 "dt_node_reg_addr_hex": (dt_node_reg, 1, 3),
787 "dt_node_reg_size_int": (dt_node_reg, 1, 3),
788 "dt_node_reg_size_hex": (dt_node_reg, 1, 3),
Jordan Yates999afdc2023-07-30 13:33:33 +1000789 "dt_nodelabel_reg_addr_int": (dt_nodelabel_reg, 1, 3),
790 "dt_nodelabel_reg_addr_hex": (dt_nodelabel_reg, 1, 3),
791 "dt_nodelabel_reg_size_int": (dt_nodelabel_reg, 1, 3),
792 "dt_nodelabel_reg_size_hex": (dt_nodelabel_reg, 1, 3),
Michał Barnaśa1ab8da2022-03-08 17:44:04 +0100793 "dt_node_bool_prop": (dt_node_bool_prop, 2, 2),
794 "dt_nodelabel_bool_prop": (dt_nodelabel_bool_prop, 2, 2),
Stephen Stautsd4b8db72022-12-27 11:40:17 +0100795 "dt_chosen_bool_prop": (dt_chosen_bool_prop, 2, 2),
Erwan Gourioub7110282021-01-07 12:06:31 +0100796 "dt_node_has_prop": (dt_node_has_prop, 2, 2),
Michał Barnaśa1ab8da2022-03-08 17:44:04 +0100797 "dt_nodelabel_has_prop": (dt_nodelabel_has_prop, 2, 2),
David Leach1e5a8302021-11-08 23:24:22 -0600798 "dt_node_int_prop_int": (dt_node_int_prop, 2, 3),
799 "dt_node_int_prop_hex": (dt_node_int_prop, 2, 3),
Eivind Jølsgard3865e082022-03-18 10:50:00 +0100800 "dt_node_array_prop_int": (dt_node_array_prop, 3, 4),
801 "dt_node_array_prop_hex": (dt_node_array_prop, 3, 4),
Johann Fischer73199f22021-11-18 17:12:23 +0100802 "dt_node_str_prop_equals": (dt_node_str_prop_equals, 3, 3),
Andrzej Głąbek3331a202020-02-14 11:53:21 +0100803 "dt_nodelabel_has_compat": (dt_nodelabel_has_compat, 2, 2),
Daniel DeGrasse6aa71942022-08-26 12:12:24 -0500804 "dt_node_has_compat": (dt_node_has_compat, 2, 2),
Martí Bolívar1fff2352020-04-22 18:06:18 -0700805 "dt_nodelabel_path": (dt_nodelabel_path, 1, 1),
Daniel DeGrassedb9bcd92022-08-26 12:10:14 -0500806 "dt_node_parent": (dt_node_parent, 1, 1),
Stephen Stautsd4b8db72022-12-27 11:40:17 +0100807 "dt_nodelabel_array_prop_has_val": (dt_nodelabel_array_prop_has_val, 3, 3),
Henrik Brix Andersenfba6c7f2023-01-18 17:43:02 +0100808 "dt_gpio_hogs_enabled": (dt_gpio_hogs_enabled, 0, 0),
Erwan Gouriou17537c72019-11-22 10:06:57 +0100809 "shields_list_contains": (shields_list_contains, 1, 1),
Kumar Gala87915cd2018-11-15 11:51:50 -0600810}