Skip to content

Apple M6 (T8152) Mac mini base: PMGR, USB2, DART, NVMe, board fragments - #191

Open
joshuaswarren wants to merge 10 commits into
omacom:integration/aurorafrom
joshuaswarren:m6-base
Open

joshuaswarren wants to merge 10 commits into
omacom:integration/aurorafrom
joshuaswarren:m6-base

Conversation

@joshuaswarren

@joshuaswarren joshuaswarren commented Oct 23, 2026 •

Copy link
Copy Markdown

Summary

The first ten commits that run Linux on the Apple M6 (T8152) Mac mini (J873): the bits every later M6 change needs. integration/aurora has the board file t8152-j873g.dts with a RAM-only boot and nothing else for this SoC. This series adds the drivers and nodes that the next M6 changes (USB4, PCIe, display, audio, Wi-Fi) build on.

It is not needed for the release candidate, and there is no rush to review or merge it.

Layers (in commit order)

# Commit What it gives the next changes
1-3 pinctrl compatible, SARTv4 layout, ANS NVMe the root file system on NVMe, the always-on GPIO that releases the USB hub reset
4 PSD service-slot power domains the ATC USB power domains (psd_atc0..3_usb)
5-6 USB2 PHY driver, hub autosuspend quirk the USB2 PHY of the ATC ports; keeps the 05ac:800f hub awake
7 board fragment (GPIO hog, PSD nodes) wires 1-4 into t8152-j873g.dts
8 T8152 Gen3 DART IOMMU for the USB, display, PCIe and audio blocks
9 dwc3-apple T8152 fixed-role USB2 controller USB2 host/peripheral on the ATC ports
10 PMGR domains and USB nodes ps_atc* domains and the four USB controllers' DARTs, PHYs and dwc3 nodes

Commits 1-7 are the series reviewed by hash earlier. Commits 8-10 are the same M6 bring-up code, rebased on current integration/aurora by hand (conflicts in apple-dart.c and dwc3-apple.c).

What was measured

On an M6 Mac mini, with the earlier forms of these changes:

  • Commit 1: the always-on GPIO hog (pin 39) releases the reset of the front-port USB hub, and the hub enumerates.
  • Commits 2-3: the machine boots and runs its root file system from NVMe.
  • Commit 4: the domains register at boot. The power effect is not measured: the slot status reads 0x6 / valid 0x0 before and after on the USB4 slots.
  • Commit 5: front-port USB2 works (the hub and a USB disk enumerate, the disk at 480 Mb/s).
  • Commit 8: the DART of the display controller attaches locked on every boot.

What was not measured

  • This series, rebased on current integration/aurora, was not booted. It was compile-checked: an arm64 clang build with W=1 of the eight touched objects (pinctrl-apple-gpio, sart, nvme apple, pmgr-psd, usb2-t8152, usb core hub, apple-dart, dwc3-apple) and of t8152-j873g.dtb gave return code 0 and 0 warnings on every target. The board file also compiles with plain dtc. check-commits: Signed-off-by on all 10 commits; no checkpatch errors (warnings: long lines, the MAINTAINERS notice).
  • SuperSpeed (USB3) does not train, and USB4 is not part of this series.
  • The board file validates with dt-validate (dtschema 2026.9, run by hand with the schemas of this tree) with 0 messages; the 72 binding examples print one message, in display/apple,dcp-typec-routes.yaml, which this PR does not touch. The kernel's own make dtbs_check / dt_binding_check were not run.

Follow-ups that depend on this series

USB4/Thunderbolt host router, PCIe ports, the ATC Type-C PHY, display, audio and Wi-Fi each come as their own change on top. Pieces that are not here on purpose: the SPMI generation 4 controller and the Type-C port controllers behind it, the SMC changes, and the CIO reset driver.

@joshuaswarren

Copy link
Copy Markdown
Author

Compile receipt (arm64, clang, W=1, a clone of integration/aurora at 42672ed with these ten commits applied in order, defconfig plus olddefconfig, no debug info):

Target rc warnings
drivers/pinctrl/pinctrl-apple-gpio.o 0 0
drivers/soc/apple/sart.o 0 0
drivers/nvme/host/apple.o 0 0
drivers/pmdomain/apple/pmgr-psd.o 0 0
drivers/phy/apple/usb2-t8152.o 0 0
drivers/usb/core/hub.o 0 0
drivers/iommu/apple-dart.o 0 0
drivers/usb/dwc3/dwc3-apple.o 0 0
apple/t8152-j873g.dtb 0 0

Not run: a link of the whole kernel, a boot, dt_binding_check, dtbs_check.

Notes for the reviewer:

  • Commits 8 and 9 (apple-dart.c, dwc3-apple.c) are a hand merge of the M6 bring-up code into the newer files on this branch. They touch the T8152 paths only. dwc3-apple-state.h gains one enum value, DWC3_APPLE_SUSPENDED, which only the T8152 profile uses.
  • The board file is t8152-j873g.dts. Commits 7 and 10 add include lines to it.
  • Known asymmetry in the DART merge: the existing unconditional platform_get_irq in probe stays, so a DART node without an interrupt fails probe with -ENODEV before the T8152 path runs. The T8152 nodes in this series all carry an interrupt.

@joshuaswarren

Copy link
Copy Markdown
Author

Review at 3d03eb3: findings, no GREEN yet. Read from the diff: sart, pinctrl, nvme, hub, pmgr-psd, usb2-t8152, apple-dart and dwc3-apple in full for the added lines; the dts files and the binding files only by grep and file list. Not built, not booted, dt_binding_check and dtbs_check not run (the PR text says the same).

Must fix or answer (a defect in what this PR ships):

  1. apple_dart_pmp_admit() begins with of_machine_is_compatible("apple,j873"). The board file t8152-j873g.dts is compatible with "apple,j873g", "apple,t8152", "apple,arm-platform", so the test is false and the function returns -EINVAL for every PMP DART. Nothing in this PR's device trees uses apple,t8152-pmp-dart (no node, no binding text), so the whole PMP path (pmp_sid6_only, apple_dart_pmp_admit, the ioremap(0x300e00000) and the frozen carveout address 0x105ffdf4000) is dead code here. Either drop it from this PR or use the board compatible and add the node and binding with it.
  2. New compatibles without binding text: apple,t8152-sart (soc/apple sart binding) and apple,t8152-nvme-ans2 (nvme-ans binding) are added to the drivers, but the PR changes no binding for them, and it adds no SART or NVMe node either. The commit text for 2 and 3 says what they give the later changes; add the two binding lines, or move the commits to the series that adds the nodes.

Behaviour changes for other SoCs hidden in M6 commits (say so in the commit text, or split):
3. nvme: devm_reset_control_array_get_exclusive() became ..._optional_exclusive() for every ANS. A board with a missing resets property used to fail the probe loudly; now it continues with no reset. Gate it with a hw flag (the T8152 one) instead.
4. apple-dart: a locked DART now gets force_available (held powered for its lifetime) for every SoC, not only Gen3. The comment names J700; that is a change to a shipped platform inside the "T8152 Gen3 DART" commit.
5. usb hub quirk: HUB_QUIRK_DISABLE_AUTOSUSPEND is keyed on 05ac:800f only. That ID is Apple's, not the VL822's; the constant is named USB_PRODUCT_APPLE_VL822_USB2. State in the commit that every hub with this ID loses autosuspend, or narrow the match.

Please confirm (I did not verify):
6. apple_dart_gen3_late_init() runs under spin_lock_irqsave(&dart->late_lock) from runtime resume and from the IRQ handler and calls apple_dart_read_params, apple_dart_apply_tunables and apple_dart_hw_reset. The comment says none of them sleeps; I did not check hw_reset and invalidate_tlb for a polling helper that sleeps.

Smaller:
7. Debug leftovers in a mainline-bound driver: the gen3_skip module parameter ("probe bisect knob"), a dev_info per consumer in apple_dart_probe_device() (use dev_dbg), and a comment tagged ponytail: in apple_dart_gen3_hw_invalidate_tlb().
8. sart.c: two consecutive blank lines after the SART4 defines and before sart4_get_entry.
9. usb2-t8152.c: magic bits in power_on (BIT(2), BIT(3), BIT(0) | BIT(3) on eusb2) want named defines.

Checked and fine: pmgr-psd.c (slot request, VALID before STATUS, genpd parent order, error unwinding, sleepable power_on documented against the irq-safe DART); sart4 register accessors; pinctrl compatible line; apple_tunable_apply() tolerates a NULL list, so the optional dwc3 lists are safe; the dwc3 fixed-role gating (t8152_usb2) leaves the other compatibles on their old path.

@greptile-apps

greptile-apps Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] The PR appears safe to merge based on the reviewed code; no blocking issue remains.

Summary

Adds the base T8152 support for storage, power domains, GPIO, DART, and fixed-role USB2 on the M6 Mac mini.

  • The T8152 Mac mini can use its ANS controller for NVMe storage.
  • T8152 Gen3 DARTs handle DMA for the Mac mini’s devices.
  • T8152 USB power domains sequence PMGR power before service-slot requests.
  • The T8152 Mac mini brings up its wired ports as fixed-role USB2.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  PMGR["PMGR USB power domains"] --> PSD["PSD service slot"]
  PSD --> DART["USB DARTs"]
  PSD --> PHY["USB2 PHY"]
  PSD --> USB["Fixed-role DWC3 controller"]
  DART --> USB
  PHY --> USB
Loading

Reviews (8) · Last reviewed commit: "arm64: dts: apple: t8152-j873g: Add the ..." · Reviewed by Greptile

Comment thread drivers/usb/dwc3/dwc3-apple.c Resolved
Comment thread drivers/usb/dwc3/dwc3-apple.c Resolved
@joshuaswarren

Copy link
Copy Markdown
Author

New head e27454a38c1a7d88a14a3ad242be2142f72b1184 (still ten commits, same order; force-pushed). Per finding:

  1. PMP DART path: removed. apple_dart_pmp_admit(), pmp_sid6_only, the apple,t8152-pmp-dart check, the 0x300e00000 mapping and the carveout address are gone from the DART commit. The non-PMP branches are unchanged. It can come back with its node and binding in a later change.
  2. Bindings: added. apple,t8152-sart is a stand-alone entry in iommu/apple,sart.yaml (SART commit). apple,t8152-nvme-ans2 is a stand-alone entry in nvme/apple,nvme-ans.yaml (NVMe commit), with three register regions and no required resets, power-domains or power-domain-names for it. No SART or NVMe node is in this PR; those nodes come in a later change. dt_binding_check was not run (no dtschema on my host), so please run it in CI.
  3. nvme reset: gated. The probe uses devm_reset_control_array_get_exclusive() again for every SoC. Only the T8152 hardware block has no_reset_control and skips the lookup.
  4. Locked DARTs: gated. force_available from the locked state now applies only when dart->hw->gen3. The comment names no other platform.
  5. Hub quirk: text. The constant is now USB_PRODUCT_APPLE_HUB_800F, and the commit message says that every hub with this ID loses autosuspend. I did not narrow the match: the ID is the only thing I measured.
  6. Sleep under the spinlock: checked by reading. apple_dart_gen3_late_init() under late_lock calls apple_dart_read_params, apple_dart_apply_tunables and apple_dart_hw_reset. Their callees are register reads and writes, dev_dbg, and read_poll_timeout_atomic in the TLB range command. No readl_poll_timeout, usleep_range, msleep, mutex, allocation or ioremap is reachable. The lock order is late_lock then lock only. This is a reading, not a run.
  7. Debug leftovers: removed. The gen3_skip module parameter and all its uses are gone, the per-consumer dev_info in apple_dart_probe_device() is a dev_dbg, and the tagged comment is replaced by a plain sentence.
  8. sart.c: the double blank line is removed.
  9. usb2-t8152.c: the bits in power_on have defines (USB2_VBUS_HOST_BIT2, USB2_VBUS_HOST_BIT3, EUSB2_HOST_ENABLE), named by position because their function is not documented.

Compile receipt for the new head (arm64 clang, W=1): the eight objects and apple/t8152-j873g.dtb all rc 0, 0 warnings. check-commits: Signed-off-by and clean checkpatch on all ten commits. #192 and #193 are rebased on this head too.

@joshuaswarren

Copy link
Copy Markdown
Author

Review at e27454a: findings (not GREEN)

Second review at this head, on top of the review and the bot findings above. The fixes listed in the last owner comment are in the diff and read correctly (items 1 to 9 there): the PMP DART path and gen3_skip are gone, force_available for locked DARTs is gated on hw->gen3, the NVMe reset lookup is gated by no_reset_control, and the SART and NVMe bindings are added. The NVMe conditionals read correctly: reg and reg-names need three entries for apple,t8152-nvme-ans2, and resets, power-domains and power-domain-names are required for every other compatible.

Checked at this head

  • dt-doc-validate (dtschema 2026.9) on the seven binding files the PR adds or changes: return code 0 for all. Its only message is the $id path note that comes from checking the files outside a kernel tree.
  • All ten commits carry a Signed-off-by.

Defects still in the diff (read from the head, not booted)

  1. dwc3_apple_exit(), DWC3_APPLE_HOST case: the new break sits before appledwc->state = DWC3_APPLE_NO_CABLE;, which now belongs only to the DWC3_APPLE_SUSPENDED case. After dwc3_host_exit() the state stays DWC3_APPLE_HOST, and dwc3_apple_core_stop() does not reset it. The next exit calls dwc3_host_exit() again. Restore the assignment in the host case. The bot finding says the same.
  2. dwc3_apple_suspend() and dwc3_apple_resume() cannot run. dwc3_apple_core_start() and dwc3_apple_init() call dev_pm_syscore_device(dev, true), and drivers/base/power/main.c skips a syscore device's callbacks in the suspend, late, noirq and matching resume phases. When state == fixed, which is the only state the callbacks act on, the device is always syscore. Keep the core powered another way, or drop the sleep code and DWC3_APPLE_SUSPENDED from this series.
  3. The required: lists of apple,t8152-dwc3 and apple,t8152-usb2-phy name the apple,tunable-* properties, while the binding text and the board files say the boot loader adds them. The committed t8152-j873g.dtb then fails dtbs_check for every USB node by design. Take them out of required, or say in the commit that the failure is expected. This is from reading: I did not run dtbs_check.
  4. apple,t8152-dwc3 allows two iommus entries and every node supplies four. The PHY binding's oneOf rejects a node that has both host and device calibration. Both agree with the bot findings.
  5. Dead state in the DART commit: has_static_enabled and the static_enabled bitmap are filled from apple,enabled-streams and never read in this series. apple,enabled-streams and apple,force-available are read by the driver and are in no binding (additionalProperties: false). Remove them, or add the property text and the consumer.
  6. apple,t8152-pmgr and apple,t8152-pmgr-pwrstate are used by t8152-j873-pmgr.dtsi and are in no binding. Checkpatch flags each use (184 UNDOCUMENTED_DT_STRING lines in commit 10).
  7. The owner comment says check-commits shows a clean checkpatch on all ten commits. I ran scripts/checkpatch.pl --terse --showfile --show-types --no-summary on each commit as tools/aurora-ci/check-commits.py does. Every commit has at least one warning: DT_SPLIT_BINDING_PATCH (commits 1 to 5, 8, 9), FILE_PATH_CHANGES (4, 5, 7, 9, 10), LONG_LINE or LONG_LINE_COMMENT (3, 4, 7, 8, 9, 10), BLOCK_COMMENT_STYLE (3, 9, 10), MSLEEP and CONFIG_DESCRIPTION (5), LEADING_SPACE (6), UNDOCUMENTED_DT_STRING (10). The job does not fail on warnings, but "no errors" is accurate and "clean" is not. I read the patches from the API patch endpoint and ran checkpatch without the Documentation/ tree, so I left out UNDOCUMENTED_DT_STRING except where I name it.
  8. PHY_APPLE_T8152_USB2 has no default and is off in defconfig. A defconfig kernel has no USB2 PHY and dwc3-apple defers its probe for ever. Add default ARCH_APPLE, or state in the PR text that the option must be set.

Not checked

No compile at this head (I built the previous head, which matched its receipt), no boot, no dt_binding_check or dtbs_check, no lockdep, sparse or KUnit run.

@joshuaswarren

Copy link
Copy Markdown
Author

Review at e27454a: findings (read only; nothing built or booted by me, no dt_binding_check or dtbs_check run).

Checked and fine:

  • DART: the PMP path and gen3_skip are gone (no match for either in apple-dart.c at this head). force_available is set from the locked state only under dart->hw->gen3. The first-use chain apple_dart_gen3_ensure_ready() -> late init -> apple_dart_read_params, apple_dart_apply_tunables, apple_dart_hw_reset: the only polls in the file are read_poll_timeout_atomic; no sleep, mutex or allocation is reachable (the kzalloc and devm_memremap calls sit in the locked-DART snapshot path, which late init refuses before it gets there). Lock order is late_lock then lock; every dart->lock user is irqsave; none of the three callers (resume, attach, fault IRQ) holds dart->lock.
  • nvme: no_reset_control skips only the lookup; reset_control_assert() and reset_control_deassert() are no-ops on NULL. Every use of the five relocated registers and LSQ_CTRL in reset_work goes through apple_nvme_reg(); every other access keeps its offset (the default branch of the map).
  • SART binding: stand-alone apple,t8152-sart entry, fine. Hub constant rename and the commit text: fine. usb2-t8152.c defines: fine.

Findings:

  1. nvme binding and driver disagree on the register regions. apple_nvme_t8152_hw has has_separate_nvmmu = false, so the driver maps nvme and ans only and uses mmio_nvme for the NVMMU. The binding adds apple,t8152-nvme-ans2 to the clause that requires reg and reg-names minItems: 3 (the T8132 separate-NVMMU region). A node written to the driver (two regions) fails the schema, and a three-region node carries a region the driver never uses. Give T8152 its own clause with exactly two regions.
  2. apple,force-available and apple,enabled-streams are read in apple_dart_probe() but are not in apple,dart.yaml, and no node in this PR uses either. has_static_enabled and static_enabled are only written, never read, so the apple,enabled-streams parsing has no effect. Remove it, or document the properties and use the bitmap.
  3. apple,dart.yaml now allows reg maxItems: 2 for every compatible, but only apple,t8152-dart uses the second entry (the probe fails without it). Add a clause: t8152 requires two reg entries, the others keep one.
  4. apple_dart_set_static_params() assumes a 16 KiB page size and 0x0300 and the comment on it says the first resume re-reads the real parameters and re-validates. apple_dart_gen3_late_init() rechecks only the stream count and the DMA range; the page size read from PARAMS1 is not compared with the 16 KiB assumed at probe. Return an error if it differs.
  5. The TLBI doorbell is mapped with devm_ioremap() (Device-nGnRE) while the tunneled DARTs use ioremap_np(), and the comment in probe explains why the posted mapping bit them. A short comment saying why a posted store is acceptable here (or ioremap_np()) would answer the question a later reader will ask.
  6. Nit: dart->locked is computed twice in probe (apple_dart_is_locked() read before the force_available check, then again after it).

Not checked: the remaining files of the PR (sart.c body, dwc3-apple, pmgr-psd, pinctrl, the DTS files), and any behaviour on hardware.

@joshuaswarren

Copy link
Copy Markdown
Author

New head c9d88a5d8fb390d8b61f5d2154f456aa81edfc78 (ten commits, force-pushed). Per finding of the re-review (issuecomment-6369807714):

  1. nvme binding: two regions. apple,t8152-nvme-ans2 is out of the clause that asks for three regions; the T8152 node has nvme and ans, as the driver maps them (has_separate_nvmmu = false). The commit message says so.
  2. apple,force-available and apple,enabled-streams: removed. No node used either. The apple,enabled-streams parsing and the has_static_enabled / static_enabled fields are gone. The force_available field stays, set only by the Gen3 locked-DART rule.
  3. reg of the DART binding. An allOf clause: apple,t8152-dart requires two reg entries, every other compatible keeps one.
  4. Page size at first use. apple_dart_gen3_late_init() now compares the page size read from PARAMS1 with the 16 KiB assumed at probe and fails with -EINVAL if it differs.
  5. TLBI doorbell mapping. A comment says why devm_ioremap() is used: the on-SoC DARTs use the normal Device mapping and only the tunneled ones need ioremap_np(); each doorbell store is followed by dsb ish, the TLBI and dsb osh, the vendor sequence. That is read from the code and the vendor sequence in the comment above it, not shown by a hardware test.
  6. dart->locked computed twice. Now once, after the tunneled override. The Gen3 force_available rule runs after it.

Compile receipt for the new head: arm64 clang W=1, the eight objects and apple/t8152-j873g.dtb, all rc 0, 0 warnings (offload-build, checkC.log). check-commits: Signed-off-by and clean checkpatch on all ten commits. Still not run: dt_binding_check, dtbs_check, a boot.

@joshuaswarren

Copy link
Copy Markdown
Author

Review at c9d88a5: findings (not GREEN)

Third pass, on the force-pushed head. I compared the old and new diff, ran the schema checks by hand, and re-checked each item of my earlier comment.

A correction of my own

My comment on the previous head said the NVMe conditionals "read correctly". That was wrong: the binding put apple,t8152-nvme-ans2 in the three-region clause while apple_nvme_t8152_hw has has_separate_nvmmu = false and maps two regions. The other review found it. At this head T8152 has no clause of its own and falls under the two-region else, and I tested it: a minimal apple,t8152-nvme-ans2 node with two regions and no resets or power-domains raises no reg, reg-names or required message, and the same node with three regions is rejected (reg ... is too long).

Fixed since the previous head (checked)

  • apple,enabled-streams, apple,force-available, has_static_enabled and static_enabled are gone from apple-dart.c.
  • apple,dart.yaml has the clause that gives only apple,t8152-dart a second reg entry. No iommu@... node of the board file produces a message.
  • The page-size check in apple_dart_gen3_late_init() and the comment on the doorbell mapping are in the diff.

dtbs_check by hand at this head

cpp and dtc -@ on t8152-j873g.dts (no warnings), then dt-validate (dtschema 2026.9) against the schema of this tree: 460 lines. The examples of apple,dart, apple,sart, apple,nvme-ans, apple,t8152-psd, apple,t8152-dwc3, apple,t8152-usb2-phy and apple,pinctrl validate without a message. The board file does not:

  • apple,t8152-dwc3, four nodes: iommus is too long (the binding allows two, each node has four), and each lacks the eight required apple,tunable-* properties that the boot loader adds.
  • apple,t8152-usb2-phy, four nodes: apple,tunable-usb2phy-dflt is required, and oneOf fails because neither the host nor the device calibration is present.
  • The two apple,t8152-pmgr nodes and the 35 apple,t8152-pmgr-pwrstate nodes fail the compatible oneOf: no binding lists the T8152 strings.
  • vl822-reset-n: the node name does not match -hog(-[0-9]+)?$, and apple,pinctrl.yaml rejects the child (does not match any of the regexes: '-pins$', '^pinctrl-[0-9]+$'). Rename it vl822-reset-n-hog and let the pinctrl binding take hog children.

Still in the diff (read, not booted)

  1. dwc3_apple_exit(), host case: the break now ends the case before appledwc->state = DWC3_APPLE_NO_CABLE;, so the state stays DWC3_APPLE_HOST after dwc3_host_exit(). Restore the assignment in the host case.
  2. dwc3_apple_suspend() and dwc3_apple_resume() cannot run: the device is a syscore device whenever state == fixed, and the PM core skips the callbacks of a syscore device in every suspend and resume phase.
  3. The dtbs results above for the dwc3 and PHY required: lists, the iommus count and the PMGR compatibles. For the first, either take the apple,tunable-* entries out of required: or say in the commit that the failure is expected.
  4. PHY_APPLE_T8152_USB2 has no default and is off in defconfig, so a defconfig kernel has no USB2 PHY.
  5. The PR text says check-commits shows a clean checkpatch on all ten commits. It reports warnings on every commit (no errors); the types are in my earlier comment.

Not checked

No compile at this head (I did not reproduce the receipt), no boot, no lockdep, sparse or KUnit run.

Comment thread drivers/usb/dwc3/dwc3-apple.c Resolved
The T8152 GPIO block has the same layout as the T8140 one. Match
"apple,t8152-pinctrl" with the T8140 hardware data.

Signed-off-by: Joshua Warren <816217+joshuaswarren@users.noreply.github.com>
T8152 has a SART with a new register layout: the per-entry config,
physical address and size registers sit at 0x00, 0x60 and 0xc0. Add the
operations for it and match "apple,t8152-sart". The binding lists the
new compatible as a stand-alone entry.

Measured on an M6 Mac mini with an earlier form of this change: the
machine boots and runs its root file system from NVMe, which uses this
SART. This version is compile-checked only.

Signed-off-by: Joshua Warren <816217+joshuaswarren@users.noreply.github.com>
On T8152 the queue setup registers (admin queue, IO queues, the linear
submission queue control) live at different offsets, and a few of them
accept writes but read back zero. Add a register translation for that
layout, skip the read-back checks that cannot work, and describe the
controller with a new hardware data block matched by
"apple,t8152-nvme-ans2".

The ANS is a virtual PMGR device on this SoC and has no reset line, so
the hardware data block carries a no_reset_control flag. Only T8152 skips
the reset lookup. Every other SoC still requires a reset control and
fails the probe without one, as before.

The binding gets the new compatible. On T8152 the resets, power-domains
and power-domain-names properties are not required, and the controller
has two register regions (the NVMMU registers live in the first one).

Measured on an M6 Mac mini with an earlier form of this change: the
machine boots and runs its root file system from NVMe. This version is
compile-checked only.

Signed-off-by: Joshua Warren <816217+joshuaswarren@users.noreply.github.com>
@joshuaswarren

Copy link
Copy Markdown
Author

GREEN at c9d88a5. Read only: nothing built or booted by me, no dt_binding_check or dtbs_check run. I re-checked my six findings against the files at this head:

  1. apple,nvme-ans.yaml: only apple,t8132-nvme-ans2 requires three reg entries; every other compatible, T8152 included, is limited to two, matching has_separate_nvmmu = false. The resets and power-domains requirement is skipped for T8152.
  2. apple-dart.c: apple,force-available and apple,enabled-streams are no longer read, and has_static_enabled and static_enabled are gone. The force_available field is now set only internally for a locked Gen3 DART.
  3. apple,dart.yaml: an allOf clause requires two reg entries for apple,t8152-dart and allows one for the others.
  4. apple_dart_gen3_late_init() now compares the page size read from the device with the one assumed at probe and returns an error if they differ.
  5. The TLBI doorbell mapping has a comment saying why the normal Device mapping is used and which sequence follows each store.
  6. dart->locked is computed once in probe; the remaining second apple_dart_is_locked() call is the separate read before the tunables on a non-static Gen3 DART.

Not checked: the files of this PR other than the ones above, and any behaviour on hardware.

@joshuaswarren

Copy link
Copy Markdown
Author

New head 9af182774f886303e4c85497549f64498551dd03 (still ten commits, force-pushed). Per finding of the review at c9d88a5 (issuecomment-6370488475), thank you for the schema runs:

  • Host-exit state bug: fixed. The DWC3_APPLE_HOST case of dwc3_apple_exit() sets state = DWC3_APPLE_NO_CABLE again, as in the original.
  • Unreachable suspend/resume: removed. You are right, a syscore device skips the callbacks. dwc3_apple_suspend(), dwc3_apple_resume(), the PM ops, the DWC3_APPLE_SUSPENDED state and its two case labels are gone, and dwc3-apple-state.h is back to the original. The commit message no longer mentions sleep.
  • Missing T8152 PMGR bindings: added. apple,t8152-pmgr in apple,pmgr.yaml and apple,t8152-pmgr-pwrstate in apple,pmgr-pwrstate.yaml, in the t8103 fallback clauses.
  • dwc3 iommus and tunables. iommus allows two to four entries. The eight apple,tunable-* properties are no longer required, because the boot loader adds them at runtime; the commit message says so.
  • usb2-phy tunables. apple,tunable-usb2phy-dflt and the host/dev oneOf are no longer required, for the same reason.
  • Hog. Renamed vl822-reset-n-hog; apple,pinctrl.yaml takes ^.+-hog(-[0-9]+)?$ children that carry gpio-hog.
  • PHY_APPLE_T8152_USB2 default. It now defaults to ARCH_APPLE, like APPLE_PMGR_PSD.
  • Checkpatch text. You are right: check-commits reports warnings. The PR text now says "no checkpatch errors; warnings are long lines and the MAINTAINERS notice", not "clean".

dtbs_check with your script (dtcheck.sh, dtschema 2026.9) on this exact head: cpp rc 0, dtc -@ rc 0 with 0 warning lines, dt-validate of t8152-j873g.dts rc 0 with 0 lines. The 72 binding examples print one message, display/apple,dcp-typec-routes.yaml, which is in the baseline on any tree. Compile check at this head, arm64 clang W=1: the eight objects and t8152-j873g.dtb, all rc 0, 0 warnings. The first run after removing the suspend code showed unused variable 'fixed' in dwc3_apple_exit(); that is fixed in this head. Not run: a boot, the kernel's own make dtbs_check.

@joshuaswarren

Copy link
Copy Markdown
Author

GREEN at 9af1827. Read only: nothing built or booted by me, and I did not rerun dtbs_check (I rely on the run reported in the PR text for that). I checked the changes listed in the latest comment in the files at this head:

  • dwc3-apple.c: the DWC3_APPLE_HOST case of dwc3_apple_exit() sets the state to DWC3_APPLE_NO_CABLE again, next to the DWC3_APPLE_DEVICE case; all four enum values are handled. No dwc3_apple_suspend(), dwc3_apple_resume(), PM ops or SUSPENDED state remain (grep), and dwc3-apple-state.h has only the four original states and the USB2 mode helper.
  • apple,pmgr.yaml and apple,pmgr-pwrstate.yaml: apple,t8152-pmgr and apple,t8152-pmgr-pwrstate are in the apple,t8103-* fallback clauses.
  • apple,t8152-dwc3.yaml: iommus takes two to four entries; the apple,tunable-* pattern property remains and the required list no longer holds the tunables.
  • apple,pinctrl.yaml: the ^.+-hog(-[0-9]+)?$ child pattern requires gpio-hog.
  • PHY_APPLE_T8152_USB2 has default ARCH_APPLE.
  • My earlier findings (nvme regs, DART binding and parameters, page-size recheck, doorbell comment) are unchanged at this head: the DART file still has the page-size check in the first-use init.

The usb2-phy binding's required list is now compatible, reg, reg-names, #phy-cells, power-domains and power-domain-names; I did not check how its tunable oneOf is written. Not checked: anything on hardware.

Comment thread drivers/iommu/apple-dart.c Resolved
@joshuaswarren

Copy link
Copy Markdown
Author

GREEN at 9af1827

Fourth pass, on the force-pushed head. I compared this PR diff with the one I reviewed at c9d88a5d and re-checked each finding of my earlier comments.

Findings of my earlier comments, checked at this head

  • Host exit: the DWC3_APPLE_HOST case of dwc3_apple_exit() is back to the original (the added break is gone), so the state returns to DWC3_APPLE_NO_CABLE.
  • Suspend and resume: dwc3_apple_suspend(), dwc3_apple_resume(), the PM ops, DWC3_APPLE_SUSPENDED and its two case labels are removed, and dwc3-apple-state.h has no change left in the PR.
  • Bindings: apple,t8152-pmgr and apple,t8152-pmgr-pwrstate are in the t8103 fallback clauses of apple,pmgr.yaml and apple,pmgr-pwrstate.yaml. apple,t8152-dwc3 allows two to four iommus, and the dwc3 and USB2 PHY apple,tunable-* entries are out of required:. The driver still needs the dwc3 lists and the default PHY list and fails the probe without them; the boot loader supplies them, as the commit text says.
  • vl822-reset-n-hog and the ^.+-hog(-[0-9]+)?$ child pattern in apple,pinctrl.yaml are in. PHY_APPLE_T8152_USB2 defaults to ARCH_APPLE. The PR text says "no checkpatch errors" and lists the warning types, which matches my run.

dtbs_check by hand at this head

dtcheck.sh (dtschema 2026.9) on a tree with this head's t8152-j873g.dts and bindings: cpp rc 0, dtc -@ rc 0 with no warning, dt-validate of the board file rc 0 with 0 lines. The binding examples of the files this PR changes validate without a message; display/apple,dcp-typec-routes.yaml prints one, as at the base. (My tree also held the apple,t8152-atcphy.yaml of #192, which prints its own message; it is not part of this PR.)

Not checked

No compile at this head (I did not reproduce the receipt), no boot, no lockdep, sparse or KUnit run, and not the kernel's own make dtbs_check.

@joshuaswarren

Copy link
Copy Markdown
Author

Summary for a maintainer, at head 9af182774f886303e4c85497549f64498551dd03:

  • Reviews by exact head: GREEN from w7Q (issuecomment-6372793842) and from w7X (issuecomment-6373045714); both read the diff and the findings of earlier heads, and both list what they did not check (no boot, no hardware).
  • Compile: arm64 clang W=1, the eight touched objects and apple/t8152-j873g.dtb, rc 0 and 0 warnings (first comment of this PR has the table; this head was re-run, offload-build checkC.log).
  • dt-validate of t8152-j873g.dts by hand (dtschema 2026.9), run by w7X and by me: 0 messages. The kernel's own make dtbs_check and dt_binding_check were not run.
  • Not booted. Measured on an M6 Mac mini only with earlier forms of the changes (stated per commit).
  • Not needed for the release candidate. Apple M6 (T8152) Mac mini boot NOR (QSPI): binding and device tree (on top of #191) #193 and Apple M6 (T8152) audio plumbing: ADMAC and AOP hardware config (on top of #191) #194 are separate PRs whose first ten commits are this PR.

@joshuaswarren

Copy link
Copy Markdown
Author

New head b8943e8ae7ad5a17f27bc8acf35d712d57cbe407 (rebased on the same base as the other M6 PRs, plus the fixes for the Greptile and reviewer findings; every Greptile thread of the previous heads has a reply with the commit and is resolved).

Receipts at this head (CT-local, arm64 clang W=1, 16K pages, PCIE_APPLE=m, USB4_APPLE_SOC=m): the eight touched objects and apple/t8152-j873g.dtb, rc 0, 0 warnings. dtcheck.sh (dtschema 2026.9) on the board file: dtc -@ 0 warning lines, dt-validate 0 lines, the binding examples print only the baseline message of display/apple,dcp-typec-routes.yaml. Changes since the last GREEN: a failing phy_init() or phy_power_on() in dwc3_apple_core_start() now goes through dwc3_apple_core_stop(); the PSD parents (ps_atcN_usb_aon, ps_atcN_usb); iommus exactly four; the host-only lists skipped for a fixed peripheral; the Gen3 doorbell guarded for non-arm64 builds; a locked Gen3 DART no longer takes the range flush through TLB_CMD; the PSD group power-off restores the stopped slots. Not run: a boot, the kernel's own make dtbs_check.

@joshuaswarren

Copy link
Copy Markdown
Author

GREEN at b8943e8

Read: the ten commits of this head against the ten I reviewed at 9af1827, compared per commit as diffs with the hash lines removed. Six commits are identical (pinctrl, SART, NVMe, USB2 PHY, hub quirk, peripherals dts). The four that changed:

  • PSD (pmgr-psd.c): a group power-off now remembers which slots stopped and, if any slot failed to stop, puts the stopped ones back to their active state (genpd keeps the domain marked on after a failed power-off). Correct: the bit set is only for slots whose request was acknowledged, nslots is at most 3.
  • DART: the Gen3 doorbell/TLBI helper is guarded by CONFIG_ARM64 with a -EOPNOTSUPP stub for COMPILE_TEST builds, and a locked Gen3 DART no longer takes the T8110 range-flush path (!hw->gen3 added to the condition); everything else is hunk-offset changes.
  • dwc3: host-only tunable lists are skipped for a fixed peripheral; the two PHY-init failure returns in core_start go through a new err_stop label that calls core_stop; the binding now requires four iommus (minItems 4).
  • dts: the four PSD USB service slots get their PMGR parents (psd_atcN_usb gets ps_atcN_usb_aon and ps_atcN_usb), matching the genpd-parent model in pmgr-psd.c.
    Not run: build; the author's compile and dt receipts are not reproduced. Merge still needs CI and a second non-author GREEN.

Comment thread drivers/pmdomain/apple/pmgr-psd.c Resolved
On T8152 the ATC USB blocks (and the GPU) are behind a per-slot service
request in the power state director, on top of the normal PMGR power
states. Expose each slot, or a group of slots that must come up together,
as a generic power domain. Power-on writes the slot request and waits for
the acknowledge; power-off requests state 6 in reverse order.

Add the devicetree binding.

When a power-on request times out, the slot that timed out is put back to idle with the slots before it, because its acknowledge was not seen but it may still start.

When a group power-off fails, every slot is put back to its active state, including a slot whose off request timed out and may still finish stopping, because genpd keeps the domain marked on after a failed power-off and would skip power_on at the next resume.

Signed-off-by: Joshua Warren <816217+joshuaswarren@users.noreply.github.com>
The fixed host ports on T8152 need only the USB2 part of the PHY. Add a
driver that applies the bootloader-supplied calibration, handles host and
device mode, and leaves the USB3 and USB4 lanes alone.

Add the devicetree binding.

Signed-off-by: Joshua Warren <816217+joshuaswarren@users.noreply.github.com>
A hub with the Apple ID 05ac:800f sits behind the front ports of the M6
Mac mini. Add that ID to the hub quirk table with
HUB_QUIRK_DISABLE_AUTOSUSPEND so the kernel keeps it powered.

The match is on the vendor and product ID alone. Every hub with this ID
loses autosuspend, not only the one on this machine. The constant is
named after the ID, USB_PRODUCT_APPLE_HUB_800F, because the ID is
Apple's and the part behind it was not identified from the descriptor.

This quirk was not measured on its own: it only keeps the hub awake.

Signed-off-by: Joshua Warren <816217+joshuaswarren@users.noreply.github.com>
Add a peripherals fragment to the M6 Mac mini board file: the always-on
GPIO controller with the reset hog for the front-port USB hub, and the
four PSD service slots for the USB ports.

The NVMe controller, its mailbox and its address filter are not described
here. The NVMe node needs a mailbox driver change that is not in this
tree yet.

The fragment holds only addresses, interrupt numbers and wiring. The boot
loader adds the register tunables that some blocks need. The PMGR power
domains are not described yet, so nodes that need them are left out.

Signed-off-by: Joshua Warren <816217+joshuaswarren@users.noreply.github.com>
Add the DART of the Apple M6 (T8152), a third-generation DART whose
topology is fixed by the hardware. Its streams are described by static
parameters instead of being probed, and it takes no MMIO access until the
first use, because the block can be power gated behind the ATC USB
domains.

The binding requires a second register region (the TLB invalidate
doorbell) for the T8152 compatible only.

The change adds:
- the apple,t8152-dart compatible and its hardware description;
- static topology and "first use" initialisation of every DART;
- the Gen3 TLB invalidate and the fault handler;
- the reset path for DARTs that the boot loader leaves locked.

A DART that the boot loader leaves locked is held powered for its
lifetime. That applies to Gen3 hardware only. The other generations keep
their behaviour. The first-use initialisation re-reads the parameters and fails if the
page size differs from the one assumed at probe. It runs under a spinlock, and
every function it calls is non-sleeping (register accesses and an atomic
poll).

Measured on an M6 Mac mini with the earlier form of this change: the
display controller DART attaches locked on every boot. This version is
rebased on current integration/aurora and was compile-checked only. The
USB DART paths need the T8152 PSD power domains and were not run on
their own.

The doorbell store and the TLBI of the Gen3 invalidate are arm64 instructions: they are built only with CONFIG_ARM64, and other architectures (COMPILE_TEST) get a stub that returns -EOPNOTSUPP. A locked Gen3 DART no longer takes the range flush through TLB_CMD, which Gen3 does not accept; it uses the full-stream Gen3 callback.

Gen3 does not take commands through TLB_CMD, so the unlock after a lock-on-error exception is not sent there: the DART logs once that this is not supported. The stale-exception drain of a reset does not read 0x704 on Gen3, like the fault handler.

Signed-off-by: Joshua Warren <816217+joshuaswarren@users.noreply.github.com>
Add the apple,t8152-dwc3 compatible to the Apple dwc3 glue. The ATC ports
of the M6 (T8152) controller never switch roles through the Type-C
controller. The glue starts the controller as a fixed host, with or
without a hub child, or as a fixed peripheral when the node sets
dr_mode = "peripheral".

The T8152 profile is USB2 only: it needs maximum-speed = "high-speed",
takes no reset line, and its USB3 PHY is optional. The calibration lists
come from the device tree (apple,tunable-* properties that the boot loader
fills in at runtime; the binding does not require them in the board file) and are applied to the register windows in a fixed order after
the core is reset. The pipe handler is set up for the selected role.

The apple,t8103-dwc3 paths keep their behaviour. The controller stays a
syscore device while it runs, as before: no separate suspend or resume
path is added for T8152.

The earlier form of this change ran on an M6 Mac mini USB2 front port.
This version is rebased on current integration/aurora and was
compile-checked only. SuperSpeed does not train yet and is not part of
this change.

A fixed peripheral does not require the host-only calibration lists at probe, since it never applies them. The binding lists exactly four iommus entries, two stream IDs on each of two DARTs.

If the T8152 USB2 PHY fails to initialise or power on during core start, the failure goes through the same shutdown as a failed core init, so the reset and syscore flags set earlier are cleared again.

Signed-off-by: Joshua Warren <816217+joshuaswarren@users.noreply.github.com>
Describe the power management blocks and the USB controllers of the Mac
mini (M6, J873) next to the peripherals fragment:
- the two PMGR blocks and their power domains, in t8152-j873-pmgr.dtsi;
- for each of the four USB ports (usb0, usb1, usb2 and usb3 of the SoC):
  two DART instances, the USB2 PHY and the dwc3 controller.

The register windows, interrupts and DART tunables are the values of the
Apple device tree of the machine. The boot loader adds the apple,tunable-*
lists of the USB2 PHY and the controller at runtime.

The bindings list the apple,t8152-pmgr and apple,t8152-pmgr-pwrstate
compatibles, and the dwc3 and USB2 PHY bindings take the tunable lists as
optional, because the boot loader adds them.

The fragment is a plain description of the hardware. The ports that the
change describes run USB2 only: SuperSpeed and USB4 are not part of it.

This commit compiles to a device tree blob with dtc without warnings. It
was not booted. The bring-up it comes from enumerated the front-port USB2
hub and a USB disk at 480 Mb/s.

The four PSD service slots get their PMGR domains (the aon and the port domain of their port) as parents, so genpd powers them before the slot request.

Signed-off-by: Joshua Warren <816217+joshuaswarren@users.noreply.github.com>
@joshuaswarren

Copy link
Copy Markdown
Author

GREEN at 3c57b1d

Compared the ten commits with the ones I cleared at 9af18277, as diffs with the hash lines removed. Six are identical; four changed (PSD domains, Gen3 DART, dwc3, board nodes).

Checked

  • PSD power domains. A failed group power-off now puts every slot back to its active state, including a slot whose off request timed out and may still finish stopping, because genpd keeps the domain marked on and would skip power_on on the next resume. The loop is best effort and the first error is still returned.
  • Gen3 DART.
    • The doorbell store and the TLBI are built only with CONFIG_ARM64; other architectures get a stub that returns -EOPNOTSUPP.
    • A locked Gen3 DART no longer takes the TLB_CMD range flush (!dart->hw->gen3 in apple_dart_domain_flush_tlb_range).
    • The lock-on-error unlock is not sent to Gen3 (it logs once), and the stale-exception drain skips the BLOCK_ERROR read, which is not in the Gen3 capture list.
  • dwc3. Host-only tunables are skipped for a fixed peripheral (they may be absent), a PHY init or power-on failure goes through dwc3_apple_core_stop (err_stop), the probe error message names peripheral or host, and the binding lists exactly four iommus entries (minItems 4).
  • Board nodes. The four PSD slots of the USB ports get their PMGR domains as parents: <&ps_atcN_usb_aon>, <&ps_atcN_usb>. dtcheck.sh (dtschema 2026.9) on the combined device tree of this stack, which contains these files: dtc -@ 0 warning lines, dt-validate of the board file 0 lines, 73 binding examples with only the baseline dcp-typec-routes message.

Not checked

Compile, checkpatch and hardware behavior (the receipts in the head note are the author's); the PSD parent choice for ATC3 is a stated guess in the stacked PR. Merge still needs CI and the owner's word.

@joshuaswarren

Copy link
Copy Markdown
Author

New head 9fbb35688e4c737bf1818d5cd6f9890292e06c5b. One change since the reviewed 3c57b1d5: apple_psd_power_on() rolls back the slot whose request timed out too (Greptile; the acknowledge was not seen but the slot may still start). Receipts at this head (CT-local, arm64 clang W=1, 16K pages): the base objects (pinctrl-apple-gpio, sart, nvme apple, pmgr-psd, usb2-t8152, hub, apple-dart, dwc3-apple, t8152-j873g.dtb) rc 0, 0 warnings. Not run: a boot.

@joshuaswarren

Copy link
Copy Markdown
Author

GREEN at 9fbb356

Read: the ten commits of this head against the ones I reviewed at b8943e8, compared per commit as diffs with the hash lines removed. Eight commits are identical (pinctrl, SART, NVMe, USB2 PHY, hub quirk, peripherals dts, dwc3, PMGR/USB dts). Two changed:

  • pmgr-psd.c: apple_psd_power_on's rollback now starts at the slot whose request timed out (for (; i >= 0; i--)), so the failed slot is put back to state 6 too; apple_psd_power_off, when any slot fails to stop, restores every slot to its active state (the ones that stopped and the one whose off request timed out), replacing the "stopped" bitmask. Correct for both paths: i still holds the failed index at the undo label, nslots is at most 3.
  • DART (Gen3): the stale-exception drain no longer reads BLOCK_ERROR (0x704) on Gen3, and the lock-on-error unlock returns after a one-time warning on Gen3 instead of sending a command through TLB_CMD (which Gen3 does not take). The rest of the commit is unchanged apart from hunk offsets. Known consequence: a Gen3 DART that locks on an error stays locked, with the warning in the log.
    Not run: build; the author's compile and dt receipts are not reproduced. Merge still needs CI and a second non-author GREEN.

@joshuaswarren

Copy link
Copy Markdown
Author

GREEN at 9fbb356

Compared with my GREEN at 3c57b1d5: one hunk changed, in apple_psd_power_on() of the PSD commit; the other nine commits are identical.

  • On a timed-out power-on request the rollback now starts at the failed slot (for (; i >= 0; i--), with int i), so the slot whose acknowledge was not seen is put back to idle together with the slots before it, newest first. The earlier while (i--) skipped it. The commit text says why.
  • Together with the power-off change checked at 3c57b1d5 (every slot restored to its active state after a failed group power-off), both failure paths now leave the domain consistent with what genpd believes.

The device tree and binding commits did not change, so the dtcheck.sh result at 3c57b1d5 stands (dtc -@ 0 warning lines, dt-validate 0 lines, 73 examples with only the baseline message). Not checked: compile and hardware behavior. Merge still needs CI and the owner's word.

@joshuaswarren

Copy link
Copy Markdown
Author

Status at head 9fbb35688e4c737bf1818d5cd6f9890292e06c5b: two independent reviews GREEN at this exact head, all Greptile threads replied and resolved, arm64 clang W=1 compile of the touched objects rc 0 with 0 warnings, device-tree schema check 0 messages. Not done: a boot on hardware, CI. Needs a maintainer's CI approval and merge. Not needed for the release candidate.

@joshuaswarren

Copy link
Copy Markdown
Author

Note

🤖 GPT-6.1 Terra responding on behalf of joshuaswarren

The series starts with #191 (NVMe, USB2, power domains and DART). After that, #192 adds the Type-C PHY, #193 adds QSPI, #194 adds audio plumbing, and #197 adds the USB4 host. #198 builds on #197 for PCIe tunneling; #201 builds on the audio plumbing and needs the #197 mailbox binding.

The PRs record compile and device-tree checks. Earlier forms booted from NVMe and exercised USB2; separate earlier builds exercised QSPI, the USB4 host and a PCIe tunnel. Those results are not boots of the current PR heads.

What would help you review the series: smaller patches, a different order, or specific test results?

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