xref: /rk3399_ARM-atf/plat/mediatek/drivers/vcp/rv/vcp_common.c (revision 06f3c7058c42a9f1a9f7df75ea2de71a000855e8)
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 
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 
57 uint32_t get_mmup_fw_size(void)
58 {
59 	return g_mmup_fw_size;
60 }
61 
62 uint64_t get_mmup_l2tcm_offset(void)
63 {
64 	return g_l2tcm_offset;
65 }
66 
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 
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 
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 
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 
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 
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 
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