1 /**
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 *
15 * Description: Provide pm port source. \n
16 *
17 * History: \n
18 * 2023-11-13, Create file. \n
19 */
20
21 #include <los_task.h>
22 #include "errcode.h"
23 #include "chip_io.h"
24 #include "osal_types.h"
25 #include "soc_osal.h"
26 #include "arch_barrier.h"
27 #include "debug_print.h"
28 #include "tcxo.h"
29 #include "timer.h"
30 #include "timer_porting.h"
31 #include "soc_porting.h"
32 #include "uart.h"
33 #include "uart_porting.h"
34 #include "dma.h"
35 #include "gpio.h"
36 #include "efuse.h"
37 #include "tsensor.h"
38 #include "watchdog.h"
39 #include "clock_init.h"
40 #include "security_init.h"
41 #include "pinctrl.h"
42 #include "efuse.h"
43 #include "main.h"
44 #include "wifi_device.h"
45 #include "hal_watchdog_v151_regs_op.h"
46 #include "hal_watchdog.h"
47 #include "radar_service.h"
48 #include "reboot_porting.h"
49 #include "pm_porting.h"
50
51 // 寄存器地址定义
52 #define REG_AON_CRG_CKEN_CTL 0x40002100
53 #define REG_AON_SOFT_RST_CTL 0x40002110
54
55 #define REG_PMU_CMULDO1_0P9 0x4000312C
56 #define REG_PMU_RXLDO_1P0 0x40003134
57 #define REG_PMU_LNALDO_1P0 0x40003138
58 #define REG_PMU_VCOLDO_1P0 0x40003140
59 #define REG_PMU_ABBLDO_1P0 0x40003144
60 #define REG_PMU_PLLLDO_1P0 0x40003148
61 #define REG_PMU_TXLDO_1P8 0x40003168
62 #define REG_PMU_PHY_LDO 0x4000316C
63 #define REG_EXCEP_RO_RG 0x4000319C
64 #define REG_ISO_SIG 0x40003230
65
66 #define REG_FNPLL_CFG0 0x4000340C
67 #define REG_FNPLL_CFG1 0x40003410
68 #define REG_FNPLL_CFG2 0x40003414
69 #define REG_FNPLL_CFG3 0x40003418
70 #define REG_FNPLL_CFG4 0x4000341C
71 #define REG_FNPLL_CFG5 0x40003420
72
73 #define REG_CMU_FNPLL_SIG 0x4000342C
74 #define REG_CMU_FBDIV 0x40003430
75 #define REG_CMU_FRAC 0x40003434
76 #define REG_CMU_CLK_480M_WDBB 0x4000344C
77
78 #define REG_WDT_CR 0x40006010
79
80 #define REG_CLDO_SUB_CRG_CKEN_CTL0 0x44001100
81 #define REG_CLDO_SUB_CRG_CKEN_CTL1 0x44001104
82 #define REG_CLDO_CRG_DIV_CTL0 0x44001108
83 #define REG_CLDO_CRG_DIV_CTL7 0x44001124
84 #define REG_CLDO_CRG_CLK_SEL 0x44001134
85 #define REG_CLDO_CRG_RST_SOFT_CFG0 0x44001138
86 #define REG_CLDO_CRG_RST_SOFT_CFG1 0x4400113C
87
88 #define TCXO_CLOCK_24M 24000000
89 #define TCXO_CLOCK_40M 40000000
90 #define PLL_CLOCK_160M 160000000
91 #define PMU_RF_OPEN_DELAY_US 120
92 #define RF_PLL_LOCK_DELAY_US 100
93 #define PMU_PROCESS_DELAY_US 10
94 #define UART_PRINT_DELAY_MS 10
95 #define WIFI_BLE_HW_PROCESS_DELAY_US 10
96
97 // 恢复时FNPLL锁定及查询处理
98 #define PLL_LOCKED 1
99 #define PLL_UNLOCKED 0
100 #define FNPLL_LOCK_RETRY_DELAY_US 2
101 #define FNPLL_LOCK_QUERY_DELAY_MS 1
102 #define FNPLL_LOCK_RETRY_TIMES 3
103 #define FNPLL_LOCK_QUERY_TIMES 30
104
105 // 当前记录 GPIO 0-14 的IOCFG信息, 保留UART0/1
106 #define IOCFG_RECORD_NUM 15
107 #define REG_GPIO_SEL_START_ADDR 0x4400D000
108 #define REG_GPIO_PAD_START_ADDR 0x4400D800
109 #define REG_ADDR_INTERVAL 0x4
110 #define VAL_GPIO_SEL_DEFAULT 0x0
111 #define VAL_GPIO_PAD_DEFAULT 0x800
112
113 // 仅保留WKUP_UART允许唤醒, 其余UART低功耗过程中关中断
114 #define WKUP_UART CONFIG_PM_SUPPORT_WKUP_UART
115
116 // 看门狗默认超时时间
117 #define WDT_TIMEOUT_S 15
118
119 #define PM_ENTER_LOWPOWER_WFI_DELAY_MS 200
120 #define PM_WAIT_EXIT_LOWPOWER_MS 100
121 #define PM_WAIT_FLASH_WORK_DOWN_MS 10
122
123 typedef enum {
124 PM_CRG_CKEN_CTL0 = 0,
125 PM_CRG_CKEN_CTL1,
126 PM_CRG_RST_CTL0,
127 PM_CRG_RST_CTL1,
128 PM_CRG_RECORD_MAX
129 } pm_crg_record_index_t;
130
131 // 相关寄存器状态记录变量
132 uint32_t g_pm_iocfg_sel_record[IOCFG_RECORD_NUM] = {};
133 uint32_t g_pm_iocfg_pad_record[IOCFG_RECORD_NUM] = {};
134 uint32_t g_pm_crg_record[PM_CRG_RECORD_MAX] = {};
135 uint32_t g_pm_uart_clock_record[UART_BUS_MAX_NUMBER] = {};
136 uint32_t g_pm_wdt_timeout = 0;
137 uint32_t g_pm_wdt_mode = 0;
138
139 #ifdef CONFIG_PM_SUPPORT_SRV_DECOUPLING
140 typedef enum {
141 PM_CTRL_INIT,
142 PM_CTRL_RESUME,
143 PM_CTRL_SUSPEND,
144 PM_CTRL_MAX,
145 } pm_ctrl_mode;
146
147 typedef struct _pm_srv_ctrl {
148 pm_srv_mode srv_mode[PM_SRV_MAX];
149 pm_ctrl_mode ctrl_mode;
150 pm_ctrl_mode ctrl_protect;
151 } pm_srv_ctrl;
152
153 pm_srv_ctrl g_pm_srv_ctrl = {0};
154
pm_print_srv_stats(void)155 static void pm_print_srv_stats(void)
156 {
157 uint32_t srv_index = 0;
158 while (srv_index < PM_SRV_MAX) {
159 PRINT("pm_srv[%u] mode[%u].\r\n", srv_index, g_pm_srv_ctrl.srv_mode[srv_index]);
160 srv_index++;
161 }
162 PRINT("pm_ctrl:[%u] :protect[%u].\r\n", g_pm_srv_ctrl.ctrl_mode, g_pm_srv_ctrl.ctrl_protect);
163 }
164
pm_config_srv_power(pm_srv_type svr,pm_srv_mode mode)165 static void pm_config_srv_power(pm_srv_type svr, pm_srv_mode mode)
166 {
167 PRINT("[pm_port] svc[%u] mode change: [%u] -> [%u]\r\n", svr, g_pm_srv_ctrl.srv_mode[svr], mode);
168 if ((mode == PM_MODE_SUSPEND) && (g_pm_srv_ctrl.srv_mode[svr] != PM_MODE_SUSPEND)) {
169 /* 关闭模块时钟和模块复位 */
170 if (svr == PM_SRV_WIFI) {
171 pm_port_close_wifi_hw();
172 }
173 if (svr == PM_SRV_BLE) {
174 pm_port_close_bt_hw();
175 }
176 } else if ((mode == PM_MODE_RESUME) && (g_pm_srv_ctrl.srv_mode[svr] == PM_MODE_SUSPEND)) {
177 /* 恢复模块时钟 */
178 if (svr == PM_SRV_WIFI) {
179 pm_port_open_wifi_hw();
180 }
181 if (svr == PM_SRV_BLE) {
182 pm_port_open_bt_hw();
183 }
184 }
185 PRINT("[pm_port] mode change finish.\r\n");
186 }
187
pm_set_srv_mode(pm_srv_type svr,pm_srv_mode mode)188 errcode_t pm_set_srv_mode(pm_srv_type svr, pm_srv_mode mode)
189 {
190 uint32_t srv_index = 0;
191 uint32_t irq_flag;
192 bool pm_suspend = true;
193
194 if (svr >= PM_SRV_PLAT || mode >= PM_MODE_MAX) {
195 return ERRCODE_FAIL;
196 }
197
198 PRINT("pm_set_srv_mode srv:%u, mode:%u.\r\n", svr, mode);
199 irq_flag = osal_irq_lock();
200 pm_config_srv_power(svr, mode);
201 g_pm_srv_ctrl.srv_mode[svr] = mode;
202 if (mode > PM_MODE_SUSPEND) {
203 g_pm_srv_ctrl.srv_mode[PM_SRV_PLAT] = PM_MODE_RESUME;
204 osal_irq_restore(irq_flag);
205 return ERRCODE_SUCC;
206 }
207 while (srv_index < PM_SRV_PLAT) {
208 if (g_pm_srv_ctrl.srv_mode[srv_index] > PM_MODE_SUSPEND) {
209 pm_suspend = false;
210 break;
211 }
212 srv_index++;
213 }
214 if (pm_suspend) {
215 PRINT("pm_set_srv_mode plat suspend.\r\n");
216 g_pm_srv_ctrl.srv_mode[PM_SRV_PLAT] = PM_MODE_SUSPEND;
217 }
218 osal_irq_restore(irq_flag);
219 return ERRCODE_SUCC;
220 }
221
pm_porting_init(void)222 errcode_t pm_porting_init(void)
223 {
224 uint32_t srv_index = 0;
225 while (srv_index < PM_SRV_MAX) {
226 g_pm_srv_ctrl.srv_mode[srv_index] = PM_MODE_INIT;
227 srv_index++;
228 }
229 g_pm_srv_ctrl.ctrl_mode = PM_CTRL_INIT;
230 g_pm_srv_ctrl.ctrl_protect = PM_CTRL_INIT;
231 return ERRCODE_SUCC;
232 }
233 #endif
234
235 // 低功耗处理回调
236 pm_hook_cb_t g_pm_hook_cb_list[PM_HOOK_MAX_NUM] = {
237 pm_port_enter_lowpower_prepare_cb_default,
238 pm_port_enter_lowpower_finish_cb_default,
239 pm_port_exit_lowpower_prepare_cb_default,
240 pm_port_exit_lowpower_finish_cb_default
241 };
242
243 // wifi bt 硬件状态记录
244 bool g_pm_is_wifi_hw_open = true;
245 bool g_pm_is_bt_hw_open = true;
246
247 // 低功耗状态记录
248 #ifndef CONFIG_PM_SUPPORT_SRV_DECOUPLING
249 bool g_pm_is_in_lowpower = false;
250 bool g_pm_is_in_process = false;
251 #endif
252
253 #define HW_CTL 0x40000014
254 #define EXCEP_RO_RG 0x4000319c
255 #define CMU_CLK_320M_WDBB 0x40003448
256 #define CMU_CLK_480M_WDBB 0x4000344c
257 #define CMU_CLK_24M_USB 0x40003454
258 #define CLDO_CRG_CLK_SEL 0x44001134
259 #define CLDO_CRG_DIV_CTL0 0x44001108
260
261 #define CLOCK_MASK 0x1
262 #define CLOCK_24MHZ 0x1
263
check_efuse_boot_done(void)264 static void check_efuse_boot_done(void)
265 {
266 #define EFUSE_STS 0x4400802c
267 #define EFUSE_BOOT_DONE_MASK 0x4
268 #define MAX_RETRY_TIMES 50
269 uint32_t data;
270
271 for (uint32_t i = 0; i < MAX_RETRY_TIMES; i++) {
272 data = readl(EFUSE_STS);
273 if ((data & EFUSE_BOOT_DONE_MASK) == EFUSE_BOOT_DONE_MASK) {
274 break;
275 }
276 uapi_tcxo_delay_ms(1);
277 }
278 }
279
set_efuse_clock_period(void)280 static void set_efuse_clock_period(void)
281 {
282 #define EFUSE_CLOCK_PERIOD 0x44008034
283 #define EFUSE_24M_CLOCK_PERIOD 0x29
284 #define EFUSE_40M_CLOCK_PERIOD 0x19
285 uint32_t reg_value = 0;
286 reg_value = readl(HW_CTL);
287 if ((reg_value & CLOCK_MASK) == CLOCK_24MHZ) {
288 writel(EFUSE_CLOCK_PERIOD, EFUSE_24M_CLOCK_PERIOD);
289 } else {
290 writel(EFUSE_CLOCK_PERIOD, EFUSE_40M_CLOCK_PERIOD);
291 }
292 }
293
pm_port_open_rf(void)294 void pm_port_open_rf(void)
295 {
296 uapi_reg_setbits(REG_PMU_RXLDO_1P0, 14, 1, 0x1); // 0x1 -> 0x40003134 bit 14
297 uapi_tcxo_delay_us(PMU_RF_OPEN_DELAY_US);
298 uapi_reg_setbits(REG_PMU_RXLDO_1P0, 13, 1, 0x1); // 0x1 -> 0x40003134 bit 13
299 uapi_tcxo_delay_us(PMU_PROCESS_DELAY_US);
300
301 uapi_reg_setbits(REG_PMU_PLLLDO_1P0, 14, 1, 0x1); // 0x1 -> 0x40003148 bit 14
302 uapi_tcxo_delay_us(PMU_RF_OPEN_DELAY_US);
303 uapi_reg_setbits(REG_PMU_PLLLDO_1P0, 13, 1, 0x1); // 0x1 -> 0x40003148 bit 13
304 uapi_tcxo_delay_us(PMU_PROCESS_DELAY_US);
305
306 uapi_reg_setbits(REG_PMU_LNALDO_1P0, 14, 1, 0x1); // 0x1 -> 0x40003138 bit 14
307 uapi_tcxo_delay_us(PMU_RF_OPEN_DELAY_US);
308 uapi_reg_setbits(REG_PMU_LNALDO_1P0, 13, 1, 0x1); // 0x1 -> 0x40003138 bit 13
309 uapi_tcxo_delay_us(PMU_PROCESS_DELAY_US);
310
311 uapi_reg_setbits(REG_PMU_VCOLDO_1P0, 14, 1, 0x1); // 0x1 -> 0x40003140 bit 14
312 uapi_tcxo_delay_us(PMU_RF_OPEN_DELAY_US);
313 uapi_reg_setbits(REG_PMU_VCOLDO_1P0, 13, 1, 0x1); // 0x1 -> 0x40003140 bit 13
314 uapi_tcxo_delay_us(PMU_PROCESS_DELAY_US);
315
316 uapi_reg_setbits(REG_PMU_TXLDO_1P8, 14, 1, 0x1); // 0x1 -> 0x40003168 bit 14
317 uapi_tcxo_delay_us(PMU_RF_OPEN_DELAY_US);
318 uapi_reg_setbits(REG_PMU_TXLDO_1P8, 13, 1, 0x1); // 0x1 -> 0x40003168 bit 13
319 uapi_tcxo_delay_us(PMU_PROCESS_DELAY_US);
320
321 uapi_reg_setbits(REG_PMU_ABBLDO_1P0, 14, 1, 0x1); // 0x1 -> 0x40003144 bit 14
322 uapi_tcxo_delay_us(PMU_RF_OPEN_DELAY_US);
323 uapi_reg_setbits(REG_PMU_ABBLDO_1P0, 13, 1, 0x1); // 0x1 -> 0x40003144 bit 13
324 uapi_tcxo_delay_us(PMU_PROCESS_DELAY_US);
325
326 uapi_reg_write(REG_ISO_SIG, 0x3); // 0x3 -> 0x40003230
327 uapi_tcxo_delay_us(RF_PLL_LOCK_DELAY_US);
328 }
329
pm_port_close_rf(void)330 void pm_port_close_rf(void)
331 {
332 uapi_reg_write(REG_ISO_SIG, 0xC); // 0xC -> 0x40003230
333 uapi_reg_setbits(REG_PMU_ABBLDO_1P0, 13, 2, 0x0); // 0x0 -> 0x40003144 bit 14:13 (2 bits)
334 uapi_tcxo_delay_us(PMU_PROCESS_DELAY_US);
335 uapi_reg_setbits(REG_PMU_TXLDO_1P8, 13, 2, 0x0); // 0x0 -> 0x40003168 bit 14:13 (2 bits)
336 uapi_tcxo_delay_us(PMU_PROCESS_DELAY_US);
337 uapi_reg_setbits(REG_PMU_VCOLDO_1P0, 13, 2, 0x0); // 0x0 -> 0x40003140 bit 14:13 (2 bits)
338 uapi_tcxo_delay_us(PMU_PROCESS_DELAY_US);
339 uapi_reg_setbits(REG_PMU_LNALDO_1P0, 13, 2, 0x0); // 0x0 -> 0x40003138 bit 14:13 (2 bits)
340 uapi_tcxo_delay_us(PMU_PROCESS_DELAY_US);
341 uapi_reg_setbits(REG_PMU_PLLLDO_1P0, 13, 2, 0x0); // 0x0 -> 0x40003148 bit 14:13 (2 bits)
342 uapi_tcxo_delay_us(PMU_PROCESS_DELAY_US);
343 uapi_reg_setbits(REG_PMU_RXLDO_1P0, 13, 2, 0x0); // 0x0 -> 0x40003134 bit 14:13 (2 bits)
344 }
345
pm_port_open_wifi_sub(void)346 void pm_port_open_wifi_sub(void)
347 {
348 // wifi 开启
349 uapi_reg_setbits(REG_CLDO_SUB_CRG_CKEN_CTL1, 13, 2, 0x3); // 0x3 -> 0x44001104 bit 14:13 (2 bits)
350 uapi_reg_setbits(REG_CLDO_SUB_CRG_CKEN_CTL1, 29, 1, 0x1); // 0x1 -> 0x44001104 bit 29
351 uapi_reg_setbits(REG_CLDO_CRG_RST_SOFT_CFG1, 4, 1, 0x1); // 0x1 -> 0x4400113C bit 4
352 uapi_tcxo_delay_us(WIFI_BLE_HW_PROCESS_DELAY_US);
353 }
354
pm_port_close_wifi_sub(void)355 void pm_port_close_wifi_sub(void)
356 {
357 // wifi 关闭
358 uapi_reg_setbits(REG_CLDO_CRG_RST_SOFT_CFG1, 4, 1, 0x0); // 0x0 -> 0x4400113C bit 4
359 uapi_reg_setbits(REG_CLDO_SUB_CRG_CKEN_CTL1, 13, 2, 0x0); // 0x0 -> 0x44001104 bit 14:13 (2 bits)
360 uapi_reg_setbits(REG_CLDO_SUB_CRG_CKEN_CTL1, 29, 1, 0x0); // 0x0 -> 0x44001104 bit 29
361 uapi_tcxo_delay_us(WIFI_BLE_HW_PROCESS_DELAY_US);
362 }
363
pm_port_open_bt_sub(void)364 void pm_port_open_bt_sub(void)
365 {
366 // BT 开启
367 uapi_reg_setbits(REG_CLDO_SUB_CRG_CKEN_CTL1, 8, 5, 0x1F); // 0x1F -> 0x44001104 bit 12:8 (5 bits)
368 uapi_reg_setbits(REG_CLDO_CRG_RST_SOFT_CFG1, 1, 3, 0x7); // 0x7 -> 0x4400113C bit 3:1 (3 bits)
369 uapi_tcxo_delay_us(WIFI_BLE_HW_PROCESS_DELAY_US);
370 }
371
pm_port_close_bt_sub(void)372 void pm_port_close_bt_sub(void)
373 {
374 // BT 关闭
375 uapi_reg_setbits(REG_CLDO_CRG_RST_SOFT_CFG1, 1, 3, 0x0); // 0x0 -> 0x4400113C bit 3:1 (3 bits)
376 uapi_reg_setbits(REG_CLDO_SUB_CRG_CKEN_CTL1, 8, 5, 0x0); // 0x0 -> 0x44001104 bit 12:8 (5 bits)
377 uapi_tcxo_delay_us(WIFI_BLE_HW_PROCESS_DELAY_US);
378 }
379
pm_port_open_wifi_hw(void)380 void pm_port_open_wifi_hw(void)
381 {
382 uint32_t irq_status;
383 irq_status = osal_irq_lock();
384 if (g_pm_is_wifi_hw_open) {
385 osal_irq_restore(irq_status);
386 return;
387 }
388
389 // wifi ble 首次打开时开启RF
390 if (!(g_pm_is_wifi_hw_open || g_pm_is_bt_hw_open)) {
391 pm_port_open_rf();
392 }
393
394 pm_port_open_wifi_sub();
395
396 g_pm_is_wifi_hw_open = true;
397 osal_irq_restore(irq_status);
398 return;
399 }
400
pm_port_close_wifi_hw(void)401 void pm_port_close_wifi_hw(void)
402 {
403 uint32_t irq_status;
404 irq_status = osal_irq_lock();
405 if (!g_pm_is_wifi_hw_open) {
406 osal_irq_restore(irq_status);
407 return;
408 }
409
410 pm_port_close_wifi_sub();
411 g_pm_is_wifi_hw_open = false;
412
413 // wifi ble 全部关闭时关闭RF
414 if (!(g_pm_is_wifi_hw_open || g_pm_is_bt_hw_open)) {
415 pm_port_close_rf();
416 }
417
418 osal_irq_restore(irq_status);
419 return;
420 }
421
pm_port_open_bt_hw(void)422 void pm_port_open_bt_hw(void)
423 {
424 uint32_t irq_status;
425 irq_status = osal_irq_lock();
426 if (g_pm_is_bt_hw_open) {
427 osal_irq_restore(irq_status);
428 return;
429 }
430
431 // wifi ble 首次打开时开启RF
432 if (!(g_pm_is_wifi_hw_open || g_pm_is_bt_hw_open)) {
433 pm_port_open_rf();
434 }
435
436 pm_port_open_bt_sub();
437
438 g_pm_is_bt_hw_open = true;
439 osal_irq_restore(irq_status);
440 return;
441 }
442
pm_port_close_bt_hw(void)443 void pm_port_close_bt_hw(void)
444 {
445 uint32_t irq_status;
446 irq_status = osal_irq_lock();
447 if (!g_pm_is_bt_hw_open) {
448 osal_irq_restore(irq_status);
449 return;
450 }
451
452 pm_port_close_bt_sub();
453 g_pm_is_bt_hw_open = false;
454
455 // wifi ble 全部关闭时关闭RF
456 if (!(g_pm_is_wifi_hw_open || g_pm_is_bt_hw_open)) {
457 pm_port_close_rf();
458 }
459
460 osal_irq_restore(irq_status);
461 return;
462 }
463
464 #define PM_FLASH_SEM_INIT_CNT 1
465 osal_semaphore *g_flash_sem = NULL;
466
pm_port_flash_sem_down(void)467 int pm_port_flash_sem_down(void)
468 {
469 if (g_flash_sem == NULL) {
470 g_flash_sem = (osal_semaphore *)osal_kmalloc(sizeof(osal_semaphore), 0);
471 if (g_flash_sem == OSAL_NULL) {
472 return OSAL_FAILURE;
473 }
474 if (osal_sem_binary_sem_init(g_flash_sem, PM_FLASH_SEM_INIT_CNT) != OSAL_SUCCESS) {
475 osal_kfree(g_flash_sem);
476 g_flash_sem = NULL;
477 return OSAL_FAILURE;
478 }
479 }
480 return osal_sem_down(g_flash_sem);
481 }
482
pm_port_flash_sem_up(void)483 void pm_port_flash_sem_up(void)
484 {
485 if (g_flash_sem == NULL) {
486 return;
487 }
488 osal_sem_up(g_flash_sem);
489 }
490
491 #define PM_DMA_SEM_INIT_CNT 1
492 osal_semaphore *g_dma_sem = NULL;
pm_port_dma_sem_down(void)493 int pm_port_dma_sem_down(void)
494 {
495 if (g_dma_sem == NULL) {
496 g_dma_sem = (osal_semaphore *)osal_kmalloc(sizeof(osal_semaphore), 0);
497 if (g_dma_sem == OSAL_NULL) {
498 return OSAL_FAILURE;
499 }
500 if (osal_sem_binary_sem_init(g_dma_sem, PM_DMA_SEM_INIT_CNT) != OSAL_SUCCESS) {
501 osal_kfree(g_dma_sem);
502 g_dma_sem = NULL;
503 return OSAL_FAILURE;
504 }
505 }
506 return osal_sem_down(g_dma_sem);
507 }
508
pm_port_dma_sem_up(void)509 void pm_port_dma_sem_up(void)
510 {
511 if (g_dma_sem == NULL) {
512 return;
513 }
514 osal_sem_up(g_dma_sem);
515 }
516
pm_port_pm_hook_cb_register(uint32_t hook,pm_hook_cb_t cb)517 void pm_port_pm_hook_cb_register(uint32_t hook, pm_hook_cb_t cb)
518 {
519 if (hook >= PM_HOOK_MAX_NUM) {
520 return;
521 }
522 g_pm_hook_cb_list[hook] = cb;
523 }
524
525
pm_port_enter_lowpower_prepare_cb_default(void)526 void pm_port_enter_lowpower_prepare_cb_default(void)
527 {
528 #if !defined(TEST_SUITE)
529 // 业务退出
530 #ifndef CONFIG_PM_SUPPORT_SRV_DECOUPLING
531 uapi_radar_set_status(0);
532 wifi_deinit();
533 bt_thread_close_btc();
534 #endif
535 // 看门狗恢复
536 g_pm_wdt_timeout = hal_watchdog_get_funcs()->get_attr();
537 g_pm_wdt_mode = (hal_watchdog_wdt_cr_get_wdt_mode() == 0) ? WDT_MODE_RESET : WDT_MODE_INTERRUPT;
538 // testsuit版本未启动看门狗
539 uapi_watchdog_disable();
540
541 uapi_watchdog_deinit();
542 #endif
543 // 外设驱动去初始化
544 uapi_drv_cipher_env_suspend();
545 uapi_tsensor_deinit();
546 uapi_gpio_deinit();
547 uapi_pin_deinit();
548 uapi_efuse_deinit();
549
550 #ifndef CONFIG_PM_SUPPORT_SRV_DECOUPLING
551 pm_port_flash_sem_down();
552 #endif
553 // UART休眠, 并记录时钟
554 uapi_uart_suspend(0);
555 g_pm_uart_clock_record[UART_BUS_0] = uart_port_get_clock_value(UART_BUS_0);
556 g_pm_uart_clock_record[UART_BUS_1] = uart_port_get_clock_value(UART_BUS_1);
557 g_pm_uart_clock_record[UART_BUS_2] = uart_port_get_clock_value(UART_BUS_2);
558
559 // dma休眠
560 uapi_dma_suspend(0);
561 }
562
563 #define UART2_RXD_SEL 0x4400d01c
564 #define UART_2_MODE 2
565 #define UART1_RXD_SEL 0x4400d040
566 #define UART_1_MODE 1
567 #define UART0_RXD_SEL 0x4400d048
568 #define UART_0_MODE 1
pm_port_enter_lowpower_finish_cb_default(void)569 void pm_port_enter_lowpower_finish_cb_default(void)
570 {
571 uint32_t index;
572
573 // dma恢复
574 uapi_dma_resume(0);
575
576 // UART重设时钟并恢复
577 if (get_tcxo_freq() == CLK24M_TCXO) {
578 uart_port_set_clock_value(UART_BUS_0, TCXO_CLOCK_24M);
579 uart_port_set_clock_value(UART_BUS_1, TCXO_CLOCK_24M);
580 uart_port_set_clock_value(UART_BUS_2, TCXO_CLOCK_24M);
581 } else {
582 uart_port_set_clock_value(UART_BUS_0, TCXO_CLOCK_40M);
583 uart_port_set_clock_value(UART_BUS_1, TCXO_CLOCK_40M);
584 uart_port_set_clock_value(UART_BUS_2, TCXO_CLOCK_40M);
585 }
586 uapi_uart_resume(0);
587
588 // UART0/2 关闭中断
589 for (index = UART_BUS_0; index < UART_BUS_MAX_NUMBER; index++) {
590 if (index == WKUP_UART) {
591 continue;
592 }
593 osal_irq_disable(UART_0_IRQN + index - UART_BUS_0);
594 if (index == UART_BUS_2) {
595 writel(UART2_RXD_SEL, 0x0);
596 } else if (index == UART_BUS_1) {
597 writel(UART1_RXD_SEL, 0x0);
598 } else if (index == UART_BUS_0) {
599 writel(UART0_RXD_SEL, 0x0);
600 }
601 }
602 }
603
pm_port_exit_lowpower_prepare_cb_default(void)604 void pm_port_exit_lowpower_prepare_cb_default(void)
605 {
606 uint32_t index;
607
608 for (index = UART_BUS_0; index < UART_BUS_MAX_NUMBER; index++) {
609 if (index == WKUP_UART) {
610 continue;
611 }
612 if (index == UART_BUS_2) {
613 writel(UART2_RXD_SEL, UART_2_MODE);
614 } else if (index == UART_BUS_1) {
615 writel(UART1_RXD_SEL, UART_1_MODE);
616 } else if (index == UART_BUS_0) {
617 writel(UART0_RXD_SEL, UART_0_MODE);
618 }
619 osal_irq_enable(UART_0_IRQN + index - UART_BUS_0);
620 }
621
622 // UART休眠
623 uapi_uart_suspend(0);
624
625 // dma休眠
626 uapi_dma_suspend(0);
627 }
628
pm_port_exit_lowpower_finish_cb_default(void)629 void pm_port_exit_lowpower_finish_cb_default(void)
630 {
631 // dma恢复
632 uapi_dma_resume(0);
633
634 // UART重设时钟并恢复
635 uart_port_set_clock_value(UART_BUS_0, g_pm_uart_clock_record[UART_BUS_0]);
636 uart_port_set_clock_value(UART_BUS_1, g_pm_uart_clock_record[UART_BUS_1]);
637 uart_port_set_clock_value(UART_BUS_2, g_pm_uart_clock_record[UART_BUS_2]);
638 uapi_uart_resume(0);
639
640 // 外设驱动恢复
641 // flash
642 #ifndef CONFIG_PM_SUPPORT_SRV_DECOUPLING
643 pm_port_flash_sem_up();
644 #endif
645 // pinctrl & gpio
646 uapi_pin_init();
647 uapi_gpio_init();
648
649 // efuse
650 check_efuse_boot_done();
651 set_efuse_period();
652 set_efuse_clock_period();
653 uapi_efuse_init();
654
655 // tsensor
656 uapi_tsensor_init();
657 // 默认采样周期为 0xFFFF 个32K时钟
658 uapi_tsensor_start_inquire_mode(TSENSOR_SAMP_MODE_AVERAGE_CYCLE, 0xFFFF);
659
660 // 安全驱动恢复
661 uapi_drv_cipher_env_resume();
662
663 #if !defined(TEST_SUITE)
664 // watchdog恢复
665 uapi_watchdog_init(WDT_TIMEOUT_S);
666 hal_watchdog_get_funcs()->set_attr(g_pm_wdt_timeout);
667 uapi_watchdog_enable(g_pm_wdt_mode);
668 // 业务恢复
669 // 设置wifi校准标志为false
670 cali_set_cali_done_flag(OSAL_FALSE);
671 #ifndef CONFIG_PM_SUPPORT_SRV_DECOUPLING
672 wifi_init();
673 bt_thread_open_btc();
674 #endif
675 #endif
676 }
677
cmu_is_fnpll_locked(void)678 static bool cmu_is_fnpll_locked(void)
679 {
680 uint32_t i;
681
682 for (i = 0; i < FNPLL_LOCK_QUERY_TIMES; i++) {
683 // 查询 CMU_FNPLL_LOCK_GRM (bit 12) 为 0x1
684 if (uapi_reg_getbits(REG_EXCEP_RO_RG, 12, 1) == 0x1) {
685 return true;
686 }
687 }
688
689 return false;
690 }
691
check_cmu_lock_status(void)692 static uint32_t check_cmu_lock_status(void)
693 {
694 uint32_t retry_times;
695
696 for (retry_times = 0; retry_times < FNPLL_LOCK_RETRY_TIMES; retry_times++) {
697 // enable pd
698 uapi_reg_setbits(REG_CMU_FNPLL_SIG, 15, 1, 0x0); // 0x0 -> 0x4000342C bit 15
699 uapi_tcxo_delay_ms(FNPLL_LOCK_QUERY_DELAY_MS);
700 if (cmu_is_fnpll_locked()) {
701 return PLL_LOCKED;
702 }
703 // disable pd
704 uapi_reg_setbits(REG_CMU_FNPLL_SIG, 15, 1, 0x1); // 0x1 -> 0x4000342C bit 15
705 uapi_tcxo_delay_us(FNPLL_LOCK_RETRY_DELAY_US);
706 }
707
708 return PLL_UNLOCKED;
709 }
710
pm_port_wfi_process(void)711 static void pm_port_wfi_process(void)
712 {
713 LOS_TaskLock();
714
715 // timer0-liteOS时钟 屏蔽中断
716 uapi_reg_setbit(0x44002110, 3); // 0x1 -> 0x44002110 bit 3
717 osal_irq_clear(TIMER_0_IRQN);
718 dsb();
719 wfi();
720 isb();
721 nop();
722 nop();
723 nop();
724 nop();
725
726 // timer0-liteOS时钟 恢复中断
727 uapi_reg_clrbit(0x44002110, 3); // 0x0 -> 0x44002110 bit 3
728
729 LOS_TaskUnlock();
730 }
731
pm_port_enter_lowpower(void)732 void pm_port_enter_lowpower(void)
733 {
734 uint32_t irq_status, index, reg_addr, reg_val;
735
736 PRINT("Enter low-power start.\r\n");
737 uapi_tcxo_delay_ms(UART_PRINT_DELAY_MS);
738 #ifdef CONFIG_PM_SUPPORT_SRV_DECOUPLING
739 irq_status = osal_irq_lock();
740 g_pm_srv_ctrl.ctrl_protect = PM_CTRL_SUSPEND;
741 if (g_pm_srv_ctrl.ctrl_mode == PM_CTRL_SUSPEND) {
742 PRINT("Already in low-power state, enter process return.\r\n");
743 pm_port_wfi_process();
744 osal_irq_restore(irq_status);
745 return;
746 }
747 if (g_pm_srv_ctrl.srv_mode[PM_SRV_PLAT] == PM_MODE_RESUME) {
748 osal_irq_restore(irq_status);
749 PRINT("pm service not suspend.\r\n");
750 pm_print_srv_stats();
751 return;
752 }
753 osal_irq_restore(irq_status);
754 pm_port_flash_sem_down();
755 pm_port_dma_sem_down();
756 irq_status = osal_irq_lock();
757 /* 如果等待期间客户要求退出低功耗,则平台不进低功耗 */
758 if (g_pm_srv_ctrl.ctrl_protect != PM_CTRL_SUSPEND) {
759 osal_irq_restore(irq_status);
760 pm_port_flash_sem_up();
761 pm_port_dma_sem_up();
762 PRINT("Return before entering low-power.\r\n");
763 return;
764 }
765 g_pm_srv_ctrl.ctrl_mode = PM_CTRL_SUSPEND;
766 #else
767 /* 1.低功耗状态判断 */
768 irq_status = osal_irq_lock();
769 if (g_pm_is_in_process) {
770 osal_irq_restore(irq_status);
771 PRINT("Low-power processing, enter process return.\r\n");
772 return;
773 }
774 if (g_pm_is_in_lowpower) {
775 osal_irq_restore(irq_status);
776 PRINT("Already in low-power state, enter process return.\r\n");
777 pm_port_wfi_process();
778 return;
779 }
780 g_pm_is_in_process = true;
781 osal_irq_restore(irq_status);
782 #endif
783
784 /* 2.调用 enter_lowpower_prepare 回调 */
785 if (g_pm_hook_cb_list[PM_HOOK_ENTER_LOWPOWER_PREPARE] != NULL) {
786 g_pm_hook_cb_list[PM_HOOK_ENTER_LOWPOWER_PREPARE]();
787 }
788
789 #ifndef CONFIG_PM_SUPPORT_SRV_DECOUPLING
790 irq_status = osal_irq_lock();
791 #endif
792 /* 3.WDT关闭 */
793 uapi_reg_clrbit(REG_AON_CRG_CKEN_CTL, 4); // 0x0 -> 0x40002100 bit 4
794 uapi_reg_clrbit(REG_AON_SOFT_RST_CTL, 1); // 0x0 -> 0x40002110 bit 1
795
796 /* 4.CLDO 各模块 复位并关闭时钟 */
797 // BIT[30/29/28/27 /24/23/22/21/20/19/18/17 /15/14/13/12/11/10/9/8/7/6/5/4/3]配置成0x0
798 uapi_reg_read32(REG_CLDO_CRG_RST_SOFT_CFG0, reg_val);
799 g_pm_crg_record[PM_CRG_RST_CTL0] = reg_val;
800 uapi_reg_setbits(REG_CLDO_CRG_RST_SOFT_CFG0, 3, 13, 0x0); // 0x0 -> 0x44001138 bit 15:3 (13 bits)
801 uapi_reg_setbits(REG_CLDO_CRG_RST_SOFT_CFG0, 17, 8, 0x0); // 0x0 -> 0x44001138 bit 24:17 (8 bits)
802 uapi_reg_setbits(REG_CLDO_CRG_RST_SOFT_CFG0, 27, 2, 0x0); // 0x0 -> 0x44001138 bit 28:27 (2 bits)
803 uapi_reg_setbits(REG_CLDO_CRG_RST_SOFT_CFG0, 30, 1, 0x0); // 0x0 -> 0x44001138 bit 30
804
805 // BIT[7, 5, 0]配置成0x0
806 uapi_reg_read32(REG_CLDO_CRG_RST_SOFT_CFG1, reg_val);
807 g_pm_crg_record[PM_CRG_RST_CTL1] = reg_val;
808 uapi_reg_setbits(REG_CLDO_CRG_RST_SOFT_CFG1, 0, 1, 0x0); // 0x0 -> 0x4400113C bit 0
809 uapi_reg_setbits(REG_CLDO_CRG_RST_SOFT_CFG1, 5, 1, 0x0); // 0x0 -> 0x4400113C bit 5
810 uapi_reg_setbits(REG_CLDO_CRG_RST_SOFT_CFG1, 7, 1, 0x0); // 0x0 -> 0x4400113C bit 7
811
812 // [27/26/25/24/23/22/21/20/19/18 /16/15/14/13/12/11/10/9/8/7/6/5/4/3/2] 配置成0x0
813 uapi_reg_read32(REG_CLDO_SUB_CRG_CKEN_CTL0, reg_val);
814 g_pm_crg_record[PM_CRG_CKEN_CTL0] = reg_val;
815 uapi_reg_setbits(REG_CLDO_SUB_CRG_CKEN_CTL0, 18, 10, 0x0); // 0x0 -> 0x44001100 bit 27:18 (10 bits)
816 uapi_reg_setbits(REG_CLDO_SUB_CRG_CKEN_CTL0, 2, 15, 0x0); // 0x0 -> 0x44001100 bit 16:2 (15 bits)
817
818 // BIT[28/27/26/25/24/23/22 /17/16 /7/6 /4/3/2/1/0] 配置成0x0
819 uapi_reg_read32(REG_CLDO_SUB_CRG_CKEN_CTL1, reg_val);
820 g_pm_crg_record[PM_CRG_CKEN_CTL1] = reg_val;
821 uapi_reg_setbits(REG_CLDO_SUB_CRG_CKEN_CTL1, 0, 5, 0x0); // 0x0 -> 0x44001104 bit 4:0 (5 bits)
822 uapi_reg_setbits(REG_CLDO_SUB_CRG_CKEN_CTL1, 6, 2, 0x0); // 0x0 -> 0x44001104 bit 7:6 (2 bits)
823 uapi_reg_setbits(REG_CLDO_SUB_CRG_CKEN_CTL1, 16, 2, 0x0); // 0x0 -> 0x44001104 bit 17:16 (2 bits)
824 uapi_reg_setbits(REG_CLDO_SUB_CRG_CKEN_CTL1, 22, 7, 0x0); // 0x0 -> 0x44001104 bit 28:22 (7 bits)
825
826 /* 6.Flash/UART/总线时钟切换到TCXO */
827 uapi_reg_clrbit(REG_CLDO_CRG_CLK_SEL, 18); // 0x0 -> 0x44001134 bit 18
828 uapi_reg_clrbit(REG_CLDO_CRG_CLK_SEL, 1); // 0x0 -> 0x44001134 bit 1
829 uapi_reg_clrbit(REG_CLDO_CRG_CLK_SEL, 2); // 0x0 -> 0x44001134 bit 2
830 uapi_reg_clrbit(REG_CLDO_CRG_CLK_SEL, 3); // 0x0 -> 0x44001134 bit 2
831
832 // wifi phy 时钟切换
833 uapi_reg_clrbit(REG_CLDO_CRG_CLK_SEL, 19); // 0x0 -> 0x44001134 bit 19
834 uapi_tcxo_delay_us(PMU_PROCESS_DELAY_US);
835
836 if (get_tcxo_freq() == CLK24M_TCXO) {
837 // 总线时钟降频, 24M -> 4M
838 uapi_reg_clrbit(REG_CLDO_CRG_DIV_CTL0, 8); // 0x0 -> 0x44001108 bit 8
839 uapi_reg_setbits(REG_CLDO_CRG_DIV_CTL0, 4, 4, 0x6); // 0x6 -> 0x44001108 bit 7:4 (4 bits)
840 uapi_reg_setbit(REG_CLDO_CRG_DIV_CTL0, 8); // 0x0 -> 0x44001108 bit 8
841 } else {
842 // 总线时钟降频, 40M -> 4M
843 uapi_reg_clrbit(REG_CLDO_CRG_DIV_CTL0, 8); // 0x0 -> 0x44001108 bit 8
844 uapi_reg_setbits(REG_CLDO_CRG_DIV_CTL0, 4, 4, 0xA); // 0xA -> 0x44001108 bit 7:4 (4 bits)
845 uapi_reg_setbit(REG_CLDO_CRG_DIV_CTL0, 8); // 0x0 -> 0x44001108 bit 8
846 }
847 uapi_reg_clrbit(REG_CLDO_CRG_CLK_SEL, 17); // 0x0 -> 0x44001134 bit 17
848
849 /* 7.FNPLL时钟关断 */
850 uapi_reg_setbit(REG_CMU_FNPLL_SIG, 14); // 0x1 -> 0x4000342C bit 14
851 uapi_reg_setbit(REG_CMU_FNPLL_SIG, 15); // 0x1 -> 0x4000342C bit 15
852
853 /* 8.FNPLL电源关闭 */
854 uapi_reg_setbits(REG_PMU_PHY_LDO, 13, 3, 0x4); // 0x4 -> 0x4000316C bit 15:13 (3 bits)
855 uapi_reg_setbits(REG_PMU_CMULDO1_0P9, 13, 3, 0x4); // 0x4 -> 0x4000312C bit 15:13 (3 bits)
856 uapi_tcxo_delay_us(PMU_PROCESS_DELAY_US);
857
858 /* 9.备份并复位IOCFG配置(除UART和SFC), 降低VDDIO功耗 */
859 for (index = 0; index < IOCFG_RECORD_NUM; index++) {
860 // SEL配置
861 reg_addr = REG_GPIO_SEL_START_ADDR + (REG_ADDR_INTERVAL * index);
862 uapi_reg_read32(reg_addr, reg_val);
863 g_pm_iocfg_sel_record[index] = reg_val;
864 uapi_reg_write32(reg_addr, VAL_GPIO_SEL_DEFAULT);
865
866 // PAD配置
867 reg_addr = REG_GPIO_PAD_START_ADDR + (REG_ADDR_INTERVAL * index);
868 uapi_reg_read32(reg_addr, reg_val);
869 g_pm_iocfg_pad_record[index] = reg_val;
870 uapi_reg_write32(reg_addr, VAL_GPIO_PAD_DEFAULT);
871 }
872
873 /* 10.调用 enter_lowpower_finish 回调 */
874 if (g_pm_hook_cb_list[PM_HOOK_ENTER_LOWPOWER_FINISH] != NULL) {
875 g_pm_hook_cb_list[PM_HOOK_ENTER_LOWPOWER_FINISH]();
876 }
877
878 #ifndef CONFIG_PM_SUPPORT_SRV_DECOUPLING
879 /* 11.低功耗状态刷新 */
880 g_pm_is_in_process = false;
881 g_pm_is_in_lowpower = true;
882 osal_irq_restore(irq_status);
883 #endif
884 PRINT("Enter low-power succ!\r\n");
885
886 uapi_tcxo_delay_ms(PM_ENTER_LOWPOWER_WFI_DELAY_MS);
887
888 pm_port_wfi_process();
889 #ifdef CONFIG_PM_SUPPORT_SRV_DECOUPLING
890 osal_irq_restore(irq_status);
891 #endif
892 pm_port_dma_sem_up();
893 }
894
pm_port_exit_lowpower(void)895 void pm_port_exit_lowpower(void)
896 {
897 uint32_t irq_status, reg_addr, index;
898
899 PRINT("Exit low-power start.\r\n");
900 pm_port_dma_sem_down();
901 /* 1.低功耗状态判断 */
902 irq_status = osal_irq_lock();
903 #ifdef CONFIG_PM_SUPPORT_SRV_DECOUPLING
904 if (g_pm_srv_ctrl.ctrl_mode != PM_CTRL_SUSPEND) {
905 pm_port_dma_sem_up();
906 osal_irq_restore(irq_status);
907 PRINT("Not in low-power state, exit process return.\r\n");
908 return;
909 }
910 g_pm_srv_ctrl.ctrl_mode = PM_CTRL_RESUME;
911 g_pm_srv_ctrl.ctrl_protect = PM_CTRL_RESUME;
912 #else
913 if (g_pm_is_in_process) {
914 osal_irq_restore(irq_status);
915 PRINT("Low-power processing, exit process return.\r\n");
916 return;
917 }
918 if (!g_pm_is_in_lowpower) {
919 osal_irq_restore(irq_status);
920 PRINT("Not in low-power state, exit process return.\r\n");
921 return;
922 }
923 g_pm_is_in_process = true;
924 #endif
925 /* 2.调用 exit_lowpower_prepare 回调 */
926 if (g_pm_hook_cb_list[PM_HOOK_EXIT_LOWPOWER_PREPARE] != NULL) {
927 g_pm_hook_cb_list[PM_HOOK_EXIT_LOWPOWER_PREPARE]();
928 }
929
930 /* 3.恢复IOCFG配置 */
931 for (index = 0; index < IOCFG_RECORD_NUM; index++) {
932 // SEL配置
933 reg_addr = REG_GPIO_SEL_START_ADDR + (REG_ADDR_INTERVAL * index);
934 uapi_reg_write32(reg_addr, g_pm_iocfg_sel_record[index]);
935
936 // PAD配置
937 reg_addr = REG_GPIO_PAD_START_ADDR + (REG_ADDR_INTERVAL * index);
938 uapi_reg_write32(reg_addr, g_pm_iocfg_pad_record[index]);
939 }
940
941 /* 4.FNPLL 电源恢复 */
942 // 打开PMU_CMU_LDO电源
943 uapi_reg_setbits(REG_PMU_CMULDO1_0P9, 15, 1, 0x1); // 0x4 -> 0x4000312C bit 15
944 uapi_reg_setbits(REG_PMU_CMULDO1_0P9, 14, 1, 0x1); // 0x4 -> 0x4000312C bit 14
945 uapi_tcxo_delay_us(PMU_RF_OPEN_DELAY_US);
946 uapi_reg_setbits(REG_PMU_CMULDO1_0P9, 13, 1, 0x1); // 0x4 -> 0x4000312C bit 13
947 uapi_tcxo_delay_us(PMU_PROCESS_DELAY_US);
948
949 // 打开PMU_PHY_LDO电源
950 uapi_reg_setbits(REG_PMU_PHY_LDO, 15, 1, 0x1); // 0x4 -> 0x4000316C bit 15
951 uapi_reg_setbits(REG_PMU_PHY_LDO, 14, 1, 0x1); // 0x4 -> 0x4000316C bit 14
952 uapi_tcxo_delay_us(PMU_RF_OPEN_DELAY_US);
953 uapi_reg_setbits(REG_PMU_PHY_LDO, 13, 1, 0x1); // 0x4 -> 0x4000316C bit 13
954 uapi_tcxo_delay_us(PMU_PROCESS_DELAY_US);
955
956 /* 5.时钟初始化与恢复 */
957 // 晶振时钟初始化
958 if (get_tcxo_freq() == CLK24M_TCXO) {
959 // 24M晶振
960 uapi_reg_setbits(REG_CMU_FNPLL_SIG, 6, 6, 0x1); // 0x1 -> 0x4000342C bit 6
961 uapi_reg_setbits(REG_CMU_FBDIV, 0, 12, 0x78); // 0x78 -> 0x40003430 bit 12:0 (13 bits)
962 uapi_reg_setbits(REG_CMU_FRAC, 0, 24, 0x0); // 0x0 -> 0x40003434 bit 24:0 (25 bits)
963 uapi_reg_setbits(REG_CMU_FNPLL_SIG, 3, 3, 0x2); // 0x2 -> 0x4000342C bit 5:3 (3 bits)
964 uapi_reg_setbits(REG_CMU_FNPLL_SIG, 0, 3, 0x0); // 0x0 -> 0x4000342C bit 2:0 (3 bits)
965 uapi_reg_setbits(REG_CMU_FNPLL_SIG, 17, 1, 0x1); // 0x1 -> 0x4000342C bit 17
966 uapi_reg_write32(REG_FNPLL_CFG0, 0xE0000004); // 0xE0000004 -> 0x4000340C
967 uapi_reg_write32(REG_FNPLL_CFG1, 0x00B40000); // 0x00B40000 -> 0x40003410
968 uapi_reg_write32(REG_FNPLL_CFG2, 0x20111FA8); // 0x20111FA8 -> 0x40003414
969 uapi_reg_write32(REG_FNPLL_CFG3, 0x2404FF20); // 0x2404FF20 -> 0x40003418
970 uapi_reg_write32(REG_FNPLL_CFG4, 0x0802013F); // 0x0802013F -> 0x4000341C
971 uapi_reg_write32(REG_FNPLL_CFG5, 0x00004046); // 0x00004046 -> 0x40003420
972 } else {
973 // 40M晶振
974 uapi_reg_setbits(REG_CMU_FNPLL_SIG, 6, 6, 0x1); // 0x1 -> 0x4000342C bit 6
975 uapi_reg_setbits(REG_CMU_FBDIV, 0, 12, 0x48); // 0x48 -> 0x40003430 bit 12:0 (13 bits)
976 uapi_reg_setbits(REG_CMU_FRAC, 0, 24, 0x0); // 0x0 -> 0x40003434 bit 24:0 (25 bits)
977 uapi_reg_setbits(REG_CMU_FNPLL_SIG, 3, 3, 0x2); // 0x2 -> 0x4000342C bit 5:3 (3 bits)
978 uapi_reg_setbits(REG_CMU_FNPLL_SIG, 0, 3, 0x0); // 0x0 -> 0x4000342C bit 2:0 (3 bits)
979 uapi_reg_setbits(REG_CMU_FNPLL_SIG, 17, 1, 0x1); // 0x1 -> 0x4000342C bit 17
980 uapi_reg_write32(REG_FNPLL_CFG0, 0x84000004); // 0x84000004 -> 0x4000340C
981 uapi_reg_write32(REG_FNPLL_CFG1, 0x00B40000); // 0x00B40000 -> 0x40003410
982 uapi_reg_write32(REG_FNPLL_CFG2, 0x20111FA8); // 0x20111FA8 -> 0x40003414
983 uapi_reg_write32(REG_FNPLL_CFG3, 0x2404FF20); // 0x2404FF20 -> 0x40003418
984 uapi_reg_write32(REG_FNPLL_CFG4, 0x0802013F); // 0x0802013F -> 0x4000341C
985 uapi_reg_write32(REG_FNPLL_CFG5, 0x00004046); // 0x00004046 -> 0x40003420
986 }
987 uapi_tcxo_delay_us(1);
988
989 // 尝试PLL锁定, 若失败则恢复uart进行打印, 然后复位
990 if (check_cmu_lock_status() != PLL_LOCKED) {
991 // PLL时钟初始化失败, 恢复串口
992 if (get_tcxo_freq() == CLK24M_TCXO) {
993 uart_port_set_clock_value(UART_BUS_0, TCXO_CLOCK_24M);
994 uart_port_set_clock_value(UART_BUS_1, TCXO_CLOCK_24M);
995 uart_port_set_clock_value(UART_BUS_2, TCXO_CLOCK_24M);
996 } else {
997 uart_port_set_clock_value(UART_BUS_0, TCXO_CLOCK_40M);
998 uart_port_set_clock_value(UART_BUS_1, TCXO_CLOCK_40M);
999 uart_port_set_clock_value(UART_BUS_2, TCXO_CLOCK_40M);
1000 }
1001 uapi_uart_resume(0);
1002
1003 // PLL初始化失败, 打印 10 次后复位
1004 for (index = 10; index > 0; index--) {
1005 PRINT("PLL init fail, reboot in %us!\r\n", index);
1006 uapi_tcxo_delay_ms(1000); // delay 1000ms
1007 }
1008 reboot_port_reboot_chip();
1009 }
1010
1011 uapi_reg_setbits(REG_CMU_FNPLL_SIG, 14, 1, 0x0); // 0x0 -> 0x4000342C bit 14
1012 uapi_reg_setbits(REG_CMU_CLK_480M_WDBB, 0, 1, 0x1); // 0x1 -> 0x4000344C bit 0
1013 uapi_tcxo_delay_us(1);
1014 uapi_reg_setbits(REG_CMU_CLK_480M_WDBB, 1, 1, 0x1); // 0x1 -> 0x4000344C bit 1
1015 uapi_tcxo_delay_us(1);
1016 uapi_reg_setbits(REG_CLDO_CRG_CLK_SEL, 17, 1, 0x1); // 0x1 -> 0x44001134 bit 17
1017 uapi_reg_setbits(REG_CLDO_CRG_DIV_CTL7, 24, 1, 0x0); // 0x0 -> 0x44001124 bit 24
1018 uapi_reg_setbits(REG_CLDO_CRG_DIV_CTL7, 22, 2, 0x2); // 0x2 -> 0x44001124 bit 23:22 (2 bits)
1019 uapi_reg_setbits(REG_CLDO_CRG_DIV_CTL7, 24, 1, 0x1); // 0x1 -> 0x44001124 bit 24
1020
1021 uapi_reg_clrbit(REG_CLDO_CRG_DIV_CTL0, 8); // 0x0 -> 0x44001108 bit 8
1022 uapi_reg_setbits(REG_CLDO_CRG_DIV_CTL0, 4, 4, 0x1); // 0x1 -> 0x44001108 bit 7:4 (4 bits)
1023 uapi_reg_setbit(REG_CLDO_CRG_DIV_CTL0, 8); // 0x0 -> 0x44001108 bit 8
1024
1025 // wifi phy 时钟切换
1026 uapi_reg_setbit(REG_CLDO_CRG_CLK_SEL, 19); // 0x0 -> 0x44001134 bit 19
1027 uapi_tcxo_delay_us(PMU_PROCESS_DELAY_US);
1028
1029 /* 6.Flash/UART时钟切换 */
1030 uapi_reg_setbit(REG_CLDO_CRG_CLK_SEL, 1); // 0x1 -> 0x44001134 bit 1
1031 uapi_reg_setbit(REG_CLDO_CRG_CLK_SEL, 2); // 0x1 -> 0x44001134 bit 2
1032 uapi_reg_setbit(REG_CLDO_CRG_CLK_SEL, 3); // 0x1 -> 0x44001134 bit 2
1033 uapi_reg_setbit(REG_CLDO_CRG_CLK_SEL, 18); // 0x1 -> 0x44001134 bit 18
1034
1035 /* 8.CLDO 各设备恢复时钟并解复位 */
1036 uapi_reg_write32(REG_CLDO_SUB_CRG_CKEN_CTL1, g_pm_crg_record[PM_CRG_CKEN_CTL1]);
1037 uapi_reg_write32(REG_CLDO_SUB_CRG_CKEN_CTL0, g_pm_crg_record[PM_CRG_CKEN_CTL0]);
1038 uapi_reg_write32(REG_CLDO_CRG_RST_SOFT_CFG1, g_pm_crg_record[PM_CRG_RST_CTL1]);
1039 uapi_reg_write32(REG_CLDO_CRG_RST_SOFT_CFG0, g_pm_crg_record[PM_CRG_RST_CTL0]);
1040
1041 /* 9.WDT门控开启, 并停止使能 */
1042 uapi_reg_setbit(REG_AON_SOFT_RST_CTL, 1); // 0x1 -> 0x40002110 bit 1
1043 uapi_reg_setbit(REG_AON_CRG_CKEN_CTL, 4); // 0x1 -> 0x40002100 bit 4
1044 uapi_reg_clrbit(REG_WDT_CR, 0); // 0x0 -> 0x40006010 bit 0
1045
1046 #ifndef CONFIG_PM_SUPPORT_SRV_DECOUPLING
1047 osal_irq_restore(irq_status);
1048 #endif
1049 /* 10.调用 exit_lowpower_finish 回调 */
1050 if (g_pm_hook_cb_list[PM_HOOK_EXIT_LOWPOWER_FINISH] != NULL) {
1051 g_pm_hook_cb_list[PM_HOOK_EXIT_LOWPOWER_FINISH]();
1052 }
1053
1054 /* 11.低功耗状态刷新 */
1055 #ifndef CONFIG_PM_SUPPORT_SRV_DECOUPLING
1056 irq_status = osal_irq_lock();
1057 g_pm_is_in_process = false;
1058 g_pm_is_in_lowpower = false;
1059 #else
1060 osal_irq_restore(irq_status);
1061 pm_port_flash_sem_up();
1062 #endif
1063 pm_port_dma_sem_up();
1064 PRINT("Exit low-power succ!\r\n");
1065 }
1066
pm_porting_wait_exit_lowpower(void)1067 void pm_porting_wait_exit_lowpower(void)
1068 {
1069 PRINT("[pm_port][0x%x][%ld]Wait start.\r\n", __builtin_return_address(0), osal_get_current_tid());
1070 #ifdef CONFIG_PM_SUPPORT_SRV_DECOUPLING
1071 while (g_pm_srv_ctrl.ctrl_mode == PM_CTRL_SUSPEND) {
1072 #else
1073 while (g_pm_is_in_lowpower) {
1074 #endif
1075 osal_msleep(PM_WAIT_EXIT_LOWPOWER_MS);
1076 }
1077 PRINT("[pm_port][0x%x][%ld]Wait succ!\r\n", __builtin_return_address(0), osal_get_current_tid());
1078 }
1079