1 /*
2 * Copyright (c) 2021 STMicroelectronics.
3 * Copyright (c) 2021 G-Technologies Sdn. Bhd.
4 * Copyright (c) 2022 Worldcoin Foundation.
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8 #include <zephyr/init.h>
9 #include <zephyr/kernel.h>
10 #include <zephyr/logging/log.h>
11 #include <zephyr/pm/pm.h>
12 #include <soc.h>
13
14 #include <clock_control/clock_stm32_ll_common.h>
15 #include <stm32g4xx_ll_bus.h>
16 #include <stm32g4xx_ll_cortex.h>
17 #include <stm32g4xx_ll_pwr.h>
18 #include <stm32g4xx_ll_system.h>
19 #include <stm32g4xx_ll_utils.h>
20 LOG_MODULE_REGISTER(soc, CONFIG_SOC_LOG_LEVEL);
21
22 /* Invoke Low Power/System Off specific Tasks */
pm_state_set(enum pm_state state,uint8_t substate_id)23 void pm_state_set(enum pm_state state, uint8_t substate_id)
24 {
25 if (state != PM_STATE_SUSPEND_TO_IDLE) {
26 LOG_DBG("Unsupported power state %u", state);
27 return;
28 }
29
30 switch (substate_id) {
31 case 1: /* this corresponds to the STOP0 mode: */
32 /* enter STOP0 mode */
33 LL_PWR_SetPowerMode(LL_PWR_MODE_STOP0);
34 LL_LPM_EnableDeepSleep();
35 /* enter SLEEP mode : WFE or WFI */
36 k_cpu_idle();
37 break;
38 case 2: /* this corresponds to the STOP1 mode: */
39 /* enter STOP1 mode */
40 LL_PWR_SetPowerMode(LL_PWR_MODE_STOP1);
41 LL_LPM_EnableDeepSleep();
42 /* enter SLEEP mode : WFE or WFI */
43 k_cpu_idle();
44 break;
45 default:
46 LOG_DBG("Unsupported power state substate-id %u", substate_id);
47 break;
48 }
49 }
50
51 /* Handle SOC specific activity after Low Power Mode Exit */
pm_state_exit_post_ops(enum pm_state state,uint8_t substate_id)52 void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id)
53 {
54 if (state != PM_STATE_SUSPEND_TO_IDLE) {
55 LOG_DBG("Unsupported power substate %u", state);
56 } else {
57 switch (substate_id) {
58 case 1: /* STOP0 */
59 __fallthrough;
60 case 2: /* STOP1 */
61 LL_LPM_DisableSleepOnExit();
62 /* Clear SLEEPDEEP bit */
63 LL_LPM_EnableSleep();
64 break;
65 default:
66 LOG_DBG("Unsupported power substate-id %u", substate_id);
67 break;
68 }
69 /* need to restore the clock */
70 stm32_clock_control_init(NULL);
71 }
72
73 /*
74 * System is now in active mode.
75 * Reenable interrupts which were disabled
76 * when OS started idling code.
77 */
78 irq_unlock(0);
79 }
80
81 /* Initialize STM32 Power */
stm32_power_init(void)82 static int stm32_power_init(void)
83 {
84
85 /* enable Power clock */
86 LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR);
87
88 return 0;
89 }
90
91 SYS_INIT(stm32_power_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
92