System suspend (A64)
I haven't tested this yet, or tried to integrate A64 support for system suspend/deep sleep into my tree.
System suspend is done on multiple levels:
- Userspace processes are stopped/frozen.
- Linux suspends individual devices it has drivers loaded for (if the driver has suspend/resume callbacks implemented)
- Linux offlines all but one CPU core via PSCI, and issues final PSCI call to suspend the last core
- ATF hadnles the PSCI calls by handing some of them off the management firmware running on the arisc CPU
- management firmware shuts down:
- the CPU cores and the entire CPU core cluster and power gates them
- 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.
Management firmware (crust) then loops and watches for wakeup interrupts and restores the system into running state if necessary.
At the moment, the status of crust development seems to be that it disables CPU cores, but doesn't power down the regulators or CPU clocks. No further sleep actions are performed.
That's very roughly what can be done to save power. Just shutting down ARM CPUs without anything else, doesn't lead to much power savings compared to letting them run idle. PinePhone consumes around 1W in these cases.
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
# 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