scripts: dts: Change 'child/parent: bus: ...' to 'child/parent-bus:'
Instead of child: bus: foo parent: bus: bar , have child-bus: foo parent-bus: bar 'bus' is the only key that ever appears under 'child' and 'parent'. Support the old keys for backwards compatibility, with a deprecation warning if they're used. Also add 'child/parent-bus' tests to the edtlib test suite. It was untested before. I also considered putting more stuff under 'child' and 'parent', but there's not much point when there's just a few keys I think. Top-level stuff is cleaner and easier to read. I'm planning to add a 'child-binding' key a bit later (like 'sub-node', but more flexible), and child-* is consistent with that. Also add an unrelated test-bindings/grandchild-3.yaml that was accidentally left out earlier. Signed-off-by: Ulf Magnusson <Ulf.Magnusson@nordicsemi.no>
This commit is contained in:
parent
af8df4f764
commit
1ebe945643
25 changed files with 156 additions and 54 deletions
|
@ -46,19 +46,19 @@ compatible: "manufacturer,device"
|
|||
# 'required: true' is always respected.
|
||||
include: other.yaml # or [other1.yaml, other2.yaml]
|
||||
|
||||
# If the node describes a bus, then the bus type should be given, like below
|
||||
child:
|
||||
bus: <string describing bus type, e.g. "i2c">
|
||||
# If the node describes a bus, then the bus type should be given, like below.
|
||||
# The name has "child" in it since it describes the bus children of the node
|
||||
# appear on.
|
||||
child-bus: <string describing bus type, e.g. "i2c">
|
||||
|
||||
# If the node appears on a bus, then the bus type should be given, like below.
|
||||
#
|
||||
# When looking for a binding for a node, the code checks if the binding for the
|
||||
# parent node contains 'child: bus: <bus type>'. If it does, then only bindings
|
||||
# with a matching 'parent: bus: <bus type>' are considered. This allows the
|
||||
# same type of device to have different bindings depending on what bus it
|
||||
# appears on.
|
||||
parent:
|
||||
bus: <string describing bus type, e.g. "i2c">
|
||||
# parent node contains 'child-bus: <bus type>'. If it does, then only bindings
|
||||
# with a matching 'parent-bus: <bus type>' are considered. This allows the same
|
||||
# type of device to have different bindings depending on what bus it appears
|
||||
# on.
|
||||
parent-bus: <string describing bus type, e.g. "i2c">
|
||||
|
||||
# 'sub-node' is used to simplify cases where a node has children that can all
|
||||
# use the same binding. The contents of 'sub-node' becomes the binding for each
|
||||
|
|
|
@ -11,8 +11,7 @@ compatible: "zephyr,bt-hci-spi-slave"
|
|||
|
||||
include: base.yaml
|
||||
|
||||
parent:
|
||||
bus: spi
|
||||
parent-bus: spi
|
||||
|
||||
properties:
|
||||
irq-gpios:
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
|
||||
include: base.yaml
|
||||
|
||||
child:
|
||||
bus: can
|
||||
child-bus: can
|
||||
|
||||
properties:
|
||||
"#address-cells":
|
||||
|
|
|
@ -5,8 +5,7 @@
|
|||
|
||||
include: base.yaml
|
||||
|
||||
parent:
|
||||
bus: can
|
||||
parent-bus: can
|
||||
|
||||
properties:
|
||||
reg:
|
||||
|
|
|
@ -5,8 +5,7 @@
|
|||
|
||||
include: base.yaml
|
||||
|
||||
child:
|
||||
bus: espi
|
||||
child-bus: espi
|
||||
|
||||
properties:
|
||||
label:
|
||||
|
|
|
@ -6,8 +6,7 @@ compatible: "holtek,ht16k33-keyscan"
|
|||
|
||||
include: base.yaml
|
||||
|
||||
parent:
|
||||
bus: ht16k33
|
||||
parent-bus: ht16k33
|
||||
|
||||
properties:
|
||||
reg:
|
||||
|
|
|
@ -5,8 +5,7 @@
|
|||
|
||||
include: base.yaml
|
||||
|
||||
child:
|
||||
bus: i2c
|
||||
child-bus: i2c
|
||||
|
||||
properties:
|
||||
"#address-cells":
|
||||
|
|
|
@ -5,8 +5,7 @@
|
|||
|
||||
include: base.yaml
|
||||
|
||||
parent:
|
||||
bus: i2c
|
||||
parent-bus: i2c
|
||||
|
||||
properties:
|
||||
reg:
|
||||
|
|
|
@ -5,8 +5,7 @@
|
|||
|
||||
include: base.yaml
|
||||
|
||||
child:
|
||||
bus: i2s
|
||||
child-bus: i2s
|
||||
|
||||
properties:
|
||||
"#address-cells":
|
||||
|
|
|
@ -5,8 +5,7 @@
|
|||
|
||||
include: base.yaml
|
||||
|
||||
parent:
|
||||
bus: i2s
|
||||
parent-bus: i2s
|
||||
|
||||
properties:
|
||||
reg:
|
||||
|
|
|
@ -6,8 +6,7 @@ compatible: "holtek,ht16k33"
|
|||
|
||||
include: i2c-device.yaml
|
||||
|
||||
child:
|
||||
bus: ht16k33
|
||||
child-bus: ht16k33
|
||||
|
||||
properties:
|
||||
"#address-cells":
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
|
||||
include: base.yaml
|
||||
|
||||
child:
|
||||
bus: uart
|
||||
child-bus: uart
|
||||
|
||||
properties:
|
||||
clock-frequency:
|
||||
|
|
|
@ -5,8 +5,7 @@
|
|||
|
||||
include: base.yaml
|
||||
|
||||
parent:
|
||||
bus: uart
|
||||
parent-bus: uart
|
||||
|
||||
properties:
|
||||
label:
|
||||
|
|
|
@ -5,8 +5,7 @@
|
|||
|
||||
include: base.yaml
|
||||
|
||||
child:
|
||||
bus: spi
|
||||
child-bus: spi
|
||||
|
||||
properties:
|
||||
clock-frequency:
|
||||
|
|
|
@ -5,8 +5,7 @@
|
|||
|
||||
include: base.yaml
|
||||
|
||||
parent:
|
||||
bus: spi
|
||||
parent-bus: spi
|
||||
|
||||
properties:
|
||||
reg:
|
||||
|
|
|
@ -580,15 +580,25 @@ class Device:
|
|||
self.description = None
|
||||
|
||||
def _bus_from_parent_binding(self):
|
||||
# _init_binding() helper. Returns the bus specified by
|
||||
# 'child: bus: ...' in the parent binding, or None if missing.
|
||||
# _init_binding() helper. Returns the bus specified by 'child-bus: ...'
|
||||
# in the parent binding (or the legacy 'child: bus: ...'), or None if
|
||||
# missing.
|
||||
|
||||
if not self.parent:
|
||||
return None
|
||||
|
||||
binding = self.parent._binding
|
||||
if binding and "child" in binding:
|
||||
return binding["child"].get("bus")
|
||||
if not binding:
|
||||
return None
|
||||
|
||||
if "child-bus" in binding:
|
||||
return binding["child-bus"]
|
||||
|
||||
# Legacy key
|
||||
if "child" in binding:
|
||||
# _check_binding() has checked that the "bus" key exists
|
||||
return binding["child"]["bus"]
|
||||
|
||||
return None
|
||||
|
||||
def _init_props(self):
|
||||
|
@ -1307,12 +1317,20 @@ def _binding_compat(binding, binding_path):
|
|||
|
||||
|
||||
def _binding_bus(binding):
|
||||
# Returns the bus specified in 'binding' (the bus the device described by
|
||||
# 'binding' is on), e.g. "i2c", or None if 'binding' is None or doesn't
|
||||
# specify a bus
|
||||
# Returns the bus specified by 'parent-bus: ...' in the binding (or the
|
||||
# legacy 'parent: bus: ...'), or None if missing
|
||||
|
||||
if not binding:
|
||||
return None
|
||||
|
||||
if "parent-bus" in binding:
|
||||
return binding["parent-bus"]
|
||||
|
||||
# Legacy key
|
||||
if "parent" in binding:
|
||||
# _check_binding() has checked that the "bus" key exists
|
||||
return binding["parent"]["bus"]
|
||||
|
||||
if binding and "parent" in binding:
|
||||
return binding["parent"].get("bus")
|
||||
return None
|
||||
|
||||
|
||||
|
@ -1421,7 +1439,7 @@ def _check_binding(binding, binding_path):
|
|||
.format(prop, binding_path))
|
||||
|
||||
ok_top = {"title", "description", "compatible", "properties", "#cells",
|
||||
"parent", "child", "sub-node"}
|
||||
"parent-bus", "child-bus", "parent", "child", "sub-node"}
|
||||
|
||||
for prop in binding:
|
||||
if prop not in ok_top:
|
||||
|
@ -1429,8 +1447,20 @@ def _check_binding(binding, binding_path):
|
|||
.format(prop, binding_path, ", ".join(ok_top)))
|
||||
|
||||
for pc in "parent", "child":
|
||||
# 'parent/child-bus:'
|
||||
bus_key = pc + "-bus"
|
||||
if bus_key in binding and \
|
||||
not isinstance(binding[bus_key], str):
|
||||
_warn("malformed '{}:' value in {}, expected string"
|
||||
.format(bus_key, binding_path))
|
||||
|
||||
# Legacy 'child/parent: bus: ...' keys
|
||||
if pc in binding:
|
||||
# Just 'bus:' is expected at the moment
|
||||
_warn("'{0}: bus: ...' in {1} is deprecated and will be removed - "
|
||||
"please use a top-level '{0}-bus:' key instead (see "
|
||||
"binding-template.yaml)".format(pc, binding_path))
|
||||
|
||||
# Just 'bus:' is expected
|
||||
if binding[pc].keys() != {"bus"}:
|
||||
_err("expected (just) 'bus:' in '{}:' in {}"
|
||||
.format(pc, binding_path))
|
||||
|
|
|
@ -317,6 +317,11 @@ def get_binding(node_path):
|
|||
return parent_binding['sub-node']
|
||||
|
||||
# look for a bus-specific binding
|
||||
|
||||
if 'child-bus' in parent_binding:
|
||||
bus = parent_binding['child-bus']
|
||||
return bus_bindings[bus][compat]
|
||||
|
||||
if 'child' in parent_binding and 'bus' in parent_binding['child']:
|
||||
bus = parent_binding['child']['bus']
|
||||
return bus_bindings[bus][compat]
|
||||
|
|
|
@ -65,7 +65,8 @@ def generate_prop_defines(node_path, prop):
|
|||
# named 'prop' on the device tree node at 'node_path'
|
||||
|
||||
binding = get_binding(node_path)
|
||||
if 'parent' in binding and 'bus' in binding['parent']:
|
||||
if 'parent-bus' in binding or \
|
||||
'parent' in binding and 'bus' in binding['parent']:
|
||||
# If the binding specifies a parent for the node, then include the
|
||||
# parent in the #define's generated for the properties
|
||||
parent_path = get_parent_path(node_path)
|
||||
|
@ -154,7 +155,8 @@ def generate_bus_defines(node_path):
|
|||
# bus: ...
|
||||
|
||||
binding = get_binding(node_path)
|
||||
if not ('parent' in binding and 'bus' in binding['parent']):
|
||||
if not ('parent-bus' in binding or
|
||||
'parent' in binding and 'bus' in binding['parent']):
|
||||
return
|
||||
|
||||
parent_path = get_parent_path(node_path)
|
||||
|
@ -162,17 +164,24 @@ def generate_bus_defines(node_path):
|
|||
# Check that parent has matching child bus value
|
||||
try:
|
||||
parent_binding = get_binding(parent_path)
|
||||
parent_bus = parent_binding['child']['bus']
|
||||
if 'child-bus' in parent_binding:
|
||||
parent_bus = parent_binding['child-bus']
|
||||
else:
|
||||
parent_bus = parent_binding['child']['bus']
|
||||
except (KeyError, TypeError):
|
||||
raise Exception("{0} defines parent {1} as bus master, but {1} is not "
|
||||
"configured as bus master in binding"
|
||||
.format(node_path, parent_path))
|
||||
|
||||
if parent_bus != binding['parent']['bus']:
|
||||
if 'parent-bus' in binding:
|
||||
bus = binding['parent-bus']
|
||||
else:
|
||||
bus = binding['parent']['bus']
|
||||
|
||||
if parent_bus != bus:
|
||||
raise Exception("{0} defines parent {1} as {2} bus master, but {1} is "
|
||||
"configured as {3} bus master"
|
||||
.format(node_path, parent_path,
|
||||
binding['parent']['bus'], parent_bus))
|
||||
.format(node_path, parent_path, bus, parent_bus))
|
||||
|
||||
# Generate *_BUS_NAME #define
|
||||
extract_bus_name(
|
||||
|
@ -358,6 +367,9 @@ def load_bindings(root, binding_dirs):
|
|||
if compat not in compats:
|
||||
compats.append(compat)
|
||||
|
||||
if 'parent-bus' in binding:
|
||||
bus_to_binding[binding['parent-bus']][compat] = binding
|
||||
|
||||
if 'parent' in binding:
|
||||
bus_to_binding[binding['parent']['bus']][compat] = binding
|
||||
|
||||
|
|
8
scripts/dts/test-bindings/bar-bus.yaml
Normal file
8
scripts/dts/test-bindings/bar-bus.yaml
Normal file
|
@ -0,0 +1,8 @@
|
|||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
title: Bar bus controller
|
||||
description: Bar bus controller
|
||||
|
||||
compatible: "bar-bus"
|
||||
|
||||
child-bus: "bar"
|
8
scripts/dts/test-bindings/device-on-bar-bus.yaml
Normal file
8
scripts/dts/test-bindings/device-on-bar-bus.yaml
Normal file
|
@ -0,0 +1,8 @@
|
|||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
title: Device on bar bus
|
||||
description: Device on bar bus
|
||||
|
||||
compatible: "on-bus"
|
||||
|
||||
parent-bus: "bar"
|
8
scripts/dts/test-bindings/device-on-foo-bus.yaml
Normal file
8
scripts/dts/test-bindings/device-on-foo-bus.yaml
Normal file
|
@ -0,0 +1,8 @@
|
|||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
title: Device on foo bus
|
||||
description: Device on foo bus
|
||||
|
||||
compatible: "on-bus"
|
||||
|
||||
parent-bus: "foo"
|
8
scripts/dts/test-bindings/foo-bus.yaml
Normal file
8
scripts/dts/test-bindings/foo-bus.yaml
Normal file
|
@ -0,0 +1,8 @@
|
|||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
title: Foo bus controller
|
||||
description: Foo bus controller
|
||||
|
||||
compatible: "foo-bus"
|
||||
|
||||
child-bus: "foo"
|
6
scripts/dts/test-bindings/grandchild-3.yaml
Normal file
6
scripts/dts/test-bindings/grandchild-3.yaml
Normal file
|
@ -0,0 +1,6 @@
|
|||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
properties:
|
||||
qaz:
|
||||
required: true
|
||||
type: int
|
|
@ -318,6 +318,27 @@
|
|||
default-not-used = <234>;
|
||||
};
|
||||
|
||||
//
|
||||
// For testing 'child-bus:' and 'parent-bus:'
|
||||
//
|
||||
|
||||
buses {
|
||||
// The nodes below will map to different bindings since they
|
||||
// appear on different buses
|
||||
foo-bus {
|
||||
compatible = "foo-bus";
|
||||
node {
|
||||
compatible = "on-bus";
|
||||
};
|
||||
};
|
||||
bar-bus {
|
||||
compatible = "bar-bus";
|
||||
node {
|
||||
compatible = "on-bus";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
//
|
||||
// Parent with 'sub-node:' in binding
|
||||
//
|
||||
|
|
|
@ -105,6 +105,16 @@ def run():
|
|||
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 'sub-node:' in binding
|
||||
#
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue