1 /******************************************************************************
2 * Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
3 * All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *****************************************************************************/
18 #pragma once
19
20 #include "clock.h"
21 #include "compiler.h"
22 #include "gpio.h"
23 #include "reg_include/register_b91.h"
24
25 /********************************************************************************************************
26 * internal
27 *******************************************************************************************************/
28
29 /********************************************************************************************************
30 * This is currently included in the H file for compatibility with other SDKs.
31 *******************************************************************************************************/
32
33 /**
34 * When the watchdog comes back, the Eagle chip does not clear 0x7f[0].
35 * To avoid this problem, this macro definition is added.
36 */
37
38 #ifndef WDT_REBOOT_RESET_ANA7F_WORK_AROUND
39 #define WDT_REBOOT_RESET_ANA7F_WORK_AROUND 1
40 #endif
41
42 #ifndef SYS_TIMER_AUTO_MODE
43 #define SYS_TIMER_AUTO_MODE 1
44 #endif
45
46 /********************************************************************************************************
47 * external
48 *******************************************************************************************************/
49
50 /**
51 * @brief these analog register can store data in deepsleep mode or deepsleep with SRAM retention mode.
52 * Reset these analog registers by watchdog, chip reset, RESET Pin, power cycle
53 */
54 #define PM_ANA_REG_WD_CLR_BUF0 0x38 // initial value 0xff. [Bit0] is already occupied. The customer cannot change!
55
56 /**
57 * @brief analog register below can store infomation when MCU in deepsleep mode or deepsleep with SRAM retention mode.
58 * Reset these analog registers only by power cycle
59 */
60 #define PM_ANA_REG_POWER_ON_CLR_BUF0 \
61 0x39 // initial value 0x00. [Bit0] is already occupied. The customer cannot change!
62 #define PM_ANA_REG_POWER_ON_CLR_BUF1 0x3a // initial value 0x00
63 #define PM_ANA_REG_POWER_ON_CLR_BUF2 0x3b // initial value 0x00
64 #define PM_ANA_REG_POWER_ON_CLR_BUF3 0x3c // initial value 0x00
65 #define PM_ANA_REG_POWER_ON_CLR_BUF4 0x3d // initial value 0x00
66 #define PM_ANA_REG_POWER_ON_CLR_BUF5 0x3e // initial value 0x00
67 #define PM_ANA_REG_POWER_ON_CLR_BUF6 0x3f // initial value 0x0f
68
69 /**
70 * @brief gpio wakeup level definition
71 */
72 typedef enum {
73 WAKEUP_LEVEL_LOW = 0,
74 WAKEUP_LEVEL_HIGH = 1,
75 } pm_gpio_wakeup_level_e;
76
77 /**
78 * @brief wakeup tick type definition
79 */
80 typedef enum {
81 PM_TICK_STIMER_16M = 0,
82 PM_TICK_32K = 1,
83 } pm_wakeup_tick_type_e;
84
85 /**
86 * @brief suspend power weather to power down definition
87 */
88 typedef enum {
89 PM_POWERON_BASEBAND = BIT(0), // weather to power on the BASEBAND before suspend.
90 PM_POWERON_USB = BIT(1), // weather to power on the USB before suspend.
91 PM_POWERON_NPE = BIT(2), // weather to power on the NPE before suspend.
92 } pm_suspend_power_cfg_e;
93
94 /**
95 * @brief sleep mode.
96 */
97 typedef enum {
98 // available mode for customer
99 SUSPEND_MODE = 0x00, // The A0 version of the suspend execution process is abnormal and the program restarts.
100 DEEPSLEEP_MODE = 0x30, // when use deep mode pad wakeup(low or high level), if the high(low) level always in
101 // the pad, system will not enter sleep and go to below of pm API, will reboot by core_6f = 0x20
102 // deep retention also had this issue, but not to reboot.
103 DEEPSLEEP_MODE_RET_SRAM_LOW32K = 0x21, // for boot from sram
104 DEEPSLEEP_MODE_RET_SRAM_LOW64K = 0x03, // for boot from sram
105 // not available mode
106 DEEPSLEEP_RETENTION_FLAG = 0x0F,
107 } pm_sleep_mode_e;
108
109 /**
110 * @brief available wake-up source for customer
111 */
112 typedef enum {
113 PM_WAKEUP_PAD = BIT(3),
114 PM_WAKEUP_CORE = BIT(4),
115 PM_WAKEUP_TIMER = BIT(5),
116 PM_WAKEUP_COMPARATOR = BIT(6),
117 PM_WAKEUP_MDEC = BIT(7),
118 } pm_sleep_wakeup_src_e;
119
120 /**
121 * @brief wakeup status
122 */
123 typedef enum {
124 WAKEUP_STATUS_COMPARATOR = BIT(0),
125 WAKEUP_STATUS_TIMER = BIT(1),
126 WAKEUP_STATUS_CORE = BIT(2),
127 WAKEUP_STATUS_PAD = BIT(3),
128 WAKEUP_STATUS_MDEC = BIT(4),
129
130 STATUS_GPIO_ERR_NO_ENTER_PM = BIT(7),
131 STATUS_ENTER_SUSPEND = BIT(30),
132 } pm_wakeup_status_e;
133
134 /**
135 * @brief mcu status
136 */
137 typedef enum {
138 MCU_STATUS_POWER_ON = BIT(0),
139 MCU_STATUS_REBOOT_BACK = BIT(2),
140 MCU_STATUS_DEEPRET_BACK = BIT(3),
141 MCU_STATUS_DEEP_BACK = BIT(4),
142 MCU_STATUS_REBOOT_DEEP_BACK = BIT(5), // reboot + deep
143 } pm_mcu_status;
144
145 /**
146 * @brief early wakeup time
147 */
148 typedef struct {
149 unsigned short suspend_early_wakeup_time_us;
150 /** < suspend_early_wakeup_time_us = deep_ret_r_delay_us + xtal_stable_time + early_time */
151 unsigned short
152 deep_ret_early_wakeup_time_us; /** < deep_ret_early_wakeup_time_us = deep_ret_r_delay_us + early_time */
153 unsigned short deep_early_wakeup_time_us; /** < deep_early_wakeup_time_us = suspend_ret_r_delay_us */
154 unsigned short sleep_min_time_us; /** < sleep_min_time_us = suspend_early_wakeup_time_us + 200 */
155 } pm_early_wakeup_time_us_s;
156
157 /**
158 * @brief hardware delay time
159 */
160 typedef struct {
161 unsigned short deep_r_delay_cycle; /* hardware delay time ,deep_ret_r_delay_us = deep_r_delay_cycle * 1/16k */
162 unsigned short
163 suspend_ret_r_delay_cycle; /* hardware delay time,suspend_ret_r_delay_us = suspend_ret_r_delay_cycle * 1/16k */
164 } pm_r_delay_cycle_s;
165
166 /**
167 * @brief deepsleep wakeup status
168 */
169 typedef struct {
170 unsigned char is_pad_wakeup;
171 unsigned char wakeup_src;
172 /* The pad pin occasionally wakes up abnormally in A0. The core wakeup flag will be incorrectly set in A0 */
173 unsigned char mcu_status;
174 unsigned char rsvd;
175 } pm_status_info_s;
176
177 /**
178 * @brief pm 32k rc calibration algorithm.
179 */
180 typedef struct pm_clock_drift {
181 unsigned int ref_tick;
182 unsigned int ref_tick_32k;
183 int offset;
184 int offset_dc;
185 unsigned int offset_cal_tick;
186 int tc;
187 int rc32;
188 int rc32_wakeup;
189 int rc32_rt;
190 int s0;
191 unsigned char calib;
192 unsigned char ref_no;
193 } pm_clock_drift_t;
194
195 extern pm_clock_drift_t pmcd;
196 extern _attribute_aligned_(4) pm_status_info_s g_pm_status_info;
197 extern _attribute_data_retention_sec_ unsigned char g_pm_suspend_power_cfg;
198 extern _attribute_data_retention_sec_ unsigned char g_pm_vbat_v;
199
200 /**
201 * @brief This function servers to set the match value for MDEC wakeup.
202 * @param[in] value - the MDEC match value for wakeup.
203 * @return none.
204 */
pm_set_mdec_value_wakeup(unsigned char value)205 static inline void pm_set_mdec_value_wakeup(unsigned char value)
206 {
207 analog_write_reg8(mdec_ctrl, ((analog_read_reg8(mdec_ctrl) & (~0x0f)) | value));
208 }
209
210 /**
211 * @brief This function serves to set baseband/usb/npe power on.
212 * @param[in] value - weather to power on the baseband/usb/npe.
213 * @return none.
214 */
pm_set_suspend_power_cfg(pm_suspend_power_cfg_e value)215 static inline void pm_set_suspend_power_cfg(pm_suspend_power_cfg_e value)
216 {
217 g_pm_suspend_power_cfg &= (~value);
218 }
219
220 /**
221 * @brief This function serves to get deep retention flag.
222 * @return 1 deep retention, 0 deep.
223 */
pm_get_deep_retention_flag(void)224 static inline unsigned char pm_get_deep_retention_flag(void)
225 {
226 return !(analog_read_reg8(0x7f) & BIT(0));
227 }
228
229 /**
230 * @brief This function serves to get wakeup source.
231 * @return wakeup source.
232 */
pm_get_wakeup_src(void)233 static inline pm_wakeup_status_e pm_get_wakeup_src(void)
234 {
235 return analog_read_reg8(0x64);
236 }
237
238 /**
239 * @brief This function configures a GPIO pin as the wakeup pin.
240 * @param[in] pin - the pin needs to be configured as wakeup pin.
241 * @param[in] pol - the wakeup polarity of the pad pin(0: low-level wakeup, 1: high-level wakeup).
242 * @param[in] en - enable or disable the wakeup function for the pan pin(1: enable, 0: disable).
243 * @return none.
244 */
245 void pm_set_gpio_wakeup(gpio_pin_e pin, pm_gpio_wakeup_level_e pol, int en);
246
247 /**
248 * @brief This function configures pm wakeup time parameter.
249 * @param[in] param - pm wakeup time parameter.
250 * @return none.
251 */
252 void pm_set_wakeup_time_param(pm_r_delay_cycle_s param);
253
254 /**
255 * @brief this function servers to wait bbpll clock lock.
256 * @return none.
257 */
258 _attribute_ram_code_sec_noinline_ void pm_wait_bbpll_done(void);
259
260 /**
261 * @brief This function serves to recover system timer.
262 * The code is placed in the ram code section, in order to shorten the time.
263 * @return none.
264 */
265 _attribute_ram_code_sec_noinline_ void pm_stimer_recover(void);
266
267 /**
268 * @brief This function serves to set the working mode of MCU based on 32k crystal,
269 * e.g. suspend mode, deepsleep mode, deepsleep with SRAM retention mode and shutdown mode.
270 * @param[in] sleep_mode - sleep mode type select.
271 * @param[in] wakeup_src - wake up source select.
272 * A0 note: The reference current values under different configurations are as followsUnit (uA):
273 * | pad | 32k rc | 32k xtal | mdec | lpc |
274 * deep | 0.7 | 1.3 | 1.7 | 1.4 | 1.6 |
275 * deep ret 32k | 1.8 | 2.4 | 2.8 | 2.6 | 2.8 |
276 * deep ret 64k | 2.7 | 3.2 | 3.7 | 3.4 | 3.7 |
277 * A0 chip, the retention current will float up.
278 * @param[in] wakeup_tick_type - tick type select.
279 * For long timer sleep.currently only 16M is supported(PM_TICK_STIMER_16M).
280 * @param[in] wakeup_tick - the time of short sleep, which means MCU can sleep for less than 5 minutes.
281 * @return indicate whether the cpu is wake up successful.
282 */
283 _attribute_ram_code_sec_noinline_ int pm_sleep_wakeup(pm_sleep_mode_e sleep_mode, pm_sleep_wakeup_src_e wakeup_src,
284 pm_wakeup_tick_type_e wakeup_tick_type,
285 unsigned int wakeup_tick);
286
287 /**
288 * @brief Calculate the offset value based on the difference of 16M tick.
289 * @param[in] offset_tick - the 16M tick difference between the standard clock and the expected clock.
290 * @return none.
291 */
292 _attribute_ram_code_sec_noinline_ void pm_cal_32k_rc_offset(int offset_tick);
293
294 void pm_ble_32k_rc_cal_reset(void);
295 void pm_ble_cal_32k_rc_offset(int, int);
296
297 /**
298 * @brief When 32k rc sleeps, the calibration function is initialized.
299 * @return none.
300 */
301 _attribute_ram_code_sec_noinline_ void pm_32k_rc_offset_init(void);
302