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.
108 The free-form description of the binding, or None.
115 using 'child-binding:' with no compatible.
122 A dict that maps specifier space names (like "gpio",
126 for the 'gpio' specifier space, like this:
128 gpio-cells:
129 - pin
130 - flags
161 are multiple levels of 'child-binding' descriptions in the binding.
201 with open(path, encoding="utf-8") as f:
212 if "child-binding" in raw:
213 if not isinstance(raw["child-binding"], dict):
214 _err(f"malformed 'child-binding:' in {self.path}, "
218 raw=raw["child-binding"],
233 if key.endswith("-cells"):
234 self.specifier2cells[key[:-len("-cells")]] = val
236 def __repr__(self) -> str:
245 def description(self) -> Optional[str]:
250 def compatible(self) -> Optional[str]:
255 def bus(self) -> Union[None, str, List[str]]:
260 def buses(self) -> List[str]:
268 def on_bus(self) -> Optional[str]:
270 return self.raw.get('on-bus')
272 def _merge_includes(self, raw: dict, binding_path: Optional[str]) -> dict:
304 allowlist = elem.pop('property-allowlist', None)
305 blocklist = elem.pop('property-blocklist', None)
306 child_filter = elem.pop('child-binding', None)
324 "and optional 'property-allowlist' or "
325 f"'property-blocklist' keys, but got: {elem}")
339 def _load_raw(self, fname: str) -> dict:
350 with open(path, encoding="utf-8") as f:
366 f"field in {self.path} - "
378 # Allowed top-level keys. The 'include' key should have been
380 ok_top = {"description", "compatible", "bus", "on-bus",
381 "properties", "child-binding"}
385 "#cells": "expected *-cells syntax",
387 "child-bus": "use 'bus: <bus>' instead",
388 "parent": "use 'on-bus: <bus>' instead",
389 "parent-bus": "use 'on-bus: <bus>' instead",
390 "sub-node": "use 'child-binding' instead",
398 if key not in ok_top and not key.endswith("-cells"):
400 "expected one of {', '.join(ok_top)}, or *-cells")
416 if ("on-bus" in raw
417 and not isinstance(raw["on-bus"], str)):
418 _err(f"malformed 'on-bus:' value in {self.path}, "
424 if key.endswith("-cells"):
430 def _check_properties(self) -> None:
440 "specifier-space"}
494 The free-form description of the property as a string, or None.
503 A property must have string or string-array type and an "enum:" in its
505 unique after converting all non-alphanumeric characters to underscores
512 non-alphanumeric characters to underscores.
527 The specifier space for the property as given in the binding, or None.
535 def __repr__(self) -> str:
539 def path(self) -> Optional[str]:
544 def type(self) -> str:
549 def description(self) -> Optional[str]:
554 def enum(self) -> Optional[list]:
559 def enum_tokenizable(self) -> bool:
562 if self.type not in {'string', 'string-array'} or self.enum is None:
576 def enum_upper_tokenizable(self) -> bool:
589 def const(self) -> Union[None, int, List[int], str, List[str]]:
594 def default(self) -> Union[None, int, List[int], str, List[str]]:
599 def required(self) -> bool:
604 def deprecated(self) -> bool:
609 def specifier_space(self) -> Optional[str]:
611 return self._raw.get("specifier-space")
643 - For 'type: int/array/string/string-array', 'val' is what you'd expect
646 - For 'type: uint8-array', 'val' is a bytes object
648 - For 'type: phandle' and 'type: path', 'val' is the pointed-to Node
651 - For 'type: phandles', 'val' is a list of the pointed-to Node
654 - For 'type: phandle-array', 'val' is a list of ControllerAndData
671 The value of the property as a list of tokens, i.e. with non-alphanumeric
685 def name(self) -> str:
690 def description(self) -> Optional[str]:
695 def type(self) -> str:
700 def val_as_tokens(self) -> List[str]:
709 def enum_indices(self) -> Optional[List[int]]:
727 The name of the register as given in the 'reg-names' property, or None if
728 there is no 'reg-names' property
731 The starting address of the register, in the parent address space, or None
732 if #address-cells is zero. Any 'ranges' properties are taken into account.
758 A physical address within the child bus address space, or None if the
759 child's #address-cells equals 0.
765 A physical address within the parent bus address space, or None if the
766 parent's #address-cells equals 0.
770 the child's address space.
773 The size of the range in the child address space, or None if the
774 child's #size-cells equals 0.
788 Represents an entry in an 'interrupts' or 'type: phandle-array' property
789 value, e.g. <&ctrl-1 4 0> in
791 cs-gpios = <&ctrl-1 4 0 &ctrl-2 3 4>;
803 A dictionary that maps names from the *-cells key in the binding for the
811 'interrupt-names'/'gpio-names'/'pwm-names'/etc., or None if there is no
812 *-names property
828 e.g. pinctrl-0 or pinctrl-1.
833 The Node instance the pinctrl-* property is on
836 The name of the configuration, as given in pinctrl-names, or None if
837 there is no pinctrl-names property
840 Like 'name', but with non-alphanumeric characters converted to underscores.
846 pinctrl-0 = <&state_1 &state_2>;
862 with some interpretation of devicetree properties. There's a one-to-one
874 An integer with the ...@<unit-address> portion of the node name,
876 the node name has no unit-address portion. PCI devices use a different
909 A non-negative integer value such that the value for a Node is
927 True if the node has a 'read-only' property, and False otherwise
961 A list of PinCtrl objects for the pinctrl-<index> properties on the
963 pinctrl-<index> properties.
989 Documentation/devicetree/bindings/spi/spi-controller.yaml in the Linux kernel.
1022 self.dep_ordinal: int = -1
1036 def name(self) -> str:
1041 def unit_addr(self) -> Optional[int]:
1053 _err(f"{self!r} has non-hex unit address")
1058 def description(self) -> Optional[str]:
1065 def path(self) -> str:
1070 def label(self) -> Optional[str]:
1077 def labels(self) -> List[str]:
1082 def parent(self) -> Optional['Node']:
1087 def children(self) -> Dict[str, 'Node']:
1095 def child_index(self, node) -> int:
1112 def required_by(self) -> List['Node']:
1117 def depends_on(self) -> List['Node']:
1122 def status(self) -> str:
1137 def read_only(self) -> bool:
1139 return "read-only" in self._node.props
1142 def matching_compat(self) -> Optional[str]:
1149 def binding_path(self) -> Optional[str]:
1156 def aliases(self) -> List[str]:
1162 def buses(self) -> List[str]:
1169 def on_buses(self) -> List[str]:
1175 def flash_controller(self) -> 'Node':
1179 # /flash-controller@4001E000/flash@0/partitions/partition@fc000. We go
1182 # For the case of 'soc-nv-flash', we assume the controller is the
1189 if controller.matching_compat == "soc-nv-flash":
1196 def spi_cs_gpio(self) -> Optional[ControllerAndData]:
1201 and "cs-gpios" in self.bus_node.props):
1208 parent_cs_lst = self.bus_node.props["cs-gpios"].val
1212 # cs-gpios is indexed by the unit address
1219 "is >= number of cs-gpios in "
1228 def gpio_hogs(self) -> List[ControllerAndData]:
1231 if "gpio-hog" not in self.props:
1234 if not self.parent or not "gpio-controller" in self.parent.props:
1237 if not "#gpio-cells" in self.parent._node.props:
1238 _err(f"GPIO hog {self!r} parent node lacks #gpio-cells")
1240 n_cells = self.parent._node.props["#gpio-cells"].to_num()
1244 f"4*(<#gpio-cells> (= {n_cells})"):
1254 def has_child_binding(self) -> bool:
1256 True if the node's binding contains a child-binding definition, False
1262 def is_pci_device(self) -> bool:
1266 def __repr__(self) -> str:
1273 def _init_binding(self) -> None:
1313 # nesting with 'child-binding:'.
1323 def _binding_from_properties(self) -> None:
1339 pp["type"] = "uint8-array"
1347 pp["type"] = "string-array"
1353 pp["type"] = "phandle-array"
1365 def _binding_from_parent(self) -> Optional[Binding]:
1366 # Returns the binding from 'child-binding:' in the parent node's
1382 ) -> Optional['Node']:
1390 # Treat 'fixed-partitions' as if they are not on any bus. The reason is
1392 # bus be None means we'll always match the binding for fixed-partitions
1393 # also this means want processing the fixed-partitions node we wouldn't
1395 if support_fixed_partitions_on_any_bus and "fixed-partitions" in self.compats:
1407 ) -> None:
1408 # Initializes all properties that require cross-references to other
1418 err_on_deprecated: bool = False) -> None:
1443 err_on_deprecated: bool) -> None:
1473 # Skip properties that start with '#', like '#size-cells', and mapping
1474 # properties like 'gpio-map'/'interrupt-map'
1475 if name[0] == "#" or name.endswith("-map"):
1485 ) -> PropertyValType:
1528 if prop_type == "uint8-array":
1549 if prop_type == "uint8-array":
1555 if prop_type == "string-array":
1564 if prop_type == "phandle-array":
1565 # This type is a bit high-level for dtlib as it involves
1566 # information from bindings and *-names properties, so there's no
1587 def _check_undeclared_props(self) -> None:
1590 "interrupt-parent", "interrupts-extended", "device_type"}
1594 if (prop_name.endswith("-controller")
1607 def _init_ranges(self) -> None:
1616 raw_child_address_cells = node.props.get("#address-cells")
1622 raw_child_size_cells = node.props.get("#size-cells")
1628 # Number of cells for one translation 3-tuple in 'ranges'
1636 f"<#address-cells> = {child_address_cells}, "
1637 f"<#address-cells for parent> = {parent_address_cells} and "
1638 f"<#size-cells> = {child_size_cells}")
1641 f"4*(<#address-cells> (= {child_address_cells}) + "
1642 "<#address-cells for parent> "
1644 f"<#size-cells> (= {child_size_cells}))"):
1669 def _init_regs(self) -> None:
1683 f"4*(<#address-cells> (= {address_cells}) + "
1684 f"<#size-cells> (= {size_cells}))"):
1695 _err(f"zero-sized 'reg' in {self._node!r} seems meaningless "
1696 "(maybe you want a size of one or #size-cells = 0 "
1704 def _init_pinctrls(self) -> None:
1705 # Initializes self.pinctrls from any pinctrl-<index> properties
1709 # pinctrl-<index> properties
1711 if re.match("pinctrl-[0-9]+", name)]
1717 if prop.name != "pinctrl-" + str(i):
1718 _err(f"missing 'pinctrl-{i}' property on {node!r} "
1719 "- indices should be contiguous and start from zero")
1732 def _init_interrupts(self) -> None:
1753 ) -> List[Optional[ControllerAndData]]:
1760 # #<specifier_space>-cells = <size>;
1773 # #pwm-cells = <2>;
1777 # #pwm-cells = <1>;
1780 # These values can be given names using the <specifier_space>-names:
1785 # <specifier_space>-names = "...", "...", ...
1789 # An index is None if the underlying phandle-array element is
1794 # There's some slight special-casing for *-gpios properties in that
1795 # e.g. foo-gpios still maps to #gpio-cells rather than
1796 # #foo-gpio-cells
1799 # Strip -s. We've already checked that property names end in -s
1800 # if there is no specifier space in _check_prop_by_type().
1801 specifier_space = prop.name[:-1]
1832 ) -> Dict[str, int]:
1833 # Returns a dictionary that maps <basename>-cells names given in the
1844 # Treat no *-cells in the binding the same as an empty *-cells, so
1845 # that bindings don't have to have e.g. an empty 'clock-cells:' for
1846 # '#clock-cells = <0>'.
1851 _err(f"unexpected '{basename}-cells:' length in binding for "
1852 f"{controller._node!r} - {len(cell_names)} "
1905 and processing /delete-node/ and /delete-property/, as a string
1953 If True, set the Node.bus for 'fixed-partitions' compatible nodes
1954 to None. This allows 'fixed-partitions' binding to match regardless
1955 of the bus the 'fixed-partition' is under.
1966 exempt set of grandfathered-in cases will cause warnings.
2016 def _finish_init(self) -> None:
2028 def get_node(self, path: str) -> Node:
2039 def chosen_nodes(self) -> Dict[str, Node]:
2058 def chosen_node(self, name: str) -> Optional[Node]:
2066 def dts_source(self) -> str:
2069 def __repr__(self) -> str:
2073 def __deepcopy__(self, memo) -> 'EDT':
2095 def scc_order(self) -> List[List[Node]]:
2101 def _process_properties_r(self, root_node: Node, props_node: Node) -> None:
2111 # 'phandles', or 'phandle-array' property values.
2120 elif prop.type == 'phandle-array':
2144 def _process_properties(self, node: Node) -> None:
2151 def _init_graph(self) -> None:
2170 def _init_compat2binding(self) -> None:
2195 with open(binding_path, encoding="utf-8") as f:
2230 dt_compats: Set[str]) -> Optional[Binding]:
2252 def _register_binding(self, binding: Binding) -> None:
2254 # 'compatible:'/'on-bus:' combo
2263 msg += f" and 'on-bus: {binding.on_bus}'"
2269 def _init_nodes(self) -> None:
2300 def _init_luts(self) -> None:
2316 # The regular expression comes from dt-schema.
2317 compat_re = r'^[a-zA-Z][a-zA-Z0-9,+\-._]+$'
2350 def _check(self) -> None:
2351 # Tree-wide checks and warnings.
2361 f"in binding '{binding.path}' has non-tokenizable enum "
2382 # is a list, but add an assert for future-proofing.
2386 # This is also just for future-proofing.
2391 ignore_errors: bool = False) -> List[Binding]:
2413 "Exception raised for devicetree- and binding-related errors"
2420 def load_vendor_prefixes_txt(vendor_prefixes: str) -> Dict[str, str]:
2421 """Load a vendor-prefixes.txt file and return a dict
2425 with open(vendor_prefixes, 'r', encoding='utf-8') as f:
2446 def _dt_compats(dt: DT) -> Set[str]:
2456 def _binding_paths(bindings_dirs: List[str]) -> List[str]:
2481 binding_path: Optional[str]) -> None:
2482 # Check that an 'include:' named 'name' with property-allowlist
2483 # 'allowlist', property-blocklist 'blocklist', and
2484 # child-binding filter 'child_filter' has valid structure.
2492 "should not specify both 'property-allowlist:' "
2493 "and 'property-blocklist:'")
2498 child_copy.pop('property-allowlist', None))
2500 child_copy.pop('property-blocklist', None))
2502 child_copy.pop('child-binding', None))
2508 f"'child-binding': {child_copy}")
2512 "should not specify both 'property-allowlist:' and "
2513 "'property-blocklist:' in a 'child-binding:'")
2522 binding_path: Optional[str]) -> None:
2524 # 'raw["child-binding"]', if they exist, according to
2530 child_binding = raw.get('child-binding')
2533 child_filter.get('property-allowlist'),
2534 child_filter.get('property-blocklist'),
2536 child_filter = child_filter.get('child-binding')
2537 child_binding = child_binding.get('child-binding')
2543 binding_path: Optional[str]) -> None:
2547 _check_prop_filter('property-allowlist', allowlist, binding_path)
2548 _check_prop_filter('property-blocklist', blocklist, binding_path)
2564 binding_path: Optional[str]) -> None:
2565 # Ensure an include: ... property-allowlist or property-blocklist
2588 # which might help keep bindings well-organized.
2595 # 'from_dict', and 'binding_path' is the path to the top-level binding.
2622 check_required: bool) -> bool:
2658 binding_path: Optional[str]) -> None:
2660 # 'const:' and # 'specifier-space:' for the property named 'prop_name'
2670 ok_types = {"boolean", "int", "array", "uint8-array", "string",
2671 "string-array", "phandle", "phandles", "phandle-array",
2679 if "specifier-space" in options and prop_type != "phandle-array":
2680 _err(f"'specifier-space' in 'properties: {prop_name}' "
2681 f"has type '{prop_type}', expected 'phandle-array'")
2683 if prop_type == "phandle-array":
2684 if not prop_name.endswith("s") and not "specifier-space" in options:
2686 f"has type 'phandle-array' and its name does not end in 's', "
2687 f"but no 'specifier-space' was provided.")
2691 const_types = {"int", "array", "uint8-array", "string", "string-array"}
2703 "phandle-array", "path"}:
2708 def ok_default() -> bool:
2717 # array, uint8-array, or string-array
2726 if (prop_type == "uint8-array"
2731 # string-array
2740 def _translate(addr: int, node: dtlib_Node) -> int:
2741 # Recursively translates 'addr' on 'node' to the address space(s) of its
2751 # specifies that the parent and child address space is identical, and
2754 # Treat this the same as a 'range' that explicitly does a one-to-one
2758 # Gives the size of each component in a translation 3-tuple in 'ranges'
2763 # Number of cells for one translation 3-tuple in 'ranges'
2767 f"4*(<#address-cells> (= {child_address_cells}) + "
2768 "<#address-cells for parent> "
2770 f"<#size-cells> (= {child_size_cells}))"):
2782 return _translate(parent_addr + addr - child_addr, node.parent)
2788 def _add_names(node: dtlib_Node, names_ident: str, objs: Any) -> None:
2789 # Helper for registering names from <foo>-names properties.
2794 # names-ident:
2795 # The <foo> part of <foo>-names, e.g. "reg" for "reg-names"
2800 full_names_ident = names_ident + "-names"
2819 def _interrupt_parent(start_node: dtlib_Node) -> dtlib_Node:
2820 # Returns the node pointed at by the closest 'interrupt-parent', searching
2827 if "interrupt-parent" in node.props:
2828 return node.props["interrupt-parent"].to_node()
2832 f"nor any of its parents has an 'interrupt-parent' property")
2835 def _interrupts(node: dtlib_Node) -> List[Tuple[dtlib_Node, bytes]]:
2838 # interrupt (possibly after mapping through an 'interrupt-map'), and <data>
2842 if "interrupts-extended" in node.props:
2843 prop = node.props["interrupts-extended"]
2848 _err(f"node '{node.path}' interrupts-extended property "
2855 # Treat 'interrupts' as a special case of 'interrupts-extended', with
2863 "4*<#interrupt-cells>")]
2872 ) -> Tuple[dtlib_Node, bytes]:
2874 # 'child_spec' through any 'interrupt-map' properties. Returns a
2877 if "interrupt-controller" in parent.props:
2881 # Used for parents pointed at by 'interrupt-map'. We can't use
2882 # _address_cells(), because it's the #address-cells property on 'node'
2885 address_cells = node.props.get("#address-cells")
2887 _err(f"missing #address-cells on {node!r} "
2888 "(while handling interrupt-map)")
2892 # Can't use _address_cells() here, because it's the #address-cells
2909 ) -> Tuple[dtlib_Node, bytes]:
2911 # mapping through any '<basename>-map' (e.g. gpio-map) properties. See
2915 prop_name = f"#{basename}-cells"
2921 # Do not require <prefix>-controller for anything but interrupts for now
2933 ) -> Tuple[dtlib_Node, bytes]:
2934 # Common code for mapping through <prefix>-map properties, e.g.
2935 # interrupt-map and gpio-map.
2944 # The "receiver", e.g. a node with 'interrupt-map = <...>' or
2945 # 'interrupt-controller' (no mapping)
2949 # e.g. <1 2> for 'foo-gpios = <&gpio1 1 2>'.
2952 # Function called on a parent specified in a *-map property to get the
2953 # length of the parent specifier (data after phandle in *-map), in cells
2957 # to have a <prefix>-controller property.
2959 map_prop = parent.props.get(prefix + "-map")
2961 if require_controller and prefix + "-controller" not in parent.props:
2962 _err(f"expected '{prefix}-controller' property on {parent!r} "
2982 # Parent specified in *-map
2993 # Got one *-map row. Check if it matches the child data.
2995 # Handle *-map-pass-thru
3003 _err(f"child specifier for {child!r} ({child_spec!r}) "
3012 ) -> bytes:
3013 # Common code for handling <prefix>-mask properties, e.g. interrupt-mask.
3016 mask_prop = parent.props.get(prefix + "-map-mask")
3023 _err(f"{child!r}: expected '{prefix}-mask' in {parent!r} "
3035 ) -> bytes:
3036 # Common code for handling <prefix>-map-thru properties, e.g.
3037 # interrupt-pass-thru.
3040 # The parent data from the matched entry in the <prefix>-map property
3044 pass_thru_prop = parent.props.get(prefix + "-map-pass-thru")
3046 # No pass-thru
3051 _err(f"{child!r}: expected '{prefix}-map-pass-thru' in {parent!r} "
3058 return res[-len(parent_spec):]
3061 def _raw_unit_addr(node: dtlib_Node) -> bytes:
3063 # #address-cells) as a raw 'bytes'
3067 "(needed for 'interrupt-map' unit address lookup)")
3073 "(while doing 'interrupt-map' unit address lookup)")
3078 def _and(b1: bytes, b2: bytes) -> bytes:
3088 def _or(b1: bytes, b2: bytes) -> bytes:
3098 def _not(b: bytes) -> bytes:
3108 ) -> List[Optional[Tuple[dtlib_Node, bytes]]]:
3117 # The <name> part of the #<name>-cells property to look for on the nodes
3118 # the phandles point to, e.g. "gpio" for #gpio-cells.
3124 full_n_cells_name = f"#{n_cells_name}-cells"
3138 # Unspecified phandle-array element. This is valid; a 0
3156 def _address_cells(node: dtlib_Node) -> int:
3157 # Returns the #address-cells setting for 'node', giving the number of <u32>
3162 if "#address-cells" in node.parent.props:
3163 return node.parent.props["#address-cells"].to_num()
3167 def _size_cells(node: dtlib_Node) -> int:
3168 # Returns the #size-cells setting for 'node', giving the number of <u32>
3173 if "#size-cells" in node.parent.props:
3174 return node.parent.props["#size-cells"].to_num()
3178 def _interrupt_cells(node: dtlib_Node) -> int:
3179 # Returns the #interrupt-cells property value on 'node', erroring out if
3180 # 'node' has no #interrupt-cells property
3182 if "#interrupt-cells" not in node.props:
3183 _err(f"{node!r} lacks #interrupt-cells")
3184 return node.props["#interrupt-cells"].to_num()
3190 size_hint: str) -> List[bytes]:
3194 def _check_dt(dt: DT) -> None:
3196 # anything-goes except for very special properties like phandle, but in
3202 ok_status = {"ok", "okay", "disabled", "reserved", "fail", "fail-sss"}
3226 def _err(msg) -> NoReturn:
3232 # Regular expression for non-alphanumeric-or-underscore characters.
3236 def str_as_token(val: str) -> str:
3263 "compatible": "string-array",
3267 "reg-names": "string-array",
3270 "interrupts-extended": "compound",
3271 "interrupt-names": "string-array",
3272 "interrupt-controller": "boolean",
3275 _STATUS_ENUM: List[str] = "ok okay disabled reserved fail fail-sss".split()
3279 ) -> Dict[str, Union[str, bool, List[str]]]: