3.3.3. CPUIdle
Overview
The cpuidle framework consists of two key components:
A governor that decides the target C-state of the system. A driver that implements the functions to transition to target C-state. The idle loop is executed when the Linux scheduler has no thread to run. When the idle loop is executed, current ‘governor’ is called to decide the target C-state. Governor decides whether to continue in current state/ transition to a different state. Current ‘driver’ is called to transition to the selected state.
Standby Mode
On AM62x platforms, “Standby” mode is implemented through the Linux CPUIdle framework. Standby is the default low-power state that the system enters automatically when idle, using the WFI (Wait For Interrupt) C-state. This power-saving mechanism activates whenever the system is “just sitting idle” without requiring any special configuration or activation from the user.
When your device appears inactive, it is actually cycling in and out of this standby state many times per second, seamlessly managing power while remaining responsive.
Enable Standby
In order to enable Standby the k3-am62x-sk-lpm-standby.dtso overlay should be applied. Refer to How to enable DT overlays for more details. More information on what the overlay does is in the Linux Device Tree Implementation section.
Standby Implementation Architecture
For AM62x, the Standby implementation involves a multi-layer architecture:
Linux CPUIdle Framework: - Determines when to place CPUs into idle states based on system activity - Uses governors (like the menu governor) to predict how long CPUs will be idle - Invokes platform-specific drivers to transition to appropriate C-states
ARM Generic CPUIdle Driver: - Implements the Linux CPUIdle driver interface for ARM platforms - Communicates with TF-A through PSCI SMC (Secure Monitor Call) interface
PSCI Interface in Linux: - Provides a standardized method for the kernel to request power management operations - Translates Linux-side requests into PSCI calls to TF-A
TF-A PSCI Implementation: - Runs in secure world (EL3) - Implements the PSCI specification - Provides platform-specific handlers via the
plat_psci_opsstructure
When your system goes idle, the following sequence occurs:
Linux idle loop detects no runnable tasks
CPUIdle governor selects the appropriate C-state (“stby” for these platforms)
CPUIdle driver communicates with TF-A via the PSCI interface
TF-A’s PSCI implementation validates the requested power state through
validate_power_state()TF-A executes the
cpu_standby()handler fromplat_psci_opsThe actual WFI instruction is executed within the TF-A’s standby handler
On interrupt: CPU automatically exits WFI state
Control returns to Linux
This automated process happens continuously during system operation, seamlessly transitioning between active and idle states to save power whenever possible.
Standby vs. Deep Sleep: Understanding the Difference
It’s important to distinguish between the lightweight “standby” provided by CPUIdle and deeper sleep states:
CPUIdle Standby (WFI): - Processor-level power saving only - Very fast entry and exit (microseconds) - Occurs automatically hundreds of times per second - No user intervention required - All peripherals remain operational - Perfect for normal “idle” periods
Deep Sleep Modes: - System-wide power saving - Slower entry and exit (milliseconds to seconds) - Requires explicit software requests - May require peripheral reconfiguration - Suitable for extended inactive periods
Source Location
Linux Side:
drivers/cpuidle/cpuidle-arm.c- ARM CPU idle driverdrivers/cpuidle/dt_idle_states.c- Device tree parsing for idle statesdrivers/cpuidle/cpuidle.c- Core CPUIdle frameworkkernel/sched/idle.c- Kernel idle loop implementationdrivers/firmware/psci.c- PSCI interface to TF-A
TF-A Side (not part of Linux kernel):
plat/ti/k3/common/k3_psci.c- PSCI implementation for K3 platforms
Linux Device Tree Implementation
In order to implement Standby in Linux, an idle-states node has to be added and then referenced by the CPU node. The k3-am62x-sk-lpm-standby.dtso can be used as a reference.
idle-states {
entry-method = "psci";
CPU_SLEEP_0: stby {
compatible = "arm,idle-state";
idle-state-name = "standby";
arm,psci-suspend-param = <0x00000001>;
entry-latency-us = <100>;
exit-latency-us = <50>;
min-residency-us = <1000>;
};
};
The entry-latency-us, exit-latency-us, and min-residency-us
properties are explained in depth here.
The min-residency-us can be fine tuned to change the minimum amount of
time Linux is in idle which can change the power savings.
Driver Usage
CPUIdle works automatically once enabled in the kernel, with no user intervention required. The CPUIdle framework statistics can be accessed through the sysfs interface:
# ls -l /sys/devices/system/cpu/cpu0/cpuidle/
drwxr-xr-x 2 root root 0 Jan 1 00:01 state0
drwxr-xr-x 2 root root 0 Jan 1 00:01 state1
# ls -l /sys/devices/system/cpu/cpu0/cpuidle/state1/
-r--r--r-- 1 root root 4096 Jan 1 00:02 desc
-r--r--r-- 1 root root 4096 Jan 1 00:02 latency
-r--r--r-- 1 root root 4096 Jan 1 00:02 name
-r--r--r-- 1 root root 4096 Jan 1 00:02 power
-r--r--r-- 1 root root 4096 Jan 1 00:02 time
-r--r--r-- 1 root root 4096 Jan 1 00:02 usage
To view the current C-state statistics:
# cat /sys/devices/system/cpu/cpu0/cpuidle/state1/name
stby
# cat /sys/devices/system/cpu/cpu0/cpuidle/state1/usage
6245738