The Linux kernel uses several power management strategies:
-
Dynamic voltage frequency scaling (DVFS) adjusts the CPU frequency and the different voltages depending on the system’s load. The combination of a CPU frequency and a set of voltages for that frequency is called an operating point.
-
Suspend to memory allows for the system to sleep waiting for an event. On suspend, all system devices, including CPU and memory, enter low power mode. On resume, the system will continue from the same state it was in before it suspended.
-
Power off, which brings the system to a halt until an event wakes the system. On power off the system power remains enabled and the system is placed on its lowest consumption mode. On wake up, the bootloader starts up again and the system is initialized.
Dynamic Voltage Frequency Scaling
Dynamic Voltage Frequency Scaling is enabled by default, so the CPU frequency and voltages of a running system will adapt to the system’s load.
You can list, read, and configure the CPU frequency from your Android application. See Configure CPU frequencies.
The DVFS subsystem can be configured with different governors that control its behavior. See Configure governors.
Actual output may differ depending on kernel version/configuration. |
The current governor is shown in scaling_governor
, and by default is set to the ondemand
governor.
-
ondemand
: This governor does a periodic polling to adjust the operating mode to the system load. -
conservative
: Similar to the ondemand governor, the conservative governor performs graceful frequency and voltage changes that are better suited to battery powered devices. -
powersave
: This governor uses the lowest available frequency without dynamic adaptation. -
userspace
: This governor allows for user space to select the operating frequencies. -
performance
: This governor uses the highest available frequency without dynamic adaptation. -
schedutil
: This governor uses an scheduler-driven CPU frequency selection.
# echo userspace > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
# cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies
1200000 1600000
# echo 1600000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed
# cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq
1600000
Suspend to memory
The Linux kernel can also perform a suspend to memory or suspend to RAM operation. When entering this low-power mode, the system state is kept in self-refreshing RAM while the system enters a low-power-consumption mode. The system resumes when a previously selected interrupt is received, restores the previous state, and continues running from where it left off. There is often a trade-off between the depth of the low-power mode and the speed at which the system can resume.
Entering suspend mode
To enter suspend mode:
-
Briefly press (less than two seconds) the power key
Resume events
The system can resume from any interrupt generating event, including:
-
MCA GPIOs
-
Android alarm
-
Power key event
By default, the power key event will always be registered to resume a system from suspend. See Configuring wake-up sources for additional details.
Power off
The Linux kernel can perform a power off operation that places the Power Management IC (PMIC) in power off mode, disabling all power sources that are not needed for wake up.
Entering power off
To enter power off mode you can do one of the following:
-
Press the power key for nine seconds or longer to perform an unconditional hardware power off (not controlled by software).
Press time values are configurable on the MCA power key device tree. |
Wake up events
You can wake up the target from power off mode with an interrupt event to the PMIC, but not to the CPU as it will not be powered. These include:
-
Power key event
-
MCA GPIOs
-
Android alarm
The power key will always wake up the system. |
Configuring wake-up sources
GPIO resume from suspend
To program a GPIO N to generate a wake-up interrupt when it changes status, use the GPIO API to instantiate the GPIO and configure as interrupt (either rising or falling edge):
import com.digi.android.gpio.GPIO;
import com.digi.android.gpio.GPIOManager;
import com.digi.android.gpio.GPIOMode;
[...]
GPIOManager gpioManager = ...;
GPIO gpio = gpioManager.createGPIO(N, GPIOMode.INTERRUPT_EDGE_RISING);
[...]