1 /*
2 * Copyright (c) 2024, MediaTek Inc. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <errno.h>
8 #include <inttypes.h>
9 #include <stdint.h>
10 #include <stdio.h>
11
12 #include <arch_helpers.h>
13 #include <common/debug.h>
14 #include <lib/mmio.h>
15 #include <lib/xlat_tables/xlat_tables_v2.h>
16 #include <smccc_helpers.h>
17
18 #include "mmup_common.h"
19 #include <mtk_mmap_pool.h>
20 #include <mtk_sip_svc.h>
21 #include "vcp_helper.h"
22 #include "vcp_reg.h"
23
24 #define MODULE_TAG "[VCP]"
25
26 static const mmap_region_t vcp_mmap[] MTK_MMAP_SECTION = {
27 MAP_REGION_FLAT(VCP_R_CFGREG, MTK_VCP_REG_BANK_SIZE,
28 MT_DEVICE | MT_RW | MT_SECURE),
29 MAP_REGION_FLAT(VCP_R_CFGREG_CORE0, MTK_VCP_REG_BANK_SIZE,
30 MT_DEVICE | MT_RW | MT_SECURE),
31 MAP_REGION_FLAT(VCP_R_CFGREG_CORE1, MTK_VCP_REG_BANK_SIZE,
32 MT_DEVICE | MT_RW | MT_SECURE),
33 MAP_REGION_FLAT(VCP_R_SEC_CTRL, MTK_VCP_REG_BANK_SIZE,
34 MT_DEVICE | MT_RW | MT_SECURE),
35 {0}
36 };
37 DECLARE_MTK_MMAP_REGIONS(vcp_mmap);
38
39 /* vcp-mmup l2tcm memory offset */
40 static uint64_t g_l2tcm_offset;
41 static uint32_t g_mmup_fw_size;
42
get_vcp_pwr_status(void)43 static bool get_vcp_pwr_status(void)
44 {
45 #if defined(SPM_BASE)
46 uint32_t spm_pwr_sta = mmio_read_32(SPM_BASE + VCP_POWER_STATUS);
47
48 if (!(spm_pwr_sta & (MMUP_PWR_STA_EN << MMUP_PWR_STA_BIT))) {
49 ERROR("%s: pwr_sta:%x, bit:%d disable\n", MODULE_TAG,
50 spm_pwr_sta, MMUP_PWR_STA_BIT);
51 return false;
52 }
53 #endif
54 return true;
55 }
56
get_mmup_fw_size(void)57 uint32_t get_mmup_fw_size(void)
58 {
59 return g_mmup_fw_size;
60 }
61
get_mmup_l2tcm_offset(void)62 uint64_t get_mmup_l2tcm_offset(void)
63 {
64 return g_l2tcm_offset;
65 }
66
vcp_cold_boot_reset(void)67 static bool vcp_cold_boot_reset(void)
68 {
69 mmio_write_32(VCP_GPR2_CFGREG_SEC, 0);
70 mmio_write_32(VCP_GPR3_CFGREG_SEC, 0);
71
72 return true;
73 }
74
mmup_cold_boot_reset(void)75 static bool mmup_cold_boot_reset(void)
76 {
77 mmio_write_32(VCP_GPR0_CFGREG_SEC, 0);
78 mmio_write_32(VCP_GPR1_CFGREG_SEC, 0);
79
80 return true;
81 }
82
vcp_set_mmup_l2tcm_offset(uint64_t l2tcm_offset)83 static bool vcp_set_mmup_l2tcm_offset(uint64_t l2tcm_offset)
84 {
85 g_l2tcm_offset = l2tcm_offset;
86
87 if (g_l2tcm_offset > MTK_VCP_SRAM_SIZE) {
88 g_l2tcm_offset = 0;
89 return false;
90 }
91
92 return true;
93 }
94
vcp_set_mmup_fw_size(uint64_t fw_size)95 static bool vcp_set_mmup_fw_size(uint64_t fw_size)
96 {
97 g_mmup_fw_size = fw_size;
98
99 if (g_mmup_fw_size > MTK_VCP_SRAM_SIZE - g_l2tcm_offset) {
100 g_mmup_fw_size = 0;
101 return false;
102 }
103
104 return true;
105 }
106
vcp_smc_rstn_set(bool boot_ok)107 static bool vcp_smc_rstn_set(bool boot_ok)
108 {
109 if (mmio_read_32(VCP_GPR_C0_H0_REBOOT) != 0 &&
110 mmio_read_32(VCP_R_CORE0_STATUS) != 0 &&
111 (mmio_read_32(VCP_R_GIPC_IN_SET) & B_GIPC3_SETCLR_1) == 0 &&
112 (mmio_read_32(VCP_R_GIPC_IN_CLR) & B_GIPC3_SETCLR_1) == 0 &&
113 mmio_read_32(VCP_GPR_C0_H0_REBOOT) != VCP_CORE_RDY_TO_REBOOT &&
114 mmio_read_32(VCP_GPR_C0_H1_REBOOT) != VCP_CORE_RDY_TO_REBOOT) {
115 ERROR("%s: [%s] mmup reset set fail!GIPC 0x%x 0x%x REBOOT 0x%x 0x%x\n",
116 MODULE_TAG, __func__, mmio_read_32(VCP_R_GIPC_IN_SET),
117 mmio_read_32(VCP_R_GIPC_IN_CLR),
118 mmio_read_32(VCP_GPR_C0_H0_REBOOT),
119 mmio_read_32(VCP_GPR_C0_H1_REBOOT));
120 return false;
121 }
122
123 mmio_write_32(VCP_R_CORE0_SW_RSTN_SET, BIT(0));
124
125 /* reset sec control */
126 mmio_write_32(VCP_R_SEC_CTRL_2, 0);
127
128 /* reset domain setting */
129 mmio_write_32(VCP_R_S_DOM_EN0_31, 0x0);
130 mmio_write_32(VCP_R_S_DOM_EN32_63, 0x0);
131 mmio_write_32(VCP_R_NS_DOM_EN0_31, 0x0);
132 mmio_write_32(VCP_R_NS_DOM_EN32_63, 0x0);
133
134 /* reset sec setting */
135 mmio_clrbits_32(VCP_R_DYN_SECURE,
136 RESET_NS_SECURE_B_REGION << VCP_NS_SECURE_B_REGION_ENABLE);
137
138 if (boot_ok) {
139 mmio_write_32(VCP_GPR_C0_H0_REBOOT, VCP_CORE_REBOOT_OK);
140 mmio_write_32(VCP_GPR_C0_H1_REBOOT, VCP_CORE_REBOOT_OK);
141 }
142
143 dsbsy();
144 return true;
145 }
146
vcp_smc_rstn_clr(void)147 static bool vcp_smc_rstn_clr(void)
148 {
149 if ((mmio_read_32(VCP_R_CORE0_SW_RSTN_SET) & BIT(0)) == 1) {
150 ERROR("%s: [%s] mmup not reset set !\n", MODULE_TAG, __func__);
151 return false;
152 }
153
154 mmio_clrsetbits_32(VCP_R_SEC_DOMAIN,
155 ~(VCP_DOMAIN_MASK << VCP_HWCCF_DOMAIN), VCP_DOMAIN_SET);
156
157 /* enable IOVA Mode */
158 mmio_write_32(VCP_R_AXIOMMUEN_DEV_APC, BIT(0));
159
160 /* reset secure setting */
161 mmio_setbits_32(VCP_R_SEC_CTRL_2, CORE0_SEC_BIT_SEL);
162 mmio_clrbits_32(VCP_R_DYN_SECURE, VCP_NS_I0 | VCP_NS_D0);
163 mmio_clrbits_32(VCP_R_DYN_SECURE_TH1, VCP_NS_I1 | VCP_NS_D1);
164
165 /* start vcp */
166 mmio_write_32(VCP_R_CORE0_SW_RSTN_CLR, BIT(0));
167 dsbsy();
168 return true;
169 }
170
tinysys_vcp_kernel_control(u_register_t arg0,u_register_t arg1,u_register_t arg2,u_register_t arg3,void * handle,struct smccc_res * smccc_ret)171 static u_register_t tinysys_vcp_kernel_control(u_register_t arg0,
172 u_register_t arg1,
173 u_register_t arg2,
174 u_register_t arg3,
175 void *handle,
176 struct smccc_res *smccc_ret)
177 {
178 uint32_t request_ops;
179 uint64_t ret = MTK_SIP_E_SUCCESS;
180
181 if (!get_vcp_pwr_status())
182 return MTK_SIP_E_NOT_SUPPORTED;
183
184 request_ops = (uint32_t)arg0;
185
186 switch (request_ops) {
187 case MTK_TINYSYS_VCP_KERNEL_OP_RESET_SET:
188 ret = vcp_smc_rstn_set((bool)!!arg1);
189 break;
190 case MTK_TINYSYS_VCP_KERNEL_OP_RESET_RELEASE:
191 ret = vcp_smc_rstn_clr();
192 break;
193 case MTK_TINYSYS_VCP_KERNEL_OP_COLD_BOOT_VCP:
194 ret = vcp_cold_boot_reset();
195 break;
196 case MTK_TINYSYS_MMUP_KERNEL_OP_RESET_SET:
197 ret = mmup_smc_rstn_set((bool)!!arg1);
198 break;
199 case MTK_TINYSYS_MMUP_KERNEL_OP_RESET_RELEASE:
200 ret = mmup_smc_rstn_clr();
201 break;
202 case MTK_TINYSYS_MMUP_KERNEL_OP_SET_L2TCM_OFFSET:
203 ret = vcp_set_mmup_l2tcm_offset(arg1);
204 break;
205 case MTK_TINYSYS_MMUP_KERNEL_OP_SET_FW_SIZE:
206 ret = vcp_set_mmup_fw_size(arg1);
207 break;
208 case MTK_TINYSYS_MMUP_KERNEL_OP_COLD_BOOT_MMUP:
209 ret = mmup_cold_boot_reset();
210 break;
211 default:
212 ERROR("%s: %s, unknown request_ops = %x\n", MODULE_TAG, __func__, request_ops);
213 ret = MTK_SIP_E_INVALID_PARAM;
214 break;
215 }
216
217 return ret;
218 }
219
220 /* Register SiP SMC service */
221 DECLARE_SMC_HANDLER(MTK_SIP_KERNEL_VCP_CONTROL, tinysys_vcp_kernel_control);
222