blob: e346d6a3955f9b4e839300c8dc0e844375d571c9 [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"
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +080033
xiaohu.huang2beac512022-05-07 15:10:04 +080034SemaphoreHandle_t xSTRSemaphore;
35QueueHandle_t xSTRQueue;
36SemaphoreHandle_t xSTRFlagSem;
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +080037uint32_t suspend_flag;
Jianyi Shifd8850a2023-10-23 17:46:48 +080038#if BL30_SUSPEND_DEBUG_EN
39uint32_t suspend_debug_flag;
40static TaskHandle_t printTask;
41#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
Jianyi Shifd8850a2023-10-23 17:46:48 +0800110#if BL30_SUSPEND_DEBUG_EN
111inline void split_suspend_flag(uint32_t *temp)
112{
113 suspend_debug_flag = (*temp) & SUSPEND_DEBUG_MASK;
114 *temp = (*temp) & ~SUSPEND_DEBUG_MASK;
115}
116
117inline uint32_t get_suspend_flag(void)
118{
119 return suspend_debug_flag;
120}
121
122void vDebugPrintTask(void *pvParameters)
123{
124 /*make compiler happy*/
125 (void) pvParameters;
126
127 for ( ;; ) {
128 printf("vPTask1...\n");
129 vTaskDelay(pdMS_TO_TICKS(TEST_TASK1_DELAY));
130 }
131}
132#endif
133
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800134void system_resume(uint32_t pm)
135{
136 uint32_t shutdown_flag = 0;
137
Jianyi Shifd8850a2023-10-23 17:46:48 +0800138#if BL30_SUSPEND_DEBUG_EN
139 enter_func_print();
140#endif
141
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800142 if (pm == 0xf)
143 shutdown_flag = 1;
Xiaohu.Huang60950452022-03-12 22:51:01 +0800144 vCLK_resume(shutdown_flag);
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800145 /*Need clr alarm ASAP*/
146 alarm_clr();
147 str_power_on(shutdown_flag);
Jianyi Shifd8850a2023-10-23 17:46:48 +0800148#if BL30_SUSPEND_DEBUG_EN
149 if (!IS_EN(BL30_SKIP_DDR_SUSPEND))
150#endif
151 vDDR_resume(shutdown_flag);
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800152 str_hw_disable();
153 vRTC_update();
154 wakeup_ap();
155 clear_wakeup_trigger();
156 /*Shutdown*/
Xiaohu.Huang60950452022-03-12 22:51:01 +0800157 if (shutdown_flag) {
158 /* Store RTC time for a5 temporarily*/
159 store_rtc();
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800160 watchdog_reset_system();
Xiaohu.Huang60950452022-03-12 22:51:01 +0800161 }
Jianyi Shifd8850a2023-10-23 17:46:48 +0800162
163#if BL30_SUSPEND_DEBUG_EN
164 stop_debug_task();
165 exit_func_print();
166#endif
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800167}
168
169void system_suspend(uint32_t pm)
170{
171 uint32_t shutdown_flag = 0;
Jianyi Shifd8850a2023-10-23 17:46:48 +0800172#if BL30_SUSPEND_DEBUG_EN
173 split_suspend_flag(&pm);
174 enter_func_print();
175 start_debug_task();
176#endif
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800177 if (pm == 0xf)
178 shutdown_flag = 1;
179
180 /*Need set alarm ASAP*/
181 alarm_set();
182 str_hw_init();
183 /*Set flag befor delay. It can be wakeup during delay*/
184 set_suspend_flag();
185 /*Delay 500ms for FSM switch to off*/
186 vTaskDelay(pdMS_TO_TICKS(500));
Jianyi Shifd8850a2023-10-23 17:46:48 +0800187#if BL30_SUSPEND_DEBUG_EN
188 if (!IS_EN(BL30_SKIP_DDR_SUSPEND))
189#endif
190 vDDR_suspend(shutdown_flag);
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800191 str_power_off(shutdown_flag);
Xiaohu.Huang60950452022-03-12 22:51:01 +0800192 vCLK_suspend(shutdown_flag);
Jianyi Shifd8850a2023-10-23 17:46:48 +0800193#if BL30_SUSPEND_DEBUG_EN
194 exit_func_print();
195#endif
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800196}
197
198void set_reason_flag(char exit_reason)
199{
Yao Jie5d17b5c2022-11-24 11:00:17 +0800200 uint32_t val;
201
202 val = REG32(WAKEUP_REASON_STICK_REG) & ~0xff;
203 val |= EXIT_REASON_EXTENSION_FLAG;
204 val |= (exit_reason & 0x7f);
205 REG32(WAKEUP_REASON_STICK_REG) = val;
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800206}
207
208uint32_t get_reason_flag(void)
209{
Yao Jie5d17b5c2022-11-24 11:00:17 +0800210 return REG32(WAKEUP_REASON_STICK_REG) & 0x7f;
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800211}
212
213uint32_t get_stick_reboot_flag(void)
214{
215#if (configSUPPORT_STICK_MEM == 1)
216 return last_stick_reboot_flag;
217#else
218 printf("Don't support stick memory!\r\n");
219 return 0;
220#endif
221}
222
223void *xMboxGetWakeupReason(void *msg)
224{
225 *(uint32_t *)msg = get_reason_flag();
226 return NULL;
227}
228
229void *xMboxClrWakeupReason(void *msg)
230{
xiaohu.huang2beac512022-05-07 15:10:04 +0800231 (void)msg;
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800232 return NULL;
233}
234
235void *xMboxGetStickRebootFlag(void *msg)
236{
237 *(uint32_t *)msg = get_stick_reboot_flag();
238
239 return NULL;
240}
241
242void STR_Start_Sem_Give_FromISR(void)
243{
244 BaseType_t xHigherPriorityTaskWoken;
xiaohu.huang2beac512022-05-07 15:10:04 +0800245
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800246 xSemaphoreGiveFromISR(xSTRSemaphore, &xHigherPriorityTaskWoken);
247}
248
249void STR_Start_Sem_Give(void)
250{
251 xSemaphoreGive(xSTRSemaphore);
252}
253
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800254void STR_Wakeup_src_Queue_Send_FromISR(uint32_t *src)
255{
256 BaseType_t xHigherPriorityTaskWoken;
257 uint32_t flag = 0;
258 UBaseType_t uxSavedInterruptStatus;
259
260 uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR();
261 if (suspend_flag) {
262 suspend_flag = 0;
263 flag = 1;
264 }
265 taskEXIT_CRITICAL_FROM_ISR(uxSavedInterruptStatus);
266
267 if (flag)
268 xQueueSendFromISR(xSTRQueue, src, &xHigherPriorityTaskWoken);
269}
270
271void STR_Wakeup_src_Queue_Send(uint32_t *src)
272{
273 uint32_t flag = 0;
274
275 taskENTER_CRITICAL();
276 if (suspend_flag) {
277 suspend_flag = 0;
278 flag = 1;
279 }
280 taskEXIT_CRITICAL();
281
282 if (flag)
283 xQueueSend(xSTRQueue, src, portMAX_DELAY);
284}
285
286void *xMboxSuspend_Sem(void *msg)
287{
288 power_mode = *(uint32_t *)msg;
289
Jianyi Shifd8850a2023-10-23 17:46:48 +0800290 printf("power_mode=0x%x\n", power_mode & POWER_MODE_MASK);
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800291 STR_Start_Sem_Give();
292
293 return NULL;
294}
295
xiaohu.huang2beac512022-05-07 15:10:04 +0800296#define FREEZE_ENTER 0x01
297#define FREEZE_EXIT 0x02
Xiaohu.Huang60950452022-03-12 22:51:01 +0800298
299void *xMboxpm_sem(void *msg);
300void *xMboxpm_sem(void *msg)
301{
302 uint32_t mode = *(uint32_t *)msg;
303
binbin.wang093973e2023-06-26 14:00:32 +0800304#ifdef CONFIG_PM
xiaohu.huang2beac512022-05-07 15:10:04 +0800305 if (mode == FREEZE_ENTER)
Xiaohu.Huang60950452022-03-12 22:51:01 +0800306 pm_enter();
xiaohu.huang2beac512022-05-07 15:10:04 +0800307 else if (mode == FREEZE_EXIT)
Xiaohu.Huang60950452022-03-12 22:51:01 +0800308 wakeup_ap_from_kernel();
binbin.wang093973e2023-06-26 14:00:32 +0800309#endif
Xiaohu.Huang60950452022-03-12 22:51:01 +0800310
311 return NULL;
312}
313
xiaohu.huang2beac512022-05-07 15:10:04 +0800314static void vSTRTask(void *pvParameters)
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800315{
316 /*make compiler happy*/
317 uint32_t buffer = UDEFINED_WAKEUP;
318 uint32_t exit_reason = 0;
319
xiaohu.huang2beac512022-05-07 15:10:04 +0800320 (void)pvParameters;
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800321 xSTRQueue = xQueueCreate(STR_QUEUE_LENGTH, STR_QUEUE_ITEM_SIZE);
322 configASSERT(xSTRQueue);
323 xSTRSemaphore = xSemaphoreCreateBinary();
324 configASSERT(xSTRSemaphore);
325
326 while (1) {
327 xSemaphoreTake(xSTRSemaphore, portMAX_DELAY);
328 system_suspend(power_mode);
xiaohu.huang2beac512022-05-07 15:10:04 +0800329 while (xQueueReceive(xSTRQueue, &buffer, portMAX_DELAY)) {
330 switch (buffer) {
331 case REMOTE_WAKEUP:
332 exit_reason = REMOTE_WAKEUP;
333 break;
334 case RTC_WAKEUP:
335 exit_reason = RTC_WAKEUP;
336 break;
337 case BT_WAKEUP:
338 exit_reason = BT_WAKEUP;
339 break;
340 case CEC_WAKEUP:
341 exit_reason = CEC_WAKEUP;
342 break;
343 case CECB_WAKEUP:
344 exit_reason = CECB_WAKEUP;
345 break;
346 case REMOTE_CUS_WAKEUP:
347 exit_reason = REMOTE_CUS_WAKEUP;
348 break;
349 case POWER_KEY_WAKEUP:
350 exit_reason = POWER_KEY_WAKEUP;
351 break;
352 case ETH_PMT_WAKEUP:
353 exit_reason = ETH_PMT_WAKEUP;
354 break;
355 case WIFI_WAKEUP:
356 exit_reason = WIFI_WAKEUP;
357 break;
Zhuo Wang450eab72022-11-09 14:39:32 +0800358 case ETH_PHY_GPIO:
359 exit_reason = ETH_PHY_GPIO;
360 printf("wzh eth gpio\n");
361 break;
xiaohu.huang2beac512022-05-07 15:10:04 +0800362 case VAD_WAKEUP:
363 exit_reason = VAD_WAKEUP;
364 break;
365 case HDMI_RX_WAKEUP:
366 exit_reason = HDMI_RX_WAKEUP;
367 break;
Yu Tue700c712023-04-10 15:28:09 +0800368 case UART_RX_WAKEUP:
369 exit_reason = UART_RX_WAKEUP;
370 break;
xiaohu.huang2beac512022-05-07 15:10:04 +0800371 default:
bangzheng.liu6889f9a2023-11-17 11:20:48 +0800372 printf("unknown exit_reason %d\n", exit_reason);
373 set_suspend_flag();
xiaohu.huang2beac512022-05-07 15:10:04 +0800374 break;
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800375 }
376 if (exit_reason) {
xiaohu.huang2beac512022-05-07 15:10:04 +0800377 printf("exit_reason=%d, %s\n", exit_reason,
378 vWakeupReason[exit_reason].name);
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800379 set_reason_flag((char)exit_reason);
380 exit_reason = 0;
381 system_resume(power_mode);
382 goto loop;
383 }
384 }
xiaohu.huang2beac512022-05-07 15:10:04 +0800385loop:
386 continue;
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800387 }
388}
389
390void create_str_task(void)
391{
392 int ret;
393
xiaohu.huang2beac512022-05-07 15:10:04 +0800394 if (xTaskCreate(vSTRTask, "STR_task", configMINIMAL_STACK_SIZE, NULL, 3, NULL) < 0)
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800395 printf("STR_task create fail!!\n");
396
397 vCreat_alarm_timer();
398
399 ret = xInstallRemoteMessageCallbackFeedBack(AOTEE_CHANNEL, MBX_CMD_SUSPEND,
xiaohu.huang2beac512022-05-07 15:10:04 +0800400 xMboxSuspend_Sem, 0);
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800401 if (ret == MBOX_CALL_MAX)
402 printf("mbox cmd 0x%x register fail\n", MBX_CMD_SUSPEND);
403
404 ret = xInstallRemoteMessageCallbackFeedBack(AOREE_CHANNEL, MBX_CMD_GET_WAKEUP_REASON,
xiaohu.huang2beac512022-05-07 15:10:04 +0800405 xMboxGetWakeupReason, 1);
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800406 if (ret == MBOX_CALL_MAX)
407 printf("mbox cmd 0x%x register fail\n", MBX_CMD_GET_WAKEUP_REASON);
408
409 ret = xInstallRemoteMessageCallbackFeedBack(AOREE_CHANNEL, MBX_CMD_CLR_WAKEUP_REASON,
xiaohu.huang2beac512022-05-07 15:10:04 +0800410 xMboxClrWakeupReason, 0);
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800411
412 ret = xInstallRemoteMessageCallbackFeedBack(AOREE_CHANNEL, MBX_CMD_GET_STICK_REBOOT_FLAG,
xiaohu.huang2beac512022-05-07 15:10:04 +0800413 xMboxGetStickRebootFlag, 1);
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800414 if (ret == MBOX_CALL_MAX)
415 printf("mbox cmd 0x%x register fail\n", MBX_CMD_CLR_WAKEUP_REASON);
Xiaohu.Huang60950452022-03-12 22:51:01 +0800416
xiaohu.huang2beac512022-05-07 15:10:04 +0800417 ret = xInstallRemoteMessageCallbackFeedBack(AOREE_CHANNEL, MBX_CMD_PM_FREEZE, xMboxpm_sem,
418 1);
Xiaohu.Huang60950452022-03-12 22:51:01 +0800419 if (ret == MBOX_CALL_MAX)
420 printf("mbox cmd 0x%x register fail\n", MBX_CMD_PM_FREEZE);
Kelvin Zhangc4c3dd12021-12-24 20:59:18 +0800421}