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