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_chosen_bool_prop(kconf, _, chosen, prop): 536 """ 537 This function takes a /chosen node property named 'chosen', and 538 looks for the chosen node. If that node exists and has a boolean 539 property 'prop', it returns "y". Otherwise, it returns "n". 540 """ 541 if doc_mode or edt is None: 542 return "n" 543 544 return _dt_node_bool_prop_generic(edt.chosen_node, chosen, prop) 545 546def _dt_node_has_prop_generic(node_search_function, search_arg, prop): 547 """ 548 This function takes the 'node_search_function' and uses it to search for 549 a node with 'search_arg' and if node exists, then checks if 'prop' 550 exists inside the node and returns "y". Otherwise, it returns "n". 551 """ 552 try: 553 node = node_search_function(search_arg) 554 except edtlib.EDTError: 555 return "n" 556 557 if node is None: 558 return "n" 559 560 if prop in node.props: 561 return "y" 562 563 return "n" 564 565def dt_node_has_prop(kconf, _, path, prop): 566 """ 567 This function takes a 'path' and looks for an EDT node at that path. If it 568 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.get_node, path, prop) 576 577def dt_nodelabel_has_prop(kconf, _, label, prop): 578 """ 579 This function takes a 'label' and looks for an EDT node with that label. 580 If it finds an EDT node, it will look to see if that node has a property 581 by the name of 'prop'. If the 'prop' exists it will return "y" otherwise 582 it returns "n". 583 """ 584 if doc_mode or edt is None: 585 return "n" 586 587 return _dt_node_has_prop_generic(edt.label2node.get, label, prop) 588 589def dt_node_int_prop(kconf, name, path, prop, unit=None): 590 """ 591 This function takes a 'path' and property name ('prop') looks for an EDT 592 node at that path. If it finds an EDT node, it will look to see if that 593 node has a property called 'prop' and if that 'prop' is an integer type 594 will return the value of the property 'prop' as either a string int or 595 string hex value, if not we return 0. 596 597 The function will divide the value based on 'unit': 598 None No division 599 'k' or 'K' divide by 1024 (1 << 10) 600 'm' or 'M' divide by 1,048,576 (1 << 20) 601 'g' or 'G' divide by 1,073,741,824 (1 << 30) 602 'kb' or 'Kb' divide by 8192 (1 << 13) 603 'mb' or 'Mb' divide by 8,388,608 (1 << 23) 604 'gb' or 'Gb' divide by 8,589,934,592 (1 << 33) 605 """ 606 if doc_mode or edt is None: 607 return "0" 608 609 try: 610 node = edt.get_node(path) 611 except edtlib.EDTError: 612 return "0" 613 614 if name == "dt_node_int_prop_int": 615 return str(_node_int_prop(node, prop, unit)) 616 if name == "dt_node_int_prop_hex": 617 return hex(_node_int_prop(node, prop, unit)) 618 619 620def dt_node_array_prop(kconf, name, path, prop, index, unit=None): 621 """ 622 This function takes a 'path', property name ('prop') and index ('index') 623 and looks for an EDT node at that path. If it finds an EDT node, it will 624 look to see if that node has a property called 'prop' and if that 'prop' 625 is an array type will return the value of the property 'prop' at the given 626 'index' as either a string int or string hex value. If not found we return 0. 627 628 The function will divide the value based on 'unit': 629 None No division 630 'k' or 'K' divide by 1024 (1 << 10) 631 'm' or 'M' divide by 1,048,576 (1 << 20) 632 'g' or 'G' divide by 1,073,741,824 (1 << 30) 633 """ 634 if doc_mode or edt is None: 635 return "0" 636 637 try: 638 node = edt.get_node(path) 639 except edtlib.EDTError: 640 return "0" 641 if name == "dt_node_array_prop_int": 642 return str(_node_array_prop(node, prop, index, unit)) 643 if name == "dt_node_array_prop_hex": 644 return hex(_node_array_prop(node, prop, index, unit)) 645 646 647def dt_node_ph_array_prop(kconf, name, path, prop, index, cell, unit=None): 648 """ 649 This function takes a 'path', property name ('prop'), index ('index') and 650 a cell ('cell') and looks for an EDT node at that path. 651 If it finds an EDT node, it will look to see if that node has a property 652 called 'prop' and if that 'prop' is an phandle-array type. 653 Then it will check if that phandle array has a cell matching the given index 654 and ten return the value of the cell named 'cell' in this array index as 655 either a string int or string hex value. If not found we return 0. 656 657 The function will divide the value based on 'unit': 658 None No division 659 'k' or 'K' divide by 1024 (1 << 10) 660 'm' or 'M' divide by 1,048,576 (1 << 20) 661 'g' or 'G' divide by 1,073,741,824 (1 << 30) 662 """ 663 if doc_mode or edt is None: 664 return "0" 665 666 try: 667 node = edt.get_node(path) 668 except edtlib.EDTError: 669 return "0" 670 if name == "dt_node_ph_array_prop_int": 671 return str(_node_ph_array_prop(node, prop, index, cell, unit)) 672 if name == "dt_node_ph_array_prop_hex": 673 return hex(_node_ph_array_prop(node, prop, index, cell, unit)) 674 675def dt_node_ph_prop_path(kconf, name, path, prop): 676 """ 677 This function takes a 'path' and a property name ('prop') and 678 looks for an EDT node at that path. If it finds an EDT node, 679 it will look to see if that node has a property called 'prop' 680 and if that 'prop' is an phandle type. Then it will return the 681 path to the pointed-to node, or an empty string if there is 682 no such node. 683 """ 684 if doc_mode or edt is None: 685 return "" 686 687 try: 688 node = edt.get_node(path) 689 except edtlib.EDTError: 690 return "" 691 692 if prop not in node.props: 693 return "" 694 if node.props[prop].type != "phandle": 695 return "" 696 697 phandle = node.props[prop].val 698 699 return phandle.path if phandle else "" 700 701def dt_node_str_prop_equals(kconf, _, path, prop, val): 702 """ 703 This function takes a 'path' and property name ('prop') looks for an EDT 704 node at that path. If it finds an EDT node, it will look to see if that 705 node has a property 'prop' of type string. If that 'prop' is equal to 'val' 706 it will return "y" otherwise return "n". 707 """ 708 709 if doc_mode or edt is None: 710 return "n" 711 712 try: 713 node = edt.get_node(path) 714 except edtlib.EDTError: 715 return "n" 716 717 if prop not in node.props: 718 return "n" 719 720 if node.props[prop].type != "string": 721 return "n" 722 723 if node.props[prop].val == val: 724 return "y" 725 726 return "n" 727 728 729def dt_has_compat(kconf, _, compat): 730 """ 731 This function takes a 'compat' and returns "y" if any compatible node 732 can be found in the EDT, otherwise it returns "n". 733 """ 734 if doc_mode or edt is None: 735 return "n" 736 737 return "y" if compat in edt.compat2nodes else "n" 738 739 740def dt_compat_enabled(kconf, _, compat): 741 """ 742 This function takes a 'compat' and returns "y" if we find a status "okay" 743 compatible node in the EDT otherwise we return "n" 744 """ 745 if doc_mode or edt is None: 746 return "n" 747 748 return "y" if compat in edt.compat2okay else "n" 749 750 751def dt_compat_on_bus(kconf, _, compat, bus): 752 """ 753 This function takes a 'compat' and returns "y" if we find an enabled 754 compatible node in the EDT which is on bus 'bus'. It returns "n" otherwise. 755 """ 756 if doc_mode or edt is None: 757 return "n" 758 759 if compat in edt.compat2okay: 760 for node in edt.compat2okay[compat]: 761 if node.on_buses is not None and bus in node.on_buses: 762 return "y" 763 764 return "n" 765 766def dt_compat_any_has_prop(kconf, _, compat, prop, value=None): 767 """ 768 This function takes a 'compat', a 'prop', and a 'value'. 769 If value=None, the function returns "y" if any 770 enabled node with compatible 'compat' also has a valid property 'prop'. 771 If value is given, the function returns "y" if any enabled node with compatible 'compat' 772 also has a valid property 'prop' with value 'value'. 773 It returns "n" otherwise. 774 """ 775 if doc_mode or edt is None: 776 return "n" 777 778 if compat in edt.compat2okay: 779 for node in edt.compat2okay[compat]: 780 if prop in node.props: 781 if value is None: 782 return "y" 783 elif str(node.props[prop].val) == value: 784 return "y" 785 return "n" 786 787def dt_compat_any_not_has_prop(kconf, _, compat, prop): 788 """ 789 This function takes a 'compat', and a 'prop'. 790 The function returns "y" if any enabled node with compatible 'compat' 791 does NOT contain the property 'prop'. 792 It returns "n" otherwise. 793 """ 794 if doc_mode or edt is None: 795 return "n" 796 797 if compat in edt.compat2okay: 798 for node in edt.compat2okay[compat]: 799 if prop not in node.props: 800 return "y" 801 802 return "n" 803 804def dt_nodelabel_has_compat(kconf, _, label, compat): 805 """ 806 This function takes a 'label' and looks for an EDT node with that label. 807 If it finds such node, it returns "y" if this node is compatible with 808 the provided 'compat'. Otherwise, it return "n" . 809 """ 810 if doc_mode or edt is None: 811 return "n" 812 813 node = edt.label2node.get(label) 814 815 if node and compat in node.compats: 816 return "y" 817 818 return "n" 819 820def dt_node_has_compat(kconf, _, path, compat): 821 """ 822 This function takes a 'path' and looks for an EDT node at that path. If it 823 finds an EDT node, it returns "y" if this node is compatible with 824 the provided 'compat'. Otherwise, it return "n" . 825 """ 826 827 if doc_mode or edt is None: 828 return "n" 829 830 try: 831 node = edt.get_node(path) 832 except edtlib.EDTError: 833 return "n" 834 835 if node and compat in node.compats: 836 return "y" 837 838 return "n" 839 840def dt_nodelabel_enabled_with_compat(kconf, _, label, compat): 841 """ 842 This function takes a 'label' and returns "y" if an enabled node with 843 such label can be found in the EDT and that node is compatible with the 844 provided 'compat', otherwise it returns "n". 845 """ 846 if doc_mode or edt is None: 847 return "n" 848 849 if compat in edt.compat2okay: 850 for node in edt.compat2okay[compat]: 851 if label in node.labels: 852 return "y" 853 854 return "n" 855 856 857def dt_nodelabel_array_prop_has_val(kconf, _, label, prop, val): 858 """ 859 This function looks for a node with node label 'label'. 860 If the node exists, it checks if the node node has a property 861 'prop' with type "array". If so, and the property contains 862 an element equal to the integer 'val', it returns "y". 863 Otherwise, it returns "n". 864 """ 865 if doc_mode or edt is None: 866 return "n" 867 868 node = edt.label2node.get(label) 869 870 if not node or (prop not in node.props) or (node.props[prop].type != "array"): 871 return "n" 872 else: 873 return "y" if int(val, base=0) in node.props[prop].val else "n" 874 875 876def dt_nodelabel_path(kconf, _, label): 877 """ 878 This function takes a node label (not a label property) and 879 returns the path to the node which has that label, or an empty 880 string if there is no such node. 881 """ 882 if doc_mode or edt is None: 883 return "" 884 885 node = edt.label2node.get(label) 886 887 return node.path if node else "" 888 889def dt_node_parent(kconf, _, path): 890 """ 891 This function takes a 'path' and looks for an EDT node at that path. If it 892 finds an EDT node, it will look for the parent of that node. If the parent 893 exists, it will return the path to that parent. Otherwise, an empty string 894 will be returned. 895 """ 896 if doc_mode or edt is None: 897 return "" 898 899 try: 900 node = edt.get_node(path) 901 except edtlib.EDTError: 902 return "" 903 904 if node is None: 905 return "" 906 907 return node.parent.path if node.parent else "" 908 909def dt_gpio_hogs_enabled(kconf, _): 910 """ 911 Return "y" if any GPIO hog node is enabled. Otherwise, return "n". 912 """ 913 if doc_mode or edt is None: 914 return "n" 915 916 for node in edt.nodes: 917 if node.gpio_hogs and node.status == "okay": 918 return "y" 919 920 return "n" 921 922 923def normalize_upper(kconf, _, string): 924 """ 925 Normalize the string, so that the string only contains alpha-numeric 926 characters or underscores. All non-alpha-numeric characters are replaced 927 with an underscore, '_'. 928 When string has been normalized it will be converted into upper case. 929 """ 930 return re.sub(r'[^a-zA-Z0-9_]', '_', string).upper() 931 932 933def shields_list_contains(kconf, _, shield): 934 """ 935 Return "n" if cmake environment variable 'SHIELD_AS_LIST' doesn't exist. 936 Return "y" if 'shield' is present list obtained after 'SHIELD_AS_LIST' 937 has been split using ";" as a separator and "n" otherwise. 938 """ 939 try: 940 list = os.environ['SHIELD_AS_LIST'] 941 except KeyError: 942 return "n" 943 944 return "y" if shield in list.split(";") else "n" 945 946 947def substring(kconf, _, string, start, stop=None): 948 """ 949 Extracts a portion of the string, removing characters from the front, back or both. 950 """ 951 if stop is not None: 952 return string[int(start):int(stop)] 953 else: 954 return string[int(start):] 955 956def arith(kconf, name, *args): 957 """ 958 The arithmetic operations on integers. 959 If three or more arguments are given, it returns the result of performing 960 the operation on the first two arguments and operates the same operation as 961 the result and the following argument. 962 For interoperability with inc and dec, 963 if there is only one argument, it will be split with a comma and processed 964 as a sequence of numbers. 965 966 Examples in Kconfig: 967 968 $(add, 10, 3) # -> 13 969 $(add, 10, 3, 2) # -> 15 970 $(sub, 10, 3) # -> 7 971 $(sub, 10, 3, 2) # -> 5 972 $(mul, 10, 3) # -> 30 973 $(mul, 10, 3, 2) # -> 60 974 $(div, 10, 3) # -> 3 975 $(div, 10, 3, 2) # -> 1 976 $(mod, 10, 3) # -> 1 977 $(mod, 10, 3, 2) # -> 1 978 $(inc, 1) # -> 2 979 $(inc, 1, 1) # -> "2,2" 980 $(inc, $(inc, 1, 1)) # -> "3,3" 981 $(dec, 1) # -> 0 982 $(dec, 1, 1) # -> "0,0" 983 $(dec, $(dec, 1, 1)) # -> "-1,-1" 984 $(add, $(inc, 1, 1)) # -> 4 985 $(div, $(dec, 1, 1)) # Error (0 div 0) 986 """ 987 988 intarray = map(int, args if len(args) > 1 else args[0].split(",")) 989 990 if name == "add": 991 return str(int(functools.reduce(operator.add, intarray))) 992 elif name == "sub": 993 return str(int(functools.reduce(operator.sub, intarray))) 994 elif name == "mul": 995 return str(int(functools.reduce(operator.mul, intarray))) 996 elif name == "div": 997 return str(int(functools.reduce(operator.truediv, intarray))) 998 elif name == "mod": 999 return str(int(functools.reduce(operator.mod, intarray))) 1000 elif name == "max": 1001 return str(int(functools.reduce(max, intarray))) 1002 elif name == "min": 1003 return str(int(functools.reduce(min, intarray))) 1004 else: 1005 assert False 1006 1007 1008def inc_dec(kconf, name, *args): 1009 """ 1010 Calculate the increment and the decrement of integer sequence. 1011 Returns a string that concatenates numbers with a comma as a separator. 1012 """ 1013 1014 intarray = map(int, args if len(args) > 1 else args[0].split(",")) 1015 1016 if name == "inc": 1017 return ",".join(map(lambda a: str(a + 1), intarray)) 1018 elif name == "dec": 1019 return ",".join(map(lambda a: str(a - 1), intarray)) 1020 else: 1021 assert False 1022 1023 1024# Keys in this dict are the function names as they appear 1025# in Kconfig files. The values are tuples in this form: 1026# 1027# (python_function, minimum_number_of_args, maximum_number_of_args) 1028# 1029# Each python function is given a kconf object and its name in the 1030# Kconfig file, followed by arguments from the Kconfig file. 1031# 1032# See the kconfiglib documentation for more details. 1033functions = { 1034 "dt_has_compat": (dt_has_compat, 1, 1), 1035 "dt_compat_enabled": (dt_compat_enabled, 1, 1), 1036 "dt_compat_on_bus": (dt_compat_on_bus, 2, 2), 1037 "dt_compat_any_has_prop": (dt_compat_any_has_prop, 2, 3), 1038 "dt_compat_any_not_has_prop": (dt_compat_any_not_has_prop, 2, 2), 1039 "dt_chosen_label": (dt_chosen_label, 1, 1), 1040 "dt_chosen_enabled": (dt_chosen_enabled, 1, 1), 1041 "dt_chosen_path": (dt_chosen_path, 1, 1), 1042 "dt_chosen_has_compat": (dt_chosen_has_compat, 2, 2), 1043 "dt_path_enabled": (dt_node_enabled, 1, 1), 1044 "dt_alias_enabled": (dt_node_enabled, 1, 1), 1045 "dt_nodelabel_exists": (dt_nodelabel_exists, 1, 1), 1046 "dt_nodelabel_enabled": (dt_nodelabel_enabled, 1, 1), 1047 "dt_nodelabel_enabled_with_compat": (dt_nodelabel_enabled_with_compat, 2, 2), 1048 "dt_chosen_reg_addr_int": (dt_chosen_reg, 1, 3), 1049 "dt_chosen_reg_addr_hex": (dt_chosen_reg, 1, 3), 1050 "dt_chosen_reg_size_int": (dt_chosen_reg, 1, 3), 1051 "dt_chosen_reg_size_hex": (dt_chosen_reg, 1, 3), 1052 "dt_node_reg_addr_int": (dt_node_reg, 1, 3), 1053 "dt_node_reg_addr_hex": (dt_node_reg, 1, 3), 1054 "dt_node_reg_size_int": (dt_node_reg, 1, 3), 1055 "dt_node_reg_size_hex": (dt_node_reg, 1, 3), 1056 "dt_nodelabel_reg_addr_int": (dt_nodelabel_reg, 1, 3), 1057 "dt_nodelabel_reg_addr_hex": (dt_nodelabel_reg, 1, 3), 1058 "dt_nodelabel_reg_size_int": (dt_nodelabel_reg, 1, 3), 1059 "dt_nodelabel_reg_size_hex": (dt_nodelabel_reg, 1, 3), 1060 "dt_node_bool_prop": (dt_node_bool_prop, 2, 2), 1061 "dt_nodelabel_bool_prop": (dt_nodelabel_bool_prop, 2, 2), 1062 "dt_chosen_bool_prop": (dt_chosen_bool_prop, 2, 2), 1063 "dt_node_has_prop": (dt_node_has_prop, 2, 2), 1064 "dt_nodelabel_has_prop": (dt_nodelabel_has_prop, 2, 2), 1065 "dt_node_int_prop_int": (dt_node_int_prop, 2, 3), 1066 "dt_node_int_prop_hex": (dt_node_int_prop, 2, 3), 1067 "dt_node_array_prop_int": (dt_node_array_prop, 3, 4), 1068 "dt_node_array_prop_hex": (dt_node_array_prop, 3, 4), 1069 "dt_node_ph_array_prop_int": (dt_node_ph_array_prop, 4, 5), 1070 "dt_node_ph_array_prop_hex": (dt_node_ph_array_prop, 4, 5), 1071 "dt_node_ph_prop_path": (dt_node_ph_prop_path, 2, 2), 1072 "dt_node_str_prop_equals": (dt_node_str_prop_equals, 3, 3), 1073 "dt_nodelabel_has_compat": (dt_nodelabel_has_compat, 2, 2), 1074 "dt_node_has_compat": (dt_node_has_compat, 2, 2), 1075 "dt_nodelabel_path": (dt_nodelabel_path, 1, 1), 1076 "dt_node_parent": (dt_node_parent, 1, 1), 1077 "dt_nodelabel_array_prop_has_val": (dt_nodelabel_array_prop_has_val, 3, 3), 1078 "dt_gpio_hogs_enabled": (dt_gpio_hogs_enabled, 0, 0), 1079 "dt_chosen_partition_addr_int": (dt_chosen_partition_addr, 1, 3), 1080 "dt_chosen_partition_addr_hex": (dt_chosen_partition_addr, 1, 3), 1081 "normalize_upper": (normalize_upper, 1, 1), 1082 "shields_list_contains": (shields_list_contains, 1, 1), 1083 "substring": (substring, 2, 3), 1084 "add": (arith, 1, 255), 1085 "sub": (arith, 1, 255), 1086 "mul": (arith, 1, 255), 1087 "div": (arith, 1, 255), 1088 "mod": (arith, 1, 255), 1089 "max": (arith, 1, 255), 1090 "min": (arith, 1, 255), 1091 "inc": (inc_dec, 1, 255), 1092 "dec": (inc_dec, 1, 255), 1093} 1094