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 
45 #if SOC_PM_SUPPORT_EXT1_WAKEUP
46 #define RTC_EXT1_TRIG_EN            PMU_EXT1_WAKEUP_EN      //!< EXT1 wakeup
47 #else
48 #define RTC_EXT1_TRIG_EN            0
49 #endif
50 
51 #define RTC_GPIO_TRIG_EN            PMU_GPIO_WAKEUP_EN      //!< GPIO wakeup
52 
53 #if SOC_LP_TIMER_SUPPORTED
54 #define RTC_TIMER_TRIG_EN           PMU_LP_TIMER_WAKEUP_EN  //!< Timer wakeup
55 #else
56 #define RTC_TIMER_TRIG_EN           0
57 #endif
58 
59 #if SOC_WIFI_SUPPORTED
60 #define RTC_WIFI_TRIG_EN            PMU_WIFI_SOC_WAKEUP_EN  //!< WIFI wakeup (light sleep only)
61 #else
62 #define RTC_WIFI_TRIG_EN            0
63 #endif
64 
65 #if SOC_UART_SUPPORT_WAKEUP_INT
66 #define RTC_UART0_TRIG_EN           PMU_UART0_WAKEUP_EN     //!< UART0 wakeup (light sleep only)
67 #define RTC_UART1_TRIG_EN           PMU_UART1_WAKEUP_EN     //!< UART1 wakeup (light sleep only)
68 #else
69 #define RTC_UART0_TRIG_EN           0
70 #define RTC_UART1_TRIG_EN           0
71 #endif
72 
73 #if SOC_BT_SUPPORTED
74 #define RTC_BT_TRIG_EN              PMU_BLE_SOC_WAKEUP_EN   //!< BT wakeup (light sleep only)
75 #else
76 #define RTC_BT_TRIG_EN              0
77 #endif
78 
79 #define RTC_USB_TRIG_EN             PMU_USB_WAKEUP_EN
80 
81 #if SOC_LP_CORE_SUPPORTED
82 #define RTC_LP_CORE_TRIG_EN         PMU_LP_CORE_WAKEUP_EN   //!< LP core wakeup
83 #else
84 #define RTC_LP_CORE_TRIG_EN         0
85 #endif //SOC_LP_CORE_SUPPORTED
86 
87 #define RTC_XTAL32K_DEAD_TRIG_EN    0 // TODO
88 #define RTC_BROWNOUT_DET_TRIG_EN    0 // TODO
89 
90 /**
91  * RTC_SLEEP_REJECT_MASK records sleep reject sources supported by chip
92  */
93 #define RTC_SLEEP_REJECT_MASK (RTC_EXT0_TRIG_EN         | \
94                                RTC_EXT1_TRIG_EN         | \
95                                RTC_GPIO_TRIG_EN         | \
96                                RTC_TIMER_TRIG_EN        | \
97                                RTC_WIFI_TRIG_EN         | \
98                                RTC_UART0_TRIG_EN        | \
99                                RTC_UART1_TRIG_EN        | \
100                                RTC_BT_TRIG_EN           | \
101                                RTC_LP_CORE_TRIG_EN      | \
102                                RTC_XTAL32K_DEAD_TRIG_EN | \
103                                RTC_USB_TRIG_EN          | \
104                                RTC_BROWNOUT_DET_TRIG_EN)
105 
106 #if SOC_PM_SUPPORT_EXT0_WAKEUP
107 #define PMU_EXT0_WAKEUP_EN          BIT(0)
108 #endif
109 #if SOC_PM_SUPPORT_EXT1_WAKEUP
110 #define PMU_EXT1_WAKEUP_EN          BIT(1)
111 #endif
112 
113 #define PMU_GPIO_WAKEUP_EN          BIT(2)
114 #define PMU_WIFI_BEACON_WAKEUP_EN   BIT(3)
115 #define PMU_LP_TIMER_WAKEUP_EN      BIT(4)
116 #define PMU_WIFI_SOC_WAKEUP_EN      BIT(5)
117 #define PMU_UART0_WAKEUP_EN         BIT(6)
118 #define PMU_UART1_WAKEUP_EN         BIT(7)
119 #define PMU_SDIO_WAKEUP_EN          BIT(8)
120 #define PMU_BLE_SOC_WAKEUP_EN       BIT(10)
121 #if SOC_LP_CORE_SUPPORTED
122 #define PMU_LP_CORE_WAKEUP_EN       BIT(11)
123 #endif //SOC_LP_CORE_SUPPORTED
124 #define PMU_USB_WAKEUP_EN           BIT(14)
125 
126 
127 #define PMU_SLEEP_PD_TOP            BIT(0)
128 #define PMU_SLEEP_PD_VDDSDIO        BIT(1)
129 #define PMU_SLEEP_PD_MODEM          BIT(2)
130 #define PMU_SLEEP_PD_HP_PERIPH      BIT(3)
131 #define PMU_SLEEP_PD_CPU            BIT(4)
132 
133 #if SOC_PM_SUPPORT_HP_AON_PD
134 #define PMU_SLEEP_PD_HP_AON         BIT(5)
135 #endif
136 
137 #define PMU_SLEEP_PD_MEM_G0         BIT(6)
138 #define PMU_SLEEP_PD_MEM_G1         BIT(7)
139 #define PMU_SLEEP_PD_MEM_G2         BIT(8)
140 #define PMU_SLEEP_PD_MEM_G3         BIT(9)
141 #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)
142 #define PMU_SLEEP_PD_XTAL           BIT(10)
143 #define PMU_SLEEP_PD_RC_FAST        BIT(11)
144 #define PMU_SLEEP_PD_XTAL32K        BIT(12)
145 #define PMU_SLEEP_PD_RC32K          BIT(13)
146 #define PMU_SLEEP_PD_LP_PERIPH      BIT(14)
147 
148 typedef struct {
149     pmu_hal_context_t *hal;
150     void *mc;
151 } pmu_context_t;
152 
153 pmu_context_t * PMU_instance(void);
154 
155 typedef enum pmu_hp_sysclk_src {
156     PMU_HP_SYSCLK_XTAL = 0,
157     PMU_HP_SYSCLK_PLL,
158     PMU_HP_SYSCLK_FOSC
159 } pmu_hp_sysclk_src_t;
160 
161 typedef enum pmu_sleep_protect_mode {
162     PMU_SLEEP_PROTECT_HP_SLEEP = 0,
163     PMU_SLEEP_PROTECT_XTAL,
164     PMU_SLEEP_PROTECT_HP_LP_SLEEP,
165     PMU_SLEEP_PROTECT_DISABLE
166 } pmu_sleep_protect_mode_t;
167 
168 typedef enum pmu_sleep_regdma_entry {
169     PMU_SLEEP_REGDMA_ENTRY_0 = 0,
170     PMU_SLEEP_REGDMA_ENTRY_1,
171     PMU_SLEEP_REGDMA_ENTRY_2,
172     PMU_SLEEP_REGDMA_ENTRY_3,
173     PMU_SLEEP_REGDMA_ENTRY_MAX
174 } pmu_sleep_regdma_entry_t;
175 
176 /**
177  * @brief PMU ICG modem code of HP system
178  */
179 typedef enum {
180     PMU_HP_ICG_MODEM_CODE_SLEEP = 0,
181     PMU_HP_ICG_MODEM_CODE_MODEM = 1,
182     PMU_HP_ICG_MODEM_CODE_ACTIVE = 2,
183 } pmu_hp_icg_modem_mode_t;
184 
185 
186 /**
187   * @brief  Enable_regdma_backup.
188   */
189 void pmu_sleep_enable_regdma_backup(void);
190 
191 /**
192   * @brief  Disable_regdma_backup.
193   */
194 void pmu_sleep_disable_regdma_backup(void);
195 
196 /**
197  * @brief Get sleep PLL enable status
198  *
199  * @return true if PLL is enabled by PMU in modem state
200  */
201 bool pmu_sleep_pll_already_enabled(void);
202 
203 /**
204  * @brief Calculate the hardware time overhead during sleep to compensate for sleep time
205  *
206  * @param pd_flags flags indicates the power domain that will be powered down
207  * @param slowclk_period re-calibrated slow clock period
208  * @param fastclk_period re-calibrated fast clock period
209  *
210  * @return hardware time overhead in us
211  */
212 uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t pd_flags, uint32_t slowclk_period, uint32_t fastclk_period);
213 
214 /**
215  * @brief Get default sleep configuration
216  * @param config pmu_sleep_config instance
217  * @param pd_flags flags indicates the power domain that will be powered down
218  * @param adjustment total software and hardware time overhead
219  * @param slowclk_period re-calibrated slow clock period in microseconds,
220  *                       Q13.19 fixed point format
221  * @param fastclk_period re-calibrated fast clock period in microseconds,
222  *                       Q13.19 fixed point format
223  * @param dslp configuration for deep sleep mode
224 
225  * @return hardware time overhead in us
226  */
227 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);
228 
229 /**
230  * @brief Prepare the chip to enter sleep mode
231  *
232  * This function configures various power/analog parameters and lp/lp system configuration
233  * used in sleep state machines
234  *
235  * This function does not actually enter sleep mode; this is done using
236  * pmu_sleep_start function. Software may do some other actions between
237  * pmu_sleep_init and pmu_sleep_start, such as set wakeup timer and configure
238  * wakeup sources.
239  *
240  * @param config sleep mode configuration
241  *
242  * @param dslp is initialize for deep sleep mode
243  */
244 void pmu_sleep_init(const pmu_sleep_config_t *config, bool dslp);
245 
246 /**
247  * @brief Enter deep or light sleep mode
248  *
249  * This function enters the sleep mode previously configured using pmu_sleep_init
250  * function. Before entering sleep, software should configure wake up sources
251  * appropriately (set up GPIO wakeup registers, timer wakeup registers,
252  * and so on).
253  *
254  * If deep sleep mode was configured using pmu_sleep_init, and sleep is not
255  * rejected by hardware (based on reject_opt flags), this function never returns.
256  * When the chip wakes up from deep sleep, CPU is reset and execution starts
257  * from ROM bootloader.
258  *
259  * If light sleep mode was configured using pmu_sleep_init, this function
260  * returns on wakeup, or if sleep is rejected by hardware.
261  *
262  * @param wakeup_opt  bit mask wake up reasons to enable (RTC_xxx_TRIG_EN flags
263  *                    combined with OR)
264  * @param reject_opt  bit mask of sleep reject reasons, used to
265  *                    prevent wakeup source set before the sleep request)
266  * @param lslp_mem_inf_fpu If non-zero then the low power config is restored
267  *                         immediately on wake. Recommended for light sleep,
268  *                         has no effect if the system goes into deep sleep.
269  *
270  * @return non-zero if sleep was rejected by hardware
271  */
272 uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp);
273 
274 /**
275  * @brief   Finish sleep process settings and get sleep reject status
276  * @return  return sleep reject status
277  */
278 bool pmu_sleep_finish(void);
279 
280 /**
281  * @brief Initialize PMU related power/clock/digital parameters and functions
282  */
283 void pmu_init(void);
284 
285 /**
286  * @brief Enable or disable system clock in PMU HP sleep state
287  *
288  * This API only used for fix BLE 40 MHz low power clock source issue
289  *
290  * @param enable  true to enable, false to disable
291  */
292 void pmu_sleep_enable_hp_sleep_sysclk(bool enable);
293 
294 /**
295  * Get the time overhead used by regdma to work on the retention link during the hardware wake-up process
296  * @return  regdma time cost during hardware wake-up stage in microseconds
297  */
298 uint32_t pmu_sleep_get_wakup_retention_cost(void);
299 
300 #endif //#if SOC_PMU_SUPPORTED
301 
302 #ifdef __cplusplus
303 }
304 #endif
305