Registered User |
Registered User Tag: 2017 source edit |
||
(292 intermediate revisions by 16 users not shown) | |||
Line 1: | Line 1: | ||
<noinclude> | <noinclude>{{ApplicableFor | ||
{{ | |MPUs list=STM32MP13x, STM32MP15x, STM32MP21x, STM32MP23x, STM32MP25x | ||
{{ | |MPUs checklist=STM32MP13x, STM32MP15x, STM32MP21x, STM32MP23x, STM32MP25x | ||
{{ | }} | ||
</noinclude> | |||
==Framework purpose== | |||
The purpose of this article is to explain the Linux<sup>®</sup> Power Management on {{MicroprocessorDevice | device=Class}}: | |||
* 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 | |||
==Software overview== | |||
The Linux<sup>®</sup> 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: | |||
** CPUfreq, Devfreq (see the page [[How to change the CPU frequency]] for details) | |||
** OPP with link to [[Thermal_overview|thermal framework]] | |||
** Genpd (performance states) | |||
** Runtime Power Management (RPM or runtime RPM): dynamically disable the resources of the peripherals (clocks and power supply when applicable) in case of inactivity (see {{DocSource | domain=Linux kernel | path=power/runtime_pm.html }}). | |||
*** [[Clock overview|Clocks]] | |||
*** [[Regulator overview|Regulators]] | |||
*** [[SCMI_overview|SCMI framework]] for system resources | |||
Refer to Linux documentation for more details, for example pages in {{DocSource | domain=Linux kernel | path=power | text=Documentation/power}} and in {{DocSource | domain=Linux kernel | path=admin-guide/pm |text=Documentation/admin-guide/pm}}. | |||
The OpenSTLinux power management support is based on Arm<sup>®</sup> interface specifications: | |||
* ''Power state coordination interface'' (PSCI) <ref> ''Arm Power State Coordination Interface'' (PSCI):<br>https://developer.arm.com/documentation/den0022</ref> | |||
* ''System Control and Management Interface'' (SCMI)<ref>Arm System Control and Management Interface Platform Design Document (SCMI) specification:<br>https://developer.arm.com/documentation/den0056</ref> | |||
==={{MicroprocessorDevice | device=1}}=== | |||
On {{MicroprocessorDevice | device=1}}, the "System-Wide Power Management" is supported: | |||
[[File:Power mgt.png|link=]] | |||
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. | |||
==={{MicroprocessorDevice | device=2}}=== | |||
The "System-Wide Power Management" is supported, the low power modes are requested to TF-A BL31 with PSCI API. | |||
[[File:STM32MP2_Power mgt.png|link=]] | |||
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 {{TrustedDomainFlavor | flavor=M33-TD}}, Linux use the same PSCI but DDR is not managed in TF-A; the low power request is forwarded to [[TF-M overview|TF-M]]. | |||
===Component description=== | |||
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 {{MicroprocessorDevice | device=1}}. | |||
* '''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 {{MicroprocessorDevice | device=1}} : | |||
* '''Low power driver''': the role of this driver is to choose the low-power mode according to the programmed wakeup source(s) | |||
* [[PWR_internal_peripheral|'''PWR driver''']]: this driver is responsible for configuring the low-power mode | |||
* [[RCC_internal_peripheral|'''RCC driver''']]: this driver handles the circuit secure clocks | |||
* '''PSCI libray''': generic PSCI stack | |||
Secure world components (OP-TEE) on AArch64 platforms for {{MicroprocessorDevice | device=2}}: | |||
* '''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 {{MicroprocessorDevice | device=2}} | |||
* '''PM''' manage PSCI topology and modes and DDR self refresh | |||
* '''PSCI libray''': generic PSCI stack | |||
* '''DDR driver''': DDR driver (only for {{TrustedDomainFlavor | flavor=A35-TD}}) | |||
STM32 peripherals (Hardware): | |||
* [[RCC_internal_peripheral|'''RCC''']] | |||
* [[PWR_internal_peripheral|'''PWR''']] | |||
* [[DDRCTRL_and_DDRPHYC_internal_peripherals|'''DDR''']] | |||
===API description=== | |||
The suspend process is triggered from the user space through standard commands (see next [[#How to use the framework|chapter]] for details). | |||
The system sleep control file is the ''state'' file, located under: /sys/power/<br/> | |||
Further details can be found in {{DocSource | domain=Linux kernel | path=admin-guide/pm/sleep-states.html}}. | |||
The sysfs ABI are described in {{DocSource | domain=Linux kernel | path=admin-guide/abi-testing.html#abi-sys-power | text=sysfs-power}} and {{DocSource | domain=Linux kernel | path=admin-guide/abi-testing.html#abi-sys-devices-power | text=sysfs-devices-power}}. | |||
The device power API are described in {{DocSource | domain=Linux kernel | path=driver-api/pm/index.html}}, in particular in {{DocSource | domain=Linux kernel | path=driver-api/pm/devices.html}}. | |||
==Configuration == | |||
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. | |||
===Kernel configuration=== | |||
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 | Menuconfig or how to configure kernel ]]. | |||
===Device tree configuration=== | |||
==== {{MicroprocessorDevice | device=1}} ==== | |||
The default system low-power mode mapping can be modified through the secure monitor device tree, as described OP-TEE {{CodeSource | OP-TEE_OS | documentation/devicetree/bindings/regulator/st,stm32mp1-pwr-reg.yaml}}. | |||
See [[STM32MP1 power overview]] for impacts on OP-TEE device tree. | |||
==== {{MicroprocessorDevice | device=2}} ==== | |||
The | The SoC device tree describes the [[STM32MP2_power_overview#PSCI_topology|PSCI topology]] in sub-nodes of <code>cpus/domain-idle-states</code> in SOC device tree, one node for each PSCI_CPU_SUSPEND supported parameter (only the Stop1 modes). | ||
== | For example in {{CodeSource | Linux kernel | 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 [[PMIC_hardware_components|STPMIC]], if the PWR_LP pins control the reduced voltage mode of the V<sub>DDCORE</sub> and V<sub>DDCPU</sub> regulators, then only LPLV-Stop1 modes can be reached. LP-Stop1 modes must be deleted in Linux device tree (CLUSTER_PD <code>domain-idle-states = <&STOP1>, <&LP_STOP1>;</code> 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. | |||
==How to use the framework== | |||
The power framework is managed with [[#API description|userfs API]]. | |||
For [[Wayland_Weston_overview|Weston]] OpenSTLinux distribution, the direct access to sysfs must be avoided and must be replaced by <code>systemctl</code> command to correctly stop the systemd services and avoid issues on next wake-up. | |||
{| class=" | {| class="st-table" | ||
|+ | |||
! rowspan=2 | Linux mode | |||
! rowspan=2 | userFS API | |||
! rowspan=2 | command | |||
! rowspan=2 style="text-align: center;" | {{MicroprocessorDevice | device=1}} | |||
! colspan=2 style="text-align: center;" | {{MicroprocessorDevice | device=2}} | |||
|- | |- | ||
! | ! {{MicroprocessorDevice | device=21}} | ||
! {{MicroprocessorDevice | device=23}}<br/>{{MicroprocessorDevice | device=25}} | |||
|- | |- | ||
| | | rowspan=2 |{{highlightParam|S2Idle}}<br>'''Suspend-to-Idle''' (or freeze) | ||
| rowspan=2 |{{Board$}}echo freeze > /sys/power/state | |||
| rowspan=2 |with <code>SuspendState=freeze</code> in /etc/systemd/sleep.conf<br/>{{Board$}}systemctl suspend | |||
| rowspan=2 tyle="text-align: center;" |{{highlight|not supported}} | |||
| colspan=2 style="text-align: center;" | Stop1<br>LP-Stop1 | |||
|- | |- | ||
| | | style="text-align: center;" | <ref group="lp">{{highlight|LPLV-Stop1}} is '''not supported''' in OpenSTLinux for {{MicroprocessorDevice | device=21}} as Linux have no [[#Scheduling_in_low_power_mode|HR timer]] available in this mode.</ref> | ||
| style="text-align: center;" | LPLV-Stop1 | |||
|- | |- | ||
| | | rowspan=2 |{{highlightParam|S2RAM}} <br> '''Suspend-to-RAM''' (or deep) | ||
| rowspan=2 |{{Board$}}echo mem > /sys/power/state<ref group="lp">"deep" for S2RAM is the default suspend variants associated with the "mem" string in the ``state`` file<br>{{Board$}}cat /sys/power/mem_sleep<br>s2idle [deep]</ref> | |||
| rowspan=2 |with <code>SuspendState=mem</code> in /etc/systemd/sleep.conf<br> | |||
{{Board$}}systemctl suspend | |||
| rowspan=2 style="text-align: center;" |Stop<br>LP-Stop<br>LPLV-Stop<br>Standby | |||
| colspan=2 style="text-align: center;" |Run2<ref group="lp">{{highlight|Run2}} is only supported for {{TrustedDomainFlavor | flavor=M33-TD}}</ref><br>Stop2<br>LP-Stop2<br>LPLV-Stop2 | |||
|- | |- | ||
| | | style="text-align: center;" | Standby | ||
| style="text-align: center;" | Standby1 | |||
|- | |- | ||
| | | rowspan=2 | {{highlightParam|power off}} | ||
| rowspan=2 | | |||
| rowspan=2 | {{Board$}}shutdown -P now<br>{{Board$}}systemctl poweroff | |||
| rowspan=2 | Standby (DDR off) | |||
| style="text-align: center;" | Standby | |||
| style="text-align: center;" | Standby2 | |||
|- | |- | ||
| | | colspan=2 style="text-align: center;" | V<sub>BAT</sub> | ||
|} | |} | ||
===Wakeup sources=== | <references group="lp" /> | ||
See platform power page for more details on each family: | |||
* [[STM32MP1 power overview]] | |||
* [[STM32MP2 power overview]] | |||
In OpenSTLinux, the low power modes are selected with devices activity and with activated wake up sources. | |||
{{Info| You must be sure your wakeup device is able to provide the wake up signal during low-power mode. | |||
E.g. supply, clock, reset, etc... must be present, if any}} | |||
Each sysfs device in ''/sys/devices/'' that supports wake up contains the file <code>wakeup</code> 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: | |||
{{Board$}}find /sys/devices/platform | grep 'power/wakeup$' | |||
You can check or control the wake up source with: | |||
{{Board$}}cat /sys/devices/platform/<device>/power/wakeup | |||
{{Board$}}echo enabled > /sys/devices/platform/<device>/power/wakeup | |||
{{Board$}}echo disabled > /sys/devices/platform/<device>/power/wakeup | |||
For Arm<sup>®</sup> Cortex<sup>®</sup>-M coprocessor, the platform selects the allowed system modes depending of the MCU state and if firmware use the DDR.<br/>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 [[Linux_remoteproc_framework_overview#Remote_processor_stop|stop the MCU firmware]] when DDR is used by this firmware. Please refer to [[Cortex-M coprocessor power management]] for Arm<sup>®</sup> Cortex<sup>®</sup>-M commands. | |||
====Examples==== | |||
With default wake up source (RTC, Wakeup pins), the deepest platform mode is selected: Standby on {{MicroprocessorDevice | device=1}} / Standby on {{MicroprocessorDevice | device=21}} / Standby1 on {{MicroprocessorDevice | device=23}} and {{MicroprocessorDevice | device=25}}. | |||
The activation of other wake-up sources prevents entering into this deepest low-power mode. | |||
===== PWR WKUP pins ===== | |||
If [[How to configure PWR Wake-up pins|PWR wake-up pins]] are enabled, for example see the [[LEDs_and_buttons_on_STM32_MPU_boards#Buttons|WKUP button]] on STMicroelectronics boards, you can directly use the next command to call the low power entry: | |||
{{Board$}}systemctl suspend {{highlight|for weston}} | |||
{{Board$}}echo mem > /sys/power/state {{highlight|for distribution without <code>systemctl</code>}} | |||
Press the WKUP button on STMicroelectronics boards to wake up the board. | |||
===== RTC wake up ===== | |||
| | |||
The [[RTC overview|RTC]] wake up is activated by default in Linux (<code>/sys/devices/platform/*/*.rtc/power/wakeup</code>), so you just need to [[How_to_use_the_RTC|program the alarm]]. | |||
The tools <code>rtcwake</code> is used to enter a system sleep state until specified wake up time, for example 5 seconds with: | |||
{{Board$}}rtcwake --date +5sec -m mem | |||
===== Serial wake-up ===== | |||
== | With [[USART_internal_peripheral|USART]] wake-up enabled, the low-power mode is limited to | ||
* LPLV-Stop on {{MicroprocessorDevice | device=13}} | |||
* LP-Stop on {{MicroprocessorDevice | device=15}} | |||
* LP-Stop2 on {{MicroprocessorDevice | device=2}}. | |||
Enable serial wake up on associated TTY wake up source, for example | |||
{{Board$}}echo enabled > /sys/class/tty/ttySTM0/power/wakeup | |||
Call the low-power entry command | |||
{{Board$}}systemctl suspend {{highlight|for weston}} | |||
{{Board$}}echo mem > /sys/power/state {{highlight|for distribution without <code>systemctl</code>}} | |||
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. | |||
===== GPIO wake-up ===== | |||
== | For [[GPIO_internal_peripheral|GPIO]] wake-up enabled, the low-power mode is limited at LPLV-Stop on {{MicroprocessorDevice | device=1}} / LPLV-Stop2 on {{MicroprocessorDevice | device=2}}. | ||
To enable test GPIO wake up, adds the wake up support with the property <code>wakeup-source</code> 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: | |||
* | * {{MicroprocessorDevice | device=13}} | ||
&user-pa13 { | |||
wakeup-source; | |||
}; | |||
* | * {{MicroprocessorDevice | device=15}} | ||
* | / { | ||
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; | |||
}; | |||
}; | |||
* | * {{MicroprocessorDevice | device=2}} | ||
&button-user-1 { | |||
wakeup-source; | |||
}; | |||
Call the low-power entry command: | |||
{{Board$}}systemctl suspend {{highlight|for weston}} | |||
{{Board$}}echo mem > /sys/power/state {{highlight|for distribution without <code>systemctl</code>}} | |||
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 [[Overview_of_GPIO_pins|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 | |||
=== PSCI in Linux === | |||
The low power modes selection in OpenSTLinux use the PSCI stack: | |||
* in OP-TEE for {{MicroprocessorDevice | device=1}}, see [[STM32MP2 power overview]] for details | |||
* in TF-A BL31 for {{MicroprocessorDevice | device=2}}, see [[STM32MP1 power overview]] for details | |||
=== S2IDLE and CPUIdle (PSCI_CPU_SUSPEND) === | |||
This mode is NOT supported for {{MicroprocessorDevice | device=1}}. | |||
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 {{CodeSource|Linux kernel|Documentation/devicetree/bindings/arm/psci.yaml}}. | |||
= | For example for {{MicroprocessorDevice | device=25}}, in {{CodeSource|Linux kernel|arch/arm64/boot/dts/st/stm32mp251.dtsi}} and in {{CodeSource|Linux kernel|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). | |||
= | [[File:STM32MP2_power_domain.png|link=]] | ||
The | 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 resources#Reference manuals|STM32 MPU reference manuals]] (autonomous mode is not managed in OpenSTLinux). | ||
* {{highlight|d1_pd}} for peripherals not functional in '''"Stop1/2 and LP-Stop1/2"''' | |||
* {{highlight|ret_pd}} for peripherals not functional in '''"LPLV-Stop1/2"''' | |||
The EXTI1 driver is part of {{highlight|ret_pd}} because LPLV-Stop1 mode is not not allowed for the [[STM32MP2_power_overview#Low-power_modes|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 {{MicroprocessorDevice | device=2}} peripherals in {{highlight|d1_pd}} which don't support the '''autosuspend''' features must be deactivated or stopped manually by user to allow low power modes. | |||
For | For [[Cortex-M_coprocessor_management_overview|coprocessor_management_]] with {{TrustedDomainFlavor | flavor=A35-TD}}, the Cortex<sup>®</sup>-M33 firmware is managed by [[Linux_remoteproc_framework_overview|remote proc driver]], which select automatically the ''default'' power domain {{highlight|cluster_pd}} when it use DDR, to forbid low power when it is running, or ''sleep'' power domain {{highlight|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"; | |||
}; | |||
==== Scheduling in low power mode ==== | |||
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 {{DocSource | domain=Linux kernel | path=timers/ | text=timer documentation}} for details. | |||
It is indicated in SoC device tree with {{highlight|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>; | |||
{{highlight|local-timer-stop;}} | |||
entry-latency-us = <300>; | |||
exit-latency-us = <500>; | |||
min-residency-us = <1000>; | |||
}; | |||
}; | |||
See {{CodeSource|Linux kernel|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 {{MicroprocessorDevice | device=2}}, 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 {{highlightParam|LSE}} or {{highlightParam|LSI}} (see Table ''Kernel clock distribution overview'' in reference manual). | ||
But for {{MicroprocessorDevice | device=21}}, the LPTIMy wake-up are not available for '''{{highlight|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: | |||
{{Board$}}ls /sys/bus/platform/drivers/stm32-lptimer/*.timer | |||
{{Board$}}cat /sys/devices/system/clockevents/broadcast/current_device | |||
{{Info|The modules associated to the lptimer driver must be correctly loaded; on OpenSTLinux, the [[LPTIM OpenSTLinux drivers|MFD LPTIM Linux driver]] is compiled in module by default (CONFIG_MFD_STM32_LPTIMER), if <code>lsmod</code> command does not show this module run the command <code>modprobe stm32-lptimer</code> to get it properly loaded.}}. | |||
NB: the [[LPTIM_internal_peripheral#Runtime_assignment|firewall configuration]] must provide access by Linux to [[LPTIM OpenSTLinux drivers]] resources, including associated interruption. | |||
=== S2RAM (PSCI_SYSTEM_SUSPEND) === | |||
== | For <code>deep</code> 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 {{MicroprocessorDevice | device=1}}. | |||
* TF-A BL31 for {{MicroprocessorDevice | device=2}}, based on activated wake up and co-processor activity (See [[STM32MP2 power overview]] for details). | |||
==== {{MicroprocessorDevice | device=1}} power domains ==== | |||
The lowest power mode on STM32MP15 is based on power domain state of {{CodeSource|Linux kernel | drivers/soc/st/stm32_pm_domain.c | 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 (<code>0x82001008</code>) based on the topology is defined in SoC device tree, {{CodeSource|Linux kernel|arch/arm/boot/dts/st/stm32mp131.dtsi}} or {{CodeSource|Linux kernel|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. | |||
==Source code location== | |||
The source files are located inside the Linux kernel. | |||
*'''power core''': | |||
** {{CodeSource | Linux kernel | kernel/power/}} | |||
*'''power drivers''': | |||
** {{CodeSource | Linux kernel | drivers/base/power/ }} | |||
*** GENPD driver: {{CodeSource | Linux kernel | drivers/base/power/domain.c | domain.c}} | |||
** CPUIdle driver: {{CodeSource | Linux kernel | drivers/cpuidle/ }} | |||
*** {{CodeSource | Linux kernel |drivers/cpuidle/dt_idle_genpd.c|dt_idle_genpd.c}} | |||
*** {{CodeSource | Linux kernel |drivers/cpuidle/cpuidle-psci.c|cpuidle-psci.c}} | |||
*** {{CodeSource | Linux kernel |drivers/cpuidle/cpuidle-psci-domain.c|cpuidle-psci-domain.c}} | |||
** PSCI drivers: | |||
*** {{CodeSource | Linux kernel |drivers/firmware/psci/}} | |||
*** {{CodeSource | Linux kernel |arch/arm64/kernel/psci.c}} | |||
*** {{CodeSource | Linux kernel |arch/arm/kernel/psci_smp.c}} | |||
** STM32MP specific driver: | |||
*** {{CodeSource | Linux kernel | drivers/soc/st/stm32_pm_domain.c}} for {{MicroprocessorDevice | device=1}} | |||
*** {{CodeSource | Linux kernel | drivers/pmdomain/st/stm32mp-pm-domain.c}} for {{MicroprocessorDevice | device=2}} | |||
*'''bindings''': | |||
** {{CodeSource | Linux kernel | Documentation/devicetree/bindings/power/}} for generic power bindings | |||
*** {{CodeSource | Linux kernel | Documentation/devicetree/bindings/power/domain-idle-state.yaml | domain-idle-state.yaml}} | |||
*** {{CodeSource | Linux kernel | Documentation/devicetree/bindings/power/power-domain.yaml | power-domain.yaml}} | |||
*** {{CodeSource | Linux kernel | Documentation/devicetree/bindings/power/wakeup-source.txt | wakeup-source.txt}} | |||
** {{CodeSource | Linux kernel | Documentation/devicetree/bindings/arm/psci.yaml}} | |||
** {{CodeSource | Linux kernel |Documentation/devicetree/bindings/soc/st/stm32mp-pm-domain.yaml | stm32mp-pm-domain.yaml}} | |||
For the framework used in Linux power management, see the associated pages: | |||
* [[SCMI overview]] | |||
* [[Reset overview]] | |||
* [[Clock overview]] | |||
* [[Regulator_overview]] | |||
* [[Thermal overview]] | |||
And drivers in other software component for each internal peripheral or external component are described in the associated pages: | |||
* [[PWR_internal_peripheral|PWR]] | |||
* [[PMIC_hardware_components|PMIC]] | |||
==How to trace and debug== | ==How to trace and debug== | ||
===suspend/resume=== | |||
The suspend/resume process execution is logged in the MPU console. It gives useful information on the platform state (sleeping or active). | The suspend/resume process execution is logged in the MPU console. It gives useful information on the platform state (sleeping or active). | ||
Line 247: | Line 546: | ||
[ 1072.752596] PM: suspend exit | [ 1072.752596] PM: suspend exit | ||
Get more debug information from the console with the following commands: | |||
{{Board$}}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: | |||
{{Board$}}echo "func pm_dev_dbg +p" > /sys/kernel/debug/dynamic_debug/control | |||
{{Board$}}echo "func pm_pr_dbg +p" > /sys/kernel/debug/dynamic_debug/control | |||
{{Board$}}echo "func dpm_show_time +p" > /sys/kernel/debug/dynamic_debug/control | |||
{{Board$}}echo "func s2idle_loop +p" > /sys/kernel/debug/dynamic_debug/control | |||
And use power [[#API_description|sysfs ABI]] {{DocSource | domain=Linux kernel | path=admin-guide/abi-testing.html#abi-sys-devices-power | text=sysfs-devices-power}}, for example: | |||
{{Board$}}echo 1 > /sys/power/pm_debug_messages | |||
{{Board$}}echo 0 > /sys/power/pm_async | |||
You can also activate <code>CONFIG_PM_DEBUG</code> and <code>CONFIG_PM_TRACE</code>. | |||
===wakeup interruption=== | |||
For each wakeup device, you can check wakeup status with [[#API_description|sysfs ABI]] {{DocSource | domain=Linux kernel | path=admin-guide/abi-testing.html#abi-sys-devices-power | text=sysfs-devices-power}}, for example: | |||
{{Board$}}more `find /sys/devices/. | grep wakeup_active_count` | |||
Moreover, if you activate <code>CONFIG_PM_SLEEP_DEBUG</code> | |||
You can get the IRQ number that triggered the wakeup with: | |||
{{Board$}}cat /sys/power/pm_wakeup_irq | |||
And the interruption can be identified with [[Interrupt_overview#Kernel_space_API|sysfs]]: | |||
{{Board$}}cat /proc/interrupts | |||
===PSCI OSI=== | |||
The PSCI stack in Linux is initialized with OSI support indicated by TFA-BL31: | |||
{{Board$}} 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] {{highlight|psci: OSI mode supported.}} | |||
Then you can check the used CUPIdle states with: | |||
{{Board$}}more /sys/devices/system/cpu/cpu?/cpuidle/state*/usage | cat | |||
:::::::::::::: | |||
/sys/devices/system/cpu/cpu0/cpuidle/{{highlightParam|state0}}/usage | |||
:::::::::::::: | |||
125645 | |||
:::::::::::::: | |||
/sys/devices/system/cpu/cpu0/cpuidle/{{highlight|state1}}/usage | |||
:::::::::::::: | |||
711689 | |||
:::::::::::::: | |||
/sys/devices/system/cpu/cpu1/cpuidle/{{highlightParam|state0}}/usage | |||
:::::::::::::: | |||
59219 | |||
:::::::::::::: | |||
/sys/devices/system/cpu/cpu1/cpuidle/{{highlight|state1}}/usage | |||
:::::::::::::: | |||
368800 | |||
With: | |||
* {{highlightParam|state0}}: Linux ARM WFI (default chosen by CPUIdle governor, without latency) | |||
* {{highlight|state1}}: PSCI CpuIdle with CPU_SUSPEND used to select WFI Stop1, LP-Stop1 or LPLVStop1 mode,<br/>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: | |||
{{Board$}}ls /sys/bus/platform/drivers/stm32-lptimer/*.timer | |||
{{Board$}}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: | |||
{{Board$}}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 | |||
{{Board$}}cat /sys/devices/platform/psci/state_synced | |||
1 | |||
{{Board$}}cat /sys/devices/platform/power-domain-d1/state_synced | |||
1 | |||
If it not the case, you must check the log for <code>sync_state</code> issue: | |||
{{Board$}}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'' | |||
{{Board$}}ls -l /sys/devices/platform/psci/consumer:* | |||
{{Board$}}more /sys/devices/platform/psci/consumer:*/status | cat | |||
{{Board$}}ls -l /sys/devices/platform/power-domain-d1/consumer:* | |||
{{Board$}}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 | |||
{{Board$}}cat /sys/kernel/debug/pm_genpd/pm_genpd_summary | |||
The CPUIdle go in low power mode when the {{highlight|cluster_pd}} become '''off'''. | |||
We have for each {{highlight|power domain}}, its status ("on"/"off"), the {{highlightParam|child power domain}} and the runtime status ("active"/"suspended") of its probed device. | |||
domain status children performance | |||
/device runtime status | |||
------------------------------------------------------------------------------------------ | |||
{{highlight|gpu-pd}} off-0 0 | |||
{{highlight|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 | |||
{{highlight|power-domain-cpu1}} on 0 | |||
/devices/genpd:0:cpu1 active 0 | |||
{{highlight|power-domain-retention}} on 0 | |||
{{highlightParam|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 | |||
{{highlight|power-domain-cluster}} on 0 | |||
{{highlightParam|power-domain-cpu0, power-domain-cpu1, power-domain-d1}} | |||
/devices/platform/power-domain-d1 suspended 0 | |||
/devices/genpd:0:0.m33 active 0 | |||
{{highlight|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 : | |||
{{Board$}}systemctl stop weston-graphical-session.service | |||
{{Board$}}systemctl stop st-m33firmware-load.service | |||
''{{Green|# for ethernet part}}'' | |||
{{Board$}}systemctl stop netdata | |||
{{Board$}}systemctl stop systemd-networkd.socket | |||
{{Board$}}systemctl stop systemd-networkd | |||
{{Board$}}systemctl stop systemd-resolved | |||
{{Board$}}systemctl stop tcf-agent | |||
{{Board$}}systemctl stop usbotg-config.service | |||
{{Board$}}ip link set <N> down | |||
{{Board$}}echo 482c0000.eth1 > /sys/bus/platform/drivers/stm32-dwmac/unbind | |||
{{Board$}}echo 482d0000.eth2 > /sys/bus/platform/drivers/stm32-dwmac/unbind | |||
{{Board$}}echo 48230000.mmc > /sys/bus/amba/drivers/mmci-pl18x/unbind | |||
''{{Green|# for other services}}'' | |||
{{Board$}}systemctl disable bluetooth-brcmfmac-sleep | |||
{{Board$}}systemctl stop systemd-rfkill.service | |||
{{Board$}}systemctl stop tee-supplicant.service | |||
{{Board$}}systemctl stop stm32mp-calibration.timer | |||
{{Board$}}systemctl stop iiod.service | |||
{{Board$}}systemctl stop rng-tools.service | |||
{{Board$}}systemctl stop bluetooth.service | |||
{{Board$}}systemctl stop rpcbind.service | |||
{{Board$}}systemctl stop rpcbind.socket | |||
{{Board$}}systemctl stop syslog.socket | |||
{{Board$}}systemctl stop systemd-timesyncd.service | |||
{{Board$}}systemctl stop ebtables.service | |||
{{Board$}}systemctl stop ip6tables.service | |||
{{Board$}}systemctl stop iptables.service | |||
{{Board$}}systemctl stop systemd-tmpfiles-clean.timer | |||
It is also possible to monitor the hardware signals related to the system low-power modes thanks to the [[HDP internal peripheral]].< | 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. | ||
* {{CodeSource | External_DT | a35-td/linux/stm32mp215f-dk-psci-osi.dts}} | |||
* {{CodeSource | External_DT | a35-td/linux/stm32mp257f-ev1-psci-osi.dts}} | |||
When CPUIdle with PSCI OSI is functional, you can check the number of request and time passed in each low power mode with: | |||
{{Board$}}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 | |||
** {{highlight|S0}} => Stop1 | |||
** {{highlightParam|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 | |||
{{highlight|S0}} {{highlight|173}} {{highlight|86}} 0 | |||
{{highlightParam|S1}} {{highlightParam|11352}} {{highlightParam|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. | |||
{{Board$}}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 | |||
===other debug tips=== | |||
To go further see the kernel documentation | |||
{{DocSource | domain=Linux kernel | path=power/basic-pm-debugging.html | text=power/basic-pm-debugging.rst}} and {{DocSource | domain=Linux kernel | path=power/s2ram.html | text=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]].<br> | |||
Please refer to [[HDP Linux driver]] for its configuration. | Please refer to [[HDP Linux driver]] for its configuration. | ||
==To go further== | ==To go further== | ||
Please refer to the [[STM32 MPU resources#Reference manuals|STM32MPU reference manuals]] for a detailed description of low-power modes and peripheral wakeup sources and to [[Category:Platform_power|platform power]] pages: | |||
* [[STM32MP1 power overview]] | |||
* [[STM32MP2 power overview]] | |||
See documentation in Linux and presentations: | |||
* {{DocSource | domain=Linux kernel | path=power | text=Documentation/power}} | |||
* {{DocSource | domain=Linux kernel | path=admin-guide/pm |text=Documentation/admin-guide/pm}}. | |||
* Linaro connect presentation "Device Power Management for Idle"<ref>[https://static.linaro.org/connect/san19/presentations/san19-421.pdf Linaro connect presentation "Device Power Management for Idle"]</ref> | |||
==References== | |||
<references /> | |||
<noinclude> | |||
[[Category:Power and Thermal|0]] | |||
{{ArticleBasedOnModel | Framework overview article model}} | |||
{{PublicationRequestId | 10387 | 2019-01-21 |AnneJ}} | |||
</noinclude> |
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 :
- 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:
- CPUfreq, Devfreq (see the page How to change the CPU frequency for details)
- OPP with link to thermal framework
- Genpd (performance states)
- Runtime Power Management (RPM or runtime RPM): dynamically disable the resources of the peripherals (clocks and power supply when applicable) in case of inactivity (see power/runtime_pm.html).
- Clocks
- Regulators
- SCMI framework for system resources
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:
2.1. STM32MP1 series[edit | edit source]
On STM32MP1 series, the "System-Wide Power Management" is supported:
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.
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 , 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
)
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
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>; }; };domain-idle-states { STOP1: domain-stop1 { compatible = "domain-idle-state"; arm,psci-suspend-param = <0x00000011>; };
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 ![]() |
STM32MP23x lines ![]() STM32MP25x lines ![]() | ||||
S2Idle Suspend-to-Idle (or freeze) |
echo freeze > /sys/power/state | with SuspendState=freeze in /etc/systemd/sleep.confsystemctl 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.confsystemctl 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 |
- ↑ LPLV-Stop1 is not supported in OpenSTLinux for STM32MP21x lines
as Linux have no HR timer available in this mode.
- ↑ "deep" for S2RAM is the default suspend variants associated with the "mem" string in the ``state`` file
cat /sys/power/mem_sleep
s2idle [deep] - ↑ Run2 is only supported for M33-TD flavor
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.
![]() |
You must be sure your wakeup device is able to provide the wake up signal during low-power mode.
E.g. supply, clock, reset, etc... must be present, if any |
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 / Standby1 on STM32MP23x lines
and STM32MP25x lines
.
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:
for weston
echo mem > /sys/power/state for distribution without systemctl
systemctl suspend 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
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
for weston
echo mem > /sys/power/state for distribution without systemctl
systemctl suspend 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:
&user-pa13 {
wakeup-source;
};
GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; wakeup-source; }; };/ { 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 (
- STM32MP2 series
&button-user-1 {
wakeup-source;
};
Call the low-power entry command:
for weston
echo mem > /sys/power/state for distribution without systemctl
systemctl suspend 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:
- in OP-TEE for STM32MP1 series, see STM32MP2 power overview for details
- in TF-A BL31 for STM32MP2 series, see STM32MP1 power overview for details
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 , in arch/arm64/boot/dts/st/stm32mp251.dtsi and in arch/arm64/boot/dts/st/stm32mp253.dtsi is described by:
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>; }; };/ { cpus { idle-states { entry-method = "psci";
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).
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 , 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:
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>; }; };idle-states { entry-method = "psci";
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 , 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
![]() |
The modules associated to the lptimer driver must be correctly loaded; on OpenSTLinux, the MFD LPTIM Linux driver is compiled in module by default (CONFIG_MFD_STM32_LPTIMER), if lsmod command does not show this module run the command modprobe stm32-lptimer to get it properly loaded.
|
.
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.
- power core:
- power drivers:
- drivers/base/power/
- GENPD driver: domain.c
- CPUIdle driver: drivers/cpuidle/
- PSCI drivers:
- STM32MP specific driver:
- drivers/soc/st/stm32_pm_domain.c for STM32MP1 series
- drivers/pmdomain/st/stm32mp-pm-domain.c for STM32MP2 series
- drivers/base/power/
- bindings:
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).
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 exitroot@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]
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:
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.dmesg | grep psci [ 0.000000] psci: probing for conduit method from
Then you can check the used CUPIdle states with:
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 :::::::::::::: 368800more /sys/devices/system/cpu/cpu?/cpuidle/state*/usage | cat :::::::::::::: /sys/devices/system/cpu/cpu0/cpuidle/
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.
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 0domain status children performance /device runtime status ------------------------------------------------------------------------------------------
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 :
# 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.timersystemctl stop weston-graphical-session.service systemctl stop st-m33firmware-load.service
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
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:::::::::::::: /sys/kernel/debug/pm_genpd/power-domain-cluster/idle_states :::::::::::::: State Time Spent(ms) Usage Rejected
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:
- Documentation/power
- Documentation/admin-guide/pm.
- Linaro connect presentation "Device Power Management for Idle"[3]
8. References[edit | edit source]
- ↑ Arm Power State Coordination Interface (PSCI):
https://developer.arm.com/documentation/den0022 - ↑ Arm System Control and Management Interface Platform Design Document (SCMI) specification:
https://developer.arm.com/documentation/den0056 - ↑ Linaro connect presentation "Device Power Management for Idle"