1 /*
2  * SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #pragma once
8 
9 #include <stdbool.h>
10 #include <stddef.h>
11 #include <stdint.h>
12 #include <stdlib.h>
13 
14 #include "soc/soc_caps.h"
15 
16 #ifdef __cplusplus
17 extern "C" {
18 #endif
19 
20 #if SOC_PMU_SUPPORTED
21 #include "hal/pmu_hal.h"
22 #include "pmu_param.h"
23 
24 #define RTC_SLEEP_PD_DIG                PMU_SLEEP_PD_TOP        //!< Deep sleep (power down digital domain, includes all power domains
25                                                                 //   except CPU, Modem, LP peripheral, AON,VDDSDIO, MEM and clock power domains)
26 #define RTC_SLEEP_PD_RTC_PERIPH         PMU_SLEEP_PD_LP_PERIPH  //!< Power down RTC peripherals
27 #define RTC_SLEEP_PD_VDDSDIO            PMU_SLEEP_PD_VDDSDIO    //!< Power down VDDSDIO regulator
28 #define RTC_SLEEP_PD_CPU                PMU_SLEEP_PD_CPU        //!< Power down CPU when in lightsleep, but not restart
29 #define RTC_SLEEP_PD_DIG_PERIPH         PMU_SLEEP_PD_HP_PERIPH  //!< Power down DIG peripherals
30 #define RTC_SLEEP_PD_INT_8M             PMU_SLEEP_PD_RC_FAST    //!< Power down Internal 20M oscillator
31 #define RTC_SLEEP_PD_XTAL               PMU_SLEEP_PD_XTAL       //!< Power down main XTAL
32 #define RTC_SLEEP_PD_MODEM              PMU_SLEEP_PD_MODEM      //!< Power down modem(include wifi, ble and 15.4)
33 
34 //These flags are not power domains, but will affect some sleep parameters
35 #define RTC_SLEEP_DIG_USE_8M            BIT(16)
36 #define RTC_SLEEP_USE_ADC_TESEN_MONITOR BIT(17)
37 #define RTC_SLEEP_NO_ULTRA_LOW          BIT(18) //!< Avoid using ultra low power in deep sleep, in which RTCIO cannot be used as input, and RTCMEM can't work under high temperature
38 
39 #if SOC_PM_SUPPORT_EXT0_WAKEUP
40 #define RTC_EXT0_TRIG_EN            PMU_EXT0_WAKEUP_EN                       //!< EXT0 wakeup
41 #else
42 #define RTC_EXT0_TRIG_EN            0
43 #endif
44 #if SOC_PM_SUPPORT_EXT1_WAKEUP
45 #define RTC_EXT1_TRIG_EN            PMU_EXT1_WAKEUP_EN      //!< EXT1 wakeup
46 #endif
47 #define RTC_GPIO_TRIG_EN            PMU_GPIO_WAKEUP_EN      //!< GPIO wakeup
48 #define RTC_TIMER_TRIG_EN           PMU_LP_TIMER_WAKEUP_EN  //!< Timer wakeup
49 #define RTC_WIFI_TRIG_EN            PMU_WIFI_SOC_WAKEUP_EN  //!< WIFI wakeup (light sleep only)
50 #define RTC_UART0_TRIG_EN           PMU_UART0_WAKEUP_EN     //!< UART0 wakeup (light sleep only)
51 #define RTC_UART1_TRIG_EN           PMU_UART1_WAKEUP_EN     //!< UART1 wakeup (light sleep only)
52 #define RTC_BT_TRIG_EN              PMU_BLE_SOC_WAKEUP_EN   //!< BT wakeup (light sleep only)
53 #define RTC_USB_TRIG_EN             PMU_USB_WAKEUP_EN
54 #if SOC_LP_CORE_SUPPORTED
55 #define RTC_LP_CORE_TRIG_EN         PMU_LP_CORE_WAKEUP_EN   //!< LP core wakeup
56 #endif //SOC_LP_CORE_SUPPORTED
57 #define RTC_XTAL32K_DEAD_TRIG_EN    0 // TODO
58 #define RTC_BROWNOUT_DET_TRIG_EN    0 // TODO
59 
60 /**
61  * RTC_SLEEP_REJECT_MASK records sleep reject sources supported by chip
62  */
63 #define RTC_SLEEP_REJECT_MASK (RTC_GPIO_TRIG_EN         | \
64                                RTC_TIMER_TRIG_EN        | \
65                                RTC_WIFI_TRIG_EN         | \
66                                RTC_UART0_TRIG_EN        | \
67                                RTC_UART1_TRIG_EN        | \
68                                RTC_BT_TRIG_EN           | \
69                                RTC_XTAL32K_DEAD_TRIG_EN | \
70                                RTC_USB_TRIG_EN          | \
71                                RTC_BROWNOUT_DET_TRIG_EN)
72 
73 #if SOC_PM_SUPPORT_EXT0_WAKEUP
74 #define PMU_EXT0_WAKEUP_EN          BIT(0)
75 #endif
76 #if SOC_PM_SUPPORT_EXT1_WAKEUP
77 #define PMU_EXT1_WAKEUP_EN          BIT(1)
78 #endif
79 
80 #define PMU_GPIO_WAKEUP_EN          BIT(2)
81 #define PMU_WIFI_BEACON_WAKEUP_EN   BIT(3)
82 #define PMU_LP_TIMER_WAKEUP_EN      BIT(4)
83 #define PMU_WIFI_SOC_WAKEUP_EN      BIT(5)
84 #define PMU_UART0_WAKEUP_EN         BIT(6)
85 #define PMU_UART1_WAKEUP_EN         BIT(7)
86 #define PMU_SDIO_WAKEUP_EN          BIT(8)
87 #define PMU_BLE_SOC_WAKEUP_EN       BIT(10)
88 #if SOC_LP_CORE_SUPPORTED
89 #define PMU_LP_CORE_WAKEUP_EN       BIT(11)
90 #endif //SOC_LP_CORE_SUPPORTED
91 #define PMU_USB_WAKEUP_EN           BIT(14)
92 
93 
94 #define PMU_SLEEP_PD_TOP            BIT(0)
95 #define PMU_SLEEP_PD_VDDSDIO        BIT(1)
96 #define PMU_SLEEP_PD_MODEM          BIT(2)
97 #define PMU_SLEEP_PD_HP_PERIPH      BIT(3)
98 #define PMU_SLEEP_PD_CPU            BIT(4)
99 
100 #if SOC_PM_SUPPORT_HP_AON_PD
101 #define PMU_SLEEP_PD_HP_AON         BIT(5)
102 #endif
103 
104 #define PMU_SLEEP_PD_MEM_G0         BIT(6)
105 #define PMU_SLEEP_PD_MEM_G1         BIT(7)
106 #define PMU_SLEEP_PD_MEM_G2         BIT(8)
107 #define PMU_SLEEP_PD_MEM_G3         BIT(9)
108 #define PMU_SLEEP_PD_MEM            (PMU_SLEEP_PD_MEM_G0|PMU_SLEEP_PD_MEM_G1|PMU_SLEEP_PD_MEM_G2|PMU_SLEEP_PD_MEM_G3)
109 #define PMU_SLEEP_PD_XTAL           BIT(10)
110 #define PMU_SLEEP_PD_RC_FAST        BIT(11)
111 #define PMU_SLEEP_PD_XTAL32K        BIT(12)
112 #define PMU_SLEEP_PD_RC32K          BIT(13)
113 #define PMU_SLEEP_PD_LP_PERIPH      BIT(14)
114 
115 typedef struct {
116     pmu_hal_context_t *hal;
117     void *mc;
118 } pmu_context_t;
119 
120 pmu_context_t * PMU_instance(void);
121 
122 typedef enum pmu_hp_sysclk_src {
123     PMU_HP_SYSCLK_XTAL = 0,
124     PMU_HP_SYSCLK_PLL,
125     PMU_HP_SYSCLK_FOSC
126 } pmu_hp_sysclk_src_t;
127 
128 typedef enum pmu_sleep_protect_mode {
129     PMU_SLEEP_PROTECT_HP_SLEEP = 0,
130     PMU_SLEEP_PROTECT_XTAL,
131     PMU_SLEEP_PROTECT_HP_LP_SLEEP,
132     PMU_SLEEP_PROTECT_DISABLE
133 } pmu_sleep_protect_mode_t;
134 
135 typedef enum pmu_sleep_regdma_entry {
136     PMU_SLEEP_REGDMA_ENTRY_0 = 0,
137     PMU_SLEEP_REGDMA_ENTRY_1,
138     PMU_SLEEP_REGDMA_ENTRY_2,
139     PMU_SLEEP_REGDMA_ENTRY_3,
140     PMU_SLEEP_REGDMA_ENTRY_MAX
141 } pmu_sleep_regdma_entry_t;
142 
143 /**
144  * @brief PMU ICG modem code of HP system
145  */
146 typedef enum {
147     PMU_HP_ICG_MODEM_CODE_SLEEP = 0,
148     PMU_HP_ICG_MODEM_CODE_MODEM = 1,
149     PMU_HP_ICG_MODEM_CODE_ACTIVE = 2,
150 } pmu_hp_icg_modem_mode_t;
151 
152 
153 /**
154   * @brief  Enable_regdma_backup.
155   */
156 void pmu_sleep_enable_regdma_backup(void);
157 
158 /**
159   * @brief  Disable_regdma_backup.
160   */
161 void pmu_sleep_disable_regdma_backup(void);
162 
163 /**
164  * @brief Get sleep PLL enable status
165  *
166  * @return true if PLL is enabled by PMU in modem state
167  */
168 bool pmu_sleep_pll_already_enabled(void);
169 
170 /**
171  * @brief Calculate the hardware time overhead during sleep to compensate for sleep time
172  *
173  * @param pd_flags flags indicates the power domain that will be powered down
174  * @param slowclk_period re-calibrated slow clock period
175  * @param fastclk_period re-calibrated fast clock period
176  *
177  * @return hardware time overhead in us
178  */
179 uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t pd_flags, uint32_t slowclk_period, uint32_t fastclk_period);
180 
181 /**
182  * @brief Get default sleep configuration
183  * @param config pmu_sleep_config instance
184  * @param pd_flags flags indicates the power domain that will be powered down
185  * @param adjustment total software and hardware time overhead
186  * @param slowclk_period re-calibrated slow clock period in microseconds,
187  *                       Q13.19 fixed point format
188  * @param fastclk_period re-calibrated fast clock period in microseconds,
189  *                       Q13.19 fixed point format
190  * @param dslp configuration for deep sleep mode
191 
192  * @return hardware time overhead in us
193  */
194 const pmu_sleep_config_t* pmu_sleep_config_default(pmu_sleep_config_t *config, uint32_t pd_flags, uint32_t adjustment, uint32_t slowclk_period, uint32_t fastclk_period, bool dslp);
195 
196 /**
197  * @brief Prepare the chip to enter sleep mode
198  *
199  * This function configures various power/analog parameters and lp/lp system configuration
200  * used in sleep state machines
201  *
202  * This function does not actually enter sleep mode; this is done using
203  * pmu_sleep_start function. Software may do some other actions between
204  * pmu_sleep_init and pmu_sleep_start, such as set wakeup timer and configure
205  * wakeup sources.
206  *
207  * @param config sleep mode configuration
208  *
209  * @param dslp is initialize for deep sleep mode
210  */
211 void pmu_sleep_init(const pmu_sleep_config_t *config, bool dslp);
212 
213 /**
214  * @brief Enter deep or light sleep mode
215  *
216  * This function enters the sleep mode previously configured using pmu_sleep_init
217  * function. Before entering sleep, software should configure wake up sources
218  * appropriately (set up GPIO wakeup registers, timer wakeup registers,
219  * and so on).
220  *
221  * If deep sleep mode was configured using pmu_sleep_init, and sleep is not
222  * rejected by hardware (based on reject_opt flags), this function never returns.
223  * When the chip wakes up from deep sleep, CPU is reset and execution starts
224  * from ROM bootloader.
225  *
226  * If light sleep mode was configured using pmu_sleep_init, this function
227  * returns on wakeup, or if sleep is rejected by hardware.
228  *
229  * @param wakeup_opt  bit mask wake up reasons to enable (RTC_xxx_TRIG_EN flags
230  *                    combined with OR)
231  * @param reject_opt  bit mask of sleep reject reasons, used to
232  *                    prevent wakeup source set before the sleep request)
233  * @param lslp_mem_inf_fpu If non-zero then the low power config is restored
234  *                         immediately on wake. Recommended for light sleep,
235  *                         has no effect if the system goes into deep sleep.
236  *
237  * @return non-zero if sleep was rejected by hardware
238  */
239 uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp);
240 
241 /**
242  * @brief   Finish sleep process settings and get sleep reject status
243  * @return  return sleep reject status
244  */
245 bool pmu_sleep_finish(void);
246 
247 /**
248  * @brief Initialize PMU related power/clock/digital parameters and functions
249  */
250 void pmu_init(void);
251 
252 /**
253  * @brief Enable or disable system clock in PMU HP sleep state
254  *
255  * This API only used for fix BLE 40 MHz low power clock source issue
256  *
257  * @param enable  true to enable, false to disable
258  */
259 void pmu_sleep_enable_hp_sleep_sysclk(bool enable);
260 
261 
262 #endif //#if SOC_PMU_SUPPORTED
263 
264 #ifdef __cplusplus
265 }
266 #endif
267