Skip to content

Latest commit

 

History

History
87 lines (69 loc) · 5.21 KB

File metadata and controls

87 lines (69 loc) · 5.21 KB

Power-off / shutdown (SOLVED)

Symptom: pressing shutdown left the phone hung on a black screen with the last console text, never powering off, needing a hard reset. Reboot worked fine. First we fixed the hang (clean power-cut), but the phone still auto-rebooted after ~15-25 seconds even on battery. That re-power was the main PMIC's own watchdog (WTSR), and it is now fixed: the phone shuts down and stays off from any shutdown path. See "The fix (implemented and verified)" below.

Why it hung

The kernel's pm_power_off is PSCI SYSTEM_OFF. On this device S-Boot's secure firmware hangs on SYSTEM_OFF instead of cutting power (reboot works because it uses a different PSCI path, SYSTEM_RESET). So the kernel called into EL3 and never came back.

The real power-off mechanism on exynos9830

Power is cut by driving the PS_HOLD pin low, which tells the main PMIC (S2MPS19) to drop the rails. On this SoC (downstream exynos-reboot.c, CONFIG_SOC_EXYNOS9830) that is PMU register PS_HOLD_CONTROL = 0x030C, clearing bit 8 (PS_HOLD_EN): regmap_update_bits(pmu, 0x030C, 0x100, 0). Note it is 0x030C, not the old S5P value 0x330C (using 0x330C reproduces the original hang). The same #else branch also gives SWRESET = 0x3A00, which matches the working reboot node, confirming the branch.

The PMU syscon maps at physical 0x15860000 (the DT node is named @11860000 but its reg overrides to 0x15860000).

What we added

  • A syscon-poweroff DT node on the PMU (offset = 0x030c, mask = 0x100, value = 0x0) and CONFIG_POWER_RESET_SYSCON_POWEROFF=y, registered at SYS_OFF_PRIO_HIGH so it runs before the broken PSCI handler.
  • An ACPM "enter WFI / STOP" step before PS_HOLD, mirroring the vendor's exynos_acpm_reboot() -> acpm_enter_wfi(): an ACPM IPC with cmd[0] = 1 << 22 (ACPM_IPC_PROTOCOL_STOP) on the ACPM framework channel (firmware channel id 4, found by logging the channel table; index == id on this firmware). Added to the in-tree ACPM driver and registered as a power-off handler at SYS_OFF_PRIO_FIRMWARE.

Result: clean power-cut, but a ~20 s re-power

Shutdown became a clean systemd power-off and PS_HOLD 0x030C really does cut power (the screen goes black; the behaviour changed from a permanent hang to a clean power-cut). But the phone auto-reboots ~20 s later, even unplugged. The ACPM STOP does not suppress it.

Root cause found: the S2MPS19 WTSR watchdog

The re-power is not the APM and not the power button. Proof: triggering systemctl poweroff over SSH with nothing touched still re-powers at ~20 s. The cause is the main PMIC (S2MPS19) WTSR (Watchdog Timer Software Reset, RTC register 0x01 bit 6) and SMPL (bit 7). S-Boot leaves them enabled. On a normal Samsung phone the PMIC's RTC driver disables them during shutdown (s2m_rtc_shutdown -> clear WTSR/SMPL in RTC reg 0x01). But mainline rtc-s5m.c has no such shutdown disable, and on this port no PMIC or RTC driver is loaded at all (/sys/class/rtc is empty) because the S2MPS19 is managed entirely over ACPM. So nothing ever disables WTSR, its watchdog times out ~20 s after PS_HOLD drops, and it power-cycles the phone.

exynos_acpm_force_apm_wdt_reset (STOP_WDT, bit 27) does the opposite (forces a reset), so it is not the fix.

The fix (implemented and verified, 2026-07-30)

Clear WTSR (bit 6) and SMPL (bit 7) in the PMIC's RTC register 0x01, over ACPM, before dropping PS_HOLD. Addressing: ACPM IPC channel 2 (PMIC), speedy channel 0, S2MPS19 RTC sub-address 0x02, register 0x01, read-modify-write to clear bits 6 and 7.

Validation (before touching the poweroff path): a read-only one-shot module (acpm-rtc-probe.c) dumped the RTC block over ACPM using the in-tree handle->ops->pmic.bulk_read. RTC reg 0x01 read back 0xe3, WTSR_EN and SMPL_EN both armed, exactly as diagnosed. The same register via the PMIC sub-address (0x01) returned 0x10, proving the ACPM type field is the S2MPS19 sub-block i2c address (PMIC 0x01, RTC 0x02, DEBUG 0x0F). SUB_SMPL (CAPSEL reg 0x03 bit 3) already read 0, matching the vendor shutdown sequence which clears it too.

Implementation: s2mps19_disable_wtsr_smpl() in exynos-acpm.c, called at the top of acpm_power_off_notify() BEFORE acpm_enter_wfi() sends the APM STOP, because the APM must still be alive to service the PMIC channel. Read reg 0x01, write it back with bits 6/7 cleared if set, read back and log with dev_emerg. The full patched driver is kernel/drivers/acpm-pmic/exynos-acpm.c in this repo.

Result: flashed as kernel #22 and tested on battery over SSH: systemctl poweroff, screen black, phone stays off. Because the handler sits in the kernel sys-off chain, every userspace shutdown path (systemctl poweroff, the Plasma GUI shutdown, poweroff, halt -p) gets the fix automatically; there is nothing per-app to configure. Power back on with the power button. Note that plugging in USB power while off can boot the phone via charger detection; that is normal PMIC behaviour, not the WTSR bug. The shutdown-time dev_emerg lines are usually lost from the journal because PS_HOLD cuts power before journald flushes, so the staying-off behaviour is the proof of record.