Commit Graph

27 Commits

Author SHA1 Message Date
Martí Bolívar
2522eec578 scripts: testedtlib: add more child-binding tests
The child_binding object should default to having a path and
compatible that matches the parent's. Mark it as xfail because the
compatible part is failing.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2020-11-03 14:58:51 -06:00
Kumar Gala
33db7b5b01 scripts: edtlib: Add support for 'deprecated'
Add the ability to mark a property as 'deprecated' to get a warning that
it will be removed in the future.

Signed-off-by: Kumar Gala <kumar.gala@linaro.org>
2020-10-29 11:06:32 -05:00
Martí Bolívar
1ea7bf0db0 scripts: dts: fix handling for phandle-arrays with *-cells=0
Each controller node in a phandle-array may set the number of cells in
a specifier as any nonnegative integer. Currently, we don't allow
this in edtlib in the case where there are multiple controllers in a
phandle-array property all of which have 0 cells in the relevant
specifier, which is not correct. Fix this, add a regression test, and
improve the error message while we are here.

Fixes: #28709
Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
2020-10-06 12:05:37 -05:00
Kumar Gala
6bf761fc0a dts: Remove support for deprecated DTS binding syntax
We deprecated a number of aspects of the DTS binding syntax in Zephyr
2.1.  Remove the support for the deprecated syntax.  Remove from docs
about the deprecated syntax as well.

Removed reference in release-notes-2.1.rst to legacy_binding_syntax
since that anchor doesn't exist anymore.

Signed-off-by: Kumar Gala <kumar.gala@linaro.org>
2020-07-08 22:03:24 -04:00
Ulf Magnusson
23a5b4963b dts: edtlib: Add 'type: path' for path references
Add binding support for a 'path' property type, for properties that are
assigned node paths. Usually, paths are assigned with path references
like 'foo = &label' (common in /chosen), but plain strings are accepted
as well as long as they're valid paths.

The 'path' type is mostly for completeness at this point, but might be
useful for https://github.com/zephyrproject-rtos/zephyr/issues/21623.
The support is there already in dtlib.

Signed-off-by: Ulf Magnusson <Ulf.Magnusson@nordicsemi.no>
2020-01-08 08:02:00 -06:00
Ulf Magnusson
379145ffce scripts: edtlib: Rename 'child-bus:'/'parent-bus:' to 'bus:'/'on-bus:'
I keep mixing these up, so that's probably a sign that the names are
bad. The root of the problem is that "parent-bus" can be read as both
"this is the parent bus" and as "the parent bus is this".

Use 'bus:' for the bus "provider" and 'on-bus:' for nodes on the bus
instead, which is less confusing.

Support the old keys for backwards compatibility, along with a
deprecation warning.

Signed-off-by: Ulf Magnusson <Ulf.Magnusson@nordicsemi.no>
2019-12-19 11:02:28 +01:00
Ulf Magnusson
36b7ca44b8 scripts: edtlib.py: Deprecate 'title:'
Most bindings look something like this:

    title: Foo

    description: This binding provides a base representation of Foo

That kind of description doesn't add any useful information, as it's
just the title along with some copy-pasted text. I'm not sure what "base
representation" was supposed to mean originally either.

Many bindings also put something that's closer to a description in the
title, because it's not clear what's expected or how the title is used.
In reality, the title isn't used anywhere. 'description:' on the other
hand shows up as a comment in the generated header.

Deprecate 'title:' and generate a long informative warning if it shows
up in a binding.

Next commits will clean up the 'description:' strings (bringing them
closer to 'title:' in most cases) and remove 'title:' from all bindings.

Signed-off-by: Ulf Magnusson <Ulf.Magnusson@nordicsemi.no>
2019-12-18 11:52:45 +01:00
Ulf Magnusson
567c348167 scripts: dts: Generalize '#cells' to allow multiple sources
Implement a nice generalization suggested by Bobby Noelte.

Instead of having a generic #cells key in bindings, have source-specific
*-cells keys. Some examples:

    interrupt-cells:
        - irq
        - priority
        - flags

    gpio-cells:
        - pin
        - flags

    pwm-cells:
        - channel
        - period

This makes bindings a bit easier to read, and allows a node to be a
controller for many different 'phandle-array' properties.

The prefix before *-cells is derived from the property name, meaning
there's no fixed set of *-cells keys. This is possible because of the
earlier 'phandle-array' generalization.

The older #cells key is supported for backwards compatibility, but
generates a deprecation warning.

Signed-off-by: Ulf Magnusson <Ulf.Magnusson@nordicsemi.no>
2019-10-02 11:49:58 -07:00
Ulf Magnusson
b97ed9e4b4 scripts: dts: Generalize handling of phandle-array types
Generating generic information for 'type: phandle-array' properties in
edtlib was difficult due to defining phandle-array as just a list of
phandles and numbers. To make sense of a phandle-array property like
'pwms', you have to know that #pwm-cells is expected to appear on
each referenced controller, and that the binding for the controller has
a #cells.

Because of this, handling of various 'type: phandle-array' properties
was previously hardcoded in edtlib and exposed through properties like
Node.pwms, instead of through the generic Node.props (though with a lot
of shared code).

In practice, it turns out that all 'type: phandle-array' properties in
Zephyr work exactly the same way: They all have names that end in -s,
the 's' is removed to derive the name of related properties, and they
all look up #cells in the binding for the controller, which gives names
to the data values.

Strengthen the definition of 'type: phandle-array' to mean a property
that works exactly like the existing phandle-array properties (which
also means requiring that the name ends in -s). This removes a ton of
hardcoding from edtlib and allows new 'type: phandle-array' properties
to be added without making any code changes.

If we ever need a property type that's a list of phandles and numbers
but that doesn't follow this scheme, then we could add a separate type
for it. We should check if the standard scheme is fine first though.

The only property type for which no information is generated is now
'compound'.

There's some inconsistency in how we generate identifiers for clocks
compared to other 'type: phandle-array' properties, so keep
special-casing them for now in gen_defines.py (see the comment in
write_clocks()).

This change also enabled a bunch of other simplifications, like reusing
the ControllerAndData class for interrupts.

Piggyback generalization of *-map properties so that they work for any
phandle-array properties. It's now possible to have things like
'io-channel-map', if you need to.

Signed-off-by: Ulf Magnusson <Ulf.Magnusson@nordicsemi.no>
2019-09-26 15:30:23 -07:00
Ulf Magnusson
0b1ab4ab09 scripts: dts: Replace 'sub-node:' with more general 'child-binding:'
Deprecate 'sub-node:' and add a more general 'child-binding:' mechanism
to bindings. Keep supporting 'sub-node:', but print a deprecation
warning when it's used.

Like 'sub-node:', 'child-binding:' gives a binding to child nodes, but
the binding is required to be a complete binding, and is treated (and
checked) like a normal binding.

'child-binding:' can in turn contain another 'child-binding:', up to any
number of levels. This is automatic from treating it like a normal
binding, and from the code initializing parent Devices before child
Devices.

This lets nodes give bindings to grandchildren.

For example, take this devicetree fragment:

    parent {
            compatible = "foo";
            child-1 {
                    grandchild-1 {
                            ...
                    };
                    grandchild-2 {
                            ...
                    };
            };
            child-2 {
                    grandchild-3 {
                            ...
                    };
            };
    };

The binding for 'foo' could provide bindings for grandchild-1/2/3 like
this:

    compatible: "foo"

    # Binding for children
    child-binding:
        title: ...
        description: ...

        ...

        # Binding for grandchildren
        child-binding:
            title: ...
            description: ...

            properties:
                ...

Due to implementation issues with the old devicetree scripts, only two
levels of 'child-binding:' is supported for now. This limitation will go
away in Zephyr 2.2.

Piggyback shortening 'description:' and 'title:' in some bindings that
provide child bindings. This makes the generated header a bit neater.

Signed-off-by: Ulf Magnusson <Ulf.Magnusson@nordicsemi.no>
2019-09-19 08:39:22 -05:00
Ulf Magnusson
1ebe945643 scripts: dts: Change 'child/parent: bus: ...' to 'child/parent-bus:'
Instead of

    child:
        bus: foo

    parent:
        bus: bar

, have

    child-bus: foo

    parent-bus: bar

'bus' is the only key that ever appears under 'child' and 'parent'.

Support the old keys for backwards compatibility, with a deprecation
warning if they're used.

Also add 'child/parent-bus' tests to the edtlib test suite. It was
untested before.

I also considered putting more stuff under 'child' and 'parent', but
there's not much point when there's just a few keys I think. Top-level
stuff is cleaner and easier to read.

I'm planning to add a 'child-binding' key a bit later (like 'sub-node',
but more flexible), and child-* is consistent with that.

Also add an unrelated test-bindings/grandchild-3.yaml that was
accidentally left out earlier.

Signed-off-by: Ulf Magnusson <Ulf.Magnusson@nordicsemi.no>
2019-09-17 14:37:43 -05:00
Ulf Magnusson
2845d8f404 scripts: edtlib: Make order irrelevant when including multiple files
When foo.yaml set some property 'required: true' and bar.yaml set the
same property 'required: false', the check for changing
'required: false' to 'required: true' would raise an error for

    include: [bar.yaml, foo.yaml]

(with that particular order due to implementation details).

The order files are included in shouldn't matter. To fix it, change the
logic so that 'required' values are ORed together between included files
(so that 'required: true' is always respected), and remove the
'required' true-to-false check when merging included files.

Keep the true-to-false check when merging the (merged) included files
into the main binding (the binding with the 'include:' in it). This
might give a good organization, and the old scripts do it too.

Piggyback two fixes/cleanups:

 - 'compatible' should be allowed to appear in included files

 - No need to allow an 'inherits' key in _check_binding(), because
   it has been removed before then, when merging bindings

Signed-off-by: Ulf Magnusson <Ulf.Magnusson@nordicsemi.no>
2019-09-11 07:50:30 -05:00
Ulf Magnusson
ff1f75293e dts: edtlib: Support giving missing properties a default value
For missing optional properties, it can be handy to generate a default
value instead of no value, to cut down on #ifdefs.

Allow a default value to be specified in the binding, via a new
'default: <default value>' setting for properties in bindings.
Defaults are supported for both scalar and array types. YAML arrays are
used to specify the value for array types.

'default:' also appears in json-schema, with the same meaning.

Include misc. sanity checks, like the 'default' value matching 'type'.

The documentation changes in binding-template.yaml explain the syntax.

Suggested by Peter A. Bigot in
https://github.com/zephyrproject-rtos/zephyr/issues/17829.

Fixes: #17829
Signed-off-by: Ulf Magnusson <Ulf.Magnusson@nordicsemi.no>
2019-09-09 08:47:49 -05:00
Ulf Magnusson
a0fceff1a2 scripts: dts: Simplify and improve 'compatible' matching
Instead of

    properties:
        compatible:
            constraint: "foo"

, just have

    compatible: "foo"

at the top level of the binding.

For backwards compatibility, the old 'properties: compatible: ...' form
is still accepted for now, and is treated the same as a single-element
'compatible:'.

The old syntax was inspired by dt-schema (though it isn't
dt-schema-compatible), which is in turn a thin wrapper around
json-schema (the idea is to transform .dts files into YAML and then
verify them).

Maybe the idea was to gradually switch the syntax over to dt-schema and
then be able to use unmodified dt-schema bindings, but dt-schema is
really a different kind of tool (a completely standalone linter), and
works very differently from our stuff (see schemas/dt-core.yaml in the
dt-schema repo to get an idea of just how differently).

Better to keep it simple.

This commit also piggybacks some clarifications to the binding template
re. '#cells:'.

Signed-off-by: Ulf Magnusson <Ulf.Magnusson@nordicsemi.no>
2019-09-07 10:25:02 -05:00
Ulf Magnusson
8d317bc665 scripts: edtlib: Add backwards compatibility for 'category:'
Having backwards compatibility for !include and 'constraint:' is silly
without also having backwards compatibility for 'category:', because
that forces a binding change anyway.

Add backwards compatibility for 'category:', and just print a
deprecation warning when it's used.

Also move tests for deprecated features into a dedicated
test-bindings/deprecated.yaml binding, instead of piggybacking on other
tests.

Signed-off-by: Ulf Magnusson <Ulf.Magnusson@nordicsemi.no>
2019-09-07 10:25:02 -05:00
Ulf Magnusson
d834b69bd9 scripts: dts: Improve syntax and code for including binding files
Have

    include: foo.dts
    include: [foo.dts, bar.dts]

instead of

    inherits:
        !include foo.dts

    inherits:
        !include [foo.dts, bar.dts]

This is a nicer and shorter and less cryptic syntax, and will make it
possible to get rid of the custom PyYAML constructor for '!include'
later.

'inherits: !include ...' is still supported for backwards compatibility
for now. Later on, I'm planning to mass-replace it, add a deprecation
warning if it's used, and document 'include:'. Then the '!include'
implementation can be removed a bit later.

'!include' has caused issues in the past (see the comment above the
add_constructor() call), gets iffy with multiple EDT instances, and
makes the code harder to follow.

I'm guessing '!include' might've been intended to be useful outside of
'inherits:' originally, but that's the only place where it's used. It's
undocumented that it's possible to put it elsewhere.

To implement the backwards compatibility, the code just transforms

    inherits:
        !include foo.dts

into

    inherits:
        - foo.dts

and treats 'inherits:' similarly to 'include:'. Previously, !include
inserted the contents of the included file instead.

Some more sanity checks for 'include:'/'inherits:' are included as well.

Signed-off-by: Ulf Magnusson <Ulf.Magnusson@nordicsemi.no>
2019-09-07 10:25:02 -05:00
Ulf Magnusson
fcd665a26c dts: bindings: Have 'required: true/false' instead of 'category: ...'
The 'category: required/optional' setting for properties is just a
yes/no thing. Using a boolean makes it clearer, so have
'required: true/false' instead.

Print a clear error when 'category:' is used:

    edtlib.EDTError: please put 'required: true' instead of 'category:
    required' in 'properties: foo: ...' in
    test-bindings/sub-node-parent.yaml - 'category' has been removed

The old scripts in scripts/dts/ ignore this setting, and only print a
warning if 'category: required' in an inherited binding is changed to
'category: optional'. Remove that code, since the new scripts already
have the same check.

The replacement was done with

    git ls-files 'dts/bindings/*.yaml' | xargs sed -i \
        -e 's/category:\s*required/required: true/' \
        -e 's/category:\s*optional/required: false/'

dts/binding-template.yaml is updated as well.

Signed-off-by: Ulf Magnusson <Ulf.Magnusson@nordicsemi.no>
2019-09-07 10:25:02 -05:00
Ulf Magnusson
14138c3b9b dts: edtlib: Improve how we get the compatible string from bindings
Use Galak's idea from
https://github.com/zephyrproject-rtos/zephyr/pull/18313 to read the
'properties: compatible: constraint: "foo"' string from bindings in a
more robust way.

First, check if any of the compatible strings are in the file (needed as
an optimization). If any of them are, do a more careful check for the
'properties: compatible: constraint: ...' value matching a compatible,
to filter out false positives from comments and the like.

This commit a no-op in itself besides making things a bit more robust,
but it'll make later work easier (supporting multiple compatibles for a
binding, in a dt-schema-like way).

Co-authored-by: Kumar Gala <kumar.gala@linaro.org>
Signed-off-by: Ulf Magnusson <Ulf.Magnusson@nordicsemi.no>
2019-09-07 10:25:02 -05:00
Ulf Magnusson
1480ad9ce7 dts: edtlib: Sanity-check the final merged binding only
Sanity-checking each !included file separately was inherited from the
old scripts. It makes it messy to check that combinations of fields make
sense, e.g. to check 'const:' or 'default:' against 'type:', since those
fields might come from different files (this is handy, since it makes
sense to just add/change a 'const:' value, for example).

Drop the requirement that each !included file is a complete binding in
itself, and treat them as binding fragments instead. Only check the
final merged binding.

This also means that !included files no longer need to have a
'description:' or 'title:' (those have always been unused for !included
files), so remove those, and add comments that explain what the
fragments are for instead. That should demystify bindings a bit.

Also fix the descriptions of i2c.yaml, i2s.yaml, spi.yaml, and
uart.yaml. They're for controllers, not devices. These are copy-paste
error from the corresponding device .yaml files.

Piggyback some indentation consistency nits in binding-template.yaml.

Signed-off-by: Ulf Magnusson <Ulf.Magnusson@nordicsemi.no>
2019-09-07 10:25:02 -05:00
Ulf Magnusson
c42873fbe7 dts: dtlib/edtlib: Add phandle and phandle+nums array types
Add two new type-checked property types 'phandles' and 'phandle-array'
to edtlib.

'phandles' is for pure lists of phandles, with no other data, like

    foo = < &bar &baz ... >

'phandle-array' is for lists of phandles and (possibly) numbers, like

    foo = < &bar 1 2 &baz 3 4 ... >

dt-schema also has the 'phandle-array' type.

Property.val (in edtlib) is set to an array of Device objects for the
'phandles' type.

For the 'phandle-array' type, no Property object is created. This type
is only used for type checking.

Also refactor how types that do not create a Property object
('phandle-array' and 'compound') are handled. Have _prop_val() return
None for them.

The new types are implemented with two new TYPE_PHANDLES and
TYPE_PHANDLES_AND_NUMS types at the dtlib level. There is also a new
Property.to_nodes() functions for fetching the Nodes for an array of
phandles, with type checking.

Signed-off-by: Ulf Magnusson <Ulf.Magnusson@nordicsemi.no>
2019-09-07 10:25:02 -05:00
Ulf Magnusson
e703b4954a dts: edtlib: Sanity-check contents of 'sub-node:'
The contents of 'sub-node:' was assigned as-is as the binding, bypassing
_check_binding(). This also hid an error in
test-bindings/sub-node-parent.yaml.

Require 'sub-node:' to just have 'properties:' in it, and sanity-check
the properties like for regular bindings.

Signed-off-by: Ulf Magnusson <Ulf.Magnusson@nordicsemi.no>
2019-09-07 10:25:02 -05:00
Kumar Gala
3d14374c5e scripts/dts/edtlib.py: add 'const' support to bindings
Add a 'const' property to bindings for any properties that are expected
to have a specifi known value.  For example, #address-cells for an I2C
bus should always be '1'.  So we can do something like the following in
the I2C bus binding:

    "#address-cells":
      type: int
      category: required
      const: 1

Signed-off-by: Kumar Gala <kumar.gala@linaro.org>
Signed-off-by: Ulf Magnusson <Ulf.Magnusson@nordicsemi.no>
2019-09-07 10:25:02 -05:00
Ulf Magnusson
06b746cc58 dts: dtlib/edtlib: Add a syntax-based type-checking system
Property type-checking has been pretty rudimentary until now, only
checking things like the length being divisible by 4 for 'type: array',
and strings being null-terminated. In particular, no checking was done
for 'type: uint8-array', letting

  jedec-id = < 0xc8 0x28 0x17 >;

slip through when

  jedec-id = [ 0xc8 0x28 0x17 ];

was intended.

Fix it by adding a syntax-based type checker:

  1. Add Property.type, which gives a high-level type for the property,
     derived from the markers added in the previous commit.

     This includes types like TYPE_EMPTY ('foo;'),
     TYPE_NUM ('foo = < 3 >;'), TYPE_BYTES ('foo = [ 01 02 ];'),
     TYPE_STRINGS ('foo = "bar", "baz"'),
     TYPE_PHANDLE ('foo = < &bar >;'), and TYPE_COMPOUND (everything not
     recognized).

     See the Property.type docstring in dtlib for more info.

  2. Use the high-level type in
     Property.to_num()/to_string()/to_node()/etc. to verify that the
     property was assigned in an expected way for the type.

     If the assignment looks bad, give a helpful error:

       expected property 'nums' on /foo/bar in some.dts to be assigned
       with 'nums = < (number) (number) ... >', not 'nums = "oops";'

Some other related changes are included as well:

  - There's a new Property.to_bytes() function that works like accessing
    Property.bytes, except with an added check for the value being
    assigned like 'foo = [ ... ]'.

    This function solves problems like the jedec-id one.

  - There's a new Property.to_path() function for fetching the
    referenced node for assignments like 'foo = &node;', with type
    checking. (Strings are accepted too, as long as they give the path
    to an existing node.)

    This function is used for /chosen and /aliases.

  - A new 'type: phandle' type can now be given in bindings, for
    properties that are assigned like 'foo = < &node >;'.

  - Property.__str__() now displays phandles and path references as they
    were written (e.g. '< &foo >' instead of '< 0x1 >', if the
    allocated phandle happened to be 1).

  - Property.to_num() and Property.to_nums() no longer take a 'length'
    parameter, because it makes no sense with the type checking.

  - The global dtlib.to_string() and dtlib.to_strings() functions were
    removed, because they're not that useful.

  - More tests were added, along with misc. minor cleanup in various
    places.

  - Probably other stuff I forgot.

The more strict type checking in dtlib indirectly makes some parts of
edtlib more strict as well (wherever Property.to_*() is used).

Fixes: #18131

Signed-off-by: Ulf Magnusson <Ulf.Magnusson@nordicsemi.no>
2019-08-13 07:41:45 -05:00
Jim Paris
998d7a01dd scripts/dts: add basic test for IO channel property
Test the new io-channel support

Signed-off-by: Jim Paris <jim@jtan.com>
2019-08-09 13:16:09 -05:00
Ulf Magnusson
75391c4f2c dts: edtlib: Shorten some license headers
One line instead of three.

Signed-off-by: Ulf Magnusson <Ulf.Magnusson@nordicsemi.no>
2019-08-09 00:03:19 -05:00
Ulf Magnusson
fe2d858b5f scripts: dts: Add test for multiple binding directories
Add two bindings

    test-bindings/multidir.yaml
    test-bindings-2/multidir.yaml

and a new test-multidir.dts with two nodes that use them.

Verify that the two bindings were found by checking the
Device.binding_path attribute for the two device nodes.

Signed-off-by: Ulf Magnusson <Ulf.Magnusson@nordicsemi.no>
2019-08-03 14:17:49 -04:00
Ulf Magnusson
62d5741476 dts: Add new DTS/binding parser
Add a new DTS/binding parser to scripts/dts/ for generating
generated_dts_board.conf and generated_dts_board_unfixed.h.

The old code is kept to generate some deprecated defines, using the
--deprecated-only flag. It will be removed later.

The new parser is implemented in three files in scripts/dts/:

dtlib.py:
  A low-level .dts parsing library. This is similar to devicetree.py in
  the old code, but is a general robust DTS parser that doesn't rely on
  preprocessing.

edtlib.py (e for extended):
  A library built on top of dtlib.py that brings together data from DTS
  files and bindings and creates Device instances with all the data for
  a device.

gen_defines.py:
  A script that uses edtlib.py to generate generated_dts_board.conf and
  generated_dts_board_unfixed.h. Corresponds to extract_dts_includes.py
  and the files in extract/ in the old code.

testdtlib.py:
  Test suite for dtlib.py. Can be run directly as a script.

testedtlib.py (uses test.dts and test-bindings/):
  Test suite for edtlib.py. Can be run directly as a script.

The test suites will be run automatically in CI.

The new code turns some things that were warnings (or not checked) in
the old code into errors, like missing properties that are specified
with 'category: required' in the binding for the node.

The code includes lots of documentation and tries to give helpful error
messages instead of Python errors.

Co-authored-by: Kumar Gala <kumar.gala@linaro.org>
Signed-off-by: Ulf Magnusson <Ulf.Magnusson@nordicsemi.no>
2019-07-29 16:22:17 -04:00