Lines Matching +full:- +full:f

3 # Copyright (c) 2019 - 2020 Nordic Semiconductor ASA
6 # SPDX-License-Identifier: BSD-3-Clause
11 # Note: Do not access private (_-prefixed) identifiers from edtlib here (and
25 sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'python-devicetree',
40 with open(args.edt_pickle, 'rb') as f:
41 edt = pickle.load(f)
46 with open(args.header_out, "w", encoding="utf-8") as header_file:
58 # Check to see if we have duplicate "zephyr,memory-region" property values.
61 if 'zephyr,memory-region' in node.props:
62 region = node.props['zephyr,memory-region'].val
64 sys.exit(f"ERROR: Duplicate 'zephyr,memory-region' ({region}) properties "
65 f"between {regions[region].path} and {node.path}")
72 out_dt_define(f"{node.z_path_id}_PATH", f'"{escape(node.path)}"')
74 out_comment("Node's name with unit-address:")
75 out_dt_define(f"{node.z_path_id}_FULL_NAME",
76 f'"{escape(node.name)}"')
77 out_dt_define(f"{node.z_path_id}_FULL_NAME_UNQUOTED",
78 f'{escape(node.name)}')
79 out_dt_define(f"{node.z_path_id}_FULL_NAME_TOKEN",
80 f'{edtlib.str_as_token(escape(node.name))}')
81 out_dt_define(f"{node.z_path_id}_FULL_NAME_UPPER_TOKEN",
82 f'{edtlib.str_as_token(escape(node.name)).upper()}')
85 out_comment(f"Node parent ({node.parent.path}) identifier:")
86 out_dt_define(f"{node.z_path_id}_PARENT",
87 f"DT_{node.parent.z_path_id}")
89 out_comment(f"Node's index in its parent's list of children:")
90 out_dt_define(f"{node.z_path_id}_CHILD_IDX",
94 out_dt_define(f"{node.z_path_id}_NODELABEL_NUM", len(node.labels))
95 out_dt_define(f"{node.z_path_id}_FOREACH_NODELABEL(fn)",
96 " ".join(f"fn({nodelabel})" for nodelabel in node.labels))
97 out_dt_define(f"{node.z_path_id}_FOREACH_NODELABEL_VARGS(fn, ...)",
98 " ".join(f"fn({nodelabel}, __VA_ARGS__)" for nodelabel in node.labels))
112 def node_z_path_id(node: edtlib.Node) -> str:
115 # - the root node's path "/" has path identifier "N"
116 # - "/foo" has "N_S_foo"
117 # - "/foo/bar" has "N_S_foo_S_bar"
118 # - "/foo/bar@123" has "N_S_foo_S_bar_123"
125 components.extend(f"S_{str2ident(component)}" for component in
131 def parse_args() -> argparse.Namespace:
132 # Returns parsed command-line arguments
135 parser.add_argument("--header-out", required=True,
137 parser.add_argument("--edt-pickle",
143 def write_top_comment(edt: edtlib.EDT) -> None:
147 s = f"""\
163 s += f" {scc[0].dep_ordinal:<3} {scc[0].path}\n"
173 def write_utils() -> None:
180 def write_node_comment(node: edtlib.Node) -> None:
183 s = f"""\
191 s += f"""
196 s += f"""
209 # themselves couldn't contain C multi-line comments, which is
219 def relativize(path) -> Optional[str]:
235 def write_idents_and_existence(node: edtlib.Node) -> None:
240 idents = [f"N_ALIAS_{str2ident(alias)}" for alias in node.aliases]
244 idents.append(f"N_INST_{instance_no}_{str2ident(compat)}")
246 idents.extend(f"N_NODELABEL_{str2ident(label)}" for label in node.labels)
249 out_dt_define(f"{node.z_path_id}_EXISTS", 1)
253 maxlen = max(len(f"DT_{ident}") for ident in idents)
255 out_dt_define(ident, f"DT_{node.z_path_id}", width=maxlen)
258 def write_bus(node: edtlib.Node) -> None:
265 out_comment(f"Bus info (controller: '{bus.path}', type: '{node.on_buses}')")
268 out_dt_define(f"{node.z_path_id}_BUS_{str2ident(one_bus)}", 1)
270 out_dt_define(f"{node.z_path_id}_BUS", f"DT_{bus.z_path_id}")
273 def write_special_props(node: edtlib.Node) -> None:
293 def write_ranges(node: edtlib.Node) -> None:
294 # ranges property: edtlib knows the right #address-cells and
295 # #size-cells of parent and child, and can therefore pack the
302 idx_vals.append((f"{path_id}_RANGES_NUM", len(node.ranges)))
305 idx_vals.append((f"{path_id}_RANGES_IDX_{i}_EXISTS", 1))
308 idx_vals.append((f"{path_id}_RANGES_IDX_{i}_VAL_CHILD_BUS_FLAGS_EXISTS", 1))
309 idx_macro = f"{path_id}_RANGES_IDX_{i}_VAL_CHILD_BUS_FLAGS"
310 idx_value = range.child_bus_addr >> ((range.child_bus_cells - 1) * 32)
312 f"{idx_value} /* {hex(idx_value)} */"))
314 idx_macro = f"{path_id}_RANGES_IDX_{i}_VAL_CHILD_BUS_ADDRESS"
316 idx_value = range.child_bus_addr & ((1 << (range.child_bus_cells - 1) * 32) - 1)
320 f"{idx_value} /* {hex(idx_value)} */"))
322 idx_macro = f"{path_id}_RANGES_IDX_{i}_VAL_PARENT_BUS_ADDRESS"
324 f"{range.parent_bus_addr} /* {hex(range.parent_bus_addr)} */"))
326 idx_macro = f"{path_id}_RANGES_IDX_{i}_VAL_LENGTH"
328 f"{range.length} /* {hex(range.length)} */"))
333 out_dt_define(f"{path_id}_FOREACH_RANGE(fn)",
334 " ".join(f"fn(DT_{path_id}, {i})" for i,range in enumerate(node.ranges)))
337 def write_regs(node: edtlib.Node) -> None:
338 # reg property: edtlib knows the right #address-cells and
339 # #size-cells, and can therefore pack the register base addresses
347 idx_vals.append((f"{path_id}_REG_NUM", len(node.regs)))
350 idx_vals.append((f"{path_id}_REG_IDX_{i}_EXISTS", 1))
352 idx_macro = f"{path_id}_REG_IDX_{i}_VAL_ADDRESS"
354 f"{reg.addr} /* {hex(reg.addr)} */"))
356 name_vals.append((f"{path_id}_REG_NAME_{reg.name}_EXISTS", 1))
357 name_macro = f"{path_id}_REG_NAME_{reg.name}_VAL_ADDRESS"
358 name_vals.append((name_macro, f"DT_{idx_macro}"))
361 idx_macro = f"{path_id}_REG_IDX_{i}_VAL_SIZE"
363 f"{reg.size} /* {hex(reg.size)} */"))
365 name_macro = f"{path_id}_REG_NAME_{reg.name}_VAL_SIZE"
366 name_vals.append((name_macro, f"DT_{idx_macro}"))
374 def write_interrupts(node: edtlib.Node) -> None:
375 # interrupts property: we have some hard-coded logic for interrupt
384 err(f"Expected binding for {irq.controller!r} to have 'type' in "
385 "interrupt-cells")
392 err(f"Invalid interrupt type specified for {irq!r}")
399 idx_vals.append((f"{path_id}_IRQ_NUM", len(node.interrupts)))
409 idx_vals.append((f"{path_id}_IRQ_IDX_{i}_EXISTS", 1))
410 idx_macro = f"{path_id}_IRQ_IDX_{i}_VAL_{name}"
415 f"{path_id}_IRQ_NAME_{str2ident(irq.name)}_VAL_{name}")
416 name_vals.append((name_macro, f"DT_{idx_macro}"))
419 idx_controller_macro = f"{path_id}_IRQ_IDX_{i}_CONTROLLER"
420 idx_controller_path = f"DT_{irq.controller.z_path_id}"
423 name_controller_macro = f"{path_id}_IRQ_NAME_{str2ident(irq.name)}_CONTROLLER"
424 name_vals.append((name_controller_macro, f"DT_{idx_controller_macro}"))
434 idx_vals.append((f"{path_id}_IRQ_LEVEL", len(irqs)))
442 def write_compatibles(node: edtlib.Node) -> None:
449 f"{node.z_path_id}_COMPAT_MATCHES_{str2ident(compat)}", 1)
452 out_dt_define(f"{node.z_path_id}_COMPAT_VENDOR_IDX_{i}_EXISTS", 1)
453 out_dt_define(f"{node.z_path_id}_COMPAT_VENDOR_IDX_{i}",
457 out_dt_define(f"{node.z_path_id}_COMPAT_MODEL_IDX_{i}_EXISTS", 1)
458 out_dt_define(f"{node.z_path_id}_COMPAT_MODEL_IDX_{i}",
461 def write_parent(node: edtlib.Node) -> None:
469 out_dt_define(f"{node.z_path_id}_FOREACH_ANCESTOR(fn)",
470 " ".join(f"fn(DT_{parent.z_path_id})" for parent in
473 def write_children(node: edtlib.Node) -> None:
478 out_dt_define(f"{node.z_path_id}_CHILD_NUM", len(node.children))
485 out_dt_define(f"{node.z_path_id}_CHILD_NUM_STATUS_OKAY", ok_nodes_num)
487 out_dt_define(f"{node.z_path_id}_FOREACH_CHILD(fn)",
488 " ".join(f"fn(DT_{child.z_path_id})" for child in
491 out_dt_define(f"{node.z_path_id}_FOREACH_CHILD_SEP(fn, sep)",
492 " DT_DEBRACKET_INTERNAL sep ".join(f"fn(DT_{child.z_path_id})"
495 out_dt_define(f"{node.z_path_id}_FOREACH_CHILD_VARGS(fn, ...)",
496 " ".join(f"fn(DT_{child.z_path_id}, __VA_ARGS__)"
499 out_dt_define(f"{node.z_path_id}_FOREACH_CHILD_SEP_VARGS(fn, sep, ...)",
500 " DT_DEBRACKET_INTERNAL sep ".join(f"fn(DT_{child.z_path_id}, __VA_ARGS__)"
503 out_dt_define(f"{node.z_path_id}_FOREACH_CHILD_STATUS_OKAY(fn)",
504 " ".join(f"fn(DT_{child.z_path_id})"
507 out_dt_define(f"{node.z_path_id}_FOREACH_CHILD_STATUS_OKAY_SEP(fn, sep)",
508 " DT_DEBRACKET_INTERNAL sep ".join(f"fn(DT_{child.z_path_id})"
511 out_dt_define(f"{node.z_path_id}_FOREACH_CHILD_STATUS_OKAY_VARGS(fn, ...)",
512 " ".join(f"fn(DT_{child.z_path_id}, __VA_ARGS__)"
515 out_dt_define(f"{node.z_path_id}_FOREACH_CHILD_STATUS_OKAY_SEP_VARGS(fn, sep, ...)",
516 " DT_DEBRACKET_INTERNAL sep ".join(f"fn(DT_{child.z_path_id}, __VA_ARGS__)"
520 def write_status(node: edtlib.Node) -> None:
521 out_dt_define(f"{node.z_path_id}_STATUS_{str2ident(node.status)}", 1)
524 def write_pinctrls(node: edtlib.Node) -> None:
525 # Write special macros for pinctrl-<index> and pinctrl-names properties.
527 out_comment("Pin control (pinctrl-<i>, pinctrl-names) properties:")
529 out_dt_define(f"{node.z_path_id}_PINCTRL_NUM", len(node.pinctrls))
535 out_dt_define(f"{node.z_path_id}_PINCTRL_IDX_{pc_idx}_EXISTS", 1)
543 # pinctrl-<pc_idx> properties are contiguous, start from 0,
545 out_dt_define(f"{node.z_path_id}_PINCTRL_IDX_{pc_idx}_TOKEN", name)
546 out_dt_define(f"{node.z_path_id}_PINCTRL_IDX_{pc_idx}_UPPER_TOKEN", name.upper())
547 out_dt_define(f"{node.z_path_id}_PINCTRL_NAME_{name}_EXISTS", 1)
548 out_dt_define(f"{node.z_path_id}_PINCTRL_NAME_{name}_IDX", pc_idx)
550 out_dt_define(f"{node.z_path_id}_PINCTRL_NAME_{name}_IDX_{idx}_PH",
551 f"DT_{ph.z_path_id}")
554 def write_fixed_partitions(node: edtlib.Node) -> None:
555 # Macros for child nodes of each fixed-partitions node.
557 if not (node.parent and "fixed-partitions" in node.parent.compats):
561 out_comment("fixed-partitions identifier:")
562 out_dt_define(f"{node.z_path_id}_PARTITION_ID", flash_area_num)
566 def write_gpio_hogs(node: edtlib.Node) -> None:
567 # Write special macros for gpio-hog node properties.
569 macro = f"{node.z_path_id}_GPIO_HOGS"
576 out_dt_define(f"{macro}_EXISTS", 1)
577 out_dt_define(f"{macro}_NUM", len(node.gpio_hogs))
582 def write_vanilla_props(node: edtlib.Node) -> None:
588 # never-ending amounts of special case code here to skip special
596 macro = f"{node.z_path_id}_P_{prop_id}"
599 # DT_N_<node-id>_P_<prop-id>
604 # DT_N_<node-id>_P_<prop-id>_IDX_0:
605 # DT_N_<node-id>_P_<prop-id>_IDX_0_EXISTS:
607 # string-array of length 1.
608 macro2val[f"{macro}_IDX_0"] = quote_str(prop.val)
609 macro2val[f"{macro}_IDX_0_EXISTS"] = 1
621 # DT_N_<node-id>_P_<prop-id>_FOREACH_PROP_ELEM
622 macro2val[f"{macro}_FOREACH_PROP_ELEM(fn)"] = (
623 ' \\\n\t'.join(f'fn(DT_{node.z_path_id}, {prop_id}, {i})'
626 # DT_N_<node-id>_P_<prop-id>_FOREACH_PROP_ELEM_SEP
627 macro2val[f"{macro}_FOREACH_PROP_ELEM_SEP(fn, sep)"] = (
629 f'fn(DT_{node.z_path_id}, {prop_id}, {i})'
632 # DT_N_<node-id>_P_<prop-id>_FOREACH_PROP_ELEM_VARGS
633 macro2val[f"{macro}_FOREACH_PROP_ELEM_VARGS(fn, ...)"] = (
635 f'fn(DT_{node.z_path_id}, {prop_id}, {i}, __VA_ARGS__)'
638 # DT_N_<node-id>_P_<prop-id>_FOREACH_PROP_ELEM_SEP_VARGS
639 macro2val[f"{macro}_FOREACH_PROP_ELEM_SEP_VARGS(fn, sep, ...)"] = (
641 f'fn(DT_{node.z_path_id}, {prop_id}, {i}, __VA_ARGS__)'
644 # DT_N_<node-id>_P_<prop-id>_LEN
645 macro2val[f"{macro}_LEN"] = plen
647 # DT_N_<node-id>_P_<prop-id>_EXISTS
648 macro2val[f"{macro}_EXISTS"] = 1
660 # The 'macro' argument is the N_<node-id>_P_<prop-id>... part.
664 # DT_N_<node-id>_P_<prop-id>_IDX_<i>_STRING_UNQUOTED
665 f"{macro}_STRING_UNQUOTED": escape_unquoted(val),
666 # DT_N_<node-id>_P_<prop-id>_IDX_<i>_STRING_TOKEN
667 f"{macro}_STRING_TOKEN": as_token,
668 # DT_N_<node-id>_P_<prop-id>_IDX_<i>_STRING_UPPER_TOKEN
669 f"{macro}_STRING_UPPER_TOKEN": as_token.upper()}
673 # Returns a dict of macros for property 'prop' with a defined enum in their dt-binding.
674 # The 'macro' argument is the N_<node-id>_P_<prop-id> part.
677 # DT_N_<node-id>_P_<prop-id>_IDX_<i>_ENUM_IDX
678 ret = {f"{macro}_IDX_{i}_ENUM_IDX": index for i, index in enumerate(prop.enum_indices)}
682 # DT_N_<node-id>_P_<prop-id>_IDX_<i>_EXISTS
683 ret[f"{macro}_IDX_{i}_EXISTS"] = 1
684 # DT_N_<node-id>_P_<prop-id>_IDX_<i>_ENUM_VAL_<val>_EXISTS 1
685 ret[f"{macro}_IDX_{i}_ENUM_VAL_{subval}_EXISTS"] = 1
692 # The 'macro' argument is the N_<node-id>_P_<prop-id> part.
696 # DT_N_<node-id>_P_<prop-id>_IDX_<i>_EXISTS
697 ret[f"{macro}_IDX_{i}_EXISTS"] = 1
699 # DT_N_<node-id>_P_<prop-id>_IDX_<i>
701 ret[f"{macro}_IDX_{i}"] = quote_str(subval)
702 # DT_N_<node-id>_P_<prop-id>_IDX_<i>_STRING_...
703 ret.update(string_macros(f"{macro}_IDX_{i}", subval))
705 ret[f"{macro}_IDX_{i}"] = subval
710 def write_dep_info(node: edtlib.Node) -> None:
711 # Write dependency-related information about the node.
718 .join(f"{n.dep_ordinal}, /* {n.path} */"
724 out_dt_define(f"{node.z_path_id}_ORD", node.dep_ordinal)
725 out_dt_define(f"{node.z_path_id}_ORD_STR_SORTABLE", f"{node.dep_ordinal:0>5}")
728 out_dt_define(f"{node.z_path_id}_REQUIRES_ORDS",
732 out_dt_define(f"{node.z_path_id}_SUPPORTS_ORDS",
736 def prop2value(prop: edtlib.Property) -> edtlib.PropertyValType:
738 # a single well-defined C rvalue that it can be represented as.
750 if prop.type in ["array", "uint8-array"]:
751 return list2init(f"{val} /* {hex(val)} */" for val in prop.val)
753 if prop.type == "string-array":
756 # phandle, phandles, phandle-array, path, compound: nothing
760 def prop_len(prop: edtlib.Property) -> Optional[int]:
769 # This deliberately excludes ranges, dma-ranges, reg and interrupts.
771 # basically nonsense semantically due to #address-cells and
772 # #size-cells for "reg", #interrupt-cells for "interrupts"
773 # and #address-cells, #size-cells and the #address-cells from the
774 # parent node for "ranges" and "dma-ranges".
784 # string is treated as a string-array of length 1.
787 if (prop.type in ["array", "uint8-array", "string-array",
788 "phandles", "phandle-array"] and
789 prop.name not in ["ranges", "dma-ranges", "reg", "interrupts"]):
795 def phandle_macros(prop: edtlib.Property, macro: str) -> dict:
798 # The 'macro' argument is the N_<node-id>_P_<prop-id> bit.
806 # to use the same macros for phandle, phandles, and phandle-array.
812 ret[f"{macro}"] = f"DT_{prop.val.z_path_id}"
813 ret[f"{macro}_IDX_0"] = f"DT_{prop.val.z_path_id}"
814 ret[f"{macro}_IDX_0_PH"] = f"DT_{prop.val.z_path_id}"
815 ret[f"{macro}_IDX_0_EXISTS"] = 1
818 ret[f"{macro}_IDX_{i}"] = f"DT_{node.z_path_id}"
819 ret[f"{macro}_IDX_{i}_PH"] = f"DT_{node.z_path_id}"
820 ret[f"{macro}_IDX_{i}_EXISTS"] = 1
821 elif prop.type == "phandle-array":
824 # Unspecified element. The phandle-array at this index
827 ret[f"{macro}_IDX_{i}_EXISTS"] = 0
845 # DT_N_<node-id>_P_<prop-id>_IDX_<i>_EXISTS
846 ret[f"{macro}_IDX_{i}_EXISTS"] = 1
847 # DT_N_<node-id>_P_<prop-id>_IDX_<i>_PH
848 ret[f"{macro}_IDX_{i}_PH"] = f"DT_{entry.controller.z_path_id}"
849 # DT_N_<node-id>_P_<prop-id>_IDX_<i>_VAL_<VAL>
851 ret[f"{macro}_IDX_{i}_VAL_{str2ident(cell)}"] = val
852 ret[f"{macro}_IDX_{i}_VAL_{str2ident(cell)}_EXISTS"] = 1
858 # DT_N_<node-id>_P_<prop-id>_IDX_<i>_EXISTS
859 ret[f"{macro}_IDX_{i}_EXISTS"] = 1
860 # DT_N_<node-id>_P_<prop-id>_IDX_<i>_NAME
861 ret[f"{macro}_IDX_{i}_NAME"] = quote_str(entry.name)
862 # DT_N_<node-id>_P_<prop-id>_NAME_<NAME>_PH
863 ret[f"{macro}_NAME_{name}_PH"] = f"DT_{entry.controller.z_path_id}"
864 # DT_N_<node-id>_P_<prop-id>_NAME_<NAME>_EXISTS
865 ret[f"{macro}_NAME_{name}_EXISTS"] = 1
866 # DT_N_<node-id>_P_<prop-id>_NAME_<NAME>_VAL_<VAL>
869 ret[f"{macro}_NAME_{name}_VAL_{cell_ident}"] = (
870 f"DT_{macro}_IDX_{i}_VAL_{cell_ident}")
871 ret[f"{macro}_NAME_{name}_VAL_{cell_ident}_EXISTS"] = 1
877 # Tree-wide information such as chosen nodes is printed here.
882 chosen[f"DT_CHOSEN_{str2ident(name)}"] = f"DT_{node.z_path_id}"
883 chosen[f"DT_CHOSEN_{str2ident(name)}_EXISTS"] = 1
890 # Global or tree-wide information, such as number of instances
896 " ".join(f"fn(DT_{node.z_path_id})" for node in edt.nodes))
898 " ".join(f"fn(DT_{node.z_path_id})" for node in edt.nodes
901 " ".join(f"fn(DT_{node.z_path_id}, __VA_ARGS__)" for node in edt.nodes))
903 " ".join(f"fn(DT_{node.z_path_id}, __VA_ARGS__)" for node in edt.nodes
917 n_okay_macros[f"DT_N_INST_{ident}_NUM_OKAY"] = len(okay_nodes)
919 # Helpers for non-INST for-each macros that take node
921 for_each_macros[f"DT_FOREACH_OKAY_{ident}(fn)"] = (
922 " ".join(f"fn(DT_{node.z_path_id})"
924 for_each_macros[f"DT_FOREACH_OKAY_VARGS_{ident}(fn, ...)"] = (
925 " ".join(f"fn(DT_{node.z_path_id}, __VA_ARGS__)"
928 # Helpers for INST versions of for-each macros, which take
930 # avoiding an intermediate node_id --> instance number
933 for_each_macros[f"DT_FOREACH_OKAY_INST_{ident}(fn)"] = (
934 " ".join(f"fn({edt.compat2nodes[compat].index(node)})"
936 for_each_macros[f"DT_FOREACH_OKAY_INST_VARGS_{ident}(fn, ...)"] = (
937 " ".join(f"fn({edt.compat2nodes[compat].index(node)}, __VA_ARGS__)"
942 if compat == "fixed-partitions":
946 macro = f"COMPAT_{str2ident(compat)}_LABEL_{str2ident(label)}"
947 val = f"DT_{child.z_path_id}"
955 out_define(f"DT_COMPAT_HAS_OKAY_{str2ident(compat)}", 1)
967 f"DT_COMPAT_{str2ident(compat)}_BUS_{str2ident(bus)}", 1)
970 def str2ident(s: str) -> str:
973 return re.sub('[-,.@/+]', '_', s.lower())
976 def list2init(l: Iterable[str]) -> str:
987 ) -> str:
990 # The macro will be left-justified to 'width' characters if that
999 ret = f"DT_{macro}"
1009 ) -> None:
1017 s = f"#define {macro.ljust(width)}{warn} {val}"
1019 s = f"#define {macro}{warn} {val}"
1024 def out_comment(s: str, blank_before=True) -> None:
1033 # Format multi-line comments like
1045 res.append(f" * {line}".rstrip())
1049 # Format single-line comments like
1052 print(f"/* {s} */", file=header_file)
1064 def escape(s: str) -> str:
1065 # Backslash-escapes any double quotes, backslashes, and new lines in 's'
1070 def quote_str(s: str) -> str:
1074 return f'"{escape(s)}"'
1077 def escape_unquoted(s: str) -> str:
1086 def err(s: str) -> NoReturn: