From e2510831f8ee22da837bd2327c1f6d170d802c81 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 26 Aug 2026 13:15:53 +0200 Subject: dtc: dt-check-style: Handle sorting of top-level nodes and properties Top-level DTS (but not example in the bindings) has only two nodes with unit-addresses: memory@ and soc@. There are two special cases here, in terms of coding style: 1. The unit-address of memory is often not known thus set to @0, because it is filled up by bootloader. 2. There is mixture of non-unit-address and unit-address nodes. Therefore usually the DTS chooses for the top-level part sorting by the node name, not the unit address. Also the properties have one exception: 'model' property is supposed to be before the 'compatible'. This cannot be applied to the entire DTS, because sound cards have also 'model' where it is supposed to follow standard rules (after the 'compatible'). Root node is just special. Signed-off-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20260826-n-dts-style-checker-continued-v6-1-f270b1e81f8e@oss.qualcomm.com Signed-off-by: Rob Herring (Arm) --- scripts/dtc/dt-check-style | 70 ++++++++++++++++++---- .../bad/dts-child-name-order.dtso | 33 ++++++++++ .../dt-style-selftest/bad/dts-digit-node-order.dts | 40 +++++++++++++ .../bad/dts-digit-node-order.dtso | 41 +++++++++++++ .../bad/dts-extend-node-child-name-order.dtso | 26 ++++++++ .../bad/dts-extend-node-digit-node-order.dtso | 34 +++++++++++ .../dt-style-selftest/bad/dts-property-order.dts | 15 +++++ .../dt-style-selftest/bad/dts-property-order.dtso | 59 ++++++++++++++++++ .../expected/dts-child-name-order.dts.txt | 1 + .../expected/dts-child-name-order.dtso.txt | 3 + .../expected/dts-digit-node-order.dts.txt | 2 + .../expected/dts-digit-node-order.dtso.txt | 2 + .../dts-extend-node-child-name-order.dtso.txt | 2 + .../dts-extend-node-digit-node-order.dtso.txt | 2 + .../expected/dts-property-order.dts.txt | 14 +++-- .../expected/dts-property-order.dtso.txt | 10 ++++ .../good/dts-child-name-order.dtso | 44 ++++++++++++++ .../good/dts-digit-node-order.dts | 3 - .../good/dts-digit-node-order.dtso | 59 ++++++++++++++++++ .../good/dts-extend-node-child-name-order.dtso | 26 ++++++++ .../good/dts-extend-node-digit-node-order.dtso | 34 +++++++++++ .../dt-style-selftest/good/dts-property-order.dts | 5 ++ .../dt-style-selftest/good/dts-property-order.dtso | 47 +++++++++++++++ 23 files changed, 554 insertions(+), 18 deletions(-) create mode 100644 scripts/dtc/dt-style-selftest/bad/dts-child-name-order.dtso create mode 100644 scripts/dtc/dt-style-selftest/bad/dts-digit-node-order.dts create mode 100644 scripts/dtc/dt-style-selftest/bad/dts-digit-node-order.dtso create mode 100644 scripts/dtc/dt-style-selftest/bad/dts-extend-node-child-name-order.dtso create mode 100644 scripts/dtc/dt-style-selftest/bad/dts-extend-node-digit-node-order.dtso create mode 100644 scripts/dtc/dt-style-selftest/bad/dts-property-order.dtso create mode 100644 scripts/dtc/dt-style-selftest/expected/dts-child-name-order.dtso.txt create mode 100644 scripts/dtc/dt-style-selftest/expected/dts-digit-node-order.dts.txt create mode 100644 scripts/dtc/dt-style-selftest/expected/dts-digit-node-order.dtso.txt create mode 100644 scripts/dtc/dt-style-selftest/expected/dts-extend-node-child-name-order.dtso.txt create mode 100644 scripts/dtc/dt-style-selftest/expected/dts-extend-node-digit-node-order.dtso.txt create mode 100644 scripts/dtc/dt-style-selftest/expected/dts-property-order.dtso.txt create mode 100644 scripts/dtc/dt-style-selftest/good/dts-child-name-order.dtso create mode 100644 scripts/dtc/dt-style-selftest/good/dts-digit-node-order.dtso create mode 100644 scripts/dtc/dt-style-selftest/good/dts-extend-node-child-name-order.dtso create mode 100644 scripts/dtc/dt-style-selftest/good/dts-extend-node-digit-node-order.dtso create mode 100644 scripts/dtc/dt-style-selftest/good/dts-property-order.dtso (limited to 'scripts') diff --git a/scripts/dtc/dt-check-style b/scripts/dtc/dt-check-style index 96deffc0d8a7..5a9985baa051 100755 --- a/scripts/dtc/dt-check-style +++ b/scripts/dtc/dt-check-style @@ -77,24 +77,26 @@ def is_preprocessor(stripped): class DtsLine: - __slots__ = ('lineno', 'raw', 'linetype', 'indent_str', 'stripped', + __slots__ = ('lineno', 'raw', 'linetype', 'indent_str', 'stripped', 'is_root', 'prop_name', 'continuations', - 'node_name', 'node_addr', 'label', 'ref_name', 'depth', + 'node_name', 'node_addr', 'label', 'ref_name', 'parent', 'depth', 'closures') - def __init__(self, lineno, raw, linetype, depth, indent_str, stripped): + def __init__(self, lineno, raw, linetype, depth, indent_str, stripped, is_root = False): self.lineno = lineno # 1-based within the block self.raw = raw self.linetype = linetype self.indent_str = indent_str # leading whitespace as-is self.depth = depth self.stripped = stripped + self.is_root = is_root self.prop_name = None self.continuations = [] self.node_name = None self.node_addr = None self.label = None self.ref_name = None + self.parent = None # DtsLine of parent node self.closures = 1 # count of '}' on a NODE_CLOSE line @@ -228,7 +230,10 @@ def classify_lines(text): continue if code.endswith('{'): - dl = DtsLine(i, raw, LineType.NODE_OPEN, depth, indent_str, code) + is_root = False + if re.search(r'&{/}\s*{', code) or re.search(r'^/\s*\{$', code): + is_root = True + dl = DtsLine(i, raw, LineType.NODE_OPEN, depth, indent_str, code, is_root=is_root) parse_node_header(dl) out.append(dl) depth += 1 @@ -491,16 +496,24 @@ def _walk_bodies(lines): """Yield lists of immediate-child NODE_OPEN lines for each node body in the input. Skips ref-nodes (&label) since those don't have an intrinsic ordering.""" + # Array of stacked nodes (parent/child) body_stack = [[]] + # Current stack of nodes, purely to track parent relationship for each node + node_stack = [] + parent_dl = None for dl in lines: if dl.linetype == LineType.NODE_OPEN: + dl.parent = parent_dl + node_stack.append(dl) body_stack[-1].append(dl) body_stack.append([]) + parent_dl = dl continue if dl.linetype == LineType.NODE_CLOSE: if len(body_stack) <= 1: # Unbalanced; ignore to avoid crashing on malformed input continue + parent_dl = node_stack.pop().parent yield body_stack.pop() continue while body_stack: @@ -521,12 +534,18 @@ def _natural_sort_key(s): def check_child_address_order(ctx): """Addressed siblings (foo@N) must appear in ascending address - order within their parent node body.""" + order within their parent node body. + Exception: Top-level in DTS follows name order, regardless of unit address + in memory@N and soc@N nodes + """ for children in _walk_bodies(ctx.lines): addressed = [] for c in children: if c.node_addr is None: continue + if c.parent and c.parent.is_root: + # Top-level does not use unit address sorting usually + continue try: parts = tuple(int(p, 16) for p in c.node_addr.split(',')) except ValueError: @@ -544,12 +563,16 @@ def check_child_name_order(ctx): """Unaddressed siblings must appear in natural-sort order by node name within their parent node body. Addressed children are scoped by check_child_address_order; reference nodes (&label { ... }) and - the root node are skipped.""" + the root node are skipped. + However root node has children with and without unit address, and + sorting should be only by name.""" for children in _walk_bodies(ctx.lines): unaddressed = [] for c in children: if c.node_addr is not None: - continue + # Skip nodes with unit address, except when sorting top-level + if not c.parent or not c.parent.is_root: + continue if c.node_name in (None, '/'): continue if c.ref_name is not None: @@ -591,6 +614,30 @@ def _property_bucket(name): return (5 if ',' in stripped else 4, None) +def _property_bucket_root(name): + """Return the canonical bucket index for a property: + 0 model (for root nodes only) + 1 compatible + Plus a sub-key inside the bucket for fixed slots (device_type, compatible, + reg, reg-names, ranges, status). 'standard' and 'vendor' return None for + the sub-key, signalling that the within-bucket key is computed by + the pairing rules.""" + stripped = name.lstrip('#') + if name == 'model': + return (0, 0) + if name == 'compatible': + return (1, 0) + if name == 'reg': + return (2, 0) + if name == 'reg-names': + return (2, 1) + if name == 'ranges': + return (3, 0) + if name == 'status': + return (6, 0) + return (5 if ',' in stripped else 4, None) + + # Declarative pairing rules: each is a callable # (name, all_names) -> anchor_name_or_None # If a rule returns an anchor, the property sorts immediately after the @@ -627,13 +674,16 @@ def _pair_x_names(name, all_names): PAIRING_RULES = (_pair_pinctrl_names, _pair_x_names) -def _property_sort_key(name, all_names): +def _property_sort_key(dl, name, all_names): """Sort key for a property among its node-body siblings. Format: (bucket, within_key, tiebreak). 'within_key' for standard/vendor buckets follows pairing rules: a property paired with anchor X sorts as if it were X with a higher tiebreak.""" - bucket, fixed_sub = _property_bucket(name) + if dl.is_root: + bucket, fixed_sub = _property_bucket_root(name) + else: + bucket, fixed_sub = _property_bucket(name) if fixed_sub is not None: return (bucket, (), fixed_sub) @@ -668,7 +718,7 @@ def check_property_order(ctx): if len(props) < 2: continue all_names = [p.prop_name for p in props] - keyed = [(p, _property_sort_key(p.prop_name, all_names)) + keyed = [(p, _property_sort_key(dl, p.prop_name, all_names)) for p in props] for k in range(1, len(keyed)): if keyed[k][1] < keyed[k - 1][1]: diff --git a/scripts/dtc/dt-style-selftest/bad/dts-child-name-order.dtso b/scripts/dtc/dt-style-selftest/bad/dts-child-name-order.dtso new file mode 100644 index 000000000000..74b49be69e98 --- /dev/null +++ b/scripts/dtc/dt-style-selftest/bad/dts-child-name-order.dtso @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +/dts-v1/; +/plugin/; + +&{/} { + #address-cells = <1>; + #size-cells = <1>; + + pmu { + compatible = "example,pmu"; + + /* Include labels to be sure they do not affect sorting */ + foo: foo { + label = "foo"; + }; + + label_bar: bar { + label = "bar"; + }; + }; + + memory@a0000000 { + device_type = "memory"; + reg = <0x0 0xa0000000 0x0 0x0>; + }; + + pmu-2 { + compatible = "example,pmu"; + + /* Just reference labels to avoid strict warnings */ + example,foo = <&foo>, <&label_bar>; + }; +}; diff --git a/scripts/dtc/dt-style-selftest/bad/dts-digit-node-order.dts b/scripts/dtc/dt-style-selftest/bad/dts-digit-node-order.dts new file mode 100644 index 000000000000..74c956398324 --- /dev/null +++ b/scripts/dtc/dt-style-selftest/bad/dts-digit-node-order.dts @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + memory@a0000000 { + device_type = "memory"; + reg = <0x0 0xa0000000 0x0 0x0>; + }; + + pmu { + compatible = "example,pmu"; + }; + + soc@0 { + compatible = "simple-bus"; + ranges = <0 0 0 0xc0000000>; + + #address-cells = <1>; + #size-cells = <1>; + + serial@20000 { + compatible = "example,serial"; + reg = <0x20000 0x1000>; + }; + + interrupt-controller@10000 { + compatible = "example,intc"; + reg = <0x10000 0x1000>; + interrupts = <1 2 3>; + }; + + serial@30000 { + compatible = "example,serial"; + reg = <0x30000 0x1000>; + }; + }; +}; diff --git a/scripts/dtc/dt-style-selftest/bad/dts-digit-node-order.dtso b/scripts/dtc/dt-style-selftest/bad/dts-digit-node-order.dtso new file mode 100644 index 000000000000..052c02935a45 --- /dev/null +++ b/scripts/dtc/dt-style-selftest/bad/dts-digit-node-order.dtso @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +/dts-v1/; +/plugin/; + +&{/} { + #address-cells = <1>; + #size-cells = <1>; + + memory@a0000000 { + device_type = "memory"; + reg = <0x0 0xa0000000 0x0 0x0>; + }; + + pmu { + compatible = "example,pmu"; + }; + + soc@0 { + compatible = "simple-bus"; + ranges = <0 0 0 0xc0000000>; + + #address-cells = <1>; + #size-cells = <1>; + + serial@20000 { + compatible = "example,serial"; + reg = <0x20000 0x1000>; + }; + + interrupt-controller@10000 { + compatible = "example,intc"; + reg = <0x10000 0x1000>; + interrupts = <1 2 3>; + }; + + serial@30000 { + compatible = "example,serial"; + reg = <0x30000 0x1000>; + }; + }; +}; diff --git a/scripts/dtc/dt-style-selftest/bad/dts-extend-node-child-name-order.dtso b/scripts/dtc/dt-style-selftest/bad/dts-extend-node-child-name-order.dtso new file mode 100644 index 000000000000..d9cf670f19f6 --- /dev/null +++ b/scripts/dtc/dt-style-selftest/bad/dts-extend-node-child-name-order.dtso @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +/dts-v1/; +/plugin/; + +&{/} { + #address-cells = <1>; + #size-cells = <1>; + + pmu { + compatible = "example,pmu"; + + /* Just reference labels to avoid strict warnings */ + example,foo = <&foo>, <&label_bar>; + }; +}; + +&pmu { + /* Include labels to be sure they do not affect sorting */ + foo: foo { + label = "foo"; + }; + + label_bar: bar { + label = "bar"; + }; +}; diff --git a/scripts/dtc/dt-style-selftest/bad/dts-extend-node-digit-node-order.dtso b/scripts/dtc/dt-style-selftest/bad/dts-extend-node-digit-node-order.dtso new file mode 100644 index 000000000000..4b2cf60e5a92 --- /dev/null +++ b/scripts/dtc/dt-style-selftest/bad/dts-extend-node-digit-node-order.dtso @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +/dts-v1/; +/plugin/; + +&{/} { + #address-cells = <1>; + #size-cells = <1>; + + soc: soc@0 { + compatible = "simple-bus"; + ranges = <0 0 0 0xc0000000>; + + #address-cells = <1>; + #size-cells = <1>; + }; +}; + +&soc { + serial@20000 { + compatible = "example,serial"; + reg = <0x20000 0x1000>; + }; + + interrupt-controller@10000 { + compatible = "example,intc"; + reg = <0x10000 0x1000>; + interrupts = <1 2 3>; + }; + + serial@30000 { + compatible = "example,serial"; + reg = <0x30000 0x1000>; + }; +}; diff --git a/scripts/dtc/dt-style-selftest/bad/dts-property-order.dts b/scripts/dtc/dt-style-selftest/bad/dts-property-order.dts index f31abb6ceae4..ebe561e38766 100644 --- a/scripts/dtc/dt-style-selftest/bad/dts-property-order.dts +++ b/scripts/dtc/dt-style-selftest/bad/dts-property-order.dts @@ -6,6 +6,11 @@ /dts-v1/; / { + compatible = "example,test-board", "example,test-soc"; + model = "DT style selftest"; + qcom,board-id = <8 0>; + chassis-type = "handset"; + cpus { #address-cells = <1>; #size-cells = <0>; @@ -41,3 +46,13 @@ }; }; }; + +/ { + compatible = "example,test-board", "example,test-soc"; + model = "DT style selftest"; +}; + +/{ + compatible = "example,test-board", "example,test-soc"; + model = "DT style selftest"; +}; diff --git a/scripts/dtc/dt-style-selftest/bad/dts-property-order.dtso b/scripts/dtc/dt-style-selftest/bad/dts-property-order.dtso new file mode 100644 index 000000000000..64604fa6b8c3 --- /dev/null +++ b/scripts/dtc/dt-style-selftest/bad/dts-property-order.dtso @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +/* + * Test fixture: Incorrect property order + */ + +/dts-v1/; +/plugin/; + +&{/} { + compatible = "example,test-board", "example,test-soc"; + model = "DT style selftest"; + qcom,board-id = <8 0>; + chassis-type = "handset"; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + reg = <0x0 0x0>; + compatible = "arm,cortex-a57"; + device_type = "cpu"; + enable-method = "psci"; + }; + }; + + pmu { + compatible = "example,pmu"; + + status = "disabled"; + dma-coherent; + }; + + soc@0 { + ranges = <0 0 0 0xc0000000>; + compatible = "simple-bus"; + + #address-cells = <1>; + #size-cells = <1>; + + interrupt-controller@10000 { + reg = <0x10000 0x1000>; + interrupts = <1 2 3>, + <4 5 6>, + <7 8 9>; + compatible = "example,intc"; + }; + }; +}; + +&{/} { + compatible = "example,test-board", "example,test-soc"; + model = "DT style selftest"; +}; + +&{/}{ + compatible = "example,test-board", "example,test-soc"; + model = "DT style selftest"; +}; diff --git a/scripts/dtc/dt-style-selftest/expected/dts-child-name-order.dts.txt b/scripts/dtc/dt-style-selftest/expected/dts-child-name-order.dts.txt index e2eea0862102..312a45ed913a 100644 --- a/scripts/dtc/dt-style-selftest/expected/dts-child-name-order.dts.txt +++ b/scripts/dtc/dt-style-selftest/expected/dts-child-name-order.dts.txt @@ -1,2 +1,3 @@ # mode=strict bad/dts-child-name-order.dts:16: [child-name-order] child node 'bar' out of name order +bad/dts-child-name-order.dts:21: [child-name-order] child node 'memory' out of name order diff --git a/scripts/dtc/dt-style-selftest/expected/dts-child-name-order.dtso.txt b/scripts/dtc/dt-style-selftest/expected/dts-child-name-order.dtso.txt new file mode 100644 index 000000000000..e44ceb24ece8 --- /dev/null +++ b/scripts/dtc/dt-style-selftest/expected/dts-child-name-order.dtso.txt @@ -0,0 +1,3 @@ +# mode=strict +bad/dts-child-name-order.dtso:17: [child-name-order] child node 'bar' out of name order +bad/dts-child-name-order.dtso:22: [child-name-order] child node 'memory' out of name order diff --git a/scripts/dtc/dt-style-selftest/expected/dts-digit-node-order.dts.txt b/scripts/dtc/dt-style-selftest/expected/dts-digit-node-order.dts.txt new file mode 100644 index 000000000000..1f41acdea0b0 --- /dev/null +++ b/scripts/dtc/dt-style-selftest/expected/dts-digit-node-order.dts.txt @@ -0,0 +1,2 @@ +# mode=strict +bad/dts-digit-node-order.dts:29: [child-address-order] child node @10000 out of address order diff --git a/scripts/dtc/dt-style-selftest/expected/dts-digit-node-order.dtso.txt b/scripts/dtc/dt-style-selftest/expected/dts-digit-node-order.dtso.txt new file mode 100644 index 000000000000..21db32f6e639 --- /dev/null +++ b/scripts/dtc/dt-style-selftest/expected/dts-digit-node-order.dtso.txt @@ -0,0 +1,2 @@ +# mode=strict +bad/dts-digit-node-order.dtso:30: [child-address-order] child node @10000 out of address order diff --git a/scripts/dtc/dt-style-selftest/expected/dts-extend-node-child-name-order.dtso.txt b/scripts/dtc/dt-style-selftest/expected/dts-extend-node-child-name-order.dtso.txt new file mode 100644 index 000000000000..d7941a891135 --- /dev/null +++ b/scripts/dtc/dt-style-selftest/expected/dts-extend-node-child-name-order.dtso.txt @@ -0,0 +1,2 @@ +# mode=strict +bad/dts-extend-node-child-name-order.dtso:23: [child-name-order] child node 'bar' out of name order diff --git a/scripts/dtc/dt-style-selftest/expected/dts-extend-node-digit-node-order.dtso.txt b/scripts/dtc/dt-style-selftest/expected/dts-extend-node-digit-node-order.dtso.txt new file mode 100644 index 000000000000..408796d5bb03 --- /dev/null +++ b/scripts/dtc/dt-style-selftest/expected/dts-extend-node-digit-node-order.dtso.txt @@ -0,0 +1,2 @@ +# mode=strict +bad/dts-extend-node-digit-node-order.dtso:24: [child-address-order] child node @10000 out of address order diff --git a/scripts/dtc/dt-style-selftest/expected/dts-property-order.dts.txt b/scripts/dtc/dt-style-selftest/expected/dts-property-order.dts.txt index 4bc21328625f..aab048a0ba3b 100644 --- a/scripts/dtc/dt-style-selftest/expected/dts-property-order.dts.txt +++ b/scripts/dtc/dt-style-selftest/expected/dts-property-order.dts.txt @@ -1,6 +1,10 @@ # mode=strict -bad/dts-property-order.dts:15: [property-order] property 'compatible' out of canonical order (should sort before 'reg') -bad/dts-property-order.dts:16: [property-order] property 'device_type' out of canonical order (should sort before 'compatible') -bad/dts-property-order.dts:25: [property-order] property 'dma-coherent' out of canonical order (should sort before 'status') -bad/dts-property-order.dts:30: [property-order] property 'compatible' out of canonical order (should sort before 'ranges') -bad/dts-property-order.dts:40: [property-order] property 'compatible' out of canonical order (should sort before 'interrupts') +bad/dts-property-order.dts:10: [property-order] property 'model' out of canonical order (should sort before 'compatible') +bad/dts-property-order.dts:12: [property-order] property 'chassis-type' out of canonical order (should sort before 'qcom,board-id') +bad/dts-property-order.dts:20: [property-order] property 'compatible' out of canonical order (should sort before 'reg') +bad/dts-property-order.dts:21: [property-order] property 'device_type' out of canonical order (should sort before 'compatible') +bad/dts-property-order.dts:30: [property-order] property 'dma-coherent' out of canonical order (should sort before 'status') +bad/dts-property-order.dts:35: [property-order] property 'compatible' out of canonical order (should sort before 'ranges') +bad/dts-property-order.dts:45: [property-order] property 'compatible' out of canonical order (should sort before 'interrupts') +bad/dts-property-order.dts:52: [property-order] property 'model' out of canonical order (should sort before 'compatible') +bad/dts-property-order.dts:57: [property-order] property 'model' out of canonical order (should sort before 'compatible') diff --git a/scripts/dtc/dt-style-selftest/expected/dts-property-order.dtso.txt b/scripts/dtc/dt-style-selftest/expected/dts-property-order.dtso.txt new file mode 100644 index 000000000000..e9b3ac985718 --- /dev/null +++ b/scripts/dtc/dt-style-selftest/expected/dts-property-order.dtso.txt @@ -0,0 +1,10 @@ +# mode=strict +bad/dts-property-order.dtso:11: [property-order] property 'model' out of canonical order (should sort before 'compatible') +bad/dts-property-order.dtso:13: [property-order] property 'chassis-type' out of canonical order (should sort before 'qcom,board-id') +bad/dts-property-order.dtso:21: [property-order] property 'compatible' out of canonical order (should sort before 'reg') +bad/dts-property-order.dtso:22: [property-order] property 'device_type' out of canonical order (should sort before 'compatible') +bad/dts-property-order.dtso:31: [property-order] property 'dma-coherent' out of canonical order (should sort before 'status') +bad/dts-property-order.dtso:36: [property-order] property 'compatible' out of canonical order (should sort before 'ranges') +bad/dts-property-order.dtso:46: [property-order] property 'compatible' out of canonical order (should sort before 'interrupts') +bad/dts-property-order.dtso:53: [property-order] property 'model' out of canonical order (should sort before 'compatible') +bad/dts-property-order.dtso:58: [property-order] property 'model' out of canonical order (should sort before 'compatible') diff --git a/scripts/dtc/dt-style-selftest/good/dts-child-name-order.dtso b/scripts/dtc/dt-style-selftest/good/dts-child-name-order.dtso new file mode 100644 index 000000000000..1fd75a6285ce --- /dev/null +++ b/scripts/dtc/dt-style-selftest/good/dts-child-name-order.dtso @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +/dts-v1/; +/plugin/; + +&{/} { + #address-cells = <1>; + #size-cells = <1>; + + memory@a0000000 { + device_type = "memory"; + reg = <0x0 0xa0000000 0x0 0x0>; + }; + + pmu { + compatible = "example,pmu"; + + /* Include labels to be sure they do not affect sorting */ + label_bar: bar { + label = "bar"; + }; + + foo: foo { + label = "foo"; + }; + }; + + pmu-2 { + compatible = "example,pmu"; + + /* Just reference labels to avoid strict warnings */ + example,foo = <&foo>, <&label_bar>; + }; +}; + +&pmu { + /* Include labels to be sure they do not affect sorting */ + label_bar_2: bar-2 { + label = "bar"; + }; + + foo_2: foo-2 { + label = "foo"; + }; +} diff --git a/scripts/dtc/dt-style-selftest/good/dts-digit-node-order.dts b/scripts/dtc/dt-style-selftest/good/dts-digit-node-order.dts index cdf3f91ebe01..2b21dde7f3c8 100644 --- a/scripts/dtc/dt-style-selftest/good/dts-digit-node-order.dts +++ b/scripts/dtc/dt-style-selftest/good/dts-digit-node-order.dts @@ -5,13 +5,10 @@ #address-cells = <1>; #size-cells = <1>; - /* TODO: uncomment when child-address-order is fixed for top-level */ - /* memory@a0000000 { device_type = "memory"; reg = <0x0 0xa0000000 0x0 0x0>; }; - */ pmu { compatible = "example,pmu"; diff --git a/scripts/dtc/dt-style-selftest/good/dts-digit-node-order.dtso b/scripts/dtc/dt-style-selftest/good/dts-digit-node-order.dtso new file mode 100644 index 000000000000..efafa1cccc15 --- /dev/null +++ b/scripts/dtc/dt-style-selftest/good/dts-digit-node-order.dtso @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +/dts-v1/; +/plugin/; + +&{/} { + #address-cells = <1>; + #size-cells = <1>; + + memory@a0000000 { + device_type = "memory"; + reg = <0x0 0xa0000000 0x0 0x0>; + }; + + pmu { + compatible = "example,pmu"; + }; + + soc@0 { + compatible = "simple-bus"; + ranges = <0 0 0 0xc0000000>; + + #address-cells = <1>; + #size-cells = <1>; + + interrupt-controller@10000 { + compatible = "example,intc"; + reg = <0x10000 0x1000>; + interrupts = <1 2 3>; + }; + + serial@20000 { + compatible = "example,serial"; + reg = <0x20000 0x1000>; + }; + + serial@30000 { + compatible = "example,serial"; + reg = <0x30000 0x1000>; + }; + }; +}; + +&soc { + interrupt-controller@110000 { + compatible = "example,intc"; + reg = <0x110000 0x1000>; + interrupts = <1 2 3>; + }; + + serial@120000 { + compatible = "example,serial"; + reg = <0x120000 0x1000>; + }; + + serial@130000 { + compatible = "example,serial"; + reg = <0x130000 0x1000>; + }; +}; diff --git a/scripts/dtc/dt-style-selftest/good/dts-extend-node-child-name-order.dtso b/scripts/dtc/dt-style-selftest/good/dts-extend-node-child-name-order.dtso new file mode 100644 index 000000000000..b00c2a195179 --- /dev/null +++ b/scripts/dtc/dt-style-selftest/good/dts-extend-node-child-name-order.dtso @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +/dts-v1/; +/plugin/; + +&{/} { + #address-cells = <1>; + #size-cells = <1>; + + pmu { + compatible = "example,pmu"; + + /* Just reference labels to avoid strict warnings */ + example,foo = <&foo>, <&label_bar>; + }; +}; + +&pmu { + /* Include labels to be sure they do not affect sorting */ + label_bar: bar { + label = "bar"; + }; + + foo: foo { + label = "foo"; + }; +}; diff --git a/scripts/dtc/dt-style-selftest/good/dts-extend-node-digit-node-order.dtso b/scripts/dtc/dt-style-selftest/good/dts-extend-node-digit-node-order.dtso new file mode 100644 index 000000000000..1ce18afb80de --- /dev/null +++ b/scripts/dtc/dt-style-selftest/good/dts-extend-node-digit-node-order.dtso @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +/dts-v1/; +/plugin/; + +&{/} { + #address-cells = <1>; + #size-cells = <1>; + + soc: soc@0 { + compatible = "simple-bus"; + ranges = <0 0 0 0xc0000000>; + + #address-cells = <1>; + #size-cells = <1>; + }; +}; + +&soc { + interrupt-controller@10000 { + compatible = "example,intc"; + reg = <0x10000 0x1000>; + interrupts = <1 2 3>; + }; + + serial@20000 { + compatible = "example,serial"; + reg = <0x20000 0x1000>; + }; + + serial@30000 { + compatible = "example,serial"; + reg = <0x30000 0x1000>; + }; +}; diff --git a/scripts/dtc/dt-style-selftest/good/dts-property-order.dts b/scripts/dtc/dt-style-selftest/good/dts-property-order.dts index 0e183e3459cd..3d847cc9fa3e 100644 --- a/scripts/dtc/dt-style-selftest/good/dts-property-order.dts +++ b/scripts/dtc/dt-style-selftest/good/dts-property-order.dts @@ -6,6 +6,11 @@ /dts-v1/; / { + model = "DT style selftest"; + compatible = "example,test-board", "example,test-soc"; + chassis-type = "handset"; + qcom,board-id = <8 0>; + cpus { #address-cells = <1>; #size-cells = <0>; diff --git a/scripts/dtc/dt-style-selftest/good/dts-property-order.dtso b/scripts/dtc/dt-style-selftest/good/dts-property-order.dtso new file mode 100644 index 000000000000..5ae78541f68b --- /dev/null +++ b/scripts/dtc/dt-style-selftest/good/dts-property-order.dtso @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +/* + * Test fixture: Incorrect property order + */ + +/dts-v1/; +/plugin/; + +&{/} { + model = "DT style selftest"; + compatible = "example,test-board", "example,test-soc"; + chassis-type = "handset"; + qcom,board-id = <8 0>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a57"; + reg = <0x0 0x0>; + enable-method = "psci"; + }; + }; + + pmu { + compatible = "example,pmu"; + dma-coherent; + + status = "disabled"; + }; + + soc@0 { + compatible = "simple-bus"; + ranges = <0 0 0 0xc0000000>; + + #address-cells = <1>; + #size-cells = <1>; + + interrupt-controller@10000 { + compatible = "example,intc"; + reg = <0x10000 0x1000>; + interrupts = <1 2 3>; + }; + }; +}; -- cgit v1.2.3 From 35c19608562dd5d052901299cd8090017bc750a9 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 26 Aug 2026 13:15:54 +0200 Subject: dtc: dt-check-style: Drop stray backslash before quote for continuation-alignment Drop stray backslash before the quote character in a warning for continuation-alignment rule: (under "<" or \"). Since the '"' character has no quotes, drop the quotes also from '<'. Signed-off-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20260826-n-dts-style-checker-continued-v6-2-f270b1e81f8e@oss.qualcomm.com Signed-off-by: Rob Herring (Arm) --- scripts/dtc/dt-check-style | 4 ++-- scripts/dtc/dt-style-selftest/expected/yaml-cont-align.yaml.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'scripts') diff --git a/scripts/dtc/dt-check-style b/scripts/dtc/dt-check-style index 5a9985baa051..22e1ceac7f8b 100755 --- a/scripts/dtc/dt-check-style +++ b/scripts/dtc/dt-check-style @@ -948,7 +948,7 @@ def check_continuation_alignment(ctx): if _display_col(cont.indent_str) != target_col: yield (cont.lineno, 'continuation should align to column %d ' - '(under "<" or \\")' % (target_col + 1)) + '(under < or ")' % (target_col + 1)) def check_unclosed_block_comment(ctx): @@ -1052,7 +1052,7 @@ RULES = [ 'lines must not exceed 80 columns', check_line_length), Rule('continuation-alignment', 'strict', - 'multi-line property continuations align under "<" or "\\""', + 'multi-line property continuations align under < or "', check_continuation_alignment), Rule('unused-labels', 'strict', 'every label must be &-referenced in the same example/file ' diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-cont-align.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-cont-align.yaml.txt index b5576dd0f6b1..c0801c56d5db 100644 --- a/scripts/dtc/dt-style-selftest/expected/yaml-cont-align.yaml.txt +++ b/scripts/dtc/dt-style-selftest/expected/yaml-cont-align.yaml.txt @@ -1,2 +1,2 @@ # mode=strict -bad/yaml-cont-align.yaml:29: example 0 [continuation-alignment] continuation should align to column 11 (under "<" or \") +bad/yaml-cont-align.yaml:29: example 0 [continuation-alignment] continuation should align to column 11 (under < or ") -- cgit v1.2.3 From 98d3da8dc2cc5699a8f39426907cff694acb4aaf Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 26 Aug 2026 13:15:55 +0200 Subject: dtc: dt-check-style: Fix alignment of values in continued property lines Continued lines in property assignments should be indented to opening '<' or '"' if they also start with that character, e.g.: reg = <0x1000 0x100>, <0x2000 0x100>; If the continued line is part of previous phandle, then alignment should be to inner values to make it more readable, e.g.: reg = <0x1000 0x100 0x2000 0x100>; Signed-off-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20260826-n-dts-style-checker-continued-v6-3-f270b1e81f8e@oss.qualcomm.com Signed-off-by: Rob Herring (Arm) --- scripts/dtc/dt-check-style | 32 ++++++++++++++-------- .../dtc/dt-style-selftest/bad/dts-cont-align.dts | 26 ++++++++++++++++++ .../dtc/dt-style-selftest/bad/yaml-cont-align.yaml | 6 ++-- .../expected/dts-cont-align.dts.txt | 10 +++++++ .../expected/yaml-cont-align.yaml.txt | 3 +- .../expected/yaml-value-ws-multiline.yaml.txt | 1 + .../dtc/dt-style-selftest/good/dts-cont-align.dts | 13 +++++---- .../dt-style-selftest/good/yaml-cont-align.yaml | 32 ++++++++++++++++++++++ 8 files changed, 104 insertions(+), 19 deletions(-) create mode 100644 scripts/dtc/dt-style-selftest/bad/dts-cont-align.dts create mode 100644 scripts/dtc/dt-style-selftest/expected/dts-cont-align.dts.txt create mode 100644 scripts/dtc/dt-style-selftest/good/yaml-cont-align.yaml (limited to 'scripts') diff --git a/scripts/dtc/dt-check-style b/scripts/dtc/dt-check-style index 22e1ceac7f8b..eb5045f0ad9e 100755 --- a/scripts/dtc/dt-check-style +++ b/scripts/dtc/dt-check-style @@ -926,10 +926,11 @@ def check_line_length(ctx): def check_continuation_alignment(ctx): """A multi-line property's continuation lines must align their - first non-whitespace character to the display column of the first - '<' or '"' after the '=' in the leading line. Display columns are - used so tab-indented .dts files (where a continuation aligns with - tabs plus spaces) are compared correctly.""" + first non-whitespace character to the display column of: + 1. the first '<' or '"' after the '=' in the leading line, if continuation is with '<' or '"' + 2. the first value, if the continuation is still the same phandle. + Display columns are used so tab-indented .dts files (where a continuation + aligns with tabs plus spaces) are compared correctly.""" for dl in ctx.lines: if dl.linetype != LineType.PROPERTY: continue @@ -938,17 +939,26 @@ def check_continuation_alignment(ctx): eq = dl.raw.find('=') if eq < 0: continue - # First '<' or '"' after '=' - rest = dl.raw[eq + 1:] - m = re.search(r'[<"]', rest) + # First '<' or '"' after '=', but ignore comments and strip trailing + # whitespace (e.g. remaining after removing the comment) + rest = _strip_strings_and_comments(dl.raw[eq + 1:]).rstrip() + m = re.search(r'\s*([<"])', rest) if not m: continue - target_col = _display_col(dl.raw[:eq + 1 + m.start()]) + dl_value_complete = rest.endswith('",') or rest.endswith('>,') + target_col = _display_col(_strip_strings_and_comments(dl.raw[:eq + 1 + m.start(1)])) for cont in dl.continuations: - if _display_col(cont.indent_str) != target_col: + target_offset = 0 + err_msg_explanation = 'to < or "' + if not dl_value_complete: + target_offset = 1 + err_msg_explanation = 'to the value under <' + if _display_col(cont.indent_str) != target_col + target_offset: yield (cont.lineno, 'continuation should align to column %d ' - '(under < or ")' % (target_col + 1)) + '(%s)' % (target_col + target_offset + 1, err_msg_explanation)) + # Align to the value within <> or "" of continuation (so the previous line) + dl_value_complete = cont.stripped.endswith('",') or cont.stripped.endswith('>,') def check_unclosed_block_comment(ctx): @@ -1052,7 +1062,7 @@ RULES = [ 'lines must not exceed 80 columns', check_line_length), Rule('continuation-alignment', 'strict', - 'multi-line property continuations align under < or "', + 'multi-line property continuations align under <, " or the value under <', check_continuation_alignment), Rule('unused-labels', 'strict', 'every label must be &-referenced in the same example/file ' diff --git a/scripts/dtc/dt-style-selftest/bad/dts-cont-align.dts b/scripts/dtc/dt-style-selftest/bad/dts-cont-align.dts new file mode 100644 index 000000000000..5390ebbf4059 --- /dev/null +++ b/scripts/dtc/dt-style-selftest/bad/dts-cont-align.dts @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +/dts-v1/; + +/ { + compatible = "example,test-board"; + #address-cells = <1>; + #size-cells = <1>; + + interrupt-controller@10000 { + compatible = "example,intc"; + reg = <0x10000 0x1000>; + clocks = <1 2 3>, /* comments with " < , should not matter */ + <4 5 6>, + <7 8 9>; + interrupts = <1 2 3>, /* comments with " < , should not ... */ + <4 5 6>, + <7 8 9>; + pinmux = <0x01 + 0x02>, + <0x03 + 0x04>; + power-domain-names = "foo", + "bar", /* comments with " < , should not */ + "baz"; + }; +}; diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-cont-align.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-cont-align.yaml index 92778540b056..ccf443173dca 100644 --- a/scripts/dtc/dt-style-selftest/bad/yaml-cont-align.yaml +++ b/scripts/dtc/dt-style-selftest/bad/yaml-cont-align.yaml @@ -25,6 +25,8 @@ examples: - | foo@1000 { compatible = "example,test-cont-align"; - reg = <0x1000 0x100>, - <0x2000 0x100>; + reg = <0x1000 0x100>, /* comments with " < , should not matter */ + <0x2000 0x100>, /* comments with " < , should not matter */ + <0x3000 + 0x100>; }; diff --git a/scripts/dtc/dt-style-selftest/expected/dts-cont-align.dts.txt b/scripts/dtc/dt-style-selftest/expected/dts-cont-align.dts.txt new file mode 100644 index 000000000000..a7ed62677a2b --- /dev/null +++ b/scripts/dtc/dt-style-selftest/expected/dts-cont-align.dts.txt @@ -0,0 +1,10 @@ +# mode=strict +bad/dts-cont-align.dts:13: [continuation-alignment] continuation should align to column 26 (to < or ") +bad/dts-cont-align.dts:14: [continuation-alignment] continuation should align to column 26 (to < or ") +bad/dts-cont-align.dts:16: [continuation-alignment] continuation should align to column 30 (to < or ") +bad/dts-cont-align.dts:17: [continuation-alignment] continuation should align to column 30 (to < or ") +bad/dts-cont-align.dts:19: [continuation-alignment] continuation should align to column 27 (to the value under <) +bad/dts-cont-align.dts:20: [continuation-alignment] continuation should align to column 26 (to < or ") +bad/dts-cont-align.dts:21: [continuation-alignment] continuation should align to column 27 (to the value under <) +bad/dts-cont-align.dts:23: [continuation-alignment] continuation should align to column 38 (to < or ") +bad/dts-cont-align.dts:24: [continuation-alignment] continuation should align to column 38 (to < or ") diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-cont-align.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-cont-align.yaml.txt index c0801c56d5db..eb9a84d5c222 100644 --- a/scripts/dtc/dt-style-selftest/expected/yaml-cont-align.yaml.txt +++ b/scripts/dtc/dt-style-selftest/expected/yaml-cont-align.yaml.txt @@ -1,2 +1,3 @@ # mode=strict -bad/yaml-cont-align.yaml:29: example 0 [continuation-alignment] continuation should align to column 11 (under < or ") +bad/yaml-cont-align.yaml:29: example 0 [continuation-alignment] continuation should align to column 11 (to < or ") +bad/yaml-cont-align.yaml:31: example 0 [continuation-alignment] continuation should align to column 12 (to the value under <) diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-value-ws-multiline.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-value-ws-multiline.yaml.txt index 3df55b1762d0..d25b5b425e3f 100644 --- a/scripts/dtc/dt-style-selftest/expected/yaml-value-ws-multiline.yaml.txt +++ b/scripts/dtc/dt-style-selftest/expected/yaml-value-ws-multiline.yaml.txt @@ -1,2 +1,3 @@ # mode=strict bad/yaml-value-ws-multiline.yaml:25: example 0 [value-whitespace] extra whitespace inside <...> +bad/yaml-value-ws-multiline.yaml:26: example 0 [continuation-alignment] continuation should align to column 12 (to the value under <) diff --git a/scripts/dtc/dt-style-selftest/good/dts-cont-align.dts b/scripts/dtc/dt-style-selftest/good/dts-cont-align.dts index 36fb4eefcd83..b52ee6cccd8c 100644 --- a/scripts/dtc/dt-style-selftest/good/dts-cont-align.dts +++ b/scripts/dtc/dt-style-selftest/good/dts-cont-align.dts @@ -15,12 +15,15 @@ interrupt-controller@10000 { compatible = "example,intc"; reg = <0x10000 0x1000>; - interrupts = <1 2 3>, + interrupts = <1 2 3>, /* comments with " < , should not ... */ <4 5 6>, <7 8 9>; - pinmux = < - 0x01 - 0x02 - >; + pinmux = <0x01 + 0x02>, + <0x03 /* comments with " < , should not matter */ + 0x04>; + power-domain-names = "foo", /* comments with " < , should not */ + "bar", + "baz"; }; }; diff --git a/scripts/dtc/dt-style-selftest/good/yaml-cont-align.yaml b/scripts/dtc/dt-style-selftest/good/yaml-cont-align.yaml new file mode 100644 index 000000000000..2e7b8582bb7c --- /dev/null +++ b/scripts/dtc/dt-style-selftest/good/yaml-cont-align.yaml @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/test-good-cont-align.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Test fixture with aligned multi-line property + +maintainers: + - Test User + +properties: + compatible: + const: example,test-cont-align + reg: + maxItems: 2 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + foo@1000 { + compatible = "example,test-cont-align"; + reg = <0x1000 0x100>, + <0x2000 0x100>, + <0x3000 + 0x100>; + }; -- cgit v1.2.3 From a3b23ea1e3bbc17b1d974dce82ff16d5def368fe Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 26 Aug 2026 13:15:56 +0200 Subject: dtc: dt-check-style: Consistently call 'kind' as 'file_type' Script was using different names for variables or attributes with the same meaning: the type of file (YAML, DTS, DTSI, DTSO). Unify 'kind', 'input_kind' and function input_kind() to consistent 'file_type'. Signed-off-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20260826-n-dts-style-checker-continued-v6-4-f270b1e81f8e@oss.qualcomm.com Signed-off-by: Rob Herring (Arm) --- scripts/dtc/dt-check-style | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'scripts') diff --git a/scripts/dtc/dt-check-style b/scripts/dtc/dt-check-style index eb5045f0ad9e..17332018d70b 100755 --- a/scripts/dtc/dt-check-style +++ b/scripts/dtc/dt-check-style @@ -314,13 +314,13 @@ def collect_labels_and_refs(text): class Ctx: """Context passed to each rule check. Carries the parsed lines, - raw text, mode and kind.""" + raw text, mode and file_type.""" - def __init__(self, lines, text, mode, kind): + def __init__(self, lines, text, mode, file_type): self.lines = lines self.text = text self.mode = mode # 'relaxed' or 'strict' - if kind in DTS_FAMILY: + if file_type in DTS_FAMILY: self.file_type = 'dts' else: self.file_type = 'yaml' @@ -1071,14 +1071,14 @@ RULES = [ ] -def select_rules(mode, input_kind): +def select_rules(mode, file_type): """Return rules that apply to the given mode and input type.""" rank = {'relaxed': 0, 'strict': 1} out = [] for r in RULES: if rank[r.mode] > rank[mode]: continue - if input_kind not in r.applies_to: + if file_type not in r.applies_to: continue out.append(r) return out @@ -1088,12 +1088,12 @@ def select_rules(mode, input_kind): # Block runner # --------------------------------------------------------------------------- -def check_block(text, mode, input_type): +def check_block(text, mode, file_type): """Run all selected rules on a single block of DTS text. Returns a list of (lineno, rule_name, message) tuples.""" lines = classify_lines(text) - ctx = Ctx(lines, text, mode, input_type) - rules = select_rules(mode, input_type) + ctx = Ctx(lines, text, mode, file_type) + rules = select_rules(mode, file_type) findings = [] for r in rules: for lineno, msg in r.check(ctx): @@ -1150,7 +1150,7 @@ def iter_dts_file(filepath): # Top-level processing # --------------------------------------------------------------------------- -def input_kind(filepath): +def get_file_type(filepath): p = filepath.lower() if p.endswith('.yaml') or p.endswith('.yml'): return 'yaml' @@ -1170,17 +1170,17 @@ DTS_FAMILY = ('dts', 'dtsi', 'dtso') def collect_findings(filepath, mode): """Return a (lines, count) pair for filepath. lines is a list of formatted output strings; count is the number of findings.""" - kind = input_kind(filepath) - if kind == 'yaml': + file_type = get_file_type(filepath) + if file_type == 'yaml': iterator = iter_yaml_examples(filepath) - elif kind in DTS_FAMILY: + elif file_type in DTS_FAMILY: iterator = iter_dts_file(filepath) else: return (['%s: unknown file type, skipping' % filepath], 0) out = [] for text, base, idx in iterator: - for lineno, rule, msg in check_block(text, mode, kind): + for lineno, rule, msg in check_block(text, mode, file_type): abs_line = base + lineno - 1 ex_tag = '' if idx is None else ' example %d' % idx out.append('%s:%d:%s [%s] %s' % -- cgit v1.2.3 From 3a4b642c94e783c7570009c9d26d21d56bec34f0 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 26 Aug 2026 13:15:57 +0200 Subject: dtc: dt-check-style: Introduce 'stricter' mode Two rules, which are enabled in 'strict' mode make little sense for DTS: 1. line-length, limiting length of line to 80 characters: DTS often has a bit longer lines, especially for interconnects or heavily nested opp-level. Checkpatch already does not warn for exceeding 80 characters. 2. unused-labels, discouraging unused labels in DTS or YAML (not DTSI or DTSO): while not harming this leads to many false positives, e.g. unused PMIC regulators in DTS. Introduce another 'mode' of running beside existing relaxed and strict: a 'stricter' one where these two rules are moved for DTS. Intention is to have in-tree DTS passing 'strict' mode. Signed-off-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20260826-n-dts-style-checker-continued-v6-5-f270b1e81f8e@oss.qualcomm.com Signed-off-by: Rob Herring (Arm) --- scripts/dtc/dt-check-style | 25 +++++++++++++++------- .../dtc/dt-style-selftest/bad/dts-line-length.dts | 21 ++++++++++++++++++ .../dtc/dt-style-selftest/bad/dts-unused-label.dts | 21 ++++++++++++++++++ .../expected/dts-line-length.dts.txt | 2 ++ .../expected/dts-unused-label.dts.txt | 2 ++ scripts/dtc/dt-style-selftest/run.sh | 2 +- 6 files changed, 64 insertions(+), 9 deletions(-) create mode 100644 scripts/dtc/dt-style-selftest/bad/dts-line-length.dts create mode 100644 scripts/dtc/dt-style-selftest/bad/dts-unused-label.dts create mode 100644 scripts/dtc/dt-style-selftest/expected/dts-line-length.dts.txt create mode 100644 scripts/dtc/dt-style-selftest/expected/dts-unused-label.dts.txt (limited to 'scripts') diff --git a/scripts/dtc/dt-check-style b/scripts/dtc/dt-check-style index 17332018d70b..b71e6bf815a7 100755 --- a/scripts/dtc/dt-check-style +++ b/scripts/dtc/dt-check-style @@ -5,12 +5,14 @@ # .dts/.dtsi/.dtso source files. Enforces rules from # Documentation/devicetree/bindings/dts-coding-style.rst. # -# Two modes: +# Three modes: # --mode=relaxed (default) # Only rules that produce zero warnings on the current tree. # Suitable for dt_binding_check. # --mode=strict -# All rules. Required for new submissions. +# Most of the rules. Required for new submissions. +# --mode=stricter +# All rules, including ones having false positives. # # Two input types (auto-detected by file extension): # *.yaml -- DT binding; check each example block @@ -319,7 +321,7 @@ class Ctx: def __init__(self, lines, text, mode, file_type): self.lines = lines self.text = text - self.mode = mode # 'relaxed' or 'strict' + self.mode = mode # 'relaxed', 'strict' or 'stricter' if file_type in DTS_FAMILY: self.file_type = 'dts' else: @@ -332,7 +334,7 @@ class Rule: def __init__(self, name, mode, description, check, applies_to=('yaml', 'dts', 'dtsi', 'dtso')): self.name = name - self.mode = mode # 'relaxed' or 'strict' + self.mode = mode # 'relaxed', 'strict' or 'stricter' self.description = description self.check = check self.applies_to = applies_to # input types this rule covers @@ -1060,20 +1062,27 @@ RULES = [ check_node_close_alone), Rule('line-length', 'strict', 'lines must not exceed 80 columns', - check_line_length), + check_line_length, applies_to=('yaml',)), + Rule('line-length-dts', 'stricter', + 'lines must not exceed 80 columns', + check_line_length, applies_to=('dts', 'dtsi', 'dtso')), Rule('continuation-alignment', 'strict', 'multi-line property continuations align under <, " or the value under <', check_continuation_alignment), Rule('unused-labels', 'strict', 'every label must be &-referenced in the same example/file ' '(skipped for .dtsi/.dtso since labels there are exported)', - check_unused_labels, applies_to=('yaml', 'dts')), + check_unused_labels, applies_to=('yaml',)), + Rule('unused-labels-dts', 'stricter', + 'every label must be &-referenced in the same example/file ' + '(skipped for .dtsi/.dtso since labels there are exported)', + check_unused_labels, applies_to=('dts',)), ] def select_rules(mode, file_type): """Return rules that apply to the given mode and input type.""" - rank = {'relaxed': 0, 'strict': 1} + rank = {'relaxed': 0, 'strict': 1, 'stricter': 2} out = [] for r in RULES: if rank[r.mode] > rank[mode]: @@ -1201,7 +1210,7 @@ def main(): description='Check DTS coding style on YAML examples and ' '.dts/.dtsi/.dtso files.', fromfile_prefix_chars='@') - ap.add_argument('--mode', choices=('relaxed', 'strict'), + ap.add_argument('--mode', choices=('relaxed', 'strict', 'stricter'), default='relaxed', help='which rule set to apply (default: relaxed)') ap.add_argument('-j', '--jobs', type=int, default=0, diff --git a/scripts/dtc/dt-style-selftest/bad/dts-line-length.dts b/scripts/dtc/dt-style-selftest/bad/dts-line-length.dts new file mode 100644 index 000000000000..bde91a922477 --- /dev/null +++ b/scripts/dtc/dt-style-selftest/bad/dts-line-length.dts @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +/* + * Test fixture: Line length in DTS + */ + +/dts-v1/; + +/ { + soc@0 { + compatible = "simple-bus"; + ranges = <0 0 0 0xc0000000>; + + #address-cells = <1>; + #size-cells = <1>; + + foo@1000 { + compatible = "example,test-line-length-this-is-a-very-long-name-indeed-yeah"; + reg = <0x1000 0x100>; + }; + }; +}; diff --git a/scripts/dtc/dt-style-selftest/bad/dts-unused-label.dts b/scripts/dtc/dt-style-selftest/bad/dts-unused-label.dts new file mode 100644 index 000000000000..90802ae107e1 --- /dev/null +++ b/scripts/dtc/dt-style-selftest/bad/dts-unused-label.dts @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +/* + * Test fixture: Unused label in DTS + */ + +/dts-v1/; + +/ { + soc@0 { + compatible = "simple-bus"; + ranges = <0 0 0 0xc0000000>; + + #address-cells = <1>; + #size-cells = <1>; + + dev: device@1000 { + compatible = "example,test-unused-label"; + reg = <0x1000 0x100>; + }; + }; +}; diff --git a/scripts/dtc/dt-style-selftest/expected/dts-line-length.dts.txt b/scripts/dtc/dt-style-selftest/expected/dts-line-length.dts.txt new file mode 100644 index 000000000000..8ed08c309632 --- /dev/null +++ b/scripts/dtc/dt-style-selftest/expected/dts-line-length.dts.txt @@ -0,0 +1,2 @@ +# mode=stricter +bad/dts-line-length.dts:17: [line-length-dts] line exceeds 80 columns (101) diff --git a/scripts/dtc/dt-style-selftest/expected/dts-unused-label.dts.txt b/scripts/dtc/dt-style-selftest/expected/dts-unused-label.dts.txt new file mode 100644 index 000000000000..4cdcaba3ba2f --- /dev/null +++ b/scripts/dtc/dt-style-selftest/expected/dts-unused-label.dts.txt @@ -0,0 +1,2 @@ +# mode=stricter +bad/dts-unused-label.dts:16: [unused-labels-dts] label 'dev' defined but never &-referenced diff --git a/scripts/dtc/dt-style-selftest/run.sh b/scripts/dtc/dt-style-selftest/run.sh index 8117dd9be90a..5691301d6a4a 100755 --- a/scripts/dtc/dt-style-selftest/run.sh +++ b/scripts/dtc/dt-style-selftest/run.sh @@ -26,7 +26,7 @@ run() { # good/ -- must exit 0 and produce no output in both modes for f in "$here"/good/*; do [ -e "$f" ] || continue - for mode in relaxed strict; do + for mode in relaxed strict stricter; do out=$(run "$f" "$mode") rc=$? if [ -n "$out" ] || [ "$rc" -ne 0 ]; then -- cgit v1.2.3 From 7e17fa6b828385aaa6602d032a51041c30bcdcff Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 26 Aug 2026 13:15:58 +0200 Subject: dtc: dt-check-style: Replace Test User email with Rob Herring scripts/get_maintainer.pl reports email from the example binding fixtures, so let's spare someone at @example.com from receiving bunch of odd emails. Signed-off-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20260826-n-dts-style-checker-continued-v6-6-f270b1e81f8e@oss.qualcomm.com Signed-off-by: Rob Herring (Arm) --- scripts/dtc/dt-style-selftest/bad/yaml-child-addr-order.yaml | 2 +- scripts/dtc/dt-style-selftest/bad/yaml-child-name-order.yaml | 2 +- scripts/dtc/dt-style-selftest/bad/yaml-cont-align.yaml | 2 +- scripts/dtc/dt-style-selftest/bad/yaml-digit-node-order.yaml | 2 +- scripts/dtc/dt-style-selftest/bad/yaml-hex-case.yaml | 2 +- scripts/dtc/dt-style-selftest/bad/yaml-indent-strict.yaml | 2 +- scripts/dtc/dt-style-selftest/bad/yaml-label-in-string.yaml | 2 +- scripts/dtc/dt-style-selftest/bad/yaml-line-length.yaml | 2 +- scripts/dtc/dt-style-selftest/bad/yaml-mixed-indent.yaml | 2 +- scripts/dtc/dt-style-selftest/bad/yaml-multi-close.yaml | 2 +- scripts/dtc/dt-style-selftest/bad/yaml-node-close.yaml | 2 +- scripts/dtc/dt-style-selftest/bad/yaml-prop-order-device-type.yaml | 2 +- scripts/dtc/dt-style-selftest/bad/yaml-prop-order.yaml | 2 +- scripts/dtc/dt-style-selftest/bad/yaml-prop-pairing.yaml | 2 +- scripts/dtc/dt-style-selftest/bad/yaml-required-blank.yaml | 2 +- scripts/dtc/dt-style-selftest/bad/yaml-tab.yaml | 2 +- scripts/dtc/dt-style-selftest/bad/yaml-trailing-comment.yaml | 2 +- scripts/dtc/dt-style-selftest/bad/yaml-trailing-ws.yaml | 2 +- scripts/dtc/dt-style-selftest/bad/yaml-unclosed-comment.yaml | 2 +- scripts/dtc/dt-style-selftest/bad/yaml-unit-addr-prefix.yaml | 2 +- scripts/dtc/dt-style-selftest/bad/yaml-unit-addr.yaml | 2 +- scripts/dtc/dt-style-selftest/bad/yaml-unused-label.yaml | 2 +- scripts/dtc/dt-style-selftest/bad/yaml-value-ws-multiline.yaml | 2 +- scripts/dtc/dt-style-selftest/bad/yaml-value-ws.yaml | 2 +- scripts/dtc/dt-style-selftest/good/yaml-4space.yaml | 2 +- scripts/dtc/dt-style-selftest/good/yaml-cont-align.yaml | 2 +- scripts/dtc/dt-style-selftest/good/yaml-tricky-parsing.yaml | 2 +- 27 files changed, 27 insertions(+), 27 deletions(-) (limited to 'scripts') diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-child-addr-order.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-child-addr-order.yaml index 3df56e69a1ff..7c3b731e059a 100644 --- a/scripts/dtc/dt-style-selftest/bad/yaml-child-addr-order.yaml +++ b/scripts/dtc/dt-style-selftest/bad/yaml-child-addr-order.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Test fixture with addressed children out of order maintainers: - - Test User + - Rob Herring properties: compatible: diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-child-name-order.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-child-name-order.yaml index 35d85e5573c2..f3483033859a 100644 --- a/scripts/dtc/dt-style-selftest/bad/yaml-child-name-order.yaml +++ b/scripts/dtc/dt-style-selftest/bad/yaml-child-name-order.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Test fixture with unaddressed children out of name order maintainers: - - Test User + - Rob Herring properties: compatible: diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-cont-align.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-cont-align.yaml index ccf443173dca..a5a9eb17fc17 100644 --- a/scripts/dtc/dt-style-selftest/bad/yaml-cont-align.yaml +++ b/scripts/dtc/dt-style-selftest/bad/yaml-cont-align.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Test fixture with mis-aligned multi-line property maintainers: - - Test User + - Rob Herring properties: compatible: diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-digit-node-order.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-digit-node-order.yaml index 44a9d25e5ba0..068542a98576 100644 --- a/scripts/dtc/dt-style-selftest/bad/yaml-digit-node-order.yaml +++ b/scripts/dtc/dt-style-selftest/bad/yaml-digit-node-order.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Test fixture with digit-leading nodes out of address order maintainers: - - Test User + - Rob Herring properties: compatible: diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-hex-case.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-hex-case.yaml index b26d1bf58de9..c55359a4ca68 100644 --- a/scripts/dtc/dt-style-selftest/bad/yaml-hex-case.yaml +++ b/scripts/dtc/dt-style-selftest/bad/yaml-hex-case.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Test fixture with uppercase hex literals maintainers: - - Test User + - Rob Herring properties: compatible: diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-indent-strict.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-indent-strict.yaml index bee4cf118d73..155060a79887 100644 --- a/scripts/dtc/dt-style-selftest/bad/yaml-indent-strict.yaml +++ b/scripts/dtc/dt-style-selftest/bad/yaml-indent-strict.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Test fixture using 2-space indent (rejected by strict mode) maintainers: - - Test User + - Rob Herring properties: compatible: diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-label-in-string.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-label-in-string.yaml index ba512869b702..4a69b503af4b 100644 --- a/scripts/dtc/dt-style-selftest/bad/yaml-label-in-string.yaml +++ b/scripts/dtc/dt-style-selftest/bad/yaml-label-in-string.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Test fixture where a label is only "referenced" inside a string maintainers: - - Test User + - Rob Herring properties: compatible: diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-line-length.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-line-length.yaml index 64427bf1c385..6e4140e500b5 100644 --- a/scripts/dtc/dt-style-selftest/bad/yaml-line-length.yaml +++ b/scripts/dtc/dt-style-selftest/bad/yaml-line-length.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Test fixture exceeding 80 columns maintainers: - - Test User + - Rob Herring properties: compatible: diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-mixed-indent.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-mixed-indent.yaml index 5401d1a423a1..c25a0d1a999e 100644 --- a/scripts/dtc/dt-style-selftest/bad/yaml-mixed-indent.yaml +++ b/scripts/dtc/dt-style-selftest/bad/yaml-mixed-indent.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Test fixture mixing tabs and spaces in indent maintainers: - - Test User + - Rob Herring properties: compatible: diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-multi-close.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-multi-close.yaml index 4d9fa27b50a2..afc202a698eb 100644 --- a/scripts/dtc/dt-style-selftest/bad/yaml-multi-close.yaml +++ b/scripts/dtc/dt-style-selftest/bad/yaml-multi-close.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Test fixture with two closing braces on one line maintainers: - - Test User + - Rob Herring properties: compatible: diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-node-close.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-node-close.yaml index e107659fd9e8..9e714f7e7d47 100644 --- a/scripts/dtc/dt-style-selftest/bad/yaml-node-close.yaml +++ b/scripts/dtc/dt-style-selftest/bad/yaml-node-close.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Test fixture with closing brace not on its own line maintainers: - - Test User + - Rob Herring properties: compatible: diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-prop-order-device-type.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-prop-order-device-type.yaml index e2c69e9ff452..c71fb2c0a3e5 100644 --- a/scripts/dtc/dt-style-selftest/bad/yaml-prop-order-device-type.yaml +++ b/scripts/dtc/dt-style-selftest/bad/yaml-prop-order-device-type.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Test fixture with device_type maintainers: - - Test User + - Rob Herring properties: compatible: diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-prop-order.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-prop-order.yaml index 75582a3d2f6e..bf1480e97209 100644 --- a/scripts/dtc/dt-style-selftest/bad/yaml-prop-order.yaml +++ b/scripts/dtc/dt-style-selftest/bad/yaml-prop-order.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Test fixture with reg before compatible maintainers: - - Test User + - Rob Herring properties: compatible: diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-prop-pairing.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-prop-pairing.yaml index 767ab21c39f3..51abc540af11 100644 --- a/scripts/dtc/dt-style-selftest/bad/yaml-prop-pairing.yaml +++ b/scripts/dtc/dt-style-selftest/bad/yaml-prop-pairing.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Test fixture exercising -names and pinctrl-names pairing maintainers: - - Test User + - Rob Herring properties: compatible: diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-required-blank.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-required-blank.yaml index 8bb53240cffa..0036d5e0c4ea 100644 --- a/scripts/dtc/dt-style-selftest/bad/yaml-required-blank.yaml +++ b/scripts/dtc/dt-style-selftest/bad/yaml-required-blank.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Test fixture missing required blank lines maintainers: - - Test User + - Rob Herring properties: compatible: diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-tab.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-tab.yaml index 487d07ff8cb6..937ecdd923b0 100644 --- a/scripts/dtc/dt-style-selftest/bad/yaml-tab.yaml +++ b/scripts/dtc/dt-style-selftest/bad/yaml-tab.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Test fixture with a tab in a DTS line maintainers: - - Test User + - Rob Herring properties: compatible: diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-trailing-comment.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-trailing-comment.yaml index 2368ada8106f..695d046e8454 100644 --- a/scripts/dtc/dt-style-selftest/bad/yaml-trailing-comment.yaml +++ b/scripts/dtc/dt-style-selftest/bad/yaml-trailing-comment.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Test fixture with properties out of order behind trailing comments maintainers: - - Test User + - Rob Herring properties: compatible: diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-trailing-ws.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-trailing-ws.yaml index 5c4b4bd833c5..f338c14174e6 100644 --- a/scripts/dtc/dt-style-selftest/bad/yaml-trailing-ws.yaml +++ b/scripts/dtc/dt-style-selftest/bad/yaml-trailing-ws.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Test fixture with trailing whitespace maintainers: - - Test User + - Rob Herring properties: compatible: diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-unclosed-comment.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-unclosed-comment.yaml index 63c1c08712a5..191ed775384b 100644 --- a/scripts/dtc/dt-style-selftest/bad/yaml-unclosed-comment.yaml +++ b/scripts/dtc/dt-style-selftest/bad/yaml-unclosed-comment.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Test fixture with an unclosed /* block comment maintainers: - - Test User + - Rob Herring properties: compatible: diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-unit-addr-prefix.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-unit-addr-prefix.yaml index 9b3fe508c5fd..62590948d2de 100644 --- a/scripts/dtc/dt-style-selftest/bad/yaml-unit-addr-prefix.yaml +++ b/scripts/dtc/dt-style-selftest/bad/yaml-unit-addr-prefix.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Test fixture with 0x-prefixed unit address maintainers: - - Test User + - Rob Herring properties: compatible: diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-unit-addr.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-unit-addr.yaml index 93705cd45410..5bb19fba5c19 100644 --- a/scripts/dtc/dt-style-selftest/bad/yaml-unit-addr.yaml +++ b/scripts/dtc/dt-style-selftest/bad/yaml-unit-addr.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Test fixture with malformed unit address maintainers: - - Test User + - Rob Herring properties: compatible: diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-unused-label.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-unused-label.yaml index 28d7176cbf08..7f862ae5a175 100644 --- a/scripts/dtc/dt-style-selftest/bad/yaml-unused-label.yaml +++ b/scripts/dtc/dt-style-selftest/bad/yaml-unused-label.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Test fixture with an unused label maintainers: - - Test User + - Rob Herring properties: compatible: diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-value-ws-multiline.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-value-ws-multiline.yaml index 504bf0931c27..1d7bc8142fd7 100644 --- a/scripts/dtc/dt-style-selftest/bad/yaml-value-ws-multiline.yaml +++ b/scripts/dtc/dt-style-selftest/bad/yaml-value-ws-multiline.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Test fixture with extra whitespace in a multi-line cell array maintainers: - - Test User + - Rob Herring properties: compatible: diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-value-ws.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-value-ws.yaml index 342ab9f399f1..a5082a158155 100644 --- a/scripts/dtc/dt-style-selftest/bad/yaml-value-ws.yaml +++ b/scripts/dtc/dt-style-selftest/bad/yaml-value-ws.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Test fixture with extra whitespace inside <...> maintainers: - - Test User + - Rob Herring properties: compatible: diff --git a/scripts/dtc/dt-style-selftest/good/yaml-4space.yaml b/scripts/dtc/dt-style-selftest/good/yaml-4space.yaml index 1502f803c24c..b91b8a8a9512 100644 --- a/scripts/dtc/dt-style-selftest/good/yaml-4space.yaml +++ b/scripts/dtc/dt-style-selftest/good/yaml-4space.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Test fixture for dt-check-style maintainers: - - Test User + - Rob Herring properties: compatible: diff --git a/scripts/dtc/dt-style-selftest/good/yaml-cont-align.yaml b/scripts/dtc/dt-style-selftest/good/yaml-cont-align.yaml index 2e7b8582bb7c..8463075f9f4c 100644 --- a/scripts/dtc/dt-style-selftest/good/yaml-cont-align.yaml +++ b/scripts/dtc/dt-style-selftest/good/yaml-cont-align.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Test fixture with aligned multi-line property maintainers: - - Test User + - Rob Herring properties: compatible: diff --git a/scripts/dtc/dt-style-selftest/good/yaml-tricky-parsing.yaml b/scripts/dtc/dt-style-selftest/good/yaml-tricky-parsing.yaml index a836d5f36b93..a95d07f883ef 100644 --- a/scripts/dtc/dt-style-selftest/good/yaml-tricky-parsing.yaml +++ b/scripts/dtc/dt-style-selftest/good/yaml-tricky-parsing.yaml @@ -17,7 +17,7 @@ description: | not leave the parser in block-comment state. maintainers: - - Test User + - Rob Herring properties: compatible: -- cgit v1.2.3 From e1945a960f35b17bcbcea55dabca76384f6321d4 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 26 Aug 2026 13:15:59 +0200 Subject: dtc: dt-check-style: Call _strip_strings_and_comments() only once More than one rule evaluates pure code - stripped from comments and indentation - thus store this pure code in DtsLine class for better performance. Signed-off-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20260826-n-dts-style-checker-continued-v6-7-f270b1e81f8e@oss.qualcomm.com Signed-off-by: Rob Herring (Arm) --- scripts/dtc/dt-check-style | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'scripts') diff --git a/scripts/dtc/dt-check-style b/scripts/dtc/dt-check-style index b71e6bf815a7..43069fc1fac9 100755 --- a/scripts/dtc/dt-check-style +++ b/scripts/dtc/dt-check-style @@ -79,18 +79,19 @@ def is_preprocessor(stripped): class DtsLine: - __slots__ = ('lineno', 'raw', 'linetype', 'indent_str', 'stripped', 'is_root', + __slots__ = ('lineno', 'raw', 'code', 'linetype', 'indent_str', 'stripped', 'is_root', 'prop_name', 'continuations', 'node_name', 'node_addr', 'label', 'ref_name', 'parent', 'depth', 'closures') def __init__(self, lineno, raw, linetype, depth, indent_str, stripped, is_root = False): self.lineno = lineno # 1-based within the block - self.raw = raw + self.raw = raw # Entire raw line self.linetype = linetype self.indent_str = indent_str # leading whitespace as-is self.depth = depth - self.stripped = stripped + self.stripped = stripped # Code without indentation + self.code = _strip_strings_and_comments(stripped) # Only the code, skipping trailing comments self.is_root = is_root self.prop_name = None self.continuations = [] @@ -811,8 +812,7 @@ def check_hex_case(ctx): LineType.COMMENT_START, LineType.COMMENT_BODY, LineType.COMMENT_END, LineType.PREPROCESSOR): continue - text = _strip_strings_and_comments(dl.raw) - for m in re.finditer(r'\b0[xX][0-9a-fA-F]+\b', text): + for m in re.finditer(r'\b0[xX][0-9a-fA-F]+\b', dl.code): lit = m.group(0) if any(c.isupper() for c in lit[2:]) or lit[1] == 'X': yield (dl.lineno, @@ -860,9 +860,9 @@ def check_value_whitespace(ctx): for dl in ctx.lines: if dl.linetype != LineType.PROPERTY: continue - segs = [_strip_strings_and_comments(dl.raw).strip()] + segs = [dl.code.strip()] for cont in dl.continuations: - segs.append(_strip_strings_and_comments(cont.stripped).strip()) + segs.append(cont.code.strip()) text = '' for s in segs: if not s: @@ -895,8 +895,7 @@ def check_node_close_alone(ctx): LineType.COMMENT_START, LineType.COMMENT_BODY, LineType.COMMENT_END, LineType.PREPROCESSOR): continue - text = _strip_strings_and_comments(dl.raw) - if '};' in text: + if '};' in dl.code: yield (dl.lineno, 'closing brace must be on its own line') -- cgit v1.2.3 From f976e82f64d99c028bb503c4993754d14ea96996 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 26 Aug 2026 13:16:00 +0200 Subject: dtc: dt-check-style: Add test for trailing white-space in DTS Add unit tests for expected warnings for trailing white-spaces in DTS (there is only one for YAML files). Signed-off-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20260826-n-dts-style-checker-continued-v6-8-f270b1e81f8e@oss.qualcomm.com Signed-off-by: Rob Herring (Arm) --- scripts/dtc/dt-style-selftest/bad/dts-trailing-ws.dts | 8 ++++++++ scripts/dtc/dt-style-selftest/expected/dts-trailing-ws.dts.txt | 2 ++ 2 files changed, 10 insertions(+) create mode 100644 scripts/dtc/dt-style-selftest/bad/dts-trailing-ws.dts create mode 100644 scripts/dtc/dt-style-selftest/expected/dts-trailing-ws.dts.txt (limited to 'scripts') diff --git a/scripts/dtc/dt-style-selftest/bad/dts-trailing-ws.dts b/scripts/dtc/dt-style-selftest/bad/dts-trailing-ws.dts new file mode 100644 index 000000000000..1eb24d91c640 --- /dev/null +++ b/scripts/dtc/dt-style-selftest/bad/dts-trailing-ws.dts @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +/dts-v1/; + +/ { + compatible = "example,test-board"; + #address-cells = <1>; + #size-cells = <1>; +}; diff --git a/scripts/dtc/dt-style-selftest/expected/dts-trailing-ws.dts.txt b/scripts/dtc/dt-style-selftest/expected/dts-trailing-ws.dts.txt new file mode 100644 index 000000000000..94d9ae9d616c --- /dev/null +++ b/scripts/dtc/dt-style-selftest/expected/dts-trailing-ws.dts.txt @@ -0,0 +1,2 @@ +# mode=relaxed +bad/dts-trailing-ws.dts:5: [trailing-whitespace] trailing whitespace -- cgit v1.2.3 From ed47943d94f18bb2ca2995936ae8c06f65fa720e Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 26 Aug 2026 13:16:01 +0200 Subject: dtc: dt-check-style: Add warning for redundant white-spaces Show warnings of too many spaces around '=', after ':', before '{' and ';' characters, or using tabs for these. Both in-tree DTS and DT bindings have many warnings for the first case (too mant spaces around '='), thus keep this one only for 'strict' mode. Signed-off-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20260826-n-dts-style-checker-continued-v6-9-f270b1e81f8e@oss.qualcomm.com Signed-off-by: Rob Herring (Arm) --- scripts/dtc/dt-check-style | 44 ++++++++++++++++++++++ .../bad/dts-redundant-ws-strict.dts | 27 +++++++++++++ .../dtc/dt-style-selftest/bad/dts-redundant-ws.dts | 28 ++++++++++++++ .../dt-style-selftest/bad/dts-redundant-ws.dtso | 9 +++++ .../bad/yaml-redundant-ws-strict.yaml | 31 +++++++++++++++ .../dt-style-selftest/bad/yaml-redundant-ws.yaml | 35 +++++++++++++++++ .../expected/dts-property-order.dts.txt | 1 + .../expected/dts-property-order.dtso.txt | 1 + .../expected/dts-redundant-ws-strict.dts.txt | 13 +++++++ .../expected/dts-redundant-ws.dts.txt | 10 +++++ .../expected/dts-redundant-ws.dtso.txt | 2 + .../expected/yaml-redundant-ws-strict.yaml.txt | 5 +++ .../expected/yaml-redundant-ws.yaml.txt | 4 ++ 13 files changed, 210 insertions(+) create mode 100644 scripts/dtc/dt-style-selftest/bad/dts-redundant-ws-strict.dts create mode 100644 scripts/dtc/dt-style-selftest/bad/dts-redundant-ws.dts create mode 100644 scripts/dtc/dt-style-selftest/bad/dts-redundant-ws.dtso create mode 100644 scripts/dtc/dt-style-selftest/bad/yaml-redundant-ws-strict.yaml create mode 100644 scripts/dtc/dt-style-selftest/bad/yaml-redundant-ws.yaml create mode 100644 scripts/dtc/dt-style-selftest/expected/dts-redundant-ws-strict.dts.txt create mode 100644 scripts/dtc/dt-style-selftest/expected/dts-redundant-ws.dts.txt create mode 100644 scripts/dtc/dt-style-selftest/expected/dts-redundant-ws.dtso.txt create mode 100644 scripts/dtc/dt-style-selftest/expected/yaml-redundant-ws-strict.yaml.txt create mode 100644 scripts/dtc/dt-style-selftest/expected/yaml-redundant-ws.yaml.txt (limited to 'scripts') diff --git a/scripts/dtc/dt-check-style b/scripts/dtc/dt-check-style index 43069fc1fac9..487e76b85105 100755 --- a/scripts/dtc/dt-check-style +++ b/scripts/dtc/dt-check-style @@ -349,6 +349,42 @@ def check_trailing_whitespace(ctx): yield (dl.lineno, 'trailing whitespace') +def _check_redundant_whitespace(dl): + if dl.linetype in (LineType.COMMENT, LineType.COMMENT_BODY, + LineType.COMMENT_END, LineType.COMMENT_START, + LineType.PREPROCESSOR): + return + if re.search(r'(\s\s+|\t)\{', dl.code): + yield (dl.lineno, 'extra whitespace before {') + if re.search(r':(\s\s+|\t)', dl.code): + yield (dl.lineno, 'extra whitespace after :') + if re.search(r'\s+;', dl.code): + yield (dl.lineno, 'extra whitespace before ;') + + +def check_redundant_whitespace(ctx): + """No whitespace between brackets or other code elements. + See also check_value_whitespace() for more checks.""" + for dl in ctx.lines: + yield from _check_redundant_whitespace(dl) + for cont in dl.continuations: + yield from _check_redundant_whitespace(cont) + + +def check_redundant_whitespace_strict(ctx): + """No whitespace between brackets or other code elements. + See also check_value_whitespace() for more checks.""" + for dl in ctx.lines: + if dl.linetype in (LineType.COMMENT, LineType.COMMENT_BODY, + LineType.COMMENT_END, LineType.COMMENT_START, + LineType.PREPROCESSOR): + continue + if re.search(r'(\s\s+|\t)=', dl.code): + yield (dl.lineno, 'extra whitespace before =') + if re.search(r'=(\s\s+|\t)', dl.code): + yield (dl.lineno, 'extra whitespace after =') + + def check_tab_in_yaml_example(ctx): """Reject literal tabs in DTS lines when input is YAML. @@ -1003,6 +1039,10 @@ RULES = [ Rule('trailing-whitespace', 'relaxed', 'no trailing whitespace on any line', check_trailing_whitespace), + # See also check_redundant_whitespace_strict() and check_value_whitespace() + Rule('redundant-whitespace', 'relaxed', + 'no redundant whitespace within code', + check_redundant_whitespace), Rule('tab-in-yaml', 'relaxed', 'YAML (also DTS examples) may not contain tab characters', check_tab_in_yaml_example, applies_to=('yaml',)), @@ -1053,6 +1093,10 @@ RULES = [ Rule('unit-address-format', 'strict', 'unit addresses must be lowercase hex without leading zeros', check_unit_address_format), + # See also check_redundant_whitespace() and check_value_whitespace() + Rule('redundant-whitespace-strict', 'strict', + 'no redundant whitespace within code', + check_redundant_whitespace_strict), Rule('value-whitespace', 'strict', 'no whitespace directly inside <...> brackets', check_value_whitespace), diff --git a/scripts/dtc/dt-style-selftest/bad/dts-redundant-ws-strict.dts b/scripts/dtc/dt-style-selftest/bad/dts-redundant-ws-strict.dts new file mode 100644 index 000000000000..201e3940ba1c --- /dev/null +++ b/scripts/dtc/dt-style-selftest/bad/dts-redundant-ws-strict.dts @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +/dts-v1/; + +#define SOME_MACRO(foo) \ + (foo) ? <1> : <2> ; + +/ { + compatible = "example,test-board"; + #address-cells = <1>; + #size-cells = <1>; + + /* comments { are okay = though ; */ + soc: soc@0 { /* comments { are okay = though ; */ + compatible = "simple-bus"; /* comments { are okay = though ; */ + ranges = <0 0 0 0xc0000000>; + + #address-cells = <1>; + #size-cells = <1>; + } ; +}; /* comments { are okay = though ; */ + +&soc { + serial: serial@20000 { /* comments { are okay = though ; */ + compatible = "example,serial"; + reg = <0x20000 0x1000>; + } ; +}; diff --git a/scripts/dtc/dt-style-selftest/bad/dts-redundant-ws.dts b/scripts/dtc/dt-style-selftest/bad/dts-redundant-ws.dts new file mode 100644 index 000000000000..f6480ddc508a --- /dev/null +++ b/scripts/dtc/dt-style-selftest/bad/dts-redundant-ws.dts @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +/dts-v1/; + +#define SOME_MACRO(foo) \ + (foo) ? <1> : <2> ; + +/ { + compatible = "example,test-board"; + #address-cells = <1>; + #size-cells = <1>; + + /* comments { are okay = though ; */ + soc: soc@0 { /* comments { are okay = though ; */ + compatible = "simple-bus"; /* comments { are okay = though ; */ + ranges = <0 0 0 0xc0000000>; + + #address-cells = <1>; + #size-cells = <1>; + } ; +}; /* comments { are okay = though ; */ + +&soc { + serial: serial@20000 { /* comments { are okay = though ; */ + compatible = "example,serial"; + reg = <0x20000 0x1000>, + <0x30000 0x1000> ; + } ; /* comments { are okay = though ; */ +}; diff --git a/scripts/dtc/dt-style-selftest/bad/dts-redundant-ws.dtso b/scripts/dtc/dt-style-selftest/bad/dts-redundant-ws.dtso new file mode 100644 index 000000000000..01d94e14071a --- /dev/null +++ b/scripts/dtc/dt-style-selftest/bad/dts-redundant-ws.dtso @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +/dts-v1/; +/plugin/; + +&{/} { + compatible = "example,test-board"; + #address-cells = <1>; + #size-cells = <1>; +}; diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-redundant-ws-strict.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-redundant-ws-strict.yaml new file mode 100644 index 000000000000..739c44fd7217 --- /dev/null +++ b/scripts/dtc/dt-style-selftest/bad/yaml-redundant-ws-strict.yaml @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/yaml-redundant-ws-strict.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Test fixture with redundant whitespace + +maintainers: + - Rob Herring + +properties: + compatible: + const: example,test-redundant + reg: + maxItems: 1 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + device@1000 { + compatible = "example,test-trailing"; + reg = <0x1000 0x100>; + clocks = <&clk 0>; /* comments { are okay = though ; */ + clock-names = "bus"; /* comments { are okay = though ; */ + } ; diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-redundant-ws.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-redundant-ws.yaml new file mode 100644 index 000000000000..b2f51969b0ff --- /dev/null +++ b/scripts/dtc/dt-style-selftest/bad/yaml-redundant-ws.yaml @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/yaml-redundant-ws.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Test fixture with redundant whitespace + +maintainers: + - Rob Herring + +properties: + compatible: + const: example,test-redundant + reg: + maxItems: 1 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + device@1000 { /* comments { are okay = though ; */ + compatible = "example,test-trailing"; + reg = <0x1000 0x100>, + <0x3000 0x100> ; + } ; + + device@2000 { /* comments { are okay = though ; */ + compatible = "example,test-trailing"; + reg = <0x2000 0x100>; + }; /* comments { are okay = though ; */ diff --git a/scripts/dtc/dt-style-selftest/expected/dts-property-order.dts.txt b/scripts/dtc/dt-style-selftest/expected/dts-property-order.dts.txt index aab048a0ba3b..0ab832ccf07a 100644 --- a/scripts/dtc/dt-style-selftest/expected/dts-property-order.dts.txt +++ b/scripts/dtc/dt-style-selftest/expected/dts-property-order.dts.txt @@ -6,5 +6,6 @@ bad/dts-property-order.dts:21: [property-order] property 'device_type' out of ca bad/dts-property-order.dts:30: [property-order] property 'dma-coherent' out of canonical order (should sort before 'status') bad/dts-property-order.dts:35: [property-order] property 'compatible' out of canonical order (should sort before 'ranges') bad/dts-property-order.dts:45: [property-order] property 'compatible' out of canonical order (should sort before 'interrupts') +bad/dts-property-order.dts:50: [redundant-whitespace] extra whitespace before { bad/dts-property-order.dts:52: [property-order] property 'model' out of canonical order (should sort before 'compatible') bad/dts-property-order.dts:57: [property-order] property 'model' out of canonical order (should sort before 'compatible') diff --git a/scripts/dtc/dt-style-selftest/expected/dts-property-order.dtso.txt b/scripts/dtc/dt-style-selftest/expected/dts-property-order.dtso.txt index e9b3ac985718..9f2a00916329 100644 --- a/scripts/dtc/dt-style-selftest/expected/dts-property-order.dtso.txt +++ b/scripts/dtc/dt-style-selftest/expected/dts-property-order.dtso.txt @@ -6,5 +6,6 @@ bad/dts-property-order.dtso:22: [property-order] property 'device_type' out of c bad/dts-property-order.dtso:31: [property-order] property 'dma-coherent' out of canonical order (should sort before 'status') bad/dts-property-order.dtso:36: [property-order] property 'compatible' out of canonical order (should sort before 'ranges') bad/dts-property-order.dtso:46: [property-order] property 'compatible' out of canonical order (should sort before 'interrupts') +bad/dts-property-order.dtso:51: [redundant-whitespace] extra whitespace before { bad/dts-property-order.dtso:53: [property-order] property 'model' out of canonical order (should sort before 'compatible') bad/dts-property-order.dtso:58: [property-order] property 'model' out of canonical order (should sort before 'compatible') diff --git a/scripts/dtc/dt-style-selftest/expected/dts-redundant-ws-strict.dts.txt b/scripts/dtc/dt-style-selftest/expected/dts-redundant-ws-strict.dts.txt new file mode 100644 index 000000000000..ac0d57bdecdf --- /dev/null +++ b/scripts/dtc/dt-style-selftest/expected/dts-redundant-ws-strict.dts.txt @@ -0,0 +1,13 @@ +# mode=strict +bad/dts-redundant-ws-strict.dts:7: [redundant-whitespace] extra whitespace before { +bad/dts-redundant-ws-strict.dts:13: [redundant-whitespace] extra whitespace before { +bad/dts-redundant-ws-strict.dts:13: [redundant-whitespace] extra whitespace after : +bad/dts-redundant-ws-strict.dts:17: [redundant-whitespace-strict] extra whitespace before = +bad/dts-redundant-ws-strict.dts:18: [redundant-whitespace-strict] extra whitespace after = +bad/dts-redundant-ws-strict.dts:19: [redundant-whitespace] extra whitespace before ; +bad/dts-redundant-ws-strict.dts:22: [redundant-whitespace] extra whitespace before { +bad/dts-redundant-ws-strict.dts:23: [redundant-whitespace] extra whitespace before { +bad/dts-redundant-ws-strict.dts:23: [redundant-whitespace] extra whitespace after : +bad/dts-redundant-ws-strict.dts:24: [redundant-whitespace-strict] extra whitespace before = +bad/dts-redundant-ws-strict.dts:25: [redundant-whitespace-strict] extra whitespace after = +bad/dts-redundant-ws-strict.dts:26: [redundant-whitespace] extra whitespace before ; diff --git a/scripts/dtc/dt-style-selftest/expected/dts-redundant-ws.dts.txt b/scripts/dtc/dt-style-selftest/expected/dts-redundant-ws.dts.txt new file mode 100644 index 000000000000..3b2a989045ed --- /dev/null +++ b/scripts/dtc/dt-style-selftest/expected/dts-redundant-ws.dts.txt @@ -0,0 +1,10 @@ +# mode=relaxed +bad/dts-redundant-ws.dts:7: [redundant-whitespace] extra whitespace before { +bad/dts-redundant-ws.dts:13: [redundant-whitespace] extra whitespace before { +bad/dts-redundant-ws.dts:13: [redundant-whitespace] extra whitespace after : +bad/dts-redundant-ws.dts:19: [redundant-whitespace] extra whitespace before ; +bad/dts-redundant-ws.dts:22: [redundant-whitespace] extra whitespace before { +bad/dts-redundant-ws.dts:23: [redundant-whitespace] extra whitespace before { +bad/dts-redundant-ws.dts:23: [redundant-whitespace] extra whitespace after : +bad/dts-redundant-ws.dts:26: [redundant-whitespace] extra whitespace before ; +bad/dts-redundant-ws.dts:27: [redundant-whitespace] extra whitespace before ; diff --git a/scripts/dtc/dt-style-selftest/expected/dts-redundant-ws.dtso.txt b/scripts/dtc/dt-style-selftest/expected/dts-redundant-ws.dtso.txt new file mode 100644 index 000000000000..5f9a63061709 --- /dev/null +++ b/scripts/dtc/dt-style-selftest/expected/dts-redundant-ws.dtso.txt @@ -0,0 +1,2 @@ +# mode=strict +bad/dts-redundant-ws.dtso:5: [redundant-whitespace] extra whitespace before { diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-redundant-ws-strict.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-redundant-ws-strict.yaml.txt new file mode 100644 index 000000000000..fbf323832c91 --- /dev/null +++ b/scripts/dtc/dt-style-selftest/expected/yaml-redundant-ws-strict.yaml.txt @@ -0,0 +1,5 @@ +# mode=strict +bad/yaml-redundant-ws-strict.yaml:26: example 0 [redundant-whitespace] extra whitespace before { +bad/yaml-redundant-ws-strict.yaml:27: example 0 [redundant-whitespace-strict] extra whitespace before = +bad/yaml-redundant-ws-strict.yaml:28: example 0 [redundant-whitespace-strict] extra whitespace after = +bad/yaml-redundant-ws-strict.yaml:31: example 0 [redundant-whitespace] extra whitespace before ; diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-redundant-ws.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-redundant-ws.yaml.txt new file mode 100644 index 000000000000..a162967e4336 --- /dev/null +++ b/scripts/dtc/dt-style-selftest/expected/yaml-redundant-ws.yaml.txt @@ -0,0 +1,4 @@ +# mode=relaxed +bad/yaml-redundant-ws.yaml:26: example 0 [redundant-whitespace] extra whitespace before { +bad/yaml-redundant-ws.yaml:29: example 0 [redundant-whitespace] extra whitespace before ; +bad/yaml-redundant-ws.yaml:30: example 0 [redundant-whitespace] extra whitespace before ; -- cgit v1.2.3 From 50a0e8d6481ea4f5c204c4a3743fcac502f38fc1 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2026 21:53:17 +0200 Subject: dtc: dt-check-style: Sort rule directory by name Sort the array with all the rules, so managing this will be at bit easier and simultaneous addons of new rules less conflict-prone. No functional changes. Signed-off-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20260829-dts-style-checker-sort-v1-1-6693a37d7ae1@oss.qualcomm.com Signed-off-by: Rob Herring (Arm) --- scripts/dtc/dt-check-style | 89 +++++++++++++++++++++++----------------------- 1 file changed, 45 insertions(+), 44 deletions(-) (limited to 'scripts') diff --git a/scripts/dtc/dt-check-style b/scripts/dtc/dt-check-style index 487e76b85105..49b5c28563eb 100755 --- a/scripts/dtc/dt-check-style +++ b/scripts/dtc/dt-check-style @@ -1036,9 +1036,17 @@ RULES = [ # 'relaxed' is the default; rules in this group must produce zero # output on a clean kernel tree (post the small prep-cleanup # commit at the head of this series). - Rule('trailing-whitespace', 'relaxed', - 'no trailing whitespace on any line', - check_trailing_whitespace), + # Rules are sorted here by group (relaxed, strict, stricter) and name + + # DTS files always use tabs; this is not negotiable per kernel + # coding style (.dts files are real source). Relaxed mode. + Rule('indent-unit-dts', 'relaxed', + 'DTS files: 1 tab per nesting level', + check_indent_unit_dts, + applies_to=('dts', 'dtsi', 'dtso')), + Rule('mixed-indent-chars', 'relaxed', + 'indent must not mix tabs and spaces', + check_mixed_indent_chars, applies_to=('dts', 'dtsi', 'dtso')), # See also check_redundant_whitespace_strict() and check_value_whitespace() Rule('redundant-whitespace', 'relaxed', 'no redundant whitespace within code', @@ -1046,32 +1054,16 @@ RULES = [ Rule('tab-in-yaml', 'relaxed', 'YAML (also DTS examples) may not contain tab characters', check_tab_in_yaml_example, applies_to=('yaml',)), - Rule('mixed-indent-chars', 'relaxed', - 'indent must not mix tabs and spaces', - check_mixed_indent_chars, applies_to=('dts', 'dtsi', 'dtso')), + Rule('trailing-whitespace', 'relaxed', + 'no trailing whitespace on any line', + check_trailing_whitespace), Rule('unclosed-block-comment', 'relaxed', 'every /* block comment must close with */', check_unclosed_block_comment), - # DTS files always use tabs; this is not negotiable per kernel - # coding style (.dts files are real source). Relaxed mode. - Rule('indent-unit-dts', 'relaxed', - 'DTS files: 1 tab per nesting level', - check_indent_unit_dts, - applies_to=('dts', 'dtsi', 'dtso')), - # 'strict' rules are opt-in (e.g. for new submissions via # checkpatch.pl in a follow-up series). They flag many existing # files and can be promoted to relaxed once those are cleaned up. - Rule('indent-unit', 'strict', - 'YAML: 2 or 4 spaces per level', - check_indent_unit_relaxed, applies_to=('yaml',)), - Rule('indent-unit-strict', 'strict', - 'YAML: must be 4 spaces per level', - check_indent_unit_strict, applies_to=('yaml',)), - Rule('indent-consistent', 'strict', - 'every line indented at depth * unit', - check_indent_consistent), Rule('blank-lines', 'strict', 'no consecutive blanks; no blanks at node body edges', check_blank_lines), @@ -1081,37 +1073,43 @@ RULES = [ Rule('child-name-order', 'strict', 'unaddressed siblings must be in natural-sort name order', check_child_name_order), - Rule('property-order', 'strict', - 'canonical bucket + pairing + natural-sort order of properties', - check_property_order), - Rule('required-blank-lines', 'strict', - 'blank line before child nodes and before "status"', - check_required_blank_lines), + Rule('continuation-alignment', 'strict', + 'multi-line property continuations align under <, " or the value under <', + check_continuation_alignment), Rule('hex-case', 'strict', 'hex literals must be lowercase', check_hex_case), - Rule('unit-address-format', 'strict', - 'unit addresses must be lowercase hex without leading zeros', - check_unit_address_format), - # See also check_redundant_whitespace() and check_value_whitespace() - Rule('redundant-whitespace-strict', 'strict', - 'no redundant whitespace within code', - check_redundant_whitespace_strict), - Rule('value-whitespace', 'strict', - 'no whitespace directly inside <...> brackets', - check_value_whitespace), - Rule('node-close-alone', 'strict', - 'closing brace must be on its own line', - check_node_close_alone), + Rule('indent-consistent', 'strict', + 'every line indented at depth * unit', + check_indent_consistent), + Rule('indent-unit', 'strict', + 'YAML: 2 or 4 spaces per level', + check_indent_unit_relaxed, applies_to=('yaml',)), + Rule('indent-unit-strict', 'strict', + 'YAML: must be 4 spaces per level', + check_indent_unit_strict, applies_to=('yaml',)), Rule('line-length', 'strict', 'lines must not exceed 80 columns', check_line_length, applies_to=('yaml',)), Rule('line-length-dts', 'stricter', 'lines must not exceed 80 columns', check_line_length, applies_to=('dts', 'dtsi', 'dtso')), - Rule('continuation-alignment', 'strict', - 'multi-line property continuations align under <, " or the value under <', - check_continuation_alignment), + Rule('node-close-alone', 'strict', + 'closing brace must be on its own line', + check_node_close_alone), + Rule('property-order', 'strict', + 'canonical bucket + pairing + natural-sort order of properties', + check_property_order), + # See also check_redundant_whitespace() and check_value_whitespace() + Rule('redundant-whitespace-strict', 'strict', + 'no redundant whitespace within code', + check_redundant_whitespace_strict), + Rule('required-blank-lines', 'strict', + 'blank line before child nodes and before "status"', + check_required_blank_lines), + Rule('unit-address-format', 'strict', + 'unit addresses must be lowercase hex without leading zeros', + check_unit_address_format), Rule('unused-labels', 'strict', 'every label must be &-referenced in the same example/file ' '(skipped for .dtsi/.dtso since labels there are exported)', @@ -1120,6 +1118,9 @@ RULES = [ 'every label must be &-referenced in the same example/file ' '(skipped for .dtsi/.dtso since labels there are exported)', check_unused_labels, applies_to=('dts',)), + Rule('value-whitespace', 'strict', + 'no whitespace directly inside <...> brackets', + check_value_whitespace), ] -- cgit v1.2.3 From f7ec3884072509b92588c402dd21e53a6dff8f9a Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2026 21:53:18 +0200 Subject: dtc: dt-check-style: Sort rule functions by name Sort all the functions implementing style rules by name, so managing this will be at bit easier and simultaneous addons of new rules less conflict-prone. No functional changes, except adding underscore to _detect_indent_unit() to match other helpers used by the rules. Signed-off-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20260829-dts-style-checker-sort-v1-2-6693a37d7ae1@oss.qualcomm.com Signed-off-by: Rob Herring (Arm) --- scripts/dtc/dt-check-style | 619 +++++++++++++++++++++++---------------------- 1 file changed, 310 insertions(+), 309 deletions(-) (limited to 'scripts') diff --git a/scripts/dtc/dt-check-style b/scripts/dtc/dt-check-style index 49b5c28563eb..5385a03f377e 100755 --- a/scripts/dtc/dt-check-style +++ b/scripts/dtc/dt-check-style @@ -343,88 +343,8 @@ class Rule: # --- individual rule check functions -------------------------------------- -def check_trailing_whitespace(ctx): - for dl in ctx.lines: - if dl.raw != dl.raw.rstrip(): - yield (dl.lineno, 'trailing whitespace') - -def _check_redundant_whitespace(dl): - if dl.linetype in (LineType.COMMENT, LineType.COMMENT_BODY, - LineType.COMMENT_END, LineType.COMMENT_START, - LineType.PREPROCESSOR): - return - if re.search(r'(\s\s+|\t)\{', dl.code): - yield (dl.lineno, 'extra whitespace before {') - if re.search(r':(\s\s+|\t)', dl.code): - yield (dl.lineno, 'extra whitespace after :') - if re.search(r'\s+;', dl.code): - yield (dl.lineno, 'extra whitespace before ;') - - -def check_redundant_whitespace(ctx): - """No whitespace between brackets or other code elements. - See also check_value_whitespace() for more checks.""" - for dl in ctx.lines: - yield from _check_redundant_whitespace(dl) - for cont in dl.continuations: - yield from _check_redundant_whitespace(cont) - - -def check_redundant_whitespace_strict(ctx): - """No whitespace between brackets or other code elements. - See also check_value_whitespace() for more checks.""" - for dl in ctx.lines: - if dl.linetype in (LineType.COMMENT, LineType.COMMENT_BODY, - LineType.COMMENT_END, LineType.COMMENT_START, - LineType.PREPROCESSOR): - continue - if re.search(r'(\s\s+|\t)=', dl.code): - yield (dl.lineno, 'extra whitespace before =') - if re.search(r'=(\s\s+|\t)', dl.code): - yield (dl.lineno, 'extra whitespace after =') - - -def check_tab_in_yaml_example(ctx): - """Reject literal tabs in DTS lines when input is YAML. - - For YAML examples, indent and content must use spaces. Tabs inside - a #define value are tolerated (those are CPP macros, not DTS). - For .dts files, this rule does not apply -- tabs are required. - """ - if ctx.file_type != 'yaml': - return - for dl in ctx.lines: - if dl.linetype == LineType.PREPROCESSOR: - continue - if dl.linetype == LineType.BLANK: - continue - if '\t' in dl.raw: - yield (dl.lineno, 'tab character not allowed in DTS example') - - -def check_mixed_indent_chars(ctx): - """Indent must be all-tabs, except for aligning indentation (comments - or continued lines).""" - for dl in ctx.lines: - if not dl.indent_str: - continue - if dl.linetype == LineType.PREPROCESSOR: - continue - if re.search(r' \t', dl.indent_str): - yield (dl.lineno, 'mixed tabs and spaces in indent') - if dl.indent_str.count(' ') > 7: - yield (dl.lineno, 'too many space characters in indent (more than 7)') - for cont in dl.continuations: - if not cont.indent_str: - continue - if cont.linetype == LineType.PREPROCESSOR: - continue - if re.search(r' \t', cont.indent_str): - yield (cont.lineno, 'mixed tabs and spaces in indent') - - -def detect_indent_unit(ctx): +def _detect_indent_unit(ctx): """Find the indent unit used at depth 1 in this block. Returns tuple of string (one of: ' ' (2 spaces), ' ' (4 spaces), @@ -450,85 +370,42 @@ def detect_indent_unit(ctx): return (None, None) -def check_indent_unit_relaxed(ctx): - """YAML examples: 2 or 4 spaces. Never tabs or other widths.""" - (unit, lineno) = detect_indent_unit(ctx) - if unit is None: - return - if unit not in (' ', ' '): - yield (lineno, 'indent unit must be 2 or 4 spaces, got %r' % unit) - - -def check_indent_unit_dts(ctx): - """DTS files: 1 tab per level. Always required.""" - (unit, lineno) = detect_indent_unit(ctx) - if unit is None: - return - if unit != '\t': - yield (lineno, 'indent unit must be 1 tab in DTS, got %r' % unit) - - -def check_indent_unit_strict(ctx): - """YAML: must be exactly 4 spaces. DTS: 1 tab (same as relaxed).""" - (unit, lineno) = detect_indent_unit(ctx) - if unit is None: - return - if ctx.file_type == 'yaml': - if unit != ' ': - yield (lineno, 'indent unit must be 4 spaces in strict mode, ' - 'got %r' % unit) - +def _display_col(text): + """Visual column width of text, with tabs expanded to the next + 8-column stop, matching how printf and most editors render a + line and the kernel-wide line length convention.""" + col = 0 + for ch in text: + if ch == '\t': + col = (col // 8 + 1) * 8 + else: + col += 1 + return col -def check_indent_consistent(ctx): - """All indented lines must be a multiple of the detected unit.""" - (unit, lineno) = detect_indent_unit(ctx) - if unit is None: - return - if ctx.file_type == 'yaml': - if unit not in (' ', ' '): - return # let check_indent_unit_* report this - else: - if unit != '\t': - return - for dl in ctx.lines: - if dl.linetype in (LineType.BLANK, LineType.PREPROCESSOR): - continue - if dl.linetype == LineType.CONTINUATION: - continue # continuations align to <, not to indent unit - if dl.linetype in (LineType.COMMENT_BODY, LineType.COMMENT_END): - continue - if not dl.indent_str: - continue - # The indent must be 'unit' repeated dl.depth times, exactly. - # NODE_CLOSE lines have depth equal to the post-decrement value, - # which matches the indent expected. - expected = unit * dl.depth - if dl.indent_str != expected: - yield (dl.lineno, - 'indent mismatch (expected depth %d * %r)' % - (dl.depth, unit)) +def _natural_sort_key(s): + """Split a string into a tuple of (kind, value) pairs that compares + numeric runs as ints, so 'foo10' sorts after 'foo2'.""" + parts = [] + for part in re.split(r'(\d+)', s): + if part.isdigit(): + parts.append((0, int(part))) + else: + parts.append((1, part)) + return tuple(parts) -def check_blank_lines(ctx): - """No two consecutive blank lines, no leading/trailing blank lines - in any node body.""" - lines = ctx.lines - # Consecutive blanks - for i in range(1, len(lines)): - if lines[i].linetype == LineType.BLANK and \ - lines[i - 1].linetype == LineType.BLANK: - yield (lines[i].lineno, 'consecutive blank lines') - # Blank right after { or right before } - for i, dl in enumerate(lines): - if dl.linetype != LineType.BLANK: - continue - prev = lines[i - 1] if i > 0 else None - nxt = lines[i + 1] if i + 1 < len(lines) else None - if prev is not None and prev.linetype == LineType.NODE_OPEN: - yield (dl.lineno, 'blank line at start of node body') - if nxt is not None and nxt.linetype == LineType.NODE_CLOSE: - yield (dl.lineno, 'blank line at end of node body') +def _strip_strings_and_comments(text): + """Remove string literals and /* */ + // comments from a single + line, replacing them with empty strings. Used so syntactic checks + (whitespace, hex case, etc.) don't false-positive on contents of + quoted strings or comments. An unclosed /* on the line is treated + as a comment running to end of line.""" + text = re.sub(r'"(?:[^"\\]|\\.)*"', '""', text) + text = re.sub(r'/\*.*?\*/', '', text) + text = re.sub(r'/\*.*$', '', text) + text = re.sub(r'//.*$', '', text) + return text def _walk_bodies(lines): @@ -559,16 +436,25 @@ def _walk_bodies(lines): yield body_stack.pop() -def _natural_sort_key(s): - """Split a string into a tuple of (kind, value) pairs that compares - numeric runs as ints, so 'foo10' sorts after 'foo2'.""" - parts = [] - for part in re.split(r'(\d+)', s): - if part.isdigit(): - parts.append((0, int(part))) - else: - parts.append((1, part)) - return tuple(parts) +def check_blank_lines(ctx): + """No two consecutive blank lines, no leading/trailing blank lines + in any node body.""" + lines = ctx.lines + # Consecutive blanks + for i in range(1, len(lines)): + if lines[i].linetype == LineType.BLANK and \ + lines[i - 1].linetype == LineType.BLANK: + yield (lines[i].lineno, 'consecutive blank lines') + # Blank right after { or right before } + for i, dl in enumerate(lines): + if dl.linetype != LineType.BLANK: + continue + prev = lines[i - 1] if i > 0 else None + nxt = lines[i + 1] if i + 1 < len(lines) else None + if prev is not None and prev.linetype == LineType.NODE_OPEN: + yield (dl.lineno, 'blank line at start of node body') + if nxt is not None and nxt.linetype == LineType.NODE_CLOSE: + yield (dl.lineno, 'blank line at end of node body') def check_child_address_order(ctx): @@ -614,14 +500,180 @@ def check_child_name_order(ctx): continue if c.node_name in (None, '/'): continue - if c.ref_name is not None: + if c.ref_name is not None: + continue + unaddressed.append((_natural_sort_key(c.node_name), c)) + for i in range(1, len(unaddressed)): + if unaddressed[i][0] < unaddressed[i - 1][0]: + dl = unaddressed[i][1] + yield (dl.lineno, + 'child node %r out of name order' % dl.node_name) + + +def check_continuation_alignment(ctx): + """A multi-line property's continuation lines must align their + first non-whitespace character to the display column of: + 1. the first '<' or '"' after the '=' in the leading line, if continuation is with '<' or '"' + 2. the first value, if the continuation is still the same phandle. + Display columns are used so tab-indented .dts files (where a continuation + aligns with tabs plus spaces) are compared correctly.""" + for dl in ctx.lines: + if dl.linetype != LineType.PROPERTY: + continue + if not dl.continuations: + continue + eq = dl.raw.find('=') + if eq < 0: + continue + # First '<' or '"' after '=', but ignore comments and strip trailing + # whitespace (e.g. remaining after removing the comment) + rest = _strip_strings_and_comments(dl.raw[eq + 1:]).rstrip() + m = re.search(r'\s*([<"])', rest) + if not m: + continue + dl_value_complete = rest.endswith('",') or rest.endswith('>,') + target_col = _display_col(_strip_strings_and_comments(dl.raw[:eq + 1 + m.start(1)])) + for cont in dl.continuations: + target_offset = 0 + err_msg_explanation = 'to < or "' + if not dl_value_complete: + target_offset = 1 + err_msg_explanation = 'to the value under <' + if _display_col(cont.indent_str) != target_col + target_offset: + yield (cont.lineno, + 'continuation should align to column %d ' + '(%s)' % (target_col + target_offset + 1, err_msg_explanation)) + # Align to the value within <> or "" of continuation (so the previous line) + dl_value_complete = cont.stripped.endswith('",') or cont.stripped.endswith('>,') + + +def check_hex_case(ctx): + """Hex literals (0xN) must use lowercase digits and prefix.""" + for dl in ctx.lines: + if dl.linetype in (LineType.BLANK, LineType.COMMENT, + LineType.COMMENT_START, LineType.COMMENT_BODY, + LineType.COMMENT_END, LineType.PREPROCESSOR): + continue + for m in re.finditer(r'\b0[xX][0-9a-fA-F]+\b', dl.code): + lit = m.group(0) + if any(c.isupper() for c in lit[2:]) or lit[1] == 'X': + yield (dl.lineno, + 'hex literal %r must be lowercase' % lit) + + +def check_indent_consistent(ctx): + """All indented lines must be a multiple of the detected unit.""" + (unit, lineno) = _detect_indent_unit(ctx) + if unit is None: + return + if ctx.file_type == 'yaml': + if unit not in (' ', ' '): + return # let check_indent_unit_* report this + else: + if unit != '\t': + return + + for dl in ctx.lines: + if dl.linetype in (LineType.BLANK, LineType.PREPROCESSOR): + continue + if dl.linetype == LineType.CONTINUATION: + continue # continuations align to <, not to indent unit + if dl.linetype in (LineType.COMMENT_BODY, LineType.COMMENT_END): + continue + if not dl.indent_str: + continue + # The indent must be 'unit' repeated dl.depth times, exactly. + # NODE_CLOSE lines have depth equal to the post-decrement value, + # which matches the indent expected. + expected = unit * dl.depth + if dl.indent_str != expected: + yield (dl.lineno, + 'indent mismatch (expected depth %d * %r)' % + (dl.depth, unit)) + + +def check_indent_unit_dts(ctx): + """DTS files: 1 tab per level. Always required.""" + (unit, lineno) = _detect_indent_unit(ctx) + if unit is None: + return + if unit != '\t': + yield (lineno, 'indent unit must be 1 tab in DTS, got %r' % unit) + + +def check_indent_unit_relaxed(ctx): + """YAML examples: 2 or 4 spaces. Never tabs or other widths.""" + (unit, lineno) = _detect_indent_unit(ctx) + if unit is None: + return + if unit not in (' ', ' '): + yield (lineno, 'indent unit must be 2 or 4 spaces, got %r' % unit) + + +def check_indent_unit_strict(ctx): + """YAML: must be exactly 4 spaces. DTS: 1 tab (same as relaxed).""" + (unit, lineno) = _detect_indent_unit(ctx) + if unit is None: + return + if ctx.file_type == 'yaml': + if unit != ' ': + yield (lineno, 'indent unit must be 4 spaces in strict mode, ' + 'got %r' % unit) + + +def check_line_length(ctx): + """Lines must not exceed 80 columns; tabs count as 8 (see + _display_col).""" + for dl in ctx.lines: + if dl.linetype == LineType.BLANK: + continue + cols = _display_col(dl.raw) + if cols > 80: + yield (dl.lineno, + 'line exceeds 80 columns (%d)' % cols) + + +def check_mixed_indent_chars(ctx): + """Indent must be all-tabs, except for aligning indentation (comments + or continued lines).""" + for dl in ctx.lines: + if not dl.indent_str: + continue + if dl.linetype == LineType.PREPROCESSOR: + continue + if re.search(r' \t', dl.indent_str): + yield (dl.lineno, 'mixed tabs and spaces in indent') + if dl.indent_str.count(' ') > 7: + yield (dl.lineno, 'too many space characters in indent (more than 7)') + for cont in dl.continuations: + if not cont.indent_str: + continue + if cont.linetype == LineType.PREPROCESSOR: continue - unaddressed.append((_natural_sort_key(c.node_name), c)) - for i in range(1, len(unaddressed)): - if unaddressed[i][0] < unaddressed[i - 1][0]: - dl = unaddressed[i][1] + if re.search(r' \t', cont.indent_str): + yield (cont.lineno, 'mixed tabs and spaces in indent') + + +def check_node_close_alone(ctx): + """The closing '};' of a node must be on its own line. The + classifier accepts a canonical "}" or "};" as NODE_CLOSE; a line + that is all closures (e.g. "}; };") is still NODE_CLOSE for depth + tracking but is flagged here via dl.closures. Any other line that + still contains '};' (in code, not in strings or comments) is + mixing a node close with something else.""" + for dl in ctx.lines: + if dl.linetype == LineType.NODE_CLOSE: + if dl.closures > 1: yield (dl.lineno, - 'child node %r out of name order' % dl.node_name) + 'closing brace must be on its own line') + continue + if dl.linetype in (LineType.BLANK, LineType.COMMENT, + LineType.COMMENT_START, LineType.COMMENT_BODY, + LineType.COMMENT_END, LineType.PREPROCESSOR): + continue + if '};' in dl.code: + yield (dl.lineno, + 'closing brace must be on its own line') def _property_bucket(name): @@ -769,17 +821,40 @@ def check_property_order(ctx): (p.prop_name, prev.prop_name)) -def _strip_strings_and_comments(text): - """Remove string literals and /* */ + // comments from a single - line, replacing them with empty strings. Used so syntactic checks - (whitespace, hex case, etc.) don't false-positive on contents of - quoted strings or comments. An unclosed /* on the line is treated - as a comment running to end of line.""" - text = re.sub(r'"(?:[^"\\]|\\.)*"', '""', text) - text = re.sub(r'/\*.*?\*/', '', text) - text = re.sub(r'/\*.*$', '', text) - text = re.sub(r'//.*$', '', text) - return text +def _check_redundant_whitespace(dl): + if dl.linetype in (LineType.COMMENT, LineType.COMMENT_BODY, + LineType.COMMENT_END, LineType.COMMENT_START, + LineType.PREPROCESSOR): + return + if re.search(r'(\s\s+|\t)\{', dl.code): + yield (dl.lineno, 'extra whitespace before {') + if re.search(r':(\s\s+|\t)', dl.code): + yield (dl.lineno, 'extra whitespace after :') + if re.search(r'\s+;', dl.code): + yield (dl.lineno, 'extra whitespace before ;') + + +def check_redundant_whitespace(ctx): + """No whitespace between brackets or other code elements. + See also check_value_whitespace() for more checks.""" + for dl in ctx.lines: + yield from _check_redundant_whitespace(dl) + for cont in dl.continuations: + yield from _check_redundant_whitespace(cont) + + +def check_redundant_whitespace_strict(ctx): + """No whitespace between brackets or other code elements. + See also check_value_whitespace() for more checks.""" + for dl in ctx.lines: + if dl.linetype in (LineType.COMMENT, LineType.COMMENT_BODY, + LineType.COMMENT_END, LineType.COMMENT_START, + LineType.PREPROCESSOR): + continue + if re.search(r'(\s\s+|\t)=', dl.code): + yield (dl.lineno, 'extra whitespace before =') + if re.search(r'=(\s\s+|\t)', dl.code): + yield (dl.lineno, 'extra whitespace after =') def check_required_blank_lines(ctx): @@ -841,18 +916,49 @@ def check_required_blank_lines(ctx): between_blanks = 0 -def check_hex_case(ctx): - """Hex literals (0xN) must use lowercase digits and prefix.""" +def check_tab_in_yaml_example(ctx): + """Reject literal tabs in DTS lines when input is YAML. + + For YAML examples, indent and content must use spaces. Tabs inside + a #define value are tolerated (those are CPP macros, not DTS). + For .dts files, this rule does not apply -- tabs are required. + """ + if ctx.file_type != 'yaml': + return for dl in ctx.lines: - if dl.linetype in (LineType.BLANK, LineType.COMMENT, - LineType.COMMENT_START, LineType.COMMENT_BODY, - LineType.COMMENT_END, LineType.PREPROCESSOR): + if dl.linetype == LineType.PREPROCESSOR: continue - for m in re.finditer(r'\b0[xX][0-9a-fA-F]+\b', dl.code): - lit = m.group(0) - if any(c.isupper() for c in lit[2:]) or lit[1] == 'X': - yield (dl.lineno, - 'hex literal %r must be lowercase' % lit) + if dl.linetype == LineType.BLANK: + continue + if '\t' in dl.raw: + yield (dl.lineno, 'tab character not allowed in DTS example') + + +def check_trailing_whitespace(ctx): + for dl in ctx.lines: + if dl.raw != dl.raw.rstrip(): + yield (dl.lineno, 'trailing whitespace') + + +def check_unclosed_block_comment(ctx): + """Every /* must have a matching */ in the same block. Catches both + a comment opened on its own line (COMMENT_START) and a tail comment + opened on a PROPERTY or other code line (where in_block_comment is + set by _split_code so the next line becomes COMMENT_BODY without a + preceding COMMENT_START).""" + open_lineno = None + for dl in ctx.lines: + if dl.linetype == LineType.COMMENT_START: + open_lineno = dl.lineno + elif dl.linetype == LineType.COMMENT_END: + open_lineno = None + elif dl.linetype == LineType.COMMENT_BODY and open_lineno is None: + # Block was opened by a /* tail on a code line; report at + # the first orphan body line since the originating line is + # already classified as something else. + open_lineno = dl.lineno + if open_lineno is not None: + yield (open_lineno, 'unclosed /* block comment') def check_unit_address_format(ctx): @@ -886,6 +992,17 @@ def check_unit_address_format(ctx): break +def check_unused_labels(ctx): + """Labels defined but never referenced are clutter.""" + defined, referenced = collect_labels_and_refs(ctx.text) + for label in sorted(defined - referenced): + # Find the line where this label is defined for line-number + # reporting. + m = re.search(r'(?m)^.*\b' + re.escape(label) + r'\s*:', ctx.text) + lineno = ctx.text[:m.start()].count('\n') + 1 if m else 1 + yield (lineno, 'label %r defined but never &-referenced' % label) + + def check_value_whitespace(ctx): """A <...> cell list must have no whitespace directly after '<' or directly before '>'. Continuation lines are joined onto the @@ -914,122 +1031,6 @@ def check_value_whitespace(ctx): break -def check_node_close_alone(ctx): - """The closing '};' of a node must be on its own line. The - classifier accepts a canonical "}" or "};" as NODE_CLOSE; a line - that is all closures (e.g. "}; };") is still NODE_CLOSE for depth - tracking but is flagged here via dl.closures. Any other line that - still contains '};' (in code, not in strings or comments) is - mixing a node close with something else.""" - for dl in ctx.lines: - if dl.linetype == LineType.NODE_CLOSE: - if dl.closures > 1: - yield (dl.lineno, - 'closing brace must be on its own line') - continue - if dl.linetype in (LineType.BLANK, LineType.COMMENT, - LineType.COMMENT_START, LineType.COMMENT_BODY, - LineType.COMMENT_END, LineType.PREPROCESSOR): - continue - if '};' in dl.code: - yield (dl.lineno, - 'closing brace must be on its own line') - - -def _display_col(text): - """Visual column width of text, with tabs expanded to the next - 8-column stop, matching how printf and most editors render a - line and the kernel-wide line length convention.""" - col = 0 - for ch in text: - if ch == '\t': - col = (col // 8 + 1) * 8 - else: - col += 1 - return col - - -def check_line_length(ctx): - """Lines must not exceed 80 columns; tabs count as 8 (see - _display_col).""" - for dl in ctx.lines: - if dl.linetype == LineType.BLANK: - continue - cols = _display_col(dl.raw) - if cols > 80: - yield (dl.lineno, - 'line exceeds 80 columns (%d)' % cols) - - -def check_continuation_alignment(ctx): - """A multi-line property's continuation lines must align their - first non-whitespace character to the display column of: - 1. the first '<' or '"' after the '=' in the leading line, if continuation is with '<' or '"' - 2. the first value, if the continuation is still the same phandle. - Display columns are used so tab-indented .dts files (where a continuation - aligns with tabs plus spaces) are compared correctly.""" - for dl in ctx.lines: - if dl.linetype != LineType.PROPERTY: - continue - if not dl.continuations: - continue - eq = dl.raw.find('=') - if eq < 0: - continue - # First '<' or '"' after '=', but ignore comments and strip trailing - # whitespace (e.g. remaining after removing the comment) - rest = _strip_strings_and_comments(dl.raw[eq + 1:]).rstrip() - m = re.search(r'\s*([<"])', rest) - if not m: - continue - dl_value_complete = rest.endswith('",') or rest.endswith('>,') - target_col = _display_col(_strip_strings_and_comments(dl.raw[:eq + 1 + m.start(1)])) - for cont in dl.continuations: - target_offset = 0 - err_msg_explanation = 'to < or "' - if not dl_value_complete: - target_offset = 1 - err_msg_explanation = 'to the value under <' - if _display_col(cont.indent_str) != target_col + target_offset: - yield (cont.lineno, - 'continuation should align to column %d ' - '(%s)' % (target_col + target_offset + 1, err_msg_explanation)) - # Align to the value within <> or "" of continuation (so the previous line) - dl_value_complete = cont.stripped.endswith('",') or cont.stripped.endswith('>,') - - -def check_unclosed_block_comment(ctx): - """Every /* must have a matching */ in the same block. Catches both - a comment opened on its own line (COMMENT_START) and a tail comment - opened on a PROPERTY or other code line (where in_block_comment is - set by _split_code so the next line becomes COMMENT_BODY without a - preceding COMMENT_START).""" - open_lineno = None - for dl in ctx.lines: - if dl.linetype == LineType.COMMENT_START: - open_lineno = dl.lineno - elif dl.linetype == LineType.COMMENT_END: - open_lineno = None - elif dl.linetype == LineType.COMMENT_BODY and open_lineno is None: - # Block was opened by a /* tail on a code line; report at - # the first orphan body line since the originating line is - # already classified as something else. - open_lineno = dl.lineno - if open_lineno is not None: - yield (open_lineno, 'unclosed /* block comment') - - -def check_unused_labels(ctx): - """Labels defined but never referenced are clutter.""" - defined, referenced = collect_labels_and_refs(ctx.text) - for label in sorted(defined - referenced): - # Find the line where this label is defined for line-number - # reporting. - m = re.search(r'(?m)^.*\b' + re.escape(label) + r'\s*:', ctx.text) - lineno = ctx.text[:m.start()].count('\n') + 1 if m else 1 - yield (lineno, 'label %r defined but never &-referenced' % label) - - # --- registry -------------------------------------------------------------- RULES = [ -- cgit v1.2.3 From e3a8397f060251d53715877ee4225ae539d95cfa Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2026 21:53:19 +0200 Subject: dtc: dt-check-style: Process property names with a question mark Devicetree spec allows question mark '?' in property names and such code is also accepted by DTC, thus catch such properties as a valid code, even if discouraged. Otherwise certain rules checking for property names would ignore that line. Signed-off-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20260829-dts-style-checker-sort-v1-3-6693a37d7ae1@oss.qualcomm.com Signed-off-by: Rob Herring (Arm) --- scripts/dtc/dt-check-style | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/dtc/dt-check-style b/scripts/dtc/dt-check-style index 5385a03f377e..7c3ee1432dc6 100755 --- a/scripts/dtc/dt-check-style +++ b/scripts/dtc/dt-check-style @@ -280,7 +280,7 @@ def parse_node_header(dl): def parse_property_name(dl): - m = re.match(r'^([a-zA-Z0-9#][a-zA-Z0-9,._+#-]*)\s*[=;]', dl.stripped) + m = re.match(r'^([a-zA-Z0-9#][a-zA-Z0-9,._+?#-]*)\s*[=;]', dl.stripped) if m: dl.prop_name = m.group(1) -- cgit v1.2.3 From 868507636f6c9c8ee2d0cf48f1a03ccd5abb6195 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2026 21:53:20 +0200 Subject: dtc: dt-check-style: Add test for node and property name styles Common style violation is usage of underscores in node or property names, so add rules for following recommended names. There is plenty of legacy approach, so add the rules only for 'strict' mode of checking. Signed-off-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20260829-dts-style-checker-sort-v1-4-6693a37d7ae1@oss.qualcomm.com Signed-off-by: Rob Herring (Arm) --- scripts/dtc/dt-check-style | 31 +++++++++++ .../dtc/dt-style-selftest/bad/dts-node-name.dts | 60 ++++++++++++++++++++++ .../dt-style-selftest/bad/dts-property-name.dts | 28 ++++++++++ .../dtc/dt-style-selftest/bad/yaml-node-name.yaml | 54 +++++++++++++++++++ .../dt-style-selftest/bad/yaml-property-name.yaml | 46 +++++++++++++++++ .../expected/dts-node-name.dts.txt | 13 +++++ .../expected/dts-property-name.dts.txt | 14 +++++ .../expected/yaml-node-name.yaml.txt | 7 +++ .../expected/yaml-property-name.yaml.txt | 14 +++++ 9 files changed, 267 insertions(+) create mode 100644 scripts/dtc/dt-style-selftest/bad/dts-node-name.dts create mode 100644 scripts/dtc/dt-style-selftest/bad/dts-property-name.dts create mode 100644 scripts/dtc/dt-style-selftest/bad/yaml-node-name.yaml create mode 100644 scripts/dtc/dt-style-selftest/bad/yaml-property-name.yaml create mode 100644 scripts/dtc/dt-style-selftest/expected/dts-node-name.dts.txt create mode 100644 scripts/dtc/dt-style-selftest/expected/dts-property-name.dts.txt create mode 100644 scripts/dtc/dt-style-selftest/expected/yaml-node-name.yaml.txt create mode 100644 scripts/dtc/dt-style-selftest/expected/yaml-property-name.yaml.txt (limited to 'scripts') diff --git a/scripts/dtc/dt-check-style b/scripts/dtc/dt-check-style index 7c3ee1432dc6..16586d0029ff 100755 --- a/scripts/dtc/dt-check-style +++ b/scripts/dtc/dt-check-style @@ -676,6 +676,31 @@ def check_node_close_alone(ctx): 'closing brace must be on its own line') +def check_node_name(ctx): + """Only recommended characters are used in node names.""" + for dl in ctx.lines: + if not dl.node_name in (None, '/'): + if not re.match(r'[0-9a-z][0-9a-z-]*(?; + #size-cells = <1>; + + foo_bar { + compatible = "example,test-node-name"; + }; + + foo,bar { + compatible = "example,test-node-name"; + }; + + foo.bar { + compatible = "example,test-node-name"; + }; + + foo+bar { + compatible = "example,test-node-name"; + }; + + foo-bar- { + compatible = "example,test-node-name"; + }; + + soc@0 { + compatible = "simple-bus"; + ranges = <0 0 0 0xc0000000>; + + #address-cells = <1>; + #size-cells = <1>; + + foo_bar@1000 { + compatible = "example,test-node-name"; + reg = <0x1000 0x100>; + }; + + foo,bar@2000 { + compatible = "example,test-node-name"; + reg = <0x2000 0x100>; + }; + + foo.bar@3000 { + compatible = "example,test-node-name"; + reg = <0x3000 0x100>; + }; + + foo+bar@4000 { + compatible = "example,test-node-name"; + reg = <0x4000 0x100>; + }; + + foo-bar-@5000 { + compatible = "example,test-node-name"; + reg = <0x5000 0x100>; + }; + }; +}; diff --git a/scripts/dtc/dt-style-selftest/bad/dts-property-name.dts b/scripts/dtc/dt-style-selftest/bad/dts-property-name.dts new file mode 100644 index 000000000000..110e33a524dd --- /dev/null +++ b/scripts/dtc/dt-style-selftest/bad/dts-property-name.dts @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + foo { + compatible = "example,test-property-name"; + + property#foo; + property+foo; + property-foo; + property-foo-; + property.foo; + property?foo; + property_foo; + + vendor,property#foo; + vendor,property+foo; + vendor,property,foo; + vendor,property-foo; + vendor,property-foo-; + vendor,property.foo; + vendor,property?foo; + vendor,property_foo; + }; +}; diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-node-name.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-node-name.yaml new file mode 100644 index 000000000000..03373cae9a66 --- /dev/null +++ b/scripts/dtc/dt-style-selftest/bad/yaml-node-name.yaml @@ -0,0 +1,54 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/test-node-name.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Test fixture with incorrect node names + +maintainers: + - Rob Herring + +properties: + compatible: + const: example,test-node-name + reg: + maxItems: 1 + +required: + - compatible + +additionalProperties: false + +examples: + - | + foo_bar@1000 { + compatible = "example,test-node-name"; + reg = <0x1000 0x100>; + }; + + foo,bar@2000 { + compatible = "example,test-node-name"; + reg = <0x2000 0x100>; + }; + + foo.bar@3000 { + compatible = "example,test-node-name"; + reg = <0x3000 0x100>; + }; + + foo+bar@4000 { + compatible = "example,test-node-name"; + reg = <0x4000 0x100>; + }; + + foo-bar-@5000 { + compatible = "example,test-node-name"; + reg = <0x5000 0x100>; + }; + + // TODO handle also "-foo-bar" which is against spec but accepted by DTC + + foo_bar { + compatible = "example,test-node-name"; + }; diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-property-name.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-property-name.yaml new file mode 100644 index 000000000000..08e0d1eb152a --- /dev/null +++ b/scripts/dtc/dt-style-selftest/bad/yaml-property-name.yaml @@ -0,0 +1,46 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/test-property-name.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Test fixture with incorrect property names + +maintainers: + - Rob Herring + +properties: + compatible: + const: example,test-property-name + reg: + maxItems: 1 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + foo@1000 { + compatible = "example,test-property-name"; + reg = <0x1000 0x100>; + + property#foo; + property+foo; + property-foo; + property-foo-; + property.foo; + property?foo; + property_foo; + + vendor,property#foo; + vendor,property+foo; + vendor,property,foo; + vendor,property-foo; + vendor,property-foo-; + vendor,property.foo; + vendor,property?foo; + vendor,property_foo; + }; diff --git a/scripts/dtc/dt-style-selftest/expected/dts-node-name.dts.txt b/scripts/dtc/dt-style-selftest/expected/dts-node-name.dts.txt new file mode 100644 index 000000000000..bd8d7e21e243 --- /dev/null +++ b/scripts/dtc/dt-style-selftest/expected/dts-node-name.dts.txt @@ -0,0 +1,13 @@ +# mode=strict +bad/dts-node-name.dts:8: [node-name] node name "foo_bar" is using discouraged style +bad/dts-node-name.dts:12: [child-name-order] child node 'foo,bar' out of name order +bad/dts-node-name.dts:12: [node-name] node name "foo,bar" is using discouraged style +bad/dts-node-name.dts:16: [node-name] node name "foo.bar" is using discouraged style +bad/dts-node-name.dts:20: [child-name-order] child node 'foo+bar' out of name order +bad/dts-node-name.dts:20: [node-name] node name "foo+bar" is using discouraged style +bad/dts-node-name.dts:24: [node-name] node name "foo-bar-" is using discouraged style +bad/dts-node-name.dts:35: [node-name] node name "foo_bar" is using discouraged style +bad/dts-node-name.dts:40: [node-name] node name "foo,bar" is using discouraged style +bad/dts-node-name.dts:45: [node-name] node name "foo.bar" is using discouraged style +bad/dts-node-name.dts:50: [node-name] node name "foo+bar" is using discouraged style +bad/dts-node-name.dts:55: [node-name] node name "foo-bar-" is using discouraged style diff --git a/scripts/dtc/dt-style-selftest/expected/dts-property-name.dts.txt b/scripts/dtc/dt-style-selftest/expected/dts-property-name.dts.txt new file mode 100644 index 000000000000..f447743383da --- /dev/null +++ b/scripts/dtc/dt-style-selftest/expected/dts-property-name.dts.txt @@ -0,0 +1,14 @@ +# mode=strict +bad/dts-property-name.dts:11: [property-name] property name "property#foo" is using discouraged style +bad/dts-property-name.dts:12: [property-name] property name "property+foo" is using discouraged style +bad/dts-property-name.dts:14: [property-name] property name "property-foo-" is using discouraged style +bad/dts-property-name.dts:15: [property-name] property name "property.foo" is using discouraged style +bad/dts-property-name.dts:16: [property-name] property name "property?foo" is using discouraged style +bad/dts-property-name.dts:17: [property-name] property name "property_foo" is using discouraged style +bad/dts-property-name.dts:19: [property-name] property name "vendor,property#foo" is using discouraged style +bad/dts-property-name.dts:20: [property-name] property name "vendor,property+foo" is using discouraged style +bad/dts-property-name.dts:21: [property-name] property name "vendor,property,foo" is using discouraged style +bad/dts-property-name.dts:23: [property-name] property name "vendor,property-foo-" is using discouraged style +bad/dts-property-name.dts:24: [property-name] property name "vendor,property.foo" is using discouraged style +bad/dts-property-name.dts:25: [property-name] property name "vendor,property?foo" is using discouraged style +bad/dts-property-name.dts:26: [property-name] property name "vendor,property_foo" is using discouraged style diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-node-name.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-node-name.yaml.txt new file mode 100644 index 000000000000..d9cf749e35c2 --- /dev/null +++ b/scripts/dtc/dt-style-selftest/expected/yaml-node-name.yaml.txt @@ -0,0 +1,7 @@ +# mode=strict +bad/yaml-node-name.yaml:25: example 0 [node-name] node name "foo_bar" is using discouraged style +bad/yaml-node-name.yaml:30: example 0 [node-name] node name "foo,bar" is using discouraged style +bad/yaml-node-name.yaml:35: example 0 [node-name] node name "foo.bar" is using discouraged style +bad/yaml-node-name.yaml:40: example 0 [node-name] node name "foo+bar" is using discouraged style +bad/yaml-node-name.yaml:45: example 0 [node-name] node name "foo-bar-" is using discouraged style +bad/yaml-node-name.yaml:52: example 0 [node-name] node name "foo_bar" is using discouraged style diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-property-name.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-property-name.yaml.txt new file mode 100644 index 000000000000..6aa3a004532b --- /dev/null +++ b/scripts/dtc/dt-style-selftest/expected/yaml-property-name.yaml.txt @@ -0,0 +1,14 @@ +# mode=strict +bad/yaml-property-name.yaml:30: example 0 [property-name] property name "property#foo" is using discouraged style +bad/yaml-property-name.yaml:31: example 0 [property-name] property name "property+foo" is using discouraged style +bad/yaml-property-name.yaml:33: example 0 [property-name] property name "property-foo-" is using discouraged style +bad/yaml-property-name.yaml:34: example 0 [property-name] property name "property.foo" is using discouraged style +bad/yaml-property-name.yaml:35: example 0 [property-name] property name "property?foo" is using discouraged style +bad/yaml-property-name.yaml:36: example 0 [property-name] property name "property_foo" is using discouraged style +bad/yaml-property-name.yaml:38: example 0 [property-name] property name "vendor,property#foo" is using discouraged style +bad/yaml-property-name.yaml:39: example 0 [property-name] property name "vendor,property+foo" is using discouraged style +bad/yaml-property-name.yaml:40: example 0 [property-name] property name "vendor,property,foo" is using discouraged style +bad/yaml-property-name.yaml:42: example 0 [property-name] property name "vendor,property-foo-" is using discouraged style +bad/yaml-property-name.yaml:43: example 0 [property-name] property name "vendor,property.foo" is using discouraged style +bad/yaml-property-name.yaml:44: example 0 [property-name] property name "vendor,property?foo" is using discouraged style +bad/yaml-property-name.yaml:45: example 0 [property-name] property name "vendor,property_foo" is using discouraged style -- cgit v1.2.3 From 233c5c03adbfa0a39f64556f7b7198bc989f4b12 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2026 21:53:21 +0200 Subject: dtc: dt-check-style: Check for indentation also in continued lines of DTS Add missing code in check_mixed_indent_chars() for DTS to apply the same rule of too many spaces for indentation also for continued lines (iterating over all DtsLines is not enough). Reported-by: sashiko-bot@kernel.org Closes: https://lore.kernel.org/all/20260709180118.6935B1F000E9@smtp.kernel.org/ Signed-off-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20260829-dts-style-checker-sort-v1-5-6693a37d7ae1@oss.qualcomm.com Signed-off-by: Rob Herring (Arm) --- scripts/dtc/dt-check-style | 2 ++ scripts/dtc/dt-style-selftest/expected/dts-mixed-indent.dts.txt | 1 + 2 files changed, 3 insertions(+) (limited to 'scripts') diff --git a/scripts/dtc/dt-check-style b/scripts/dtc/dt-check-style index 16586d0029ff..dc5a8ee23d68 100755 --- a/scripts/dtc/dt-check-style +++ b/scripts/dtc/dt-check-style @@ -652,6 +652,8 @@ def check_mixed_indent_chars(ctx): continue if re.search(r' \t', cont.indent_str): yield (cont.lineno, 'mixed tabs and spaces in indent') + if cont.indent_str.count(' ') > 7: + yield (cont.lineno, 'too many space characters in indent (more than 7)') def check_node_close_alone(ctx): diff --git a/scripts/dtc/dt-style-selftest/expected/dts-mixed-indent.dts.txt b/scripts/dtc/dt-style-selftest/expected/dts-mixed-indent.dts.txt index 93146cfb51c7..1706390f5664 100644 --- a/scripts/dtc/dt-style-selftest/expected/dts-mixed-indent.dts.txt +++ b/scripts/dtc/dt-style-selftest/expected/dts-mixed-indent.dts.txt @@ -6,4 +6,5 @@ bad/dts-mixed-indent.dts:12: [mixed-indent-chars] mixed tabs and spaces in inden bad/dts-mixed-indent.dts:13: [indent-consistent] indent mismatch (expected depth 2 * '\t') bad/dts-mixed-indent.dts:13: [mixed-indent-chars] mixed tabs and spaces in indent bad/dts-mixed-indent.dts:16: [mixed-indent-chars] mixed tabs and spaces in indent +bad/dts-mixed-indent.dts:18: [mixed-indent-chars] too many space characters in indent (more than 7) bad/dts-mixed-indent.dts:19: [indent-consistent] indent mismatch (expected depth 2 * '\t') -- cgit v1.2.3 From 99a1ea49cd4239726f2382213c273f73bcb6a93d Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2026 21:53:22 +0200 Subject: dtc: dt-check-style: Check for indentation also in continued lines of bindings example Add missing code in check_tab_in_yaml_example() for example in the bindings to apply the same rule of discouraged tab character also for continued lines (iterating over all DtsLines is not enough). Signed-off-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20260829-dts-style-checker-sort-v1-6-6693a37d7ae1@oss.qualcomm.com Signed-off-by: Rob Herring (Arm) --- scripts/dtc/dt-check-style | 3 +++ scripts/dtc/dt-style-selftest/bad/yaml-mixed-indent.yaml | 2 ++ scripts/dtc/dt-style-selftest/expected/yaml-mixed-indent.yaml.txt | 1 + 3 files changed, 6 insertions(+) (limited to 'scripts') diff --git a/scripts/dtc/dt-check-style b/scripts/dtc/dt-check-style index dc5a8ee23d68..0ebbe658b893 100755 --- a/scripts/dtc/dt-check-style +++ b/scripts/dtc/dt-check-style @@ -959,6 +959,9 @@ def check_tab_in_yaml_example(ctx): continue if '\t' in dl.raw: yield (dl.lineno, 'tab character not allowed in DTS example') + for cont in dl.continuations: + if '\t' in cont.raw: + yield (cont.lineno, 'tab character not allowed in DTS example') def check_trailing_whitespace(ctx): diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-mixed-indent.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-mixed-indent.yaml index c25a0d1a999e..4f76188b5e23 100644 --- a/scripts/dtc/dt-style-selftest/bad/yaml-mixed-indent.yaml +++ b/scripts/dtc/dt-style-selftest/bad/yaml-mixed-indent.yaml @@ -26,4 +26,6 @@ examples: device@1000 { compatible = "example,test-mixed"; reg = <0x1000 0x100>; + clocks = <1>, + <2>; }; diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-mixed-indent.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-mixed-indent.yaml.txt index bc3fc3cf00cc..442f21f90e83 100644 --- a/scripts/dtc/dt-style-selftest/expected/yaml-mixed-indent.yaml.txt +++ b/scripts/dtc/dt-style-selftest/expected/yaml-mixed-indent.yaml.txt @@ -1,2 +1,3 @@ # mode=relaxed bad/yaml-mixed-indent.yaml:27: example 0 [tab-in-yaml] tab character not allowed in DTS example +bad/yaml-mixed-indent.yaml:30: example 0 [tab-in-yaml] tab character not allowed in DTS example -- cgit v1.2.3 From 95041262511eeec15aa14c53b7e7daf1355259c5 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 15 Sep 2026 19:03:45 +0200 Subject: dtc: dt-check-style: Handle continued lines in check_hex_case() Continued lines are not separate DtsLine items in ctx.lines, so they need own iteration. Rule for hex case is applicable to continued values as well. Signed-off-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20260915-b4-dts-style-checker-continued-lines-v4-1-5b8e09b11ef2@oss.qualcomm.com Signed-off-by: Rob Herring (Arm) --- scripts/dtc/dt-check-style | 24 ++++++++++++++-------- .../dtc/dt-style-selftest/bad/yaml-hex-case.yaml | 5 ++++- .../expected/yaml-hex-case.yaml.txt | 2 ++ 3 files changed, 21 insertions(+), 10 deletions(-) (limited to 'scripts') diff --git a/scripts/dtc/dt-check-style b/scripts/dtc/dt-check-style index 0ebbe658b893..2d0463c626e5 100755 --- a/scripts/dtc/dt-check-style +++ b/scripts/dtc/dt-check-style @@ -547,18 +547,24 @@ def check_continuation_alignment(ctx): dl_value_complete = cont.stripped.endswith('",') or cont.stripped.endswith('>,') +def _check_hex_case(dl): + if dl.linetype in (LineType.BLANK, LineType.COMMENT, + LineType.COMMENT_START, LineType.COMMENT_BODY, + LineType.COMMENT_END, LineType.PREPROCESSOR): + return + for m in re.finditer(r'\b0[xX][0-9a-fA-F]+\b', dl.code): + lit = m.group(0) + if any(c.isupper() for c in lit[2:]) or lit[1] == 'X': + yield (dl.lineno, + 'hex literal %r must be lowercase' % lit) + + def check_hex_case(ctx): """Hex literals (0xN) must use lowercase digits and prefix.""" for dl in ctx.lines: - if dl.linetype in (LineType.BLANK, LineType.COMMENT, - LineType.COMMENT_START, LineType.COMMENT_BODY, - LineType.COMMENT_END, LineType.PREPROCESSOR): - continue - for m in re.finditer(r'\b0[xX][0-9a-fA-F]+\b', dl.code): - lit = m.group(0) - if any(c.isupper() for c in lit[2:]) or lit[1] == 'X': - yield (dl.lineno, - 'hex literal %r must be lowercase' % lit) + yield from _check_hex_case(dl) + for cont in dl.continuations: + yield from _check_hex_case(cont) def check_indent_consistent(ctx): diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-hex-case.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-hex-case.yaml index c55359a4ca68..b0b8683b883a 100644 --- a/scripts/dtc/dt-style-selftest/bad/yaml-hex-case.yaml +++ b/scripts/dtc/dt-style-selftest/bad/yaml-hex-case.yaml @@ -25,5 +25,8 @@ examples: - | foo@1000 { compatible = "example,test-hex-case"; - reg = <0xABCD 0x100>; + reg = <0xABCD 0x100>, + <0x2BCD 0x100>, + <0x3BCD + 0x100>; }; diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-hex-case.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-hex-case.yaml.txt index 6600f7cd1ba5..f42490256939 100644 --- a/scripts/dtc/dt-style-selftest/expected/yaml-hex-case.yaml.txt +++ b/scripts/dtc/dt-style-selftest/expected/yaml-hex-case.yaml.txt @@ -1,2 +1,4 @@ # mode=strict bad/yaml-hex-case.yaml:28: example 0 [hex-case] hex literal '0xABCD' must be lowercase +bad/yaml-hex-case.yaml:29: example 0 [hex-case] hex literal '0x2BCD' must be lowercase +bad/yaml-hex-case.yaml:30: example 0 [hex-case] hex literal '0x3BCD' must be lowercase -- cgit v1.2.3 From 27e3cf7b9125af41acdb935ffb413e6a4f03e94d Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 15 Sep 2026 19:03:46 +0200 Subject: dtc: dt-check-style: Handle continued lines in check_line_length() Continued lines are not separate DtsLine items in ctx.lines, so they need own iteration. Rule for length of line is applicable to continued values as well. Signed-off-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20260915-b4-dts-style-checker-continued-lines-v4-2-5b8e09b11ef2@oss.qualcomm.com Signed-off-by: Rob Herring (Arm) --- scripts/dtc/dt-check-style | 18 ++++++++++++------ scripts/dtc/dt-style-selftest/bad/dts-line-length.dts | 3 ++- .../dtc/dt-style-selftest/bad/yaml-line-length.yaml | 3 ++- .../dt-style-selftest/expected/dts-line-length.dts.txt | 1 + .../expected/yaml-line-length.yaml.txt | 1 + 5 files changed, 18 insertions(+), 8 deletions(-) (limited to 'scripts') diff --git a/scripts/dtc/dt-check-style b/scripts/dtc/dt-check-style index 2d0463c626e5..525d9df6c11b 100755 --- a/scripts/dtc/dt-check-style +++ b/scripts/dtc/dt-check-style @@ -627,16 +627,22 @@ def check_indent_unit_strict(ctx): 'got %r' % unit) +def _check_line_length(dl): + if dl.linetype == LineType.BLANK: + return + cols = _display_col(dl.raw) + if cols > 80: + yield (dl.lineno, + 'line exceeds 80 columns (%d)' % cols) + + def check_line_length(ctx): """Lines must not exceed 80 columns; tabs count as 8 (see _display_col).""" for dl in ctx.lines: - if dl.linetype == LineType.BLANK: - continue - cols = _display_col(dl.raw) - if cols > 80: - yield (dl.lineno, - 'line exceeds 80 columns (%d)' % cols) + yield from _check_line_length(dl) + for cont in dl.continuations: + yield from _check_line_length(cont) def check_mixed_indent_chars(ctx): diff --git a/scripts/dtc/dt-style-selftest/bad/dts-line-length.dts b/scripts/dtc/dt-style-selftest/bad/dts-line-length.dts index bde91a922477..adf40e3c95f7 100644 --- a/scripts/dtc/dt-style-selftest/bad/dts-line-length.dts +++ b/scripts/dtc/dt-style-selftest/bad/dts-line-length.dts @@ -14,7 +14,8 @@ #size-cells = <1>; foo@1000 { - compatible = "example,test-line-length-this-is-a-very-long-name-indeed-yeah"; + compatible = "example,test-line-length-this-is-a-very-long-name-indeed-yeah", + "example,test-line-length-this-is-a-very-long-name-indeed-yeah-second"; reg = <0x1000 0x100>; }; }; diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-line-length.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-line-length.yaml index 6e4140e500b5..6b1209ee4f26 100644 --- a/scripts/dtc/dt-style-selftest/bad/yaml-line-length.yaml +++ b/scripts/dtc/dt-style-selftest/bad/yaml-line-length.yaml @@ -24,6 +24,7 @@ additionalProperties: false examples: - | foo@1000 { - compatible = "example,test-line-length-this-is-a-very-long-name-indeed-yeah"; + compatible = "example,test-line-length-this-is-a-very-long-name-indeed-yeah", + "example,test-line-length-this-is-a-very-long-name-indeed-yeah-second"; reg = <0x1000 0x100>; }; diff --git a/scripts/dtc/dt-style-selftest/expected/dts-line-length.dts.txt b/scripts/dtc/dt-style-selftest/expected/dts-line-length.dts.txt index 8ed08c309632..9cdb7550b56c 100644 --- a/scripts/dtc/dt-style-selftest/expected/dts-line-length.dts.txt +++ b/scripts/dtc/dt-style-selftest/expected/dts-line-length.dts.txt @@ -1,2 +1,3 @@ # mode=stricter bad/dts-line-length.dts:17: [line-length-dts] line exceeds 80 columns (101) +bad/dts-line-length.dts:18: [line-length-dts] line exceeds 80 columns (108) diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-line-length.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-line-length.yaml.txt index 89b36360caa4..f21b823c6136 100644 --- a/scripts/dtc/dt-style-selftest/expected/yaml-line-length.yaml.txt +++ b/scripts/dtc/dt-style-selftest/expected/yaml-line-length.yaml.txt @@ -1,2 +1,3 @@ # mode=strict bad/yaml-line-length.yaml:27: example 0 [line-length] line exceeds 80 columns (81) +bad/yaml-line-length.yaml:28: example 0 [line-length] line exceeds 80 columns (88) -- cgit v1.2.3 From 77852e61c8f0bcca5aab708df649571c16388806 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 15 Sep 2026 19:03:47 +0200 Subject: dtc: dt-check-style: Handle continued lines in check_trailing_whitespace() Continued lines are not separate DtsLine items in ctx.lines, so they need own iteration. Rule for trailing white-space is applicable to continued values as well. Signed-off-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20260915-b4-dts-style-checker-continued-lines-v4-3-5b8e09b11ef2@oss.qualcomm.com Signed-off-by: Rob Herring (Arm) --- scripts/dtc/dt-check-style | 10 ++++++++-- scripts/dtc/dt-style-selftest/bad/dts-trailing-ws.dts | 8 ++++++++ scripts/dtc/dt-style-selftest/bad/yaml-trailing-ws.yaml | 5 ++++- scripts/dtc/dt-style-selftest/expected/dts-trailing-ws.dts.txt | 1 + .../dtc/dt-style-selftest/expected/yaml-trailing-ws.yaml.txt | 2 ++ 5 files changed, 23 insertions(+), 3 deletions(-) (limited to 'scripts') diff --git a/scripts/dtc/dt-check-style b/scripts/dtc/dt-check-style index 525d9df6c11b..4ac10cb45068 100755 --- a/scripts/dtc/dt-check-style +++ b/scripts/dtc/dt-check-style @@ -976,10 +976,16 @@ def check_tab_in_yaml_example(ctx): yield (cont.lineno, 'tab character not allowed in DTS example') +def _check_trailing_whitespace(dl): + if dl.raw != dl.raw.rstrip(): + yield (dl.lineno, 'trailing whitespace') + + def check_trailing_whitespace(ctx): for dl in ctx.lines: - if dl.raw != dl.raw.rstrip(): - yield (dl.lineno, 'trailing whitespace') + yield from _check_trailing_whitespace(dl) + for cont in dl.continuations: + yield from _check_trailing_whitespace(cont) def check_unclosed_block_comment(ctx): diff --git a/scripts/dtc/dt-style-selftest/bad/dts-trailing-ws.dts b/scripts/dtc/dt-style-selftest/bad/dts-trailing-ws.dts index 1eb24d91c640..73c24525ce18 100644 --- a/scripts/dtc/dt-style-selftest/bad/dts-trailing-ws.dts +++ b/scripts/dtc/dt-style-selftest/bad/dts-trailing-ws.dts @@ -5,4 +5,12 @@ compatible = "example,test-board"; #address-cells = <1>; #size-cells = <1>; + + interrupt-controller@10000 { + compatible = "example,intc"; + reg = <0x10000 0x1000>; + clocks = <1 2 3>, + <4 5 6>, + <7 8 9>; + }; }; diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-trailing-ws.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-trailing-ws.yaml index f338c14174e6..17eeed3411c6 100644 --- a/scripts/dtc/dt-style-selftest/bad/yaml-trailing-ws.yaml +++ b/scripts/dtc/dt-style-selftest/bad/yaml-trailing-ws.yaml @@ -25,5 +25,8 @@ examples: - | device@1000 { compatible = "example,test-trailing"; - reg = <0x1000 0x100>; + reg = <0x1000 0x100>, + <0x2000 0x100>, + <0x3000 + 0x100>; }; diff --git a/scripts/dtc/dt-style-selftest/expected/dts-trailing-ws.dts.txt b/scripts/dtc/dt-style-selftest/expected/dts-trailing-ws.dts.txt index 94d9ae9d616c..a15a7d637c30 100644 --- a/scripts/dtc/dt-style-selftest/expected/dts-trailing-ws.dts.txt +++ b/scripts/dtc/dt-style-selftest/expected/dts-trailing-ws.dts.txt @@ -1,2 +1,3 @@ # mode=relaxed bad/dts-trailing-ws.dts:5: [trailing-whitespace] trailing whitespace +bad/dts-trailing-ws.dts:13: [trailing-whitespace] trailing whitespace diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-trailing-ws.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-trailing-ws.yaml.txt index cfdbc8476c73..4f2ec9572bc6 100644 --- a/scripts/dtc/dt-style-selftest/expected/yaml-trailing-ws.yaml.txt +++ b/scripts/dtc/dt-style-selftest/expected/yaml-trailing-ws.yaml.txt @@ -1,2 +1,4 @@ # mode=relaxed bad/yaml-trailing-ws.yaml:27: example 0 [trailing-whitespace] trailing whitespace +bad/yaml-trailing-ws.yaml:29: example 0 [trailing-whitespace] trailing whitespace +bad/yaml-trailing-ws.yaml:30: example 0 [trailing-whitespace] trailing whitespace -- cgit v1.2.3 From c6138ed5cec688f86c4c2b872c6fb872b162987a Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 15 Sep 2026 19:03:48 +0200 Subject: dtc: dt-check-style: Unduplicate checks in check_mixed_indent_chars() Code checking each DtsLine and continuations is the same, so split it to separate function to avoid duplicated code. This has a positive side effect - if DtsLine did not have indentation, then check continued to next one, but now it will still go through the continued lines in the second loop. Signed-off-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20260915-b4-dts-style-checker-continued-lines-v4-4-5b8e09b11ef2@oss.qualcomm.com Signed-off-by: Rob Herring (Arm) --- scripts/dtc/dt-check-style | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) (limited to 'scripts') diff --git a/scripts/dtc/dt-check-style b/scripts/dtc/dt-check-style index 4ac10cb45068..41c97d996882 100755 --- a/scripts/dtc/dt-check-style +++ b/scripts/dtc/dt-check-style @@ -645,27 +645,24 @@ def check_line_length(ctx): yield from _check_line_length(cont) +def _check_mixed_indent_chars(dl): + if not dl.indent_str: + return + if dl.linetype == LineType.PREPROCESSOR: + return + if re.search(r' \t', dl.indent_str): + yield (dl.lineno, 'mixed tabs and spaces in indent') + if dl.indent_str.count(' ') > 7: + yield (dl.lineno, 'too many space characters in indent (more than 7)') + + def check_mixed_indent_chars(ctx): """Indent must be all-tabs, except for aligning indentation (comments or continued lines).""" for dl in ctx.lines: - if not dl.indent_str: - continue - if dl.linetype == LineType.PREPROCESSOR: - continue - if re.search(r' \t', dl.indent_str): - yield (dl.lineno, 'mixed tabs and spaces in indent') - if dl.indent_str.count(' ') > 7: - yield (dl.lineno, 'too many space characters in indent (more than 7)') + yield from _check_mixed_indent_chars(dl) for cont in dl.continuations: - if not cont.indent_str: - continue - if cont.linetype == LineType.PREPROCESSOR: - continue - if re.search(r' \t', cont.indent_str): - yield (cont.lineno, 'mixed tabs and spaces in indent') - if cont.indent_str.count(' ') > 7: - yield (cont.lineno, 'too many space characters in indent (more than 7)') + yield from _check_mixed_indent_chars(cont) def check_node_close_alone(ctx): -- cgit v1.2.3 From 897e4c0de6e6fda41815ae0457db0e254fc67821 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 15 Sep 2026 19:03:49 +0200 Subject: dtc: dt-check-style: Right strip whitespaces, leftovers before comments Stripping a comment from a line to get the code leads trailing whitespace (e.g. in a line like "enable-active-high; /* comment */") which will break DtsLine.code.endswith() checks. Signed-off-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20260915-b4-dts-style-checker-continued-lines-v4-5-5b8e09b11ef2@oss.qualcomm.com Signed-off-by: Rob Herring (Arm) --- scripts/dtc/dt-check-style | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/dtc/dt-check-style b/scripts/dtc/dt-check-style index 41c97d996882..a36c45c29476 100755 --- a/scripts/dtc/dt-check-style +++ b/scripts/dtc/dt-check-style @@ -91,7 +91,8 @@ class DtsLine: self.indent_str = indent_str # leading whitespace as-is self.depth = depth self.stripped = stripped # Code without indentation - self.code = _strip_strings_and_comments(stripped) # Only the code, skipping trailing comments + # Only the code, skipping trailing comments and space between code and trailing comment + self.code = _strip_strings_and_comments(stripped).rstrip() self.is_root = is_root self.prop_name = None self.continuations = [] -- cgit v1.2.3 From e97e9becf957216855a6b182ca5c1d0bc5e5065d Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 15 Sep 2026 19:03:50 +0200 Subject: dtc: dt-check-style: Properly detect comments in multi-line properties Code classifying given line exits on first condition match, thus a line consisting only of a comment in a continued (multi-line) property, like: interrupts = , /* Performance counter interrupts */ ; was treated as a comment-line line, not as continuation, leading to false positive warnings of invalid indentation: arch/arm64/boot/dts/tesla/fsd.dtsi:456: [indent-consistent] indent mismatch (expected depth 3 * '\t') This needs two related fixes: 1. Move the judgment as a LineType.CONTINUATION earlier before one classifying as a comment 2. Check the comment-stripped DtsLine.code, not DtsLine.stripped, to verify if it is a continuation. Signed-off-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20260915-b4-dts-style-checker-continued-lines-v4-6-5b8e09b11ef2@oss.qualcomm.com Signed-off-by: Rob Herring (Arm) --- scripts/dtc/dt-check-style | 19 ++++++++++--------- scripts/dtc/dt-style-selftest/bad/dts-cont-align.dts | 1 + .../dtc/dt-style-selftest/bad/yaml-cont-align.yaml | 1 + .../dt-style-selftest/expected/dts-cont-align.dts.txt | 11 ++++++----- .../expected/yaml-cont-align.yaml.txt | 3 ++- scripts/dtc/dt-style-selftest/good/dts-cont-align.dts | 1 + .../dtc/dt-style-selftest/good/yaml-cont-align.yaml | 1 + 7 files changed, 22 insertions(+), 15 deletions(-) (limited to 'scripts') diff --git a/scripts/dtc/dt-check-style b/scripts/dtc/dt-check-style index a36c45c29476..cbbb8d384aca 100755 --- a/scripts/dtc/dt-check-style +++ b/scripts/dtc/dt-check-style @@ -202,6 +202,14 @@ def classify_lines(text): if opens_block: in_block_comment = True + if not prev_complete: + dl = DtsLine(i, raw, LineType.CONTINUATION, depth, indent_str, code) + out.append(dl) + prev_complete = (code.endswith(';') or + code.endswith('{') or + code.endswith('};')) + continue + # Pure-comment line: nothing left after stripping. Classify as # COMMENT_START (carries to next line) or COMMENT, and skip the # structural classification entirely. @@ -211,14 +219,6 @@ def classify_lines(text): out.append(dl) continue - if not prev_complete: - dl = DtsLine(i, raw, LineType.CONTINUATION, depth, indent_str, code) - out.append(dl) - prev_complete = (code.endswith(';') or - code.endswith('{') or - code.endswith('};')) - continue - # NODE_CLOSE: the canonical form is "}" or "};" alone. A line # that is nothing but closures (e.g. "}; };") is still treated # as NODE_CLOSE for depth tracking, but the multi-closure case @@ -545,7 +545,8 @@ def check_continuation_alignment(ctx): 'continuation should align to column %d ' '(%s)' % (target_col + target_offset + 1, err_msg_explanation)) # Align to the value within <> or "" of continuation (so the previous line) - dl_value_complete = cont.stripped.endswith('",') or cont.stripped.endswith('>,') + if len(cont.code): + dl_value_complete = cont.code.endswith('",') or cont.code.endswith('>,') def _check_hex_case(dl): diff --git a/scripts/dtc/dt-style-selftest/bad/dts-cont-align.dts b/scripts/dtc/dt-style-selftest/bad/dts-cont-align.dts index 5390ebbf4059..91a74887c774 100644 --- a/scripts/dtc/dt-style-selftest/bad/dts-cont-align.dts +++ b/scripts/dtc/dt-style-selftest/bad/dts-cont-align.dts @@ -11,6 +11,7 @@ reg = <0x10000 0x1000>; clocks = <1 2 3>, /* comments with " < , should not matter */ <4 5 6>, + /* but comments should be placed properly */ <7 8 9>; interrupts = <1 2 3>, /* comments with " < , should not ... */ <4 5 6>, diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-cont-align.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-cont-align.yaml index a5a9eb17fc17..0189b654a5b0 100644 --- a/scripts/dtc/dt-style-selftest/bad/yaml-cont-align.yaml +++ b/scripts/dtc/dt-style-selftest/bad/yaml-cont-align.yaml @@ -27,6 +27,7 @@ examples: compatible = "example,test-cont-align"; reg = <0x1000 0x100>, /* comments with " < , should not matter */ <0x2000 0x100>, /* comments with " < , should not matter */ + /* but comments should be placed properly */ <0x3000 0x100>; }; diff --git a/scripts/dtc/dt-style-selftest/expected/dts-cont-align.dts.txt b/scripts/dtc/dt-style-selftest/expected/dts-cont-align.dts.txt index a7ed62677a2b..fd7f389d6cce 100644 --- a/scripts/dtc/dt-style-selftest/expected/dts-cont-align.dts.txt +++ b/scripts/dtc/dt-style-selftest/expected/dts-cont-align.dts.txt @@ -1,10 +1,11 @@ # mode=strict bad/dts-cont-align.dts:13: [continuation-alignment] continuation should align to column 26 (to < or ") bad/dts-cont-align.dts:14: [continuation-alignment] continuation should align to column 26 (to < or ") -bad/dts-cont-align.dts:16: [continuation-alignment] continuation should align to column 30 (to < or ") +bad/dts-cont-align.dts:15: [continuation-alignment] continuation should align to column 26 (to < or ") bad/dts-cont-align.dts:17: [continuation-alignment] continuation should align to column 30 (to < or ") -bad/dts-cont-align.dts:19: [continuation-alignment] continuation should align to column 27 (to the value under <) -bad/dts-cont-align.dts:20: [continuation-alignment] continuation should align to column 26 (to < or ") -bad/dts-cont-align.dts:21: [continuation-alignment] continuation should align to column 27 (to the value under <) -bad/dts-cont-align.dts:23: [continuation-alignment] continuation should align to column 38 (to < or ") +bad/dts-cont-align.dts:18: [continuation-alignment] continuation should align to column 30 (to < or ") +bad/dts-cont-align.dts:20: [continuation-alignment] continuation should align to column 27 (to the value under <) +bad/dts-cont-align.dts:21: [continuation-alignment] continuation should align to column 26 (to < or ") +bad/dts-cont-align.dts:22: [continuation-alignment] continuation should align to column 27 (to the value under <) bad/dts-cont-align.dts:24: [continuation-alignment] continuation should align to column 38 (to < or ") +bad/dts-cont-align.dts:25: [continuation-alignment] continuation should align to column 38 (to < or ") diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-cont-align.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-cont-align.yaml.txt index eb9a84d5c222..9e98c28867aa 100644 --- a/scripts/dtc/dt-style-selftest/expected/yaml-cont-align.yaml.txt +++ b/scripts/dtc/dt-style-selftest/expected/yaml-cont-align.yaml.txt @@ -1,3 +1,4 @@ # mode=strict bad/yaml-cont-align.yaml:29: example 0 [continuation-alignment] continuation should align to column 11 (to < or ") -bad/yaml-cont-align.yaml:31: example 0 [continuation-alignment] continuation should align to column 12 (to the value under <) +bad/yaml-cont-align.yaml:30: example 0 [continuation-alignment] continuation should align to column 11 (to < or ") +bad/yaml-cont-align.yaml:32: example 0 [continuation-alignment] continuation should align to column 12 (to the value under <) diff --git a/scripts/dtc/dt-style-selftest/good/dts-cont-align.dts b/scripts/dtc/dt-style-selftest/good/dts-cont-align.dts index b52ee6cccd8c..e6450a1d8209 100644 --- a/scripts/dtc/dt-style-selftest/good/dts-cont-align.dts +++ b/scripts/dtc/dt-style-selftest/good/dts-cont-align.dts @@ -17,6 +17,7 @@ reg = <0x10000 0x1000>; interrupts = <1 2 3>, /* comments with " < , should not ... */ <4 5 6>, + /* but comments should be placed properly */ <7 8 9>; pinmux = <0x01 0x02>, diff --git a/scripts/dtc/dt-style-selftest/good/yaml-cont-align.yaml b/scripts/dtc/dt-style-selftest/good/yaml-cont-align.yaml index 8463075f9f4c..4a5b5ad43ee8 100644 --- a/scripts/dtc/dt-style-selftest/good/yaml-cont-align.yaml +++ b/scripts/dtc/dt-style-selftest/good/yaml-cont-align.yaml @@ -27,6 +27,7 @@ examples: compatible = "example,test-cont-align"; reg = <0x1000 0x100>, <0x2000 0x100>, + /* but comments should be placed properly */ <0x3000 0x100>; }; -- cgit v1.2.3 From c08fe4da4acc36103152cd310a9eb64a99c161d2 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 15 Sep 2026 19:03:51 +0200 Subject: dtc: dt-check-style: Relax property ordering rules (drop alphabetical) Existing rules checked whether properties follow DTS Coding Style guidelines in respect of common properties and standard vs vendor properties, plus additionally it enforced alphabetical order within each of such group. The in-tree DTS does not follow such style at all, so this lead to many warnings. There is little value in fixing these warnings, because DTS with non-alphabetical order of properties is exactly the same readable, even though DTS Coding Style mentions natural order. Actually groupping properties logically, e.g. all supplies together regardless of their name, is more readable than pure natural sort. Relax the property order rules to the most important aspects (device_type, reg/reg-names, ranges, standard properties, vendor properties, status) and skip the alphabetical sorting completely. Assisted-by: LLM Signed-off-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20260915-b4-dts-style-checker-continued-lines-v4-7-5b8e09b11ef2@oss.qualcomm.com Signed-off-by: Rob Herring (Arm) --- .../devicetree/bindings/dts-coding-style.rst | 5 +- scripts/dtc/dt-check-style | 137 +++++++++------------ .../dt-style-selftest/bad/dts-property-order.dts | 3 + .../dt-style-selftest/bad/dts-property-order.dtso | 3 + .../dtc/dt-style-selftest/bad/yaml-prop-order.yaml | 5 + .../expected/dts-property-order.dts.txt | 7 +- .../expected/dts-property-order.dtso.txt | 7 +- .../expected/yaml-prop-order.yaml.txt | 1 + .../expected/yaml-prop-pairing.yaml.txt | 4 +- .../dt-style-selftest/good/dts-property-order.dts | 3 + .../dt-style-selftest/good/dts-property-order.dtso | 3 + 11 files changed, 89 insertions(+), 89 deletions(-) (limited to 'scripts') diff --git a/Documentation/devicetree/bindings/dts-coding-style.rst b/Documentation/devicetree/bindings/dts-coding-style.rst index 63648db377e1..441436b7fa80 100644 --- a/Documentation/devicetree/bindings/dts-coding-style.rst +++ b/Documentation/devicetree/bindings/dts-coding-style.rst @@ -135,8 +135,9 @@ The above-described ordering follows this approach: 3. Status is the last information to annotate that device node is or is not finished (board resources are needed). -The individual properties inside each group shall use natural sort order by -the property name. +The individual properties inside each group shall use usually natural sort +order by the property name, with exceptions of logical grouping of properties, +e.g. supplies. Example:: diff --git a/scripts/dtc/dt-check-style b/scripts/dtc/dt-check-style index cbbb8d384aca..b8c40873905c 100755 --- a/scripts/dtc/dt-check-style +++ b/scripts/dtc/dt-check-style @@ -714,65 +714,40 @@ def check_property_name(ctx): yield (dl.lineno, f'property name "{dl.prop_name}" is using discouraged style') -def _property_bucket(name): - """Return the canonical bucket index for a property: - 0 device_type +def _property_bucket(name, is_root=False): + """Return the canonical bucket (group) index for a property: + 0 device_type ('model' in the root node) 1 compatible - 2 reg / reg-names + 2 reg, reg-names 3 ranges 4 standard properties (no vendor comma in #-stripped name) 5 vendor-specific properties 6 status - Plus a sub-key inside the bucket for fixed slots (device_type, compatible, - reg, reg-names, ranges, status). 'standard' and 'vendor' return None for - the sub-key, signalling that the within-bucket key is computed by - the pairing rules.""" + Properties sharing a bucket compare equal: their relative order + within the group is not checked, only the pairing rules below + apply.""" stripped = name.lstrip('#') - if name == 'device_type': - return (0, 0) - if name == 'compatible': - return (1, 0) - if name == 'reg': - return (2, 0) - if name == 'reg-names': - return (2, 1) - if name == 'ranges': - return (3, 0) - if name == 'status': - return (6, 0) - return (5 if ',' in stripped else 4, None) - - -def _property_bucket_root(name): - """Return the canonical bucket index for a property: - 0 model (for root nodes only) - 1 compatible - Plus a sub-key inside the bucket for fixed slots (device_type, compatible, - reg, reg-names, ranges, status). 'standard' and 'vendor' return None for - the sub-key, signalling that the within-bucket key is computed by - the pairing rules.""" - stripped = name.lstrip('#') - if name == 'model': - return (0, 0) + if is_root: + if name == 'model': + return 0 + elif name == 'device_type': + return 0 if name == 'compatible': - return (1, 0) - if name == 'reg': - return (2, 0) - if name == 'reg-names': - return (2, 1) + return 1 + if name in ('reg', 'reg-names'): + return 2 if name == 'ranges': - return (3, 0) + return 3 if name == 'status': - return (6, 0) - return (5 if ',' in stripped else 4, None) + return 6 + return 5 if ',' in stripped else 4 # Declarative pairing rules: each is a callable # (name, all_names) -> anchor_name_or_None -# If a rule returns an anchor, the property sorts immediately after the +# If a rule returns an anchor, the property must be placed after the # anchor. Rules are tried in order; the first match wins. If none -# matches, the within-bucket key falls back to natural sort by the -# #-stripped name. +# matches, the property can be placed anywhere within its bucket. def _pair_pinctrl_names(name, all_names): """pinctrl-names follows the highest pinctrl-N in the same node.""" @@ -787,8 +762,7 @@ def _pair_pinctrl_names(name, all_names): def _pair_x_names(name, all_names): """Generic -names follows its owning property. The owner is usually plural (clocks/clock-names, dmas/dma-names, - resets/reset-names) but occasionally singular (reg/reg-names is - handled by the fixed slot above; this rule catches anything else).""" + resets/reset-names) but occasionally singular (reg/reg-names).""" if not name.endswith('-names'): return None base = name[:-len('-names')] @@ -803,33 +777,27 @@ def _pair_x_names(name, all_names): PAIRING_RULES = (_pair_pinctrl_names, _pair_x_names) -def _property_sort_key(dl, name, all_names): - """Sort key for a property among its node-body siblings. - - Format: (bucket, within_key, tiebreak). 'within_key' for - standard/vendor buckets follows pairing rules: a property paired - with anchor X sorts as if it were X with a higher tiebreak.""" - if dl.is_root: - bucket, fixed_sub = _property_bucket_root(name) - else: - bucket, fixed_sub = _property_bucket(name) - if fixed_sub is not None: - return (bucket, (), fixed_sub) - +def _property_anchor(name, all_names): + """Return the property this one must be placed after, or None.""" for rule in PAIRING_RULES: anchor = rule(name, all_names) if anchor is not None: - return (bucket, _natural_sort_key(anchor.lstrip('#')), 1) - - return (bucket, _natural_sort_key(name.lstrip('#')), 0) + return anchor + return None def check_property_order(ctx): - """Properties within a node body must appear in canonical order: - compatible, reg(/reg-names), ranges, then the standard group, then - the vendor-specific group, then status. Inside the standard and - vendor groups, pairing rules apply (e.g. -names follows ); - everything else falls back to natural sort by the #-stripped name.""" + """Properties within a node body must be grouped in canonical + order: device_type ('model' for the root node), compatible, + reg(/reg-names), ranges, then the standard group, then the + vendor-specific group, then status. + + The order of properties within one group is free, e.g. it does not + matter whether '#address-cells' comes before or after 'clocks'. + Paired properties still keep their relative order: -names + follows (clocks/clock-names, reg/reg-names, ...), pinctrl-names + follows the pinctrl-N states and #size-cells follows + #address-cells.""" lines = ctx.lines for i, dl in enumerate(lines): if dl.linetype != LineType.NODE_OPEN: @@ -847,16 +815,26 @@ def check_property_order(ctx): if len(props) < 2: continue all_names = [p.prop_name for p in props] - keyed = [(p, _property_sort_key(dl, p.prop_name, all_names)) - for p in props] - for k in range(1, len(keyed)): - if keyed[k][1] < keyed[k - 1][1]: - p = keyed[k][0] - prev = keyed[k - 1][0] - yield (p.lineno, - 'property %r out of canonical order ' - '(should sort before %r)' % - (p.prop_name, prev.prop_name)) + buckets = [_property_bucket(p.prop_name, dl.is_root) for p in props] + findings = [] + # Group (bucket) order + for k in range(1, len(props)): + if buckets[k] < buckets[k - 1]: + findings.append((props[k].lineno, + 'property %r out of canonical order ' + '(should sort before %r)' % + (props[k].prop_name, + props[k - 1].prop_name))) + # Pairing within a group: the anchor must come first + seen = set() + for p in props: + anchor = _property_anchor(p.prop_name, all_names) + if anchor is not None and anchor not in seen: + findings.append((p.lineno, + 'property %r must be placed after %r' % + (p.prop_name, anchor))) + seen.add(p.prop_name) + yield from sorted(findings) def _check_redundant_whitespace(dl): @@ -1152,7 +1130,8 @@ RULES = [ 'property names use only recommended characters (see DTS Coding Style)', check_property_name), Rule('property-order', 'strict', - 'canonical bucket + pairing + natural-sort order of properties', + 'canonical group + pairing order of properties (order within ' + 'a group is not checked)', check_property_order), # See also check_redundant_whitespace() and check_value_whitespace() Rule('redundant-whitespace-strict', 'strict', diff --git a/scripts/dtc/dt-style-selftest/bad/dts-property-order.dts b/scripts/dtc/dt-style-selftest/bad/dts-property-order.dts index ebe561e38766..eb36daa4fe72 100644 --- a/scripts/dtc/dt-style-selftest/bad/dts-property-order.dts +++ b/scripts/dtc/dt-style-selftest/bad/dts-property-order.dts @@ -43,6 +43,9 @@ <4 5 6>, <7 8 9>; compatible = "example,intc"; + qcom,calibration-variant = "foo"; + clocks = <6>; + qcom,opp-fuse-level = <1>; }; }; }; diff --git a/scripts/dtc/dt-style-selftest/bad/dts-property-order.dtso b/scripts/dtc/dt-style-selftest/bad/dts-property-order.dtso index 64604fa6b8c3..b2e564f2af2b 100644 --- a/scripts/dtc/dt-style-selftest/bad/dts-property-order.dtso +++ b/scripts/dtc/dt-style-selftest/bad/dts-property-order.dtso @@ -44,6 +44,9 @@ <4 5 6>, <7 8 9>; compatible = "example,intc"; + qcom,calibration-variant = "foo"; + clocks = <6>; + qcom,opp-fuse-level = <1>; }; }; }; diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-prop-order.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-prop-order.yaml index bf1480e97209..4d8a50d0e35a 100644 --- a/scripts/dtc/dt-style-selftest/bad/yaml-prop-order.yaml +++ b/scripts/dtc/dt-style-selftest/bad/yaml-prop-order.yaml @@ -26,4 +26,9 @@ examples: device@1000 { reg = <0x1000 0x100>; compatible = "example,test-prop-order"; + + interrupts = <1>; + qcom,calibration-variant = "foo"; + clocks = <6>; + qcom,opp-fuse-level = <1>; }; diff --git a/scripts/dtc/dt-style-selftest/expected/dts-property-order.dts.txt b/scripts/dtc/dt-style-selftest/expected/dts-property-order.dts.txt index 0ab832ccf07a..155b072f0ac2 100644 --- a/scripts/dtc/dt-style-selftest/expected/dts-property-order.dts.txt +++ b/scripts/dtc/dt-style-selftest/expected/dts-property-order.dts.txt @@ -6,6 +6,7 @@ bad/dts-property-order.dts:21: [property-order] property 'device_type' out of ca bad/dts-property-order.dts:30: [property-order] property 'dma-coherent' out of canonical order (should sort before 'status') bad/dts-property-order.dts:35: [property-order] property 'compatible' out of canonical order (should sort before 'ranges') bad/dts-property-order.dts:45: [property-order] property 'compatible' out of canonical order (should sort before 'interrupts') -bad/dts-property-order.dts:50: [redundant-whitespace] extra whitespace before { -bad/dts-property-order.dts:52: [property-order] property 'model' out of canonical order (should sort before 'compatible') -bad/dts-property-order.dts:57: [property-order] property 'model' out of canonical order (should sort before 'compatible') +bad/dts-property-order.dts:47: [property-order] property 'clocks' out of canonical order (should sort before 'qcom,calibration-variant') +bad/dts-property-order.dts:53: [redundant-whitespace] extra whitespace before { +bad/dts-property-order.dts:55: [property-order] property 'model' out of canonical order (should sort before 'compatible') +bad/dts-property-order.dts:60: [property-order] property 'model' out of canonical order (should sort before 'compatible') diff --git a/scripts/dtc/dt-style-selftest/expected/dts-property-order.dtso.txt b/scripts/dtc/dt-style-selftest/expected/dts-property-order.dtso.txt index 9f2a00916329..48c020d21b64 100644 --- a/scripts/dtc/dt-style-selftest/expected/dts-property-order.dtso.txt +++ b/scripts/dtc/dt-style-selftest/expected/dts-property-order.dtso.txt @@ -6,6 +6,7 @@ bad/dts-property-order.dtso:22: [property-order] property 'device_type' out of c bad/dts-property-order.dtso:31: [property-order] property 'dma-coherent' out of canonical order (should sort before 'status') bad/dts-property-order.dtso:36: [property-order] property 'compatible' out of canonical order (should sort before 'ranges') bad/dts-property-order.dtso:46: [property-order] property 'compatible' out of canonical order (should sort before 'interrupts') -bad/dts-property-order.dtso:51: [redundant-whitespace] extra whitespace before { -bad/dts-property-order.dtso:53: [property-order] property 'model' out of canonical order (should sort before 'compatible') -bad/dts-property-order.dtso:58: [property-order] property 'model' out of canonical order (should sort before 'compatible') +bad/dts-property-order.dtso:48: [property-order] property 'clocks' out of canonical order (should sort before 'qcom,calibration-variant') +bad/dts-property-order.dtso:54: [redundant-whitespace] extra whitespace before { +bad/dts-property-order.dtso:56: [property-order] property 'model' out of canonical order (should sort before 'compatible') +bad/dts-property-order.dtso:61: [property-order] property 'model' out of canonical order (should sort before 'compatible') diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-prop-order.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-prop-order.yaml.txt index 578df7209170..bb0dd5db5135 100644 --- a/scripts/dtc/dt-style-selftest/expected/yaml-prop-order.yaml.txt +++ b/scripts/dtc/dt-style-selftest/expected/yaml-prop-order.yaml.txt @@ -1,2 +1,3 @@ # mode=strict bad/yaml-prop-order.yaml:28: example 0 [property-order] property 'compatible' out of canonical order (should sort before 'reg') +bad/yaml-prop-order.yaml:32: example 0 [property-order] property 'clocks' out of canonical order (should sort before 'qcom,calibration-variant') diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-prop-pairing.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-prop-pairing.yaml.txt index e6e21349a939..ee666559424a 100644 --- a/scripts/dtc/dt-style-selftest/expected/yaml-prop-pairing.yaml.txt +++ b/scripts/dtc/dt-style-selftest/expected/yaml-prop-pairing.yaml.txt @@ -1,3 +1,3 @@ # mode=strict -bad/yaml-prop-pairing.yaml:30: example 0 [property-order] property 'clocks' out of canonical order (should sort before 'clock-names') -bad/yaml-prop-pairing.yaml:32: example 0 [property-order] property 'pinctrl-0' out of canonical order (should sort before 'pinctrl-names') +bad/yaml-prop-pairing.yaml:29: example 0 [property-order] property 'clock-names' must be placed after 'clocks' +bad/yaml-prop-pairing.yaml:31: example 0 [property-order] property 'pinctrl-names' must be placed after 'pinctrl-0' diff --git a/scripts/dtc/dt-style-selftest/good/dts-property-order.dts b/scripts/dtc/dt-style-selftest/good/dts-property-order.dts index 3d847cc9fa3e..288fcfb9888f 100644 --- a/scripts/dtc/dt-style-selftest/good/dts-property-order.dts +++ b/scripts/dtc/dt-style-selftest/good/dts-property-order.dts @@ -40,7 +40,10 @@ interrupt-controller@10000 { compatible = "example,intc"; reg = <0x10000 0x1000>; + clocks = <6>; interrupts = <1 2 3>; + qcom,calibration-variant = "foo"; + qcom,opp-fuse-level = <1>; }; }; }; diff --git a/scripts/dtc/dt-style-selftest/good/dts-property-order.dtso b/scripts/dtc/dt-style-selftest/good/dts-property-order.dtso index 5ae78541f68b..60c68b3f908a 100644 --- a/scripts/dtc/dt-style-selftest/good/dts-property-order.dtso +++ b/scripts/dtc/dt-style-selftest/good/dts-property-order.dtso @@ -41,7 +41,10 @@ interrupt-controller@10000 { compatible = "example,intc"; reg = <0x10000 0x1000>; + clocks = <6>; interrupts = <1 2 3>; + qcom,calibration-variant = "foo"; + qcom,opp-fuse-level = <1>; }; }; }; -- cgit v1.2.3 From d5eefb1d97ad476c734997fa6741651dde610ceb Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 11 Sep 2026 13:42:04 +0200 Subject: dtc: dt-check-style: Re-work classifying property continuations Script has an enumeration of DTS Line types (LineType) and one type is a continuation of multi-line property. This has limitations, because it basically hides true type of a continued line which makes certain checks difficult. For example detecting consecutive blank lines (LineType.BLANK) will fail if the type is continuation. clock-names = "foo", /* Comment */ "bar"; Above code not only fails check_blank_lines() rule, but also messes up how DtsLine array is constructed - the two middle continued lines are not put under the DtsLine.continuations array. The concepts of type of line (blank, preprocessor, property etc) and actual continuation are orthogonal to most of the checks - the checks need to know what sort of continued line it is. Fixing this solves false positives of continued properties with blank lines and comments: arch/arm64/boot/dts/exynos/exynos5433-tm2-common.dtsi:135: [blank-lines] consecutive blank lines arch/arm64/boot/dts/exynos/exynos5433-tm2-common.dtsi:135: [blank-lines] blank line at end of node body Signed-off-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20260911-dts-style-checker-blank-lines-v1-1-85e779600d98@oss.qualcomm.com Signed-off-by: Rob Herring (Arm) --- scripts/dtc/dt-check-style | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) (limited to 'scripts') diff --git a/scripts/dtc/dt-check-style b/scripts/dtc/dt-check-style index b8c40873905c..46aa4dda6d33 100755 --- a/scripts/dtc/dt-check-style +++ b/scripts/dtc/dt-check-style @@ -44,7 +44,6 @@ class LineType(Enum): NODE_OPEN = auto() # something { (with optional label/name/addr) NODE_CLOSE = auto() # }; PROPERTY = auto() # name = value; or name; - CONTINUATION = auto() # continuation of a multi-line property re_cpp_directive = re.compile( @@ -80,11 +79,12 @@ def is_preprocessor(stripped): class DtsLine: __slots__ = ('lineno', 'raw', 'code', 'linetype', 'indent_str', 'stripped', 'is_root', - 'prop_name', 'continuations', + 'prop_name', 'continuation', 'continuations', 'node_name', 'node_addr', 'label', 'ref_name', 'parent', 'depth', 'closures') - def __init__(self, lineno, raw, linetype, depth, indent_str, stripped, is_root = False): + def __init__(self, lineno, raw, linetype, depth, indent_str, stripped, + continuation = False, is_root = False): self.lineno = lineno # 1-based within the block self.raw = raw # Entire raw line self.linetype = linetype @@ -95,6 +95,7 @@ class DtsLine: self.code = _strip_strings_and_comments(stripped).rstrip() self.is_root = is_root self.prop_name = None + self.continuation = continuation # Continuation of a multi-line property self.continuations = [] self.node_name = None self.node_addr = None @@ -175,7 +176,7 @@ def classify_lines(text): continue if not stripped: - dl = DtsLine(i, raw, LineType.BLANK, depth, '', '') + dl = DtsLine(i, raw, LineType.BLANK, depth, '', '', continuation=not prev_complete) out.append(dl) continue @@ -184,7 +185,7 @@ def classify_lines(text): else LineType.COMMENT_BODY) if ltype == LineType.COMMENT_END: in_block_comment = False - dl = DtsLine(i, raw, ltype, depth, indent_str, stripped) + dl = DtsLine(i, raw, ltype, depth, indent_str, stripped, continuation=not prev_complete) out.append(dl) continue @@ -202,20 +203,12 @@ def classify_lines(text): if opens_block: in_block_comment = True - if not prev_complete: - dl = DtsLine(i, raw, LineType.CONTINUATION, depth, indent_str, code) - out.append(dl) - prev_complete = (code.endswith(';') or - code.endswith('{') or - code.endswith('};')) - continue - # Pure-comment line: nothing left after stripping. Classify as # COMMENT_START (carries to next line) or COMMENT, and skip the # structural classification entirely. if not code: ltype = LineType.COMMENT_START if opens_block else LineType.COMMENT - dl = DtsLine(i, raw, ltype, depth, indent_str, stripped) + dl = DtsLine(i, raw, ltype, depth, indent_str, stripped, continuation=not prev_complete) out.append(dl) continue @@ -245,7 +238,8 @@ def classify_lines(text): continue # Property (or first line of a multi-line property). - dl = DtsLine(i, raw, LineType.PROPERTY, depth, indent_str, code) + dl = DtsLine(i, raw, LineType.PROPERTY, depth, indent_str, code, + continuation=not prev_complete) parse_property_name(dl) out.append(dl) prev_complete = code.endswith(';') @@ -254,7 +248,7 @@ def classify_lines(text): last_prop = None grouped = [] for dl in out: - if dl.linetype == LineType.CONTINUATION and last_prop is not None: + if dl.continuation and last_prop is not None: last_prop.continuations.append(dl) continue if dl.linetype == LineType.PROPERTY: @@ -535,6 +529,8 @@ def check_continuation_alignment(ctx): dl_value_complete = rest.endswith('",') or rest.endswith('>,') target_col = _display_col(_strip_strings_and_comments(dl.raw[:eq + 1 + m.start(1)])) for cont in dl.continuations: + if cont.linetype == LineType.BLANK: + continue target_offset = 0 err_msg_explanation = 'to < or "' if not dl_value_complete: @@ -582,10 +578,10 @@ def check_indent_consistent(ctx): return for dl in ctx.lines: + if dl.continuation: + continue # continuations align to <, not to indent unit if dl.linetype in (LineType.BLANK, LineType.PREPROCESSOR): continue - if dl.linetype == LineType.CONTINUATION: - continue # continuations align to <, not to indent unit if dl.linetype in (LineType.COMMENT_BODY, LineType.COMMENT_END): continue if not dl.indent_str: @@ -890,6 +886,8 @@ def check_required_blank_lines(ctx): if d.linetype == LineType.NODE_CLOSE and \ d.depth == body_depth - 1 and depth_inside == 0: break + if d.continuation: + continue # Track depth inside nested children so we only look at # immediate-body items. if d.linetype == LineType.NODE_OPEN and \ @@ -909,8 +907,6 @@ def check_required_blank_lines(ctx): LineType.COMMENT_BODY, LineType.COMMENT_END, LineType.PREPROCESSOR): continue - if d.linetype == LineType.CONTINUATION: - continue needs_blank = False if d.linetype == LineType.NODE_OPEN: -- cgit v1.2.3 From 117d30d3107afcdbb5e681aadbd86d925675c0e2 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 11 Sep 2026 13:42:05 +0200 Subject: dtc: dt-check-style: Handle multiple blank lines in continued properties Properly ignore comments and report duplicated blank lines in multi-line properties. Signed-off-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20260911-dts-style-checker-blank-lines-v1-2-85e779600d98@oss.qualcomm.com Signed-off-by: Rob Herring (Arm) --- scripts/dtc/dt-check-style | 6 +++ .../dtc/dt-style-selftest/bad/dts-blank-lines.dts | 37 +++++++++++++++ .../dt-style-selftest/bad/yaml-blank-lines.yaml | 54 ++++++++++++++++++++++ .../expected/dts-blank-lines.dts.txt | 6 +++ .../expected/yaml-blank-lines.yaml.txt | 6 +++ 5 files changed, 109 insertions(+) create mode 100644 scripts/dtc/dt-style-selftest/bad/dts-blank-lines.dts create mode 100644 scripts/dtc/dt-style-selftest/bad/yaml-blank-lines.yaml create mode 100644 scripts/dtc/dt-style-selftest/expected/dts-blank-lines.dts.txt create mode 100644 scripts/dtc/dt-style-selftest/expected/yaml-blank-lines.yaml.txt (limited to 'scripts') diff --git a/scripts/dtc/dt-check-style b/scripts/dtc/dt-check-style index 46aa4dda6d33..6bbd12b308a1 100755 --- a/scripts/dtc/dt-check-style +++ b/scripts/dtc/dt-check-style @@ -440,6 +440,12 @@ def check_blank_lines(ctx): if lines[i].linetype == LineType.BLANK and \ lines[i - 1].linetype == LineType.BLANK: yield (lines[i].lineno, 'consecutive blank lines') + prev_is_blank = lines[i].linetype == LineType.BLANK + for cont in lines[i].continuations: + if cont.linetype == LineType.BLANK and prev_is_blank: + yield (cont.lineno, 'consecutive blank lines') + prev_is_blank = cont.linetype == LineType.BLANK + # Blank right after { or right before } for i, dl in enumerate(lines): if dl.linetype != LineType.BLANK: diff --git a/scripts/dtc/dt-style-selftest/bad/dts-blank-lines.dts b/scripts/dtc/dt-style-selftest/bad/dts-blank-lines.dts new file mode 100644 index 000000000000..f2e99fb7bb29 --- /dev/null +++ b/scripts/dtc/dt-style-selftest/bad/dts-blank-lines.dts @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +/dts-v1/; + +/ { + compatible = "example,test-board"; + #address-cells = <1>; + #size-cells = <1>; + + interrupt-controller@10000 { + compatible = "example,intc"; + + reg = <0x10000 0x1000>; + + clocks = <1 2 3>, + + + /* Comment is not a blank line */ + <4 5 6>, + + /* Comment is not a blank line */ + <7 8 9>; + + + interrupts = <1>; + + /* Comment is not a blank line */ + qcom,calibration-variant = "foo"; + }; + + + interrupt-controller@20000 { + + compatible = "example,intc"; + reg = <0x20000 0x1000>; + + }; +}; diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-blank-lines.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-blank-lines.yaml new file mode 100644 index 000000000000..a58cd534a003 --- /dev/null +++ b/scripts/dtc/dt-style-selftest/bad/yaml-blank-lines.yaml @@ -0,0 +1,54 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/test-bad-blank-lines.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Test fixture with too many blank lines + +maintainers: + - Test User + +properties: + compatible: + const: example,test-blank-lines + reg: + maxItems: 1 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + foo@1000 { + compatible = "example,test-blank-lines"; + + reg = <0x1000 0x100>; + + clocks = <1 2 3>, + + + /* Comment is not a blank line */ + <4 5 6>, + + /* Comment is not a blank line */ + <7 8 9>; + + + interrupts = <1>; + + /* Comment is not a blank line */ + qcom,calibration-variant = "foo"; + }; + + + foo@2000 { + + compatible = "example,test-blank-lines"; + + reg = <0x2000 0x100>; + + }; diff --git a/scripts/dtc/dt-style-selftest/expected/dts-blank-lines.dts.txt b/scripts/dtc/dt-style-selftest/expected/dts-blank-lines.dts.txt new file mode 100644 index 000000000000..97617bc42a17 --- /dev/null +++ b/scripts/dtc/dt-style-selftest/expected/dts-blank-lines.dts.txt @@ -0,0 +1,6 @@ +# mode=strict +bad/dts-blank-lines.dts:16: [blank-lines] consecutive blank lines +bad/dts-blank-lines.dts:23: [blank-lines] consecutive blank lines +bad/dts-blank-lines.dts:30: [blank-lines] consecutive blank lines +bad/dts-blank-lines.dts:32: [blank-lines] blank line at start of node body +bad/dts-blank-lines.dts:35: [blank-lines] blank line at end of node body diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-blank-lines.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-blank-lines.yaml.txt new file mode 100644 index 000000000000..8a8db8d35b1e --- /dev/null +++ b/scripts/dtc/dt-style-selftest/expected/yaml-blank-lines.yaml.txt @@ -0,0 +1,6 @@ +# mode=strict +bad/yaml-blank-lines.yaml:33: example 0 [blank-lines] consecutive blank lines +bad/yaml-blank-lines.yaml:40: example 0 [blank-lines] consecutive blank lines +bad/yaml-blank-lines.yaml:47: example 0 [blank-lines] consecutive blank lines +bad/yaml-blank-lines.yaml:49: example 0 [blank-lines] blank line at start of node body +bad/yaml-blank-lines.yaml:53: example 0 [blank-lines] blank line at end of node body -- cgit v1.2.3