Description
Problem Description
Zephyr only process the first compat string to get the binding properties for a given node.
Given a DTS like below where two compat string is involved but their properties does not entirely overlap.
The common mspi-aps-z8
would have the device variant/part number property that would never make into ambiq,mspi-device
that is platform specific. And ambiq,mspi-device
would have ambiq,timing-config
and ambiq,timing-config-mask
properties that would never make into the common mspi-aps-z8
; while both three properties are needed in the device tree.
aps51216ba: aps_z8@0 {
compatible = "ambiq,mspi-device", "mspi-aps-z8";
size = <DT_SIZE_M(512)>;
reg = <0>;
status = "disabled";
variant = "APS51216BA"
mspi-max-frequency = <125000000>;
mspi-io-mode = "MSPI_IO_MODE_HEX_8_8_16";
mspi-data-rate = "MSPI_DATA_RATE_S_D_D";
mspi-hardware-ce-num = <0>;
mspi-dqs-enable;
read-command = <0x20>;
write-command = <0xA0>;
command-length = "INSTR_1_BYTE";
address-length = "ADDR_4_BYTE";
rx-dummy = <7>;
tx-dummy = <8>;
xip-config = <1 0 DT_SIZE_M(64) 0>;
ce-break-config = <1024 4>;
ambiq,timing-config-mask = <0x62>;
ambiq,timing-config = <8 7 1 0 0 3 10>;
zephyr,pm-device-runtime-auto;
};
Another example is when the common device(flash) binding have gpio reset related properties that are also inappropriate to appear in a platform specific binding.
Proposed Change (Summary)
Update edtlib.py to support pulling bind properties from all listed compat string given that they are on the same bus.
Or, introduce a base keyword, and merge bindings that have the same base.
Proposed Change (Detailed)
This seems pretty easy, I was able to modify the edtlib.py _init_binding to merge bindings across listed compats. Note that this would merge without constraints.
def _init_binding(self) -> None:
# Initializes Node._binding. It holds data from the node's binding file,
# in the format returned by PyYAML (plain Python lists, dicts, etc.), or
# None if the node has no binding.
# This relies on the parent of the node having already been
# initialized, which is guaranteed by going through the nodes in
# node_iter() order.
if self.path in self.edt._infer_binding_for_paths:
self._binding_from_properties()
return
if self.compats:
on_buses = self.on_buses
merged_raw = {}
found_binding = False
for compat in self.compats:
# When matching, respect the order of the 'compatible' entries,
# and for each one first try to match against an explicitly
# specified bus (if any) and then against any bus. This is so
# that matching against bindings which do not specify a bus
# works the same way in Zephyr as it does elsewhere.
binding = None
for bus in on_buses:
if (compat, bus) in self.edt._compat2binding:
binding = self.edt._compat2binding[compat, bus]
break
if not binding and (compat, None) in self.edt._compat2binding:
binding = self.edt._compat2binding[compat, None]
if binding:
found_binding = True
_merge_props(merged_raw, binding.raw, None, binding.path, False)
if found_binding:
self._binding = Binding(None, self.edt._binding_fname2path, raw=merged_raw)
return
else:
# No 'compatible' property. See if the parent binding has
# a compatible. This can come from one or more levels of
# nesting with 'child-binding:'.
binding_from_parent = self._binding_from_parent()
if binding_from_parent:
self._binding = binding_from_parent
return
# No binding found
self._binding = None
The constraints may need further discussion. Some I come up:
- Merge only compat on the same bus
- When conflict, use binding in the most specific compat.
- ...
Dependencies
No response
Concerns and Unresolved Questions
No response
Alternatives Considered
alternative is to have DT support addtionalProperties feature seen in Linux/dt-schema.
Metadata
Metadata
Assignees
Type
Projects
Status
Status