1# Copyright (c) 2018-2019 Linaro 2# Copyright (c) 2019 Nordic Semiconductor ASA 3# 4# SPDX-License-Identifier: Apache-2.0 5 6import functools 7import inspect 8import operator 9import os 10import pickle 11import re 12import sys 13from pathlib import Path 14 15ZEPHYR_BASE = str(Path(__file__).resolve().parents[2]) 16sys.path.insert(0, os.path.join(ZEPHYR_BASE, "scripts", "dts", 17 "python-devicetree", "src")) 18 19# Types we support 20# 'string', 'int', 'hex', 'bool' 21 22doc_mode = os.environ.get('KCONFIG_DOC_MODE') == "1" 23 24if not doc_mode: 25 EDT_PICKLE = os.environ.get("EDT_PICKLE") 26 27 # The "if" handles a missing dts. 28 if EDT_PICKLE is not None and os.path.isfile(EDT_PICKLE): 29 with open(EDT_PICKLE, 'rb') as f: 30 edt = pickle.load(f) 31 edtlib = inspect.getmodule(edt) 32 else: 33 edt = None 34 edtlib = None 35 36 37def _warn(kconf, msg): 38 print("{}:{}: WARNING: {}".format(kconf.filename, kconf.linenr, msg)) 39 40 41def _dt_units_to_scale(unit): 42 if not unit: 43 return 0 44 if unit in {'k', 'K'}: 45 return 10 46 if unit in {'m', 'M'}: 47 return 20 48 if unit in {'g', 'G'}: 49 return 30 50 if unit in {'kb', 'Kb'}: 51 return 13 52 if unit in {'mb', 'Mb'}: 53 return 23 54 if unit in {'gb', 'Gb'}: 55 return 33 56 57 58def dt_chosen_label(kconf, _, chosen): 59 """ 60 This function takes a 'chosen' property and treats that property as a path 61 to an EDT node. If it finds an EDT node, it will look to see if that node 62 has a "label" property and return the value of that "label". If not, we 63 return the node's name in the devicetree. 64 """ 65 if doc_mode or edt is None: 66 return "" 67 68 node = edt.chosen_node(chosen) 69 if not node: 70 return "" 71 72 if "label" not in node.props: 73 return node.name 74 75 return node.props["label"].val 76 77 78def dt_chosen_enabled(kconf, _, chosen): 79 """ 80 This function returns "y" if /chosen contains a property named 'chosen' 81 that points to an enabled node, and "n" otherwise 82 """ 83 if doc_mode or edt is None: 84 return "n" 85 86 node = edt.chosen_node(chosen) 87 return "y" if node and node.status == "okay" else "n" 88 89 90def dt_chosen_path(kconf, _, chosen): 91 """ 92 This function takes a /chosen node property and returns the path 93 to the node in the property value, or the empty string. 94 """ 95 if doc_mode or edt is None: 96 return "n" 97 98 node = edt.chosen_node(chosen) 99 100 return node.path if node else "" 101 102def dt_chosen_has_compat(kconf, _, chosen, compat): 103 """ 104 This function takes a /chosen node property and returns 'y' if the 105 chosen node has the provided compatible string 'compat' 106 """ 107 if doc_mode or edt is None: 108 return "n" 109 110 node = edt.chosen_node(chosen) 111 112 if node is None: 113 return "n" 114 115 if compat in node.compats: 116 return "y" 117 118 return "n" 119 120def dt_node_enabled(kconf, name, node): 121 """ 122 This function is used to test if a node is enabled (has status 123 'okay') or not. 124 125 The 'node' argument is a string which is either a path or an 126 alias, or both, depending on 'name'. 127 128 If 'name' is 'dt_path_enabled', 'node' is an alias or a path. If 129 'name' is 'dt_alias_enabled, 'node' is an alias. 130 """ 131 132 if doc_mode or edt is None: 133 return "n" 134 135 if name == "dt_alias_enabled": 136 if node.startswith("/"): 137 # EDT.get_node() works with either aliases or paths. If we 138 # are specifically being asked about an alias, reject paths. 139 return "n" 140 else: 141 # Make sure this is being called appropriately. 142 assert name == "dt_path_enabled" 143 144 try: 145 node = edt.get_node(node) 146 except edtlib.EDTError: 147 return "n" 148 149 return "y" if node and node.status == "okay" else "n" 150 151 152def dt_nodelabel_enabled(kconf, _, label): 153 """ 154 This function is like dt_node_enabled(), but the 'label' argument 155 should be a node label, like "foo" is here: 156 157 foo: some-node { ... }; 158 """ 159 if doc_mode or edt is None: 160 return "n" 161 162 node = edt.label2node.get(label) 163 164 return "y" if node and node.status == "okay" else "n" 165 166 167def _node_reg_addr(node, index, unit): 168 if not node: 169 return 0 170 171 if not node.regs: 172 return 0 173 174 if int(index) >= len(node.regs): 175 return 0 176 177 if node.regs[int(index)].addr is None: 178 return 0 179 180 return node.regs[int(index)].addr >> _dt_units_to_scale(unit) 181 182 183def _node_reg_size(node, index, unit): 184 if not node: 185 return 0 186 187 if not node.regs: 188 return 0 189 190 if int(index) >= len(node.regs): 191 return 0 192 193 if node.regs[int(index)].size is None: 194 return 0 195 196 return node.regs[int(index)].size >> _dt_units_to_scale(unit) 197 198 199def _node_int_prop(node, prop, unit=None): 200 """ 201 This function takes a 'node' and will look to see if that 'node' has a 202 property called 'prop' and if that 'prop' is an integer type will return 203 the value of the property 'prop' as either a string int or string hex 204 value, if not we return 0. 205 206 The function will divide the value based on 'unit': 207 None No division 208 'k' or 'K' divide by 1024 (1 << 10) 209 'm' or 'M' divide by 1,048,576 (1 << 20) 210 'g' or 'G' divide by 1,073,741,824 (1 << 30) 211 'kb' or 'Kb' divide by 8192 (1 << 13) 212 'mb' or 'Mb' divide by 8,388,608 (1 << 23) 213 'gb' or 'Gb' divide by 8,589,934,592 (1 << 33) 214 """ 215 if not node: 216 return 0 217 218 if prop not in node.props: 219 return 0 220 221 if node.props[prop].type != "int": 222 return 0 223 224 return node.props[prop].val >> _dt_units_to_scale(unit) 225 226 227def _node_array_prop(node, prop, index=0, unit=None): 228 """ 229 This function takes a 'node' and will look to see if that 'node' has a 230 property called 'prop' and if that 'prop' is an array type will return 231 the value of the property 'prop' at the given 'index' as either a string int 232 or string hex value. If the property 'prop' is not found or the given 'index' 233 is out of range it will return 0. 234 235 The function will divide the value based on 'unit': 236 None No division 237 'k' or 'K' divide by 1024 (1 << 10) 238 'm' or 'M' divide by 1,048,576 (1 << 20) 239 'g' or 'G' divide by 1,073,741,824 (1 << 30) 240 """ 241 if not node: 242 return 0 243 244 if prop not in node.props: 245 return 0 246 if node.props[prop].type != "array": 247 return 0 248 if int(index) >= len(node.props[prop].val): 249 return 0 250 return node.props[prop].val[int(index)] >> _dt_units_to_scale(unit) 251 252def _node_ph_array_prop(node, prop, index, cell, unit=None): 253 """ 254 This function takes a 'node', a property name ('prop'), index ('index') and 255 a cell ('cell') and it will look to see if that node has a property 256 called 'prop' and if that 'prop' is an phandle-array type. 257 Then it will check if that phandle array has a cell matching the given index 258 and then return the value of the cell named 'cell' in this array index. 259 If not found it will return 0. 260 261 The function will divide the value based on 'unit': 262 None No division 263 'k' or 'K' divide by 1024 (1 << 10) 264 'm' or 'M' divide by 1,048,576 (1 << 20) 265 'g' or 'G' divide by 1,073,741,824 (1 << 30) 266 """ 267 if not node: 268 return 0 269 270 if prop not in node.props: 271 return 0 272 if node.props[prop].type != "phandle-array": 273 return 0 274 if int(index) >= len(node.props[prop].val): 275 return 0 276 if cell not in node.props[prop].val[int(index)].data.keys(): 277 return 0 278 return node.props[prop].val[int(index)].data[cell] >> _dt_units_to_scale(unit) 279 280def _dt_chosen_reg_addr(kconf, chosen, index=0, unit=None): 281 """ 282 This function takes a 'chosen' property and treats that property as a path 283 to an EDT node. If it finds an EDT node, it will look to see if that 284 node has a register at the given 'index' and return the address value of 285 that reg, if not we return 0. 286 287 The function will divide the value based on 'unit': 288 None No division 289 'k' or 'K' divide by 1024 (1 << 10) 290 'm' or 'M' divide by 1,048,576 (1 << 20) 291 'g' or 'G' divide by 1,073,741,824 (1 << 30) 292 'kb' or 'Kb' divide by 8192 (1 << 13) 293 'mb' or 'Mb' divide by 8,388,608 (1 << 23) 294 'gb' or 'Gb' divide by 8,589,934,592 (1 << 33) 295 """ 296 if doc_mode or edt is None: 297 return 0 298 299 node = edt.chosen_node(chosen) 300 301 return _node_reg_addr(node, index, unit) 302 303 304def _dt_chosen_reg_size(kconf, chosen, index=0, unit=None): 305 """ 306 This function takes a 'chosen' property and treats that property as a path 307 to an EDT node. If it finds an EDT node, it will look to see if that node 308 has a register at the given 'index' and return the size value of that reg, 309 if not we return 0. 310 311 The function will divide the value based on 'unit': 312 None No division 313 'k' or 'K' divide by 1024 (1 << 10) 314 'm' or 'M' divide by 1,048,576 (1 << 20) 315 'g' or 'G' divide by 1,073,741,824 (1 << 30) 316 'kb' or 'Kb' divide by 8192 (1 << 13) 317 'mb' or 'Mb' divide by 8,388,608 (1 << 23) 318 'gb' or 'Gb' divide by 8,589,934,592 (1 << 33) 319 """ 320 if doc_mode or edt is None: 321 return 0 322 323 node = edt.chosen_node(chosen) 324 325 return _node_reg_size(node, index, unit) 326 327 328def dt_chosen_reg(kconf, name, chosen, index=0, unit=None): 329 """ 330 This function just routes to the proper function and converts 331 the result to either a string int or string hex value. 332 """ 333 if name == "dt_chosen_reg_size_int": 334 return str(_dt_chosen_reg_size(kconf, chosen, index, unit)) 335 if name == "dt_chosen_reg_size_hex": 336 return hex(_dt_chosen_reg_size(kconf, chosen, index, unit)) 337 if name == "dt_chosen_reg_addr_int": 338 return str(_dt_chosen_reg_addr(kconf, chosen, index, unit)) 339 if name == "dt_chosen_reg_addr_hex": 340 return hex(_dt_chosen_reg_addr(kconf, chosen, index, unit)) 341 342 343def _dt_chosen_partition_addr(kconf, chosen, index=0, unit=None): 344 """ 345 This function takes a 'chosen' property and treats that property as a path 346 to an EDT node. If it finds an EDT node, it will look to see if that 347 node has a register, and if that node has a grandparent that has a register 348 at the given 'index'. The addition of both addresses will be returned, if 349 not, we return 0. 350 351 The function will divide the value based on 'unit': 352 None No division 353 'k' or 'K' divide by 1024 (1 << 10) 354 'm' or 'M' divide by 1,048,576 (1 << 20) 355 'g' or 'G' divide by 1,073,741,824 (1 << 30) 356 'kb' or 'Kb' divide by 8192 (1 << 13) 357 'mb' or 'Mb' divide by 8,388,608 (1 << 23) 358 'gb' or 'Gb' divide by 8,589,934,592 (1 << 33) 359 """ 360 if doc_mode or edt is None: 361 return 0 362 363 node = edt.chosen_node(chosen) 364 if not node: 365 return 0 366 367 p_node = node.parent 368 if not p_node: 369 return 0 370 371 return _node_reg_addr(p_node.parent, index, unit) + _node_reg_addr(node, 0, unit) 372 373 374def dt_chosen_partition_addr(kconf, name, chosen, index=0, unit=None): 375 """ 376 This function just routes to the proper function and converts 377 the result to either a string int or string hex value. 378 """ 379 if name == "dt_chosen_partition_addr_int": 380 return str(_dt_chosen_partition_addr(kconf, chosen, index, unit)) 381 if name == "dt_chosen_partition_addr_hex": 382 return hex(_dt_chosen_partition_addr(kconf, chosen, index, unit)) 383 384 385def _dt_node_reg_addr(kconf, path, index=0, unit=None): 386 """ 387 This function takes a 'path' and looks for an EDT node at that path. If it 388 finds an EDT node, it will look to see if that node has a register at the 389 given 'index' and return the address value of that reg, if not we return 0. 390 391 The function will divide the value based on 'unit': 392 None No division 393 'k' or 'K' divide by 1024 (1 << 10) 394 'm' or 'M' divide by 1,048,576 (1 << 20) 395 'g' or 'G' divide by 1,073,741,824 (1 << 30) 396 'kb' or 'Kb' divide by 8192 (1 << 13) 397 'mb' or 'Mb' divide by 8,388,608 (1 << 23) 398 'gb' or 'Gb' divide by 8,589,934,592 (1 << 33) 399 """ 400 if doc_mode or edt is None: 401 return 0 402 403 try: 404 node = edt.get_node(path) 405 except edtlib.EDTError: 406 return 0 407 408 return _node_reg_addr(node, index, unit) 409 410 411def _dt_node_reg_size(kconf, path, index=0, unit=None): 412 """ 413 This function takes a 'path' and looks for an EDT node at that path. If it 414 finds an EDT node, it will look to see if that node has a register at the 415 given 'index' and return the size value of that reg, if not we return 0. 416 417 The function will divide the value based on 'unit': 418 None No division 419 'k' or 'K' divide by 1024 (1 << 10) 420 'm' or 'M' divide by 1,048,576 (1 << 20) 421 'g' or 'G' divide by 1,073,741,824 (1 << 30) 422 'kb' or 'Kb' divide by 8192 (1 << 13) 423 'mb' or 'Mb' divide by 8,388,608 (1 << 23) 424 'gb' or 'Gb' divide by 8,589,934,592 (1 << 33) 425 """ 426 if doc_mode or edt is None: 427 return 0 428 429 try: 430 node = edt.get_node(path) 431 except edtlib.EDTError: 432 return 0 433 434 return _node_reg_size(node, index, unit) 435 436 437def dt_node_reg(kconf, name, path, index=0, unit=None): 438 """ 439 This function just routes to the proper function and converts 440 the result to either a string int or string hex value. 441 """ 442 if name == "dt_node_reg_size_int": 443 return str(_dt_node_reg_size(kconf, path, index, unit)) 444 if name == "dt_node_reg_size_hex": 445 return hex(_dt_node_reg_size(kconf, path, index, unit)) 446 if name == "dt_node_reg_addr_int": 447 return str(_dt_node_reg_addr(kconf, path, index, unit)) 448 if name == "dt_node_reg_addr_hex": 449 return hex(_dt_node_reg_addr(kconf, path, index, unit)) 450 451def dt_nodelabel_reg(kconf, name, label, index=0, unit=None): 452 """ 453 This function is like dt_node_reg(), but the 'label' argument 454 should be a node label, like "foo" is here: 455 456 foo: some-node { ... }; 457 """ 458 if doc_mode or edt is None: 459 node = None 460 else: 461 node = edt.label2node.get(label) 462 463 if name == "dt_nodelabel_reg_size_int": 464 return str(_dt_node_reg_size(kconf, node.path, index, unit)) if node else "0" 465 if name == "dt_nodelabel_reg_size_hex": 466 return hex(_dt_node_reg_size(kconf, node.path, index, unit)) if node else "0x0" 467 if name == "dt_nodelabel_reg_addr_int": 468 return str(_dt_node_reg_addr(kconf, node.path, index, unit)) if node else "0" 469 if name == "dt_nodelabel_reg_addr_hex": 470 return hex(_dt_node_reg_addr(kconf, node.path, index, unit)) if node else "0x0" 471 472 473def _dt_node_bool_prop_generic(node_search_function, search_arg, prop): 474 """ 475 This function takes the 'node_search_function' and uses it to search for 476 a node with 'search_arg' and if node exists, checks if 'prop' exists 477 inside the node and is a boolean, if it is true, returns "y". 478 Otherwise, it returns "n". 479 """ 480 try: 481 node = node_search_function(search_arg) 482 except edtlib.EDTError: 483 return "n" 484 485 if node is None: 486 return "n" 487 488 if prop not in node.props: 489 return "n" 490 491 if node.props[prop].type != "boolean": 492 return "n" 493 494 if node.props[prop].val: 495 return "y" 496 497 return "n" 498 499def dt_node_bool_prop(kconf, _, path, prop): 500 """ 501 This function takes a 'path' and looks for an EDT node at that path. If it 502 finds an EDT node, it will look to see if that node has a boolean property 503 by the name of 'prop'. If the 'prop' exists it will return "y" otherwise 504 we return "n". 505 """ 506 if doc_mode or edt is None: 507 return "n" 508 509 return _dt_node_bool_prop_generic(edt.get_node, path, prop) 510 511def dt_nodelabel_bool_prop(kconf, _, label, prop): 512 """ 513 This function takes a 'label' and looks for an EDT node with that label. 514 If it finds an EDT node, it will look to see if that node has a boolean 515 property by the name of 'prop'. If the 'prop' exists it will return "y" 516 otherwise we return "n". 517 """ 518 if doc_mode or edt is None: 519 return "n" 520 521 return _dt_node_bool_prop_generic(edt.label2node.get, label, prop) 522 523def dt_chosen_bool_prop(kconf, _, chosen, prop): 524 """ 525 This function takes a /chosen node property named 'chosen', and 526 looks for the chosen node. If that node exists and has a boolean 527 property 'prop', it returns "y". Otherwise, it returns "n". 528 """ 529 if doc_mode or edt is None: 530 return "n" 531 532 return _dt_node_bool_prop_generic(edt.chosen_node, chosen, prop) 533 534def _dt_node_has_prop_generic(node_search_function, search_arg, prop): 535 """ 536 This function takes the 'node_search_function' and uses it to search for 537 a node with 'search_arg' and if node exists, then checks if 'prop' 538 exists inside the node and returns "y". Otherwise, it returns "n". 539 """ 540 try: 541 node = node_search_function(search_arg) 542 except edtlib.EDTError: 543 return "n" 544 545 if node is None: 546 return "n" 547 548 if prop in node.props: 549 return "y" 550 551 return "n" 552 553def dt_node_has_prop(kconf, _, path, prop): 554 """ 555 This function takes a 'path' and looks for an EDT node at that path. If it 556 finds an EDT node, it will look to see if that node has a property 557 by the name of 'prop'. If the 'prop' exists it will return "y" otherwise 558 it returns "n". 559 """ 560 if doc_mode or edt is None: 561 return "n" 562 563 return _dt_node_has_prop_generic(edt.get_node, path, prop) 564 565def dt_nodelabel_has_prop(kconf, _, label, prop): 566 """ 567 This function takes a 'label' and looks for an EDT node with that label. 568 If it finds an EDT node, it will look to see if that node has a property 569 by the name of 'prop'. If the 'prop' exists it will return "y" otherwise 570 it returns "n". 571 """ 572 if doc_mode or edt is None: 573 return "n" 574 575 return _dt_node_has_prop_generic(edt.label2node.get, label, prop) 576 577def dt_node_int_prop(kconf, name, path, prop, unit=None): 578 """ 579 This function takes a 'path' and property name ('prop') looks for an EDT 580 node at that path. If it finds an EDT node, it will look to see if that 581 node has a property called 'prop' and if that 'prop' is an integer type 582 will return the value of the property 'prop' as either a string int or 583 string hex value, if not we return 0. 584 585 The function will divide the value based on 'unit': 586 None No division 587 'k' or 'K' divide by 1024 (1 << 10) 588 'm' or 'M' divide by 1,048,576 (1 << 20) 589 'g' or 'G' divide by 1,073,741,824 (1 << 30) 590 'kb' or 'Kb' divide by 8192 (1 << 13) 591 'mb' or 'Mb' divide by 8,388,608 (1 << 23) 592 'gb' or 'Gb' divide by 8,589,934,592 (1 << 33) 593 """ 594 if doc_mode or edt is None: 595 return "0" 596 597 try: 598 node = edt.get_node(path) 599 except edtlib.EDTError: 600 return "0" 601 602 if name == "dt_node_int_prop_int": 603 return str(_node_int_prop(node, prop, unit)) 604 if name == "dt_node_int_prop_hex": 605 return hex(_node_int_prop(node, prop, unit)) 606 607 608def dt_node_array_prop(kconf, name, path, prop, index, unit=None): 609 """ 610 This function takes a 'path', property name ('prop') and index ('index') 611 and looks for an EDT node at that path. If it finds an EDT node, it will 612 look to see if that node has a property called 'prop' and if that 'prop' 613 is an array type will return the value of the property 'prop' at the given 614 'index' as either a string int or string hex value. If not found we return 0. 615 616 The function will divide the value based on 'unit': 617 None No division 618 'k' or 'K' divide by 1024 (1 << 10) 619 'm' or 'M' divide by 1,048,576 (1 << 20) 620 'g' or 'G' divide by 1,073,741,824 (1 << 30) 621 """ 622 if doc_mode or edt is None: 623 return "0" 624 625 try: 626 node = edt.get_node(path) 627 except edtlib.EDTError: 628 return "0" 629 if name == "dt_node_array_prop_int": 630 return str(_node_array_prop(node, prop, index, unit)) 631 if name == "dt_node_array_prop_hex": 632 return hex(_node_array_prop(node, prop, index, unit)) 633 634 635def dt_node_ph_array_prop(kconf, name, path, prop, index, cell, unit=None): 636 """ 637 This function takes a 'path', property name ('prop'), index ('index') and 638 a cell ('cell') and looks for an EDT node at that path. 639 If it finds an EDT node, it will look to see if that node has a property 640 called 'prop' and if that 'prop' is an phandle-array type. 641 Then it will check if that phandle array has a cell matching the given index 642 and ten return the value of the cell named 'cell' in this array index as 643 either a string int or string hex value. If not found we return 0. 644 645 The function will divide the value based on 'unit': 646 None No division 647 'k' or 'K' divide by 1024 (1 << 10) 648 'm' or 'M' divide by 1,048,576 (1 << 20) 649 'g' or 'G' divide by 1,073,741,824 (1 << 30) 650 """ 651 if doc_mode or edt is None: 652 return "0" 653 654 try: 655 node = edt.get_node(path) 656 except edtlib.EDTError: 657 return "0" 658 if name == "dt_node_ph_array_prop_int": 659 return str(_node_ph_array_prop(node, prop, index, cell, unit)) 660 if name == "dt_node_ph_array_prop_hex": 661 return hex(_node_ph_array_prop(node, prop, index, cell, unit)) 662 663def dt_node_ph_prop_path(kconf, name, path, prop): 664 """ 665 This function takes a 'path' and a property name ('prop') and 666 looks for an EDT node at that path. If it finds an EDT node, 667 it will look to see if that node has a property called 'prop' 668 and if that 'prop' is an phandle type. Then it will return the 669 path to the pointed-to node, or an empty string if there is 670 no such node. 671 """ 672 if doc_mode or edt is None: 673 return "" 674 675 try: 676 node = edt.get_node(path) 677 except edtlib.EDTError: 678 return "" 679 680 if prop not in node.props: 681 return "" 682 if node.props[prop].type != "phandle": 683 return "" 684 685 phandle = node.props[prop].val 686 687 return phandle.path if phandle else "" 688 689def dt_node_str_prop_equals(kconf, _, path, prop, val): 690 """ 691 This function takes a 'path' and property name ('prop') looks for an EDT 692 node at that path. If it finds an EDT node, it will look to see if that 693 node has a property 'prop' of type string. If that 'prop' is equal to 'val' 694 it will return "y" otherwise return "n". 695 """ 696 697 if doc_mode or edt is None: 698 return "n" 699 700 try: 701 node = edt.get_node(path) 702 except edtlib.EDTError: 703 return "n" 704 705 if prop not in node.props: 706 return "n" 707 708 if node.props[prop].type != "string": 709 return "n" 710 711 if node.props[prop].val == val: 712 return "y" 713 714 return "n" 715 716 717def dt_has_compat(kconf, _, compat): 718 """ 719 This function takes a 'compat' and returns "y" if any compatible node 720 can be found in the EDT, otherwise it returns "n". 721 """ 722 if doc_mode or edt is None: 723 return "n" 724 725 return "y" if compat in edt.compat2nodes else "n" 726 727 728def dt_compat_enabled(kconf, _, compat): 729 """ 730 This function takes a 'compat' and returns "y" if we find a status "okay" 731 compatible node in the EDT otherwise we return "n" 732 """ 733 if doc_mode or edt is None: 734 return "n" 735 736 return "y" if compat in edt.compat2okay else "n" 737 738 739def dt_compat_on_bus(kconf, _, compat, bus): 740 """ 741 This function takes a 'compat' and returns "y" if we find an enabled 742 compatible node in the EDT which is on bus 'bus'. It returns "n" otherwise. 743 """ 744 if doc_mode or edt is None: 745 return "n" 746 747 if compat in edt.compat2okay: 748 for node in edt.compat2okay[compat]: 749 if node.on_buses is not None and bus in node.on_buses: 750 return "y" 751 752 return "n" 753 754def dt_compat_any_has_prop(kconf, _, compat, prop, value=None): 755 """ 756 This function takes a 'compat', a 'prop', and a 'value'. 757 If value=None, the function returns "y" if any 758 enabled node with compatible 'compat' also has a valid property 'prop'. 759 If value is given, the function returns "y" if any enabled node with compatible 'compat' 760 also has a valid property 'prop' with value 'value'. 761 It returns "n" otherwise. 762 """ 763 if doc_mode or edt is None: 764 return "n" 765 766 if compat in edt.compat2okay: 767 for node in edt.compat2okay[compat]: 768 if prop in node.props: 769 if value is None: 770 return "y" 771 elif str(node.props[prop].val) == value: 772 return "y" 773 return "n" 774 775def dt_compat_any_not_has_prop(kconf, _, compat, prop): 776 """ 777 This function takes a 'compat', and a 'prop'. 778 The function returns "y" if any enabled node with compatible 'compat' 779 does NOT contain the property 'prop'. 780 It returns "n" otherwise. 781 """ 782 if doc_mode or edt is None: 783 return "n" 784 785 if compat in edt.compat2okay: 786 for node in edt.compat2okay[compat]: 787 if prop not in node.props: 788 return "y" 789 790 return "n" 791 792def dt_nodelabel_has_compat(kconf, _, label, compat): 793 """ 794 This function takes a 'label' and looks for an EDT node with that label. 795 If it finds such node, it returns "y" if this node is compatible with 796 the provided 'compat'. Otherwise, it return "n" . 797 """ 798 if doc_mode or edt is None: 799 return "n" 800 801 node = edt.label2node.get(label) 802 803 if node and compat in node.compats: 804 return "y" 805 806 return "n" 807 808def dt_node_has_compat(kconf, _, path, compat): 809 """ 810 This function takes a 'path' and looks for an EDT node at that path. If it 811 finds an EDT node, it returns "y" if this node is compatible with 812 the provided 'compat'. Otherwise, it return "n" . 813 """ 814 815 if doc_mode or edt is None: 816 return "n" 817 818 try: 819 node = edt.get_node(path) 820 except edtlib.EDTError: 821 return "n" 822 823 if node and compat in node.compats: 824 return "y" 825 826 return "n" 827 828def dt_nodelabel_enabled_with_compat(kconf, _, label, compat): 829 """ 830 This function takes a 'label' and returns "y" if an enabled node with 831 such label can be found in the EDT and that node is compatible with the 832 provided 'compat', otherwise it returns "n". 833 """ 834 if doc_mode or edt is None: 835 return "n" 836 837 if compat in edt.compat2okay: 838 for node in edt.compat2okay[compat]: 839 if label in node.labels: 840 return "y" 841 842 return "n" 843 844 845def dt_nodelabel_array_prop_has_val(kconf, _, label, prop, val): 846 """ 847 This function looks for a node with node label 'label'. 848 If the node exists, it checks if the node node has a property 849 'prop' with type "array". If so, and the property contains 850 an element equal to the integer 'val', it returns "y". 851 Otherwise, it returns "n". 852 """ 853 if doc_mode or edt is None: 854 return "n" 855 856 node = edt.label2node.get(label) 857 858 if not node or (prop not in node.props) or (node.props[prop].type != "array"): 859 return "n" 860 else: 861 return "y" if int(val, base=0) in node.props[prop].val else "n" 862 863 864def dt_nodelabel_path(kconf, _, label): 865 """ 866 This function takes a node label (not a label property) and 867 returns the path to the node which has that label, or an empty 868 string if there is no such node. 869 """ 870 if doc_mode or edt is None: 871 return "" 872 873 node = edt.label2node.get(label) 874 875 return node.path if node else "" 876 877def dt_node_parent(kconf, _, path): 878 """ 879 This function takes a 'path' and looks for an EDT node at that path. If it 880 finds an EDT node, it will look for the parent of that node. If the parent 881 exists, it will return the path to that parent. Otherwise, an empty string 882 will be returned. 883 """ 884 if doc_mode or edt is None: 885 return "" 886 887 try: 888 node = edt.get_node(path) 889 except edtlib.EDTError: 890 return "" 891 892 if node is None: 893 return "" 894 895 return node.parent.path if node.parent else "" 896 897def dt_gpio_hogs_enabled(kconf, _): 898 """ 899 Return "y" if any GPIO hog node is enabled. Otherwise, return "n". 900 """ 901 if doc_mode or edt is None: 902 return "n" 903 904 for node in edt.nodes: 905 if node.gpio_hogs and node.status == "okay": 906 return "y" 907 908 return "n" 909 910 911def normalize_upper(kconf, _, string): 912 """ 913 Normalize the string, so that the string only contains alpha-numeric 914 characters or underscores. All non-alpha-numeric characters are replaced 915 with an underscore, '_'. 916 When string has been normalized it will be converted into upper case. 917 """ 918 return re.sub(r'[^a-zA-Z0-9_]', '_', string).upper() 919 920 921def shields_list_contains(kconf, _, shield): 922 """ 923 Return "n" if cmake environment variable 'SHIELD_AS_LIST' doesn't exist. 924 Return "y" if 'shield' is present list obtained after 'SHIELD_AS_LIST' 925 has been split using ";" as a separator and "n" otherwise. 926 """ 927 try: 928 list = os.environ['SHIELD_AS_LIST'] 929 except KeyError: 930 return "n" 931 932 return "y" if shield in list.split(";") else "n" 933 934 935def substring(kconf, _, string, start, stop=None): 936 """ 937 Extracts a portion of the string, removing characters from the front, back or both. 938 """ 939 if stop is not None: 940 return string[int(start):int(stop)] 941 else: 942 return string[int(start):] 943 944def arith(kconf, name, *args): 945 """ 946 The arithmetic operations on integers. 947 If three or more arguments are given, it returns the result of performing 948 the operation on the first two arguments and operates the same operation as 949 the result and the following argument. 950 For interoperability with inc and dec, 951 if there is only one argument, it will be split with a comma and processed 952 as a sequence of numbers. 953 954 Examples in Kconfig: 955 956 $(add, 10, 3) # -> 13 957 $(add, 10, 3, 2) # -> 15 958 $(sub, 10, 3) # -> 7 959 $(sub, 10, 3, 2) # -> 5 960 $(mul, 10, 3) # -> 30 961 $(mul, 10, 3, 2) # -> 60 962 $(div, 10, 3) # -> 3 963 $(div, 10, 3, 2) # -> 1 964 $(mod, 10, 3) # -> 1 965 $(mod, 10, 3, 2) # -> 1 966 $(inc, 1) # -> 2 967 $(inc, 1, 1) # -> "2,2" 968 $(inc, $(inc, 1, 1)) # -> "3,3" 969 $(dec, 1) # -> 0 970 $(dec, 1, 1) # -> "0,0" 971 $(dec, $(dec, 1, 1)) # -> "-1,-1" 972 $(add, $(inc, 1, 1)) # -> 4 973 $(div, $(dec, 1, 1)) # Error (0 div 0) 974 """ 975 976 intarray = map(int, args if len(args) > 1 else args[0].split(",")) 977 978 if name == "add": 979 return str(int(functools.reduce(operator.add, intarray))) 980 elif name == "sub": 981 return str(int(functools.reduce(operator.sub, intarray))) 982 elif name == "mul": 983 return str(int(functools.reduce(operator.mul, intarray))) 984 elif name == "div": 985 return str(int(functools.reduce(operator.truediv, intarray))) 986 elif name == "mod": 987 return str(int(functools.reduce(operator.mod, intarray))) 988 elif name == "max": 989 return str(int(functools.reduce(max, intarray))) 990 elif name == "min": 991 return str(int(functools.reduce(min, intarray))) 992 else: 993 assert False 994 995 996def inc_dec(kconf, name, *args): 997 """ 998 Calculate the increment and the decrement of integer sequence. 999 Returns a string that concatenates numbers with a comma as a separator. 1000 """ 1001 1002 intarray = map(int, args if len(args) > 1 else args[0].split(",")) 1003 1004 if name == "inc": 1005 return ",".join(map(lambda a: str(a + 1), intarray)) 1006 elif name == "dec": 1007 return ",".join(map(lambda a: str(a - 1), intarray)) 1008 else: 1009 assert False 1010 1011 1012# Keys in this dict are the function names as they appear 1013# in Kconfig files. The values are tuples in this form: 1014# 1015# (python_function, minimum_number_of_args, maximum_number_of_args) 1016# 1017# Each python function is given a kconf object and its name in the 1018# Kconfig file, followed by arguments from the Kconfig file. 1019# 1020# See the kconfiglib documentation for more details. 1021functions = { 1022 "dt_has_compat": (dt_has_compat, 1, 1), 1023 "dt_compat_enabled": (dt_compat_enabled, 1, 1), 1024 "dt_compat_on_bus": (dt_compat_on_bus, 2, 2), 1025 "dt_compat_any_has_prop": (dt_compat_any_has_prop, 2, 3), 1026 "dt_compat_any_not_has_prop": (dt_compat_any_not_has_prop, 2, 2), 1027 "dt_chosen_label": (dt_chosen_label, 1, 1), 1028 "dt_chosen_enabled": (dt_chosen_enabled, 1, 1), 1029 "dt_chosen_path": (dt_chosen_path, 1, 1), 1030 "dt_chosen_has_compat": (dt_chosen_has_compat, 2, 2), 1031 "dt_path_enabled": (dt_node_enabled, 1, 1), 1032 "dt_alias_enabled": (dt_node_enabled, 1, 1), 1033 "dt_nodelabel_enabled": (dt_nodelabel_enabled, 1, 1), 1034 "dt_nodelabel_enabled_with_compat": (dt_nodelabel_enabled_with_compat, 2, 2), 1035 "dt_chosen_reg_addr_int": (dt_chosen_reg, 1, 3), 1036 "dt_chosen_reg_addr_hex": (dt_chosen_reg, 1, 3), 1037 "dt_chosen_reg_size_int": (dt_chosen_reg, 1, 3), 1038 "dt_chosen_reg_size_hex": (dt_chosen_reg, 1, 3), 1039 "dt_node_reg_addr_int": (dt_node_reg, 1, 3), 1040 "dt_node_reg_addr_hex": (dt_node_reg, 1, 3), 1041 "dt_node_reg_size_int": (dt_node_reg, 1, 3), 1042 "dt_node_reg_size_hex": (dt_node_reg, 1, 3), 1043 "dt_nodelabel_reg_addr_int": (dt_nodelabel_reg, 1, 3), 1044 "dt_nodelabel_reg_addr_hex": (dt_nodelabel_reg, 1, 3), 1045 "dt_nodelabel_reg_size_int": (dt_nodelabel_reg, 1, 3), 1046 "dt_nodelabel_reg_size_hex": (dt_nodelabel_reg, 1, 3), 1047 "dt_node_bool_prop": (dt_node_bool_prop, 2, 2), 1048 "dt_nodelabel_bool_prop": (dt_nodelabel_bool_prop, 2, 2), 1049 "dt_chosen_bool_prop": (dt_chosen_bool_prop, 2, 2), 1050 "dt_node_has_prop": (dt_node_has_prop, 2, 2), 1051 "dt_nodelabel_has_prop": (dt_nodelabel_has_prop, 2, 2), 1052 "dt_node_int_prop_int": (dt_node_int_prop, 2, 3), 1053 "dt_node_int_prop_hex": (dt_node_int_prop, 2, 3), 1054 "dt_node_array_prop_int": (dt_node_array_prop, 3, 4), 1055 "dt_node_array_prop_hex": (dt_node_array_prop, 3, 4), 1056 "dt_node_ph_array_prop_int": (dt_node_ph_array_prop, 4, 5), 1057 "dt_node_ph_array_prop_hex": (dt_node_ph_array_prop, 4, 5), 1058 "dt_node_ph_prop_path": (dt_node_ph_prop_path, 2, 2), 1059 "dt_node_str_prop_equals": (dt_node_str_prop_equals, 3, 3), 1060 "dt_nodelabel_has_compat": (dt_nodelabel_has_compat, 2, 2), 1061 "dt_node_has_compat": (dt_node_has_compat, 2, 2), 1062 "dt_nodelabel_path": (dt_nodelabel_path, 1, 1), 1063 "dt_node_parent": (dt_node_parent, 1, 1), 1064 "dt_nodelabel_array_prop_has_val": (dt_nodelabel_array_prop_has_val, 3, 3), 1065 "dt_gpio_hogs_enabled": (dt_gpio_hogs_enabled, 0, 0), 1066 "dt_chosen_partition_addr_int": (dt_chosen_partition_addr, 1, 3), 1067 "dt_chosen_partition_addr_hex": (dt_chosen_partition_addr, 1, 3), 1068 "normalize_upper": (normalize_upper, 1, 1), 1069 "shields_list_contains": (shields_list_contains, 1, 1), 1070 "substring": (substring, 2, 3), 1071 "add": (arith, 1, 255), 1072 "sub": (arith, 1, 255), 1073 "mul": (arith, 1, 255), 1074 "div": (arith, 1, 255), 1075 "mod": (arith, 1, 255), 1076 "max": (arith, 1, 255), 1077 "min": (arith, 1, 255), 1078 "inc": (inc_dec, 1, 255), 1079 "dec": (inc_dec, 1, 255), 1080} 1081