Lines Matching +full:specifier +full:- +full:space
3 # SPDX-License-Identifier: BSD-3-Clause
17 but a binding can also come from a 'child-binding:' key in the binding for the
23 The top-level entry points for the library are the EDT and Binding classes.
31 # --------------------
47 # - Consider using @property for APIs that don't need parameters. It makes
51 # - Think about the data type of the thing you're exposing. Exposing something
55 # - Avoid get_*() prefixes on functions. Name them after the thing they return
60 # - Don't expose dtlib stuff directly.
62 # - Add documentation for any new APIs you add.
95 def _compute_hash(path: str) -> str:
116 The free-form description of the binding, or None.
123 using 'child-binding:' with no compatible.
130 A dict that maps specifier space names (like "gpio",
134 for the 'gpio' specifier space, like this:
136 gpio-cells:
137 - pin
138 - flags
169 are multiple levels of 'child-binding' descriptions in the binding.
209 with open(path, encoding="utf-8") as f:
220 if "child-binding" in raw:
221 if not isinstance(raw["child-binding"], dict):
222 _err(f"malformed 'child-binding:' in {self.path}, "
226 raw=raw["child-binding"],
241 if key.endswith("-cells"):
242 self.specifier2cells[key[:-len("-cells")]] = val
244 def __repr__(self) -> str:
253 def description(self) -> Optional[str]:
258 def compatible(self) -> Optional[str]:
263 def bus(self) -> Union[None, str, list[str]]:
268 def buses(self) -> list[str]:
276 def on_bus(self) -> Optional[str]:
278 return self.raw.get('on-bus')
280 def _merge_includes(self, raw: dict, binding_path: Optional[str]) -> dict:
312 allowlist = elem.pop('property-allowlist', None)
313 blocklist = elem.pop('property-blocklist', None)
314 child_filter = elem.pop('child-binding', None)
332 "and optional 'property-allowlist' or "
333 f"'property-blocklist' keys, but got: {elem}")
347 def _load_raw(self, fname: str) -> dict:
358 with open(path, encoding="utf-8") as f:
374 f"field in {self.path} - "
386 # Allowed top-level keys. The 'include' key should have been
388 ok_top = {"description", "compatible", "bus", "on-bus",
389 "properties", "child-binding"}
393 "#cells": "expected *-cells syntax",
395 "child-bus": "use 'bus: <bus>' instead",
396 "parent": "use 'on-bus: <bus>' instead",
397 "parent-bus": "use 'on-bus: <bus>' instead",
398 "sub-node": "use 'child-binding' instead",
406 if key not in ok_top and not key.endswith("-cells"):
408 "expected one of {', '.join(ok_top)}, or *-cells")
424 if ("on-bus" in raw
425 and not isinstance(raw["on-bus"], str)):
426 _err(f"malformed 'on-bus:' value in {self.path}, "
432 if key.endswith("-cells"):
438 def _check_properties(self) -> None:
448 "specifier-space"}
504 The free-form description of the property as a string, or None.
513 A property must have string or string-array type and an "enum:" in its
515 unique after converting all non-alphanumeric characters to underscores
522 non-alphanumeric characters to underscores.
537 The specifier space for the property as given in the binding, or None.
545 def __repr__(self) -> str:
549 def path(self) -> Optional[str]:
554 def type(self) -> str:
559 def description(self) -> Optional[str]:
564 def enum(self) -> Optional[list]:
569 def enum_tokenizable(self) -> bool:
572 if self.type not in {'string', 'string-array'} or self.enum is None:
586 def enum_upper_tokenizable(self) -> bool:
599 def const(self) -> Union[None, int, list[int], str, list[str]]:
604 def default(self) -> Union[None, int, list[int], str, list[str]]:
609 def required(self) -> bool:
614 def deprecated(self) -> bool:
619 def specifier_space(self) -> Optional[str]:
621 return self._raw.get("specifier-space")
653 - For 'type: int/array/string/string-array', 'val' is what you'd expect
656 - For 'type: uint8-array', 'val' is a bytes object
658 - For 'type: phandle' and 'type: path', 'val' is the pointed-to Node
661 - For 'type: phandles', 'val' is a list of the pointed-to Node
664 - For 'type: phandle-array', 'val' is a list of ControllerAndData
681 The value of the property as a list of tokens, i.e. with non-alphanumeric
695 def name(self) -> str:
700 def description(self) -> Optional[str]:
705 def type(self) -> str:
710 def val_as_tokens(self) -> list[str]:
719 def enum_indices(self) -> Optional[list[int]]:
737 The name of the register as given in the 'reg-names' property, or None if
738 there is no 'reg-names' property
741 The starting address of the register, in the parent address space, or None
742 if #address-cells is zero. Any 'ranges' properties are taken into account.
768 A physical address within the child bus address space, or None if the
769 child's #address-cells equals 0.
775 A physical address within the parent bus address space, or None if the
776 parent's #address-cells equals 0.
780 the child's address space.
783 The size of the range in the child address space, or None if the
784 child's #size-cells equals 0.
798 Represents an entry in an 'interrupts' or 'type: phandle-array' property
799 value, e.g. <&ctrl-1 4 0> in
801 cs-gpios = <&ctrl-1 4 0 &ctrl-2 3 4>;
813 A dictionary that maps names from the *-cells key in the binding for the
821 'interrupt-names'/'gpio-names'/'pwm-names'/etc., or None if there is no
822 *-names property
838 e.g. pinctrl-0 or pinctrl-1.
843 The Node instance the pinctrl-* property is on
846 The name of the configuration, as given in pinctrl-names, or None if
847 there is no pinctrl-names property
850 Like 'name', but with non-alphanumeric characters converted to underscores.
856 pinctrl-0 = <&state_1 &state_2>;
872 with some interpretation of devicetree properties. There's a one-to-one
884 An integer with the ...@<unit-address> portion of the node name,
886 the node name has no unit-address portion. PCI devices use a different
919 A non-negative integer value such that the value for a Node is
942 True if the node has a 'read-only' property, and False otherwise
977 A list of PinCtrl objects for the pinctrl-<index> properties on the
979 pinctrl-<index> properties.
1005 Documentation/devicetree/bindings/spi/spi-controller.yaml in the Linux kernel.
1038 self.dep_ordinal: int = -1
1053 def name(self) -> str:
1058 def filename(self) -> str:
1063 def lineno(self) -> int:
1068 def unit_addr(self) -> Optional[int]:
1080 _err(f"{self!r} has non-hex unit address")
1085 def description(self) -> Optional[str]:
1092 def path(self) -> str:
1097 def label(self) -> Optional[str]:
1104 def labels(self) -> list[str]:
1109 def parent(self) -> Optional['Node']:
1114 def children(self) -> dict[str, 'Node']:
1122 def child_index(self, node) -> int:
1139 def required_by(self) -> list['Node']:
1144 def depends_on(self) -> list['Node']:
1149 def status(self) -> str:
1164 def read_only(self) -> bool:
1166 return "read-only" in self._node.props
1169 def matching_compat(self) -> Optional[str]:
1176 def binding_path(self) -> Optional[str]:
1183 def aliases(self) -> list[str]:
1189 def buses(self) -> list[str]:
1196 def on_buses(self) -> list[str]:
1202 def flash_controller(self) -> 'Node':
1206 # /flash-controller@4001E000/flash@0/partitions/partition@fc000. We go
1209 # For the case of 'soc-nv-flash', we assume the controller is the
1216 if controller.matching_compat == "soc-nv-flash":
1223 def spi_cs_gpio(self) -> Optional[ControllerAndData]:
1228 and "cs-gpios" in self.bus_node.props):
1235 parent_cs_lst = self.bus_node.props["cs-gpios"].val
1239 # cs-gpios is indexed by the unit address
1246 "is >= number of cs-gpios in "
1255 def gpio_hogs(self) -> list[ControllerAndData]:
1258 if "gpio-hog" not in self.props:
1261 if not self.parent or not "gpio-controller" in self.parent.props:
1264 if not "#gpio-cells" in self.parent._node.props:
1265 _err(f"GPIO hog {self!r} parent node lacks #gpio-cells")
1267 n_cells = self.parent._node.props["#gpio-cells"].to_num()
1271 f"4*(<#gpio-cells> (= {n_cells})"):
1281 def has_child_binding(self) -> bool:
1283 True if the node's binding contains a child-binding definition, False
1289 def is_pci_device(self) -> bool:
1293 def __repr__(self) -> str:
1300 def _init_binding(self) -> None:
1340 # nesting with 'child-binding:'.
1350 def _binding_from_properties(self) -> None:
1366 pp["type"] = "uint8-array"
1374 pp["type"] = "string-array"
1380 pp["type"] = "phandle-array"
1392 def _binding_from_parent(self) -> Optional[Binding]:
1393 # Returns the binding from 'child-binding:' in the parent node's
1409 ) -> Optional['Node']:
1417 # Treat 'fixed-partitions' as if they are not on any bus. The reason is
1419 # bus be None means we'll always match the binding for fixed-partitions
1420 # also this means want processing the fixed-partitions node we wouldn't
1422 if support_fixed_partitions_on_any_bus and "fixed-partitions" in self.compats:
1434 ) -> None:
1435 # Initializes all properties that require cross-references to other
1445 err_on_deprecated: bool = False) -> None:
1470 err_on_deprecated: bool) -> None:
1500 # Skip properties that start with '#', like '#size-cells', and mapping
1501 # properties like 'gpio-map'/'interrupt-map'
1502 if name[0] == "#" or name.endswith("-map"):
1512 ) -> PropertyValType:
1555 if prop_type == "uint8-array":
1574 if prop_type == "uint8-array":
1580 if prop_type == "string-array":
1589 if prop_type == "phandle-array":
1590 # This type is a bit high-level for dtlib as it involves
1591 # information from bindings and *-names properties, so there's no
1612 def _check_undeclared_props(self) -> None:
1615 "interrupt-parent", "interrupts-extended", "device_type"}
1619 if (prop_name.endswith("-controller")
1632 def _init_ranges(self) -> None:
1641 raw_child_address_cells = node.props.get("#address-cells")
1647 raw_child_size_cells = node.props.get("#size-cells")
1653 # Number of cells for one translation 3-tuple in 'ranges'
1661 f"<#address-cells> = {child_address_cells}, "
1662 f"<#address-cells for parent> = {parent_address_cells} and "
1663 f"<#size-cells> = {child_size_cells}")
1666 f"4*(<#address-cells> (= {child_address_cells}) + "
1667 "<#address-cells for parent> "
1669 f"<#size-cells> (= {child_size_cells}))"):
1694 def _init_regs(self) -> None:
1708 f"4*(<#address-cells> (= {address_cells}) + "
1709 f"<#size-cells> (= {size_cells}))"):
1720 _err(f"zero-sized 'reg' in {self._node!r} seems meaningless "
1721 "(maybe you want a size of one or #size-cells = 0 "
1729 def _init_pinctrls(self) -> None:
1730 # Initializes self.pinctrls from any pinctrl-<index> properties
1734 # pinctrl-<index> properties
1736 if re.match("pinctrl-[0-9]+", name)]
1742 if prop.name != "pinctrl-" + str(i):
1743 _err(f"missing 'pinctrl-{i}' property on {node!r} "
1744 "- indices should be contiguous and start from zero")
1757 def _init_interrupts(self) -> None:
1778 ) -> list[Optional[ControllerAndData]]:
1785 # #<specifier_space>-cells = <size>;
1798 # #pwm-cells = <2>;
1802 # #pwm-cells = <1>;
1805 # These values can be given names using the <specifier_space>-names:
1810 # <specifier_space>-names = "...", "...", ...
1814 # An index is None if the underlying phandle-array element is
1819 # There's some slight special-casing for *-gpios properties in that
1820 # e.g. foo-gpios still maps to #gpio-cells rather than
1821 # #foo-gpio-cells
1824 # Strip -s. We've already checked that property names end in -s
1825 # if there is no specifier space in _check_prop_by_type().
1826 specifier_space = prop.name[:-1]
1857 ) -> dict[str, int]:
1858 # Returns a dictionary that maps <basename>-cells names given in the
1869 # Treat no *-cells in the binding the same as an empty *-cells, so
1870 # that bindings don't have to have e.g. an empty 'clock-cells:' for
1871 # '#clock-cells = <0>'.
1876 _err(f"unexpected '{basename}-cells:' length in binding for "
1877 f"{controller._node!r} - {len(cell_names)} "
1930 and processing /delete-node/ and /delete-property/, as a string
1978 If True, set the Node.bus for 'fixed-partitions' compatible nodes
1979 to None. This allows 'fixed-partitions' binding to match regardless
1980 of the bus the 'fixed-partition' is under.
1991 exempt set of grandfathered-in cases will cause warnings.
2041 def _finish_init(self) -> None:
2053 def get_node(self, path: str) -> Node:
2064 def chosen_nodes(self) -> dict[str, Node]:
2083 def chosen_node(self, name: str) -> Optional[Node]:
2091 def dts_source(self) -> str:
2094 def __repr__(self) -> str:
2098 def __deepcopy__(self, memo) -> 'EDT':
2120 def scc_order(self) -> list[list[Node]]:
2126 def _process_properties_r(self, root_node: Node, props_node: Node) -> None:
2136 # 'phandles', or 'phandle-array' property values.
2145 elif prop.type == 'phandle-array':
2169 def _process_properties(self, node: Node) -> None:
2176 def _init_graph(self) -> None:
2195 def _init_compat2binding(self) -> None:
2220 with open(binding_path, encoding="utf-8") as f:
2255 dt_compats: set[str]) -> Optional[Binding]:
2277 def _register_binding(self, binding: Binding) -> None:
2279 # 'compatible:'/'on-bus:' combo
2288 msg += f" and 'on-bus: {binding.on_bus}'"
2294 def _init_nodes(self) -> None:
2333 def _init_luts(self) -> None:
2349 # The regular expression comes from dt-schema.
2350 compat_re = r'^[a-zA-Z][a-zA-Z0-9,+\-._]+$'
2383 def _check(self) -> None:
2384 # Tree-wide checks and warnings.
2394 f"in binding '{binding.path}' has non-tokenizable enum "
2415 # is a list, but add an assert for future-proofing.
2419 # This is also just for future-proofing.
2424 ignore_errors: bool = False) -> list[Binding]:
2446 "Exception raised for devicetree- and binding-related errors"
2453 def load_vendor_prefixes_txt(vendor_prefixes: str) -> dict[str, str]:
2454 """Load a vendor-prefixes.txt file and return a dict
2458 with open(vendor_prefixes, 'r', encoding='utf-8') as f:
2479 def _dt_compats(dt: DT) -> set[str]:
2489 def _binding_paths(bindings_dirs: list[str]) -> list[str]:
2514 binding_path: Optional[str]) -> None:
2515 # Check that an 'include:' named 'name' with property-allowlist
2516 # 'allowlist', property-blocklist 'blocklist', and
2517 # child-binding filter 'child_filter' has valid structure.
2525 "should not specify both 'property-allowlist:' "
2526 "and 'property-blocklist:'")
2531 child_copy.pop('property-allowlist', None))
2533 child_copy.pop('property-blocklist', None))
2535 child_copy.pop('child-binding', None))
2541 f"'child-binding': {child_copy}")
2545 "should not specify both 'property-allowlist:' and "
2546 "'property-blocklist:' in a 'child-binding:'")
2555 binding_path: Optional[str]) -> None:
2557 # 'raw["child-binding"]', if they exist, according to
2563 child_binding = raw.get('child-binding')
2566 child_filter.get('property-allowlist'),
2567 child_filter.get('property-blocklist'),
2569 child_filter = child_filter.get('child-binding')
2570 child_binding = child_binding.get('child-binding')
2576 binding_path: Optional[str]) -> None:
2580 _check_prop_filter('property-allowlist', allowlist, binding_path)
2581 _check_prop_filter('property-blocklist', blocklist, binding_path)
2597 binding_path: Optional[str]) -> None:
2598 # Ensure an include: ... property-allowlist or property-blocklist
2621 # which might help keep bindings well-organized.
2628 # 'from_dict', and 'binding_path' is the path to the top-level binding.
2655 check_required: bool) -> bool:
2691 binding_path: Optional[str]) -> None:
2693 # 'const:' and # 'specifier-space:' for the property named 'prop_name'
2703 ok_types = {"boolean", "int", "array", "uint8-array", "string",
2704 "string-array", "phandle", "phandles", "phandle-array",
2712 if "specifier-space" in options and prop_type != "phandle-array":
2713 _err(f"'specifier-space' in 'properties: {prop_name}' "
2714 f"has type '{prop_type}', expected 'phandle-array'")
2716 if prop_type == "phandle-array":
2717 if not prop_name.endswith("s") and not "specifier-space" in options:
2719 f"has type 'phandle-array' and its name does not end in 's', "
2720 f"but no 'specifier-space' was provided.")
2724 const_types = {"int", "array", "uint8-array", "string", "string-array"}
2736 "phandle-array", "path"}:
2741 def ok_default() -> bool:
2750 # array, uint8-array, or string-array
2759 if (prop_type == "uint8-array"
2764 # string-array
2773 def _translate(addr: int, node: dtlib_Node) -> int:
2774 # Recursively translates 'addr' on 'node' to the address space(s) of its
2784 # specifies that the parent and child address space is identical, and
2787 # Treat this the same as a 'range' that explicitly does a one-to-one
2791 # Gives the size of each component in a translation 3-tuple in 'ranges'
2796 # Number of cells for one translation 3-tuple in 'ranges'
2800 f"4*(<#address-cells> (= {child_address_cells}) + "
2801 "<#address-cells for parent> "
2803 f"<#size-cells> (= {child_size_cells}))"):
2815 return _translate(parent_addr + addr - child_addr, node.parent)
2821 def _add_names(node: dtlib_Node, names_ident: str, objs: Any) -> None:
2822 # Helper for registering names from <foo>-names properties.
2827 # names-ident:
2828 # The <foo> part of <foo>-names, e.g. "reg" for "reg-names"
2833 full_names_ident = names_ident + "-names"
2852 def _interrupt_parent(start_node: dtlib_Node) -> dtlib_Node:
2853 # Returns the node pointed at by the closest 'interrupt-parent', searching
2860 if "interrupt-parent" in node.props:
2861 return node.props["interrupt-parent"].to_node()
2865 f"nor any of its parents has an 'interrupt-parent' property")
2868 def _interrupts(node: dtlib_Node) -> list[tuple[dtlib_Node, bytes]]:
2871 # interrupt (possibly after mapping through an 'interrupt-map'), and <data>
2875 if "interrupts-extended" in node.props:
2876 prop = node.props["interrupts-extended"]
2881 _err(f"node '{node.path}' interrupts-extended property "
2888 # Treat 'interrupts' as a special case of 'interrupts-extended', with
2896 "4*<#interrupt-cells>")]
2905 ) -> tuple[dtlib_Node, bytes]:
2907 # 'child_spec' through any 'interrupt-map' properties. Returns a
2910 if "interrupt-controller" in parent.props:
2914 # Used for parents pointed at by 'interrupt-map'. We can't use
2915 # _address_cells(), because it's the #address-cells property on 'node'
2918 address_cells = node.props.get("#address-cells")
2920 _err(f"missing #address-cells on {node!r} "
2921 "(while handling interrupt-map)")
2925 # Can't use _address_cells() here, because it's the #address-cells
2942 ) -> tuple[dtlib_Node, bytes]:
2944 # mapping through any '<basename>-map' (e.g. gpio-map) properties. See
2948 prop_name = f"#{basename}-cells"
2954 # Do not require <prefix>-controller for anything but interrupts for now
2966 ) -> tuple[dtlib_Node, bytes]:
2967 # Common code for mapping through <prefix>-map properties, e.g.
2968 # interrupt-map and gpio-map.
2977 # The "receiver", e.g. a node with 'interrupt-map = <...>' or
2978 # 'interrupt-controller' (no mapping)
2982 # e.g. <1 2> for 'foo-gpios = <&gpio1 1 2>'.
2985 # Function called on a parent specified in a *-map property to get the
2986 # length of the parent specifier (data after phandle in *-map), in cells
2990 # to have a <prefix>-controller property.
2992 map_prop = parent.props.get(prefix + "-map")
2994 if require_controller and prefix + "-controller" not in parent.props:
2995 _err(f"expected '{prefix}-controller' property on {parent!r} "
3015 # Parent specified in *-map
3026 # Got one *-map row. Check if it matches the child data.
3028 # Handle *-map-pass-thru
3036 _err(f"child specifier for {child!r} ({child_spec!r}) "
3045 ) -> bytes:
3046 # Common code for handling <prefix>-mask properties, e.g. interrupt-mask.
3049 mask_prop = parent.props.get(prefix + "-map-mask")
3056 _err(f"{child!r}: expected '{prefix}-mask' in {parent!r} "
3068 ) -> bytes:
3069 # Common code for handling <prefix>-map-thru properties, e.g.
3070 # interrupt-pass-thru.
3073 # The parent data from the matched entry in the <prefix>-map property
3077 pass_thru_prop = parent.props.get(prefix + "-map-pass-thru")
3079 # No pass-thru
3084 _err(f"{child!r}: expected '{prefix}-map-pass-thru' in {parent!r} "
3091 return res[-len(parent_spec):]
3094 def _raw_unit_addr(node: dtlib_Node) -> bytes:
3096 # #address-cells) as a raw 'bytes'
3100 "(needed for 'interrupt-map' unit address lookup)")
3106 "(while doing 'interrupt-map' unit address lookup)")
3111 def _and(b1: bytes, b2: bytes) -> bytes:
3121 def _or(b1: bytes, b2: bytes) -> bytes:
3131 def _not(b: bytes) -> bytes:
3141 ) -> list[Optional[tuple[dtlib_Node, bytes]]]:
3150 # The <name> part of the #<name>-cells property to look for on the nodes
3151 # the phandles point to, e.g. "gpio" for #gpio-cells.
3157 full_n_cells_name = f"#{n_cells_name}-cells"
3171 # Unspecified phandle-array element. This is valid; a 0
3189 def _address_cells(node: dtlib_Node) -> int:
3190 # Returns the #address-cells setting for 'node', giving the number of <u32>
3195 if "#address-cells" in node.parent.props:
3196 return node.parent.props["#address-cells"].to_num()
3200 def _size_cells(node: dtlib_Node) -> int:
3201 # Returns the #size-cells setting for 'node', giving the number of <u32>
3206 if "#size-cells" in node.parent.props:
3207 return node.parent.props["#size-cells"].to_num()
3211 def _interrupt_cells(node: dtlib_Node) -> int:
3212 # Returns the #interrupt-cells property value on 'node', erroring out if
3213 # 'node' has no #interrupt-cells property
3215 if "#interrupt-cells" not in node.props:
3216 _err(f"{node!r} lacks #interrupt-cells")
3217 return node.props["#interrupt-cells"].to_num()
3223 size_hint: str) -> list[bytes]:
3227 def _check_dt(dt: DT) -> None:
3229 # anything-goes except for very special properties like phandle, but in
3235 ok_status = {"ok", "okay", "disabled", "reserved", "fail", "fail-sss"}
3259 def _err(msg) -> NoReturn:
3265 # Regular expression for non-alphanumeric-or-underscore characters.
3269 def str_as_token(val: str) -> str:
3296 "compatible": "string-array",
3300 "reg-names": "string-array",
3303 "interrupts-extended": "compound",
3304 "interrupt-names": "string-array",
3305 "interrupt-controller": "boolean",
3308 _STATUS_ENUM: list[str] = "ok okay disabled reserved fail fail-sss".split()
3312 ) -> dict[str, Union[str, bool, list[str]]]: