Enabling real s2idle suspend on the RG34XX SP with ROCKNIX
I managed to get real Linux suspend working on the Anbernic RG34XX SP running ROCKNIX.
By default, ROCKNIX disables hardware suspend on H700 devices and uses its own fake-suspend implementation. The kernel does expose s2idle, but enabling it directly caused the console to hang during resume.
The problem turned out to be asynchronous device power management. Disabling it allows the kernel to complete suspend and resume normally.
Tested configuration
- Anbernic RG34XX SP
- Allwinner H700
- ROCKNIX
- Linux kernel
7.0.11 - ROCKNIX build from July 1, 2026
This may also work on other H700 devices, but I have only tested it on the RG34XX SP.
The problem
The kernel reports:
cat /sys/power/state
freeze mem disk
cat /sys/power/mem_sleep
[s2idle]
This means that the kernel supports suspend-to-idle.
However, enabling it directly:
echo freeze > /sys/power/state
caused the console to hang during resume.
The screen backlight came back and the previous EmulationStation frame was visible, but the system itself was still frozen. The suspend operation never returned to userspace.
The fix
The default value of:
/sys/power/pm_async
is:
1
This allows Linux to suspend and resume independent devices in parallel.
On the tested H700 configuration, that appears to cause a race or incorrect dependency ordering during resume.
Disabling asynchronous device power management fixes the issue:
echo 0 > /sys/power/pm_async
After applying this setting, the console successfully completed multiple suspend and resume cycles.
A successful kernel log ends with:
PM: suspend entry (s2idle)
...
Restarting tasks: Done
PM: suspend exit
Installation
Connect to the console over SSH as root.
It is a good idea to keep SSH enabled while testing, in case the device needs to be force-rebooted.
1. Create the autostart script
mkdir -p /storage/.config/autostart
cat > /storage/.config/autostart/999-hardware-suspend <<'EOF'
#!/bin/sh
# H700 may hang when device suspend/resume callbacks run asynchronously.
echo 0 > /sys/power/pm_async
# Enable real Linux s2idle instead of ROCKNIX fake suspend.
/usr/bin/suspendmode freeze
# Reload logind after the configuration has been applied.
systemctl restart systemd-logind
EOF
chmod +x /storage/.config/autostart/999-hardware-suspend
2. Override the ROCKNIX power-button configuration
ROCKNIX creates this file during boot:
/storage/.config/logind.conf.d/login.conf
It contains:
[Login]
HandlePowerKey=ignore
HandleSuspendKey=ignore
Do not edit this file directly, because ROCKNIX may recreate it during boot.
Instead, create another configuration file whose name sorts after login.conf:
mkdir -p /storage/.config/logind.conf.d
cat > /storage/.config/logind.conf.d/zz-hardware-suspend.conf <<'EOF'
[Login]
HandlePowerKey=suspend
HandleSuspendKey=suspend
HandleLidSwitch=suspend
HandleLidSwitchExternalPower=suspend
EOF
The zz- prefix is important.
A name such as:
99-hardware-suspend.conf
is not sufficient, because login.conf sorts later and its HandlePowerKey=ignore setting takes precedence.
3. Remove stale fake-suspend state
rm -f /var/run/power-fake-suspend-active.flag
rm -f /var/run/lid-closed.flag
rm -f /var/run/shutdown-delay.flag.*
4. Reboot
reboot
The settings can also be applied without rebooting:
echo 0 > /sys/power/pm_async
/usr/bin/suspendmode freeze
systemctl restart systemd-logind
Verification
Check that asynchronous device PM is disabled:
cat /sys/power/pm_async
Expected result:
0
Check the selected suspend mode:
get_setting system.suspendmode
Expected result:
freeze
Inspect the merged systemd-logind configuration:
systemd-analyze cat-config systemd/logind.conf \
| grep -E 'HandlePowerKey|HandleSuspendKey|HandleLidSwitch'
The final active values should be:
HandlePowerKey=suspend
HandleSuspendKey=suspend
HandleLidSwitch=suspend
HandleLidSwitchExternalPower=suspend
There may be older conflicting values earlier in the output. What matters is the last occurrence of each option.
Testing
First, test suspend manually over SSH:
sync
echo freeze > /sys/power/state
Press the Power button to wake the console.
Then test the normal controls:
- Short Power-button press suspends the console
- Another short press wakes it
- Closing the lid suspends the console
- Opening the lid wakes it
Result
Success: closing the lid now enters real Linux suspend rather than ROCKNIX fake suspend.
Opening the lid resumes the console normally. EmulationStation continues running, the buttons respond, Wi-Fi reconnects, and Bluetooth reinitializes.
Repeated suspend and resume cycles also work correctly.
Checking the kernel log
After a successful suspend and resume cycle:
dmesg | tail -n 100
Look for:
PM: suspend entry (s2idle)
...
PM: suspend exit
The important line is:
PM: suspend exit
It confirms that the kernel completed resume.
Wi-Fi will usually disconnect before suspend and reconnect afterward.
Bluetooth firmware may also be loaded again:
Bluetooth: hci0: RTL: loading rtl_bt/rtl8821cs_fw.bin
USB messages such as these may appear:
usb usb2: root hub lost power or was reset
usb usb3: root hub lost power or was reset
They are not necessarily errors if the resume process completes successfully.
What kind of suspend is this?
This enables Linux s2idle.
It is not deep suspend-to-RAM.
The current H700 kernel exposes only:
[s2idle]
and does not provide a deep option.
During s2idle:
- Userspace processes are frozen
- Devices enter their suspend states
- The display turns off
- Wi-Fi disconnects
- The kernel manages the suspend and resume cycle
It will probably consume more power than true deep suspend, but it is still a real kernel-managed suspend state rather than a userspace simulation.
Why does pm_async=0 help?
With the default value:
pm_async = 1
Linux may run power-management callbacks for several devices in parallel.
This is normally faster, but it depends on correct device dependency information.
On the tested H700 setup, parallel resume causes the kernel to hang before userspace is unfrozen.
Setting:
echo 0 > /sys/power/pm_async
forces the kernel to process device suspend and resume callbacks sequentially.
This may make suspend and resume slightly slower, but it does not affect performance during normal gameplay.
Rollback
To restore the default ROCKNIX behavior:
rm -f /storage/.config/autostart/999-hardware-suspend
rm -f /storage/.config/logind.conf.d/zz-hardware-suspend.conf
/usr/bin/suspendmode off
echo 1 > /sys/power/pm_async
reboot
Debugging a failed resume
A visible EmulationStation frame does not necessarily mean that Linux resumed successfully.
It may only be the old framebuffer image with the backlight switched on.
To check whether the kernel actually returns from suspend:
rm -f /storage/suspend-stage.log
sh -c '
echo "before: $(date)" > /storage/suspend-stage.log
sync
echo freeze > /sys/power/state
echo "after: $(date)" >> /storage/suspend-stage.log
sync
'
After a forced reboot:
cat /storage/suspend-stage.log
If the file contains only:
before: ...
the kernel never completed resume.
If it contains both:
before: ...
after: ...
the kernel resumed successfully, and the remaining issue is likely in userspace or the input stack.