Skip to content

arm64: dts: apple: fix t6032-j575d against the 27.0.1 ADT; add ADT-vs-DT CI check - #207

Open
joshuaswarren wants to merge 8 commits into
omacom:integration/aurorafrom
joshuaswarren:w7C/t6032-dt-27
Open

joshuaswarren wants to merge 8 commits into
omacom:integration/aurorafrom
joshuaswarren:w7C/t6032-dt-27

Conversation

@joshuaswarren

Copy link
Copy Markdown

Phase 2 of M3 Ultra (Mac Studio 2025, Mac15,14, j575dap, T6032) support: the board description. Draft. Target firmware macOS 27.0.1 (26A434).

What changes

  • USB-C: adds controller 3 at 0x1302280000 (ADT: inside die 0's window, power state ATC3_USB). Deletes the die-1 copy of die-0 port 2 at 0x2f02280000; the ADT has no such port. Ports 4 and 5 stay as die-1 mirrors of ports 0 and 1.
  • Deletes the die-1 USB4 controller that has no ADT entry (0x2f01ac0000).
  • Deletes laptop-only nodes with no ADT entry: MTP keyboard stack, the AOP audio ADMAC and its consumer, i2c3, spi1.
  • Adds GPU, the eight external display pipes (dcpext0..7, mailboxes, DARTs) and both ANE engines (ane0, ane1, three DARTs each), all disabled. The GPU, display and ANE drivers for this chip are separate work.
  • CI check .github/scripts/adt-dt-check-t6032.py (workflow t6032-adt-dt-check): builds the DTB, reads the device tree of the pinned 27.0.1 image from Apple's public IPSW by two HTTP range requests, verifies pinned SHA-256 hashes, and fails when a needed ADT node is not covered, a deleted window returns, a DT node maps nowhere in the ADT, a power state sits at another bank or offset, or the GPU, display or ANE nodes become enabled.

Checked: the fixed tree passes 104 checks; the tree before this change fails 43. The T6030, T6031 and T6034 DTBs still build.

Not shown: that this Mac boots Linux. No M3 Ultra is available to the developers; the ADT is the only reference. Open points are listed in the commit message.

…-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 7b96998. Not pushed.

Signed-off-by: Joshua Warren <816217+joshuaswarren@users.noreply.github.com>
…st 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 7b96998) 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>
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>
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>
@joshuaswarren

Copy link
Copy Markdown
Author

GREEN at df16bdb

Scope: the two new commits, 0bbf34a (PCIe ports, Ethernet, power-enable lines) and df16bdb (console and network config fragment), plus how they sit on the T6031 base the T6032 tree includes. I did not re-review 40ae094 and 05cc2d4 (the CI checker covers those), and I did not run the ADT check, a dtc build or any boot. No boot claim in the texts, which is right.

PCIe commit, checked against the included T6031 nodes (t6031-die0.dtsi at this head):

  • Defaults: port00 and pcie0_dart_0 are enabled by default; port01 to port03 and pcie0_dart_1 to _3 are disabled by default. The DTS enables exactly the other three ports and the three DARTs and leaves port00 and DART 0 alone, so all four ports and their IOMMUs end up on and no DART is referenced by an active port while disabled.
  • Addressing: root bus-range is <0 4>; the ports take <1 1>, <2 2>, <3 3>, <4 4>. The Ethernet child ethernet@0,0 has reg 0x30000, which is bus 3 device 0 function 0, the bus of port02. ethernet0 alias exists. local-mac-address is the usual placeholder for the loader to fill.
  • Power: pwren-gpios point at smc_gpio (a node that exists in the base, apple,smc-gpio under the SMC) with 19, 25 and 22 (hex 0x13, 0x19, 0x16, as the comment says the ADT keys read as hex). port02 has none, which matches "the ADT has no power function for port02". The WLAN, Bluetooth and SD reader children are left out for lack of PCI IDs, so nothing binds a driver to them.
  • Could it hang a console boot? Not from this node set: ports probe through the PCIe driver; a missing SMC GPIO defers the port probe, it does not block the console; the fragment (below) builds the providers in. The ports power on WLAN, SD reader and xHCI through the SMC on the first boot of an untested machine; that is the one new thing a first boot does, and it is limited to the power-enable lines.

Config fragment: every symbol exists in asahi.config as a module (PINCTRL_APPLE_GPIO, MFD_MACSMC, GPIO_MACSMC, APPLE_SART, NVME_APPLE) and the fragment turns them to y, which is what "boot without an initramfs" needs; PCIE_APPLE, APPLE_DART, APPLE_AIC, APPLE_RTKIT and SERIAL_SAMSUNG are already y there. AQTION, USB_XHCI_PCI(_ASMEDIA) and the CDC USB net options are plain additions. GPU, display and ANE stay off. The commit says olddefconfig keeps every symbol; I did not reproduce that.

Not checked, and the reason this is a GREEN for the diff and not a boot claim: the port assignment, the three SMC key values and the PERST pins (pinctrl_ap 4 to 7 come from the T6031 base, not from this commit) against the real ADT of a T6032; the checker and ADT fetch were not run by me.

@joshuaswarren

Copy link
Copy Markdown
Author

Review at df16bdb: commits 1-2 (40ae094a, 05cc2d43). The dtsi content is GREEN. The checker has one real gap (section 6) and two small ones.

What I did. Built the real t6032-j575d.dtb at each commit (cpp + dtc from the sparse tree, dt-bindings from the tree) and ran the checker, as committed, against the pinned 27.0.1 (26A434) j575dap ADT (sha256 matches the pin in the script). Also exercised --fetch-ipsw: both pinned hashes verify and the run passes.

tree result
parent of commit 1 (7b969982) 84 FAIL (fails as it should: the die-1 USB mirrors, MTP, AOP ADMAC, i2c3, SPI-NOR, drd3, interrupts)
commit 1 (40ae094a), head-version checker 30 FAIL (all interrupt checks that commit 2 fixes), commit 1's own checker passes
commit 2, commit 3, head 245 ok, 0 FAIL

dtsi against the ADT, beyond what the checker does.

  • A live ioreg dump of a retail unit (same build) agrees with the pinned ADT for every required node: register words, interrupts and interrupts-valid (one unrelated node, pmgrtools, differs in its interrupt list).
  • The 14 hard-coded PS offsets in REQUIRED_PS are right: I derived each from the ADT pmgr device table (ps-regs bank plus addr_offset << 3) and they match all 14 (DISPEXT0-3_CPU, ATC0-3_USB, ANE_SYS/MPM/CPU/TD/BASE, GFX).
  • The power-domains of the eight display pipes (node, mailbox and both DARTs) and of the six USB-C controllers point at the right pmgr state and the right die (pipes 4-7 and controllers 4-5 are die 1, pipes 0-3 and controllers 0-3 die 0). 0 mismatches.
  • All 41 labelled gated nodes (GPU, ANE and DARTs, eight DCPs, mailboxes and DARTs) are status = "disabled" in the built DTB; the GPU mailbox too.

Findings in adt-dt-check-t6032.py.

  1. Section 6 ("disabled gates") tests 2 of 42 entries. MUST_BE_DISABLED holds DT labels (dcpext0, ane0, ane0_dart0, ...), but the check compares against the node name before the @ (dcp, ane, iommu, gpu, mbox@40a408000), and the kernel does not build these DTBs with -@. Only gpu and mbox@40a408000 ever match; the ANE, all eight DCPs and their DARTs are never looked at, although the docstring promises "the GPU, ANE and display nodes must stay disabled". Mutation test: with ane0 and dcpext0 set to okay the checker prints all checks passed. Suggested fix (tested): match by register window. A DT node is gated when its first window starts where the first window of a gated ADT node starts (for the DARTs, any window). Over the 30 gated ADT nodes this finds 33 DT nodes on the real tree (none enabled) and flags exactly dcp@306c00000 and ane@3c9400000 on the mutated one. Also make "found fewer DT nodes than gated ADT nodes" a FAIL so it cannot go quiet again.
  2. CI will likely not get past the checker step. The workflow installs gcc-aarch64-linux-gnu flex bison but the checker runs dtc from PATH; the kernel build leaves its own copy in build/scripts/dtc/dtc, not on PATH. Add device-tree-compiler to the apt line (or call the built one). The workflow run for this head is waiting for approval, so this has not run on CI.
  3. Small ones. REQUIRED_PS builds its _die1 label suffix with soc.endswith("2000000000"), which is never true for soc@2200000000, so die-1 entries are reported without the suffix (messages only). The docstring says the power states must "exist at the ADT address", but the check compares the DT offset with constants typed in the script; the constants are correct (see above), so a one-line comment would do. In t6032.dtsi the die-1 ANE node is ane@23c9400000 with reg = <0x3 0xc9400000 ...>; dtc warns simple_bus_reg: expected "3c9400000" (every other node uses the same unit address on both dies).

Not run on hardware and not on CI. I did not read the commit 3-4 content again (already GREEN at this head).

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>
@joshuaswarren

Copy link
Copy Markdown
Author

GREEN at b732ee8

Read the diff over df16bdb5 (3 files under .github, no dtsi change) and ran it:

  • Section 6 now finds gated DT nodes by register window and fails when fewer DT nodes match than gated ADT nodes. On the real DTB built at this head against the pinned 26A434 ADT: 33 DT nodes match the 30 gated ADT nodes, 277 ok, 0 FAIL.
  • The CI mutation script, run as the workflow runs it (fdtput from device-tree-compiler, --fetch-ipsw): ane@3c9400000 and dcp@306c00000 set to okay are both flagged, exit 1, mutation detected.
  • The workflow installs device-tree-compiler and runs the mutation step; the die-1 label suffix and the docstring notes (offsets are typed in, ane@23c9400000 warning is expected) are as asked.

Not run on CI (the workflow still needs approval to run) or hardware.

@joshuaswarren
joshuaswarren marked this pull request as ready for review October 25, 2026 22:22
@joshuaswarren

Copy link
Copy Markdown
Author

Ready for review. The device tree and the checker fix (b732ee8) have one review, and the earlier PCIe and ethernet commits have two. Nothing here has booted a Mac.

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>
@greptile-apps

greptile-apps Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] No blocking findings remain, but the three earlier checker gaps are still open.

Findings

  1. P2 Wrong power references pass ▶
  2. P2 Missing DART passes CI ▶
  3. P2 Enabled engine escapes the check ▶

Summary

Updates the T6032 board description against the pinned macOS 27.0.1 ADT.

  • The T6032 tree maps USB-C controller 3 to its ADT address and drops absent devices.
  • The Mac Studio board description now names its built-in PCIe devices.
  • The T6032 tree describes the M3 Ultra GPU while keeping it disabled.
  • The T6032 tree describes eight external display pipes but keeps them disabled.
  • The T6032 tree describes one disabled ANE engine on each die.
  • CI checks the T6032 device tree against Apple's pinned ADT.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  DTS[Board device tree] --> Build[Build DTB]
  IPSW[Pinned Apple firmware] --> Verify[Fetch ADT and verify hashes]
  Build --> Compare[Compare DTB against ADT]
  Verify --> Compare
  Build --> Mutate[Enable two disabled devices in a copy]
  Mutate --> Reject[Check that comparison rejects the copy]
Loading

Reviews (2) · Last reviewed commit: "arm64: dts: apple: clarify the SD reader..." · Reviewed by Greptile

(0x5B8, "td"), (0x5C0, "base")):
REQUIRED_PS.append((soc, "power-management@292280000", off,
f"ps_ane_{nm}{sfx}"))
REQUIRED_PS.append(("soc@2200000000", "power-management@2a0280000", 0x158, "ps_atc3_usb"))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Wrong power references pass

REQUIRED_PS checks ps_atc3_usb on die 1, but the new USB controller and PHY use the die-0 state. The checker also never follows power-domains, so changing those devices to the wrong state still passes while the expected controller nodes remain. Check the die-0 entry and follow each device’s reference before checking its bank and offset.

Comment on lines +534 to +535
hit = any(overlap(w, dw) for _, _, dwins in dtnodes for dw in dwins
for w in wins)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Missing DART passes CI

Required-node coverage accepts any single overlapping window. Removing ane0_dart2 and its iommus entry still leaves the other two DARTs covering dart-ane0 and carrying IRQ 984. Their extra matches also keep the disabled-device count above its minimum. CI therefore misses the loss of one of the three DARTs added here. Check each required DART window separately and add a deletion mutation test.

Comment on lines +625 to +631
for path, node, wins in dtnodes:
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"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Enabled engine escapes the check

The disabled check recognizes an engine only by its first reg window, then checks a shared total instead of each device. Reordering ane0’s first two windows and setting its status to okay skips its status check. The unchanged windows and interrupts still satisfy the other checks, and the extra ANE DART matches cover the lost count. Track each gated device separately and add a mutation that changes register order as well as status.

@joshuaswarren

Copy link
Copy Markdown
Author

Review at 042b0f4: the SD reader node is fine; the commit message is wrong about the ADT.

Diff over b732ee81 is t6032-j575d.dts only. compatible = "pci17a0,9755" and reg = <0x20000 0 0 0 0> match the port01 bus-range = <2 2> and are the same child node the M2 Ultra Studio and the other boards use. The 27.0.1 j575dap ADT has a pcie-sdreader node on that port with gl9755-* properties, so the chip id is the right translation. It does not store the bytes of vendor 0x17a0 or device 0x9755.

Finding: the commit says the card-detect and write-protect polarity "is not in the ADT". Both properties are there, and both values are 1 (card-detect-polarity, write-protect-polarity). The live dump of a retail unit of the same build has the same two properties, also 1. cd-inverted and wp-inverted are copied from the M2 Ultra Studio board and are not checked against that 1. Say that, instead of saying the ADT has no polarity. I did not check whether 1 means inverted.

Not run: the checker again (this hunk adds no gated SoC node), and no SD card on hardware.

Signed-off-by: Joshua Warren <816217+joshuaswarren@users.noreply.github.com>
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>
@joshuaswarren

Copy link
Copy Markdown
Author

[Joshua's agent] The current head needs the required review; the squash commit will correct the SD reader polarity evidence.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant