1*00105882SYidi Lin /* 2*00105882SYidi Lin * Copyright (c) 2025, Mediatek Inc. All rights reserved. 3*00105882SYidi Lin * 4*00105882SYidi Lin * SPDX-License-Identifier: BSD-3-Clause 5*00105882SYidi Lin */ 6*00105882SYidi Lin 7*00105882SYidi Lin #include <common/debug.h> 8*00105882SYidi Lin 9*00105882SYidi Lin #include <lib/mtk_init/mtk_init.h> 10*00105882SYidi Lin #include <mtk_bl31_interface.h> 11*00105882SYidi Lin #include <mtk_sip_svc.h> 12*00105882SYidi Lin 13*00105882SYidi Lin #define NO_PROTECTION 0 14*00105882SYidi Lin #define SEC_RW 1 15*00105882SYidi Lin #define SEC_RW_NSEC_R 2 16*00105882SYidi Lin #define SEC_RW_NSEC_W 3 17*00105882SYidi Lin #define SEC_R_NSEC_R 4 18*00105882SYidi Lin #define FORBIDDEN 5 19*00105882SYidi Lin #define SEC_R_NSEC_RW 6 20*00105882SYidi Lin 21*00105882SYidi Lin #define EMIMPU_SET 0 22*00105882SYidi Lin #define EMIMPU_CLEAR 1 23*00105882SYidi Lin #define EMIMPU_READ 2 24*00105882SYidi Lin #define EMIMPU_SLVERR 3 25*00105882SYidi Lin #define EMIDBG_DUMP 4 26*00105882SYidi Lin #define EMIDBG_MSG 5 27*00105882SYidi Lin #define AID_TABLE_SET 6 28*00105882SYidi Lin #define EMIMPU_CLEAR_MD 7 29*00105882SYidi Lin #define KP_SET 8 30*00105882SYidi Lin #define KP_CLEAR 9 31*00105882SYidi Lin 32*00105882SYidi Lin #define EMIMPU_READ_SA 0 33*00105882SYidi Lin #define EMIMPU_READ_EA 1 34*00105882SYidi Lin #define EMIMPU_READ_APC 2 35*00105882SYidi Lin #define EMIMPU_READ_ENABLE 3 36*00105882SYidi Lin #define EMIMPU_READ_AID 4 37*00105882SYidi Lin #define EMIMPU_CHECK_NS_CPU 5 38*00105882SYidi Lin #define EMIMPU_CHECK_REGION_INFO 6 39*00105882SYidi Lin #define EMIMPU_PAGE_BASE_REGION 7 40*00105882SYidi Lin #define SLBMPU_CLEAR 8 41*00105882SYidi Lin #define EMIMPU_CHECK_HP_MOD 9 42*00105882SYidi Lin #define EMI_CLE 10 43*00105882SYidi Lin #define SLC_PARITY_SELECT 11 44*00105882SYidi Lin #define SLC_PARITY_CLEAR 12 45*00105882SYidi Lin 46*00105882SYidi Lin static uint64_t emi_mpu_read_by_type(unsigned int reg_type, unsigned int region, 47*00105882SYidi Lin unsigned int aid_shift, struct smccc_res *smccc_ret) 48*00105882SYidi Lin { 49*00105882SYidi Lin switch (reg_type) { 50*00105882SYidi Lin case EMIMPU_READ_SA: 51*00105882SYidi Lin return emi_mpu_read_addr(region, 0x0); 52*00105882SYidi Lin case EMIMPU_READ_EA: 53*00105882SYidi Lin return emi_mpu_read_addr(region, 0x8); 54*00105882SYidi Lin case EMIMPU_READ_ENABLE: 55*00105882SYidi Lin return emi_mpu_read_enable(region); 56*00105882SYidi Lin case EMIMPU_READ_AID: 57*00105882SYidi Lin return emi_mpu_read_aid(region, aid_shift); 58*00105882SYidi Lin case EMIMPU_CHECK_REGION_INFO: 59*00105882SYidi Lin return emi_mpu_check_region_info(region, &smccc_ret->a1, &smccc_ret->a2); 60*00105882SYidi Lin case EMIMPU_CHECK_NS_CPU: 61*00105882SYidi Lin return emi_mpu_check_ns_cpu(); 62*00105882SYidi Lin case EMIMPU_PAGE_BASE_REGION: 63*00105882SYidi Lin return emi_mpu_page_base_region(); 64*00105882SYidi Lin case EMIMPU_CHECK_HP_MOD: 65*00105882SYidi Lin return emi_mpu_smc_hp_mod_check(); 66*00105882SYidi Lin default: 67*00105882SYidi Lin return 0; 68*00105882SYidi Lin } 69*00105882SYidi Lin } 70*00105882SYidi Lin 71*00105882SYidi Lin static u_register_t sip_emidbg_control(u_register_t op_id, 72*00105882SYidi Lin u_register_t x2, 73*00105882SYidi Lin u_register_t x3, 74*00105882SYidi Lin u_register_t x4, 75*00105882SYidi Lin void *handle, 76*00105882SYidi Lin struct smccc_res *smccc_ret) 77*00105882SYidi Lin { 78*00105882SYidi Lin enum mtk_bl31_status ret; 79*00105882SYidi Lin 80*00105882SYidi Lin switch (op_id) { 81*00105882SYidi Lin case EMIDBG_DUMP: 82*00105882SYidi Lin return MTK_SIP_E_SUCCESS; 83*00105882SYidi Lin case EMIDBG_MSG: 84*00105882SYidi Lin return MTK_SIP_E_SUCCESS; 85*00105882SYidi Lin #ifdef MTK_EMI_MPU_DEBUG 86*00105882SYidi Lin case EMIMPU_READ: 87*00105882SYidi Lin ret = emi_mpu_read_by_type((unsigned int)x2, (unsigned int)x3, 88*00105882SYidi Lin (unsigned int)x4, smccc_ret); 89*00105882SYidi Lin break; 90*00105882SYidi Lin #endif 91*00105882SYidi Lin case EMIMPU_CLEAR_MD: 92*00105882SYidi Lin ret = emi_clear_md_violation(); 93*00105882SYidi Lin break; 94*00105882SYidi Lin case KP_CLEAR: 95*00105882SYidi Lin ret = emi_kp_clear_violation((unsigned int)x2); 96*00105882SYidi Lin break; 97*00105882SYidi Lin #ifdef CONFIG_MTK_SLB_MPU_CLEAR 98*00105882SYidi Lin case SLBMPU_CLEAR: 99*00105882SYidi Lin ret = slb_clear_violation((unsigned int)x2); 100*00105882SYidi Lin break; 101*00105882SYidi Lin #endif 102*00105882SYidi Lin #ifdef CONFIG_MTK_EMI_CLEAR 103*00105882SYidi Lin case EMI_CLEAR: 104*00105882SYidi Lin ret = emi_clear_violation((unsigned int)x2, (unsigned int)x3); 105*00105882SYidi Lin break; 106*00105882SYidi Lin #endif 107*00105882SYidi Lin #ifdef CONFIG_MTK_SLC_PARITY 108*00105882SYidi Lin case SLC_PARITY_SELECT: 109*00105882SYidi Lin ret = slc_parity_select((unsigned int)x2, (unsigned int)x3); 110*00105882SYidi Lin break; 111*00105882SYidi Lin case SLC_PARITY_CLEAR: 112*00105882SYidi Lin ret = slc_parity_clear((unsigned int)x2); 113*00105882SYidi Lin break; 114*00105882SYidi Lin #endif 115*00105882SYidi Lin default: 116*00105882SYidi Lin return MTK_SIP_E_NOT_SUPPORTED; 117*00105882SYidi Lin } 118*00105882SYidi Lin 119*00105882SYidi Lin return mtk_bl31_map_to_sip_error(ret); 120*00105882SYidi Lin } 121*00105882SYidi Lin DECLARE_SMC_HANDLER(MTK_SIP_EMIDBG_CONTROL, sip_emidbg_control); 122*00105882SYidi Lin 123*00105882SYidi Lin static u_register_t sip_emimpu_control(u_register_t op_id, 124*00105882SYidi Lin u_register_t x2, 125*00105882SYidi Lin u_register_t x3, 126*00105882SYidi Lin u_register_t x4, 127*00105882SYidi Lin void *handle, 128*00105882SYidi Lin struct smccc_res *smccc_ret) 129*00105882SYidi Lin { 130*00105882SYidi Lin enum mtk_bl31_status ret; 131*00105882SYidi Lin 132*00105882SYidi Lin switch (op_id) { 133*00105882SYidi Lin case EMIMPU_SET: 134*00105882SYidi Lin ret = emi_mpu_set_protection((uint32_t)x2, (uint32_t)x3, (unsigned int)x4); 135*00105882SYidi Lin break; 136*00105882SYidi Lin case AID_TABLE_SET: 137*00105882SYidi Lin ret = emi_mpu_set_aid((unsigned int)x2, (unsigned int)x3); 138*00105882SYidi Lin break; 139*00105882SYidi Lin case EMIMPU_READ: 140*00105882SYidi Lin ret = emi_mpu_read_by_type((unsigned int)x2, (unsigned int)x3, 141*00105882SYidi Lin (unsigned int)x4, smccc_ret); 142*00105882SYidi Lin break; 143*00105882SYidi Lin case KP_SET: 144*00105882SYidi Lin ret = emi_kp_set_protection((size_t)x2, (size_t)x3, (unsigned int)x4); 145*00105882SYidi Lin break; 146*00105882SYidi Lin case KP_CLEAR: 147*00105882SYidi Lin ret = emi_kp_clear_violation((unsigned int)x2); 148*00105882SYidi Lin break; 149*00105882SYidi Lin default: 150*00105882SYidi Lin return MTK_SIP_E_NOT_SUPPORTED; 151*00105882SYidi Lin } 152*00105882SYidi Lin 153*00105882SYidi Lin return mtk_bl31_map_to_sip_error(ret); 154*00105882SYidi Lin } 155*00105882SYidi Lin DECLARE_SMC_HANDLER(MTK_SIP_BL_EMIMPU_CONTROL, sip_emimpu_control); 156*00105882SYidi Lin 157*00105882SYidi Lin static u_register_t sip_tee_emimpu_control(u_register_t op_id, 158*00105882SYidi Lin u_register_t x2, 159*00105882SYidi Lin u_register_t x3, 160*00105882SYidi Lin u_register_t x4, 161*00105882SYidi Lin void *handle, 162*00105882SYidi Lin struct smccc_res *smccc_ret) 163*00105882SYidi Lin { 164*00105882SYidi Lin enum mtk_bl31_status ret; 165*00105882SYidi Lin 166*00105882SYidi Lin switch (op_id) { 167*00105882SYidi Lin case EMIMPU_SET: 168*00105882SYidi Lin ret = emi_mpu_set_protection((uint32_t)x2, (uint32_t)x3, (unsigned int)x4); 169*00105882SYidi Lin break; 170*00105882SYidi Lin case EMIMPU_CLEAR: 171*00105882SYidi Lin ret = emi_clear_protection((unsigned int)x2); 172*00105882SYidi Lin break; 173*00105882SYidi Lin default: 174*00105882SYidi Lin return MTK_SIP_E_NOT_SUPPORTED; 175*00105882SYidi Lin } 176*00105882SYidi Lin 177*00105882SYidi Lin return mtk_bl31_map_to_sip_error(ret); 178*00105882SYidi Lin } 179*00105882SYidi Lin DECLARE_SMC_HANDLER(MTK_SIP_TEE_EMI_MPU_CONTROL, sip_tee_emimpu_control); 180*00105882SYidi Lin 181*00105882SYidi Lin int emi_mpu_init(void) 182*00105882SYidi Lin { 183*00105882SYidi Lin INFO("[%s] emi mpu initialization\n", __func__); 184*00105882SYidi Lin 185*00105882SYidi Lin emi_protection_init(); 186*00105882SYidi Lin 187*00105882SYidi Lin return 0; 188*00105882SYidi Lin } 189*00105882SYidi Lin MTK_PLAT_SETUP_0_INIT(emi_mpu_init); 190