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