• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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