2018-12-17 20:09:47 +01:00
#!/usr/bin/env python3
# Copyright (c) 2019 Nordic Semiconductor ASA
# SPDX-License-Identifier: BSD-3-Clause
2019-09-28 15:03:45 +02:00
import io
2020-01-09 07:03:42 +01:00
import os
2019-09-20 00:21:03 +02:00
import sys
2018-12-17 20:09:47 +01:00
import edtlib
2019-09-21 04:14:33 +02:00
# Test suite for edtlib.py. Run it directly as an executable, in this
# directory:
2018-12-17 20:09:47 +01:00
#
2019-09-21 04:14:33 +02:00
# $ ./testedtlib.py
2018-12-17 20:09:47 +01:00
#
2020-01-09 07:03:42 +01:00
# test.dts is the main test file. test-bindings/ and test-bindings-2/ has
# bindings. The tests mostly use string comparisons via the various __repr__()
# methods.
2018-12-17 20:09:47 +01:00
def run ( ) :
"""
Runs all edtlib tests . Immediately exits with status 1 and a message on
stderr on test suite failures .
"""
2019-09-28 15:03:45 +02:00
warnings = io . StringIO ( )
edt = edtlib . EDT ( " test.dts " , [ " test-bindings " ] , warnings )
# Deprecated features are tested too, which generate warnings. Verify them.
2019-10-03 05:28:52 +02:00
verify_eq ( warnings . getvalue ( ) , """ \
2019-09-28 15:03:45 +02:00
warning : The ' properties: compatible: constraint: ... ' way of specifying the compatible in test - bindings / deprecated . yaml is deprecated . Put ' compatible: " deprecated " ' at the top level of the binding instead .
warning : the ' inherits: ' syntax in test - bindings / deprecated . yaml is deprecated and will be removed - please use ' include: foo.yaml ' or ' include: [foo.yaml, bar.yaml] ' instead
2019-11-19 10:38:25 +01:00
warning : ' title: ' in test - bindings / deprecated . yaml is deprecated and will be removed ( and was never used ) . Just put a ' description: ' that describes the device instead . Use other bindings as a reference , and note that all bindings were updated recently . Think about what information would be useful to other people ( e . g . explanations of acronyms , or datasheet links ) , and put that in as well . The description text shows up as a comment in the generated header . See yaml - multiline . info for how to deal with multiple lines . You probably want ' description: | ' .
2019-09-28 15:03:45 +02:00
warning : please put ' required: true ' instead of ' category: required ' in properties : required : . . . ' in test-bindings/deprecated.yaml - ' category ' will be removed
warning : please put ' required: false ' instead of ' category: optional ' in properties : optional : . . . ' in test-bindings/deprecated.yaml - ' category ' will be removed
warning : ' sub-node: properties: ... ' in test - bindings / deprecated . yaml is deprecated and will be removed - please give a full binding for the child node in ' child-binding: ' instead ( see binding - template . yaml )
warning : " #cells: " in test - bindings / deprecated . yaml is deprecated and will be removed - please put ' interrupt-cells: ' , ' pwm-cells: ' , ' gpio-cells: ' , etc . , instead . The name should match the name of the corresponding phandle - array property ( see binding - template . yaml )
""" )
2018-12-17 20:09:47 +01:00
#
# Test interrupts
#
2019-09-23 05:14:18 +02:00
verify_streq ( edt . get_node ( " /interrupt-parent-test/node " ) . interrupts ,
2019-11-12 18:33:00 +01:00
" [<ControllerAndData, name: foo, controller: <Node /interrupt-parent-test/controller in ' test.dts ' , binding test-bindings/interrupt-3-cell.yaml>, data: OrderedDict([( ' one ' , 1), ( ' two ' , 2), ( ' three ' , 3)])>, <ControllerAndData, name: bar, controller: <Node /interrupt-parent-test/controller in ' test.dts ' , binding test-bindings/interrupt-3-cell.yaml>, data: OrderedDict([( ' one ' , 4), ( ' two ' , 5), ( ' three ' , 6)])>] " )
2018-12-17 20:09:47 +01:00
2019-09-23 05:14:18 +02:00
verify_streq ( edt . get_node ( " /interrupts-extended-test/node " ) . interrupts ,
2019-11-12 18:33:00 +01:00
" [<ControllerAndData, controller: <Node /interrupts-extended-test/controller-0 in ' test.dts ' , binding test-bindings/interrupt-1-cell.yaml>, data: OrderedDict([( ' one ' , 1)])>, <ControllerAndData, controller: <Node /interrupts-extended-test/controller-1 in ' test.dts ' , binding test-bindings/interrupt-2-cell.yaml>, data: OrderedDict([( ' one ' , 2), ( ' two ' , 3)])>, <ControllerAndData, controller: <Node /interrupts-extended-test/controller-2 in ' test.dts ' , binding test-bindings/interrupt-3-cell.yaml>, data: OrderedDict([( ' one ' , 4), ( ' two ' , 5), ( ' three ' , 6)])>] " )
2018-12-17 20:09:47 +01:00
2019-09-23 05:14:18 +02:00
verify_streq ( edt . get_node ( " /interrupt-map-test/node@0 " ) . interrupts ,
2019-11-12 18:33:00 +01:00
" [<ControllerAndData, controller: <Node /interrupt-map-test/controller-0 in ' test.dts ' , binding test-bindings/interrupt-1-cell.yaml>, data: OrderedDict([( ' one ' , 0)])>, <ControllerAndData, controller: <Node /interrupt-map-test/controller-1 in ' test.dts ' , binding test-bindings/interrupt-2-cell.yaml>, data: OrderedDict([( ' one ' , 0), ( ' two ' , 1)])>, <ControllerAndData, controller: <Node /interrupt-map-test/controller-2 in ' test.dts ' , binding test-bindings/interrupt-3-cell.yaml>, data: OrderedDict([( ' one ' , 0), ( ' two ' , 0), ( ' three ' , 2)])>] " )
2018-12-17 20:09:47 +01:00
2019-09-23 05:14:18 +02:00
verify_streq ( edt . get_node ( " /interrupt-map-test/node@1 " ) . interrupts ,
2019-11-12 18:33:00 +01:00
" [<ControllerAndData, controller: <Node /interrupt-map-test/controller-0 in ' test.dts ' , binding test-bindings/interrupt-1-cell.yaml>, data: OrderedDict([( ' one ' , 3)])>, <ControllerAndData, controller: <Node /interrupt-map-test/controller-1 in ' test.dts ' , binding test-bindings/interrupt-2-cell.yaml>, data: OrderedDict([( ' one ' , 0), ( ' two ' , 4)])>, <ControllerAndData, controller: <Node /interrupt-map-test/controller-2 in ' test.dts ' , binding test-bindings/interrupt-3-cell.yaml>, data: OrderedDict([( ' one ' , 0), ( ' two ' , 0), ( ' three ' , 5)])>] " )
2018-12-17 20:09:47 +01:00
2019-09-23 05:14:18 +02:00
verify_streq ( edt . get_node ( " /interrupt-map-bitops-test/node@70000000E " ) . interrupts ,
2019-11-12 18:33:00 +01:00
" [<ControllerAndData, controller: <Node /interrupt-map-bitops-test/controller in ' test.dts ' , binding test-bindings/interrupt-2-cell.yaml>, data: OrderedDict([( ' one ' , 3), ( ' two ' , 2)])>] " )
2019-08-07 15:21:12 -04:00
2018-12-17 20:09:47 +01:00
#
# Test 'reg'
#
2019-09-23 05:14:18 +02:00
verify_streq ( edt . get_node ( " /reg-zero-address-cells/node " ) . regs ,
2018-12-17 20:09:47 +01:00
" [<Register, addr: 0x0, size: 0x1>, <Register, addr: 0x0, size: 0x2>] " )
2019-09-23 05:14:18 +02:00
verify_streq ( edt . get_node ( " /reg-zero-size-cells/node " ) . regs ,
2018-12-17 20:09:47 +01:00
" [<Register, addr: 0x1, size: 0x0>, <Register, addr: 0x2, size: 0x0>] " )
2019-09-23 05:14:18 +02:00
verify_streq ( edt . get_node ( " /reg-ranges/parent/node " ) . regs ,
2018-12-17 20:09:47 +01:00
" [<Register, addr: 0x5, size: 0x1>, <Register, addr: 0xe0000000f, size: 0x1>, <Register, addr: 0xc0000000e, size: 0x1>, <Register, addr: 0xc0000000d, size: 0x1>, <Register, addr: 0xa0000000b, size: 0x1>, <Register, addr: 0x0, size: 0x1>] " )
2019-09-23 05:14:18 +02:00
verify_streq ( edt . get_node ( " /reg-nested-ranges/grandparent/parent/node " ) . regs ,
2018-12-17 20:09:47 +01:00
" [<Register, addr: 0x30000000200000001, size: 0x1>] " )
2019-10-30 16:05:30 +01:00
#
# Test 'pinctrl-<index>'
#
verify_streq ( edt . get_node ( " /pinctrl/dev " ) . pinctrls ,
" [<PinCtrl, name: zero, configuration nodes: []>, <PinCtrl, name: one, configuration nodes: [<Node /pinctrl/pincontroller/state-1 in ' test.dts ' , no binding>]>, <PinCtrl, name: two, configuration nodes: [<Node /pinctrl/pincontroller/state-1 in ' test.dts ' , no binding>, <Node /pinctrl/pincontroller/state-2 in ' test.dts ' , no binding>]>] " )
2019-09-21 04:14:33 +02:00
#
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-23 09:10:22 +02:00
# Test Node.parent and Node.children
2019-09-21 04:14:33 +02:00
#
2019-09-23 05:14:18 +02:00
verify_eq ( edt . get_node ( " / " ) . parent , None )
2019-09-21 04:14:33 +02:00
2019-09-23 05:14:18 +02:00
verify_streq ( edt . get_node ( " /parent/child-1 " ) . parent ,
" <Node /parent in ' test.dts ' , no binding> " )
2019-09-21 04:14:33 +02:00
2019-09-23 05:14:18 +02:00
verify_streq ( edt . get_node ( " /parent/child-2/grandchild " ) . parent ,
" <Node /parent/child-2 in ' test.dts ' , no binding> " )
2019-09-21 04:14:33 +02:00
2019-09-23 05:14:18 +02:00
verify_streq ( edt . get_node ( " /parent " ) . children ,
2019-11-12 18:33:00 +01:00
" OrderedDict([( ' child-1 ' , <Node /parent/child-1 in ' test.dts ' , no binding>), ( ' child-2 ' , <Node /parent/child-2 in ' test.dts ' , no binding>)]) " )
2019-09-21 04:14:33 +02:00
2019-09-23 05:14:18 +02:00
verify_eq ( edt . get_node ( " /parent/child-1 " ) . children , { } )
2019-09-21 04:14:33 +02:00
2018-12-17 20:09:47 +01:00
#
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-08-21 16:41:03 +02:00
# Test 'include:' and the legacy 'inherits: !include ...'
2018-12-17 20:09:47 +01:00
#
2019-09-23 05:14:18 +02:00
verify_streq ( edt . get_node ( " /binding-include " ) . description ,
2018-12-17 20:09:47 +01:00
" Parent binding " )
2019-09-23 05:14:18 +02:00
verify_streq ( edt . get_node ( " /binding-include " ) . props ,
2019-11-12 18:33:00 +01:00
" OrderedDict([( ' foo ' , <Property, name: foo, type: int, value: 0>), ( ' bar ' , <Property, name: bar, type: int, value: 1>), ( ' baz ' , <Property, name: baz, type: int, value: 2>), ( ' qaz ' , <Property, name: qaz, type: int, value: 3>)]) " )
2018-12-17 20:09:47 +01:00
2019-09-16 16:42:18 +02:00
#
2019-11-26 22:19:55 +01:00
# Test 'bus:' and 'on-bus:'
2019-09-16 16:42:18 +02:00
#
scripts: edtlib: Support nested nodes on buses
For the following devicetree, view 'nested' as being on the bus.
Previously, only 'node' was considered to be on the bus.
some-bus {
compatible = "foo,bus-controller";
node {
nested {
compatible = "foo,device-on-bus";
};
};
};
In practice, this means that a 'bus:' key in the binding for
'foo,bus-controller' will now get matched up to an 'on-bus:' key in the
binding for 'foo,device-on-bus'.
Change the meaning of Node.bus and add two new attributes Node.on_bus
and Node.bus_node, with these meanings:
Node.bus:
The bus type (as a string) if the node is a bus controller, and
None otherwise
Node.on_bus:
The bus type (as a string) if the node appears on a bus, and None
otherwise. The bus type is determined from the closest parent
that's a bus controller.
Node.bus_node:
The node for the bus controller if the node appears on a bus, and
None otherwise
It's a bit redundant to have both Node.bus_node and Node.on_bus, since
Node.on_bus is the same as Node.bus_node.bus, but Node.on_bus is pretty
handy to save some None checks.
Also update gen_defines.py to use Node.on_bus and Node.bus_node instead
of Node.parent wherever the code deals with buses.
Signed-off-by: Ulf Magnusson <Ulf.Magnusson@nordicsemi.no>
2019-11-27 04:08:36 +01:00
verify_eq ( edt . get_node ( " /buses/foo-bus " ) . bus , " foo " )
# foo-bus does not itself appear on a bus
verify_eq ( edt . get_node ( " /buses/foo-bus " ) . on_bus , None )
verify_eq ( edt . get_node ( " /buses/foo-bus " ) . bus_node , None )
# foo-bus/node is not a bus node...
verify_eq ( edt . get_node ( " /buses/foo-bus/node " ) . bus , None )
# ...but is on a bus
verify_eq ( edt . get_node ( " /buses/foo-bus/node " ) . on_bus , " foo " )
verify_eq ( edt . get_node ( " /buses/foo-bus/node " ) . bus_node . path ,
" /buses/foo-bus " )
# Same compatible string, but different bindings from being on different
# buses
2019-09-23 05:14:18 +02:00
verify_streq ( edt . get_node ( " /buses/foo-bus/node " ) . binding_path ,
2019-09-16 16:42:18 +02:00
" test-bindings/device-on-foo-bus.yaml " )
2019-09-23 05:14:18 +02:00
verify_streq ( edt . get_node ( " /buses/bar-bus/node " ) . binding_path ,
2019-09-16 16:42:18 +02:00
" test-bindings/device-on-bar-bus.yaml " )
scripts: edtlib: Support nested nodes on buses
For the following devicetree, view 'nested' as being on the bus.
Previously, only 'node' was considered to be on the bus.
some-bus {
compatible = "foo,bus-controller";
node {
nested {
compatible = "foo,device-on-bus";
};
};
};
In practice, this means that a 'bus:' key in the binding for
'foo,bus-controller' will now get matched up to an 'on-bus:' key in the
binding for 'foo,device-on-bus'.
Change the meaning of Node.bus and add two new attributes Node.on_bus
and Node.bus_node, with these meanings:
Node.bus:
The bus type (as a string) if the node is a bus controller, and
None otherwise
Node.on_bus:
The bus type (as a string) if the node appears on a bus, and None
otherwise. The bus type is determined from the closest parent
that's a bus controller.
Node.bus_node:
The node for the bus controller if the node appears on a bus, and
None otherwise
It's a bit redundant to have both Node.bus_node and Node.on_bus, since
Node.on_bus is the same as Node.bus_node.bus, but Node.on_bus is pretty
handy to save some None checks.
Also update gen_defines.py to use Node.on_bus and Node.bus_node instead
of Node.parent wherever the code deals with buses.
Signed-off-by: Ulf Magnusson <Ulf.Magnusson@nordicsemi.no>
2019-11-27 04:08:36 +01:00
# foo-bus/node/nested also appears on the foo-bus bus
verify_eq ( edt . get_node ( " /buses/foo-bus/node/nested " ) . on_bus , " foo " )
verify_streq ( edt . get_node ( " /buses/foo-bus/node/nested " ) . binding_path ,
" test-bindings/device-on-foo-bus.yaml " )
2018-12-17 20:09:47 +01:00
#
2019-09-17 18:24:30 +02:00
# Test 'child-binding:'
2018-12-17 20:09:47 +01:00
#
2019-09-23 05:14:18 +02:00
child1 = edt . get_node ( " /child-binding/child-1 " )
child2 = edt . get_node ( " /child-binding/child-2 " )
grandchild = edt . get_node ( " /child-binding/child-1/grandchild " )
2018-12-17 20:09:47 +01:00
2019-09-17 18:24:30 +02:00
verify_streq ( child1 . binding_path , " test-bindings/child-binding.yaml " )
verify_streq ( child1 . description , " child node " )
2019-11-12 18:33:00 +01:00
verify_streq ( child1 . props , " OrderedDict([( ' child-prop ' , <Property, name: child-prop, type: int, value: 1>)]) " )
2019-09-17 18:24:30 +02:00
verify_streq ( child2 . binding_path , " test-bindings/child-binding.yaml " )
verify_streq ( child2 . description , " child node " )
2019-11-12 18:33:00 +01:00
verify_streq ( child2 . props , " OrderedDict([( ' child-prop ' , <Property, name: child-prop, type: int, value: 3>)]) " )
2019-09-17 18:24:30 +02:00
verify_streq ( grandchild . binding_path , " test-bindings/child-binding.yaml " )
verify_streq ( grandchild . description , " grandchild node " )
2019-11-12 18:33:00 +01:00
verify_streq ( grandchild . props , " OrderedDict([( ' grandchild-prop ' , <Property, name: grandchild-prop, type: int, value: 2>)]) " )
2019-09-17 18:24:30 +02:00
#
2019-09-26 20:34:13 +02:00
# Test deprecated 'sub-node' key (replaced with 'child-binding') and
# deprecated '#cells' key (replaced with '*-cells')
2019-09-17 18:24:30 +02:00
#
2019-09-23 05:14:18 +02:00
verify_streq ( edt . get_node ( " /deprecated/sub-node " ) . props ,
2019-11-12 18:33:00 +01:00
" OrderedDict([( ' foos ' , <Property, name: foos, type: phandle-array, value: [<ControllerAndData, controller: <Node /deprecated in ' test.dts ' , binding test-bindings/deprecated.yaml>, data: OrderedDict([( ' foo ' , 1), ( ' bar ' , 2)])>]>)]) " )
2018-12-17 20:09:47 +01:00
2020-01-28 04:46:12 +01:00
#
# Test EDT.compat2enabled
#
verify_streq ( edt . compat2enabled [ " compat2enabled " ] , " [<Node /compat2enabled/foo-1 in ' test.dts ' , no binding>, <Node /compat2enabled/foo-2 in ' test.dts ' , no binding>] " )
if " compat2enabled-disabled " in edt . compat2enabled :
fail ( " ' compat2enabled-disabled ' should not appear in edt.compat2enabled " )
2018-12-17 20:09:47 +01:00
#
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-23 09:10:22 +02:00
# Test Node.props (derived from DT and 'properties:' in the binding)
#
verify_streq ( edt . get_node ( " /props " ) . props [ " int " ] ,
" <Property, name: int, type: int, value: 1> " )
verify_streq ( edt . get_node ( " /props " ) . props [ " existent-boolean " ] ,
" <Property, name: existent-boolean, type: boolean, value: True> " )
verify_streq ( edt . get_node ( " /props " ) . props [ " nonexistent-boolean " ] ,
" <Property, name: nonexistent-boolean, type: boolean, value: False> " )
verify_streq ( edt . get_node ( " /props " ) . props [ " array " ] ,
" <Property, name: array, type: array, value: [1, 2, 3]> " )
verify_streq ( edt . get_node ( " /props " ) . props [ " uint8-array " ] ,
r " <Property, name: uint8-array, type: uint8-array, value: b ' \ x124 ' > " )
verify_streq ( edt . get_node ( " /props " ) . props [ " string " ] ,
" <Property, name: string, type: string, value: ' foo ' > " )
verify_streq ( edt . get_node ( " /props " ) . props [ " string-array " ] ,
" <Property, name: string-array, type: string-array, value: [ ' foo ' , ' bar ' , ' baz ' ]> " )
verify_streq ( edt . get_node ( " /props " ) . props [ " phandle-ref " ] ,
" <Property, name: phandle-ref, type: phandle, value: <Node /props/ctrl-1 in ' test.dts ' , binding test-bindings/phandle-array-controller-1.yaml>> " )
verify_streq ( edt . get_node ( " /props " ) . props [ " phandle-refs " ] ,
" <Property, name: phandle-refs, type: phandles, value: [<Node /props/ctrl-1 in ' test.dts ' , binding test-bindings/phandle-array-controller-1.yaml>, <Node /props/ctrl-2 in ' test.dts ' , binding test-bindings/phandle-array-controller-2.yaml>]> " )
verify_streq ( edt . get_node ( " /props " ) . props [ " phandle-array-foos " ] ,
2019-11-12 18:33:00 +01:00
" <Property, name: phandle-array-foos, type: phandle-array, value: [<ControllerAndData, controller: <Node /props/ctrl-1 in ' test.dts ' , binding test-bindings/phandle-array-controller-1.yaml>, data: OrderedDict([( ' one ' , 1)])>, <ControllerAndData, controller: <Node /props/ctrl-2 in ' test.dts ' , binding test-bindings/phandle-array-controller-2.yaml>, data: OrderedDict([( ' one ' , 2), ( ' two ' , 3)])>]> " )
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-23 09:10:22 +02:00
verify_streq ( edt . get_node ( " /props " ) . props [ " foo-gpios " ] ,
2019-11-12 18:33:00 +01:00
" <Property, name: foo-gpios, type: phandle-array, value: [<ControllerAndData, controller: <Node /props/ctrl-1 in ' test.dts ' , binding test-bindings/phandle-array-controller-1.yaml>, data: OrderedDict([( ' gpio-one ' , 1)])>]> " )
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-23 09:10:22 +02:00
2019-12-30 22:52:11 +01:00
verify_streq ( edt . get_node ( " /props " ) . props [ " path " ] ,
" <Property, name: path, type: path, value: <Node /props/ctrl-1 in ' test.dts ' , binding test-bindings/phandle-array-controller-1.yaml>> " )
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-23 09:10:22 +02:00
#
# Test <prefix>-map, via gpio-map (the most common case)
2018-12-17 20:09:47 +01:00
#
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-23 09:10:22 +02:00
verify_streq ( edt . get_node ( " /gpio-map/source " ) . props [ " foo-gpios " ] ,
2019-11-12 18:33:00 +01:00
" <Property, name: foo-gpios, type: phandle-array, value: [<ControllerAndData, controller: <Node /gpio-map/destination in ' test.dts ' , binding test-bindings/gpio-dst.yaml>, data: OrderedDict([( ' val ' , 6)])>, <ControllerAndData, controller: <Node /gpio-map/destination in ' test.dts ' , binding test-bindings/gpio-dst.yaml>, data: OrderedDict([( ' val ' , 5)])>]> " )
2018-12-17 20:09:47 +01:00
2019-08-29 22:21:33 +02:00
#
# Test property default values given in bindings
#
2019-09-23 05:14:18 +02:00
verify_streq ( edt . get_node ( " /defaults " ) . props ,
2019-11-12 18:33:00 +01:00
r " OrderedDict([( ' int ' , <Property, name: int, type: int, value: 123>), ( ' array ' , <Property, name: array, type: array, value: [1, 2, 3]>), ( ' uint8-array ' , <Property, name: uint8-array, type: uint8-array, value: b ' \ x89 \ xab \ xcd ' >), ( ' string ' , <Property, name: string, type: string, value: ' hello ' >), ( ' string-array ' , <Property, name: string-array, type: string-array, value: [ ' hello ' , ' there ' ]>), ( ' default-not-used ' , <Property, name: default-not-used, type: int, value: 234>)]) " )
2019-08-29 22:21:33 +02:00
2019-08-02 23:45:51 +02:00
#
# Test having multiple directories with bindings, with a different .dts file
#
edt = edtlib . EDT ( " test-multidir.dts " , [ " test-bindings " , " test-bindings-2 " ] )
2019-09-23 05:14:18 +02:00
verify_streq ( edt . get_node ( " /in-dir-1 " ) . binding_path ,
2019-08-02 23:45:51 +02:00
" test-bindings/multidir.yaml " )
2019-09-23 05:14:18 +02:00
verify_streq ( edt . get_node ( " /in-dir-2 " ) . binding_path ,
2019-08-02 23:45:51 +02:00
" test-bindings-2/multidir.yaml " )
2019-09-27 11:31:36 -05:00
#
# Test dependency relations
#
2019-11-06 22:17:10 +01:00
verify_eq ( edt . get_node ( " / " ) . dep_ordinal , 0 )
verify_eq ( edt . get_node ( " /in-dir-1 " ) . dep_ordinal , 1 )
2019-11-06 22:36:50 +01:00
if edt . get_node ( " / " ) not in edt . get_node ( " /in-dir-1 " ) . depends_on :
fail ( " / should be a direct dependency of /in-dir-1 " )
if edt . get_node ( " /in-dir-1 " ) not in edt . get_node ( " / " ) . required_by :
fail ( " /in-dir-1 should directly depend on / " )
2019-09-27 11:31:36 -05:00
2020-01-09 07:03:42 +01:00
#
# Test error messages from _slice()
#
verify_error ( """
/ dts - v1 / ;
/ {
#address-cells = <1>;
#size-cells = <2>;
sub {
reg = < 3 > ;
} ;
} ;
""" , " ' reg ' property in <Node /sub in ' error.dts ' > has length 4, which is not evenly divisible by 12 (= 4*(<#address-cells> (= 1) + <#size-cells> (= 2))). Note that #*-cells properties come either from the parent node or from the controller (in the case of ' interrupts ' ). " )
verify_error ( """
/ dts - v1 / ;
/ {
sub {
interrupts = < 1 > ;
interrupt - parent = < & { / controller } > ;
} ;
controller {
interrupt - controller ;
#interrupt-cells = <2>;
} ;
} ;
""" , " ' interrupts ' property in <Node /sub in ' error.dts ' > has length 4, which is not evenly divisible by 8 (= 4*<#interrupt-cells>). Note that #*-cells properties come either from the parent node or from the controller (in the case of ' interrupts ' ). " )
verify_error ( """
/ dts - v1 / ;
/ {
#address-cells = <1>;
sub - 1 {
#address-cells = <2>;
#size-cells = <3>;
ranges = < 4 5 > ;
sub - 2 {
reg = < 1 2 3 4 5 > ;
} ;
} ;
} ;
""" , " ' ranges ' property in <Node /sub-1 in ' error.dts ' > has length 8, which is not evenly divisible by 24 (= 4*(<#address-cells> (= 2) + <#address-cells for parent> (= 1) + <#size-cells> (= 3))). Note that #*-cells properties come either from the parent node or from the controller (in the case of ' interrupts ' ). " )
2018-12-17 20:09:47 +01:00
print ( " all tests passed " )
2020-01-09 07:03:42 +01:00
def verify_error ( dts , error ) :
# Verifies that parsing a file with the contents 'dts' (a string) raises an
# EDTError with the message 'error'
# Could use the 'tempfile' module instead of 'error.dts', but having a
# consistent filename makes error messages consistent and easier to test.
# error.dts is kept if the test fails, which is helpful.
with open ( " error.dts " , " w " , encoding = " utf-8 " ) as f :
f . write ( dts )
f . flush ( ) # Can't have unbuffered text IO, so flush() instead
try :
edtlib . EDT ( " error.dts " , [ ] )
except edtlib . EDTError as e :
if str ( e ) != error :
fail ( f " expected the EDTError ' { error } ' , got the EDTError ' { e } ' " )
except Exception as e :
fail ( f " expected the EDTError ' { error } ' , got the { type ( e ) . __name__ } ' { e } ' " )
else :
fail ( f " expected the error ' { error } ' , got no error " )
os . remove ( " error.dts " )
def fail ( msg ) :
sys . exit ( " test failed: " + msg )
def verify_eq ( actual , expected ) :
if actual != expected :
# Put values on separate lines to make it easy to spot differences
fail ( " not equal (expected value last): \n ' {} ' \n ' {} ' "
. format ( actual , expected ) )
def verify_streq ( actual , expected ) :
verify_eq ( str ( actual ) , expected )
2018-12-17 20:09:47 +01:00
if __name__ == " __main__ " :
run ( )