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