blob: b444639f6e44217bf1d8a55458d8907297ae9f06 [file] [log] [blame]
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +08001/*
yang.li24770372022-01-11 15:21:49 +08002 * Copyright (c) 2021-2022 Amlogic, Inc. All rights reserved.
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +08003 *
yang.li24770372022-01-11 15:21:49 +08004 * SPDX-License-Identifier: MIT
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +08005 */
6
7#include <stdio.h>
8#include "FreeRTOS.h" /* Must come first. */
xiaohu.huang2beac512022-05-07 15:10:04 +08009#include "task.h" /* RTOS task related API prototypes. */
10#include "queue.h" /* RTOS queue related API prototypes. */
11#include "timers.h" /* Software timer related API prototypes. */
12#include "semphr.h" /* Semaphore related API prototypes. */
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +080013
14#include <unistd.h>
Xiaohu.Huang60950452022-03-12 22:51:01 +080015#include <string.h>
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +080016
17#include "n200_func.h"
18#include "common.h"
19#include "riscv_encoding.h"
xiaohu.huang2beac512022-05-07 15:10:04 +080020#include "gcc_compiler_attributes.h"
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +080021#include "suspend.h"
22#include "power.h"
23
24#include "hdmi_cec.h"
25#include "vrtc.h"
Xiaohu.Huang60950452022-03-12 22:51:01 +080026#include "rtc.h"
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +080027#include "mailbox-api.h"
qi duand271a902022-11-15 10:44:55 +080028#include "eth.h"
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +080029#include "wakeup.h"
30#include "stick_mem.h"
Xiaohu.Huang60950452022-03-12 22:51:01 +080031#include "pm.h"
Jianyi Shifd8850a2023-10-23 17:46:48 +080032#include "suspend_debug.h"
bangzheng.liu512eda62024-02-26 13:12:07 +080033#include "uart.h"
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +080034
xiaohu.huang2beac512022-05-07 15:10:04 +080035SemaphoreHandle_t xSTRSemaphore;
36QueueHandle_t xSTRQueue;
37SemaphoreHandle_t xSTRFlagSem;
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +080038uint32_t suspend_flag;
Jianyi Shifd8850a2023-10-23 17:46:48 +080039#if BL30_SUSPEND_DEBUG_EN
40uint32_t suspend_debug_flag;
41static TaskHandle_t printTask;
42#endif
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +080043uint32_t power_mode;
44
xiaohu.huang2beac512022-05-07 15:10:04 +080045struct WakeUp_Reason vWakeupReason[] = {
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +080046 [UDEFINED_WAKEUP] = { .name = "undefine" },
47 [CHARGING_WAKEUP] = { .name = "charging" },
48 [REMOTE_WAKEUP] = { .name = "remote" },
49 [RTC_WAKEUP] = { .name = "rtc" },
50 [BT_WAKEUP] = { .name = "bt" },
51 [WIFI_WAKEUP] = { .name = "wifi" },
52 [POWER_KEY_WAKEUP] = { .name = "powerkey" },
53 [AUTO_WAKEUP] = { .name = "auto" },
54 [CEC_WAKEUP] = { .name = "cec" },
55 [REMOTE_CUS_WAKEUP] = { .name = "remote_cus" },
56 [ETH_PMT_WAKEUP] = { .name = "eth" },
57 [CECB_WAKEUP] = { .name = "cecb" },
Zhuo Wang450eab72022-11-09 14:39:32 +080058 [ETH_PHY_GPIO] = { .name = "eth_gpio" },
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +080059 [VAD_WAKEUP] = { .name = "vad" },
60 [HDMI_RX_WAKEUP] = { .name = "hdmirx_plugin" },
61};
62
63void set_suspend_flag(void)
64{
65 taskENTER_CRITICAL();
66 suspend_flag = 1;
qi duand271a902022-11-15 10:44:55 +080067 vETHEnableIrq();
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +080068 taskEXIT_CRITICAL();
69}
xiaohu.huang2beac512022-05-07 15:10:04 +080070
71__weak void vDDR_suspend(uint32_t st_f)
Xiaohu.Huang60950452022-03-12 22:51:01 +080072{
xiaohu.huang2beac512022-05-07 15:10:04 +080073 (void)st_f;
Xiaohu.Huang60950452022-03-12 22:51:01 +080074}
75
xiaohu.huang2beac512022-05-07 15:10:04 +080076__weak void vDDR_resume(uint32_t st_f)
Xiaohu.Huang60950452022-03-12 22:51:01 +080077{
xiaohu.huang2beac512022-05-07 15:10:04 +080078 (void)st_f;
Xiaohu.Huang60950452022-03-12 22:51:01 +080079}
80
xiaohu.huang2beac512022-05-07 15:10:04 +080081__weak void alarm_set(void)
Xiaohu.Huang60950452022-03-12 22:51:01 +080082{
83}
84
xiaohu.huang2beac512022-05-07 15:10:04 +080085__weak void alarm_clr(void)
Xiaohu.Huang60950452022-03-12 22:51:01 +080086{
87}
88
xiaohu.huang2beac512022-05-07 15:10:04 +080089__weak void vRTC_update(void)
Xiaohu.Huang60950452022-03-12 22:51:01 +080090{
91}
92
xiaohu.huang2beac512022-05-07 15:10:04 +080093__weak void vCreat_alarm_timer(void)
Xiaohu.Huang60950452022-03-12 22:51:01 +080094{
95}
96
xiaohu.huang2beac512022-05-07 15:10:04 +080097__weak void store_rtc(void)
Xiaohu.Huang60950452022-03-12 22:51:01 +080098{
99}
100
xiaohu.huang2beac512022-05-07 15:10:04 +0800101__weak void vCLK_suspend(uint32_t st_f)
Xiaohu.Huang60950452022-03-12 22:51:01 +0800102{
xiaohu.huang2beac512022-05-07 15:10:04 +0800103 (void)st_f;
Xiaohu.Huang60950452022-03-12 22:51:01 +0800104}
105
xiaohu.huang2beac512022-05-07 15:10:04 +0800106__weak void vCLK_resume(uint32_t st_f)
Xiaohu.Huang60950452022-03-12 22:51:01 +0800107{
xiaohu.huang2beac512022-05-07 15:10:04 +0800108 (void)st_f;
Xiaohu.Huang60950452022-03-12 22:51:01 +0800109}
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800110
changpeng.jiangfd280412024-03-13 17:19:34 +0800111__weak void check_poweroff_status(void)
112{
113 vTaskDelay(pdMS_TO_TICKS(500));
114}
115
Jianyi Shifd8850a2023-10-23 17:46:48 +0800116#if BL30_SUSPEND_DEBUG_EN
117inline void split_suspend_flag(uint32_t *temp)
118{
119 suspend_debug_flag = (*temp) & SUSPEND_DEBUG_MASK;
120 *temp = (*temp) & ~SUSPEND_DEBUG_MASK;
121}
122
123inline uint32_t get_suspend_flag(void)
124{
125 return suspend_debug_flag;
126}
127
128void vDebugPrintTask(void *pvParameters)
129{
130 /*make compiler happy*/
131 (void) pvParameters;
132
133 for ( ;; ) {
134 printf("vPTask1...\n");
135 vTaskDelay(pdMS_TO_TICKS(TEST_TASK1_DELAY));
136 }
137}
138#endif
139
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800140void system_resume(uint32_t pm)
141{
142 uint32_t shutdown_flag = 0;
143
Jianyi Shifd8850a2023-10-23 17:46:48 +0800144#if BL30_SUSPEND_DEBUG_EN
145 enter_func_print();
146#endif
147
bangzheng.liu36236e62024-04-16 16:15:39 +0800148 if (pm == POWER_MODE_POWER_OFF)
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800149 shutdown_flag = 1;
Xiaohu.Huang60950452022-03-12 22:51:01 +0800150 vCLK_resume(shutdown_flag);
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800151 /*Need clr alarm ASAP*/
152 alarm_clr();
153 str_power_on(shutdown_flag);
Jianyi Shifd8850a2023-10-23 17:46:48 +0800154#if BL30_SUSPEND_DEBUG_EN
155 if (!IS_EN(BL30_SKIP_DDR_SUSPEND))
156#endif
157 vDDR_resume(shutdown_flag);
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800158 str_hw_disable();
159 vRTC_update();
160 wakeup_ap();
161 clear_wakeup_trigger();
162 /*Shutdown*/
Xiaohu.Huang60950452022-03-12 22:51:01 +0800163 if (shutdown_flag) {
164 /* Store RTC time for a5 temporarily*/
165 store_rtc();
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800166 watchdog_reset_system();
Xiaohu.Huang60950452022-03-12 22:51:01 +0800167 }
Jianyi Shifd8850a2023-10-23 17:46:48 +0800168
169#if BL30_SUSPEND_DEBUG_EN
170 stop_debug_task();
171 exit_func_print();
172#endif
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800173}
174
175void system_suspend(uint32_t pm)
176{
177 uint32_t shutdown_flag = 0;
Jianyi Shifd8850a2023-10-23 17:46:48 +0800178#if BL30_SUSPEND_DEBUG_EN
179 split_suspend_flag(&pm);
180 enter_func_print();
181 start_debug_task();
182#endif
bangzheng.liu36236e62024-04-16 16:15:39 +0800183 if (pm == POWER_MODE_POWER_OFF)
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800184 shutdown_flag = 1;
185
186 /*Need set alarm ASAP*/
187 alarm_set();
188 str_hw_init();
189 /*Set flag befor delay. It can be wakeup during delay*/
190 set_suspend_flag();
changpeng.jiangfd280412024-03-13 17:19:34 +0800191 /*Wait for FSM switch to off*/
192 check_poweroff_status();
Jianyi Shifd8850a2023-10-23 17:46:48 +0800193#if BL30_SUSPEND_DEBUG_EN
194 if (!IS_EN(BL30_SKIP_DDR_SUSPEND))
195#endif
196 vDDR_suspend(shutdown_flag);
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800197 str_power_off(shutdown_flag);
Xiaohu.Huang60950452022-03-12 22:51:01 +0800198 vCLK_suspend(shutdown_flag);
Jianyi Shifd8850a2023-10-23 17:46:48 +0800199#if BL30_SUSPEND_DEBUG_EN
200 exit_func_print();
201#endif
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800202}
203
204void set_reason_flag(char exit_reason)
205{
Yao Jie5d17b5c2022-11-24 11:00:17 +0800206 uint32_t val;
207
208 val = REG32(WAKEUP_REASON_STICK_REG) & ~0xff;
209 val |= EXIT_REASON_EXTENSION_FLAG;
210 val |= (exit_reason & 0x7f);
211 REG32(WAKEUP_REASON_STICK_REG) = val;
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800212}
213
214uint32_t get_reason_flag(void)
215{
Yao Jie5d17b5c2022-11-24 11:00:17 +0800216 return REG32(WAKEUP_REASON_STICK_REG) & 0x7f;
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800217}
218
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800219void *xMboxGetWakeupReason(void *msg)
220{
221 *(uint32_t *)msg = get_reason_flag();
222 return NULL;
223}
224
225void *xMboxClrWakeupReason(void *msg)
226{
xiaohu.huang2beac512022-05-07 15:10:04 +0800227 (void)msg;
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800228 return NULL;
229}
230
231void *xMboxGetStickRebootFlag(void *msg)
232{
Yao Jieeb106042023-11-20 10:56:31 +0800233#ifdef CONFIG_STICK_MEM
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800234 *(uint32_t *)msg = get_stick_reboot_flag();
Yao Jieeb106042023-11-20 10:56:31 +0800235#else
236 printf("Don't support stick memory!\r\n");
237#endif
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800238 return NULL;
239}
240
241void STR_Start_Sem_Give_FromISR(void)
242{
243 BaseType_t xHigherPriorityTaskWoken;
xiaohu.huang2beac512022-05-07 15:10:04 +0800244
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800245 xSemaphoreGiveFromISR(xSTRSemaphore, &xHigherPriorityTaskWoken);
246}
247
248void STR_Start_Sem_Give(void)
249{
250 xSemaphoreGive(xSTRSemaphore);
251}
252
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800253void STR_Wakeup_src_Queue_Send_FromISR(uint32_t *src)
254{
255 BaseType_t xHigherPriorityTaskWoken;
256 uint32_t flag = 0;
257 UBaseType_t uxSavedInterruptStatus;
258
259 uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR();
260 if (suspend_flag) {
261 suspend_flag = 0;
262 flag = 1;
263 }
264 taskEXIT_CRITICAL_FROM_ISR(uxSavedInterruptStatus);
265
266 if (flag)
267 xQueueSendFromISR(xSTRQueue, src, &xHigherPriorityTaskWoken);
268}
269
270void STR_Wakeup_src_Queue_Send(uint32_t *src)
271{
272 uint32_t flag = 0;
273
274 taskENTER_CRITICAL();
275 if (suspend_flag) {
276 suspend_flag = 0;
277 flag = 1;
278 }
279 taskEXIT_CRITICAL();
280
281 if (flag)
282 xQueueSend(xSTRQueue, src, portMAX_DELAY);
283}
284
285void *xMboxSuspend_Sem(void *msg)
286{
287 power_mode = *(uint32_t *)msg;
288
bangzheng.liu9f879ed2024-03-25 13:37:43 +0800289#ifdef ACS_DIS_PRINT_FLAG
bangzheng.liu512eda62024-02-26 13:12:07 +0800290 enable_bl30_print(1);
291#endif
292
bangzheng.liu36236e62024-04-16 16:15:39 +0800293 switch (power_mode & POWER_MODE_MASK) {
294 case POWER_MODE_SUSPEND_1:
295 case POWER_MODE_SUSPEND_2:
296 printf("power_mode: SUSPEND\n");
297 break;
298 case POWER_MODE_POWER_OFF:
299 printf("power_mode: POWER OFF\n");
300 break;
301 default:
302 printf("power_mode: UNKNOWN\n");
303 break;
304 }
305
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800306 STR_Start_Sem_Give();
307
308 return NULL;
309}
310
xiaohu.huang2beac512022-05-07 15:10:04 +0800311#define FREEZE_ENTER 0x01
312#define FREEZE_EXIT 0x02
Xiaohu.Huang60950452022-03-12 22:51:01 +0800313
314void *xMboxpm_sem(void *msg);
315void *xMboxpm_sem(void *msg)
316{
317 uint32_t mode = *(uint32_t *)msg;
318
bangzheng.liu9f879ed2024-03-25 13:37:43 +0800319#ifdef ACS_DIS_PRINT_FLAG
bangzheng.liu512eda62024-02-26 13:12:07 +0800320 enable_bl30_print(1);
321#endif
322
binbin.wang093973e2023-06-26 14:00:32 +0800323#ifdef CONFIG_PM
xiaohu.huang2beac512022-05-07 15:10:04 +0800324 if (mode == FREEZE_ENTER)
Xiaohu.Huang60950452022-03-12 22:51:01 +0800325 pm_enter();
xiaohu.huang2beac512022-05-07 15:10:04 +0800326 else if (mode == FREEZE_EXIT)
Xiaohu.Huang60950452022-03-12 22:51:01 +0800327 wakeup_ap_from_kernel();
binbin.wang093973e2023-06-26 14:00:32 +0800328#endif
Xiaohu.Huang60950452022-03-12 22:51:01 +0800329
330 return NULL;
331}
332
xiaohu.huang2beac512022-05-07 15:10:04 +0800333static void vSTRTask(void *pvParameters)
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800334{
335 /*make compiler happy*/
336 uint32_t buffer = UDEFINED_WAKEUP;
337 uint32_t exit_reason = 0;
338
xiaohu.huang2beac512022-05-07 15:10:04 +0800339 (void)pvParameters;
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800340 xSTRQueue = xQueueCreate(STR_QUEUE_LENGTH, STR_QUEUE_ITEM_SIZE);
341 configASSERT(xSTRQueue);
342 xSTRSemaphore = xSemaphoreCreateBinary();
343 configASSERT(xSTRSemaphore);
344
345 while (1) {
346 xSemaphoreTake(xSTRSemaphore, portMAX_DELAY);
347 system_suspend(power_mode);
xiaohu.huang2beac512022-05-07 15:10:04 +0800348 while (xQueueReceive(xSTRQueue, &buffer, portMAX_DELAY)) {
349 switch (buffer) {
350 case REMOTE_WAKEUP:
351 exit_reason = REMOTE_WAKEUP;
352 break;
353 case RTC_WAKEUP:
354 exit_reason = RTC_WAKEUP;
355 break;
356 case BT_WAKEUP:
357 exit_reason = BT_WAKEUP;
358 break;
359 case CEC_WAKEUP:
360 exit_reason = CEC_WAKEUP;
361 break;
362 case CECB_WAKEUP:
363 exit_reason = CECB_WAKEUP;
364 break;
365 case REMOTE_CUS_WAKEUP:
366 exit_reason = REMOTE_CUS_WAKEUP;
367 break;
368 case POWER_KEY_WAKEUP:
369 exit_reason = POWER_KEY_WAKEUP;
370 break;
371 case ETH_PMT_WAKEUP:
372 exit_reason = ETH_PMT_WAKEUP;
373 break;
374 case WIFI_WAKEUP:
375 exit_reason = WIFI_WAKEUP;
376 break;
Zhuo Wang450eab72022-11-09 14:39:32 +0800377 case ETH_PHY_GPIO:
378 exit_reason = ETH_PHY_GPIO;
379 printf("wzh eth gpio\n");
380 break;
xiaohu.huang2beac512022-05-07 15:10:04 +0800381 case VAD_WAKEUP:
382 exit_reason = VAD_WAKEUP;
383 break;
384 case HDMI_RX_WAKEUP:
385 exit_reason = HDMI_RX_WAKEUP;
386 break;
Yu Tue700c712023-04-10 15:28:09 +0800387 case UART_RX_WAKEUP:
388 exit_reason = UART_RX_WAKEUP;
389 break;
xiaohu.huang2beac512022-05-07 15:10:04 +0800390 default:
bangzheng.liu6889f9a2023-11-17 11:20:48 +0800391 printf("unknown exit_reason %d\n", exit_reason);
392 set_suspend_flag();
xiaohu.huang2beac512022-05-07 15:10:04 +0800393 break;
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800394 }
395 if (exit_reason) {
xiaohu.huang2beac512022-05-07 15:10:04 +0800396 printf("exit_reason=%d, %s\n", exit_reason,
397 vWakeupReason[exit_reason].name);
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800398 set_reason_flag((char)exit_reason);
399 exit_reason = 0;
400 system_resume(power_mode);
401 goto loop;
402 }
403 }
xiaohu.huang2beac512022-05-07 15:10:04 +0800404loop:
405 continue;
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800406 }
407}
408
409void create_str_task(void)
410{
411 int ret;
412
xiaohu.huang2beac512022-05-07 15:10:04 +0800413 if (xTaskCreate(vSTRTask, "STR_task", configMINIMAL_STACK_SIZE, NULL, 3, NULL) < 0)
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800414 printf("STR_task create fail!!\n");
415
416 vCreat_alarm_timer();
417
418 ret = xInstallRemoteMessageCallbackFeedBack(AOTEE_CHANNEL, MBX_CMD_SUSPEND,
xiaohu.huang2beac512022-05-07 15:10:04 +0800419 xMboxSuspend_Sem, 0);
Yao Jie5f5884b2024-02-01 17:59:34 +0800420 if (ret)
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800421 printf("mbox cmd 0x%x register fail\n", MBX_CMD_SUSPEND);
422
423 ret = xInstallRemoteMessageCallbackFeedBack(AOREE_CHANNEL, MBX_CMD_GET_WAKEUP_REASON,
xiaohu.huang2beac512022-05-07 15:10:04 +0800424 xMboxGetWakeupReason, 1);
Yao Jie5f5884b2024-02-01 17:59:34 +0800425 if (ret)
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800426 printf("mbox cmd 0x%x register fail\n", MBX_CMD_GET_WAKEUP_REASON);
427
428 ret = xInstallRemoteMessageCallbackFeedBack(AOREE_CHANNEL, MBX_CMD_CLR_WAKEUP_REASON,
xiaohu.huang2beac512022-05-07 15:10:04 +0800429 xMboxClrWakeupReason, 0);
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800430
431 ret = xInstallRemoteMessageCallbackFeedBack(AOREE_CHANNEL, MBX_CMD_GET_STICK_REBOOT_FLAG,
xiaohu.huang2beac512022-05-07 15:10:04 +0800432 xMboxGetStickRebootFlag, 1);
Yao Jie5f5884b2024-02-01 17:59:34 +0800433 if (ret)
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800434 printf("mbox cmd 0x%x register fail\n", MBX_CMD_CLR_WAKEUP_REASON);
Xiaohu.Huang60950452022-03-12 22:51:01 +0800435
xiaohu.huang2beac512022-05-07 15:10:04 +0800436 ret = xInstallRemoteMessageCallbackFeedBack(AOREE_CHANNEL, MBX_CMD_PM_FREEZE, xMboxpm_sem,
437 1);
Yao Jie5f5884b2024-02-01 17:59:34 +0800438 if (ret)
Xiaohu.Huang60950452022-03-12 22:51:01 +0800439 printf("mbox cmd 0x%x register fail\n", MBX_CMD_PM_FREEZE);
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800440}