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