This article gives information about the support power management in OpenSTlinux for STM32MP2 series.
1. Framework purpose[edit | edit source]
The purpose of this article is to explain how OpenSTlinux components handle the STM32MP2 series power management:
- Software overview
- Peripheral power support
- Low-power modes available on the device
See also the page How to define your low-power strategy.
2. Software overview[edit | edit source]
The system power request is treated with the PSCI support with TF-A.
The power requests associated to each device (clock, regulator, operation point) are consolidated by the Linux frameworks and can be treated by Linux driver or by OP-TEE through SCMI requests.
2.1. Component description[edit | edit source]
The OpenSTLinux components for low power are:
Non secure world (Linux):
- Power management frameworks: See Power overview for details
- PSCI library: this is a set of standardized functions to request a low-power service to the secure monitor
- SCMI drivers: driver for system resources (clock, regulators, power domain,...), exposed by OP-TEE with SCMI protocol
- Device driver: any peripheral driver which needs to control power
- RCC driver for clock and reset managed by non secure world
Secure world components (OP-TEE):
- SCMI protocol: see SCMI overview for details
- PM framework: call the low-power callback of each device on the call of TF-A BL31 PM hooks.
- OP-TEE drivers: driver of device for system resources
- RCC driver for clock and reset managed by secure world
- PWR driver for SoC regulators managed by secure world
- PMIC driver for external regulators
Secure monitor components (TF-A BL31):
- PSCI libray: generic PSCI stack
- PM manage PSCI topology and modes with RCC and PWR registers and DDR self refresh
- DDR driver: DDR driver
STM32 peripherals (Hardware):
2.2. API description[edit | edit source]
The OpenSTLinux power management support is based on Arm® interface specifications:
- Power state coordination interface (PSCI) [1] defines many messages (see identifiers in TF-A include/lib/psci/psci.h or in Linux include/kvm/arm_psci.h ), for examples:
- CPU_SUSPEND : used to CPU suspend (freeze/s2idle), including OS initiated state support for CpuIdle
- CPU_ON/CPU_OFF : used for hotplug feature
- SYSTEM_OFF : used for power off
- SYSTEM_RESET : used for system reset
- SYSTEM_SUSPEND : used to system suspend (deep)
- PSCI_VERSION : return the supported version of the PSCI specication, v1.1 is supported by TF-A
- System Control and Management Interface (SCMI)[2], see SCMI overview for details
3. Configuration[edit | edit source]
The objective of this chapter is to explain how to configure OpenSTLinux for #Low-power modes, based on OP-TEE and TF-A device tree.
See the page power overview for kernel configuration details.
3.1. Supported power modes[edit | edit source]
The SoC device tree describes the PSCI topology in sub-nodes of cpus/domain-idle-states
:
- for Linux in SoC device tree (arch/arm64/boot/dts/st/stm32mp211.dtsi , arch/arm64/boot/dts/st/stm32mp231.dtsi , arch/arm64/boot/dts/st/stm32mp251.dtsi ), one node for each PSCI_CPU_SUSPEND supported parameter (only the Stop1 modes):
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>;
};
};
- for TF-A BL31 secure monitor, in SoC device tree (fdts/stm32mp211.dtsi , fdts/stm32mp231.dtsi , fdts/stm32mp251.dtsi ), one node by state supported in PSCI topology:
domain-idle-states { domain-stop1 { compatible = "domain-idle-state"; arm,psci-suspend-param = <0x00000011>; }; domain-lp-stop1 { compatible = "domain-idle-state"; arm,psci-suspend-param = <0x00000021>; }; domain-lplv-stop1 { compatible = "domain-idle-state"; arm,psci-suspend-param = <0x00000211>; }; domain-stop2 { compatible = "domain-idle-state"; arm,psci-suspend-param = <0x40001333>; }; domain-lp-stop2 { compatible = "domain-idle-state"; arm,psci-suspend-param = <0x40002333>; }; domain-lplv-stop2 { compatible = "domain-idle-state"; arm,psci-suspend-param = <0x40023333>; }; domain-standby { compatible = "domain-idle-state"; arm,psci-suspend-param = <0x40033333>; }; };
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 STPMIC25, if the PWR_LP pins control the reduced voltage mode of the VDDCORE and VDDCPU regulators, then only LPLV-StopX modes can be reached. LP-StopX modes must be deleted.
- in TF-A BL31 device tree
/ { cpus { domain-idle-states { /delete-node/ domain-lp-stop1; /delete-node/ domain-lp-stop2; }; }; };
- in Linux device tree (CLUSTER_PD
domain-idle-states = <&STOP1>, <&LP_STOP1>;
for CLUSTER_PD in arch/arm64/boot/dts/st/stm32mp251.dts ):
/ { cpus { domain-idle-states { /delete-node/ domain-lp-stop1; }; }; }; &CLUSTER_PD { domain-idle-states = <&STOP1>; };
3.2. STPMIC configuration for low power mode[edit | edit source]
Please refer to PMIC OP-TEE page for details of PMIC configuration in OP-TEE for each power mode and to application note AN5727 for configurations.
In OpenSTLinux, the selected PSCI power level is indicated to OP-TEE with Secure-EL1 Payload Dispatcher (SPD) PSCI hooks. And this power level is indicated with pm_hint to each OP-TEE drivers to save/restore the device configuration (see core/include/kernel/pm.h and core/arch/arm/plat-stm32mp2/stm32mp_pm.h for details).
This hook is used by the STPMIC25 driver in OP-TEE to configure each regulators according to the selected low power mode as described in device tree by subnodes.
See OP-TEE device tree in core/arch/arm/dts/stm32mp257f-ev1.dts for configuration example:
vddcore: buck2 { regulator-name = "vddcore"; regulator-min-microvolt = <820000>; regulator-max-microvolt = <820000>; regulator-always-on; st,pwrctrl-sel = <1>; st,pwrctrl-enable; default { regulator-on-in-suspend; regulator-suspend-microvolt = <820000>; }; lplv { regulator-on-in-suspend; regulator-suspend-microvolt = <670000>; }; standby { regulator-off-in-suspend; }; off { regulator-off-in-suspend; }; };
4. How to use the framework[edit | edit source]
4.1. Low-power modes[edit | edit source]
Refer to STM32 MPU reference manuals for the full description of low-power modes.
The AN5726 Guidelines for using low-power modes on STM32MP2 MPU also gives much more information on these modes and on associated the wake-up sources.
System mode | Linux Command | PSCI request | Power consumption | Wake-up time | VDDCPU | VDDCORE | DDR state |
---|---|---|---|---|---|---|---|
Stop1 | freeze (s2idle) |
PSCI_CPU_SUSPEND | Medium | Low | ON | ON | SR, VTT on |
LP-Stop1 | Medium | Low | SR, VTT off | ||||
LPLV-Stop1 | Medium | Medium | ON (reduced)[OSTL 1] | ON (reduced) | |||
Stop2 | mem (deep) |
PSCI_SYSTEM_SUSPEND | Low | Low | OFF | ON | SR, VTT off |
LP-Stop2 | Low | Medium | |||||
LPLV-Stop2 | Low | Medium | ON (reduced) | ||||
Standby1 | Low | High | OFF | ||||
Standby2 | shutdown | PSCI_SYSTEM_OFF | Very-Low | High | Off | ||
VBAT | Very-Low | Very-High |
- ↑ VDDCPU is not reduced for LPLV-Stop1 in OpenSTLinux on STMicroelectronics boards with STPMIC25 (not implemented)
OpenSTLinux sets the DDR in Self Refresh mode (SR) in all the low-power modes except power off (Standby2 and VBAT). For LP-Stop1 and LP-Stop2 modes, the DDR VTT supply is also switched off on STMicroelectronics reference design thought the PWR_LP signal connected to PWRCTRL1 pin of STPMIC25.
This list of Wake-up capability peripheral for each mode is defined in the table named Functionalities depending on system operating mode of the STM32 MPU reference manuals.
The following tables give the list of wake-up sources available in each mode.
Plaform mode | Available wake-up sources |
---|---|
Stop1/2 and LP-Stop1/2 |
Group1 : Group2 + HPDMAx (x = 1, 2, 3), HSI frequency monitoring, USB, UCPD1, ETHx (x = 1,2), USARTx (x = 1 to 9), I2Cx (x = 1 to 7), I3Cx (x = 1 to 3), SPIx (x = 1 to 7), DTS, LPTIMx (x = 1, 2) |
LPLV-Stop1/2 | Group2 : Group3 + PVD, PVM, GPIOs |
Standby1 | Group3 : Group4 + CPU3, DBG, LPDMA, LPUART1[note 1], I2C8[note 1], I3C4[note 1], SPI8[note 1], ADF1[note 1], LPTIMy (y = 3, 4, 5), WWDG2, MBOX2, HSEM, GPIOZ |
Standby2 | Group4 : Group5 + 6 x WKUP pins |
VBAT | Group5 : BOR, VBATH/VBATL, TEMPH/TEMPL, LSE CSS, RTC/auto wake-up, tamper pins, IWDGx |
4.2. PSCI topology[edit | edit source]
The PSCI specification define the concept of the power domain topology tree, which plays a crucial role in TF-A BL31 (porting-guide.html) and its PSCI stack (see design/psci-pd-tree.html).
For PSCI suspend requests, STM32MP2 series supports 5 power levels in the PSCI topology to handle the regulators configuration done in OP-TEE, in particular to differentiate the voltages for LP and the LPLV modes with PMIC.
In OpenSTLinux, each STM32MP2 series low power mode is associated to a PSCI State-id, which uses the ARM Recommended StateID Encoding with OS initiated support and the PSCI topology is:
- defined in TF-A PM driver: plat/st/stm32mp2/stm32mp2_pm.c .
/* State-id - 0x00000001 */
#define PWRSTATE_RUN \
stm32_make_pwrstate(RUN, RUN, RUN, RUN, RET, PSTATE_TYPE_STANDBY)
/* State-id - 0x00000011 Stop1 */
#define PWRSTATE_STOP1 \
stm32_make_pwrstate(RUN, RUN, RUN, RET, RET, PSTATE_TYPE_STANDBY)
/* State-id - 0x00000021 LP-Stop1*/
#define PWRSTATE_LP_STOP1 \
stm32_make_pwrstate(RUN, RUN, RUN, LP, RET, PSTATE_TYPE_STANDBY)
/* State-id - 0x00000211 LPLV-Stop1*/
#define PWRSTATE_LPLV_STOP1 \
stm32_make_pwrstate(RUN, RUN, LP, RET, RET, PSTATE_TYPE_STANDBY)
/* State-id - 0x40001333 Stop2 */
#define PWRSTATE_STOP2 \
stm32_make_pwrstate(RUN, RET, OFF, OFF, OFF, PSTATE_TYPE_POWERDOWN)
/* State-id - 0x40002333 LP-Stop2*/
#define PWRSTATE_LP_STOP2 \
stm32_make_pwrstate(RUN, LP, OFF, OFF, OFF, PSTATE_TYPE_POWERDOWN)
/* State-id - 0x40023333 LPLV-Stop2*/
#define PWRSTATE_LPLV_STOP2 \
stm32_make_pwrstate(LP, OFF, OFF, OFF, OFF, PSTATE_TYPE_POWERDOWN)
/* State-id - 0x40033333 Standby */
#define PWRSTATE_STANDBY \
stm32_make_pwrstate(OFF, OFF, OFF, OFF, OFF, PSTATE_TYPE_POWERDOWN)
These value are based on the PSCI state system topology defined in plat/st/stm32mp2/include/platform_def.h with:
PLAT_MAX_PWR_LVL
= 4, for Core(0), D1(1), D1LPLV(2), D2(3), D2_LPLV(4)PLAT_MIN_SUSPEND_PWR_LVL
=2, limit level forPSCI_CPU_SUSPEND
supportPLAT_NUM_PWR_DOMAINS
= 6 (2 cores and 4 power level)
and with the power domain states:
STM32MP_LOCAL_STATE_RUN
(0)STM32MP_LOCAL_STATE_RET
(1)STM32MP_LOCAL_STATE_LP
(2)STM32MP_LOCAL_STATE_OFF
(3)
This State-id encoding use the extended format and a simple additive composition method, with one nibble as a local state index for each power level (bits 27:0) and StateType(bit 30):
PSCI request | Name | State-id | StateType | PowerLevel | ||||
---|---|---|---|---|---|---|---|---|
D2_LPLV(4) | D2(3) | D1_LPLV(2) | D1(1) | Core(0) | ||||
PSCI_CPU_SUSPEND | Sleep (WFI) | 0x00000001 | PSTATE_TYPE_STANDBY | RUN | RUN | RUN | RUN | RET |
Stop1 | 0x00000011 | PSTATE_TYPE_STANDBY | RUN | RUN | RUN | RET | RET | |
LP-Stop1 | 0x00000021 | PSTATE_TYPE_STANDBY | RUN | RUN | RUN | LP | RET | |
LPLV-Stop1 | 0x00000211 | PSTATE_TYPE_STANDBY | RUN | RUN | LP | RET | RET | |
PSCI_SYSTEM_SUSPEND | Stop2 | 0x40001333 | PSTATE_TYPE_POWERDOWN | RUN | RET | OFF | OFF | OFF |
LP-Stop2 | 0x40002333 | PSTATE_TYPE_POWERDOWN | RUN | LP | OFF | OFF | OFF | |
LPLV-Stop2 | 0x40023333 | PSTATE_TYPE_POWERDOWN | LP | OFF | OFF | OFF | OFF | |
Standby | 0x40002333 | PSTATE_TYPE_POWERDOWN | OFF | OFF | OFF | OFF | OFF |
- used in TF-A BL31 for
PSCI_CPU_SUSPEND
request (for S2RAM/Deep requests by Linux). - used in OP-TEE PM framework (only the power level), based on
- generic PM_HINT, defined in core/include/kernel/pm.h .
- platform PM LEVEL defined in core/arch/arm/plat-stm32mp2/stm32mp_pm.h
- used in Linux power management, the composite PSCI State-id are used in
PSCI_CPU_SUSPEND
requests and configurated in Linux device tree (for S2Idle and for OS initiated support, uses the OS initiated (PSCI OSI)support).
4.3. PSCI_CPU_SUSPEND support[edit | edit source]
Linux kernel sent the PSCI_CPU_SUSPEND
to TF-A BL31 after a S2IDLE/FREEZE system request and for PSCI CPUIdle OS initiated mode (PSCI OSI). they are described in SoC device tree using the hierarchical model with nodes idle-states
and domain-idle-states
as described in Documentation/devicetree/bindings/arm/psci.yaml (see Power overview for detail).
See SoC device tree example in arch/arm64/boot/dts/st/stm32mp251.dtsi and in arch/arm64/boot/dts/st/stm32mp253.dtsi .
The targeted arm,psci-suspend-param, based on this topology, is provided to PCSI stack in TF-A BL31 in PSCI_CPU_SUSPEND
requested (see Power overview or design_documents/psci_osi_mode.html for detail).
4.4. PSCI_SYSTEM_SUSPEND support[edit | edit source]
Linux kernel sent the PSCI_SYSTEM_SUSPEND
to TF-A BL31 after "DEEP"/"S2RAM" request (see Power overview for details). The CPU must reset at wake-up. The activated wake-up are consolidated in TF-A BL31 to select the lowest POWERDOWN supported mode in stm32_get_sys_suspend_power_state() .
If a low power mode is not supported by a board design, it must be removed in TF-A BL31 device tree.
You can limit the maximum supported mode with wake-up sources, but you can't force Stop2 mode by Linux command if LP-Stop2 is supported (same functionalities, same supported wake-up sources).
4.5. PSCI stack in TF-A[edit | edit source]
In TF-A BL31, we have 3 elements imply in low power managemet
- PSCI Stack = TF-A implementation of the PSCI API firmware-design.html
- STM32MP2 platform port, see porting-guide.html#power-state-coordination-interface-in-bl31 for details, implemented in plat/st/stm32mp2/stm32mp2_pm.c
- Secure Payload Dispatcher (SPD) for OP-TEE = components/spd/optee-dispatcher.html
In the PSCI stack call sequence (in lib/psci/psci_suspend.c ) is
- for
PSCI_SYSTEM_SUSPEND
{managed bypsci_cpu_suspend()
}- get_sys_suspend_power_state()
- SPD OP-TEE: svc_suspend()
- pwr_domain_suspend()
- pwr_domain_pwr_down_wfi()
- Low power mode (CPU powered down)
- pwr_domain_suspend_finish() {called by psci_warmboot_entrypoint()}
- SPD OP-TEE: svc_suspend_finish()
- for
PSCI_CPU_SUSPEND
{managed bypsci_cpu_suspend()
}- validate_power_state()
- pwr_domain_validate_suspend()
- pwr_domain_suspend()
- Low power mode (the 2 CPU core are stalled, context is preserved)
- pwr_domain_suspend_finish()
For PSCI_CPU_SUSPEND
case, the SPD OP-TEE is not managed by PSCI stack as the context is preserved. For OpenSTLinux, th call of OP-TEE hook is required to manage PMIC configuration in OP-TEE, it is done in STM32 functions (stm32_pwr_domain_suspend()
/ stm32_pwr_domain_suspend_finish())/code>.)
5. Source code location[edit | edit source]
Below are listed the software frameworks and drivers managing the OpenSTLinux power management.
- Linux®: Linux power management
- TF-A:
- the STM32MP2 PSCI support: plat/st/stm32mp2/stm32mp2_pm.c
- the low power context: plat/st/stm32mp2/stm32mp2_context.c
- the PSCI stack: lib/psci/ and include/lib/psci/psci.h
- OP-TEE:
- TF-A hook for STM32MP2 platform: core/arch/arm/plat-stm32mp2/stm32mp_pm.c and core/arch/arm/plat-stm32mp2/stm32mp_pm.h
- PM framework: core/kernel/pm.c and core/include/kernel/pm.h
- For each device driver, the PM function registered by register_pm_core_service_cb()
6. How to trace and debug[edit | edit source]
See How to debug TF-A BL2 and How_to_debug_OP-TEE to activate the traces.
See Power_overview#How_to_trace_and_debug
With the next command:
echo N > /sys/module/printk/parameters/console_suspend
On PSCI_SYSTEM_SUSPEND
TF-A BL31 displays the low power mode selected in stm32_get_sys_suspend_power_state()
and, if it is not Standby1, dumps the registers (EXTI1_C1IMR and PWR_CPU2D2SR) used to choose this mode, for example:
echo N > /sys/module/printk/parameters/console_suspend
echo enabled > /sys/class/tty/ttySTM0/power/wakeup
rtcwake --date +5sec -m mem
rtcwake: assuming RTC uses UTC ...
rtcwake: wakeup from "mem" using /dev/rtc0 at Mon Jan 3 03:03:24 2000
[174821.520715] PM: suspend entry (deep)
[174821.520901] Filesystems sync: 0.000 seconds
[174821.524033] Freezing user space processes
[174821.528937] Freezing user space processes completed (elapsed 0.001 seconds)
[174821.534228] OOM killer disabled.
[174821.537468] Freezing remaining freezable tasks
[174821.543294] Freezing remaining freezable tasks completed (elapsed 0.001 seconds)
[174821.553226] stm32-dwmac 482d0000.eth2 end0: FPE workqueue stop
[174821.555855] stm32-dwmac 482c0000.eth1 end1: FPE workqueue stop
[174821.646337] Disabling non-boot CPUs ...
[174821.648058] psci: CPU1 killed (polled 0 ms)
INFO: max_pwr_state=40002333 C1IMR1=8000000 C1IMR2=100000 C1IMR3=0 CPU2D2SR=1
INFO: Entering LP_Stop2 low power mode
See stm32_get_sys_suspend_power_state()
and reference Manuel to identified the reason of the low power mode selection.
6.1. How to force low power mode[edit | edit source]
In TF-A, you can force the selected mode PSCI_SYSTEM_SUSPEND for your board in stm32_get_sys_suspend_power_state()
, for example:
/* Search the max supported POWERDOWN modes <= max_pwr_state */
for (i = ARRAY_SIZE(stm32mp_supported_pwr_states) - 1U; i > 0U; i--) {
pwr_state = stm32mp_supported_pwr_states[i];
if ((pwr_state != 0U) && (pwr_state <= max_pwr_state) &&
(psci_get_pstate_type(pwr_state) == PSTATE_TYPE_POWERDOWN)) {
break;
}
}
pwr_state = PWRSTATE_STOP2;
state_id = psci_get_pstate_id(pwr_state);
or remove some states in TF-A device tree , for example remove LP-Stop2 mode to allow Stop2 selection:
/ {
cpus {
domain-idle-states {
/delete-node/ lp-stop2;
};
};
};
7. To go further[edit | edit source]
Refer to reference manual for a detailed description of low-power modes and peripheral wakeup sources:
The next application notes gives additional information on the hardware settings used for low-power management:
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