[1] was introduced to get more valuable answers from
the PropertySpec.path API, which is supposed to tell
in which file the property's specification was "last modfied".
Further work on related issues [2] showed that the
approach chosen in [1] is dead end: we need to first rethink
how bindings (and especially child-bindings) are initialized.
[1] edtlib: fix last modified semantic in included property specs
[2] edtlib: Preserve paths of properties from included child bindings
See also: #65221, #78095
This reverts commit b3b5ad8156.
Signed-off-by: Christophe Dufaza <chris@openmarl.org>
It is currently impossible to use enum with any array like type (i.e.
string-array and array, these are the only ones that make sense) in the
devicetree and dt-bindings.
However, there is no such remark in the dt-bindings section of the docs.
Since this is a feature that comes in very handy and is implemented
fairly easily, I adjusted the scripts for this.
It is now possible to do something like this.
```yaml
compatible = "enums"
properties:
array-enum:
type: string-array
enum:
- bar
- foo
- baz
- zoo
```
```dts
/ {
enums {
compatible = "enums";
array-enum = "foo", "bar";
};
};
```
Signed-off-by: Joel Hirsbrunner <jhirsbrunner@baumer.com>
Previously, dtlib would fail to parse the following:
/delete-node/ &{/};
This is accepted by dtc, so dtlib should be aligned.
The expected behavior is that the contents of the "deleted" root node
are emptied, but the node itself remains in the tree. This means that
it's possible to put that statement at the end of a DTS file and still
get a valid output. A small test case for this scenario is included.
Signed-off-by: Grzegorz Swiderski <grzegorz.swiderski@nordicsemi.no>
Although the PropertySpec.path attribute is documented as
"the file where the property was last modified",
all property specs in Binding.prop2specs will claim
they were last modified by the top-level binding itself.
Consider:
- I1 is a base binding that specifies properties x and y
- I2 is an "intermediate" binding that includes I1,
modifying the specification for property x
- B is a top-level bindings that includes I2,
and specifies an additional property p
When enumerating the properties of B,
we expect the values of PropertySpec.path to tell us:
- y was last modified by I1
- x was last modified by I2
- p was last modified by B
However, the Binding constructor:
- first merges all included bindings into the top-level one
- eventually initializes specifications for all the defined properties
As a consequence, all defined properties claim they were last modified
by the top-level binding file.
We should instead:
- first, take into account their own specifications for the
included properties
- eventually update these specifications with the properties
the top-level binding adds or modifies
Signed-off-by: Christophe Dufaza <chris@openmarl.org>
The current EDT graph logic only use properties directly under a
specific node to add dependencies. For nodes properties in
child-bindings, this means that the child phandles are only linked by
the child node itself, which does have an ordinal but no corresponding
"sturct device" in the code, causing those dependencies to be silently
ignored by gen_handles.py.
Fix that by adding the recursive logic to visit child bindings when
present, which causes all child node property handles to be linked to
the parent node.
Signed-off-by: Fabio Baltieri <fabiobaltieri@google.com>
When we have an empty Devicetree, ie,
```
/dts-v1/;
/ {
};
```
The node's dep_ordinal is never initialized because the node graph is
empty. This ends up with invalid ordinal tokens (-1) in
devicetree_generated.h which in turn produce some cryptic compiler
errors, see e.g.
```
error: pasting "dts_ord_" and "-" does not give a valid preprocessing
token
95 | #define Z_DEVICE_DT_DEV_ID(node_id) _CONCAT(dts_ord_,
DT_DEP_ORD(node_id))
...
include/zephyr/devicetree.h:2498:41:
note: in expansion of macro 'DT_FOREACH_OKAY_HELPER'
2498 | #define DT_FOREACH_STATUS_OKAY_NODE(fn)
DT_FOREACH_OKAY_HELPER(fn)
|
^~~~~~~~~~~~~~~~~~~~~~
include/zephyr/device.h:1022:1:
note: in expansion of macro 'DT_FOREACH_STATUS_OKAY_NODE'
1022 |
DT_FOREACH_STATUS_OKAY_NODE(Z_MAYBE_DEVICE_DECLARE_INTERNAL)
```
(devicetree_generated.h)
```
...
#define DT_N_ORD -1
#define DT_N_ORD_STR_SORTABLE 000-1
...
```
This patch makes sure root node is always inserted (without any target)
so that it gets initialized later.
Discovered as part of
https://github.com/zephyrproject-rtos/zephyr/pull/63696
Signed-off-by: Gerard Marull-Paretas <gerard@teslabs.com>
PCI devices are have some differences to regular nodes:
* node name specifies device/function e.g. "pcie@1,0"
* register address has a different meaning
* zero-sized register is allowed
This improves alignment with Linux DT for PCI devices
Signed-off-by: Grant Ramsay <gramsay@enphaseenergy.com>
In Linux, checkpatch.pl relies on the vendor-prefixes.yaml file
to validate manufacturers in compatible strings.
In addition to the vendors defined in vendor-prefixes.txt,
the YAML file includes expressions for "prefixes which are not vendors":
these expressions do NOT define special manufacturers that may appear
in compatible strings, and are never involved as such in DTS files.
We can rather see them as bulk-definitions of JSON/YAML properties
suitable for the dt-schema tools.
OTHO, in Zephyr, checkpatch.pl relies on the vendor-prefixes.txt file,
which does not include these additional prefixes, but edtlib.EDT adds
them as hard-coded special values.
This is confusing, if not incorrect:
- the fact that edtlib.EDT (and thus its client code in the
zephyr/scripts directory) actually allows these vendors
in compatible strings is buried in the source code
- checkpatch.pl (with vendor-prefixes.txt) in Zephyr behaves neither like
checkpatch.pl (with vendor-prefixes.yaml) in Linux, nor like edtlib.EDT
(with _VENDOR_PREFIX_ALLOWED)
- Zephyr should not treat these "prefixes which are not vendors" as
valid manufacturers in compatible strings to begin with
Signed-off-by: Christophe Dufaza <chris@openmarl.org>
This is a one-line fix for edtlib, which lets gen_defines.py indicate
whether the `ranges` property exists within a given node.
Although address translation through ranges is typically automatic,
users can choose to manually inspect ranges using DT_FOREACH_RANGE(),
DT_NUM_RANGES(), and other DT_RANGES_* macros. These can be used to
implement manual translation at runtime, which is currently done for
PCIe controllers.
The only thing missing is being able to check if a node contains an
empty `ranges;`, which signifies a 1:1 translation to the parent bus.
Checking DT_NUM_RANGES() is insufficient, because it returns zero
whether or not `ranges;` is present.
It should be possible to use DT_NODE_HAS_PROP(), but it was not working,
because edtlib ignores properties which are undeclared in bindings and
don't have a default type. Add a missing PropertySpec for `ranges` with
"compound" type; it can't be "array" because it can be empty-valued.
Signed-off-by: Grzegorz Swiderski <grzegorz.swiderski@nordicsemi.no>
This concludes the type annotations for the public API for the module,
along with the relevant internal state. It's not worth type annotating
the internal backwards compatibility shim for !include.
Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
This requires adding a private constructor so that mypy
can tell what all the final instance state is going to be.
Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
Converting this to a dataclass will make it easier to type annotate.
Adding type annotations is incremental progress towards type checking
the entire module.
Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
Converting this to a dataclass will make it easier to type annotate.
Adding type annotations is incremental progress towards type checking
the entire module.
Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
Converting this to a dataclass will make it easier to type annotate.
Adding type annotations is incremental progress towards type checking
the entire module.
Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
Converting this to a dataclass will make it easier to type annotate.
Adding type annotations is incremental progress towards type checking
the entire module.
Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
Converting this to a dataclass will make it easier to type annotate.
Adding type annotations is incremental progress towards type checking
the entire module.
Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
Incremental progress towards type annotating the whole module.
Annotate helper procedures used by the class as well.
Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
This is just moving the class definition higher in the file. I am
reordering the classes to make it possible to type annotate the module
in a more readable way.
Git might make the diff look bigger than it really is.
To verify this is just moving code, use 'git diff --minimal'.
Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
This is just moving the class definition higher in the file
to make it easier to type annotate the module.
Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
This is just moving the class definition higher in the file
to make it easier to type annotate the module.
Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
This is just moving the class definition higher in the file
to make it easier to type annotate the module.
Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
This is just moving the class definition higher in the file
to make it easier to type annotate the module.
Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
This is just moving the class definition higher in the file
to make it easier to type annotate the module.
Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
This is just moving the class definition higher in the file
to make it easier to type annotate the module.
Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
This is just moving the class definition higher in the file. I am
reordering the classes to make it possible to type annotate the module
in a more readable way.
Git might make the diff look bigger than it really is.
To verify this is just moving code, use 'git diff --minimal'.
Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
Just like we did for dtlib in 15e3e317f7
("dtlib: implement copy.deepcopy() for DT"), except this time it's for
EDT. This also can do no harm and will be useful for implementing
system devicetree support.
No functional changes expected under the assumption that no users are
relying on us having stashed the exact bindings_dirs list passed to
the constructor. This patch switches to making a defensive copy, which
is safer and makes implementing this a little cleaner.
Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
Move all the initial settings of instance attributes to the
constructor, so we can keep track of them all more easily.
No functional changes expected.
Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
This will make it more convenient to use it from multiple different
places, which we will have a need for in the future.
Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
We need to have an _include_path attribute to pretty-print
this object from within pdb, for some reason. Add it.
Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
There's no need for _parse_node() to return the Node instance that is
its sole argument. The only user of the return value is a dead store.
Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
This helper lets you place a node (really the entire subtree rooted at
that node) elsewhere in the devicetree. This will be useful when
adding system devicetree support, when we'll want to be able to, for
example, move the CPU cluster node selected by the current execution
domain to /cpus.
Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
GPIO hog nodes contain a "gpios" property, but unlike other "*-gpios"
properties, these are not phandle-arrays as they only carry the data part
(e.g. pin, flags) but lack the phandles to the (parent) GPIO controller.
Add special devicetree tooling to handle the "gpios" property of GPIO hog
nodes and generate special devicetree helper macros as if they were phandle
arrays.
Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
At some point in the past, we had to suppress a couple of false
positive pylint warnings to pass CI. But now the linter seems to have
figured out its original mistake and is complaining about a useless
supression. Sigh. Play along.
Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
The standard library copy module allows you to implement shallow and
deep copies of objects. See its documentation for more details on
these terms.
Implementing copy.deepcopy() support for DT objects will allow us to
"clone" devicetree objects in other classes. This in turn will enable
new features, such as native system devicetree support, within the
python-devicetree.
It is also a pure feature extension which can't harm anything and is
therefore safe to merge now, even if system devicetree is never
adopted in Zephyr.
Note that we are making use of the move from OrderedDict to regular
dict to make this implementation more convenient.
See https://github.com/devicetree-org/lopper/ for more information on
system devicetree. We want to add system devicetree support to dtlib
because it seems to be a useful way to model modern, heterogeneous
SoCs than traditional devicetree, which can really only model a single
CPU "cluster" within such an SoC.
In order to create 'regular' devicetrees from a system devicetree, we
will want a programming interface that does the following:
1. parse the system devicetree
2. receive the desired transformations on it
3. perform the desired transformations to make
a 'regular' devicetree
Step 3 can be done as a destructive modification on an object-oriented
representation of a system devicetree, and that's the approach we will
take in python-devicetree. It will therefore be convenient to have an
efficient deepcopy implementation to be able to preserve the original
system devicetree and the derived regular devicetree in memory in the
same python process.
Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
Regular dicts are insertion-ordered since CPython 3.6 and Python 3.7.
Zephyr now requires Python 3.8, so it should be OK to replace
OrderedDict with regular dict now. This results in less typing and
more readable object representations.
A nitpicker could argue that this is a functional change, since if a
user is doing 'assert isinstance(node.props, OrderedDict)', that will
fail now, but:
1. nobody is doing something like that in the zephyr tree
2. that would be a silly thing to do
3. we don't currently make any API stability guarantees
for this module right now anyway
so it should be fine.
Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>