Skip to content

t8112: PMU RTC wake alarm (M2), on top of #351 - #454

Draft
p4ulcristian wants to merge 6 commits into
omacom:integration/aurorafrom
p4ulcristian:t8112-rtc-alarm
Draft

p4ulcristian wants to merge 6 commits into
omacom:integration/aurorafrom
p4ulcristian:t8112-rtc-alarm

Conversation

@p4ulcristian

@p4ulcristian p4ulcristian commented Nov 11, 2026 •

Copy link
Copy Markdown

This makes the PMU's RTC wake alarm work on T8112 (M2): rtcwake, and timed wakes from s2idle. It is one device-tree commit on top of #351 (T600x), and needs #351's rtc_alarm_event cell and driver change. Only the last commit is new; the five before it are #351. Draft until #351 merges; I'll rebase then.

Patch

arm64: dts: apple: t8112: describe the alarm:

  • nub-spmi0 as an interrupt controller on AIC 384;
  • the alarm's nvmem cells on the Stowe PMU, at the offsets in macOS's device tree: info-rtc_alarm_ctrl 0xf800, info-rtc_alarm_offset 0xf808, info-rtc_alarm_event 0xf80c, info-rtc_irq_mask_offset 0xf80e;
  • the rtc node's five cells, its interrupt (peripheral interrupt 2 of nub-spmi0) and wakeup-source.

No driver change:

How the Stowe PMU behaves (read and written by hand through the nvmem device before any driver used the cells):

  • Armed, the control byte reads 0x41. On the alarm's second it reads 0x03 (enable cleared, event set) and the event byte at 0xf80c reads 1. 5 of 5 alarms fired on the second they were set for.
  • Writing 1 to the event byte clears both the event byte and the control byte's event bit.
  • Writing the control byte back does not clear either, with the event bit written as 1 (the T6030 way) or as 0.

So Stowe needs the rtc_alarm_event cell like the Maverick PMUs. One difference from #351's comments: on Stowe the control byte's event bit is cleared by the event-byte write, not by writing that bit as 0. The driver's sequence handles both.

Testing on J413 (MacBook Air 13" M2, 2022), linux-aurora 7.2.11.aurora16-1, m1n1-aurora 1.6.1.aurora23-2, Omarchy on GRUB:

  • Setup: rtc-macsmc from t600x: PMU RTC wake alarm (SPMI notify at 192, Maverick event clear, DT) #351 built as an out-of-tree module (updates/, in the initramfs), and t8112-j413.dtb built from this patch applied to the aurora16 source (bed544b). Built the same way, the unpatched source gives a dtb byte-identical to the one the package ships.
  • Awake: 3 alarms through /sys/class/rtc/rtc0/wakealarm, 3 interrupts, each on its second, event cleared and alarm disarmed after each.
  • s2idle, dtb built from this patch: 5 of 5 rtcwake -m freeze -s 20 ended on the alarm (/sys/power/pm_wakeup_irq is the macsmc-rtc interrupt each time).
  • s2idle, the same description edited into the shipped dtb (earlier boot): 13 of 13 at 20–30 s, and 1 of 1 at 3600 s on battery.
  • Sleep draw: about 1.0 W in s2idle (602 s, the SMC charge counter charge_counter fell by 50892 mA·s, 84.5 mA average at 12.1 V; Wi-Fi associated, lid open, nothing attached; one sample). Corrected: an earlier version of this text said 0.40 W. That came from energy_now over the 3600 s sleep; energy_now is the gauge's remaining-capacity estimate, which is stale right at wake and fell a further 0.46 Wh within 25 s of waking.
macsmc-rtc macsmc-rtc: registered as rtc0
128:  ...  apple_spmi   2 Edge   macsmc-rtc
run 1: rc=0 back after 22s wake_irq=128 alarm_irqs=1
run 5: rc=0 back after 22s wake_irq=128 alarm_irqs=5
DONE success=5 fail=0

Not tested

  • J415, J473 and J493: their device trees compile with the patch (kernel scripts/dtc), nothing more. I have no such Mac.
  • Wake with the lid closed, and wake with an external display attached.
  • A full kernel build: the dtb and the module were built on their own.
  • dt_binding_check / dtbs_check.

🤖 Generated with Claude Code

CoreyH and others added 6 commits November 4, 2026 14:26
…rupts

The controller's interrupt words hold the peripheral interrupts first and
the controller's own events after them, "notify" (the RX FIFO is no
longer empty) first. The driver puts notify at 256, after T6030's 256
peripheral interrupts. T6000's nub-spmi0 has 192: macOS's device tree
numbers its events from 0xc0, and with a reply left in the FIFO the
pending bit is 192 (ack word 6, bit 0).

So once a T6000 device tree gives nub-spmi0 its interrupt, the driver
unmasks bit 256 and waits for a notify that never comes: every SPMI
read times out and the PMU becomes unreachable. Take the peripheral
interrupt count from the match data, 192 for apple,t6000-spmi and 256
for the rest, and derive the notify position, the irq domain's bounds,
the handler's scan and the mask/ack setup from it.

Tested on J314s (M1 Pro): with nub-spmi0's interrupt described, SPMI
transfers complete in 40-60 us and the PMU's RTC alarm wakes the system
from s2idle.

Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Corey Henderson <nuwanda@gmail.com>
The Maverick PMUs (the M1 Pro's and the M2 Pro's) latch a fired alarm in
an event byte as well as in the alarm control byte, and keep the alarm
interrupt silent until the event byte is cleared by writing 1 to it.
Allow a fifth cell, rtc_alarm_event, after the four alarm cells.

Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Corey Henderson <nuwanda@gmail.com>
…gister

The Maverick PMUs (the M1 Pro's and the M2 Pro's) latch a fired alarm in
two places: bit 1 of the alarm control byte and an interrupt status
byte. Writing the control byte back with bit 1 set, which is how T6030's
PMU acknowledges the event, leaves the bit set here. It clears when it
is written as 0. The status byte clears when 1 is written to it, and
until then the PMU keeps the alarm interrupt silent, so every later
alarm would be lost.

With the optional rtc_alarm_event cell, clear the status byte before
arming and after firing. The control byte's bit 1 then clears where it
is written as 0. Without the cell, nothing changes.

Tested on J314s (M1 Pro): awake alarms fire on their second and leave
both registers clear, and every timed s2idle sleep that nothing else
woke ended on the alarm.

Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Corey Henderson <nuwanda@gmail.com>
The time is the SMC's CLKM plus a tick offset, but the PMU's alarm
compares against the PMU's own counter, which CLKM lags by a few ms (5.5
to 6.3 ms on J314s, once 14 to 24 ms right after boot). When the tick
offset's fraction is under that lag, the alarm fires while the time
still reads the second before. The RTC core then finds its timer not
yet expired and sets the same second again, the PMU fires again at
once, and so on until the time catches up: five or six interrupts and a
burst of SPMI traffic for one alarm. That is the state after the PMU
loses power, which leaves the offset at 0.

When the offset's fraction is under 1/32 s, arm the alarm one counter
second later. It then fires within the set second, and read_alarm still
reports the time that was set. For fractions between the lag and 1/32 s
the alarm comes up to a second late, which the tick-offset path already
allowed. The seconds-offset path is unchanged.

Tested on J314s (M1 Pro) with the offset's fraction cleared: three awake
alarms raised one interrupt each, where they raised 6, 5 and 5 before.

Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Corey Henderson <nuwanda@gmail.com>
The Maverick PMU on nub-spmi0 has an RTC alarm (macOS's device tree:
info-rtc_alarm_ctrl 0x1401, info-rtc_alarm_offset 0x140c,
info-rtc_alarm_event 0x14c0, info-rtc_irq_mask_offset 0x14c2). It raises
peripheral interrupt 2 of nub-spmi0, whose own interrupt is AIC 636.
Describe nub-spmi0 as an interrupt controller and the alarm's four
cells, and give the SMC's rtc node the cells, the alarm interrupt and
wakeup-source.

This needs the SPMI controller to put T6000's notify event at 192
(previous patches); without it, describing the interrupt breaks every
SPMI transfer.

Tested on J314s (M1 Pro) with the same description applied to the live
device tree: the alarm fires on its second, and it wakes the system
from s2idle.

Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Corey Henderson <nuwanda@gmail.com>
The Stowe PMU on nub-spmi0 has an RTC alarm (macOS's device tree:
info-rtc_alarm_ctrl 0xf800, info-rtc_alarm_offset 0xf808,
info-rtc_alarm_event 0xf80c, info-rtc_irq_mask_offset 0xf80e). It raises
peripheral interrupt 2 of nub-spmi0, whose own interrupt is AIC 384.
Describe nub-spmi0 as an interrupt controller and the alarm's four
cells, and give the SMC's rtc node the cells, the alarm interrupt and
wakeup-source.

T8112's controller has 256 peripheral interrupts (macOS lists its own
events from 256 on), so the SPMI driver needs no change.

Stowe latches a fired alarm in the event byte and in the control byte's
event bit, and clears the enable bit. Writing 1 to the event byte clears
both latches; writing the control byte back does not, with the event bit
as 1 or as 0. So the rtc node needs the rtc_alarm_event cell, like the
Maverick PMUs.

Tested on J413 (MacBook Air 13" M2), 7.2.11.aurora16 with rtc-macsmc from
this series and a device tree built from this patch: awake alarms raise
one interrupt each on their second (3 of 3), and every timed s2idle sleep
ended on the alarm (5 of 5 at 20 s; with the same description edited
into the shipped device tree, 13 of 13 at 20-30 s and 1 of 1 at 3600 s).
The J415, J473 and J493 device trees compile; they are not tested.

Assisted-by: Claude:claude-fable-5-2
Signed-off-by: Paul Martin Cristian <p4ulcristian@gmail.com>
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.

2 participants