1 /*
2  * Copyright (c) 2021 STMicroelectronics.
3  * Copyright (c) 2021 G-Technologies Sdn. Bhd.
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 #include <zephyr/kernel.h>
8 #include <zephyr/pm/pm.h>
9 #include <soc.h>
10 #include <zephyr/init.h>
11 
12 #include <stm32g0xx_ll_utils.h>
13 #include <stm32g0xx_ll_bus.h>
14 #include <stm32g0xx_ll_cortex.h>
15 #include <stm32g0xx_ll_pwr.h>
16 #include <stm32g0xx_ll_system.h>
17 #include <clock_control/clock_stm32_ll_common.h>
18 
19 #include <zephyr/logging/log.h>
20 LOG_MODULE_DECLARE(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",
47 			substate_id);
48 		break;
49 	}
50 }
51 
52 /* Handle SOC specific activity after Low Power Mode Exit */
pm_state_exit_post_ops(enum pm_state state,uint8_t substate_id)53 void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id)
54 {
55 	if (state != PM_STATE_SUSPEND_TO_IDLE) {
56 		LOG_DBG("Unsupported power substate %u", state);
57 	} else {
58 		switch (substate_id) {
59 		case 1:	/* STOP0 */
60 			__fallthrough;
61 		case 2:	/* STOP1 */
62 			LL_LPM_DisableSleepOnExit();
63 			/* Clear SLEEPDEEP bit */
64 			LL_LPM_EnableSleep();
65 			break;
66 		default:
67 			LOG_DBG("Unsupported power substate-id %u",
68 				substate_id);
69 			break;
70 		}
71 		/* need to restore the clock */
72 		stm32_clock_control_init(NULL);
73 	}
74 
75 	/*
76 	 * System is now in active mode.
77 	 * Reenable interrupts which were disabled
78 	 * when OS started idling code.
79 	 */
80 	irq_unlock(0);
81 }
82 
83 /* Initialize STM32 Power */
stm32_power_init(void)84 void stm32_power_init(void)
85 {
86 
87 	/* enable Power clock */
88 	LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR);
89 }
90