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 #ifndef DRIVERS_B91_DRIVER_EXT_EXT_PM_H_
20 #define DRIVERS_B91_DRIVER_EXT_EXT_PM_H_
21
22 #include <zephyr.h>
23 #undef irq_enable
24 #undef irq_disable
25 #undef ARRAY_SIZE
26
27 #include "../pm.h"
28 #include "types.h"
29 #include "ext_misc.h"
30
31 #ifndef PM_32k_RC_CALIBRATION_ALGORITHM_EN
32 #define PM_32k_RC_CALIBRATION_ALGORITHM_EN 1
33 #endif
34
35 #define SYS_NEED_REINIT_EXT32K BIT(1)
36 #define WAKEUP_STATUS_TIMER_CORE ( WAKEUP_STATUS_TIMER | WAKEUP_STATUS_CORE)
37 #define WAKEUP_STATUS_TIMER_PAD ( WAKEUP_STATUS_TIMER | WAKEUP_STATUS_PAD)
38
39 /**
40 * @brief analog register below can store infomation when MCU in deepsleep mode
41 * store your information in these ana_regs before deepsleep by calling analog_write function
42 * when MCU wakeup from deepsleep, read the information by by calling analog_read function
43 * Reset these analog registers only by power cycle
44 */
45 #define DEEP_ANA_REG0 0x39 //initial value =0x00
46 #define DEEP_ANA_REG1 0x3a //initial value =0x00
47 #define DEEP_ANA_REG2 0x3b //initial value =0x00
48 #define DEEP_ANA_REG3 0x3c //initial value =0x00
49 #define DEEP_ANA_REG4 0x3d //initial value =0x00
50 #define DEEP_ANA_REG5 0x3e //initial value =0x00
51 #define DEEP_ANA_REG6 0x3f //initial value =0x0f
52
53 /**
54 * @brief these analog register can store data in deepsleep mode or deepsleep with SRAM retention mode.
55 * Reset these analog registers by watchdog, chip reset, RESET Pin, power cycle
56 */
57
58 #define DEEP_ANA_REG7 0x38 //initial value =0xff
59
60 //ana3e system used, user can not use
61 #define SYS_DEEP_ANA_REG PM_ANA_REG_POWER_ON_CLR_BUF0
62
63 #define cpu_set_gpio_wakeup pm_set_gpio_wakeup
64
65 #define PM_MIN_SLEEP_US 1500 /* Eagle chip specific */
66
67
68 /**
69 * @brief available wake-up source for customer
70 */
71 typedef enum {
72 //not available wake-up source for customer
73 PM_TIM_RECOVER_START = BIT(14),
74 PM_TIM_RECOVER_END = BIT(15),
75 }pm_tim_recover_wakeup_src_e;
76
77
78
79 typedef pm_sleep_mode_e SleepMode_TypeDef;
80 typedef pm_sleep_wakeup_src_e SleepWakeupSrc_TypeDef;
81
82
83 typedef int (*suspend_handler_t)(void);
84 typedef void (*check_32k_clk_handler_t)(void);
85 typedef unsigned int (*pm_get_32k_clk_handler_t)(void);
86 typedef int (*cpu_pm_handler_t)(SleepMode_TypeDef sleep_mode, SleepWakeupSrc_TypeDef wakeup_src, unsigned int wakeup_tick);
87 typedef unsigned int (*pm_tim_recover_handler_t)(unsigned int);
88
89 extern cpu_pm_handler_t cpu_sleep_wakeup;
90 extern suspend_handler_t func_before_suspend;
91 extern check_32k_clk_handler_t pm_check_32k_clk_stable;
92 extern pm_get_32k_clk_handler_t pm_get_32k_tick;
93 extern pm_tim_recover_handler_t pm_tim_recover;
94
95 /**
96 * @brief gpio wakeup level definition
97 */
98 typedef enum{
99 Level_Low=0,
100 Level_High =1,
101 }pm_gpio_wakeup_Level_e;
102
103
104 /**
105 * @brief deepsleep wakeup by external xtal
106 */
107 typedef struct{
108 unsigned char ext_cap_en; //24xtal cap
109 unsigned char pad32k_en;
110 unsigned char pm_enter_en;
111 unsigned char rsvd;
112 }misc_para_t;
113
114 extern _attribute_aligned_(4) misc_para_t blt_miscParam;
115
116 /********************************** Internal APIs (not for user) ***************************************************/
117 extern unsigned char tl_24mrc_cal;
118 extern unsigned int g_pm_tick_32k_calib;
119 extern unsigned int g_pm_tick_cur;
120 extern unsigned int g_pm_tick_32k_cur;
121 extern unsigned char g_pm_long_suspend;
122 extern unsigned int g_pm_multi_addr;
123
124 extern unsigned int g_sleep_32k_rc_cnt;
125 extern unsigned int g_sleep_stimer_tick;
126
127 extern unsigned int ota_program_bootAddr;
128 extern unsigned int ota_program_offset;
129 /******************************** end of Internal APIs (not for user) **********************************************/
130
131
132 /**
133 * @brief This function sets pm suspend handler.
134 * @param[in] func - handler function.
135 * @return none.
136 */
137 void bls_pm_registerFuncBeforeSuspend(suspend_handler_t func);
138
139 /**
140 * @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.
141 * @param[in] sleep_mode - sleep mode type select.
142 * @param[in] wakeup_src - wake up source select.
143 * @param[in] wakeup_tick - the time of short sleep, which means MCU can sleep for less than 5 minutes.
144 * @return indicate whether the cpu is wake up successful.
145 */
146 int cpu_sleep_wakeup_32k_rc(SleepMode_TypeDef sleep_mode, SleepWakeupSrc_TypeDef wakeup_src, unsigned int wakeup_tick);
147
148 /**
149 * @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.
150 * @param[in] sleep_mode - sleep mode type select.
151 * @param[in] wakeup_src - wake up source select.
152 * @param[in] wakeup_tick - the time of short sleep, which means MCU can sleep for less than 5 minutes.
153 * @return indicate whether the cpu is wake up successful.
154 */
155 int cpu_sleep_wakeup_32k_xtal(SleepMode_TypeDef sleep_mode, SleepWakeupSrc_TypeDef wakeup_src, unsigned int wakeup_tick);
156
157 /**
158 * @brief This function serves to start sleep mode.
159 * @param none.
160 * @return none.
161 */
162 void pm_sleep_start(void);
163
164 /**
165 * @brief This function serves to reboot chip.
166 * @param none.
167 * @return none.
168 */
169 void start_reboot(void);
170
171 /**
172 * @brief This function serves to recover system timer from tick of internal 32k RC.
173 * @param none.
174 * @return none.
175 */
176 unsigned int pm_tim_recover_32k_rc(unsigned int now_tick_32k);
177
178 /**
179 * @brief This function serves to recover system timer from tick of external 32k crystal.
180 * @param none.
181 * @return none.
182 */
183 unsigned int pm_tim_recover_32k_xtal(unsigned int now_tick_32k);
184
185 /**
186 * @brief This function serves to get the 32k tick.
187 * @param none
188 * @return tick of 32k.
189 */
190 extern unsigned int get_32k_tick(void);
191
192 /**
193 * @brief This function serves to get the 32k digital tick.
194 * @param none
195 * @return digital tick of 32k.
196 */
197 unsigned int clock_get_digital_32k_tick(void);
198
199 /**
200 * @brief This function serves to determine whether external wakeup source to be used
201 * @param[in] none.
202 * @return none.
203 */
blc_pm_set_extern_wakeup_recover(cpu_pm_handler_t wakeup,pm_tim_recover_handler_t recover)204 static inline void blc_pm_set_extern_wakeup_recover(cpu_pm_handler_t wakeup, pm_tim_recover_handler_t recover)
205 {
206 cpu_sleep_wakeup = wakeup;
207 pm_tim_recover = recover;
208
209 blt_miscParam.pm_enter_en = 1;
210 }
211
212 /**
213 * @brief This function serves to determine whether wake up source is internal 32k RC.
214 * @param[in] none.
215 * @return none.
216 */
blc_pm_select_internal_32k_crystal(void)217 static inline void blc_pm_select_internal_32k_crystal(void)
218 {
219 cpu_sleep_wakeup = cpu_sleep_wakeup_32k_rc;
220 pm_tim_recover = pm_tim_recover_32k_rc;
221
222 blt_miscParam.pm_enter_en = 1; // allow enter pm, 32k rc does not need to wait for 32k clk to be stable
223 }
224
225 /**
226 * @brief This function waits for 32K oscillator frequency stabilization.
227 * @param[in] none.
228 * @return none.
229 */
230 extern void check_32k_clk_stable(void);
231
232 /**
233 * @brief This function serves to determine whether wake up source is external 32k RC.
234 * @param[in] none.
235 * @return none.
236 */
blc_pm_select_external_32k_crystal(void)237 static inline void blc_pm_select_external_32k_crystal(void)
238 {
239 cpu_sleep_wakeup = cpu_sleep_wakeup_32k_xtal;
240 pm_check_32k_clk_stable = check_32k_clk_stable;
241 pm_tim_recover = pm_tim_recover_32k_xtal;
242 pm_get_32k_tick = get_32k_tick;
243 blt_miscParam.pad32k_en = 1; // set '1': 32k clk src use external 32k crystal
244 }
245
246 /**
247 * @brief This function servers to wake up the cpu from sleep mode.
248 * @param[in] sleep_mode - sleep mode type select.
249 * @param[in] wakeup_src - wake up source select.
250 * @param[in] wakeup_tick - the time of sleep,unit is 31.25us,1ms = 32.
251 * @return indicate whether the cpu is wake up successful.
252 */
253 int cpu_long_sleep_wakeup_32k_rc(SleepMode_TypeDef sleep_mode, SleepWakeupSrc_TypeDef wakeup_src, unsigned int wakeup_tick);
254
255 /**
256 * @brief This function serves to determine whether mcu is waked up from deep retention.
257 * @param[in] none.
258 * @return 1- yes , 0- no.
259 */
pm_is_MCU_deepRetentionWakeup(void)260 static inline int pm_is_MCU_deepRetentionWakeup(void)
261 {
262 return (g_pm_status_info.mcu_status & MCU_STATUS_DEEPRET_BACK);
263 }
264
265 /**
266 * @brief This function serves to determine whether mcu is waked up by pad.
267 * @param[in] none.
268 * @return 1- yes , 0- no.
269 */
pm_is_deepPadWakeup(void)270 static inline int pm_is_deepPadWakeup(void)
271 {
272 return g_pm_status_info.is_pad_wakeup;
273 }
274
275 /**
276 * @brief This function serves to get the status of mcu.
277 * @param[in] none.
278 * @return mcu_status.
279 */
pm_get_mcu_status(void)280 static inline int pm_get_mcu_status(void)
281 {
282 return g_pm_status_info.mcu_status;
283 }
284
pm_get_latest_offset_cal_time(void)285 static inline unsigned int pm_get_latest_offset_cal_time(void)
286 {
287 return pmcd.offset_cal_tick;
288 }
289
290 #endif /* DRIVERS_B91_DRIVER_EXT_EXT_PM_H_ */
291