blob: d8e7bf24df58945de661bd45cec3f5d1597385bd [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;
Jianyi Shifd8850a2023-10-23 17:46:48 +080041#endif
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +080042uint32_t power_mode;
43
xiaohu.huang2beac512022-05-07 15:10:04 +080044struct WakeUp_Reason vWakeupReason[] = {
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +080045 [UDEFINED_WAKEUP] = { .name = "undefine" },
46 [CHARGING_WAKEUP] = { .name = "charging" },
47 [REMOTE_WAKEUP] = { .name = "remote" },
48 [RTC_WAKEUP] = { .name = "rtc" },
49 [BT_WAKEUP] = { .name = "bt" },
50 [WIFI_WAKEUP] = { .name = "wifi" },
51 [POWER_KEY_WAKEUP] = { .name = "powerkey" },
52 [AUTO_WAKEUP] = { .name = "auto" },
53 [CEC_WAKEUP] = { .name = "cec" },
54 [REMOTE_CUS_WAKEUP] = { .name = "remote_cus" },
55 [ETH_PMT_WAKEUP] = { .name = "eth" },
56 [CECB_WAKEUP] = { .name = "cecb" },
Zhuo Wang450eab72022-11-09 14:39:32 +080057 [ETH_PHY_GPIO] = { .name = "eth_gpio" },
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +080058 [VAD_WAKEUP] = { .name = "vad" },
59 [HDMI_RX_WAKEUP] = { .name = "hdmirx_plugin" },
60};
61
62void set_suspend_flag(void)
63{
64 taskENTER_CRITICAL();
65 suspend_flag = 1;
qi duand271a902022-11-15 10:44:55 +080066 vETHEnableIrq();
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +080067 taskEXIT_CRITICAL();
68}
xiaohu.huang2beac512022-05-07 15:10:04 +080069
70__weak void vDDR_suspend(uint32_t st_f)
Xiaohu.Huang60950452022-03-12 22:51:01 +080071{
xiaohu.huang2beac512022-05-07 15:10:04 +080072 (void)st_f;
Xiaohu.Huang60950452022-03-12 22:51:01 +080073}
74
xiaohu.huang2beac512022-05-07 15:10:04 +080075__weak void vDDR_resume(uint32_t st_f)
Xiaohu.Huang60950452022-03-12 22:51:01 +080076{
xiaohu.huang2beac512022-05-07 15:10:04 +080077 (void)st_f;
Xiaohu.Huang60950452022-03-12 22:51:01 +080078}
79
xiaohu.huang2beac512022-05-07 15:10:04 +080080__weak void alarm_set(void)
Xiaohu.Huang60950452022-03-12 22:51:01 +080081{
82}
83
xiaohu.huang2beac512022-05-07 15:10:04 +080084__weak void alarm_clr(void)
Xiaohu.Huang60950452022-03-12 22:51:01 +080085{
86}
87
xiaohu.huang2beac512022-05-07 15:10:04 +080088__weak void vRTC_update(void)
Xiaohu.Huang60950452022-03-12 22:51:01 +080089{
90}
91
xiaohu.huang2beac512022-05-07 15:10:04 +080092__weak void vCreat_alarm_timer(void)
Xiaohu.Huang60950452022-03-12 22:51:01 +080093{
94}
95
xiaohu.huang2beac512022-05-07 15:10:04 +080096__weak void store_rtc(void)
Xiaohu.Huang60950452022-03-12 22:51:01 +080097{
98}
99
xiaohu.huang2beac512022-05-07 15:10:04 +0800100__weak void vCLK_suspend(uint32_t st_f)
Xiaohu.Huang60950452022-03-12 22:51:01 +0800101{
xiaohu.huang2beac512022-05-07 15:10:04 +0800102 (void)st_f;
Xiaohu.Huang60950452022-03-12 22:51:01 +0800103}
104
xiaohu.huang2beac512022-05-07 15:10:04 +0800105__weak void vCLK_resume(uint32_t st_f)
Xiaohu.Huang60950452022-03-12 22:51:01 +0800106{
xiaohu.huang2beac512022-05-07 15:10:04 +0800107 (void)st_f;
Xiaohu.Huang60950452022-03-12 22:51:01 +0800108}
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800109
changpeng.jiangfd280412024-03-13 17:19:34 +0800110__weak void check_poweroff_status(void)
111{
112 vTaskDelay(pdMS_TO_TICKS(500));
113}
114
Jianyi Shifd8850a2023-10-23 17:46:48 +0800115#if BL30_SUSPEND_DEBUG_EN
Zhu Lv92cff0b2024-10-10 13:00:08 +0000116inline void split_suspend_debug_flag(uint32_t *temp)
Jianyi Shifd8850a2023-10-23 17:46:48 +0800117{
118 suspend_debug_flag = (*temp) & SUSPEND_DEBUG_MASK;
119 *temp = (*temp) & ~SUSPEND_DEBUG_MASK;
120}
121
Zhu Lv92cff0b2024-10-10 13:00:08 +0000122inline uint32_t get_suspend_debug_flag(void)
Jianyi Shifd8850a2023-10-23 17:46:48 +0800123{
124 return suspend_debug_flag;
125}
126
127void vDebugPrintTask(void *pvParameters)
128{
129 /*make compiler happy*/
130 (void) pvParameters;
131
132 for ( ;; ) {
133 printf("vPTask1...\n");
134 vTaskDelay(pdMS_TO_TICKS(TEST_TASK1_DELAY));
135 }
136}
137#endif
138
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800139void system_resume(uint32_t pm)
140{
141 uint32_t shutdown_flag = 0;
142
Jianyi Shifd8850a2023-10-23 17:46:48 +0800143#if BL30_SUSPEND_DEBUG_EN
144 enter_func_print();
145#endif
146
bangzheng.liu36236e62024-04-16 16:15:39 +0800147 if (pm == POWER_MODE_POWER_OFF)
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800148 shutdown_flag = 1;
Xiaohu.Huang60950452022-03-12 22:51:01 +0800149 vCLK_resume(shutdown_flag);
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800150 /*Need clr alarm ASAP*/
151 alarm_clr();
152 str_power_on(shutdown_flag);
Jianyi Shifd8850a2023-10-23 17:46:48 +0800153#if BL30_SUSPEND_DEBUG_EN
154 if (!IS_EN(BL30_SKIP_DDR_SUSPEND))
155#endif
156 vDDR_resume(shutdown_flag);
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800157 str_hw_disable();
158 vRTC_update();
159 wakeup_ap();
160 clear_wakeup_trigger();
161 /*Shutdown*/
Xiaohu.Huang60950452022-03-12 22:51:01 +0800162 if (shutdown_flag) {
163 /* Store RTC time for a5 temporarily*/
164 store_rtc();
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800165 watchdog_reset_system();
Xiaohu.Huang60950452022-03-12 22:51:01 +0800166 }
Jianyi Shifd8850a2023-10-23 17:46:48 +0800167
168#if BL30_SUSPEND_DEBUG_EN
169 stop_debug_task();
170 exit_func_print();
171#endif
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800172}
173
174void system_suspend(uint32_t pm)
175{
176 uint32_t shutdown_flag = 0;
Jianyi Shifd8850a2023-10-23 17:46:48 +0800177#if BL30_SUSPEND_DEBUG_EN
Zhu Lv92cff0b2024-10-10 13:00:08 +0000178 split_suspend_debug_flag(&pm);
Jianyi Shifd8850a2023-10-23 17:46:48 +0800179 enter_func_print();
180 start_debug_task();
181#endif
bangzheng.liu36236e62024-04-16 16:15:39 +0800182 if (pm == POWER_MODE_POWER_OFF)
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800183 shutdown_flag = 1;
184
185 /*Need set alarm ASAP*/
186 alarm_set();
187 str_hw_init();
188 /*Set flag befor delay. It can be wakeup during delay*/
189 set_suspend_flag();
changpeng.jiangfd280412024-03-13 17:19:34 +0800190 /*Wait for FSM switch to off*/
191 check_poweroff_status();
Jianyi Shifd8850a2023-10-23 17:46:48 +0800192#if BL30_SUSPEND_DEBUG_EN
193 if (!IS_EN(BL30_SKIP_DDR_SUSPEND))
194#endif
195 vDDR_suspend(shutdown_flag);
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800196 str_power_off(shutdown_flag);
Xiaohu.Huang60950452022-03-12 22:51:01 +0800197 vCLK_suspend(shutdown_flag);
Jianyi Shifd8850a2023-10-23 17:46:48 +0800198#if BL30_SUSPEND_DEBUG_EN
199 exit_func_print();
200#endif
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800201}
202
203void set_reason_flag(char exit_reason)
204{
Yao Jie5d17b5c2022-11-24 11:00:17 +0800205 uint32_t val;
206
207 val = REG32(WAKEUP_REASON_STICK_REG) & ~0xff;
208 val |= EXIT_REASON_EXTENSION_FLAG;
209 val |= (exit_reason & 0x7f);
210 REG32(WAKEUP_REASON_STICK_REG) = val;
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800211}
212
213uint32_t get_reason_flag(void)
214{
Yao Jie5d17b5c2022-11-24 11:00:17 +0800215 return REG32(WAKEUP_REASON_STICK_REG) & 0x7f;
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800216}
217
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800218void *xMboxGetWakeupReason(void *msg)
219{
220 *(uint32_t *)msg = get_reason_flag();
221 return NULL;
222}
223
224void *xMboxClrWakeupReason(void *msg)
225{
xiaohu.huang2beac512022-05-07 15:10:04 +0800226 (void)msg;
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800227 return NULL;
228}
229
230void *xMboxGetStickRebootFlag(void *msg)
231{
Yao Jieeb106042023-11-20 10:56:31 +0800232#ifdef CONFIG_STICK_MEM
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800233 *(uint32_t *)msg = get_stick_reboot_flag();
Yao Jieeb106042023-11-20 10:56:31 +0800234#else
235 printf("Don't support stick memory!\r\n");
236#endif
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800237 return NULL;
238}
239
240void STR_Start_Sem_Give_FromISR(void)
241{
242 BaseType_t xHigherPriorityTaskWoken;
xiaohu.huang2beac512022-05-07 15:10:04 +0800243
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800244 xSemaphoreGiveFromISR(xSTRSemaphore, &xHigherPriorityTaskWoken);
245}
246
247void STR_Start_Sem_Give(void)
248{
249 xSemaphoreGive(xSTRSemaphore);
250}
251
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800252void STR_Wakeup_src_Queue_Send_FromISR(uint32_t *src)
253{
254 BaseType_t xHigherPriorityTaskWoken;
255 uint32_t flag = 0;
256 UBaseType_t uxSavedInterruptStatus;
257
258 uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR();
259 if (suspend_flag) {
260 suspend_flag = 0;
261 flag = 1;
262 }
263 taskEXIT_CRITICAL_FROM_ISR(uxSavedInterruptStatus);
264
265 if (flag)
266 xQueueSendFromISR(xSTRQueue, src, &xHigherPriorityTaskWoken);
267}
268
269void STR_Wakeup_src_Queue_Send(uint32_t *src)
270{
271 uint32_t flag = 0;
272
273 taskENTER_CRITICAL();
274 if (suspend_flag) {
275 suspend_flag = 0;
276 flag = 1;
277 }
278 taskEXIT_CRITICAL();
279
280 if (flag)
281 xQueueSend(xSTRQueue, src, portMAX_DELAY);
282}
283
284void *xMboxSuspend_Sem(void *msg)
285{
286 power_mode = *(uint32_t *)msg;
287
bangzheng.liu9f879ed2024-03-25 13:37:43 +0800288#ifdef ACS_DIS_PRINT_FLAG
bangzheng.liu512eda62024-02-26 13:12:07 +0800289 enable_bl30_print(1);
290#endif
291
bangzheng.liu36236e62024-04-16 16:15:39 +0800292 switch (power_mode & POWER_MODE_MASK) {
293 case POWER_MODE_SUSPEND_1:
294 case POWER_MODE_SUSPEND_2:
295 printf("power_mode: SUSPEND\n");
296 break;
297 case POWER_MODE_POWER_OFF:
298 printf("power_mode: POWER OFF\n");
299 break;
300 default:
301 printf("power_mode: UNKNOWN\n");
302 break;
303 }
304
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800305 STR_Start_Sem_Give();
306
307 return NULL;
308}
309
xiaohu.huang2beac512022-05-07 15:10:04 +0800310#define FREEZE_ENTER 0x01
311#define FREEZE_EXIT 0x02
Xiaohu.Huang60950452022-03-12 22:51:01 +0800312
313void *xMboxpm_sem(void *msg);
314void *xMboxpm_sem(void *msg)
315{
316 uint32_t mode = *(uint32_t *)msg;
317
bangzheng.liu9f879ed2024-03-25 13:37:43 +0800318#ifdef ACS_DIS_PRINT_FLAG
bangzheng.liu512eda62024-02-26 13:12:07 +0800319 enable_bl30_print(1);
320#endif
321
binbin.wang093973e2023-06-26 14:00:32 +0800322#ifdef CONFIG_PM
xiaohu.huang2beac512022-05-07 15:10:04 +0800323 if (mode == FREEZE_ENTER)
Xiaohu.Huang60950452022-03-12 22:51:01 +0800324 pm_enter();
xiaohu.huang2beac512022-05-07 15:10:04 +0800325 else if (mode == FREEZE_EXIT)
Xiaohu.Huang60950452022-03-12 22:51:01 +0800326 wakeup_ap_from_kernel();
binbin.wang093973e2023-06-26 14:00:32 +0800327#endif
Xiaohu.Huang60950452022-03-12 22:51:01 +0800328
329 return NULL;
330}
331
xiaohu.huang2beac512022-05-07 15:10:04 +0800332static void vSTRTask(void *pvParameters)
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800333{
334 /*make compiler happy*/
335 uint32_t buffer = UDEFINED_WAKEUP;
336 uint32_t exit_reason = 0;
337
xiaohu.huang2beac512022-05-07 15:10:04 +0800338 (void)pvParameters;
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800339 xSTRQueue = xQueueCreate(STR_QUEUE_LENGTH, STR_QUEUE_ITEM_SIZE);
340 configASSERT(xSTRQueue);
341 xSTRSemaphore = xSemaphoreCreateBinary();
342 configASSERT(xSTRSemaphore);
343
344 while (1) {
345 xSemaphoreTake(xSTRSemaphore, portMAX_DELAY);
346 system_suspend(power_mode);
xiaohu.huang2beac512022-05-07 15:10:04 +0800347 while (xQueueReceive(xSTRQueue, &buffer, portMAX_DELAY)) {
348 switch (buffer) {
349 case REMOTE_WAKEUP:
350 exit_reason = REMOTE_WAKEUP;
351 break;
352 case RTC_WAKEUP:
353 exit_reason = RTC_WAKEUP;
354 break;
355 case BT_WAKEUP:
356 exit_reason = BT_WAKEUP;
357 break;
358 case CEC_WAKEUP:
359 exit_reason = CEC_WAKEUP;
360 break;
361 case CECB_WAKEUP:
362 exit_reason = CECB_WAKEUP;
363 break;
364 case REMOTE_CUS_WAKEUP:
365 exit_reason = REMOTE_CUS_WAKEUP;
366 break;
367 case POWER_KEY_WAKEUP:
368 exit_reason = POWER_KEY_WAKEUP;
369 break;
370 case ETH_PMT_WAKEUP:
371 exit_reason = ETH_PMT_WAKEUP;
372 break;
373 case WIFI_WAKEUP:
374 exit_reason = WIFI_WAKEUP;
375 break;
Zhuo Wang450eab72022-11-09 14:39:32 +0800376 case ETH_PHY_GPIO:
377 exit_reason = ETH_PHY_GPIO;
378 printf("wzh eth gpio\n");
379 break;
xiaohu.huang2beac512022-05-07 15:10:04 +0800380 case VAD_WAKEUP:
381 exit_reason = VAD_WAKEUP;
382 break;
383 case HDMI_RX_WAKEUP:
384 exit_reason = HDMI_RX_WAKEUP;
385 break;
Yu Tue700c712023-04-10 15:28:09 +0800386 case UART_RX_WAKEUP:
387 exit_reason = UART_RX_WAKEUP;
388 break;
xiaohu.huang2beac512022-05-07 15:10:04 +0800389 default:
bangzheng.liu6889f9a2023-11-17 11:20:48 +0800390 printf("unknown exit_reason %d\n", exit_reason);
391 set_suspend_flag();
xiaohu.huang2beac512022-05-07 15:10:04 +0800392 break;
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800393 }
394 if (exit_reason) {
xiaohu.huang2beac512022-05-07 15:10:04 +0800395 printf("exit_reason=%d, %s\n", exit_reason,
396 vWakeupReason[exit_reason].name);
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800397 set_reason_flag((char)exit_reason);
398 exit_reason = 0;
399 system_resume(power_mode);
400 goto loop;
401 }
402 }
xiaohu.huang2beac512022-05-07 15:10:04 +0800403loop:
404 continue;
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800405 }
406}
407
408void create_str_task(void)
409{
xiaohu.huang2beac512022-05-07 15:10:04 +0800410 if (xTaskCreate(vSTRTask, "STR_task", configMINIMAL_STACK_SIZE, NULL, 3, NULL) < 0)
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800411 printf("STR_task create fail!!\n");
412
413 vCreat_alarm_timer();
414
Yao Jie549b0092024-12-16 14:51:43 +0800415 xInstallRemoteMessageCallbackFeedBack(AOTEE_CHANNEL,
416 MBX_CMD_SUSPEND, xMboxSuspend_Sem, 0);
417 xInstallRemoteMessageCallbackFeedBack(AOREE_CHANNEL,
418 MBX_CMD_GET_WAKEUP_REASON, xMboxGetWakeupReason, 1);
419 xInstallRemoteMessageCallbackFeedBack(AOREE_CHANNEL,
420 MBX_CMD_CLR_WAKEUP_REASON, xMboxClrWakeupReason, 0);
421 xInstallRemoteMessageCallbackFeedBack(AOREE_CHANNEL,
422 MBX_CMD_GET_STICK_REBOOT_FLAG, xMboxGetStickRebootFlag, 1);
423 xInstallRemoteMessageCallbackFeedBack(AOREE_CHANNEL,
424 MBX_CMD_PM_FREEZE, xMboxpm_sem, 1);
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800425}