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