Example #1
0
def main():
    global conf_file
    global header_file

    args = parse_args()

    try:
        edt = edtlib.EDT(args.dts, args.bindings_dirs)
    except edtlib.EDTError as e:
        sys.exit("devicetree error: " + str(e))

    conf_file = open(args.conf_out, "w", encoding="utf-8")
    header_file = open(args.header_out, "w", encoding="utf-8")

    out_comment("Generated by gen_defines.py", blank_before=False)
    out_comment("DTS input file: " + args.dts, blank_before=False)
    out_comment("Directories with bindings: " +
                ", ".join(map(relativize, args.bindings_dirs)),
                blank_before=False)

    active_compats = set()

    for node in edt.nodes:
        if node.enabled and node.matching_compat:
            # Skip 'fixed-partitions' devices since they are handled by
            # write_flash() and would generate extra spurious #defines
            if node.matching_compat == "fixed-partitions":
                continue

            out_comment("Devicetree node: " + node.path)
            out_comment("Binding (compatible = {}): {}".format(
                node.matching_compat, relativize(node.binding_path)),
                        blank_before=False)
            out_comment("Binding description: " + node.description,
                        blank_before=False)

            write_regs(node)
            write_irqs(node)
            write_props(node)
            write_clocks(node)
            write_spi_dev(node)
            write_bus(node)
            write_existence_flags(node)

            active_compats.update(node.compats)

    out_comment("Active compatibles (mentioned in DTS + binding found)")
    for compat in sorted(active_compats):
        #define DT_COMPAT_<COMPAT> 1
        out("COMPAT_{}".format(str2ident(compat)), 1)

    # These are derived from /chosen
    write_addr_size(edt, "zephyr,sram", "SRAM")
    write_addr_size(edt, "zephyr,ccm", "CCM")
    write_addr_size(edt, "zephyr,dtcm", "DTCM")

    write_flash(edt.chosen_node("zephyr,flash"))
    write_code_partition(edt.chosen_node("zephyr,code-partition"))

    flash_index = 0
    for node in edt.nodes:
        if node.name.startswith("partition@"):
            write_flash_partition(node, flash_index)
            flash_index += 1

    out_comment("Number of flash partitions")
    if flash_index != 0:
        out("FLASH_AREA_NUM", flash_index)

    print("Devicetree configuration written to " + args.conf_out)
Example #2
0
def test_prop_defaults():
    '''Test property default values given in bindings'''
    edt = edtlib.EDT("test.dts", ["test-bindings"])

    assert str(edt.get_node("/defaults").props) == \
        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>)])"
Example #3
0
def test_pinctrl():
    '''Test 'pinctrl-<index>'.'''
    edt = edtlib.EDT("test.dts", ["test-bindings"])

    assert str(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>]>]"
Example #4
0
def run():
    """
    Runs all edtlib tests. Immediately exits with status 1 and a message on
    stderr on test suite failures.
    """
    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)

    warnings = io.StringIO()
    edt = edtlib.EDT("test.dts", ["test-bindings"], warnings)

    # Deprecated features are tested too, which generate warnings. Verify them.
    verify_eq(
        warnings.getvalue(), """\
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
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: |'.
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)
""")

    #
    # Test interrupts
    #

    verify_streq(
        edt.get_node("/interrupt-parent-test/node").interrupts,
        "[<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)])>]"
    )

    verify_streq(
        edt.get_node("/interrupts-extended-test/node").interrupts,
        "[<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)])>]"
    )

    verify_streq(
        edt.get_node("/interrupt-map-test/node@0").interrupts,
        "[<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)])>]"
    )

    verify_streq(
        edt.get_node("/interrupt-map-test/node@1").interrupts,
        "[<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)])>]"
    )

    verify_streq(
        edt.get_node("/interrupt-map-bitops-test/node@70000000E").interrupts,
        "[<ControllerAndData, controller: <Node /interrupt-map-bitops-test/controller in 'test.dts', binding test-bindings/interrupt-2-cell.yaml>, data: OrderedDict([('one', 3), ('two', 2)])>]"
    )

    #
    # Test 'reg'
    #

    verify_streq(
        edt.get_node("/reg-zero-address-cells/node").regs,
        "[<Register, addr: 0x0, size: 0x1>, <Register, addr: 0x0, size: 0x2>]")

    verify_streq(
        edt.get_node("/reg-zero-size-cells/node").regs,
        "[<Register, addr: 0x1, size: 0x0>, <Register, addr: 0x2, size: 0x0>]")

    verify_streq(
        edt.get_node("/reg-ranges/parent/node").regs,
        "[<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>]"
    )

    verify_streq(
        edt.get_node("/reg-nested-ranges/grandparent/parent/node").regs,
        "[<Register, addr: 0x30000000200000001, size: 0x1>]")

    #
    # 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>]>]"
    )

    #
    # Test Node.parent and Node.children
    #

    verify_eq(edt.get_node("/").parent, None)

    verify_streq(
        edt.get_node("/parent/child-1").parent,
        "<Node /parent in 'test.dts', no binding>")

    verify_streq(
        edt.get_node("/parent/child-2/grandchild").parent,
        "<Node /parent/child-2 in 'test.dts', no binding>")

    verify_streq(
        edt.get_node("/parent").children,
        "OrderedDict([('child-1', <Node /parent/child-1 in 'test.dts', no binding>), ('child-2', <Node /parent/child-2 in 'test.dts', no binding>)])"
    )

    verify_eq(edt.get_node("/parent/child-1").children, {})

    #
    # Test 'include:' and the legacy 'inherits: !include ...'
    #

    verify_streq(
        edt.get_node("/binding-include").description, "Parent binding")

    verify_streq(
        edt.get_node("/binding-include").props,
        "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>)])"
    )

    #
    # Test 'bus:' and 'on-bus:'
    #

    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
    verify_streq(
        edt.get_node("/buses/foo-bus/node").binding_path,
        "test-bindings/device-on-foo-bus.yaml")
    verify_streq(
        edt.get_node("/buses/bar-bus/node").binding_path,
        "test-bindings/device-on-bar-bus.yaml")

    # 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")

    #
    # Test 'child-binding:'
    #

    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")

    verify_streq(child1.binding_path, "test-bindings/child-binding.yaml")
    verify_streq(child1.description, "child node")
    verify_streq(
        child1.props,
        "OrderedDict([('child-prop', <Property, name: child-prop, type: int, value: 1>)])"
    )

    verify_streq(child2.binding_path, "test-bindings/child-binding.yaml")
    verify_streq(child2.description, "child node")
    verify_streq(
        child2.props,
        "OrderedDict([('child-prop', <Property, name: child-prop, type: int, value: 3>)])"
    )

    verify_streq(grandchild.binding_path, "test-bindings/child-binding.yaml")
    verify_streq(grandchild.description, "grandchild node")
    verify_streq(
        grandchild.props,
        "OrderedDict([('grandchild-prop', <Property, name: grandchild-prop, type: int, value: 2>)])"
    )

    #
    # Test deprecated 'sub-node' key (replaced with 'child-binding') and
    # deprecated '#cells' key (replaced with '*-cells')
    #

    verify_streq(
        edt.get_node("/deprecated/sub-node").props,
        "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)])>]>)])"
    )

    #
    # 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"],
        "<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)])>]>"
    )

    verify_streq(
        edt.get_node("/props").props["foo-gpios"],
        "<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)])>]>"
    )

    #
    # Test <prefix>-map, via gpio-map (the most common case)
    #

    verify_streq(
        edt.get_node("/gpio-map/source").props["foo-gpios"],
        "<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)])>]>"
    )

    #
    # Test property default values given in bindings
    #

    verify_streq(
        edt.get_node("/defaults").props,
        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>)])"
    )

    #
    # Test having multiple directories with bindings, with a different .dts file
    #

    edt = edtlib.EDT("test-multidir.dts", ["test-bindings", "test-bindings-2"])

    verify_streq(
        edt.get_node("/in-dir-1").binding_path, "test-bindings/multidir.yaml")

    verify_streq(
        edt.get_node("/in-dir-2").binding_path,
        "test-bindings-2/multidir.yaml")

    #
    # Test dependency relations
    #

    verify_eq(edt.get_node("/").dep_ordinal, 0)
    verify_eq(edt.get_node("/in-dir-1").dep_ordinal, 1)
    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 /")

    print("all tests passed")
Example #5
0
def main():
    global conf_file
    global header_file

    args = parse_args()

    try:
        edt = edtlib.EDT(args.dts, args.bindings_dirs)
    except edtlib.EDTError as e:
        sys.exit("devicetree error: " + str(e))

    conf_file = open(args.conf_out, "w", encoding="utf-8")
    header_file = open(args.header_out, "w", encoding="utf-8")

    out_comment("""\
Generated by gen_defines.py

DTS input file:
  {}

Directories with bindings:
  {}""".format(args.dts, ", ".join(map(relativize, args.bindings_dirs))),
                blank_before=False)

    out_comment("Nodes in dependency order (ordinal : path):")
    for scc in edt.scc_order():
        if len(scc) > 1:
            err("Cycle in devicetree involving: {}".format(", ".join(
                [n.path for n in scc])))
        node = scc[0]
        out_comment("{} : {}".format(node.dep_ordinal, node.path),
                    blank_before=False)

    active_compats = set()

    for node in edt.nodes:
        if node.enabled and node.matching_compat:
            # Skip 'fixed-partitions' devices since they are handled by
            # write_flash() and would generate extra spurious #defines
            if node.matching_compat == "fixed-partitions":
                continue

            requires_text = ""
            if node.depends_on:
                requires_text = "Requires:\n"
                for depends in node.depends_on:
                    requires_text += "  {} {}\n".format(
                        depends.dep_ordinal, depends.path)
                requires_text += "\n"

            supports_text = ""
            if node.required_by:
                supports_text = "Supports:\n"
                for required in node.required_by:
                    supports_text += "  {} {}\n".format(
                        required.dep_ordinal, required.path)
                supports_text += "\n"

            out_comment("""\
Devicetree node:
  {}

Binding (compatible = {}):
  {}

Dependency Ordinal: {}

{}{}Description:
{}""".format(
                node.path,
                node.matching_compat,
                relativize(node.binding_path),
                node.dep_ordinal,
                requires_text,
                supports_text,
                # Indent description by two spaces
                "\n".join("  " + line
                          for line in node.description.splitlines())))

            write_regs(node)
            write_irqs(node)
            write_props(node)
            write_clocks(node)
            write_spi_dev(node)
            write_bus(node)
            write_existence_flags(node)

            active_compats.update(node.compats)

    out_comment("Active compatibles (mentioned in DTS + binding found)")
    for compat in sorted(active_compats):
        #define DT_COMPAT_<COMPAT> 1
        out("COMPAT_{}".format(str2ident(compat)), 1)

    # These are derived from /chosen
    write_addr_size(edt, "zephyr,sram", "SRAM")
    write_addr_size(edt, "zephyr,ccm", "CCM")
    write_addr_size(edt, "zephyr,dtcm", "DTCM")
    write_addr_size(edt, "zephyr,ipc_shm", "IPC_SHM")

    write_flash(edt.chosen_node("zephyr,flash"))
    write_code_partition(edt.chosen_node("zephyr,code-partition"))

    flash_index = 0
    for node in edt.nodes:
        if node.name.startswith("partition@"):
            write_flash_partition(node, flash_index)
            flash_index += 1

    out_comment("Number of flash partitions")
    if flash_index != 0:
        out("FLASH_AREA_NUM", flash_index)

    print("Devicetree configuration written to " + args.conf_out)
Example #6
0
def main():
    global conf_file
    global header_file

    args = parse_args()

    try:
        edt = edtlib.EDT(args.dts, args.bindings_dir)
    except edtlib.EDTError as e:
        sys.exit("device tree error: " + str(e))

    conf_file = open(args.conf_out, "w", encoding="utf-8")
    header_file = open(args.header_out, "w", encoding="utf-8")

    out_comment("Generated by gen_defines.py", blank_before=False)
    out_comment("DTS input file: " + args.dts, blank_before=False)
    out_comment("Directory with bindings: " + args.bindings_dir,
                blank_before=False)

    active_compats = set()

    for dev in edt.devices:
        if dev.enabled and dev.matching_compat:
            # Skip 'fixed-partitions' devices since they are handled by
            # write_flash() and would generate extra spurious #defines
            if dev.matching_compat == "fixed-partitions":
                continue

            out_comment("Device tree node: " + dev.path)
            out_comment("Binding (compatible = {}): {}".format(
                dev.matching_compat, dev.binding_path),
                        blank_before=False)
            out_comment("Binding description: " + dev.description,
                        blank_before=False)

            write_regs(dev)
            write_irqs(dev)
            write_gpios(dev)
            write_pwms(dev)
            write_clocks(dev)
            write_spi_dev(dev)
            write_props(dev)
            write_bus(dev)
            write_existence_flags(dev)

            active_compats.update(dev.compats)

    out_comment("Active compatibles (mentioned in DTS + binding found)")
    for compat in active_compats:
        #define DT_COMPAT_<COMPAT> 1
        out("COMPAT_{}".format(str2ident(compat)), 1)

    # These are derived from /chosen
    write_addr_size(edt, "zephyr,sram", "SRAM")
    write_addr_size(edt, "zephyr,ccm", "CCM")
    write_addr_size(edt, "zephyr,dtcm", "DTCM")

    # NOTE: These defines aren't used by the code and just used by
    # the kconfig build system, we can remove them in the future
    # if we provide a function in kconfigfunctions.py to get
    # the same info
    write_required_label("UART_CONSOLE_ON_DEV_NAME",
                         edt.chosen_dev("zephyr,console"))
    write_required_label("UART_SHELL_ON_DEV_NAME",
                         edt.chosen_dev("zephyr,shell-uart"))
    write_required_label("BT_UART_ON_DEV_NAME",
                         edt.chosen_dev("zephyr,bt-uart"))
    write_required_label("UART_PIPE_ON_DEV_NAME",
                         edt.chosen_dev("zephyr,uart-pipe"))
    write_required_label("BT_MONITOR_ON_DEV_NAME",
                         edt.chosen_dev("zephyr,bt-mon-uart"))
    write_required_label("UART_MCUMGR_ON_DEV_NAME",
                         edt.chosen_dev("zephyr,uart-mcumgr"))
    write_required_label("BT_C2H_UART_ON_DEV_NAME",
                         edt.chosen_dev("zephyr,bt-c2h-uart"))

    write_flash(edt.chosen_dev("zephyr,flash"))
    write_code_partition(edt.chosen_dev("zephyr,code-partition"))

    flash_index = 0
    for dev in edt.devices:
        if dev.name.startswith("partition@"):
            write_flash_partition(dev, flash_index)
            flash_index += 1

    out_comment("Number of flash partitions")
    if flash_index != 0:
        out("FLASH_AREA_NUM", flash_index)

    print("Device tree configuration written to " + args.conf_out)
Example #7
0
def main():
    global header_file
    global flash_area_num

    args = parse_args()

    setup_edtlib_logging()

    try:
        edt = edtlib.EDT(args.dts, args.bindings_dirs,
                         # Suppress this warning if it's suppressed in dtc
                         warn_reg_unit_address_mismatch=
                             "-Wno-simple_bus_reg" not in args.dtc_flags,
                         default_prop_types=True,
                         infer_binding_for_paths=["/zephyr,user"])
    except edtlib.EDTError as e:
        sys.exit(f"devicetree error: {e}")

    flash_area_num = 0

    # Save merged DTS source, as a debugging aid
    with open(args.dts_out, "w", encoding="utf-8") as f:
        print(edt.dts_source, file=f)

    # The raw index into edt.compat2nodes[compat] is used for node
    # instance numbering within a compatible.
    #
    # As a way to satisfy people's intuitions about instance numbers,
    # though, we sort this list so enabled instances come first.
    #
    # This might look like a hack, but it keeps drivers and
    # applications which don't use instance numbers carefully working
    # as expected, since e.g. instance number 0 is always the
    # singleton instance if there's just one enabled node of a
    # particular compatible.
    #
    # This doesn't violate any devicetree.h API guarantees about
    # instance ordering, since we make no promises that instance
    # numbers are stable across builds.
    for compat, nodes in edt.compat2nodes.items():
        edt.compat2nodes[compat] = sorted(
            nodes, key=lambda node: 0 if node.status == "okay" else 1)

    # Create the generated header.
    with open(args.header_out, "w", encoding="utf-8") as header_file:
        write_top_comment(edt)

        # populate all z_path_id first so any children references will
        # work correctly.
        for node in sorted(edt.nodes, key=lambda node: node.dep_ordinal):
            node.z_path_id = node_z_path_id(node)

        for node in sorted(edt.nodes, key=lambda node: node.dep_ordinal):
            write_node_comment(node)

            if node.parent is not None:
                out_comment(f"Node parent ({node.parent.path}) identifier:")
                out_dt_define(f"{node.z_path_id}_PARENT",
                              f"DT_{node.parent.z_path_id}")

            write_child_functions(node)
            write_dep_info(node)
            write_idents_and_existence(node)
            write_bus(node)
            write_special_props(node)
            write_vanilla_props(node)

        write_chosen(edt)
        write_global_compat_info(edt)

    if args.edt_pickle_out:
        write_pickled_edt(edt, args.edt_pickle_out)
Example #8
0
import edtlib

# Types we support
# 'string', 'int', 'hex', 'bool'

doc_mode = os.environ.get('KCONFIG_DOC_MODE') == "1"

dt_defines = {}
if not doc_mode:
    DTS_POST_CPP = os.environ["DTS_POST_CPP"]
    BINDINGS_DIRS = os.environ.get("DTS_ROOT_BINDINGS")

    # if a board port doesn't use DTS than these might not be set
    if os.path.isfile(DTS_POST_CPP) and BINDINGS_DIRS is not None:
        edt = edtlib.EDT(DTS_POST_CPP, BINDINGS_DIRS.split("?"))
    else:
        edt = None

    # The env. var DEVICETREE_CONF must be set unless we are in doc mode
    DEVICETREE_CONF = os.environ['DEVICETREE_CONF']
    if os.path.isfile(DEVICETREE_CONF):
        with open(DEVICETREE_CONF, 'r', encoding='utf-8') as fd:
            for line in fd:
                if '=' in line:
                    define, val = line.split('=', 1)
                    dt_defines[define] = val.strip()


def _warn(kconf, msg):
    print("{}:{}: WARNING: {}".format(kconf.filename, kconf.linenr, msg))
Example #9
0
def run():
    """
    Runs all edtlib tests. Immediately exits with status 1 and a message on
    stderr on test suite failures.
    """

    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)

    edt = edtlib.EDT("test.dts", ["test-bindings"])

    #
    # Test interrupts
    #

    verify_streq(edt.get_dev("/interrupt-parent-test/node").interrupts,
                 "[<Interrupt, name: foo, target: <Device /interrupt-parent-test/controller in 'test.dts', binding test-bindings/interrupt-3-cell.yaml>, specifier: {'one': 1, 'two': 2, 'three': 3}>, <Interrupt, name: bar, target: <Device /interrupt-parent-test/controller in 'test.dts', binding test-bindings/interrupt-3-cell.yaml>, specifier: {'one': 4, 'two': 5, 'three': 6}>]")

    verify_streq(edt.get_dev("/interrupts-extended-test/node").interrupts,
                 "[<Interrupt, target: <Device /interrupts-extended-test/controller-0 in 'test.dts', binding test-bindings/interrupt-1-cell.yaml>, specifier: {'one': 1}>, <Interrupt, target: <Device /interrupts-extended-test/controller-1 in 'test.dts', binding test-bindings/interrupt-2-cell.yaml>, specifier: {'one': 2, 'two': 3}>, <Interrupt, target: <Device /interrupts-extended-test/controller-2 in 'test.dts', binding test-bindings/interrupt-3-cell.yaml>, specifier: {'one': 4, 'two': 5, 'three': 6}>]")

    verify_streq(edt.get_dev("/interrupt-map-test/node@0").interrupts,
                 "[<Interrupt, target: <Device /interrupt-map-test/controller-0 in 'test.dts', binding test-bindings/interrupt-1-cell.yaml>, specifier: {'one': 0}>, <Interrupt, target: <Device /interrupt-map-test/controller-1 in 'test.dts', binding test-bindings/interrupt-2-cell.yaml>, specifier: {'one': 0, 'two': 1}>, <Interrupt, target: <Device /interrupt-map-test/controller-2 in 'test.dts', binding test-bindings/interrupt-3-cell.yaml>, specifier: {'one': 0, 'two': 0, 'three': 2}>]")

    verify_streq(edt.get_dev("/interrupt-map-test/node@1").interrupts,
                 "[<Interrupt, target: <Device /interrupt-map-test/controller-0 in 'test.dts', binding test-bindings/interrupt-1-cell.yaml>, specifier: {'one': 3}>, <Interrupt, target: <Device /interrupt-map-test/controller-1 in 'test.dts', binding test-bindings/interrupt-2-cell.yaml>, specifier: {'one': 0, 'two': 4}>, <Interrupt, target: <Device /interrupt-map-test/controller-2 in 'test.dts', binding test-bindings/interrupt-3-cell.yaml>, specifier: {'one': 0, 'two': 0, 'three': 5}>]")

    verify_streq(edt.get_dev("/interrupt-map-bitops-test/node@70000000E").interrupts,
                 "[<Interrupt, target: <Device /interrupt-map-bitops-test/controller in 'test.dts', binding test-bindings/interrupt-2-cell.yaml>, specifier: {'one': 3, 'two': 2}>]")

    #
    # Test GPIOs
    #

    verify_streq(edt.get_dev("/gpio-test/node").gpios,
                 "{'': [<GPIO, name: , target: <Device /gpio-test/controller-0 in 'test.dts', binding test-bindings/gpio-1-cell.yaml>, specifier: {'one': 1}>, <GPIO, name: , target: <Device /gpio-test/controller-1 in 'test.dts', binding test-bindings/gpio-2-cell.yaml>, specifier: {'one': 2, 'two': 3}>], 'foo': [<GPIO, name: foo, target: <Device /gpio-test/controller-1 in 'test.dts', binding test-bindings/gpio-2-cell.yaml>, specifier: {'one': 4, 'two': 5}>], 'bar': [<GPIO, name: bar, target: <Device /gpio-test/controller-1 in 'test.dts', binding test-bindings/gpio-2-cell.yaml>, specifier: {'one': 6, 'two': 7}>]}")

    #
    # Test clocks
    #

    verify_streq(edt.get_dev("/clock-test/node").clocks,
                 "[<Clock, name: fixed, frequency: 123, target: <Device /clock-test/fixed-clock in 'test.dts', binding test-bindings/fixed-clock.yaml>, specifier: {}>, <Clock, name: one-cell, target: <Device /clock-test/clock-1 in 'test.dts', binding test-bindings/clock-1-cell.yaml>, specifier: {'one': 1}>, <Clock, name: two-cell, target: <Device /clock-test/clock-2 in 'test.dts', binding test-bindings/clock-2-cell.yaml>, specifier: {'one': 1, 'two': 2}>]")

    #
    # Test PWMs
    #

    verify_streq(edt.get_dev("/pwm-test/node").pwms,
                 "[<PWM, name: zero-cell, target: <Device /pwm-test/pwm-0 in 'test.dts', binding test-bindings/pwm-0-cell.yaml>, specifier: {}>, <PWM, name: one-cell, target: <Device /pwm-test/pwm-1 in 'test.dts', binding test-bindings/pwm-1-cell.yaml>, specifier: {'one': 1}>]")

    #
    # Test IO channels
    #

    verify_streq(edt.get_dev("/io-channel-test/node").iochannels,
                 "[<IOChannel, name: io-channel, target: <Device /io-channel-test/io-channel in 'test.dts', binding test-bindings/io-channel.yaml>, specifier: {'one': 1}>]")

    #
    # Test 'reg'
    #

    verify_streq(edt.get_dev("/reg-zero-address-cells/node").regs,
                 "[<Register, addr: 0x0, size: 0x1>, <Register, addr: 0x0, size: 0x2>]")

    verify_streq(edt.get_dev("/reg-zero-size-cells/node").regs,
                 "[<Register, addr: 0x1, size: 0x0>, <Register, addr: 0x2, size: 0x0>]")

    verify_streq(edt.get_dev("/reg-ranges/parent/node").regs,
                 "[<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>]")

    verify_streq(edt.get_dev("/reg-nested-ranges/grandparent/parent/node").regs,
                 "[<Register, addr: 0x30000000200000001, size: 0x1>]")

    #
    # Test Device.parent and Device.children
    #

    verify_eq(edt.get_dev("/").parent, None)

    verify_streq(edt.get_dev("/parent/child-1").parent,
                 "<Device /parent in 'test.dts', no binding>")

    verify_streq(edt.get_dev("/parent/child-2/grandchild").parent,
                 "<Device /parent/child-2 in 'test.dts', no binding>")

    verify_streq(edt.get_dev("/parent").children,
                 "{'child-1': <Device /parent/child-1 in 'test.dts', no binding>, 'child-2': <Device /parent/child-2 in 'test.dts', no binding>}")

    verify_eq(edt.get_dev("/parent/child-1").children, {})

    #
    # Test 'include:' and the legacy 'inherits: !include ...'
    #

    verify_streq(edt.get_dev("/binding-include").description,
                 "Parent binding")

    verify_streq(edt.get_dev("/binding-include").props,
                 "{'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>}")

    #
    # Test 'child/parent-bus:'
    #

    verify_streq(edt.get_dev("/buses/foo-bus/node").binding_path,
                 "test-bindings/device-on-foo-bus.yaml")

    verify_streq(edt.get_dev("/buses/bar-bus/node").binding_path,
                 "test-bindings/device-on-bar-bus.yaml")

    #
    # Test 'child-binding:'
    #

    child1 = edt.get_dev("/child-binding/child-1")
    child2 = edt.get_dev("/child-binding/child-2")
    grandchild = edt.get_dev("/child-binding/child-1/grandchild")

    verify_streq(child1.binding_path, "test-bindings/child-binding.yaml")
    verify_streq(child1.description, "child node")
    verify_streq(child1.props, "{'child-prop': <Property, name: child-prop, type: int, value: 1>}")

    verify_streq(child2.binding_path, "test-bindings/child-binding.yaml")
    verify_streq(child2.description, "child node")
    verify_streq(child2.props, "{'child-prop': <Property, name: child-prop, type: int, value: 3>}")

    verify_streq(grandchild.binding_path, "test-bindings/child-binding.yaml")
    verify_streq(grandchild.description, "grandchild node")
    verify_streq(grandchild.props, "{'grandchild-prop': <Property, name: grandchild-prop, type: int, value: 2>}")

    #
    # Test deprecated 'sub-node:' key (replaced with 'child-binding:')
    #

    verify_streq(edt.get_dev("/deprecated/sub-node").props,
                 "{'child-prop': <Property, name: child-prop, type: int, value: 3>}")

    #
    # Test Device.property (derived from DT and 'properties:' in the binding)
    #

    verify_streq(edt.get_dev("/props").props,
                 r"{'nonexistent-boolean': <Property, name: nonexistent-boolean, type: boolean, value: False>, 'existent-boolean': <Property, name: existent-boolean, type: boolean, value: True>, 'int': <Property, name: int, type: int, value: 1>, 'array': <Property, name: array, type: array, value: [1, 2, 3]>, 'uint8-array': <Property, name: uint8-array, type: uint8-array, value: b'\x124'>, 'string': <Property, name: string, type: string, value: 'foo'>, 'string-array': <Property, name: string-array, type: string-array, value: ['foo', 'bar', 'baz']>, 'phandle-ref': <Property, name: phandle-ref, type: phandle, value: <Device /props/node in 'test.dts', no binding>>, 'phandle-refs': <Property, name: phandle-refs, type: phandles, value: [<Device /props/node in 'test.dts', no binding>, <Device /props/node2 in 'test.dts', no binding>]>}")

    #
    # Test property default values given in bindings
    #

    verify_streq(edt.get_dev("/defaults").props,
                 r"{'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>}")

    #
    # Test having multiple directories with bindings, with a different .dts file
    #

    edt = edtlib.EDT("test-multidir.dts", ["test-bindings", "test-bindings-2"])

    verify_streq(edt.get_dev("/in-dir-1").binding_path,
                 "test-bindings/multidir.yaml")

    verify_streq(edt.get_dev("/in-dir-2").binding_path,
                 "test-bindings-2/multidir.yaml")


    print("all tests passed")
Example #10
0
def run():
    """
    Runs all edtlib tests. Immediately exits with status 1 and a message on
    stderr on test suite failures.
    """

    warnings = io.StringIO()
    edt = edtlib.EDT("test.dts", ["test-bindings"], warnings)

    # Verify warnings
    verify_eq(warnings.getvalue(), """\
warning: unit address and first address in 'reg' (0x1) don't match for /reg-zero-size-cells/node
warning: unit address and first address in 'reg' (0x5) don't match for /reg-ranges/parent/node
warning: unit address and first address in 'reg' (0x30000000200000001) don't match for /reg-nested-ranges/grandparent/parent/node
""")

    #
    # Test interrupts
    #

    verify_streq(edt.get_node("/interrupt-parent-test/node").interrupts,
                 "[<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)])>]")

    verify_streq(edt.get_node("/interrupts-extended-test/node").interrupts,
                 "[<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)])>]")

    verify_streq(edt.get_node("/interrupt-map-test/node@0").interrupts,
                 "[<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)])>]")

    verify_streq(edt.get_node("/interrupt-map-test/node@1").interrupts,
                 "[<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)])>]")

    verify_streq(edt.get_node("/interrupt-map-bitops-test/node@70000000E").interrupts,
                 "[<ControllerAndData, controller: <Node /interrupt-map-bitops-test/controller in 'test.dts', binding test-bindings/interrupt-2-cell.yaml>, data: OrderedDict([('one', 3), ('two', 2)])>]")

    #
    # Test 'reg'
    #

    verify_streq(edt.get_node("/reg-zero-address-cells/node").regs,
                 "[<Register, size: 0x1>, <Register, size: 0x2>]")

    verify_streq(edt.get_node("/reg-zero-size-cells/node").regs,
                 "[<Register, addr: 0x1>, <Register, addr: 0x2>]")

    verify_streq(edt.get_node("/reg-ranges/parent/node").regs,
                 "[<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>]")

    verify_streq(edt.get_node("/reg-nested-ranges/grandparent/parent/node").regs,
                 "[<Register, addr: 0x30000000200000001, size: 0x1>]")

    #
    # 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>]>]")

    #
    # Test Node.parent and Node.children
    #

    verify_eq(edt.get_node("/").parent, None)

    verify_streq(edt.get_node("/parent/child-1").parent,
                 "<Node /parent in 'test.dts', no binding>")

    verify_streq(edt.get_node("/parent/child-2/grandchild").parent,
                 "<Node /parent/child-2 in 'test.dts', no binding>")

    verify_streq(edt.get_node("/parent").children,
                 "OrderedDict([('child-1', <Node /parent/child-1 in 'test.dts', no binding>), ('child-2', <Node /parent/child-2 in 'test.dts', no binding>)])")

    verify_eq(edt.get_node("/parent/child-1").children, {})

    #
    # Test 'include:' and the legacy 'inherits: !include ...'
    #

    verify_streq(edt.get_node("/binding-include").description,
                 "Parent binding")

    verify_streq(edt.get_node("/binding-include").props,
                 "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>)])")

    #
    # Test 'bus:' and 'on-bus:'
    #

    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
    verify_streq(edt.get_node("/buses/foo-bus/node").binding_path,
                 "test-bindings/device-on-foo-bus.yaml")
    verify_streq(edt.get_node("/buses/bar-bus/node").binding_path,
                 "test-bindings/device-on-bar-bus.yaml")

    # 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")

    #
    # Test 'child-binding:'
    #

    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")

    verify_streq(child1.binding_path, "test-bindings/child-binding.yaml")
    verify_streq(child1.description, "child node")
    verify_streq(child1.props, "OrderedDict([('child-prop', <Property, name: child-prop, type: int, value: 1>)])")

    verify_streq(child2.binding_path, "test-bindings/child-binding.yaml")
    verify_streq(child2.description, "child node")
    verify_streq(child2.props, "OrderedDict([('child-prop', <Property, name: child-prop, type: int, value: 3>)])")

    verify_streq(grandchild.binding_path, "test-bindings/child-binding.yaml")
    verify_streq(grandchild.description, "grandchild node")
    verify_streq(grandchild.props, "OrderedDict([('grandchild-prop', <Property, name: grandchild-prop, type: int, value: 2>)])")

    #
    # 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")

    #
    # 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"],
                 "<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)])>]>")

    verify_streq(edt.get_node("/props").props["foo-gpios"],
                 "<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)])>]>")

    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>>")

    #
    # Test <prefix>-map, via gpio-map (the most common case)
    #

    verify_streq(edt.get_node("/gpio-map/source").props["foo-gpios"],
                 "<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)])>]>")

    #
    # Test property default values given in bindings
    #

    verify_streq(edt.get_node("/defaults").props,
                 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>)])")

    #
    # Test binding inference
    #

    verify_streq(edt.get_node("/zephyr,user").props, r"OrderedDict()")

    edt = edtlib.EDT("test.dts", ["test-bindings"], warnings,
                     infer_binding_for_paths=["/zephyr,user"])

    verify_streq(edt.get_node("/zephyr,user").props,
                 r"OrderedDict([('boolean', <Property, name: boolean, type: boolean, value: True>), ('bytes', <Property, name: bytes, type: uint8-array, value: b'\x81\x82\x83'>), ('number', <Property, name: number, type: int, value: 23>), ('numbers', <Property, name: numbers, type: array, value: [1, 2, 3]>), ('string', <Property, name: string, type: string, value: 'text'>), ('strings', <Property, name: strings, type: string-array, value: ['a', 'b', 'c']>), ('handle', <Property, name: handle, type: phandle, value: <Node /props/ctrl-1 in 'test.dts', binding test-bindings/phandle-array-controller-1.yaml>>), ('phandles', <Property, name: phandles, 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>]>), ('phandle-array-foos', <Property, name: phandle-array-foos, type: phandle-array, value: [<ControllerAndData, controller: <Node /props/ctrl-2 in 'test.dts', binding test-bindings/phandle-array-controller-2.yaml>, data: OrderedDict([('one', 1), ('two', 2)])>]>)])")

    #
    # Test having multiple directories with bindings, with a different .dts file
    #

    edt = edtlib.EDT("test-multidir.dts", ["test-bindings", "test-bindings-2"])

    verify_streq(edt.get_node("/in-dir-1").binding_path,
                 "test-bindings/multidir.yaml")

    verify_streq(edt.get_node("/in-dir-2").binding_path,
                 "test-bindings-2/multidir.yaml")

    #
    # Test dependency relations
    #

    verify_eq(edt.get_node("/").dep_ordinal, 0)
    verify_eq(edt.get_node("/in-dir-1").dep_ordinal, 1)
    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 /")

    #
    # 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').")

    print("all tests passed")
Example #11
0
def test_warnings():
    '''Tests for situations that should cause warnings.'''
    warnings = io.StringIO()
    edtlib.EDT("test.dts", ["test-bindings"], warnings)

    assert warnings.getvalue() == """\
import edtlib

# Types we support
# 'string', 'int', 'hex', 'bool'

doc_mode = os.environ.get('KCONFIG_DOC_MODE') == "1"

dt_defines = {}
if not doc_mode:
    DTS_POST_CPP = os.environ["DTS_POST_CPP"]
    BINDINGS_DIR = os.environ.get("DTS_ROOT_BINDINGS")

    # if a board port doesn't use DTS than these might not be set
    if os.path.isfile(DTS_POST_CPP) and BINDINGS_DIR is not None:
        edt = edtlib.EDT(DTS_POST_CPP, [BINDINGS_DIR])
    else:
        edt = None

    # The env var 'GENERATED_DTS_BOARD_CONF' must be set unless we are in
    # doc mode
    GENERATED_DTS_BOARD_CONF = os.environ['GENERATED_DTS_BOARD_CONF']
    if os.path.isfile(GENERATED_DTS_BOARD_CONF):
        with open(GENERATED_DTS_BOARD_CONF, 'r', encoding='utf-8') as fd:
            for line in fd:
                if '=' in line:
                    define, val = line.split('=', 1)
                    dt_defines[define] = val.strip()


def _warn(kconf, msg):
Example #13
0
def main():
    global conf_file
    global header_file
    global flash_area_num

    args = parse_args()

    try:
        edt = edtlib.EDT(
            args.dts,
            args.bindings_dirs,
            # Suppress this warning if it's suppressed in dtc
            warn_reg_unit_address_mismatch="-Wno-simple_bus_reg"
            not in args.dtc_flags)
    except edtlib.EDTError as e:
        sys.exit(f"devicetree error: {e}")

    # Save merged DTS source, as a debugging aid
    with open(args.dts_out, "w", encoding="utf-8") as f:
        print(edt.dts_source, file=f)

    conf_file = open(args.conf_out, "w", encoding="utf-8")
    header_file = open(args.header_out, "w", encoding="utf-8")
    flash_area_num = 0

    write_top_comment(edt)

    for node in sorted(edt.nodes, key=lambda node: node.dep_ordinal):
        write_node_comment(node)

        # Flash partition nodes are handled as a special case. It
        # would be nicer if we had bindings that would let us
        # avoid that, but this will do for now.
        if node.name.startswith("partition@"):
            write_flash_partition(node, flash_area_num)
            flash_area_num += 1

        if node.enabled and node.matching_compat:
            write_regs(node)
            write_irqs(node)
            write_props(node)
            write_clocks(node)
            write_spi_dev(node)
            write_bus(node)
            write_existence_flags(node)

    out_comment("Compatibles appearing on enabled nodes")
    for compat in sorted(edt.compat2enabled):
        #define DT_COMPAT_<COMPAT> 1
        out(f"COMPAT_{str2ident(compat)}", 1)

    # Definitions derived from /chosen nodes
    write_addr_size(edt, "zephyr,ccm", "CCM")
    write_addr_size(edt, "zephyr,dtcm", "DTCM")
    write_addr_size(edt, "zephyr,ipc_shm", "IPC_SHM")
    write_flash(edt)

    conf_file.close()
    header_file.close()

    print(f"Devicetree header saved to '{args.header_out}'")
Example #14
0
def run():
    """
    Runs all edtlib tests. Immediately exits with status 1 and a message on
    stderr on test suite failures.
    """

    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)

    warnings = io.StringIO()
    edt = edtlib.EDT("test.dts", ["test-bindings"], warnings)

    # Deprecated features are tested too, which generate warnings. Verify them.
    verify_eq(warnings.getvalue(), """\
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
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)
""")

    #
    # Test interrupts
    #

    verify_streq(edt.get_node("/interrupt-parent-test/node").interrupts,
                 "[<ControllerAndData, name: foo, controller: <Node /interrupt-parent-test/controller in 'test.dts', binding test-bindings/interrupt-3-cell.yaml>, data: {'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: {'one': 4, 'two': 5, 'three': 6}>]")

    verify_streq(edt.get_node("/interrupts-extended-test/node").interrupts,
                 "[<ControllerAndData, controller: <Node /interrupts-extended-test/controller-0 in 'test.dts', binding test-bindings/interrupt-1-cell.yaml>, data: {'one': 1}>, <ControllerAndData, controller: <Node /interrupts-extended-test/controller-1 in 'test.dts', binding test-bindings/interrupt-2-cell.yaml>, data: {'one': 2, 'two': 3}>, <ControllerAndData, controller: <Node /interrupts-extended-test/controller-2 in 'test.dts', binding test-bindings/interrupt-3-cell.yaml>, data: {'one': 4, 'two': 5, 'three': 6}>]")

    verify_streq(edt.get_node("/interrupt-map-test/node@0").interrupts,
                 "[<ControllerAndData, controller: <Node /interrupt-map-test/controller-0 in 'test.dts', binding test-bindings/interrupt-1-cell.yaml>, data: {'one': 0}>, <ControllerAndData, controller: <Node /interrupt-map-test/controller-1 in 'test.dts', binding test-bindings/interrupt-2-cell.yaml>, data: {'one': 0, 'two': 1}>, <ControllerAndData, controller: <Node /interrupt-map-test/controller-2 in 'test.dts', binding test-bindings/interrupt-3-cell.yaml>, data: {'one': 0, 'two': 0, 'three': 2}>]")

    verify_streq(edt.get_node("/interrupt-map-test/node@1").interrupts,
                 "[<ControllerAndData, controller: <Node /interrupt-map-test/controller-0 in 'test.dts', binding test-bindings/interrupt-1-cell.yaml>, data: {'one': 3}>, <ControllerAndData, controller: <Node /interrupt-map-test/controller-1 in 'test.dts', binding test-bindings/interrupt-2-cell.yaml>, data: {'one': 0, 'two': 4}>, <ControllerAndData, controller: <Node /interrupt-map-test/controller-2 in 'test.dts', binding test-bindings/interrupt-3-cell.yaml>, data: {'one': 0, 'two': 0, 'three': 5}>]")

    verify_streq(edt.get_node("/interrupt-map-bitops-test/node@70000000E").interrupts,
                 "[<ControllerAndData, controller: <Node /interrupt-map-bitops-test/controller in 'test.dts', binding test-bindings/interrupt-2-cell.yaml>, data: {'one': 3, 'two': 2}>]")

    #
    # Test 'reg'
    #

    verify_streq(edt.get_node("/reg-zero-address-cells/node").regs,
                 "[<Register, addr: 0x0, size: 0x1>, <Register, addr: 0x0, size: 0x2>]")

    verify_streq(edt.get_node("/reg-zero-size-cells/node").regs,
                 "[<Register, addr: 0x1, size: 0x0>, <Register, addr: 0x2, size: 0x0>]")

    verify_streq(edt.get_node("/reg-ranges/parent/node").regs,
                 "[<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>]")

    verify_streq(edt.get_node("/reg-nested-ranges/grandparent/parent/node").regs,
                 "[<Register, addr: 0x30000000200000001, size: 0x1>]")

    #
    # Test Node.parent and Node.children
    #

    verify_eq(edt.get_node("/").parent, None)

    verify_streq(edt.get_node("/parent/child-1").parent,
                 "<Node /parent in 'test.dts', no binding>")

    verify_streq(edt.get_node("/parent/child-2/grandchild").parent,
                 "<Node /parent/child-2 in 'test.dts', no binding>")

    verify_streq(edt.get_node("/parent").children,
                 "{'child-1': <Node /parent/child-1 in 'test.dts', no binding>, 'child-2': <Node /parent/child-2 in 'test.dts', no binding>}")

    verify_eq(edt.get_node("/parent/child-1").children, {})

    #
    # Test 'include:' and the legacy 'inherits: !include ...'
    #

    verify_streq(edt.get_node("/binding-include").description,
                 "Parent binding")

    verify_streq(edt.get_node("/binding-include").props,
                 "{'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>}")

    #
    # Test 'child/parent-bus:'
    #

    verify_streq(edt.get_node("/buses/foo-bus/node").binding_path,
                 "test-bindings/device-on-foo-bus.yaml")

    verify_streq(edt.get_node("/buses/bar-bus/node").binding_path,
                 "test-bindings/device-on-bar-bus.yaml")

    #
    # Test 'child-binding:'
    #

    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")

    verify_streq(child1.binding_path, "test-bindings/child-binding.yaml")
    verify_streq(child1.description, "child node")
    verify_streq(child1.props, "{'child-prop': <Property, name: child-prop, type: int, value: 1>}")

    verify_streq(child2.binding_path, "test-bindings/child-binding.yaml")
    verify_streq(child2.description, "child node")
    verify_streq(child2.props, "{'child-prop': <Property, name: child-prop, type: int, value: 3>}")

    verify_streq(grandchild.binding_path, "test-bindings/child-binding.yaml")
    verify_streq(grandchild.description, "grandchild node")
    verify_streq(grandchild.props, "{'grandchild-prop': <Property, name: grandchild-prop, type: int, value: 2>}")

    #
    # Test deprecated 'sub-node' key (replaced with 'child-binding') and
    # deprecated '#cells' key (replaced with '*-cells')
    #

    verify_streq(edt.get_node("/deprecated/sub-node").props,
                 "{'foos': <Property, name: foos, type: phandle-array, value: [<ControllerAndData, controller: <Node /deprecated in 'test.dts', binding test-bindings/deprecated.yaml>, data: {'foo': 1, 'bar': 2}>]>}")

    #
    # 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"],
                 "<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: {'one': 1}>, <ControllerAndData, controller: <Node /props/ctrl-2 in 'test.dts', binding test-bindings/phandle-array-controller-2.yaml>, data: {'one': 2, 'two': 3}>]>")

    verify_streq(edt.get_node("/props").props["foo-gpios"],
                 "<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: {'gpio-one': 1}>]>")

    #
    # Test <prefix>-map, via gpio-map (the most common case)
    #

    verify_streq(edt.get_node("/gpio-map/source").props["foo-gpios"],
                 "<Property, name: foo-gpios, type: phandle-array, value: [<ControllerAndData, controller: <Node /gpio-map/destination in 'test.dts', binding test-bindings/gpio-dst.yaml>, data: {'val': 6}>, <ControllerAndData, controller: <Node /gpio-map/destination in 'test.dts', binding test-bindings/gpio-dst.yaml>, data: {'val': 5}>]>")

    #
    # Test property default values given in bindings
    #

    verify_streq(edt.get_node("/defaults").props,
                 r"{'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>}")

    #
    # Test having multiple directories with bindings, with a different .dts file
    #

    edt = edtlib.EDT("test-multidir.dts", ["test-bindings", "test-bindings-2"])

    verify_streq(edt.get_node("/in-dir-1").binding_path,
                 "test-bindings/multidir.yaml")

    verify_streq(edt.get_node("/in-dir-2").binding_path,
                 "test-bindings-2/multidir.yaml")


    print("all tests passed")
Example #15
0
doc_mode = os.environ.get('KCONFIG_DOC_MODE') == "1"

if not doc_mode:
    DTS_POST_CPP = os.environ["DTS_POST_CPP"]
    BINDINGS_DIRS = os.environ.get("DTS_ROOT_BINDINGS")
    DTC_FLAGS = os.environ.get("EXTRA_DTC_FLAGS")

    if DTC_FLAGS is not None and "-Wno-simple_bus_reg" in DTC_FLAGS:
        edt_warn_flag = False
    else:
        edt_warn_flag = True

    # if a board port doesn't use DTS than these might not be set
    if os.path.isfile(DTS_POST_CPP) and BINDINGS_DIRS is not None:
        edt = edtlib.EDT(DTS_POST_CPP, BINDINGS_DIRS.split("?"),
                warn_reg_unit_address_mismatch=edt_warn_flag)
    else:
        edt = None


def _warn(kconf, msg):
    print("{}:{}: WARNING: {}".format(kconf.filename, kconf.linenr, msg))


def _dt_units_to_scale(unit):
    if not unit:
        return 0
    if unit in {'k', 'K'}:
        return 10
    if unit in {'m', 'M'}:
        return 20
Example #16
0
def run():
    """
    Runs all edtlib tests. Immediately exits with status 1 and a message on
    stderr on test suite failures.
    """
    def fail(msg):
        raise Exception("test failed: " + msg)

    def verify_streq(actual, expected):
        actual = str(actual)
        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))

    edt = edtlib.EDT("test.dts", ["test-bindings"])

    #
    # Test interrupts
    #

    verify_streq(
        edt.get_dev("/interrupt-parent-test/node").interrupts,
        "[<Interrupt, name: foo, target: <Device /interrupt-parent-test/controller in 'test.dts', binding test-bindings/interrupt-3-cell.yaml>, specifier: {'one': 1, 'two': 2, 'three': 3}>, <Interrupt, name: bar, target: <Device /interrupt-parent-test/controller in 'test.dts', binding test-bindings/interrupt-3-cell.yaml>, specifier: {'one': 4, 'two': 5, 'three': 6}>]"
    )

    verify_streq(
        edt.get_dev("/interrupts-extended-test/node").interrupts,
        "[<Interrupt, target: <Device /interrupts-extended-test/controller-0 in 'test.dts', binding test-bindings/interrupt-1-cell.yaml>, specifier: {'one': 1}>, <Interrupt, target: <Device /interrupts-extended-test/controller-1 in 'test.dts', binding test-bindings/interrupt-2-cell.yaml>, specifier: {'one': 2, 'two': 3}>, <Interrupt, target: <Device /interrupts-extended-test/controller-2 in 'test.dts', binding test-bindings/interrupt-3-cell.yaml>, specifier: {'one': 4, 'two': 5, 'three': 6}>]"
    )

    verify_streq(
        edt.get_dev("/interrupt-map-test/node@0").interrupts,
        "[<Interrupt, target: <Device /interrupt-map-test/controller-0 in 'test.dts', binding test-bindings/interrupt-1-cell.yaml>, specifier: {'one': 0}>, <Interrupt, target: <Device /interrupt-map-test/controller-1 in 'test.dts', binding test-bindings/interrupt-2-cell.yaml>, specifier: {'one': 0, 'two': 1}>, <Interrupt, target: <Device /interrupt-map-test/controller-2 in 'test.dts', binding test-bindings/interrupt-3-cell.yaml>, specifier: {'one': 0, 'two': 0, 'three': 2}>]"
    )

    verify_streq(
        edt.get_dev("/interrupt-map-test/node@1").interrupts,
        "[<Interrupt, target: <Device /interrupt-map-test/controller-0 in 'test.dts', binding test-bindings/interrupt-1-cell.yaml>, specifier: {'one': 3}>, <Interrupt, target: <Device /interrupt-map-test/controller-1 in 'test.dts', binding test-bindings/interrupt-2-cell.yaml>, specifier: {'one': 0, 'two': 4}>, <Interrupt, target: <Device /interrupt-map-test/controller-2 in 'test.dts', binding test-bindings/interrupt-3-cell.yaml>, specifier: {'one': 0, 'two': 0, 'three': 5}>]"
    )

    verify_streq(
        edt.get_dev("/interrupt-map-bitops-test/node@70000000E").interrupts,
        "[<Interrupt, target: <Device /interrupt-map-bitops-test/controller in 'test.dts', binding test-bindings/interrupt-2-cell.yaml>, specifier: {'one': 3, 'two': 2}>]"
    )

    #
    # Test GPIOs
    #

    verify_streq(
        edt.get_dev("/gpio-test/node").gpios,
        "{'': [<GPIO, name: , target: <Device /gpio-test/controller-0 in 'test.dts', binding test-bindings/gpio-1-cell.yaml>, specifier: {'one': 1}>, <GPIO, name: , target: <Device /gpio-test/controller-1 in 'test.dts', binding test-bindings/gpio-2-cell.yaml>, specifier: {'one': 2, 'two': 3}>], 'foo': [<GPIO, name: foo, target: <Device /gpio-test/controller-1 in 'test.dts', binding test-bindings/gpio-2-cell.yaml>, specifier: {'one': 4, 'two': 5}>], 'bar': [<GPIO, name: bar, target: <Device /gpio-test/controller-1 in 'test.dts', binding test-bindings/gpio-2-cell.yaml>, specifier: {'one': 6, 'two': 7}>]}"
    )

    #
    # Test clocks
    #

    verify_streq(
        edt.get_dev("/clock-test/node").clocks,
        "[<Clock, name: fixed, frequency: 123, target: <Device /clock-test/fixed-clock in 'test.dts', binding test-bindings/fixed-clock.yaml>, specifier: {}>, <Clock, name: one-cell, target: <Device /clock-test/clock-1 in 'test.dts', binding test-bindings/clock-1-cell.yaml>, specifier: {'one': 1}>, <Clock, name: two-cell, target: <Device /clock-test/clock-2 in 'test.dts', binding test-bindings/clock-2-cell.yaml>, specifier: {'one': 1, 'two': 2}>]"
    )

    #
    # Test PWMs
    #

    verify_streq(
        edt.get_dev("/pwm-test/node").pwms,
        "[<PWM, name: zero-cell, target: <Device /pwm-test/pwm-0 in 'test.dts', binding test-bindings/pwm-0-cell.yaml>, specifier: {}>, <PWM, name: one-cell, target: <Device /pwm-test/pwm-1 in 'test.dts', binding test-bindings/pwm-1-cell.yaml>, specifier: {'one': 1}>]"
    )

    #
    # Test IO channels
    #

    verify_streq(
        edt.get_dev("/io-channel-test/node").iochannels,
        "[<IOChannel, name: io-channel, target: <Device /io-channel-test/io-channel in 'test.dts', binding test-bindings/io-channel.yaml>, specifier: {'one': 1}>]"
    )

    #
    # Test 'reg'
    #

    verify_streq(
        edt.get_dev("/reg-zero-address-cells/node").regs,
        "[<Register, addr: 0x0, size: 0x1>, <Register, addr: 0x0, size: 0x2>]")

    verify_streq(
        edt.get_dev("/reg-zero-size-cells/node").regs,
        "[<Register, addr: 0x1, size: 0x0>, <Register, addr: 0x2, size: 0x0>]")

    verify_streq(
        edt.get_dev("/reg-ranges/parent/node").regs,
        "[<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>]"
    )

    verify_streq(
        edt.get_dev("/reg-nested-ranges/grandparent/parent/node").regs,
        "[<Register, addr: 0x30000000200000001, size: 0x1>]")

    #
    # Test !include in bindings
    #

    verify_streq(edt.get_dev("/binding-include").description, "Parent binding")

    verify_streq(
        edt.get_dev("/binding-include").props,
        "{'compatible': <Property, name: compatible, value: ['binding-include-test']>, 'foo': <Property, name: foo, value: 0>, 'bar': <Property, name: bar, value: 1>, 'baz': <Property, name: baz, value: 2>}"
    )

    #
    # Test 'sub-node:' in binding
    #

    verify_streq(
        edt.get_dev("/parent-with-sub-node/node").description, "Sub-node test")

    verify_streq(
        edt.get_dev("/parent-with-sub-node/node").props,
        "{'foo': <Property, name: foo, value: 1>, 'bar': <Property, name: bar, value: 2>}"
    )

    #
    # Test Device.property (derived from DT and 'properties:' in the binding)
    #

    verify_streq(
        edt.get_dev("/props").props,
        r"{'compatible': <Property, name: compatible, value: ['props']>, 'nonexistent-boolean': <Property, name: nonexistent-boolean, value: False>, 'existent-boolean': <Property, name: existent-boolean, value: True>, 'int': <Property, name: int, value: 1>, 'array': <Property, name: array, value: [1, 2, 3]>, 'uint8-array': <Property, name: uint8-array, value: b'\x124'>, 'string': <Property, name: string, value: 'foo'>, 'string-array': <Property, name: string-array, value: ['foo', 'bar', 'baz']>, 'phandle-ref': <Property, name: phandle-ref, value: <Device /props/node in 'test.dts', no binding>>}"
    )

    #
    # Test having multiple directories with bindings, with a different .dts file
    #

    edt = edtlib.EDT("test-multidir.dts", ["test-bindings", "test-bindings-2"])

    verify_streq(
        edt.get_dev("/in-dir-1").binding_path, "test-bindings/multidir.yaml")

    verify_streq(
        edt.get_dev("/in-dir-2").binding_path, "test-bindings-2/multidir.yaml")

    print("all tests passed")