Last edited 4 weeks ago

Power overview: Difference between revisions


Latest revision as of 10:00, 1 July 2025


1. Framework purpose[edit | edit source]

The purpose of this article is to explain the Linux® Power Management on STM32 Arm® Cortex® MPUs More info.png:

  • Low-power modes available on the device
  • Linux software overview for Power Management (on/off support, Suspend / Resume, Idle behavior, policy and control)
  • How to enter and exit a platform low-power mode

2. Software overview[edit | edit source]

The Linux® Power Management (PM) is divided in:

  • Static PM or System-Wide Power Management:
    • suspend framework, used to trigger a low-power mode entry/exit sequence.
    • power off
  • Dynamic PM or Working-State Power Management or Active Power Management based on other frameworks:

Refer to Linux documentation for more details, for example pages in Documentation/power and in Documentation/admin-guide/pm.

The OpenSTLinux power management support is based on Arm® interface specifications:

  • Power state coordination interface (PSCI) [1]
  • System Control and Management Interface (SCMI)[2]

2.1. STM32MP1 series[edit | edit source]

On STM32MP1 series, the "System-Wide Power Management" is supported:

Power mgt.png

The user application issues a suspend request to the kernel. This request is handled by the suspend Framework, which notifies all the device drivers to prepare for low-power entry. It then calls the PSCI service.

See also STM32MP1 power overview for details.

2.2. STM32MP2 series[edit | edit source]

The "System-Wide Power Management" is supported, the low power modes are requested to TF-A BL31 with PSCI API.

STM32MP2 Power mgt.png

When the user application sent a suspend request to the kernel (static), it is treated by the suspend framework with the PSCI suspend support.

For OS initiated low power mode (dynamic), the application idle is detected when the Linux scheduler has no thread to run and treated by CPUIdle PSCI driver and the low power mode is selected with generic power domains (GenPD).

See also STM32MP2 power overview for details.

NB: for M33-TD flavor More info green.png, Linux use the same PSCI but DDR is not managed in TF-A; the low power request is forwarded to TF-M.

2.3. Component description[edit | edit source]

Kernel components for low power:

  • Suspend framework: this framework schedules the overall sequence by stopping all the ongoing tasks
  • GenPD: generic power domain framework, based on runtime PM
    • GenPD driver: this STMicrolectronics driver is used for low-power mode selection according to the activated wakeup sources on STM32MP1 series.
  • PM runtime: device activity framework, used by each device driver
  • PSCI library: this is a set of standardized functions to request a low-power service to the secure monitor
  • PSCI cpuidle: CPU activity driver based on CPUIdle framework to handle Idle
  • Device driver: any peripheral driver which needs to control power.

Secure monitor and secure world components (OP-TEE) on AArch32 platforms for STM32MP1 series :

  • Low power driver: the role of this driver is to choose the low-power mode according to the programmed wakeup source(s)
  • PWR driver: this driver is responsible for configuring the low-power mode
  • RCC driver: this driver handles the circuit secure clocks
  • PSCI libray: generic PSCI stack

Secure world components (OP-TEE) on AArch64 platforms for STM32MP2 series:

  • PM framework: call the low-power callback of each device on the call of TF-A BL31 hooks.
  • Device drivers: driver of secure device

Secure monitor components (TF-A BL31) on AArch64 platforms for STM32MP2 series

  • PM manage PSCI topology and modes and DDR self refresh
  • PSCI libray: generic PSCI stack
  • DDR driver: DDR driver (only for A35-TD flavor More info green.png)

STM32 peripherals (Hardware):

2.4. API description[edit | edit source]

The suspend process is triggered from the user space through standard commands (see next chapter for details).

The system sleep control file is the state file, located under: /sys/power/
Further details can be found in admin-guide/pm/sleep-states.html.

The sysfs ABI are described in sysfs-power and sysfs-devices-power.

The device power API are described in driver-api/pm/index.html, in particular in driver-api/pm/devices.html.

3. Configuration[edit | edit source]

The objective of this chapter is to explain how to configure the Linux kernel and device tree to have the Power Management (PM) framework activated.

3.1. Kernel configuration[edit | edit source]

The Power Management framework is activated by default in ST deliveries.

It can be deactivated through the kernel menuconfig using Power management options/Suspend to RAM and standby: Menuconfig or how to configure kernel .

3.2. Device tree configuration[edit | edit source]

3.2.1. STM32MP1 series[edit | edit source]

The default system low-power mode mapping can be modified through the secure monitor device tree, as described OP-TEE documentation/devicetree/bindings/regulator/st,stm32mp1-pwr-reg.yaml .

See STM32MP1 power overview for impacts on OP-TEE device tree.

3.2.2. STM32MP2 series[edit | edit source]

The SoC device tree describes the PSCI topology in sub-nodes of cpus/domain-idle-states in SOC device tree, one node for each PSCI_CPU_SUSPEND supported parameter (only the Stop1 modes).

For example in arch/arm64/boot/dts/st/stm32mp251.dtsi

domain-idle-states {
	STOP1: domain-stop1 {
		compatible = "domain-idle-state";
		arm,psci-suspend-param = <0x00000011>;
	};
	LP_STOP1: domain-lp-stop1 {
		compatible = "domain-idle-state";
		arm,psci-suspend-param = <0x0000021>;
	};
	LPLV_STOP1: domain-lplv-stop1 {
		compatible = "domain-idle-state";
		arm,psci-suspend-param = <0x00000211>;
	};
};

The unsupported low power modes and associated references in domain-idle-states power domain nodes must be deleted from TF-A BL31 and Linux board device-tree files.

For example, on board without STPMIC, if the PWR_LP pins control the reduced voltage mode of the VDDCORE and VDDCPU regulators, then only LPLV-Stop1 modes can be reached. LP-Stop1 modes must be deleted in Linux device tree (CLUSTER_PD domain-idle-states = <&STOP1>, <&LP_STOP1>; for CLUSTER_PD in you board device tree with:

/ {
	cpus {
		domain-idle-states {
			/delete-node/ domain-lp-stop1;
		};
	};
};

&CLUSTER_PD {
	domain-idle-states = <&STOP1>;
};

See STM32MP2_power_overview for impacts on TF-A BL31 device tree.

4. How to use the framework[edit | edit source]

The power framework is managed with userfs API.

For Weston OpenSTLinux distribution, the direct access to sysfs must be avoided and must be replaced by systemctl command to correctly stop the systemd services and avoid issues on next wake-up.

Linux mode userFS API command STM32MP1 series STM32MP2 series
STM32MP21x lines More info.png STM32MP23x lines More info.png
STM32MP25x lines More info.png
S2Idle
Suspend-to-Idle (or freeze)
echo freeze > /sys/power/state with SuspendState=freeze in /etc/systemd/sleep.conf
systemctl suspend
not supported Stop1
LP-Stop1
[lp 1] LPLV-Stop1
S2RAM
Suspend-to-RAM (or deep)
echo mem > /sys/power/state[lp 2] with SuspendState=mem in /etc/systemd/sleep.conf

systemctl suspend

Stop
LP-Stop
LPLV-Stop
Standby
Run2[lp 3]
Stop2
LP-Stop2
LPLV-Stop2
Standby Standby1
power off shutdown -P now
systemctl poweroff
Standby (DDR off) Standby Standby2
VBAT
  1. LPLV-Stop1 is not supported in OpenSTLinux for STM32MP21x lines More info.png as Linux have no HR timer available in this mode.
  2. "deep" for S2RAM is the default suspend variants associated with the "mem" string in the ``state`` file
    cat /sys/power/mem_sleep
    s2idle [deep]
  3. Run2 is only supported for M33-TD flavor More info green.png

See platform power page for more details on each family:

In OpenSTLinux, the low power modes are selected with devices activity and with activated wake up sources.

Each sysfs device in /sys/devices/ that supports wake up contains the file wakeup in a device's power sub directory. The file contains wake up trigger's status and can be written to as well. See each device page to know the sysfs path in platform sub-directory and you can found all the possible wake up with:

find /sys/devices/platform | grep 'power/wakeup$'

You can check or control the wake up source with:

cat /sys/devices/platform/<device>/power/wakeup
echo enabled > /sys/devices/platform/<device>/power/wakeup
echo disabled > /sys/devices/platform/<device>/power/wakeup

For Arm® Cortex®-M coprocessor, the platform selects the allowed system modes depending of the MCU state and if firmware use the DDR.
You need to excute the expected low-power mode sequence for MCU side when DDR is not used, when firmware run in low power mode, or stop the MCU firmware when DDR is used by this firmware. Please refer to Cortex-M coprocessor power management for Arm® Cortex®-M commands.

4.1. Examples[edit | edit source]

With default wake up source (RTC, Wakeup pins), the deepest platform mode is selected: Standby on STM32MP1 series / Standby on STM32MP21x lines More info.png / Standby1 on STM32MP23x lines More info.png and STM32MP25x lines More info.png.

The activation of other wake-up sources prevents entering into this deepest low-power mode.

4.1.1. PWR WKUP pins[edit | edit source]

If PWR wake-up pins are enabled, for example see the WKUP button on STMicroelectronics boards, you can directly use the next command to call the low power entry:

systemctl suspend                      for weston
echo mem > /sys/power/state            for distribution without systemctl

Press the WKUP button on STMicroelectronics boards to wake up the board.

4.1.2. RTC wake up[edit | edit source]

The RTC wake up is activated by default in Linux (/sys/devices/platform/*/*.rtc/power/wakeup), so you just need to program the alarm.

The tools rtcwake is used to enter a system sleep state until specified wake up time, for example 5 seconds with:

rtcwake --date +5sec -m mem
4.1.3. Serial wake-up[edit | edit source]

With USART wake-up enabled, the low-power mode is limited to

  • LPLV-Stop on STM32MP13x lines More info.png
  • LP-Stop on STM32MP15x lines More info.png
  • LP-Stop2 on STM32MP2 series.

Enable serial wake up on associated TTY wake up source, for example

echo enabled > /sys/class/tty/ttySTM0/power/wakeup

Call the low-power entry command

systemctl suspend                      for weston
echo mem > /sys/power/state            for distribution without systemctl

The MPU is now in low power mode (LP-Stop/LPLV-Stop/LP-Stop2) and can be woken up by sending a character to the console.

4.1.4. GPIO wake-up[edit | edit source]

For GPIO wake-up enabled, the low-power mode is limited at LPLV-Stop on STM32MP1 series / LPLV-Stop2 on STM32MP2 series.

To enable test GPIO wake up, adds the wake up support with the property wakeup-source on a GPIO button (comaptible "gpio-keys") and is enabled in Linux by default (refer to Overview of GPIO pins for more details).

This property is not present on GPIO button in Linux device tree for STMicroelectronics, so you just need to add it:

  • STM32MP13x lines More info.png
&user-pa13 {
	wakeup-source;
};
  • STM32MP15x lines More info.png
/ {
	gpio-keys {
		compatible = "gpio-keys";
		/* gpio needs vdd core in retention for wakeup */
		power-domains = <&pd_core_ret>;

		button-1 {
				label = "PA13";
				linux,code = <BTN_1>;
				gpios = <&gpioa 13 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
				wakeup-source;
		};
	};
  • STM32MP2 series
&button-user-1 {
	wakeup-source;
};

Call the low-power entry command:

systemctl suspend                      for weston
echo mem > /sys/power/state            for distribution without systemctl

The STM32 MPU is now in low power mode (LPLV-Stop or LPLVStop2) and you can wake up by the GPIO button.

You can dynamically check and deactivate the wake up capability for GPIO associated to the button.

cat /sys/devices/platform/gpio-keys/power/wakeup
echo enabled > /sys/devices/platform/gpio-keys/power/wakeup
echo disabled > /sys/devices/platform/gpio-keys/power/wakeup

4.1. PSCI in Linux[edit | edit source]

The low power modes selection in OpenSTLinux use the PSCI stack:

4.2. S2IDLE and CPUIdle (PSCI_CPU_SUSPEND)[edit | edit source]

This mode is NOT supported for STM32MP1 series.

In Linux the power domain and associated low power modes for S2IDLE and CPUIdle OS initiated mode are described in SoC device tree using the hierarchical model as described in Documentation/devicetree/bindings/arm/psci.yaml .

For example for STM32MP25x lines More info.png, in arch/arm64/boot/dts/st/stm32mp251.dtsi and in arch/arm64/boot/dts/st/stm32mp253.dtsi is described by:

/ {
	cpus {
		idle-states {
			entry-method = "psci";
			CPU_PWRDN: cpu-power-down {
				compatible = "arm,idle-state";
				arm,psci-suspend-param = <0x00000001>;
			};
		};

		domain-idle-states {
			STOP1: domain-stop1 {
				compatible = "domain-idle-state";
				arm,psci-suspend-param = <0x00000011>;
			};
			LP_STOP1: domain-lp-stop1 {
				compatible = "domain-idle-state";
				arm,psci-suspend-param = <0x0000021>;
			};
			LPLV_STOP1: domain-lplv-stop1 {
				compatible = "domain-idle-state";
				arm,psci-suspend-param = <0x00000211>;
			};
		};
	};

	d1_pd: power-domain-d1 {
		compatible = "st,stm32mp-pm-domain";
		#power-domain-cells = <0>;
		power-domains = <&cluster_pd>;
	};

	psci {
		compatible = "arm,psci-1.0";
		method = "smc";
		cpu0_pd: power-domain-cpu0 {
			#power-domain-cells = <0>;
			domain-idle-states = <&CPU_PWRDN>;
			power-domains = <&cluster_pd>;
		};
		cpu1_pd: power-domain-cpu1 {
			#power-domain-cells = <0>;
			domain-idle-states = <&CPU_PWRDN>;
			power-domains = <&cluster_pd>;
		};
		cluster_pd: power-domain-cluster {
			#power-domain-cells = <0>;
			domain-idle-states = <&STOP1>, <&LP_STOP1>;
			power-domains = <&ret_pd>;
		};
		ret_pd: power-domain-retention {
			#power-domain-cells = <0>;
			domain-idle-states = <&LPLV_STOP1>;
		};
	};

This power domain hierarchy is used in generic power domain (GenPD) for S2IDLE request and for dynamic power management based on PSCI OS initiated mode PM runtime: Linux kernel selects the lowest possible low power mode with the associated PSCI State Id, according the state of each power domain (device in the power domain is running, wake-up source is activated) and which respects the OS constraint (wake-up latency in OS initiated mode for example).

STM32MP2 power domain.png

The devices are assigned to a domain in Soc device tree according the table named "Functionalities depending on system operating mode" of the STM32 MPU reference manuals (autonomous mode is not managed in OpenSTLinux).

  • d1_pd for peripherals not functional in "Stop1/2 and LP-Stop1/2"
  • ret_pd for peripherals not functional in "LPLV-Stop1/2"

The EXTI1 driver is part of ret_pd because LPLV-Stop1 mode is not not allowed for the Group2 wake up sources which are handled by EXTI1 (see in this table the peripheral Wake-up capability for each mode).

The dynamic power management is based on driver activity with device PM runtime and GenPD, so the STM32MP2 series peripherals in d1_pd which don't support the autosuspend features must be deactivated or stopped manually by user to allow low power modes.

For coprocessor_management_ with A35-TD flavor More info green.png, the Cortex®-M33 firmware is managed by remote proc driver, which select automatically the default power domain cluster_pd when it use DDR, to forbid low power when it is running, or sleep power domain ret_pd when low power is allowed.

		m33_rproc: m33@0 {
			compatible = "st,stm32mp2-m33";
...
			power-domains = <&cluster_pd>, <&ret_pd>;
			power-domain-names = "default", "sleep";
		};

4.2.1. Scheduling in low power mode[edit | edit source]

The Linux scheduling-clock interrupts use a high-resolution kernel timer (hrtimer) provided by LPTIM OpenSTLinux drivers in low power modes when the ARM generic timer is stopped, see timer documentation for details.

It is indicated in SoC device tree with local-timer-stop; for CPU power down state:

		idle-states {
			entry-method = "psci";

			CPU_PWRDN: cpu-power-down {
				compatible = "arm,idle-state";
				arm,psci-suspend-param = <0x00000001>;
				local-timer-stop;
				entry-latency-us = <300>;
				exit-latency-us = <500>;
				min-residency-us = <1000>;
			};
		};

See Documentation/devicetree/bindings/cpu/idle-states.yaml for details.

To avoid scheduling issue, the low power mode cpu-power-down are supported in Linux kernel for S2IDLE/CPUIdle only if at least one hrtimer is registered on the platform and if this timer is functional in low power mode. Without activated hrtimer the CPU is limited to WFI, the default state defined in /sys/devices/system/cpu/cpu0/cpuidle/state0.

For STM32MP2 series, LPTIMy (y = 3, 4, 5) are functional in low power modes (see Table Functionalities depending on system operating mode in reference manual) when they are clocked by LSE or LSI (see Table Kernel clock distribution overview in reference manual).

But for STM32MP21x lines More info.png, the LPTIMy wake-up are not available for LPLV-Stop1 modes, so even if this mode is supported by the SoC, it is not supported by OpenSTLinux to allow scheduling.

For STMicrolectronics board, we are using the LPTIMER3, activated in the board device tree with:

/* use LPTIMER with tick broadcast for suspend mode */
&lptimer3 {
	status = "okay";
	timer {
		status = "okay";
	};
};

We can check if this lp-timer is functional with:

ls /sys/bus/platform/drivers/stm32-lptimer/*.timer
cat /sys/devices/system/clockevents/broadcast/current_device

.

NB: the firewall configuration must provide access by Linux to LPTIM OpenSTLinux drivers resources, including associated interruption.

4.3. S2RAM (PSCI_SYSTEM_SUSPEND)[edit | edit source]

For deep request the PSCI_SYSTEM_SUSPEND is sent to PSCI stack when the secondary core is stopped and all the process are frozen. The activated wake-up are consolidated to select the lowest supported mode in:

  • OP-TEE for STM32MP1 series.
  • TF-A BL31 for STM32MP2 series, based on activated wake up and co-processor activity (See STM32MP2 power overview for details).

4.3.1. STM32MP1 series power domains[edit | edit source]

The lowest power mode on STM32MP15 is based on power domain state of stm32-pm-domain driver in Linux GENPD framework. The power domain activity (with GENPD_FLAG_ACTIVE_WAKEUP , the domain is OFF when wake up are not activated on associated device) is provided to OP-TEE low power is based on proprietary SMC (0x82001008) based on the topology is defined in SoC device tree, arch/arm/boot/dts/st/stm32mp131.dtsi or arch/arm/boot/dts/st/stm32mp151.dtsi :

	pm_domain {
		#address-cells = <1>;
		#size-cells = <0>;
		compatible = "st,stm32mp157c-pd";

		pd_core_ret: core-ret-power-domain@1 {
			#address-cells = <1>;
			#size-cells = <0>;
			reg = <1>;
			#power-domain-cells = <0>;
			label = "CORE-RETENTION";

			pd_core: core-power-domain@2 {
				reg = <2>;
				#power-domain-cells = <0>;
				label = "CORE";
			};
		};
	};

See STM32MP1 power overview for OP-TEE configuration.

5. Source code location[edit | edit source]

The source files are located inside the Linux kernel.

For the framework used in Linux power management, see the associated pages:

And drivers in other software component for each internal peripheral or external component are described in the associated pages:

6. How to trace and debug[edit | edit source]

6.1. suspend/resume[edit | edit source]

The suspend/resume process execution is logged in the MPU console. It gives useful information on the platform state (sleeping or active).

 root@stm32mp1:~# echo mem > /sys/power/state
 [ 1072.267571] PM: suspend entry (deep)
 [ 1072.269687] PM: Syncing filesystems ... done.
 [ 1072.279114] Freezing user space processes ... (elapsed 0.008 seconds) done.
 [ 1072.292835] OOM killer disabled.
 [ 1072.296046] Freezing remaining freezable tasks ... (elapsed 0.001 seconds) done.
 [ 1072.303431] Suspending console(s) (use no_console_suspend to debug)
 [ 1072.332520] dwc2 49000000.usb-otg: suspending usb gadget configfs-gadget
 [ 1072.332537] dwc2 49000000.usb-otg: dwc2_hsotg_ep_disable: called for ep0
 [ 1072.332546] dwc2 49000000.usb-otg: dwc2_hsotg_ep_disable: called for ep0
 [ 1072.468536] Disabling non-boot CPUs ...
 [ 1072.507876] CPU1 killed.
 [ 1072.509635] Enabling non-boot CPUs ...
 [ 1072.510508] CPU1 is up
 [ 1072.527553] dwmac4: Master AXI performs any burst length
 [ 1072.527583] stm32-dwmac 5800a000.ethernet eth0: No Safety Features support found
 [ 1072.527621] stm32-dwmac 5800a000.ethernet eth0: ERROR failed to create debugfs directory
 [ 1072.527631] stm32-dwmac 5800a000.ethernet eth0: stmmac_hw_setup: failed debugFS registration
 [ 1072.588234] dwc2 49000000.usb-otg: resuming usb gadget configfs-gadget
 [ 1072.738469] OOM killer enabled.
 [ 1072.741575] Restarting tasks ... done.
 [ 1072.752596] PM: suspend exit

Get more debug information from the console with the following commands:

echo N > /sys/module/printk/parameters/console_suspend 

This command allows to see the last linux kernel trace and also the PSCI stack traces, in OP-TEE for STM32MP1 and the the TF-A BL31 traces for STM32MP2 (which indicate the selected low power mode).

You can also activate the dynamic debug in Linux:

echo "func pm_dev_dbg +p" > /sys/kernel/debug/dynamic_debug/control
echo "func pm_pr_dbg +p" > /sys/kernel/debug/dynamic_debug/control
echo "func dpm_show_time +p" > /sys/kernel/debug/dynamic_debug/control
echo "func s2idle_loop +p" > /sys/kernel/debug/dynamic_debug/control

And use power sysfs ABI sysfs-devices-power, for example:

echo 1 > /sys/power/pm_debug_messages
echo 0 > /sys/power/pm_async

You can also activate CONFIG_PM_DEBUG and CONFIG_PM_TRACE.

6.2. wakeup interruption[edit | edit source]

For each wakeup device, you can check wakeup status with sysfs ABI sysfs-devices-power, for example:

more `find /sys/devices/. | grep wakeup_active_count`

Moreover, if you activate CONFIG_PM_SLEEP_DEBUG

You can get the IRQ number that triggered the wakeup with:

cat /sys/power/pm_wakeup_irq

And the interruption can be identified with sysfs:

cat /proc/interrupts

6.3. PSCI OSI[edit | edit source]

The PSCI stack in Linux is initialized with OSI support indicated by TFA-BL31:

 dmesg | grep psci
[    0.000000] psci: probing for conduit method from DT.
[    0.000000] psci: PSCIv1.1 detected in firmware.
[    0.000000] psci: Using standard PSCI v0.2 function IDs
[    0.000000] psci: Trusted OS migration not required
[    0.000000] psci: SMC Calling Convention v1.4
[    0.000000] psci: OSI mode supported.

Then you can check the used CUPIdle states with:

more /sys/devices/system/cpu/cpu?/cpuidle/state*/usage | cat
::::::::::::::
/sys/devices/system/cpu/cpu0/cpuidle/state0/usage
::::::::::::::
125645
::::::::::::::
/sys/devices/system/cpu/cpu0/cpuidle/state1/usage
::::::::::::::
711689
::::::::::::::
/sys/devices/system/cpu/cpu1/cpuidle/state0/usage
::::::::::::::
59219
::::::::::::::
/sys/devices/system/cpu/cpu1/cpuidle/state1/usage
::::::::::::::
368800

With:

  • state0: Linux ARM WFI (default chosen by CPUIdle governor, without latency)
  • state1: PSCI CpuIdle with CPU_SUSPEND used to select WFI Stop1, LP-Stop1 or LPLVStop1 mode,
    must be > 0 if OSI is functional

To handle CPUIdle a LP-Timer must be used in low power mode when the ARM generic timer is not available. You can test if this timer is functional with the commands:

ls /sys/bus/platform/drivers/stm32-lptimer/*.timer
cat /sys/devices/system/clockevents/broadcast/current_device
timer@46050000

If it is not the case check is the module (LPTIM driver is compiled as module by defualt) is correctly loaded:

lsmod | grep timer
stm32_lptimer          12288  0

The PSCI and STM32MP power domain driver must also be synchronized, i.e. all the drivers consumer of the power domains are probed

cat /sys/devices/platform/psci/state_synced
1
cat /sys/devices/platform/power-domain-d1/state_synced
1

If it not the case, you must check the log for sync_state issue:

dmesg | grep sync_state
[21.415332] stm32mp_pm_domain power-domain-d1: sync_state() pending due to 48280000.gpu

And check the device associated to the domain driver with devlinks consumer

ls -l /sys/devices/platform/psci/consumer:*
more /sys/devices/platform/psci/consumer:*/status | cat
ls -l /sys/devices/platform/power-domain-d1/consumer:*
more /sys/devices/platform/power-domain-d1/consumer:*/status | cat

The status of each devices must be "active" and not "available".

You can also compare the state of each device in power domain framework with the command

cat /sys/kernel/debug/pm_genpd/pm_genpd_summary

The CPUIdle go in low power mode when the cluster_pd become off.

We have for each power domain, its status ("on"/"off"), the child power domain and the runtime status ("active"/"suspended") of its probed device.

domain                          status          children                           performance
   /device                                             runtime status
------------------------------------------------------------------------------------------
gpu-pd                          off-0                                              0
power-domain-d1                 on                                                 0
    /devices/platform/soc@0/42080000.bus/400e0000.serial  active                     0
    /devices/platform/soc@0/42080000.bus/48230000.mmc   suspended                  0
    /devices/platform/soc@0/42080000.bus/48220000.mmc   suspended                  0
    /devices/platform/soc@0/42080000.bus/42080000.bus:usb@482e0000  active                     0
    /devices/platform/soc@0/42080000.bus/40130000.i2c   suspended                  0
    /devices/platform/soc@0/42080000.bus/480c0000.phy   active                     0
    /devices/platform/soc@0/42080000.bus/42080000.bus:usb@48300000  active                     0
    /devices/platform/soc@0/42080000.bus/48400000.pcie  active                     0
    /devices/platform/soc@0/42080000.bus/42030000.crypto  suspended                  0
    /devices/platform/soc@0/42080000.bus/402d0000.can   suspended                  0
    /devices/platform/soc@0/42080000.bus/402f0000.can   suspended                  0
    /devices/platform/soc@0/42080000.bus/482c0000.eth1  active                     0
    /devices/platform/soc@0/42080000.bus/48030000.dcmipp  suspended                  0
    /devices/platform/soc@0/42080000.bus/480d0000.vdec  suspended                  0
    /devices/platform/soc@0/42080000.bus/480e0000.venc  suspended                  0
    /devices/platform/soc@0/42080000.bus/482d0000.eth2  active                     0
power-domain-cpu1               on                                                 0
    /devices/genpd:0:cpu1                               active                     0
power-domain-retention          on                                                 0
                                                power-domain-cluster
    /devices/platform/soc@0/44220000.interrupt-controller  active                     0
    /devices/platform/soc@0/40400000.dma-controller     active                     0
    /devices/platform/soc@0/40410000.dma-controller     suspended                  0
    /devices/platform/soc@0/40420000.dma-controller     suspended                  0
power-domain-cluster            on                                                 0
                                                 power-domain-cpu0, power-domain-cpu1, power-domain-d1
    /devices/platform/power-domain-d1                   suspended                  0
    /devices/genpd:0:0.m33                              active                     0
power-domain-cpu0               on                                                 0
    /devices/genpd:0:cpu0                               active                     0


By default, the device tree provided by OpenSTLinux for STMicoelectronics board activate ALL the devices, even the devices which don't support the autosuspend feature so the active must be manually deactivated with system command in Linux console.

Please refer to page of each device to found how to deactivate this devices.

Some example with weston :

systemctl stop weston-graphical-session.service
systemctl stop st-m33firmware-load.service
# for ethernet part
systemctl stop netdata
systemctl stop systemd-networkd.socket
systemctl stop systemd-networkd
systemctl stop systemd-resolved
systemctl stop tcf-agent
systemctl stop usbotg-config.service
ip link set <N> down
echo 482c0000.eth1 > /sys/bus/platform/drivers/stm32-dwmac/unbind
echo 482d0000.eth2 > /sys/bus/platform/drivers/stm32-dwmac/unbind
echo 48230000.mmc > /sys/bus/amba/drivers/mmci-pl18x/unbind
# for other services
systemctl disable bluetooth-brcmfmac-sleep
systemctl stop systemd-rfkill.service
systemctl stop tee-supplicant.service
systemctl stop stm32mp-calibration.timer
systemctl stop iiod.service
systemctl stop rng-tools.service
systemctl stop bluetooth.service
systemctl stop rpcbind.service
systemctl stop rpcbind.socket
systemctl stop syslog.socket
systemctl stop systemd-timesyncd.service
systemctl stop ebtables.service
systemctl stop ip6tables.service
systemctl stop iptables.service
systemctl stop systemd-tmpfiles-clean.timer

We are also add device trees in external device tree, which deactivate the device not supported the autosuspend feature and allow to boot with CPUIdle based on PSCI OSI functional.


When CPUIdle with PSCI OSI is functional, you can check the number of request and time passed in each low power mode with:

more /sys/kernel/debug/pm_genpd/power-domain-*/idle_states | cat

Each low power mode are ordered as described in device tree, so:

  • for power-domain-cluster, the idle_states are
    • S0 => Stop1
    • S1 => LP-Stop1
  • for power-domain-retention, the idle_states are
    • S0 => LPLV-Stop1
::::::::::::::
/sys/kernel/debug/pm_genpd/power-domain-cluster/idle_states
::::::::::::::
State          Time Spent(ms) Usage          Rejected
S0             173            86             0
S1             11352          1376           0
::::::::::::::
/sys/kernel/debug/pm_genpd/power-domain-cpu0/idle_states
::::::::::::::
State          Time Spent(ms) Usage          Rejected
S0             17258          3912           0
::::::::::::::
/sys/kernel/debug/pm_genpd/power-domain-cpu1/idle_states
::::::::::::::
State          Time Spent(ms) Usage          Rejected
S0             19026          3728           0
::::::::::::::
/sys/kernel/debug/pm_genpd/power-domain-d1/idle_states
::::::::::::::
State          Time Spent(ms) Usage          Rejected
S0             14319          18             0
::::::::::::::
/sys/kernel/debug/pm_genpd/power-domain-retention/idle_states
::::::::::::::
State          Time Spent(ms) Usage          Rejected
S0             0              0              0

Here we are no LPLV-Stop1 request because the UART used for the console activate autosuspend and wake-up for key press; this UART have to no wake-up capability for LPLV-Stop1/2 system operating mode. To support LPLV-Stop1 feature with console you must use console on LPUART device.

You can check the status of each element of the power domain with the reduce device tree, mmc and serial are active but they support autosuspend, they are suspended after an inactivity of few miliseconds.

cat /sys/kernel/debug/pm_genpd/pm_genpd_summary
domain                          status          children                           performance
   /device                                             runtime status
----------------------------------------------------------------------------------------------
gpu-pd                          off-0                                              0
power-domain-d1                 on                                                 0
   /devices/platform/soc@0/42080000.bus/48230000.mmc   suspended                  0
   /devices/platform/soc@0/42080000.bus/400e0000.serial  active                     0
   /devices/platform/soc@0/42080000.bus/48220000.mmc   active                     0
   /devices/platform/soc@0/42080000.bus/40130000.i2c   suspended                  0
   /devices/platform/soc@0/42080000.bus/402d0000.can   suspended                  0
   /devices/platform/soc@0/42080000.bus/402f0000.can   suspended                  0
   /devices/platform/soc@0/42080000.bus/42030000.crypto  suspended                  0
   /devices/platform/soc@0/42080000.bus/480d0000.vdec  suspended                  0
   /devices/platform/soc@0/42080000.bus/480e0000.venc  suspended                  0
power-domain-cpu1               off-0                                              0
   /devices/genpd:0:cpu1                               suspended                  0
power-domain-retention          on                                                 0
                                               power-domain-cluster
   /devices/platform/soc@0/44220000.interrupt-controller  active                     0
   /devices/platform/soc@0/40400000.dma-controller     active                     0
   /devices/platform/soc@0/40410000.dma-controller     suspended                  0
   /devices/platform/soc@0/40420000.dma-controller     suspended                  0
power-domain-cluster            on                                                 0
                                               power-domain-cpu0, power-domain-cpu1, power-domain-d1
   /devices/platform/power-domain-d1                   suspended                  0
   /devices/genpd:0:0.m33                              suspended                  0
power-domain-cpu0               on                                                 0
   /devices/genpd:0:cpu0                               active                     0

6.4. other debug tips[edit | edit source]

To go further see the kernel documentation power/basic-pm-debugging.rst and power/s2ram.rst.

It is also possible to monitor the hardware signals related to the system low-power modes thanks to the HDP internal peripheral.
Please refer to HDP Linux driver for its configuration.

7. To go further[edit | edit source]

Please refer to the STM32MPU reference manuals for a detailed description of low-power modes and peripheral wakeup sources and to pages:

See documentation in Linux and presentations:

8. References[edit | edit source]

  1. Arm Power State Coordination Interface (PSCI):
    https://developer.arm.com/documentation/den0022
  2. Arm System Control and Management Interface Platform Design Document (SCMI) specification:
    https://developer.arm.com/documentation/den0056
  3. Linaro connect presentation "Device Power Management for Idle"