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