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
emi_mpu_read_by_type(unsigned int reg_type,unsigned int region,unsigned int aid_shift,struct smccc_res * smccc_ret)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
sip_emidbg_control(u_register_t op_id,u_register_t x2,u_register_t x3,u_register_t x4,void * handle,struct smccc_res * smccc_ret)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
sip_emimpu_control(u_register_t op_id,u_register_t x2,u_register_t x3,u_register_t x4,void * handle,struct smccc_res * smccc_ret)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
sip_tee_emimpu_control(u_register_t op_id,u_register_t x2,u_register_t x3,u_register_t x4,void * handle,struct smccc_res * smccc_ret)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
emi_mpu_init(void)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