System suspend (A64)
System suspend is done on multiple levels, from top to bottom:
- Linux
userspace:
- Prepares whatever it deems necessary prior to suspend
- Triggers the suspend by writing to
/sys/power/state
- Linux kernel:
- Freezes
userspace processes so that they stop asking kernel to do stuff
that device drivers would need to perform
- Puts devices it controls into low
power state or shuts them down (while
keeping enough state to be able to resume them) via
suspend
callbacksin drivers
- Offlines secondary CPU cores via PSCI interface to ATF
- Invokes
SYSTEM_SUSPEND
function of PSCI
- Freezes
userspace processes so that they stop asking kernel to do stuff
- ATF:
- Performs some CPU management tasks and
forwards some power management tasks to [crust firmware] running on
SCP
(System Control Processor), which in Allwinner world is single core CPU implementingOpenRISC 1000
architecture called variously CPUS or ARISC in Allwinner docs.
- Performs some CPU management tasks and
forwards some power management tasks to [crust firmware] running on
- Crust:
- shuts down the CPU cores and the entire CPU core cluster and power gates it
- turns off CPU clocks and CPU voltage regulators
- sets DRAM to self-refresh, powers down memory controller
- sets GPIO ports that will have to remain powered to hold mode (to hold their current state)
- configures PMIC for sleep mode
- disables remaining non-critical clocks, PLLs, etc.
- reconfigures bus clocks,
- turns off the main oscillator
- and so on
Management firmware (crust) then loops and watches for wakeup interrupts and restores the system into running state if necessary.
Currently crust is able to put system into a
sleep state that consumes ~110mW
on PinePhone.
There are some
limits to what devices can be used for wakeup currently, because of interrupt
routing for some possible wakeup sources not going through r_intc
.
So on A64 volume keys can't be used for wakeup, for example.
Controlling suspend/resume from userspace
Suspended state is entered by writing into sysfs files:
# see available suspend to RAM sleep modes cat /sys/power/mem_sleep # configure one of them (in this case suspend to idle, which just idles all ARM CPUs) echo s2idle > /sys/power/mem_sleep # initiate power state change echo mem > /sys/power/state
Wakeup sources can
be listed and configured via sysfs files under
/sys/class/wakeup
.
# list all enabled wakeup sources cat /sys/class/wakeup/wakeup*/name 1f00000.rtc alarmtimer axp20x-battery axp813-ac axp20x-usb 1c21800.lradc musb-hdrc.1.auto # disable a wakeup source cat /sys/class/wakeup/wakeup#/device/power/wakeup enabled echo disabled > /sys/class/wakeup/wakeup#/device/power/wakeup # enable a wakeup source (you need to find the device in sysfs first) find /sys/devices -wholename '*power/wakeup' /sys/devices/platform/soc/1c1a000.usb/usb1/power/wakeup /sys/devices/platform/soc/1c1b000.usb/usb3/power/wakeup /sys/devices/platform/soc/1c1a400.usb/usb2/power/wakeup /sys/devices/platform/soc/1c28c00.serial/tty/ttyS2/power/wakeup /sys/devices/platform/soc/1c1b400.usb/usb4/power/wakeup /sys/devices/platform/soc/1c21800.lradc/power/wakeup /sys/devices/platform/soc/1c28400.serial/serial0/power/wakeup /sys/devices/platform/soc/1f03400.rsb/sunxi-rsb-3a3/axp20x-ac-power-supply/power_supply/axp813-ac/power/wakeup /sys/devices/platform/soc/1f03400.rsb/sunxi-rsb-3a3/axp20x-battery-power-supply/power_supply/axp20x-battery/power/wakeup /sys/devices/platform/soc/1f03400.rsb/sunxi-rsb-3a3/axp20x-usb-power-supply/power_supply/axp20x-usb/power/wakeup /sys/devices/platform/soc/1c28000.serial/tty/ttyS0/power/wakeup /sys/devices/platform/soc/1f00000.rtc/power/wakeup /sys/devices/platform/soc/1c19000.usb/musb-hdrc.1.auto/power/wakeup /sys/devices/platform/serial8250/tty/ttyS6/power/wakeup /sys/devices/platform/serial8250/tty/ttyS4/power/wakeup /sys/devices/platform/serial8250/tty/ttyS7/power/wakeup /sys/devices/platform/serial8250/tty/ttyS5/power/wakeup /sys/devices/platform/serial8250/tty/ttyS3/power/wakeup # enable wakeup source (volume key press in this case) echo enabled > /sys/devices/platform/soc/1c21800.lradc/power/wakeup