Commit Graph

161 Commits

Author SHA1 Message Date
Fabio Baltieri
403640b75e edtlib: link child nodes to parent for nodes with child-bindings
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>
2023-10-25 18:39:31 -07:00
Gerard Marull-Paretas
7772cec6bd edtlib: always insert root node to the graph
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>
2023-10-11 18:28:01 +03:00
Gerard Marull-Paretas
73b803ab4b edtlib: pinctrl properties are required in the binding
Consumers need to include `pinctrl-device.yaml` where this is defined.

Signed-off-by: Gerard Marull-Paretas <gerard@teslabs.com>
2023-09-27 13:58:28 +02:00
Grant Ramsay
5443703dc9 edtlib: Exclude PCI devices from some inapplicable checks
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>
2023-08-18 10:13:12 +02:00
Christophe Dufaza
ad48c51651 devicetree: edtlib: prefixes which are not vendors are NOT vendors
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>
2023-08-16 14:50:26 +02:00
Grzegorz Swiderski
dcd8d60119 scripts: dts: Support DT_NODE_HAS_PROP(node_id, ranges)
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>
2023-08-02 09:56:01 -07:00
Martí Bolívar
5847890a18 edtlib: finish adding type annotations
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>
2023-04-17 08:58:14 -07:00
Martí Bolívar
3318380eaf edtlib: type annotate EDT
Incremental progress towards type annotating the entire module.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2023-04-17 08:58:14 -07:00
Martí Bolívar
d89f974760 edtlib: type annotate Node
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>
2023-04-17 08:58:14 -07:00
Martí Bolívar
cae8b6567d edtlib: make PinCtrl a type-annotated dataclass
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>
2023-04-17 08:58:14 -07:00
Martí Bolívar
83b6db2ec1 edtlib: make ControllerAndData a type-annotated dataclass
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>
2023-04-17 08:58:14 -07:00
Martí Bolívar
3a43e1b643 edtlib: make Range a type-annotated dataclass
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>
2023-04-17 08:58:14 -07:00
Martí Bolívar
b07f3ddd9f edtlib: clean up Range docstring
Fix grammar issues and typos.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2023-04-17 08:58:14 -07:00
Martí Bolívar
49c0d72234 edtlib: make Register a type-annotated dataclass
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>
2023-04-17 08:58:14 -07:00
Martí Bolívar
4415a29af2 edtlib: make Property a type-annotated dataclass
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>
2023-04-17 08:58:14 -07:00
Martí Bolívar
835a57ccfa edtlib: type annotate PropertySpec
Incremental progress towards type annotating the module.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2023-04-17 08:58:14 -07:00
Martí Bolívar
1b6921965a edtlib: type annotate Binding
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>
2023-04-17 08:58:14 -07:00
Martí Bolívar
3d75f17d5e edtlib: improve error handling paths
Miscellaneous fixes discovered by inspection while type annotating the
module.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2023-04-17 08:58:14 -07:00
Martí Bolívar
51d79808e4 edtlib: move Node
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>
2023-04-17 08:58:14 -07:00
Martí Bolívar
ba4b8a406e edtlib: move PinCtrl
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>
2023-04-17 08:58:14 -07:00
Martí Bolívar
a5d82337b7 edtlib: move ControllerAndData
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>
2023-04-17 08:58:14 -07:00
Martí Bolívar
ea4db57d90 edtlib: move Range
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>
2023-04-17 08:58:14 -07:00
Martí Bolívar
da31368eed edtlib: move Register
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>
2023-04-17 08:58:14 -07:00
Martí Bolívar
20731a3cab edtlib: move Property
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>
2023-04-17 08:58:14 -07:00
Martí Bolívar
ff8c63c03b edtlib: move PropertySpec
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>
2023-04-17 08:58:14 -07:00
Martí Bolívar
bef3970573 edtlib: move Binding
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>
2023-04-17 08:58:14 -07:00
Martí Bolívar
cf9cfc31bd edtlib: implement copy.deepcopy() for EDT
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>
2023-04-17 08:58:14 -07:00
Martí Bolívar
f4b487aea2 edtlib: refactor some internals
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>
2023-04-17 08:58:14 -07:00
Martí Bolívar
867dd1c84c devicetree: use c89 comments in test file
This is still the preferred style in a zephyr DTS.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2023-04-17 08:58:14 -07:00
Martí Bolívar
dcf1fc0592 dtlib: fix docstring
The reference is to an incorrect method.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2023-04-17 08:58:14 -07:00
Martí Bolívar
513e03ad68 edtlib: extract _slice() code to new helper module
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>
2023-02-27 17:44:45 +01:00
Martí Bolívar
c0a024253f edtlib: fix typo
Trivial fix.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2023-02-27 17:44:45 +01:00
Martí Bolívar
3bb1aaebd5 dtlib: fix pretty-printing in pdb
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>
2023-02-27 17:44:45 +01:00
Martí Bolívar
2d86e1b05d dtlib: add missing type annotations
This allows mypy to check the internal variable type annotations
within the function.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2023-02-27 17:44:45 +01:00
Martí Bolívar
78fca3c19c dtlib: fix comment header
The following section of code has nothing public inside.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2023-02-27 17:44:45 +01:00
Martí Bolívar
6ac19439b2 dtlib: remove dead code
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>
2023-02-27 17:44:45 +01:00
Martí Bolívar
5272e7f681 dtlib: add DT.move_node()
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>
2023-02-27 17:44:45 +01:00
Martí Bolívar
e479d3f7c6 dtlib: use new helper in test cases
Using dtlib_raises() throughout the test cases saves some typing.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2023-02-27 17:44:45 +01:00
Martí Bolívar
2063ddbc93 dtlib: add new test case helper
Introduce a context manager that will save some typing
when dealing with expected exceptions.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2023-02-27 17:44:45 +01:00
Martí Bolívar
faa7e530c2 dtlib: clean up a documentation string
The standard way we write this in the library is 'documentation
string', not 'docstring'.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2023-02-27 17:44:45 +01:00
Henrik Brix Andersen
28819152cb scripts: dts: add special tooling for handling GPIO hog nodes
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>
2023-01-27 14:38:52 -08:00
Chris Duf
92897ef011 python-devicetree: bump version to 0.0.2
Inconsistency between python-devicetree version numbers
may be confusing:
- the last version at PyPI is 0.0.2
- zephyr-rtos/python-devicetree/setup.py sets the version
  to 0.0.2 (this is probably the setup file used when uploading
  to PyPI)
- zephyr-rtos/zephyr/scripts/dts/python-devicetree/setup.py sets
  the version to 0.0.1

This may suggest that the mirror repository, and PyPI, are more
up-to-date than zephyr-rtos/zephyr/scripts/dts/python-devicetree.

Repositories being otherwise mostly identical (1), also bumping
the python-devicetree's version here seems a sane option.

(1) Ignoring the doc directory (only at zephyr-rtos/python-devicetree).

Signed-off-by: Chris Duf <chris@openmarl.org>
2023-01-16 11:19:54 +00:00
Chris Duf
436616c66b python-devicetree: unpin types-PyYAML version
This is essentially a revert of PR #46311 "python-devicetree: CI hotfix",
assuming the original issue has been resolved, either upstream in
types-PyYAML or in Zephyr itself.

Tested with types-PyYAML 6.0.12.2 (current version at PyPI):

  $ python -m mypy --config-file=tox.ini --package=devicetree
  dtlib.py:962: note: By default the bodies of untyped functions [...]
  dtlib.py:964: note: By default the bodies of untyped functions [...]
  dtlib.py:965: note: By default the bodies of untyped functions [...]
  dtlib.py:967: note: By default the bodies of untyped functions [...]
  Success: no issues found in 4 source files

The "notes" above are harmless (use of type hinting to define local
variables while mypy won't "check the bodies of untyped functions").

References:
- python-devicetree tox run fails (issue #46286)
- python-devicetree: CI hotfix (PR #46311)
- python-devicetree: CI hotfix (commit f6a6843)

Signed-off-by: Chris Duf <chris@openmarl.org>
2023-01-16 11:19:54 +00:00
Fabio Baltieri
0daa3a78a9 yamllint: indentation: fix files in scripts/
Fix the YAML files indentation for files in scripts/.

Signed-off-by: Fabio Baltieri <fabiobaltieri@google.com>
2023-01-04 14:23:53 +01:00
Gerard Marull-Paretas
537133fe44 devicetree: edtlib: tests: add coverage for child includes
Add test coverage for the child-binding include feature. It includes
verification of included properties as well as usage of allow/blocklist.

Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
2022-11-17 06:57:46 -06:00
Martí Bolívar
a97295b6a2 edtlib: re-appease the linter
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>
2022-11-07 19:00:31 +01:00
Martí Bolívar
15e3e317f7 dtlib: implement copy.deepcopy() for DT
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>
2022-11-07 19:00:31 +01:00
Martí Bolívar
3c976cc3b6 devicetree: stop using OrderedDict
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>
2022-11-07 19:00:31 +01:00
Martí Bolívar
c25dde3511 dtlib: fix Property.labels docstring
The value of the 'labels' attribute is a list, not a set.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2022-11-07 19:00:31 +01:00
Martí Bolívar
b64d5d6d19 dtlib: move some internal code around
Refactor the file parsing methods for readability by moving the
_parse_header() and _parse_memreserves() calls from _parse_dt() to
_parse_file(). The header and memreserves are not part of the 'tree'
part of the devicetree; now that we have a dedicated _parse_file()
helper, it makes more sense to me to have them there.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2022-11-07 19:00:31 +01:00
Martí Bolívar
c875cb0f94 dtlib: fix Property.type type annotation
Holy overloaded technical terms, Batman.

Here, 'property' and 'type' each mean two different things, which
we can distinguish like this:

- Property (capital P): dtlib.Property class, represents
  a property in a devicetree node
- @property: a Python property
- type(): an "@property" in the Property class, that returns
  a dtlib.Type value
- Type (capital T): dtlib.Type class, represents the devicetree
  type of a Property value (dtlib.Type.BYTES, etc.)

The type() @property in the Property class currently has an 'int' as
its Python return type annotation. It really returns a dtlib.Type,
which is an int (since it's an IntEnum), but that's not the same thing
as an int.

Change this to Type to be clear that not just any int can be returned
by this @property.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2022-11-07 19:00:31 +01:00
Martí Bolívar
cd18ffee22 dtlib: clean up Property initialization
Make attribute initialization order match the order that attributes
appear within the class docstring. Move the 'type' property definition
up by the constructor to make it more obvious that this 'attribute' is
a (Python) property. This is for readability.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2022-11-07 19:00:31 +01:00
Martí Bolívar
47789aa1fa dtlib: clean up Node initialization
Reorder attribute initialization to match the order that attributes
appear in the class level docstring. This is for readability.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2022-11-07 19:00:31 +01:00
Martí Bolívar
cb78a5c322 dtlib: clean up DT initialization
Initialize all the public API interface related attributes within the
constructor instead of scattering them throughout the implementation
of the class, and make sure they all have type annotations.

Move all the parsing code away from the init routines and public API
down to the main parsing block.

This is for readability and paves the way for later changes that
affect the way initialization happens.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2022-11-07 19:00:31 +01:00
Chris Duf
e067be5f0c Devicetree: edtlib: fix possible TypeError in Binding.__repr__()
Calling Binding.__repr__() when the attribute Binding.path is None
would raise TypeError: expected str, bytes or os.PathLike object,
not  NoneType.

Known bindings that may not have a path (Binding.path is None)
include bindings for properties such as 'compatible', 'reg', 'status'.

Signed-off-by: Chris Duf <chris@openmarl.org>

Co-authored-by: Gerard Marull-Paretas <gerard@teslabs.com>
2022-10-13 12:02:31 +02:00
Chris Duf
230c80e000 Devicetree: edtlib: fix possible AttributeError in Property.description
Attempting to access the property Property.description
when Property.spec.description is None would raise
AttributeError: 'NoneType' object has no attribute 'strip'.

Known properties that may not have a description
(Property.spec.description is None):
- 'compatible' for nodes such as / /soc /soc/timer@e000e010 /leds /pwmleds
- 'reg'        for nodes such as /soc/timer@e000e010
- 'status'     for nodes such as /soc/timer@e000e010
- 'gpios'      for nodes such as /leds/led_0 /buttons/button_0
- 'pwms'       for nodes such as /pwmleds/pwm_led_0

This patch checks the PropertySpec.description attribute before calling
strip(): will return None, and not raise AttributeError.

Signed-off-by: Chris Duf <chris@openmarl.org>

Co-authored-by: Gerard Marull-Paretas <gerard@teslabs.com>
2022-10-13 16:03:49 +09:00
Chris Duf
5abce9b8ec Devicetree: edtlib: fix possible KeyError in Binding.description
Attempting to access the Binding.description property
when the description is unavailable would raise KeyError: 'description'.

Known bindings that won't define a 'description' key in the
Binding.raw dictionary include the 'compatible' property's binding
of nodes such as /, /soc, /leds or /pwmleds.
Note that this may also occur when a proper YAML
binding file is available (e.g. pwmleds.yaml).

This patch simply substitutes the Binding.raw dictionary indexing
with the get() function: will return None and not raise KeyError.

Signed-off-by: Chris Duf <chris@openmarl.org>
2022-10-12 18:45:32 +09:00
Maureen Helm
e73c363346 scripts: edtlib: gen_defines: Add model name macros based on compat
Follow up to 5b5aa6ebba adding model name
and existence macros for all compatibles of a node that match an entry
in vendor prefixes.

Signed-off-by: Maureen Helm <maureen.helm@intel.com>
2022-10-07 11:48:02 -07:00
Martí Bolívar
22012894c0 dtlib: error out on duplicate node names
Attempts to define two nodes with the same name within a single set of
curly brackets should fail.

For example, this is invalid DTS according to dtc:

    / { foo {}; foo {}; };

By contrast, this is valid since the node named 'foo' appears twice in
two different sets of curly brackets:

    / { foo {}; };
    / { foo {}; };

Zephyr's dtlib currently does not error out on the invalid condition.

Now that Zephyr itself has been updated to not include such nodes (to
the best of my ability), we can fix this divergence from current dtc
behavior and add a regression test in dtlib.

Fixes: #49590
Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2022-09-21 07:55:40 -07:00
Daniel Leung
418c915f1b dts: add primitive support for multi-bus in bindings
For a single bus that supports multiple protocols, e.g. I3C and I2C,
the single value "bus:" setting is no longer sufficient, as a I3C bus
cannot be matched to a device having "on-bus: I2C". This commit
extends the "bus:" setting so that it can accept a list of values.
This change allows corresponding devicetree macros to be generated
so that DT_ON_BUS() can work properly in this scenario.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
2022-09-09 17:42:33 -04:00
Martí Bolívar
7ef9c4b20e edtlib: remove python 3.5 workaround
Remove a yaml monkeypatch. It is no longer needed since we support 3.6
or later on Zephyr v2.7 LTS and 3.8 or later on what will become v3.2.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2022-09-07 15:38:26 +02:00
Maureen Helm
a1b0c39c37 scripts: edtlib: Add compat2vendor LUT constructed from vendor prefixes
Adds a new compat2vendor lookup table that maps compatibles to vendor
names, constructed from the vendor prefixes file. This approach is a
more scalable alternative to adding a vendor name property to devicetree
bindings, as was previously proposed.

Signed-off-by: Maureen Helm <maureen.helm@intel.com>
2022-09-01 14:53:55 -07:00
Kumar Gala
f1660f4d51 edtlib: allow const arrays
Allow for having array types (array, uint8-array, string-array) be const.
This would allow for something like:

properties:
    reg-names:
        const: ["foo", "bar"]

To be supported.

Renamed function _check_prop_type_and_default to _check_prop_by_type
as part of this change and Moved the check for 'const' types into
_check_prop_by_type as its similar to the prop_type check and it was
easier to implement in _check_prop_by_type as we already extract
prop_type from the option in that function.

Signed-off-by: Kumar Gala <galak@kernel.org>
2022-08-25 18:11:27 -07:00
Martí Bolívar
4ef8c8e447 edtlib: expose str_as_token() API
Some callers need to be able to convert strings to tokens in the same
way edtlib does. Make this possible by exposing the internal helper
function used to do that under a suitable name.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2022-07-18 17:50:44 -05:00
Martí Bolívar
19bb6b330c edtlib: fix error handling in an internal helper
The error message emitted by _interrupt_parent() is wrong; it
mistakenly says:

  node None has an 'interrupts' property, but [...]

This 'None' is appearing because the same routine overwrites the
'node' argument that the caller is asking about with node parents
until it hits the root, at which point root.parent is None.

Fix it by caching the original node and using that in the error
message instead.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2022-07-18 17:50:44 -05:00
Martí Bolívar
f6a6843471 python-devicetree: CI hotfix
Pin the types-PyYAML version to 6.0.7. Version 6.0.8 is causing CI
errors for other pull requests, so we need this in to get other PRs
moving.

Fixes: #46286

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2022-06-06 09:09:27 -07:00
Martí Bolívar
7c3b445323 edtlib: add Node.child_index()
It can be useful to know what the index of a particular child is in
the list of nodes. Add a a helper for computing that and some test
cases.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2022-03-24 10:48:40 +01:00
Martí Bolívar
6c65b15ce6 edtlib: wrap DTError
Don't let a malformed devicetree escape as a DTError. Wrap it in an
EDTError instead, so callers can just rely on the edtlib APIs as is
generally expected.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2021-12-07 13:39:37 -05:00
Martí Bolívar
7738977af4 dtlib: handle GCC linemarkers
A GCC linemarker of the form:

  # 1 "filename" 2 3 4

or so is not currently being handled, because the current regular
expression assumes the "flags" values (the numbers after "filename")
are limited to a single value. Tweak the regular expression to allow
for up to 4 flags, which is what GCC documents it may emit:

https://gcc.gnu.org/onlinedocs/gcc-10.2.0/cpp/Preprocessor-Output.html

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2021-12-07 13:39:37 -05:00
Martí Bolívar
4e783a363a dtlib: add _Token __repr__
Convert numeric IDs to symbolic token ID names for ease of debugging.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2021-12-07 13:39:37 -05:00
Neil Armstrong
2f4a6646cf edtlib: add tests to check Range property
This adds some tests in test_edtlib.py and test.dts to check all
common possible combination of ranges property usage and handling
by edtlib.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
2021-11-10 08:23:00 -05:00
Neil Armstrong
cd6a5648d7 edtlib: add Range property on Node, used for PCIe I/O and memory regions
As described in IEEE Std 1275-1994, the PCIe bindings uses the ranges
property to describe the PCI I/O and memory regions.

Add parsing of this property in edtlib.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
2021-11-10 08:23:00 -05:00
Carlo Caione
42105ed882 dts: Add support for specifier-space property.
Currently all the *-names and *-cells properties are derived from the
name of the base <name>s property. This is a limitation because:

- It forces the base property name to be plural ending in -s
- It doesn't allow the english exception of plural words ending in -es

With this patch we add one additional property 'specifier-space' that
can be used to explicitly specify the base property name.

Signed-off-by: Carlo Caione <ccaione@baylibre.com>
Suggested-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2021-10-13 09:56:46 -05:00
Martí Bolívar
ffa1515978 dtlib: fix issue which allowed invalid node names
Node names are subject to the rules in table 2.1 of the devicetree
specification v0.3, while properties are subject to rules in table
2.2. These rules mean that some property names are invalid node names.

However, the same regular expression is being used to validate the
names of nodes and properties in dtlib. This leads to invalid node
names being allowed to pass. Fix this issue by moving the node name
handling code to the Node constructor and checking against the
characters in table 2.1.

The test cases claim that the existing behavior matches dtc. I can't
reproduce that. I get errors when I use invalid characters (like "?")
in a node name. For example:

foo.dts:3.8-11: ERROR (node_name_chars): /node?: Bad character '?' in
node name

Try to make the dtlib error message reminiscent of that.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2021-08-31 19:36:31 -04:00
Martí Bolívar
fff818bbe6 dtlib: remove unused variable
This is unused since the very beginning of the module's introduction.
It looks like it was abandoned in favor of the approach where each
token can have only one capturing group.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2021-08-31 19:36:31 -04:00
Martí Bolívar
fa2e82becd edtlib: emit pinctrl names as tokens
This will be necessary to going back and forth between indexes and
names in C.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2021-08-25 18:09:00 -04:00
Martí Bolívar
6e9e984e60 dtlib: remove pylint suppression
This became useless when _init_tokens() was refactored not to use
global variables (in "dtlib: use IntEnum for token IDs"), and the
linter is complaining about it now.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2021-08-25 18:03:17 -04:00
Martí Bolívar
227ce89c41 edtlib: use f-strings where it makes sense
Similarly to what was done for dtlib, use f-strings in places where it
improves readability. Some places, e.g. __repr__ methods that
construct a string using something like

    "<SomeType, {}>".format(", ".join(...))

are better left off as-is.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2021-08-25 18:03:17 -04:00
Martí Bolívar
66ee3d291c dtlib: use f-strings where it makes sense
The library was originally developed before Python 3.6 was the minimum
supported version. Use f-strings now that we can do that, as they tend
to be easier to read.

There are a few places where str.format() makes sense to preserve,
specifically where the same argument is used multiple times; leave
those alone.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2021-08-25 18:03:17 -04:00
Martí Bolívar
2533246610 edtlib: tweak vendor prefixes implementation details
If the user passes None, set the internal attribute to an empty dict
instead. This lets us avoid some None checking and simplifies things
without changing semantics -- if the user *does* pass an empty dict,
the results are the same.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2021-08-20 18:57:30 -04:00
Martí Bolívar
d14835812c edtlib: allow .yml files too
This is a common extension for YAML files. We don't have to allow it
in upstream zephyr, but we should allow downstream DTS_ROOTs to have
this ability.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2021-08-20 18:57:30 -04:00
Martí Bolívar
9e8da8953c scripts: edtlib: fix werror for unknown vendor
Commit c4079e4be2
("scripts: rework edtlib warnings-turned-errors") was trying to abort
on unknown vendor prefix, but the error log is not fatal.

Fix it by using the same error handling function we use when aborting
due to deprecated property usage.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2021-08-17 17:51:57 -04:00
Martí Bolívar
e9229f1f2b scripts: edtlib: relax vendor check for root node
There are way too many one-off vendor prefixes set up for individual
boards to bother tracking them in vendor-prefixes.txt. As a practical
matter, the compatible for the root node doesn't matter anyway. So
just relax our check for that node.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2021-08-17 17:51:57 -04:00
Martí Bolívar
c4079e4be2 scripts: rework edtlib warnings-turned-errors
Create a "global" gen_defines.py option and edtlib.EDT constructor
kwarg that turns edtlib-specific warnings into errors. This applies to
edtlib-specific warnings only. Warnings that are just dupes of dtc
warnings are not affected.

Use it from twister to increase DT testing coverage in upstream zephyr.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2021-08-03 12:21:45 -05:00
Martí Bolívar
6719fae101 edtlib: warn on unrecognized vendors
An unknown vendor prefix is now a warning. We augment the list of
vendor prefixes passed by the user with a grandfathered-in bunch from
Linux.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2021-08-03 12:21:45 -05:00
Martí Bolívar
7b60fa3a15 edtlib: move vendor-prefixes.txt parsing in here
Take this helper from the doc tooling and expose it as API.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2021-08-03 12:21:45 -05:00
Martí Bolívar
4a313129b2 edtlib: only do compatible checks once
Remember the compatibles we've validated, and don't check them again.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2021-08-03 12:21:45 -05:00
Martí Bolívar
15db98a400 dtlib: allow dangling aliases with DT(..., force=True)
As a first step towards being more forgiving on invalid inputs, allow
string-valued aliases properties that do not point to valid nodes when
the user requests permissiveness.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2021-07-14 19:51:46 -04:00
Martí Bolívar
176225db58 dtlib: add force DT kwarg
Modeled after dtc's --force option, the idea is this will try harder
and harder over time to produce an object despite malformed input.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2021-07-14 19:51:46 -04:00
Casper Meijn
d25e5c20a0 scripts: dts: Produce error for invalid yaml
I made an alignment error in a dts binding, but the build was
successful. After some debugging I found the following warning
explaining the problem:

  '/home/casper/src/zephyrproject/zephyr/dts/bindings/gpio/
       gpio-keys.yaml' appears in binding directories but isn't valid
       YAML: while parsing a block mapping
    in "<unicode string>", line 11, column 8
  did not find expected key
    in "<unicode string>", line 18, column 9

I think this should be an error as there shouldn't be any invalid yaml.

Signed-off-by: Casper Meijn <casper@meijn.net>
2021-06-14 10:36:27 -05:00
Martí Bolívar
8875340db4 python-devicetree: tox: fix mypy
Recent versions of mypy have learned that the yaml module has type
stubs and the tool is now erroring out when it discovers we import
yaml since the stubs are not involved.

This is breaking CI on unrelated patches; fix it following the
instructions here:

https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2021-06-09 21:01:55 -04:00
Martí Bolívar
bd122e5ea2 edtlib: validate compatible properties
Error out on compatible properties with invalid values. The regular
expression used to validate them matches what's used in dt-schema.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2021-05-19 22:18:25 -05:00
Martí Bolívar
2e0d95f3cd devicetree: add mypy-based type checking
Extend the steps taken in tox.ini by type checking the 'devicetree'
package. This will make it easier for callers to type-check code that
uses the low level DT module's public APIs, since they can rely on
the type checker a bit more.

It will also help avoid bugs by adding some type checking for future
changes to this module.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2021-05-05 13:13:12 -05:00
Martí Bolívar
a8f7bfbbd4 edtlib: silence type checker issue
Mypy is complaining about this line for some reason I didn't have time
to figure out. Just shut it up for now; I'll look into this when I get
around to type annotating edtlib.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2021-05-05 13:13:12 -05:00
Martí Bolívar
8e30289b84 dtlib: type annotate DT fields and public methods
Now that all the other code it depends on is annotated, we can finish
up the type annotation of this module in the main DT class.

It's not worth it to try to annotate the private methods (the ones
that begin with '_'). Most of these are low level lexing helpers that
aren't particularly amenable to static type checking, because the type
of a token's value is often dependent on the token ID in ways that
static type annotations are not well equipped to capture.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2021-05-05 13:13:12 -05:00
Martí Bolívar
c6bb336bc1 dtlib: add type checking for DT.root
We'd like users of this API to know that DT.root is always a Node,
and not an Optional[Node].

However, although DT.__init__ throws an exception if the resulting DT
object would have no root node, static analysis can't tell that since
the root instance attribute starts out as None during initialization,
so checkers like mypy are convinced it's Optional[Node].

Since this is really OK, we'll quiet the type checker down by stashing
the instance attribute in self._root instead, and providing a root
property accessor that is annotated to return Node instead of
Optional[Node]. We can tell mypy to ignore what looks like a potential
None here to allow callers to treat the result as a Node.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2021-05-05 13:13:12 -05:00
Martí Bolívar
b13b5b8b3a dtlib: fix include_path edge case
The documentation says DT.__init__ takes any iterable for the
include_path, but this leads to bad results when you pass it something
other than a 'real' sequence (list/tuple/etc), like a generator:

>>> dt = DT('/tmp/foo.dts', (x for x in ['a', 'b', 'c']))
>>> repr(dt)
"DT(filename='/tmp/foo.dts', include_path=<generator object ...>)"

Make a copy in list form just to avoid things like this.

Add a test for this and relax the regular expression in the existing
test case related to this.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2021-05-05 13:13:12 -05:00
Martí Bolívar
628fb90412 dtlib: type annotate public functions
Some of these are also tripping up a python 2 / python 3 warning
in mypy in the way that '{}'.format(b'foo') works, which we silence by
explicitly requesting the python 3 behavior.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2021-05-05 13:13:12 -05:00
Martí Bolívar
9d4ccf23ec dtlib: use IntEnum for token IDs
The way that _init_tokens() is manipulating globals() defeats static
analyses of the file that are trying to infer a type for the 'tok_id'
variable in assignment expressions like 'tok_id = _T_INCLUDE'.

To make it easier on the analyser, define the token types as an
enum.IntEnum named _T. This means we can write e.g. '_T.INCLUDE'
instead of '_T_INCLUDE', avoiding line length increases in the lexing
code.

While we're here, use '==' and '!=' instead of 'is' and 'is not'
when comparing a tok_id that is obtained from an re.Match.lastindex
with a _T.FOO value.

This is now necessary since an int object and a _T object definitely
don't point to the same memory. It worked previously because CPython
interns all integer instances from -5 to 256, but that's an
implementation detail and not a language feature. Since we're getting
the ints from an re.Match.lastindex instead of putting the exact
_T_FOO values into some list, this code probably should not strictly
speaking have been using 'is'.

Explicitly initialize the global _token_re also, to make it more
visible for static analysis.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2021-05-05 13:13:12 -05:00
Martí Bolívar
8427259ca2 dtlib: type annotate Property class
Continue annotating the module. In some cases mypy will miss that
_err() calls means the function will not return, so we return an
unnecessary local variable to appease it.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2021-05-05 13:13:12 -05:00