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