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