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)
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>)])"
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>]>]"
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")
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)
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)
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)
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))
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")
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")
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):
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}'")
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")
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
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")