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