123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480 |
- # Copyright (c) 2018-2019 Linaro
- # Copyright (c) 2019 Nordic Semiconductor ASA
- #
- # SPDX-License-Identifier: Apache-2.0
- import os
- import pickle
- import sys
- ZEPHYR_BASE = os.environ["ZEPHYR_BASE"]
- sys.path.insert(0, os.path.join(ZEPHYR_BASE, "scripts", "dts",
- "python-devicetree", "src"))
- from devicetree import edtlib
- # Types we support
- # 'string', 'int', 'hex', 'bool'
- doc_mode = os.environ.get('KCONFIG_DOC_MODE') == "1"
- if not doc_mode:
- EDT_PICKLE = os.environ.get("EDT_PICKLE")
- # The "if" handles a missing dts.
- if EDT_PICKLE is not None and os.path.isfile(EDT_PICKLE):
- with open(EDT_PICKLE, 'rb') as f:
- edt = pickle.load(f)
- else:
- edt = None
- def _warn(kconf, msg):
- print("{}:{}: WARNING: {}".format(kconf.filename, kconf.linenr, msg))
- def _dt_units_to_scale(unit):
- if not unit:
- return 0
- if unit in {'k', 'K'}:
- return 10
- if unit in {'m', 'M'}:
- return 20
- if unit in {'g', 'G'}:
- return 30
- def dt_chosen_label(kconf, _, chosen):
- """
- This function takes a 'chosen' property and treats that property as a path
- to an EDT node. If it finds an EDT node, it will look to see if that node
- has a "label" property and return the value of that "label", if not we
- return an empty string.
- """
- if doc_mode or edt is None:
- return ""
- node = edt.chosen_node(chosen)
- if not node:
- return ""
- if "label" not in node.props:
- return ""
- return node.props["label"].val
- def dt_chosen_enabled(kconf, _, chosen):
- """
- This function returns "y" if /chosen contains a property named 'chosen'
- that points to an enabled node, and "n" otherwise
- """
- if doc_mode or edt is None:
- return "n"
- node = edt.chosen_node(chosen)
- return "y" if node and node.status == "okay" else "n"
- def dt_chosen_path(kconf, _, chosen):
- """
- This function takes a /chosen node property and returns the path
- to the node in the property value, or the empty string.
- """
- if doc_mode or edt is None:
- return "n"
- node = edt.chosen_node(chosen)
- return node.path if node else ""
- def dt_node_enabled(kconf, name, node):
- """
- This function is used to test if a node is enabled (has status
- 'okay') or not.
- The 'node' argument is a string which is either a path or an
- alias, or both, depending on 'name'.
- If 'name' is 'dt_path_enabled', 'node' is an alias or a path. If
- 'name' is 'dt_alias_enabled, 'node' is an alias.
- """
- if doc_mode or edt is None:
- return "n"
- if name == "dt_alias_enabled":
- if node.startswith("/"):
- # EDT.get_node() works with either aliases or paths. If we
- # are specifically being asked about an alias, reject paths.
- return "n"
- else:
- # Make sure this is being called appropriately.
- assert name == "dt_path_enabled"
- try:
- node = edt.get_node(node)
- except edtlib.EDTError:
- return "n"
- return "y" if node and node.status == "okay" else "n"
- def dt_nodelabel_enabled(kconf, _, label):
- """
- This function is like dt_node_enabled(), but the 'label' argument
- should be a node label, like "foo" is here:
- foo: some-node { ... };
- """
- if doc_mode or edt is None:
- return "n"
- node = edt.label2node.get(label)
- return "y" if node and node.status == "okay" else "n"
- def _node_reg_addr(node, index, unit):
- if not node:
- return 0
- if not node.regs:
- return 0
- if int(index) >= len(node.regs):
- return 0
- if node.regs[int(index)].addr is None:
- return 0
- return node.regs[int(index)].addr >> _dt_units_to_scale(unit)
- def _node_reg_size(node, index, unit):
- if not node:
- return 0
- if not node.regs:
- return 0
- if int(index) >= len(node.regs):
- return 0
- if node.regs[int(index)].size is None:
- return 0
- return node.regs[int(index)].size >> _dt_units_to_scale(unit)
- def _node_int_prop(node, prop):
- if not node:
- return 0
- if prop not in node.props:
- return 0
- if node.props[prop].type != "int":
- return 0
- return node.props[prop].val
- def _dt_chosen_reg_addr(kconf, chosen, index=0, unit=None):
- """
- This function takes a 'chosen' property and treats that property as a path
- to an EDT node. If it finds an EDT node, it will look to see if that
- nodnode has a register at the given 'index' and return the address value of
- that reg, if not we return 0.
- The function will divide the value based on 'unit':
- None No division
- 'k' or 'K' divide by 1024 (1 << 10)
- 'm' or 'M' divide by 1,048,576 (1 << 20)
- 'g' or 'G' divide by 1,073,741,824 (1 << 30)
- """
- if doc_mode or edt is None:
- return 0
- node = edt.chosen_node(chosen)
- return _node_reg_addr(node, index, unit)
- def _dt_chosen_reg_size(kconf, chosen, index=0, unit=None):
- """
- This function takes a 'chosen' property and treats that property as a path
- to an EDT node. If it finds an EDT node, it will look to see if that node
- has a register at the given 'index' and return the size value of that reg,
- if not we return 0.
- The function will divide the value based on 'unit':
- None No division
- 'k' or 'K' divide by 1024 (1 << 10)
- 'm' or 'M' divide by 1,048,576 (1 << 20)
- 'g' or 'G' divide by 1,073,741,824 (1 << 30)
- """
- if doc_mode or edt is None:
- return 0
- node = edt.chosen_node(chosen)
- return _node_reg_size(node, index, unit)
- def dt_chosen_reg(kconf, name, chosen, index=0, unit=None):
- """
- This function just routes to the proper function and converts
- the result to either a string int or string hex value.
- """
- if name == "dt_chosen_reg_size_int":
- return str(_dt_chosen_reg_size(kconf, chosen, index, unit))
- if name == "dt_chosen_reg_size_hex":
- return hex(_dt_chosen_reg_size(kconf, chosen, index, unit))
- if name == "dt_chosen_reg_addr_int":
- return str(_dt_chosen_reg_addr(kconf, chosen, index, unit))
- if name == "dt_chosen_reg_addr_hex":
- return hex(_dt_chosen_reg_addr(kconf, chosen, index, unit))
- def _dt_node_reg_addr(kconf, path, index=0, unit=None):
- """
- This function takes a 'path' and looks for an EDT node at that path. If it
- finds an EDT node, it will look to see if that node has a register at the
- given 'index' and return the address value of that reg, if not we return 0.
- The function will divide the value based on 'unit':
- None No division
- 'k' or 'K' divide by 1024 (1 << 10)
- 'm' or 'M' divide by 1,048,576 (1 << 20)
- 'g' or 'G' divide by 1,073,741,824 (1 << 30)
- """
- if doc_mode or edt is None:
- return 0
- try:
- node = edt.get_node(path)
- except edtlib.EDTError:
- return 0
- return _node_reg_addr(node, index, unit)
- def _dt_node_reg_size(kconf, path, index=0, unit=None):
- """
- This function takes a 'path' and looks for an EDT node at that path. If it
- finds an EDT node, it will look to see if that node has a register at the
- given 'index' and return the size value of that reg, if not we return 0.
- The function will divide the value based on 'unit':
- None No division
- 'k' or 'K' divide by 1024 (1 << 10)
- 'm' or 'M' divide by 1,048,576 (1 << 20)
- 'g' or 'G' divide by 1,073,741,824 (1 << 30)
- """
- if doc_mode or edt is None:
- return 0
- try:
- node = edt.get_node(path)
- except edtlib.EDTError:
- return 0
- return _node_reg_size(node, index, unit)
- def dt_node_reg(kconf, name, path, index=0, unit=None):
- """
- This function just routes to the proper function and converts
- the result to either a string int or string hex value.
- """
- if name == "dt_node_reg_size_int":
- return str(_dt_node_reg_size(kconf, path, index, unit))
- if name == "dt_node_reg_size_hex":
- return hex(_dt_node_reg_size(kconf, path, index, unit))
- if name == "dt_node_reg_addr_int":
- return str(_dt_node_reg_addr(kconf, path, index, unit))
- if name == "dt_node_reg_addr_hex":
- return hex(_dt_node_reg_addr(kconf, path, index, unit))
- def dt_node_has_bool_prop(kconf, _, path, prop):
- """
- This function takes a 'path' and looks for an EDT node at that path. If it
- finds an EDT node, it will look to see if that node has a boolean property
- by the name of 'prop'. If the 'prop' exists it will return "y" otherwise
- we return "n".
- """
- if doc_mode or edt is None:
- return "n"
- try:
- node = edt.get_node(path)
- except edtlib.EDTError:
- return "n"
- if prop not in node.props:
- return "n"
- if node.props[prop].type != "boolean":
- return "n"
- if node.props[prop].val:
- return "y"
- return "n"
- def dt_node_has_prop(kconf, _, label, prop):
- """
- This function takes a 'label' and looks for an EDT node for that label. If
- it finds an EDT node, it will look to see if that node has a property
- by the name of 'prop'. If the 'prop' exists it will return "y" otherwise
- we return "n".
- """
- if doc_mode or edt is None:
- return "n"
- try:
- node = edt.label2node.get(label)
- except edtlib.EDTError:
- return "n"
- if node is None:
- return "n"
- if prop in node.props:
- return "y"
- return "n"
- def dt_node_int_prop(kconf, name, path, prop):
- """
- This function takes a 'path' and property name ('prop') looks for an EDT
- node at that path. If it finds an EDT node, it will look to see if that
- node has a property called 'prop' and if that 'prop' is an integer type
- will return the value of the property 'prop' as either a string int or
- string hex value, if not we return 0.
- """
- if doc_mode or edt is None:
- return "0"
- try:
- node = edt.get_node(path)
- except edtlib.EDTError:
- return "0"
- if name == "dt_node_int_prop_int":
- return str(_node_int_prop(node, prop))
- if name == "dt_node_int_prop_hex":
- return hex(_node_int_prop(node, prop))
- def dt_compat_enabled(kconf, _, compat):
- """
- This function takes a 'compat' and returns "y" if we find a status "okay"
- compatible node in the EDT otherwise we return "n"
- """
- if doc_mode or edt is None:
- return "n"
- return "y" if compat in edt.compat2okay else "n"
- def dt_compat_on_bus(kconf, _, compat, bus):
- """
- This function takes a 'compat' and returns "y" if we find an "enabled"
- compatible node in the EDT which is on bus 'bus'. It returns "n" otherwise.
- """
- if doc_mode or edt is None:
- return "n"
- if compat in edt.compat2okay:
- for node in edt.compat2okay[compat]:
- if node.on_bus is not None and node.on_bus == bus:
- return "y"
- return "n"
- def dt_nodelabel_has_compat(kconf, _, label, compat):
- """
- This function takes a 'label' and returns "y" if an "enabled" node with
- such label can be found in the EDT and that node is compatible with the
- provided 'compat', otherwise it returns "n".
- """
- if doc_mode or edt is None:
- return "n"
- if compat in edt.compat2okay:
- for node in edt.compat2okay[compat]:
- if label in node.labels:
- return "y"
- return "n"
- def dt_nodelabel_path(kconf, _, label):
- """
- This function takes a node label (not a label property) and
- returns the path to the node which has that label, or an empty
- string if there is no such node.
- """
- if doc_mode or edt is None:
- return ""
- node = edt.label2node.get(label)
- return node.path if node else ""
- def shields_list_contains(kconf, _, shield):
- """
- Return "n" if cmake environment variable 'SHIELD_AS_LIST' doesn't exist.
- Return "y" if 'shield' is present list obtained after 'SHIELD_AS_LIST'
- has been split using ";" as a separator and "n" otherwise.
- """
- try:
- list = os.environ['SHIELD_AS_LIST']
- except KeyError:
- return "n"
- return "y" if shield in list.split(";") else "n"
- # Keys in this dict are the function names as they appear
- # in Kconfig files. The values are tuples in this form:
- #
- # (python_function, minimum_number_of_args, maximum_number_of_args)
- #
- # Each python function is given a kconf object and its name in the
- # Kconfig file, followed by arguments from the Kconfig file.
- #
- # See the kconfiglib documentation for more details.
- functions = {
- "dt_compat_enabled": (dt_compat_enabled, 1, 1),
- "dt_compat_on_bus": (dt_compat_on_bus, 2, 2),
- "dt_chosen_label": (dt_chosen_label, 1, 1),
- "dt_chosen_enabled": (dt_chosen_enabled, 1, 1),
- "dt_chosen_path": (dt_chosen_path, 1, 1),
- "dt_path_enabled": (dt_node_enabled, 1, 1),
- "dt_alias_enabled": (dt_node_enabled, 1, 1),
- "dt_nodelabel_enabled": (dt_nodelabel_enabled, 1, 1),
- "dt_chosen_reg_addr_int": (dt_chosen_reg, 1, 3),
- "dt_chosen_reg_addr_hex": (dt_chosen_reg, 1, 3),
- "dt_chosen_reg_size_int": (dt_chosen_reg, 1, 3),
- "dt_chosen_reg_size_hex": (dt_chosen_reg, 1, 3),
- "dt_node_reg_addr_int": (dt_node_reg, 1, 3),
- "dt_node_reg_addr_hex": (dt_node_reg, 1, 3),
- "dt_node_reg_size_int": (dt_node_reg, 1, 3),
- "dt_node_reg_size_hex": (dt_node_reg, 1, 3),
- "dt_node_has_bool_prop": (dt_node_has_bool_prop, 2, 2),
- "dt_node_has_prop": (dt_node_has_prop, 2, 2),
- "dt_node_int_prop_int": (dt_node_int_prop, 2, 2),
- "dt_node_int_prop_hex": (dt_node_int_prop, 2, 2),
- "dt_nodelabel_has_compat": (dt_nodelabel_has_compat, 2, 2),
- "dt_nodelabel_path": (dt_nodelabel_path, 1, 1),
- "shields_list_contains": (shields_list_contains, 1, 1),
- }
|