blob: 89890eda0109ea7d207ff2f430b0dc2b1fa4cd9f [file] [log] [blame]
Dongjin Kim1e4d0b92025-03-05 17:52:02 +09001/*
2 * Copyright (c) 2025 Hardkernel Co, Ltd. All rights reserved.
3 *
4 * SPDX-License-Identifier: MIT
5 */
6
7#include <stdio.h>
8#include "FreeRTOS.h"
9#include "common.h"
10#include "eth.h"
11#include "gpio.h"
12#include "ir.h"
13#include "power.h"
14#include "rtc.h"
15#include "soc.h"
16#include "stick_mem.h"
17#include "suspend.h"
18#include "task.h"
19#include "keypad.h"
20
21#if BL30_SUSPEND_DEBUG_EN
22#include "suspend_debug_s7d.h"
23#endif
24
25#include "hdmi_cec.h"
26
Dongjin Kim878094c2025-04-01 15:44:43 +090027extern void vExtPhyInit(void);
28extern void vExtPhyDeinit(void);
29
Dongjin Kim1e4d0b92025-03-05 17:52:02 +090030static TaskHandle_t cecTask;
31
32#define VCC5V_GPIO GPIOC_7
33#define VDDCPU_A55_GPIO GPIO_TEST_N
34
35#define PWR_STATE_WAIT_ON 16
36
37static int vdddos_npu_vpu;
38static TaskHandle_t vadTask;
39
40static struct IRPowerKey prvPowerKeyList[] = {
41 { 0x23dc4db2, IR_NORMAL }, /* Hardkernel Stock Remote Controller */
42 { 0x00000000, IR_CUSTOM },
43 {}
44};
45
46static void vIRHandler(struct IRPowerKey *pkey)
47{
48 uint32_t buf[4] = { 0 };
49
50 if (pkey->type == IR_NORMAL)
51 buf[0] = REMOTE_WAKEUP;
52 else if (pkey->type == IR_CUSTOM)
53 buf[0] = REMOTE_CUS_WAKEUP;
54
55 stick_mem_write(STICK_IR_WAKEUP_KEY, pkey->code);
56 STR_Wakeup_src_Queue_Send_FromISR(buf);
57};
58
59static void *xMboxVadWakeup(void *msg)
60{
61 uint32_t buf[4] = { 0 };
62
63 buf[0] = VAD_WAKEUP;
64 STR_Wakeup_src_Queue_Send(buf);
65
66 return NULL;
67}
68
69void check_poweroff_status(void)
70{
71 const TickType_t xTimeout = pdMS_TO_TICKS(500); //Set timeout duration to 500ms
72 TickType_t xStartTick;
73
74 xStartTick = xTaskGetTickCount();
75
76 /*Wait for cputop fsm switch to WAIT_ON*/
77 while (((REG32(PWRCTRL_CPUTOP_FSM_STS0) >> 12) & 0x1F) != PWR_STATE_WAIT_ON) {
78 if (xTaskGetTickCount() - xStartTick >= xTimeout) {
79 printf("cputop fsm check timed out!\n");
80 printf("PWRCTRL_CPUTOP_FSM_STS0: %x\n", REG32(PWRCTRL_CPUTOP_FSM_STS0));
81 printf("PWRCTRL_CPU0_FSM_STS0: %x\n", REG32(PWRCTRL_CPU0_FSM_STS0));
82 printf("PWRCTRL_CPU1_FSM_STS0: %x\n", REG32(PWRCTRL_CPU1_FSM_STS0));
83 printf("PWRCTRL_CPU2_FSM_STS0: %x\n", REG32(PWRCTRL_CPU2_FSM_STS0));
84 printf("PWRCTRL_CPU3_FSM_STS0: %x\n", REG32(PWRCTRL_CPU3_FSM_STS0));
85 vTaskSuspend(NULL);
86 }
87 }
88}
89
90void str_hw_init(void)
91{
92 int ret;
93
94 vIRInit(MODE_HARD_NEC, GPIODV_0, PIN_FUNC1, prvPowerKeyList,
95 ARRAY_SIZE(prvPowerKeyList), vIRHandler);
96
97 xTaskCreate(vCEC_task, "CECtask", configMINIMAL_STACK_SIZE,
98 NULL, CEC_TASK_PRI, &cecTask);
99
100 vBackupAndClearGpioIrqReg();
101 vGpioIRQInit();
Dongjin Kim878094c2025-04-01 15:44:43 +0900102 vExtPhyInit();
Dongjin Kim1e4d0b92025-03-05 17:52:02 +0900103 vGpioKeyEnable();
104
105#if BL30_SUSPEND_DEBUG_EN
106 exit_func_print();
107#endif
108}
109
110void str_hw_disable(void)
111{
112#if BL30_SUSPEND_DEBUG_EN
113 enter_func_print();
114#endif
115 /*disable wakeup source interrupt*/
116 vIRDeint();
117
118 if (cecTask) {
119 vTaskDelete(cecTask);
120 cec_req_irq(0);
121 }
122
123 vGpioKeyDisable();
Dongjin Kim878094c2025-04-01 15:44:43 +0900124 vExtPhyDeinit();
Dongjin Kim1e4d0b92025-03-05 17:52:02 +0900125 vRestoreGpioIrqReg();
126
127#if BL30_SUSPEND_DEBUG_EN
128 exit_func_print();
129#endif
130}
131
132void str_power_on(int shutdown_flag)
133{
134 int ret;
135
136 (void)shutdown_flag;
137#if BL30_SUSPEND_DEBUG_EN
138 enter_func_print();
139 if (!IS_EN(BL30_SKIP_POWER_SWITCH)) {
140#endif
141 /***power on A55 vdd_cpu***/
142 ret = xGpioSetDir(VDDCPU_A55_GPIO, GPIO_DIR_OUT);
143 if (ret < 0) {
144 printf("vdd_cpu set gpio dir fail\n");
145 return;
146 }
147
148 ret = xGpioSetValue(VDDCPU_A55_GPIO, GPIO_LEVEL_HIGH);
149 if (ret < 0) {
150 printf("vdd_cpu set gpio val fail\n");
151 return;
152 }
153
154 if (shutdown_flag) {
155 /***power on vcc_3.3v***/
156
157 //ret = xGpioSetDir(VCC3V3_GPIO, GPIO_DIR_OUT);
158 //if (ret < 0) {
159 // printf("vcc_3.3v set gpio dir fail\n");
160 // return;
161 //}
162
163 //ret = xGpioSetValue(VCC3V3_GPIO, GPIO_LEVEL_HIGH);
164 //if (ret < 0) {
165 // printf("vcc_3.3v gpio val fail\n");
166 // return;
167 //}
168
169 }
170
171 /***power on vcc_5v***/
172 ret = xGpioSetDir(VCC5V_GPIO, GPIO_DIR_IN);
173 if (ret < 0) {
174 printf("vcc_5v set gpio dir fail\n");
175 return;
176 }
177
178 /*Wait POWERON_VDDCPU_DELAY for VDDCPU stable*/
179 vTaskDelay(POWERON_VDDCPU_DELAY);
180
181 printf("vdd_cpu on\n");
182#if BL30_SUSPEND_DEBUG_EN
183 }
184 /* size over load */
185 dump_cpu_fsm_regs();
186 show_pwm_regs();
187 exit_func_print();
188#endif
189}
190
191void str_power_off(int shutdown_flag)
192{
193 int ret;
194
195 (void)shutdown_flag;
196#if BL30_SUSPEND_DEBUG_EN
197 enter_func_print();
198 if (!IS_EN(BL30_SKIP_POWER_SWITCH)) {
199#endif
200 /***power off vcc_5v***/
201 ret = xGpioSetDir(VCC5V_GPIO, GPIO_DIR_OUT);
202 if (ret < 0) {
203 printf("vcc_5v set gpio dir fail\n");
204 return;
205 }
206
207 ret = xGpioSetValue(VCC5V_GPIO, GPIO_LEVEL_LOW);
208 if (ret < 0) {
209 printf("vcc_5v gpio val fail\n");
210 return;
211 }
212
213 /***power off A55 vdd_cpu***/
214 ret = xGpioSetDir(VDDCPU_A55_GPIO, GPIO_DIR_OUT);
215 if (ret < 0) {
216 printf("vdd_cpu set gpio dir fail\n");
217 return;
218 }
219
220 ret = xGpioSetValue(VDDCPU_A55_GPIO, GPIO_LEVEL_LOW);
221 if (ret < 0) {
222 printf("vdd_cpu set gpio val fail\n");
223 return;
224 }
225
226 printf("Power down done.\n");
227#if BL30_SUSPEND_DEBUG_EN
228 } else
229 printf("skiped power switch...\n");
230 dump_cpu_fsm_regs();
231 show_pwm_regs();
232 exit_func_print();
233#endif
234}