From 40ae094ac9d4a06d306872830e4ea8a99d782ae9 Mon Sep 17 00:00:00 2001 From: Joshua Warren <816217+joshuaswarren@users.noreply.github.com> Date: Sat, 24 Oct 2026 18:19:25 -0500 Subject: [PATCH 1/8] arm64: dts: apple: fix t6032-j575d against the 27.0.1 ADT; add ADT-vs-DT CI check Fix the T6032 (M3 Ultra, Mac Studio 2025, Mac15,14, j575dap) description against the j575dap ADT of the pinned macOS 27.0.1 (26A434) firmware: - Add USB-C controller 3. drd3 is not a die-stride mirror of a die-0 port: the ADT puts it at 0x1302280000, inside die 0's identity window, powered by the die-0 ATC3_USB state (dwc3 irq 1446, darts 1450). Delete the die-1 mirror of die-0 port 2 (dwc3_2_die1 at 0x2f02280000 with its darts and atcphy): no such port exists. Ports 4 and 5 stay as the dieX mirrors of die-0 ports 0 and 1 (ADT usb-drd4/5, dart-usb4/5). - Delete the phantom die-1 USB4 controller (usb4_2_acio_die1 + usb4_2_mbox_die1 at 0x2f01ac0000); the die-1 usb4_0/1 instances match ADT acio4/acio5 and stay. - Delete the laptop-only devices with no j575dap ADT counterpart: the MTP keyboard stack, the AOP audio ADMAC (with aop_audio, its only consumer), i2c3 and spi1; the board file drops spi1-nvram.dtsi with it. - Add the GPU (gpu,t6032 sgx + gfx-asc + ASC mailbox + OPP/UAT scaffolding), the eight external display pipes (dcpext0-7 with their mailboxes and DARTs) and both ANE engines (ane0/ane1 + three DARTs each) from the ADT. All stay disabled: drm/asahi g15 has no T6032 row, the DCP driver has no 27.x firmware family and m1n1 gates the display handoff on the OS firmware, and no M3 ANE driver exists. The power states these nodes reference already exist in the t6031 pmgr description. - Keep the die-1 cpufreq and pmgr nodes: hardware mirrors at the die stride (m1n1 PMGR_DIE_OFFSET) of register files the ADT describes inside the pmgr node's window list. Add an ADT-vs-DT CI checker (.github/scripts/adt-dt-check-t6032.py, workflow t6032-adt-dt-check) so these fixes cannot regress: it builds the DTB, fetches DeviceTree.j575dap.im4p from the pinned 27.0.1 IPSW by two HTTP range requests, verifies pinned SHA256 hashes of both the im4p and the LZFSE-decompressed ADT, and requires every ADT node the board needs to be covered by the DT, the phantom and laptop-only windows to be absent, every DT SoC node to map into the ADT, the referenced power states to sit at the ADT bank+offset in both dies, and the GPU/DCP/ANE nodes to stay disabled. The fixed tree passes 104 checks; the pre-fix tree fails 43. DTBs verified to still build: t6032-j575d, t6030-j516s, t6031-j514c, t6031-j516c, t6034-j514m. Local branch w7C/t6032-dt-27, based on omacom/linux-aurora integration/aurora 7b969982306e. Not pushed. Signed-off-by: Joshua Warren <816217+joshuaswarren@users.noreply.github.com> --- .github/scripts/adt-dt-check-t6032.py | 522 +++++++++++++ .github/workflows/t6032-adt-dt-check.yml | 50 ++ arch/arm64/boot/dts/apple/t6032-j575d.dts | 5 +- arch/arm64/boot/dts/apple/t6032.dtsi | 862 ++++++++++++++++++++++ 4 files changed, 1438 insertions(+), 1 deletion(-) create mode 100755 .github/scripts/adt-dt-check-t6032.py create mode 100644 .github/workflows/t6032-adt-dt-check.yml diff --git a/.github/scripts/adt-dt-check-t6032.py b/.github/scripts/adt-dt-check-t6032.py new file mode 100755 index 00000000000000..fd59b8e6679916 --- /dev/null +++ b/.github/scripts/adt-dt-check-t6032.py @@ -0,0 +1,522 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0-only OR MIT +"""ADT-vs-DT checker for the Apple T6032 (M3 Ultra) j575d device tree. + +Compares the built t6032-j575d DTB(s) against the j575dap ADT of the pinned +macOS 27.0.1 (26A434) firmware so the fixes that were made against that ADT +cannot silently regress: + + - every ADT node the board needs (six USB-C controllers, their DARTs and + phys, the GPU and its ASC mailbox, the eight external display pipes with + their DARTs and mailboxes, both ANE engines with their DARTs, and the + console devices AOP/ANS/SMC/SART/UART) must be covered by a DT node whose + register windows overlap it, after die-1 bus translation; + - nodes inherited from the laptop descriptions that the ADT does not have + (the MTP stack, the AOP audio DMA, i2c3, the SPI-NOR, and the phantom + 0x2f_ die-1 mirrors) must not exist; + - every DT SoC node with registers must overlap an ADT node, except the + die-1 cpufreq and pmgr mirrors (hardware mirrors at the die stride that + the ADT expresses inside the pmgr register-window list, not as nodes); + - the power states the new nodes reference must exist at the ADT address + (bank + offset) in both dies; + - the GPU, ANE and display nodes must stay disabled. + +Usage: + adt-dt-check-t6032.py ADT DTB [DTB...] + adt-dt-check-t6032.py --fetch-ipsw DTB [DTB...] + Fetch the pinned DeviceTree.j575dap.im4p by HTTP range requests from + the pinned 27.0.1 IPSW (no full download), verify both pinned SHA256 + hashes, LZFSE-decompress it to a temp file and check against it. + +Needs dtc on PATH for DTB decompilation; --fetch-ipsw additionally needs +pyliblzfse. Prints one line per check; the exit status is 1 if any check +fails. Nothing is written (except the temp ADT with --fetch-ipsw). +""" + +import hashlib +import re +import struct +import subprocess +import sys +import tempfile +import urllib.request +import zlib + +# macOS 27.0.1 (26A434) for Mac15,14; metadata from api.ipsw.me 2026-09-28. +IPSW_URL = ("https://updates.cdn-apple.com/2026FallFCS/59241290-5d51-4ca8-9df4-31624b9a4eac/" + "UniversalMac_27.0.1_26A434_Restore.ipsw") +IPSW_SHA256 = "2f016638293c3e641b8b25391a76fbc16563b3711915a5551cf8aa0f5598a5c1" +IM4P_SHA256 = "6c3ca4ac7272ecf9c05f6b2b413ef923ff2d3ff252469493fc700260b6938c60" +ADT_SHA256 = "4a818ecc7f3d71195c1def12c6eed0c90b287f82cad2a6a4ffd6f0849fe13c12" +IM4P_MEMBER = "Firmware/all_flash/DeviceTree.j575dap.im4p" + +# m1n1 src/pmgr.h: PMGR_DIE_OFFSET. +PMGR_DIE_OFFSET = 0x2000000000 + +failures = [] + + +def check(ok, line): + print(("ok " if ok else "FAIL ") + line) + if not ok: + failures.append(line) + + +# ---------------------------------------------------------------- ADT side + +def adt_parse(b, off=0): + nprops, nchild = struct.unpack_from("", val or ""): + for x in grp.split(): + out.append(int(x, 16) if x.lower().startswith("0x") else int(x)) + return out + + +def dt_strings(val): + return re.findall(r'"([^"]*)"', val or "") + + +def dt_soc_nodes(root): + """Yield (path, node, windows) for every DIRECT child of either SoC bus + that has a reg property, windows translated to physical addresses. + Deeper buses (pmgr states, DCP children, CIO children) use other + address-cell widths and are deliberately not covered here; the ADT-vs-DT + register comparison is on SoC-level devices.""" + for soc in root.kids: + if not soc.name.startswith("soc@"): + continue + rc = dt_cells(soc.props.get("ranges", "")) + rng = [((rc[i] << 32) | rc[i + 1], + (rc[i + 2] << 32) | rc[i + 3], + (rc[i + 4] << 32) | rc[i + 5]) for i in range(0, len(rc) - 5, 6)] + + def tr(a): + for child, parent, size in rng: + if child <= a < child + size: + return parent + (a - child) + return a + + for k in soc.kids: + if "reg" not in k.props: + continue + c = dt_cells(k.props["reg"]) + wins = [] + if len(c) % 4 == 0 and c: + for i in range(0, len(c), 4): + wins.append((tr((c[i] << 32) | c[i + 1]), + (c[i + 2] << 32) | c[i + 3])) + yield "/" + soc.name + "/" + k.name, k, wins + + +def overlap(w1, w2): + return w1[0] < w2[0] + w2[1] and w2[0] < w1[0] + w1[1] + + +# ------------------------------------------------------------------- fetch + +def http_range(url, start, end): + req = urllib.request.Request(url, headers={"Range": f"bytes={start}-{end}"}) + with urllib.request.urlopen(req, timeout=120) as r: + return r.read() + + +def fetch_adt(): + """Pull DeviceTree.j575dap.im4p out of the pinned IPSW with two range + requests (central directory, then the member) and LZFSE-decompress it. + Both pinned SHA256 hashes must match.""" + import lzfse # pyliblzfse + req = urllib.request.Request(IPSW_URL, headers={"Range": "bytes=0-0"}) + with urllib.request.urlopen(req, timeout=120) as r: + cr = r.headers.get("Content-Range", "") + total = int(cr.rsplit("/", 1)[-1]) + cd = http_range(IPSW_URL, max(0, total - (1 << 20)), total - 1) + eocd = cd.rfind(b"PK\x05\x06") + if eocd < 0: + sys.exit("no zip End Of Central Directory in the IPSW tail") + count, cdoff = struct.unpack_from("; + interrupt-parent = <&aic>; + interrupts = ; + power-domains = <&ps_atc3_usb>; + #iommu-cells = <1>; + }; + + dwc3_3_dart_1: iommu@1302f80000 { + compatible = "apple,t6031-dart", "apple,t8110-dart"; + reg = <0x13 0x02f80000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = ; + power-domains = <&ps_atc3_usb>; + #iommu-cells = <1>; + }; + + atcphy3: phy@1303000000 { + compatible = "apple,t6031-atcphy", "apple,t8122-atcphy"; + reg = <0x13 0x03000000 0x0 0x4c000>, + <0x13 0x03050000 0x0 0x8000>, + <0x13 0x00000000 0x0 0x8000>, + <0x13 0x02a90000 0x0 0x4000>, + <0x13 0x02a84000 0x0 0x4000>; + reg-names = "core", "lpdptx", "axi2af", "usb2phy", + "pipehandler"; + + #phy-cells = <1>; + #reset-cells = <0>; + + orientation-switch; + mode-switch; + power-domains = <&ps_atc3_usb>; + }; + + dwc3_3: usb@1302280000 { + compatible = "apple,t6031-dwc3", "apple,t8103-dwc3"; + reg = <0x13 0x02280000 0x0 0xcd00>, <0x13 0x0228cd00 0x0 0x3200>; + reg-names = "dwc3-core", "dwc3-apple"; + interrupt-parent = <&aic>; + interrupts = ; + dr_mode = "otg"; + usb-role-switch; + role-switch-default-mode = "host"; + iommus = <&dwc3_3_dart_0 0>, + <&dwc3_3_dart_1 1>; + power-domains = <&ps_atc3_usb>; + resets = <&atcphy3>; + phys = <&atcphy3 PHY_TYPE_USB2>, <&atcphy3 PHY_TYPE_USB3>; + phy-names = "usb2-phy", "usb3-phy"; + }; +}; + +/* + * GPU (gpu,t6032 in the ADT: G15D, two dies, one sgx and one gfx-asc for + * both) and its ASC mailbox. Register windows, gates (pmgr_gfx GPX/AFR/GFX) + * and the seven ADT interrupts match the T6031 description. The G15 driver + * has no T6032 row and m1n1 has no G15D handoff for the 27 firmware, so the + * GPU and its mailbox stay disabled and every firmware-dependent value stays + * zero until the boot loader fills it. + */ +/ { + gpu_opp: opp-table-gpu { + compatible = "operating-points-v2"; + + /* Placeholder only; filled by the boot loader from the ADT. */ + opp00 { + opp-hz = /bits/ 64 <0>; + opp-microvolt = <0 0 0 0>; + opp-microwatt = <0>; + }; + }; + + gpu_cs_opp: opp-table-gpu-cs { + compatible = "operating-points-v2"; + + opp00 { + opp-hz = /bits/ 64 <0>; + opp-microvolt = <0>; + }; + }; + + gpu_afr_opp: opp-table-gpu-afr { + compatible = "operating-points-v2"; + + opp00 { + opp-hz = /bits/ 64 <0>; + opp-microvolt = <0>; + }; + }; + + reserved-memory { + /* Filled and enabled by the boot loader from the ADT sgx + * gpu-region-*, gfx-shared-region-*, gfx-handoff-* and + * gfx-shared-l2-region-* properties. */ + uat_ttbs: uat-ttbs@10 { + reg = <0 0x10 0 0>; + status = "disabled"; + }; + + uat_pagetables: uat-pagetables@20 { + reg = <0 0x20 0 0>; + status = "disabled"; + }; + + uat_handoff: uat-handoff@30 { + reg = <0 0x30 0 0>; + status = "disabled"; + }; + + uat_pagetables_l2: uat-pagetables-l2@40 { + reg = <0 0x40 0 0>; + status = "disabled"; + }; + }; + + aliases { + gpu = &gpu; + }; +}; + +&die0 { + gpu: gpu@40a400000 { + compatible = "apple,agx-t6032"; + reg = <0x4 0x0a400000 0x0 0x6c000>, + <0x4 0x08000000 0x0 0x3fdc000>; + reg-names = "asc", "sgx"; + interrupt-parent = <&aic>; + /* ADT order; entry 5 (IRQ 1249) is marked invalid there. */ + interrupts = , + , + , + , + , + , + ; + power-domains = <&ps_gfx>; + post-init-providers = <&ps_gfx>; + mboxes = <&agx_mbox>; + memory-region = <&uat_ttbs>, <&uat_pagetables>, + <&uat_handoff>, <&uat_pagetables_l2>; + memory-region-names = "ttbs", "pagetables", "handoff", + "pagetables-l2"; + + apple,firmware-abi = <0 0 0>; + apple,firmware-version = <0 0 0>; + apple,firmware-compat = <0 0 0>; + + operating-points-v2 = <&gpu_opp>; + apple,cs-opp = <&gpu_cs_opp>; + apple,afr-opp = <&gpu_afr_opp>; + + status = "disabled"; + }; + + agx_mbox: mbox@40a408000 { + compatible = "apple,t6032-agx-asc-mailbox"; + reg = <0x4 0x0a408000 0x0 0x4000>; + interrupt-parent = <&aic>; + /* ADT gfx-asc order 1244,1243,1246,1245 -> mailbox order. */ + interrupts = , + , + , + ; + interrupt-names = "send-empty", "send-not-empty", + "recv-empty", "recv-not-empty"; + #mbox-cells = <0>; + status = "disabled"; + }; +}; + +/* + * The eight external display pipes (dcpext0-7, iop,ascwrap-v6 in the ADT; + * each dispextN shares its register windows with dcpextN, so no separate + * display node is needed). Window split and mailbox interrupt ordering + * follow the T6031 internal-display description; the compatibles are + * chip-specific so kernels without T6032 display support leave the DCPs + * unbound. Every node stays disabled: the DCP driver has no 27.x firmware + * family and m1n1 gates the display handoff on the OS firmware. + * Pipes 4-7 are die 1, except the disp-5 AOP gate window, which is die-0 + * resident (0x2_903d0000) and left out of their register maps. The ADT + * carries pipe 4's dart interrupt (5143) on dart-dispext5 and + * dart-dcpext7; those values are kept as read. + */ + +&die0 { + dispext0_dart: iommu@305304000 { + compatible = "apple,t6032-dart", "apple,t8110-dart"; + reg = <0x3 0x5304000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = ; + #iommu-cells = <1>; + apple,dma-range = <0x100 0x0 0x10 0x0>; + power-domains = <&ps_dispext0_cpu>; + status = "disabled"; + }; + + dcpext0_dart: iommu@30530c000 { + compatible = "apple,t6032-dart", "apple,t8110-dart"; + reg = <0x3 0x530c000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = ; + #iommu-cells = <1>; + apple,dma-range = <0x100 0x0 0x10 0x0>; + power-domains = <&ps_dispext0_cpu>; + status = "disabled"; + }; + + dcpext0_mbox: mbox@306c08000 { + compatible = "apple,t6032-asc-mailbox", "apple,asc-mailbox-v4"; + reg = <0x3 0x6c08000 0x0 0x4000>; + interrupt-parent = <&aic>; + /* ADT list (n+1,n,n+3,n+2) reordered to mailbox order. */ + interrupts = , + , + , + ; + interrupt-names = "send-empty", "send-not-empty", + "recv-empty", "recv-not-empty"; + power-domains = <&ps_dispext0_cpu>; + #mbox-cells = <0>; + status = "disabled"; + }; + + dcpext0: dcp@306c00000 { + compatible = "apple,t6032-dcpext"; + mboxes = <&dcpext0_mbox>; + mbox-names = "mbox"; + iommus = <&dcpext0_dart 5>; + reg-names = "coproc", "disp-0", "disp-2", "disp-3", "disp-4", "disp-5", + "iop-vbar"; + reg = <0x3 0x6c00000 0x0 0x4000>, + <0x3 0x4000000 0x0 0x4000000>, + <0x2 0x903d0000 0x0 0x4000>, + <0x3 0x5320000 0x0 0x4000>, + <0x3 0x5344000 0x0 0x4000>, + <0x3 0x6800000 0x0 0x800000>, + <0x3 0x6850000 0x0 0x4000>; + power-domains = <&ps_dispext0_cpu>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + status = "disabled"; + + dcpext0_piodma: piodma { + iommus = <&dispext0_dart 4>; + }; + }; +}; + +&die0 { + dispext1_dart: iommu@449304000 { + compatible = "apple,t6032-dart", "apple,t8110-dart"; + reg = <0x4 0x49304000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = ; + #iommu-cells = <1>; + apple,dma-range = <0x100 0x0 0x10 0x0>; + power-domains = <&ps_dispext1_cpu>; + status = "disabled"; + }; + + dcpext1_dart: iommu@44930c000 { + compatible = "apple,t6032-dart", "apple,t8110-dart"; + reg = <0x4 0x4930c000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = ; + #iommu-cells = <1>; + apple,dma-range = <0x100 0x0 0x10 0x0>; + power-domains = <&ps_dispext1_cpu>; + status = "disabled"; + }; + + dcpext1_mbox: mbox@44ac08000 { + compatible = "apple,t6032-asc-mailbox", "apple,asc-mailbox-v4"; + reg = <0x4 0x4ac08000 0x0 0x4000>; + interrupt-parent = <&aic>; + /* ADT list (n+1,n,n+3,n+2) reordered to mailbox order. */ + interrupts = , + , + , + ; + interrupt-names = "send-empty", "send-not-empty", + "recv-empty", "recv-not-empty"; + power-domains = <&ps_dispext1_cpu>; + #mbox-cells = <0>; + status = "disabled"; + }; + + dcpext1: dcp@44ac00000 { + compatible = "apple,t6032-dcpext"; + mboxes = <&dcpext1_mbox>; + mbox-names = "mbox"; + iommus = <&dcpext1_dart 5>; + reg-names = "coproc", "disp-0", "disp-2", "disp-3", "disp-4", "disp-5", + "iop-vbar"; + reg = <0x4 0x4ac00000 0x0 0x4000>, + <0x4 0x48000000 0x0 0x4000000>, + <0x2 0x903d0000 0x0 0x4000>, + <0x4 0x49320000 0x0 0x4000>, + <0x4 0x49344000 0x0 0x4000>, + <0x4 0x4a800000 0x0 0x800000>, + <0x4 0x4a850000 0x0 0x4000>; + power-domains = <&ps_dispext1_cpu>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + status = "disabled"; + + dcpext1_piodma: piodma { + iommus = <&dispext1_dart 4>; + }; + }; +}; + +&die0 { + dispext2_dart: iommu@44d304000 { + compatible = "apple,t6032-dart", "apple,t8110-dart"; + reg = <0x4 0x4d304000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = ; + #iommu-cells = <1>; + apple,dma-range = <0x100 0x0 0x10 0x0>; + power-domains = <&ps_dispext2_cpu>; + status = "disabled"; + }; + + dcpext2_dart: iommu@44d30c000 { + compatible = "apple,t6032-dart", "apple,t8110-dart"; + reg = <0x4 0x4d30c000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = ; + #iommu-cells = <1>; + apple,dma-range = <0x100 0x0 0x10 0x0>; + power-domains = <&ps_dispext2_cpu>; + status = "disabled"; + }; + + dcpext2_mbox: mbox@44ec08000 { + compatible = "apple,t6032-asc-mailbox", "apple,asc-mailbox-v4"; + reg = <0x4 0x4ec08000 0x0 0x4000>; + interrupt-parent = <&aic>; + /* ADT list (n+1,n,n+3,n+2) reordered to mailbox order. */ + interrupts = , + , + , + ; + interrupt-names = "send-empty", "send-not-empty", + "recv-empty", "recv-not-empty"; + power-domains = <&ps_dispext2_cpu>; + #mbox-cells = <0>; + status = "disabled"; + }; + + dcpext2: dcp@44ec00000 { + compatible = "apple,t6032-dcpext"; + mboxes = <&dcpext2_mbox>; + mbox-names = "mbox"; + iommus = <&dcpext2_dart 5>; + reg-names = "coproc", "disp-0", "disp-2", "disp-3", "disp-4", "disp-5", + "iop-vbar"; + reg = <0x4 0x4ec00000 0x0 0x4000>, + <0x4 0x4c000000 0x0 0x4000000>, + <0x2 0x903d0000 0x0 0x4000>, + <0x4 0x4d320000 0x0 0x4000>, + <0x4 0x4d344000 0x0 0x4000>, + <0x4 0x4e800000 0x0 0x800000>, + <0x4 0x4e850000 0x0 0x4000>; + power-domains = <&ps_dispext2_cpu>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + status = "disabled"; + + dcpext2_piodma: piodma { + iommus = <&dispext2_dart 4>; + }; + }; +}; + +&die0 { + dispext3_dart: iommu@2c9304000 { + compatible = "apple,t6032-dart", "apple,t8110-dart"; + reg = <0x2 0xc9304000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = ; + #iommu-cells = <1>; + apple,dma-range = <0x100 0x0 0x10 0x0>; + power-domains = <&ps_dispext3_cpu>; + status = "disabled"; + }; + + dcpext3_dart: iommu@2c930c000 { + compatible = "apple,t6032-dart", "apple,t8110-dart"; + reg = <0x2 0xc930c000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = ; + #iommu-cells = <1>; + apple,dma-range = <0x100 0x0 0x10 0x0>; + power-domains = <&ps_dispext3_cpu>; + status = "disabled"; + }; + + dcpext3_mbox: mbox@2cac08000 { + compatible = "apple,t6032-asc-mailbox", "apple,asc-mailbox-v4"; + reg = <0x2 0xcac08000 0x0 0x4000>; + interrupt-parent = <&aic>; + /* ADT list (n+1,n,n+3,n+2) reordered to mailbox order. */ + interrupts = , + , + , + ; + interrupt-names = "send-empty", "send-not-empty", + "recv-empty", "recv-not-empty"; + power-domains = <&ps_dispext3_cpu>; + #mbox-cells = <0>; + status = "disabled"; + }; + + dcpext3: dcp@2cac00000 { + compatible = "apple,t6032-dcpext"; + mboxes = <&dcpext3_mbox>; + mbox-names = "mbox"; + iommus = <&dcpext3_dart 5>; + reg-names = "coproc", "disp-0", "disp-2", "disp-3", "disp-4", "disp-5", + "iop-vbar"; + reg = <0x2 0xcac00000 0x0 0x4000>, + <0x2 0xc8000000 0x0 0x4000000>, + <0x2 0x903d0000 0x0 0x4000>, + <0x2 0xc9320000 0x0 0x4000>, + <0x2 0xc9344000 0x0 0x4000>, + <0x2 0xca800000 0x0 0x800000>, + <0x2 0xca850000 0x0 0x4000>; + power-domains = <&ps_dispext3_cpu>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + status = "disabled"; + + dcpext3_piodma: piodma { + iommus = <&dispext3_dart 4>; + }; + }; +}; + +&die1 { + dispext4_dart: iommu@305304000 { + compatible = "apple,t6032-dart", "apple,t8110-dart"; + reg = <0x3 0x5304000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = ; + #iommu-cells = <1>; + apple,dma-range = <0x100 0x0 0x10 0x0>; + power-domains = <&ps_dispext0_cpu_die1>; + status = "disabled"; + }; + + dcpext4_dart: iommu@30530c000 { + compatible = "apple,t6032-dart", "apple,t8110-dart"; + reg = <0x3 0x530c000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = ; + #iommu-cells = <1>; + apple,dma-range = <0x100 0x0 0x10 0x0>; + power-domains = <&ps_dispext0_cpu_die1>; + status = "disabled"; + }; + + dcpext4_mbox: mbox@306c08000 { + compatible = "apple,t6032-asc-mailbox", "apple,asc-mailbox-v4"; + reg = <0x3 0x6c08000 0x0 0x4000>; + interrupt-parent = <&aic>; + /* ADT list (n+1,n,n+3,n+2) reordered to mailbox order. */ + interrupts = , + , + , + ; + interrupt-names = "send-empty", "send-not-empty", + "recv-empty", "recv-not-empty"; + power-domains = <&ps_dispext0_cpu_die1>; + #mbox-cells = <0>; + status = "disabled"; + }; + + dcpext4: dcp@306c00000 { + compatible = "apple,t6032-dcpext"; + mboxes = <&dcpext4_mbox>; + mbox-names = "mbox"; + iommus = <&dcpext4_dart 5>; + reg-names = "coproc", "disp-0", "disp-2", "disp-3", "disp-4", + "iop-vbar"; + reg = <0x3 0x6c00000 0x0 0x4000>, + <0x3 0x4000000 0x0 0x4000000>, + <0x3 0x5320000 0x0 0x4000>, + <0x3 0x5344000 0x0 0x4000>, + <0x3 0x6800000 0x0 0x800000>, + <0x3 0x6850000 0x0 0x4000>; + power-domains = <&ps_dispext0_cpu_die1>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + status = "disabled"; + + dcpext4_piodma: piodma { + iommus = <&dispext4_dart 4>; + }; + }; +}; + +&die1 { + dispext5_dart: iommu@449304000 { + compatible = "apple,t6032-dart", "apple,t8110-dart"; + reg = <0x4 0x49304000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = ; + #iommu-cells = <1>; + apple,dma-range = <0x100 0x0 0x10 0x0>; + power-domains = <&ps_dispext1_cpu_die1>; + status = "disabled"; + }; + + dcpext5_dart: iommu@44930c000 { + compatible = "apple,t6032-dart", "apple,t8110-dart"; + reg = <0x4 0x4930c000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = ; + #iommu-cells = <1>; + apple,dma-range = <0x100 0x0 0x10 0x0>; + power-domains = <&ps_dispext1_cpu_die1>; + status = "disabled"; + }; + + dcpext5_mbox: mbox@44ac08000 { + compatible = "apple,t6032-asc-mailbox", "apple,asc-mailbox-v4"; + reg = <0x4 0x4ac08000 0x0 0x4000>; + interrupt-parent = <&aic>; + /* ADT list (n+1,n,n+3,n+2) reordered to mailbox order. */ + interrupts = , + , + , + ; + interrupt-names = "send-empty", "send-not-empty", + "recv-empty", "recv-not-empty"; + power-domains = <&ps_dispext1_cpu_die1>; + #mbox-cells = <0>; + status = "disabled"; + }; + + dcpext5: dcp@44ac00000 { + compatible = "apple,t6032-dcpext"; + mboxes = <&dcpext5_mbox>; + mbox-names = "mbox"; + iommus = <&dcpext5_dart 5>; + reg-names = "coproc", "disp-0", "disp-2", "disp-3", "disp-4", + "iop-vbar"; + reg = <0x4 0x4ac00000 0x0 0x4000>, + <0x4 0x48000000 0x0 0x4000000>, + <0x4 0x49320000 0x0 0x4000>, + <0x4 0x49344000 0x0 0x4000>, + <0x4 0x4a800000 0x0 0x800000>, + <0x4 0x4a850000 0x0 0x4000>; + power-domains = <&ps_dispext1_cpu_die1>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + status = "disabled"; + + dcpext5_piodma: piodma { + iommus = <&dispext5_dart 4>; + }; + }; +}; + +&die1 { + dispext6_dart: iommu@44d304000 { + compatible = "apple,t6032-dart", "apple,t8110-dart"; + reg = <0x4 0x4d304000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = ; + #iommu-cells = <1>; + apple,dma-range = <0x100 0x0 0x10 0x0>; + power-domains = <&ps_dispext2_cpu_die1>; + status = "disabled"; + }; + + dcpext6_dart: iommu@44d30c000 { + compatible = "apple,t6032-dart", "apple,t8110-dart"; + reg = <0x4 0x4d30c000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = ; + #iommu-cells = <1>; + apple,dma-range = <0x100 0x0 0x10 0x0>; + power-domains = <&ps_dispext2_cpu_die1>; + status = "disabled"; + }; + + dcpext6_mbox: mbox@44ec08000 { + compatible = "apple,t6032-asc-mailbox", "apple,asc-mailbox-v4"; + reg = <0x4 0x4ec08000 0x0 0x4000>; + interrupt-parent = <&aic>; + /* ADT list (n+1,n,n+3,n+2) reordered to mailbox order. */ + interrupts = , + , + , + ; + interrupt-names = "send-empty", "send-not-empty", + "recv-empty", "recv-not-empty"; + power-domains = <&ps_dispext2_cpu_die1>; + #mbox-cells = <0>; + status = "disabled"; + }; + + dcpext6: dcp@44ec00000 { + compatible = "apple,t6032-dcpext"; + mboxes = <&dcpext6_mbox>; + mbox-names = "mbox"; + iommus = <&dcpext6_dart 5>; + reg-names = "coproc", "disp-0", "disp-2", "disp-3", "disp-4", + "iop-vbar"; + reg = <0x4 0x4ec00000 0x0 0x4000>, + <0x4 0x4c000000 0x0 0x4000000>, + <0x4 0x4d320000 0x0 0x4000>, + <0x4 0x4d344000 0x0 0x4000>, + <0x4 0x4e800000 0x0 0x800000>, + <0x4 0x4e850000 0x0 0x4000>; + power-domains = <&ps_dispext2_cpu_die1>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + status = "disabled"; + + dcpext6_piodma: piodma { + iommus = <&dispext6_dart 4>; + }; + }; +}; + +&die1 { + dispext7_dart: iommu@2c9304000 { + compatible = "apple,t6032-dart", "apple,t8110-dart"; + reg = <0x2 0xc9304000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = ; + #iommu-cells = <1>; + apple,dma-range = <0x100 0x0 0x10 0x0>; + power-domains = <&ps_dispext3_cpu_die1>; + status = "disabled"; + }; + + dcpext7_dart: iommu@2c930c000 { + compatible = "apple,t6032-dart", "apple,t8110-dart"; + reg = <0x2 0xc930c000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = ; + #iommu-cells = <1>; + apple,dma-range = <0x100 0x0 0x10 0x0>; + power-domains = <&ps_dispext3_cpu_die1>; + status = "disabled"; + }; + + dcpext7_mbox: mbox@2cac08000 { + compatible = "apple,t6032-asc-mailbox", "apple,asc-mailbox-v4"; + reg = <0x2 0xcac08000 0x0 0x4000>; + interrupt-parent = <&aic>; + /* ADT list (n+1,n,n+3,n+2) reordered to mailbox order. */ + interrupts = , + , + , + ; + interrupt-names = "send-empty", "send-not-empty", + "recv-empty", "recv-not-empty"; + power-domains = <&ps_dispext3_cpu_die1>; + #mbox-cells = <0>; + status = "disabled"; + }; + + dcpext7: dcp@2cac00000 { + compatible = "apple,t6032-dcpext"; + mboxes = <&dcpext7_mbox>; + mbox-names = "mbox"; + iommus = <&dcpext7_dart 5>; + reg-names = "coproc", "disp-0", "disp-2", "disp-3", "disp-4", + "iop-vbar"; + reg = <0x2 0xcac00000 0x0 0x4000>, + <0x2 0xc8000000 0x0 0x4000000>, + <0x2 0xc9320000 0x0 0x4000>, + <0x2 0xc9344000 0x0 0x4000>, + <0x2 0xca800000 0x0 0x800000>, + <0x2 0xca850000 0x0 0x4000>; + power-domains = <&ps_dispext3_cpu_die1>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + status = "disabled"; + + dcpext7_piodma: piodma { + iommus = <&dispext7_dart 4>; + }; + }; +}; + +/* + * The Apple Neural Engine: ane0 on die 0, ane1 on die 1 (the 26.0+ ADT + * layout: ASC wrapper 0x3_c940_0000, engine 0x3_c800_0000, a second engine + * window 0x4_0400_0000). Register windows are the 27.0.1 ADT's, in ADT + * order. No Linux driver covers M3, so the engines and their DARTs stay + * disabled. + */ +&die0 { + ane0_dart0: iommu@3c9800000 { + compatible = "apple,t6031-dart", "apple,t8110-dart"; + reg = <0x3 0xc9800000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = ; + power-domains = <&ps_ane_sys>; + #iommu-cells = <1>; + status = "disabled"; + }; + + ane0_dart1: iommu@3c9810000 { + compatible = "apple,t6031-dart", "apple,t8110-dart"; + reg = <0x3 0xc9810000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = ; + power-domains = <&ps_ane_sys>; + #iommu-cells = <1>; + status = "disabled"; + }; + + ane0_dart2: iommu@3c9820000 { + compatible = "apple,t6031-dart", "apple,t8110-dart"; + reg = <0x3 0xc9820000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = ; + power-domains = <&ps_ane_sys>; + #iommu-cells = <1>; + status = "disabled"; + }; + + ane0: ane@3c9400000 { + compatible = "apple,t6032-ane"; + /* ADT windows in ADT order: ASC wrapper, ASC block, engine, + * pmgr bank, pmgr set bank, IO-clear, second engine, DART + * tunables. */ + reg = <0x3 0xc9400000 0x0 0x6c000>, + <0x3 0xc9050000 0x0 0x4000>, + <0x3 0xc8000000 0x0 0x2000000>, + <0x2 0x92280000 0x0 0x10000>, + <0x2 0x92290000 0x0 0x4000>, + <0x2 0x903c0000 0x0 0x30000>, + <0x4 0x04000000 0x0 0x2000000>, + <0x2 0xa02dc000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = , + , + , + , + ; + power-domains = <&ps_ane_sys>, <&ps_ane_mpm>, + <&ps_ane_cpu>, <&ps_ane_td>, <&ps_ane_base>; + iommus = <&ane0_dart0 0>, <&ane0_dart1 0>, <&ane0_dart2 0>; + status = "disabled"; + }; +}; + +&die1 { + ane1_dart0: iommu@3c9800000 { + compatible = "apple,t6031-dart", "apple,t8110-dart"; + reg = <0x3 0xc9800000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = ; + power-domains = <&ps_ane_sys_die1>; + #iommu-cells = <1>; + status = "disabled"; + }; + + ane1_dart1: iommu@3c9810000 { + compatible = "apple,t6031-dart", "apple,t8110-dart"; + reg = <0x3 0xc9810000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = ; + power-domains = <&ps_ane_sys_die1>; + #iommu-cells = <1>; + status = "disabled"; + }; + + ane1_dart2: iommu@3c9820000 { + compatible = "apple,t6031-dart", "apple,t8110-dart"; + reg = <0x3 0xc9820000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = ; + power-domains = <&ps_ane_sys_die1>; + #iommu-cells = <1>; + status = "disabled"; + }; + + /* The io-clear window 0x2_903c0000 is die-0 resident and shared with + * ane0; all other windows are die-1. */ + ane1: ane@23c9400000 { + compatible = "apple,t6032-ane"; + reg = <0x3 0xc9400000 0x0 0x6c000>, + <0x3 0xc9050000 0x0 0x4000>, + <0x3 0xc8000000 0x0 0x2000000>, + <0x2 0x92280000 0x0 0x10000>, + <0x2 0x92290000 0x0 0x4000>, + <0x4 0x04000000 0x0 0x2000000>, + <0x2 0xa02dc000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = , + , + , + , + ; + power-domains = <&ps_ane_sys_die1>, <&ps_ane_mpm_die1>, + <&ps_ane_cpu_die1>, <&ps_ane_td_die1>, + <&ps_ane_base_die1>; + iommus = <&ane1_dart0 0>, <&ane1_dart1 0>, <&ane1_dart2 0>; + status = "disabled"; + }; +}; From 05cc2d437419ca835744e3e9092eec1720247380 Mon Sep 17 00:00:00 2001 From: Joshua Warren <816217+joshuaswarren@users.noreply.github.com> Date: Sat, 24 Oct 2026 19:18:02 -0500 Subject: [PATCH 2/8] arm64: dts: apple: normalize t6032 die-1 interrupts; check irqs against the ADT The first interrupt column of the ADT encodes die 1 by adding 0x1000 to the AIC number; the DT interrupt spec carries the die in its own cell and uses the die-0 number. The die-1 ANE and display-pipe nodes added for t6032 carried the raw ADT numbers (5xxx) in a die-1 spec, which maps to AIC hardware interrupts that do not exist. Rewrite them as die-0 numbers with the die cell set (ane1 965/964/967/966/983 and dart 984, the pipe 4-7 mailboxes 1068-1179 and darts 1047/1083/1119/1155). Extend the ADT-vs-DT checker to compare interrupts, so this class cannot regress: every DT interrupt must appear in the interrupt set of an ADT node its windows overlap (compared as (die, irq) pairs, so order differences such as the gfx-asc mailbox reorder are handled), and every required ADT node with valid interrupts (per the ADT interrupts-valid bitmask; sgx entry 5, IRQ 1249, is invalid) must have them carried by a DT node. Allowlisted deliberate differences, each commented: the display pipes' interrupts are carried by their mailbox and DART nodes, and the inherited four-cluster mca node carries a fourth interrupt (1321) the 27.0.1 ADT does not list (it describes three MCA instances). Verified against the 27.0.1 j575dap ADT: the fixed tree passes 245 checks; the unfixed base tree (integration/aurora 7b969982306e) fails 84, the previous commit's tree fails 30, and a DTB with one dart interrupt changed fails and exits 1. Signed-off-by: Joshua Warren <816217+joshuaswarren@users.noreply.github.com> --- .github/scripts/adt-dt-check-t6032.py | 112 +++++++++++++++++++++++++- arch/arm64/boot/dts/apple/t6032.dtsi | 64 +++++++-------- 2 files changed, 143 insertions(+), 33 deletions(-) diff --git a/.github/scripts/adt-dt-check-t6032.py b/.github/scripts/adt-dt-check-t6032.py index fd59b8e6679916..ae8d9a3bee97a1 100755 --- a/.github/scripts/adt-dt-check-t6032.py +++ b/.github/scripts/adt-dt-check-t6032.py @@ -204,6 +204,53 @@ def dt_cells(val): return out +def adt_irqs(node): + """(all_irqs, valid_irqs) of an ADT node, as (die, irq) pairs. The ADT + encodes die 1 by adding 0x1000 to the AIC number. 'interrupts-valid' is + a bitmask over the 'interrupts' entries; entries whose bit is clear are + marked invalid by the firmware (sgx entry 5, IRQ 1249). Without the + property every entry counts as valid.""" + pr = node["props"] + raw = pr.get("interrupts") + if raw is None: + return [], [] + all_irqs = [(1 if n >= 0x1000 else 0, n - 0x1000 if n >= 0x1000 else n) + for n in (int.from_bytes(raw[i:i + 4], "little") + for i in range(0, len(raw), 4))] + mask = pr.get("interrupts-valid") + if mask is None: + return all_irqs, list(all_irqs) + m = int.from_bytes(mask, "little") + valid = [irq for i, irq in enumerate(all_irqs) if m & (1 << i)] + return all_irqs, valid + + +def adt_irq_tables(root, names): + io = adt_find(root, "arm-io") + out = {} + for n in io["kids"]: + if adt_name(n) in names: + out[adt_name(n)] = adt_irqs(n) + return out + + +def dt_irqs(node): + """(die, irq) pairs of a DT node: 4-cell `interrupts` specs + () and 5-cell `interrupts-extended` specs + (<&aic AIC_IRQ die irq type>). Every interrupt-parent here is the AIC, + so the fixed grouping is safe for this board; nodes whose + interrupts-extended has irregular (<0> filler) specs are skipped, as + the spec length is then not derivable (e.g. the ADMAC channel list).""" + out = [] + c = dt_cells(node.props.get("interrupts", "")) + if len(c) % 4 == 0: + out += [(c[i + 1], c[i + 2]) for i in range(0, len(c), 4)] + c = dt_cells(node.props.get("interrupts-extended", "")) + if c and len(c) % 5 == 0: + out += [(c[i + 2], c[i + 3]) for i in range(0, len(c), 5)] + return out + + def dt_strings(val): return re.findall(r'"([^"]*)"', val or "") @@ -409,6 +456,23 @@ def der_tlv(b, p): REQUIRED_PS.append(("soc@200000000", "power-management@408e80000", 0x110, "ps_gfx")) REQUIRED_PS.append(("soc@2200000000", "power-management@408e80000", 0x110, "ps_gfx_die1")) +# ADT nodes whose interrupts the DT deliberately does not carry on the node +# that covers their registers. Each display pipe (dispextN) shares its +# register windows with dcpextN, which carries no interrupts of its own: +# the ADT pipe interrupts are carried by the mailbox and DART nodes, and +# those are checked against their own ADT nodes (dart-dcpextN, dart- +# dispextN, dcpextN). +IRQ_COVERAGE_EXEMPT = {f"dispext{i}" for i in range(8)} + +# Individual (die, irq) values the DT carries deliberately although no ADT +# device lists them, each with its reason: +# (0, 1321): the DT models the T6031 four-cluster audio block in one mca +# node; the 27.0.1 j575dap ADT lists three MCA instances (mca0-2, irqs +# 1318-1320) and has no fourth instance. +DT_IRQ_ALLOW = { + (0, 1321), +} + # nodes that must carry status = "disabled" MUST_BE_DISABLED = ( ["gpu", "mbox@40a408000"] @@ -439,6 +503,16 @@ def main(): root, _ = adt_parse(open(adt_path, "rb").read()) awindows = adt_windows(root) gated = adt_gated_nodes(root, set(REQUIRED)) + airqs = adt_irq_tables(root, set(REQUIRED)) + # every /arm-io node with registers: windows + full irq set, for the + # per-DT-node subset rule + io = adt_find(root, "arm-io") + io_rng = adt_ranges(io) + adt_all = [] + for n in io["kids"]: + wins = [(adt_translate(io_rng, a), s) for a, s in adt_reg(n) if s] + if wins: + adt_all.append((adt_name(n), wins, adt_irqs(n)[0])) for dtb in dtbs: print(f"== {dtb} ==") @@ -503,7 +577,43 @@ def main(): if got == off else f"{label}: {pmgr}/power-controller@{off:x} has reg offset {got:#x}, ADT says {off:#x}") - # 5. disabled gates + # 5. interrupts: every DT interrupt must appear in the ADT irq set + # of a node its windows overlap (order differences like the + # gfx-asc mailbox reorder are handled by set comparison), and + # every required ADT node with valid interrupts must see at least + # one of them carried by a DT node (IRQ_COVERAGE_EXEMPT excepted). + matched_irqs = {name: [] for name in REQUIRED} + for path, node, wins in dtnodes: + if not wins: + continue + dirs = dt_irqs(node) + if not dirs: + continue + union = set() + names = set() + for name, aw, airq in adt_all: + if any(overlap(w, aw2) for w in wins for aw2 in aw): + union |= set(airq) + names.add(name) + bad = [i for i in dirs if i not in union and i not in DT_IRQ_ALLOW] + check(not bad, f"{path}: irqs {[f'{d}:{n}' for d, n in dirs]} within the ADT ({', '.join(sorted(names))})" + if not bad else + f"{path}: irq(s) {bad} not in the ADT interrupt set of the overlapped node(s)") + for name in names: + if name in matched_irqs: + matched_irqs[name] += dirs + for name in REQUIRED: + if name in IRQ_COVERAGE_EXEMPT: + continue + valid = airqs.get(name, ([], []))[1] + if not valid: + continue + carried = [i for i in matched_irqs[name] if i in valid] + check(carried, f"{name}: ADT interrupts {valid} carried by the DT" + if carried else + f"{name}: ADT interrupts {valid} carried by no DT node") + + # 6. disabled gates for path, node, wins in dtnodes: base = node.name.split("@")[0] if base in MUST_BE_DISABLED or node.name in MUST_BE_DISABLED: diff --git a/arch/arm64/boot/dts/apple/t6032.dtsi b/arch/arm64/boot/dts/apple/t6032.dtsi index 721b2df801d66c..0ba8dc54d85fd6 100644 --- a/arch/arm64/boot/dts/apple/t6032.dtsi +++ b/arch/arm64/boot/dts/apple/t6032.dtsi @@ -927,7 +927,7 @@ compatible = "apple,t6032-dart", "apple,t8110-dart"; reg = <0x3 0x5304000 0x0 0x4000>; interrupt-parent = <&aic>; - interrupts = ; + interrupts = ; #iommu-cells = <1>; apple,dma-range = <0x100 0x0 0x10 0x0>; power-domains = <&ps_dispext0_cpu_die1>; @@ -938,7 +938,7 @@ compatible = "apple,t6032-dart", "apple,t8110-dart"; reg = <0x3 0x530c000 0x0 0x4000>; interrupt-parent = <&aic>; - interrupts = ; + interrupts = ; #iommu-cells = <1>; apple,dma-range = <0x100 0x0 0x10 0x0>; power-domains = <&ps_dispext0_cpu_die1>; @@ -950,10 +950,10 @@ reg = <0x3 0x6c08000 0x0 0x4000>; interrupt-parent = <&aic>; /* ADT list (n+1,n,n+3,n+2) reordered to mailbox order. */ - interrupts = , - , - , - ; + interrupts = , + , + , + ; interrupt-names = "send-empty", "send-not-empty", "recv-empty", "recv-not-empty"; power-domains = <&ps_dispext0_cpu_die1>; @@ -991,7 +991,7 @@ compatible = "apple,t6032-dart", "apple,t8110-dart"; reg = <0x4 0x49304000 0x0 0x4000>; interrupt-parent = <&aic>; - interrupts = ; + interrupts = ; #iommu-cells = <1>; apple,dma-range = <0x100 0x0 0x10 0x0>; power-domains = <&ps_dispext1_cpu_die1>; @@ -1002,7 +1002,7 @@ compatible = "apple,t6032-dart", "apple,t8110-dart"; reg = <0x4 0x4930c000 0x0 0x4000>; interrupt-parent = <&aic>; - interrupts = ; + interrupts = ; #iommu-cells = <1>; apple,dma-range = <0x100 0x0 0x10 0x0>; power-domains = <&ps_dispext1_cpu_die1>; @@ -1014,10 +1014,10 @@ reg = <0x4 0x4ac08000 0x0 0x4000>; interrupt-parent = <&aic>; /* ADT list (n+1,n,n+3,n+2) reordered to mailbox order. */ - interrupts = , - , - , - ; + interrupts = , + , + , + ; interrupt-names = "send-empty", "send-not-empty", "recv-empty", "recv-not-empty"; power-domains = <&ps_dispext1_cpu_die1>; @@ -1055,7 +1055,7 @@ compatible = "apple,t6032-dart", "apple,t8110-dart"; reg = <0x4 0x4d304000 0x0 0x4000>; interrupt-parent = <&aic>; - interrupts = ; + interrupts = ; #iommu-cells = <1>; apple,dma-range = <0x100 0x0 0x10 0x0>; power-domains = <&ps_dispext2_cpu_die1>; @@ -1066,7 +1066,7 @@ compatible = "apple,t6032-dart", "apple,t8110-dart"; reg = <0x4 0x4d30c000 0x0 0x4000>; interrupt-parent = <&aic>; - interrupts = ; + interrupts = ; #iommu-cells = <1>; apple,dma-range = <0x100 0x0 0x10 0x0>; power-domains = <&ps_dispext2_cpu_die1>; @@ -1078,10 +1078,10 @@ reg = <0x4 0x4ec08000 0x0 0x4000>; interrupt-parent = <&aic>; /* ADT list (n+1,n,n+3,n+2) reordered to mailbox order. */ - interrupts = , - , - , - ; + interrupts = , + , + , + ; interrupt-names = "send-empty", "send-not-empty", "recv-empty", "recv-not-empty"; power-domains = <&ps_dispext2_cpu_die1>; @@ -1119,7 +1119,7 @@ compatible = "apple,t6032-dart", "apple,t8110-dart"; reg = <0x2 0xc9304000 0x0 0x4000>; interrupt-parent = <&aic>; - interrupts = ; + interrupts = ; #iommu-cells = <1>; apple,dma-range = <0x100 0x0 0x10 0x0>; power-domains = <&ps_dispext3_cpu_die1>; @@ -1130,7 +1130,7 @@ compatible = "apple,t6032-dart", "apple,t8110-dart"; reg = <0x2 0xc930c000 0x0 0x4000>; interrupt-parent = <&aic>; - interrupts = ; + interrupts = ; #iommu-cells = <1>; apple,dma-range = <0x100 0x0 0x10 0x0>; power-domains = <&ps_dispext3_cpu_die1>; @@ -1142,10 +1142,10 @@ reg = <0x2 0xcac08000 0x0 0x4000>; interrupt-parent = <&aic>; /* ADT list (n+1,n,n+3,n+2) reordered to mailbox order. */ - interrupts = , - , - , - ; + interrupts = , + , + , + ; interrupt-names = "send-empty", "send-not-empty", "recv-empty", "recv-not-empty"; power-domains = <&ps_dispext3_cpu_die1>; @@ -1247,7 +1247,7 @@ compatible = "apple,t6031-dart", "apple,t8110-dart"; reg = <0x3 0xc9800000 0x0 0x4000>; interrupt-parent = <&aic>; - interrupts = ; + interrupts = ; power-domains = <&ps_ane_sys_die1>; #iommu-cells = <1>; status = "disabled"; @@ -1257,7 +1257,7 @@ compatible = "apple,t6031-dart", "apple,t8110-dart"; reg = <0x3 0xc9810000 0x0 0x4000>; interrupt-parent = <&aic>; - interrupts = ; + interrupts = ; power-domains = <&ps_ane_sys_die1>; #iommu-cells = <1>; status = "disabled"; @@ -1267,7 +1267,7 @@ compatible = "apple,t6031-dart", "apple,t8110-dart"; reg = <0x3 0xc9820000 0x0 0x4000>; interrupt-parent = <&aic>; - interrupts = ; + interrupts = ; power-domains = <&ps_ane_sys_die1>; #iommu-cells = <1>; status = "disabled"; @@ -1285,11 +1285,11 @@ <0x4 0x04000000 0x0 0x2000000>, <0x2 0xa02dc000 0x0 0x4000>; interrupt-parent = <&aic>; - interrupts = , - , - , - , - ; + interrupts = , + , + , + , + ; power-domains = <&ps_ane_sys_die1>, <&ps_ane_mpm_die1>, <&ps_ane_cpu_die1>, <&ps_ane_td_die1>, <&ps_ane_base_die1>; From 0bbf34a0b727279790e39c5092b6b65bd2c40eb0 Mon Sep 17 00:00:00 2001 From: Joshua Warren <816217+joshuaswarren@users.noreply.github.com> Date: Sun, 25 Oct 2026 14:07:05 -0500 Subject: [PATCH 3/8] arm64: dts: apple: add the t6032-j575d PCIe ports Enable the four PCIe ports and their DARTs and add the 10 Gbit Ethernet node, with the SMC power-enable lines for the WLAN, SD reader and USB xHCI ports. The port assignment and the power-enable keys come from the 27.0.1 ADT of a retail unit: WLAN and Bluetooth on port00, SD reader on port01, 10 Gbit Ethernet on port02, ASM3142 xHCI on port03. The ADT has no power function for port02 and no PCI IDs, so the WLAN, Bluetooth and SD reader child nodes are left out. Checked: the dtb builds, and the ADT-versus-DT check passes. Not checked: any PCIe link, DMA or boot on hardware. Signed-off-by: Joshua Warren <816217+joshuaswarren@users.noreply.github.com> --- arch/arm64/boot/dts/apple/t6032-j575d.dts | 53 +++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/arch/arm64/boot/dts/apple/t6032-j575d.dts b/arch/arm64/boot/dts/apple/t6032-j575d.dts index fb0e10a6c3a70c..e82e96d4ce2043 100644 --- a/arch/arm64/boot/dts/apple/t6032-j575d.dts +++ b/arch/arm64/boot/dts/apple/t6032-j575d.dts @@ -16,6 +16,7 @@ model = "Apple Mac Studio (M3 Ultra, 2025)"; aliases { + ethernet0 = ðernet0; serial0 = &serial0; }; @@ -106,6 +107,58 @@ }; }; +/* + * PCIe devices, from the 27.0.1 ADT of a retail unit: port00 WLAN and + * Bluetooth, port01 SD card reader, port02 10 Gbit Ethernet, port03 USB + * xHCI (ASM3142). The pwren numbers are the SMC gPxx key of the ADT + * function-reg_on, function-sd_pwr_en and function-power_enable + * properties read as hex; the ADT has no power function for port02. The ADT + * has no PCI IDs, so the WLAN, Bluetooth and SD reader child nodes are not + * written here. + */ +&port00 { + /* WLAN */ + bus-range = <1 1>; + pwren-gpios = <&smc_gpio 19 GPIO_ACTIVE_HIGH>; +}; + +&port01 { + /* SD card reader */ + bus-range = <2 2>; + pwren-gpios = <&smc_gpio 25 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&port02 { + /* 10 Gbit Ethernet */ + bus-range = <3 3>; + status = "okay"; + ethernet0: ethernet@0,0 { + reg = <0x30000 0x0 0x0 0x0 0x0>; + /* To be filled by the loader */ + local-mac-address = [00 10 18 00 00 00]; + }; +}; + +&port03 { + /* USB xHCI */ + bus-range = <4 4>; + pwren-gpios = <&smc_gpio 22 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&pcie0_dart_1 { + status = "okay"; +}; + +&pcie0_dart_2 { + status = "okay"; +}; + +&pcie0_dart_3 { + status = "okay"; +}; + #include "hwmon-common.dtsi" #include "hwmon-fan-dual.dtsi" From df16bdb5fa8bb9e9791095a3f5c4471993d94ad0 Mon Sep 17 00:00:00 2001 From: Joshua Warren <816217+joshuaswarren@users.noreply.github.com> Date: Sun, 25 Oct 2026 14:07:05 -0500 Subject: [PATCH 4/8] arm64: configs: add a t6032 console and network fragment Build in the pin controller, SMC GPIO, SART and NVMe drivers that the PCIe ports and the disk need, so a boot without an initramfs can reach the 10 Gbit port. Add the aQuantia AQtion driver for the 10 Gbit port (the ADT names it lan-10gb with an aqc-a i2c companion; it has no PCI ID) and the xHCI PCI driver for the USB-A ports. Checked: merged over defconfig and asahi.config, olddefconfig keeps every symbol. Not checked: a kernel build with this config, or any boot. Signed-off-by: Joshua Warren <816217+joshuaswarren@users.noreply.github.com> --- arch/arm64/configs/t6032-console.config | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 arch/arm64/configs/t6032-console.config diff --git a/arch/arm64/configs/t6032-console.config b/arch/arm64/configs/t6032-console.config new file mode 100644 index 00000000000000..aa84abafec6642 --- /dev/null +++ b/arch/arm64/configs/t6032-console.config @@ -0,0 +1,25 @@ +# Console and network additions for the T6032 Mac Studio board. +# Merge over defconfig and asahi.config, then run olddefconfig and check +# that the symbols below survive. +# +# The PCIe ports take PERST from the AP pin controller and power from the +# SMC GPIO, and the NVMe controller needs the SART, so these are built in: +# a boot without an initramfs must reach the 10 Gbit port and the disk. +CONFIG_PINCTRL_APPLE_GPIO=y +CONFIG_MFD_MACSMC=y +CONFIG_GPIO_MACSMC=y +CONFIG_APPLE_SART=y +CONFIG_BLK_DEV_NVME=y +CONFIG_NVME_APPLE=y +# +# The 10 Gbit port is a PCIe Ethernet device behind port02. The ADT names it +# lan-10gb and its i2c companion aqc-a, so it is taken to be an aQuantia +# AQtion part. The ADT gives no PCI ID. +CONFIG_NET_VENDOR_AQUANTIA=y +CONFIG_AQTION=y +# +# USB-A xHCI behind port03 (ASM3142) and USB Ethernet or ACM gadget hosts. +CONFIG_USB_XHCI_PCI=y +CONFIG_USB_XHCI_PCI_ASMEDIA=y +CONFIG_USB_NET_CDCETHER=m +CONFIG_USB_NET_CDC_NCM=m From b732ee81a2070e1dfe677706486e3badb3e8a092 Mon Sep 17 00:00:00 2001 From: Joshua Warren <816217+joshuaswarren@users.noreply.github.com> Date: Sun, 25 Oct 2026 17:18:20 -0500 Subject: [PATCH 5/8] ci: match t6032 gated nodes by register window, not by label Section 6 of the ADT-versus-DT check compared the DT node name before the '@' with a list of DT labels, so it never matched a node. A DT node is now a gated node when its first register window starts where a window of a gated ADT node starts (a DART: any window); it must be disabled, and fewer matching DT nodes than gated ADT nodes is a failure. Switching on ane@3c9400000 and dcp@306c00000 in a copy of the DTB is now a CI step and must be flagged. Also: install device-tree-compiler in the workflow, fix the die-1 label test (the soc node ends in 2200000000), and say in the docstring what section 4 compares. Checked: 277 ok, 0 FAIL on the real DTB; the mutation is flagged for both nodes. Signed-off-by: Joshua Warren <816217+joshuaswarren@users.noreply.github.com> --- .../scripts/adt-dt-check-t6032-mutation.sh | 18 +++++++ .github/scripts/adt-dt-check-t6032.py | 47 ++++++++++++------- .github/workflows/t6032-adt-dt-check.yml | 8 +++- 3 files changed, 54 insertions(+), 19 deletions(-) create mode 100755 .github/scripts/adt-dt-check-t6032-mutation.sh diff --git a/.github/scripts/adt-dt-check-t6032-mutation.sh b/.github/scripts/adt-dt-check-t6032-mutation.sh new file mode 100755 index 00000000000000..b0af5fe342b671 --- /dev/null +++ b/.github/scripts/adt-dt-check-t6032-mutation.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0-only OR MIT +# Mutation test for adt-dt-check-t6032.py section 6: switch one ANE engine and one external display +# controller on in a copy of the DTB; the checker must exit 1 and name both nodes. +set -u +dtb=$1 +tmp=$(mktemp -d) +trap 'rm -rf "$tmp"' EXIT +cp "$dtb" "$tmp/mut.dtb" +fdtput -t s "$tmp/mut.dtb" /soc@200000000/ane@3c9400000 status okay || exit 2 +fdtput -t s "$tmp/mut.dtb" /soc@200000000/dcp@306c00000 status okay || exit 2 +out=$(python3 "$(dirname "$0")/adt-dt-check-t6032.py" --fetch-ipsw "$tmp/mut.dtb") +rc=$? +echo "$out" | grep -E "FAIL" | head +[ "$rc" -eq 1 ] || { echo "mutation not detected (exit $rc)"; exit 1; } +echo "$out" | grep -E "FAIL.*ane@3c9400000" >/dev/null || { echo "ane@3c9400000 not flagged"; exit 1; } +echo "$out" | grep -E "FAIL.*dcp@306c00000" >/dev/null || { echo "dcp@306c00000 not flagged"; exit 1; } +echo "mutation detected" diff --git a/.github/scripts/adt-dt-check-t6032.py b/.github/scripts/adt-dt-check-t6032.py index ae8d9a3bee97a1..c432a4e2419fef 100755 --- a/.github/scripts/adt-dt-check-t6032.py +++ b/.github/scripts/adt-dt-check-t6032.py @@ -17,9 +17,16 @@ - every DT SoC node with registers must overlap an ADT node, except the die-1 cpufreq and pmgr mirrors (hardware mirrors at the die stride that the ADT expresses inside the pmgr register-window list, not as nodes); - - the power states the new nodes reference must exist at the ADT address - (bank + offset) in both dies; - - the GPU, ANE and display nodes must stay disabled. + - the power states the new nodes reference must exist in the DT at the + bank + offset listed in REQUIRED_PS (those offsets were read from the ADT + pmgr by hand; the script does not read them from the ADT), in both dies; + - the GPU, ANE and display nodes must stay disabled: a DT node is such a + gated node when its first register window starts where a window of a gated + ADT node starts (a DART: any window), so the test needs no DT labels, and + fewer matching DT nodes than gated ADT nodes is a failure. + +Expected, not a checker failure: dtc warns simple_bus_reg for the die-1 ANE +node ane@23c9400000 (its reg is 0x3c9400000, the die-local address). Usage: adt-dt-check-t6032.py ADT DTB [DTB...] @@ -439,7 +446,7 @@ def der_tlv(b, p): # power states the new nodes reference: (soc, pmgr node, offset, what for) REQUIRED_PS = [] for soc in ("soc@200000000", "soc@2200000000"): - sfx = "_die1" if soc.endswith("2000000000") else "" + sfx = "_die1" if soc.endswith("2200000000") else "" for i in range(4): off = {0: 0x4A8, 1: 0x4F8, 2: 0x508, 3: 0x488}[i] REQUIRED_PS.append((soc, "power-management@292800000", off, @@ -473,16 +480,12 @@ def der_tlv(b, p): (0, 1321), } -# nodes that must carry status = "disabled" -MUST_BE_DISABLED = ( - ["gpu", "mbox@40a408000"] - + [f"ane{d}" for d in (0, 1)] - + [f"ane{d}_dart{i}" for d in (0, 1) for i in range(3)] - + [f"dcpext{i}" for i in range(8)] - + [f"dcpext{i}_mbox" for i in range(8)] - + [f"dcpext{i}_dart" for i in range(8)] - + [f"dispext{i}_dart" for i in range(8)] -) +# ADT nodes the DT must keep disabled: GPU and its ASC, both ANE engines and +# their DARTs, the eight external display pipes with their DARTs. The DT +# nodes are found by register window, not by name or label. +GATED_ADT = (["sgx", "gfx-asc", "ane0", "ane1", "dart-ane0", "dart-ane1"] + + [f"{p}{i}" for i in range(8) for p in ("dcpext", "dart-dcpext", "dart-dispext")]) + def main(): args = sys.argv[1:] @@ -553,7 +556,7 @@ def main(): continue check(False, f"{path} ({hex(wins[0][0])}): no ADT node overlaps it") - # 4. power states exist at the ADT address + # 4. power states exist in the DT at the REQUIRED_PS offsets psidx = {} stack = [("", tree)] while stack: @@ -613,13 +616,21 @@ def main(): if carried else f"{name}: ADT interrupts {valid} carried by no DT node") - # 6. disabled gates + # 6. disabled gates: a DT node whose first window starts where a + # window of a gated ADT node starts must be disabled (DARTs: any window) + gw = adt_gated_nodes(root, set(GATED_ADT)) + starts = {ws[0][0] for ws in gw.values() if ws} + starts |= {a for n, ws in gw.items() if n.startswith("dart-") for a, _ in ws} + hit = 0 for path, node, wins in dtnodes: - base = node.name.split("@")[0] - if base in MUST_BE_DISABLED or node.name in MUST_BE_DISABLED: + if wins and wins[0][0] in starts: + hit += 1 st = dt_strings(node.props.get("status", "")) check(st == ["disabled"], f"{path}: disabled" if st == ["disabled"] else f"{path}: status is {st or 'okay'}, must be disabled") + check(hit >= len(gw), f"{hit} DT nodes match the {len(gw)} gated ADT nodes" + if hit >= len(gw) else + f"only {hit} DT nodes match the {len(gw)} gated ADT nodes: a gated node is missing or moved") if failures: print(f"{len(failures)} check(s) failed") diff --git a/.github/workflows/t6032-adt-dt-check.yml b/.github/workflows/t6032-adt-dt-check.yml index 67fceaabd36855..d9ea93ad5b25bd 100644 --- a/.github/workflows/t6032-adt-dt-check.yml +++ b/.github/workflows/t6032-adt-dt-check.yml @@ -16,6 +16,7 @@ on: - "arch/arm64/boot/dts/apple/t6031*" - "arch/arm64/boot/dts/apple/t603x*" - ".github/scripts/adt-dt-check-t6032.py" + - ".github/scripts/adt-dt-check-t6032-mutation.sh" - ".github/workflows/t6032-adt-dt-check.yml" push: paths: @@ -23,6 +24,7 @@ on: - "arch/arm64/boot/dts/apple/t6031*" - "arch/arm64/boot/dts/apple/t603x*" - ".github/scripts/adt-dt-check-t6032.py" + - ".github/scripts/adt-dt-check-t6032-mutation.sh" - ".github/workflows/t6032-adt-dt-check.yml" workflow_dispatch: @@ -35,7 +37,7 @@ jobs: - name: Install toolchain run: | sudo apt-get update - sudo apt-get install -y gcc-aarch64-linux-gnu flex bison + sudo apt-get install -y gcc-aarch64-linux-gnu flex bison device-tree-compiler pip install pyliblzfse - name: Build t6032-j575d.dtb @@ -48,3 +50,7 @@ jobs: run: | python3 .github/scripts/adt-dt-check-t6032.py --fetch-ipsw \ build/arch/arm64/boot/dts/apple/t6032-j575d.dtb + + - name: A gated node switched on must fail the check + run: bash .github/scripts/adt-dt-check-t6032-mutation.sh \ + build/arch/arm64/boot/dts/apple/t6032-j575d.dtb From 042b0f432b97d298fe2b3b506206c8af953a8041 Mon Sep 17 00:00:00 2001 From: Joshua Warren <816217+joshuaswarren@users.noreply.github.com> Date: Sun, 25 Oct 2026 17:28:47 -0500 Subject: [PATCH 6/8] arm64: dts: apple: add the t6032-j575d SD card reader The 27.0.1 ADT of a retail unit names the SD reader on port01 as pci17a0,9755, so the child node can be written. The card-detect and write-protect polarity is taken from the M2 Ultra Studio board; it is not in the ADT. Checked: the dtb builds, the ADT-versus-DT check passes, and the mutation check still flags a gated node switched on. Not checked: any SD card on hardware. Signed-off-by: Joshua Warren <816217+joshuaswarren@users.noreply.github.com> --- arch/arm64/boot/dts/apple/t6032-j575d.dts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/apple/t6032-j575d.dts b/arch/arm64/boot/dts/apple/t6032-j575d.dts index e82e96d4ce2043..880af664a0f01a 100644 --- a/arch/arm64/boot/dts/apple/t6032-j575d.dts +++ b/arch/arm64/boot/dts/apple/t6032-j575d.dts @@ -113,8 +113,8 @@ * xHCI (ASM3142). The pwren numbers are the SMC gPxx key of the ADT * function-reg_on, function-sd_pwr_en and function-power_enable * properties read as hex; the ADT has no power function for port02. The ADT - * has no PCI IDs, so the WLAN, Bluetooth and SD reader child nodes are not - * written here. + * gives the PCI id only for the SD reader, so the WLAN and Bluetooth child + * nodes are not written here. */ &port00 { /* WLAN */ @@ -127,6 +127,13 @@ bus-range = <2 2>; pwren-gpios = <&smc_gpio 25 GPIO_ACTIVE_HIGH>; status = "okay"; + /* The ADT gives the id (pci17a0,9755); the card-detect and write-protect polarity is the M2 Ultra Studio's */ + sdhci0: mmc@0,0 { + compatible = "pci17a0,9755"; + reg = <0x20000 0x0 0x0 0x0 0x0>; + cd-inverted; + wp-inverted; + }; }; &port02 { From 42ed6f93d18c4f722635f3bee6568a303d320ac3 Mon Sep 17 00:00:00 2001 From: Joshua Warren <816217+joshuaswarren@users.noreply.github.com> Date: Sun, 25 Oct 2026 17:43:21 -0500 Subject: [PATCH 7/8] arm64: dts: apple: clarify the SD reader polarity evidence Signed-off-by: Joshua Warren <816217+joshuaswarren@users.noreply.github.com> --- arch/arm64/boot/dts/apple/t6032-j575d.dts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/apple/t6032-j575d.dts b/arch/arm64/boot/dts/apple/t6032-j575d.dts index 880af664a0f01a..5784364d00c405 100644 --- a/arch/arm64/boot/dts/apple/t6032-j575d.dts +++ b/arch/arm64/boot/dts/apple/t6032-j575d.dts @@ -127,7 +127,10 @@ bus-range = <2 2>; pwren-gpios = <&smc_gpio 25 GPIO_ACTIVE_HIGH>; status = "okay"; - /* The ADT gives the id (pci17a0,9755); the card-detect and write-protect polarity is the M2 Ultra Studio's */ + /* + * The ADT gives both polarity properties as 1. The inverted flags below + * are copied from the M2 Ultra Studio; their mapping to 1 is unverified. + */ sdhci0: mmc@0,0 { compatible = "pci17a0,9755"; reg = <0x20000 0x0 0x0 0x0 0x0>; From 25179fbf434a45adc93edf1204c3d9329c3a8a70 Mon Sep 17 00:00:00 2001 From: Joshua Warren <816217+joshuaswarren@users.noreply.github.com> Date: Wed, 4 Nov 2026 15:43:43 -0600 Subject: [PATCH 8/8] ci: make the t6032 ADT-versus-DT workflow pass the CI's own audit The self-test job audits every workflow with zizmor in the pedantic persona, and the new t6032 workflow tripped six findings: an action pinned to a tag instead of a hash, a checkout that keeps the token, default permissions at both the workflow and the job level, a job with no name, and no concurrency setting. The unpinned action is an error, so the audit exited 14 and the self-test failed, which failed the result gate. Give the workflow the same shape as the kernel CI workflows it sits next to: an empty workflow permissions block, a job permissions block that only reads the tree, a named job, a concurrency group that replaces a superseded pull request run, the checkout pinned to the hash the other workflows use with persist-credentials off, and a timeout. The runner is pinned to ubuntu-24.04 so the toolchain does not move under the job. Checked: zizmor 1.31.1 in the pedantic persona reports no findings on .github/workflows, and actionlint 1.7.12 is clean. Not checked: the workflow has never run on CI, because a workflow from a pull request needs a maintainer to approve it first. Signed-off-by: Joshua Warren <816217+joshuaswarren@users.noreply.github.com> --- .github/workflows/t6032-adt-dt-check.yml | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/.github/workflows/t6032-adt-dt-check.yml b/.github/workflows/t6032-adt-dt-check.yml index d9ea93ad5b25bd..e3847f6eb2dcc3 100644 --- a/.github/workflows/t6032-adt-dt-check.yml +++ b/.github/workflows/t6032-adt-dt-check.yml @@ -28,11 +28,25 @@ on: - ".github/workflows/t6032-adt-dt-check.yml" workflow_dispatch: +permissions: {} + +# A new push to a pull request replaces its run; every other run is kept. +concurrency: + group: t6032-adt-dt-check-${{ github.event_name }}-${{ github.event.pull_request.number || github.sha }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + jobs: adt-dt-check: - runs-on: ubuntu-latest + name: adt-dt-check + runs-on: ubuntu-24.04 + timeout-minutes: 45 + permissions: + contents: read # check out the repository steps: - - uses: actions/checkout@v4 + - name: Check out the tree + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false - name: Install toolchain run: |