Skip to content

Commit ff4f249

Browse files
committed
soc: stm23u5: Provide power implementation
Provide power modes implementation for u5 socs. For now STOP3 mode is not implemented as this mode is not compatible with LPTIM activation and hence cannot be used as a workable suspend to idle state using LPTIM as kernel tick source. Signed-off-by: Erwan Gouriou <[email protected]>
1 parent 7a01ea9 commit ff4f249

File tree

3 files changed

+160
-0
lines changed

3 files changed

+160
-0
lines changed

soc/arm/st_stm32/stm32u5/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,7 @@ zephyr_include_directories(${ZEPHYR_BASE}/drivers)
44
zephyr_sources(
55
soc.c
66
)
7+
8+
zephyr_sources_ifdef(CONFIG_PM
9+
power.c
10+
)

soc/arm/st_stm32/stm32u5/Kconfig.defconfig.series

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,7 @@ source "soc/arm/st_stm32/stm32u5/Kconfig.defconfig.stm32u5*"
1010
config SOC_SERIES
1111
default "stm32u5"
1212

13+
config STM32_LPTIM_TIMER
14+
default y if PM
15+
1316
endif # SOC_SERIES_STM32U5X

soc/arm/st_stm32/stm32u5/power.c

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
/*
2+
* Copyright (c) 2021 Linaro Limited
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
#include <zephyr.h>
7+
#include <pm/pm.h>
8+
#include <soc.h>
9+
#include <init.h>
10+
11+
#include <stm32u5xx_ll_utils.h>
12+
#include <stm32u5xx_ll_bus.h>
13+
#include <stm32u5xx_ll_cortex.h>
14+
#include <stm32u5xx_ll_pwr.h>
15+
#include <stm32u5xx_ll_rcc.h>
16+
#include <stm32u5xx_ll_system.h>
17+
#include <clock_control/clock_stm32_ll_common.h>
18+
19+
#include <logging/log.h>
20+
LOG_MODULE_DECLARE(soc, CONFIG_SOC_LOG_LEVEL);
21+
22+
/* select MSI as wake-up system clock if configured, HSI otherwise */
23+
#if STM32_SYSCLK_SRC_MSI
24+
#define RCC_STOP_WAKEUPCLOCK_SELECTED LL_RCC_STOP_WAKEUPCLOCK_MSI
25+
#else
26+
#define RCC_STOP_WAKEUPCLOCK_SELECTED LL_RCC_STOP_WAKEUPCLOCK_HSI
27+
#endif
28+
29+
void set_mode_stop(uint8_t substate_id)
30+
{
31+
/* ensure the proper wake-up system clock */
32+
LL_RCC_SetClkAfterWakeFromStop(RCC_STOP_WAKEUPCLOCK_SELECTED);
33+
34+
switch (substate_id) {
35+
case 1: /* enter STOP0 mode */
36+
LL_PWR_SetPowerMode(LL_PWR_STOP0_MODE);
37+
break;
38+
case 2: /* enter STOP1 mode */
39+
LL_PWR_SetPowerMode(LL_PWR_STOP1_MODE);
40+
break;
41+
case 3: /* enter STOP2 mode */
42+
LL_PWR_SetPowerMode(LL_PWR_STOP2_MODE);
43+
break;
44+
default:
45+
LOG_DBG("Unsupported power state substate-id %u", substate_id);
46+
break;
47+
}
48+
}
49+
50+
void set_mode_standby(uint8_t substate_id)
51+
{
52+
ARG_UNUSED(substate_id);
53+
/* Select standby mode */
54+
LL_PWR_SetPowerMode(LL_PWR_STANDBY_MODE);
55+
}
56+
57+
void set_mode_shutdown(uint8_t substate_id)
58+
{
59+
ARG_UNUSED(substate_id);
60+
/* Select shutdown mode */
61+
LL_PWR_SetPowerMode(LL_PWR_SHUTDOWN_MODE);
62+
}
63+
64+
/* Invoke Low Power/System Off specific Tasks */
65+
__weak void pm_power_state_set(struct pm_state_info info)
66+
{
67+
68+
switch (info.state) {
69+
case PM_STATE_SUSPEND_TO_IDLE:
70+
set_mode_stop(info.substate_id);
71+
break;
72+
case PM_STATE_STANDBY:
73+
/* To be tested */
74+
set_mode_standby(info.substate_id);
75+
break;
76+
case PM_STATE_SOFT_OFF:
77+
set_mode_shutdown(info.substate_id);
78+
break;
79+
/* Following states are not supported */
80+
case PM_STATE_RUNTIME_IDLE:
81+
__fallthrough;
82+
case PM_STATE_ACTIVE:
83+
__fallthrough;
84+
case PM_STATE_SUSPEND_TO_RAM:
85+
__fallthrough;
86+
case PM_STATE_SUSPEND_TO_DISK:
87+
LOG_DBG("Unsupported power state %u", info.state);
88+
return;
89+
}
90+
91+
/* Set SLEEPDEEP bit of Cortex System Control Register */
92+
LL_LPM_EnableDeepSleep();
93+
94+
/* Select mode entry : WFE or WFI and enter the CPU selected mode */
95+
k_cpu_idle();
96+
}
97+
98+
/* Handle SOC specific activity after Low Power Mode Exit */
99+
__weak void pm_power_state_exit_post_ops(struct pm_state_info info)
100+
{
101+
switch (info.state) {
102+
case PM_STATE_SUSPEND_TO_IDLE:
103+
if (info.substate_id <= 3) {
104+
LL_LPM_DisableSleepOnExit();
105+
LL_LPM_EnableSleep();
106+
} else {
107+
LOG_DBG("Unsupported power substate-id %u",
108+
info.substate_id);
109+
}
110+
case PM_STATE_STANDBY:
111+
/* To be tested */
112+
LL_LPM_EnableSleep();
113+
case PM_STATE_SOFT_OFF:
114+
/* We should not get there */
115+
__fallthrough;
116+
case PM_STATE_ACTIVE:
117+
__fallthrough;
118+
case PM_STATE_SUSPEND_TO_RAM:
119+
__fallthrough;
120+
case PM_STATE_SUSPEND_TO_DISK:
121+
__fallthrough;
122+
default:
123+
LOG_DBG("Unsupported power state %u", info.state);
124+
break;
125+
}
126+
/* need to restore the clock */
127+
stm32_clock_control_init(NULL);
128+
129+
/*
130+
* System is now in active mode.
131+
* Reenable interrupts which were disabled
132+
* when OS started idling code.
133+
*/
134+
irq_unlock(0);
135+
}
136+
137+
/* Initialize STM32 Power */
138+
static int stm32_power_init(const struct device *dev)
139+
{
140+
ARG_UNUSED(dev);
141+
142+
/* enable Power clock */
143+
LL_AHB3_GRP1_EnableClock(LL_AHB3_GRP1_PERIPH_PWR);
144+
145+
#ifdef CONFIG_DEBUG
146+
/* Enable the Debug Module during all and any Low power mode */
147+
LL_DBGMCU_EnableDBGStopMode();
148+
#endif /* CONFIG_DEBUG */
149+
150+
return 0;
151+
}
152+
153+
SYS_INIT(stm32_power_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);

0 commit comments

Comments
 (0)