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