xref: /rk3399_ARM-atf/plat/mediatek/drivers/apusys/apusys_rv/2.0/apusys_rv.c (revision 5e5c57d52b1cfaec5182b2d01f804fae9ed54af4)
1 /*
2  * Copyright (c) 2023-2024, MediaTek Inc. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <errno.h>
8 
9 /* TF-A system header */
10 #include <common/debug.h>
11 #include <drivers/delay_timer.h>
12 #include <lib/mmio.h>
13 #include <lib/spinlock.h>
14 
15 /* Vendor header */
16 #include "apusys.h"
17 #include "apusys_rv.h"
18 #include "apusys_rv_mbox_mpu.h"
19 #include "apusys_rv_pwr_ctrl.h"
20 #include "apusys_rv_sec_info.h"
21 #ifdef CONFIG_MTK_APUSYS_SEC_CTRL
22 #include "apusys_security_ctrl_perm.h"
23 #endif
24 #include "apusys_security_ctrl_plat.h"
25 #include "emi_mpu.h"
26 #include <mtk_mmap_pool.h>
27 #include <mtk_sip_svc.h>
28 
29 #ifdef CONFIG_MTK_APUSYS_RV_APUMMU_SUPPORT
30 #include "apusys_ammu.h"
31 #endif
32 
33 static spinlock_t apusys_rv_lock;
34 
35 void apusys_rv_mbox_mpu_init(void)
36 {
37 	int i;
38 
39 	for (i = 0; i < APU_MBOX_NUM; i++) {
40 		mmio_write_32(APU_MBOX_FUNC_CFG(i),
41 			      (MBOX_CTRL_LOCK |
42 			       (mbox_mpu_setting_tab[i].no_mpu << MBOX_NO_MPU_SHIFT)));
43 		mmio_write_32(APU_MBOX_DOMAIN_CFG(i),
44 			      (MBOX_CTRL_LOCK |
45 			       (mbox_mpu_setting_tab[i].rx_ns << MBOX_RX_NS_SHIFT) |
46 			       (mbox_mpu_setting_tab[i].rx_domain << MBOX_RX_DOMAIN_SHIFT) |
47 			       (mbox_mpu_setting_tab[i].tx_ns << MBOX_TX_NS_SHIFT) |
48 			       (mbox_mpu_setting_tab[i].tx_domain << MBOX_TX_DOMAIN_SHIFT)));
49 	}
50 }
51 
52 int apusys_kernel_apusys_rv_setup_reviser(void)
53 {
54 	spin_lock(&apusys_rv_lock);
55 
56 	mmio_write_32(USERFW_CTXT, CFG_4GB_SEL_EN | CFG_4GB_SEL);
57 	mmio_write_32(SECUREFW_CTXT, CFG_4GB_SEL_EN | CFG_4GB_SEL);
58 
59 	mmio_write_32(UP_IOMMU_CTRL, MMU_CTRL_LOCK | MMU_CTRL | MMU_EN);
60 
61 	mmio_write_32(UP_NORMAL_DOMAIN_NS,
62 		      (UP_NORMAL_DOMAIN << UP_DOMAIN_SHIFT) | (UP_NORMAL_NS << UP_NS_SHIFT));
63 	mmio_write_32(UP_PRI_DOMAIN_NS,
64 		      (UP_PRI_DOMAIN << UP_DOMAIN_SHIFT) | (UP_PRI_NS << UP_NS_SHIFT));
65 
66 	mmio_write_32(UP_CORE0_VABASE0,
67 		      VLD | PARTIAL_ENABLE | (THREAD_NUM_PRI << THREAD_NUM_SHIFT));
68 	mmio_write_32(UP_CORE0_MVABASE0, VASIZE_1MB | (APU_SEC_FW_IOVA >> MVA_34BIT_SHIFT));
69 
70 	mmio_write_32(UP_CORE0_VABASE1,
71 		      VLD | PARTIAL_ENABLE | (THREAD_NUM_NORMAL << THREAD_NUM_SHIFT));
72 	mmio_write_32(UP_CORE0_MVABASE1, VASIZE_1MB | (APU_SEC_FW_IOVA >> MVA_34BIT_SHIFT));
73 
74 	spin_unlock(&apusys_rv_lock);
75 
76 	return 0;
77 }
78 
79 int apusys_kernel_apusys_rv_reset_mp(void)
80 {
81 	spin_lock(&apusys_rv_lock);
82 
83 	mmio_write_32(MD32_SYS_CTRL, MD32_SYS_CTRL_RST);
84 
85 	dsb();
86 	udelay(RESET_DEALY_US);
87 
88 	mmio_write_32(MD32_SYS_CTRL, MD32_G2B_CG_EN | MD32_DBG_EN | MD32_DM_AWUSER_IOMMU_EN |
89 		      MD32_DM_ARUSER_IOMMU_EN | MD32_PM_AWUSER_IOMMU_EN | MD32_PM_ARUSER_IOMMU_EN |
90 		      MD32_SOFT_RSTN);
91 
92 	mmio_write_32(MD32_CLK_CTRL, MD32_CLK_EN);
93 	mmio_write_32(UP_WAKE_HOST_MASK0, WDT_IRQ_EN);
94 	mmio_write_32(UP_WAKE_HOST_MASK1, MBOX0_IRQ_EN | MBOX1_IRQ_EN | MBOX2_IRQ_EN);
95 
96 	spin_unlock(&apusys_rv_lock);
97 
98 	return 0;
99 }
100 
101 int apusys_kernel_apusys_rv_setup_boot(void)
102 {
103 	spin_lock(&apusys_rv_lock);
104 
105 	mmio_write_32(MD32_BOOT_CTRL, APU_SEC_FW_IOVA);
106 
107 	mmio_write_32(MD32_PRE_DEFINE, (PREDEFINE_CACHE_TCM << PREDEF_1G_OFS) |
108 		      (PREDEFINE_CACHE << PREDEF_2G_OFS) | (PREDEFINE_CACHE << PREDEF_3G_OFS) |
109 		      (PREDEFINE_CACHE << PREDEF_4G_OFS));
110 
111 	apusys_infra_dcm_setup();
112 
113 	spin_unlock(&apusys_rv_lock);
114 	return 0;
115 }
116 
117 int apusys_kernel_apusys_rv_start_mp(void)
118 {
119 	spin_lock(&apusys_rv_lock);
120 	mmio_write_32(MD32_RUNSTALL, MD32_RUN);
121 	spin_unlock(&apusys_rv_lock);
122 
123 	return 0;
124 }
125 
126 static int hw_sema2_release(uint32_t timeout)
127 {
128 #ifdef CONFIG_MTK_APUSYS_RV_COREDUMP_WA_SUPPORT
129 	int ret;
130 
131 	ret = apu_hw_sema_ctl(HW_SEMA2, HW_SEMA_USER, 0, timeout, 0);
132 	if (ret) {
133 		ERROR("%s: HW semaphore release timeout\n", __func__);
134 	}
135 
136 	return ret;
137 #else
138 	return 0;
139 #endif
140 }
141 
142 static int hw_sema2_acquire(uint32_t timeout)
143 {
144 #ifdef CONFIG_MTK_APUSYS_RV_COREDUMP_WA_SUPPORT
145 	int ret;
146 
147 	ret = apu_hw_sema_ctl(HW_SEMA2, HW_SEMA_USER, 1, timeout, 0);
148 	if (ret) {
149 		ERROR("%s: HW semaphore acquire timeout\n", __func__);
150 	}
151 
152 	return ret;
153 #else
154 	return 0;
155 #endif
156 }
157 
158 int apusys_kernel_apusys_rv_stop_mp(void)
159 {
160 	int ret;
161 
162 	ret = hw_sema2_acquire(HW_SEM_TIMEOUT);
163 	if (ret)
164 		return ret;
165 
166 	spin_lock(&apusys_rv_lock);
167 	mmio_write_32(MD32_RUNSTALL, MD32_STALL);
168 	spin_unlock(&apusys_rv_lock);
169 
170 	ret = hw_sema2_release(HW_SEM_TIMEOUT);
171 
172 	return ret;
173 }
174 
175 int apusys_kernel_apusys_rv_setup_sec_mem(void)
176 {
177 	int ret;
178 
179 	spin_lock(&apusys_rv_lock);
180 
181 	ret = set_apu_emi_mpu_region();
182 	if (ret != 0) {
183 		ERROR(MODULE_TAG "%s: set emimpu protection failed\n", __func__);
184 	}
185 
186 	spin_unlock(&apusys_rv_lock);
187 	return ret;
188 }
189 
190 int apusys_kernel_apusys_rv_disable_wdt_isr(void)
191 {
192 	int ret;
193 
194 	ret = hw_sema2_acquire(0);
195 	if (ret)
196 		return ret;
197 
198 	spin_lock(&apusys_rv_lock);
199 	mmio_clrbits_32(WDT_CTRL0, WDT_EN);
200 	spin_unlock(&apusys_rv_lock);
201 
202 	ret = hw_sema2_release(0);
203 
204 	return ret;
205 }
206 
207 int apusys_kernel_apusys_rv_clear_wdt_isr(void)
208 {
209 	int ret;
210 
211 	ret = hw_sema2_acquire(HW_SEM_TIMEOUT);
212 	if (ret)
213 		return ret;
214 
215 	spin_lock(&apusys_rv_lock);
216 	mmio_clrbits_32(UP_INT_EN2, DBG_APB_EN);
217 	mmio_write_32(WDT_INT, WDT_INT_W1C);
218 	spin_unlock(&apusys_rv_lock);
219 
220 	ret = hw_sema2_release(HW_SEM_TIMEOUT);
221 
222 	return ret;
223 }
224 
225 int apusys_kernel_apusys_rv_cg_gating(void)
226 {
227 	int ret;
228 
229 	ret = hw_sema2_acquire(HW_SEM_TIMEOUT);
230 	if (ret)
231 		return ret;
232 
233 	spin_lock(&apusys_rv_lock);
234 	mmio_write_32(MD32_CLK_CTRL, MD32_CLK_DIS);
235 	spin_unlock(&apusys_rv_lock);
236 
237 	ret = hw_sema2_release(HW_SEM_TIMEOUT);
238 
239 	return ret;
240 }
241 
242 int apusys_kernel_apusys_rv_cg_ungating(void)
243 {
244 	int ret;
245 
246 	ret = hw_sema2_acquire(HW_SEM_TIMEOUT);
247 	if (ret)
248 		return ret;
249 
250 	spin_lock(&apusys_rv_lock);
251 	mmio_write_32(MD32_CLK_CTRL, MD32_CLK_EN);
252 	spin_unlock(&apusys_rv_lock);
253 
254 	ret = hw_sema2_release(HW_SEM_TIMEOUT);
255 
256 	return ret;
257 }
258 
259 int apusys_kernel_apusys_rv_setup_apummu(void)
260 {
261 	spin_lock(&apusys_rv_lock);
262 
263 #ifdef CONFIG_MTK_APUSYS_SEC_CTRL
264 	sec_set_rv_dns();
265 #endif
266 
267 #ifdef CONFIG_MTK_APUSYS_RV_APUMMU_SUPPORT
268 	uint32_t apummu_tcm_sz_select = 0;
269 
270 	if (APU_MD32_TCM_SZ <= 0x20000)
271 		apummu_tcm_sz_select = APUMMU_PAGE_LEN_128KB;
272 	else if (APU_MD32_TCM_SZ <= 0x40000)
273 		apummu_tcm_sz_select = APUMMU_PAGE_LEN_256KB;
274 	else if (APU_MD32_TCM_SZ <= 0x80000)
275 		apummu_tcm_sz_select = APUMMU_PAGE_LEN_512KB;
276 	else if (APU_MD32_TCM_SZ <= 0x100000)
277 		apummu_tcm_sz_select = APUMMU_PAGE_LEN_1MB;
278 	else {
279 		ERROR("%s: APU_MD32_TCM_SZ = 0x%x > 1MB", __func__, APU_MD32_TCM_SZ);
280 		spin_unlock(&apusys_rv_lock);
281 		return -EINVAL;
282 	}
283 
284 	INFO("%s: apummu_tcm_sz_select = %u\n", __func__, apummu_tcm_sz_select);
285 	rv_boot(APU_SEC_FW_IOVA, 0, APUMMU_PAGE_LEN_1MB,
286 		APU_MD32_TCM, apummu_tcm_sz_select);
287 #endif
288 
289 	spin_unlock(&apusys_rv_lock);
290 	return 0;
291 }
292 
293 int apusys_kernel_apusys_rv_pwr_ctrl(enum APU_PWR_OP op)
294 {
295 	return apusys_rv_pwr_ctrl(op);
296 }
297 
298 #ifdef CONFIG_MTK_APUSYS_LOGTOP_SUPPORT
299 int apusys_kernel_apusys_logtop_reg_dump(uint32_t op, struct smccc_res *smccc_ret)
300 {
301 	int ret = 0;
302 	uint8_t smc_op;
303 	uint32_t reg_addr[MAX_SMC_OP_NUM];
304 	uint32_t i;
305 
306 	if (op == 0) {
307 		ERROR("%s empty op = 0x%08x\n", MODULE_TAG, op);
308 		return -EINVAL;
309 	}
310 
311 	for (i = 0; i < MAX_SMC_OP_NUM; i++) {
312 		smc_op = (op >> (LOGTOP_OP_SHIFT * i)) & LOGTOP_OP_MASK;
313 		switch (smc_op) {
314 		case SMC_OP_APU_LOG_BUF_NULL:
315 			reg_addr[i] = 0x0;
316 			break;
317 		case SMC_OP_APU_LOG_BUF_T_SIZE:
318 			reg_addr[i] = APU_LOG_BUF_T_SIZE;
319 			break;
320 		case SMC_OP_APU_LOG_BUF_W_PTR:
321 			reg_addr[i] = APU_LOG_BUF_W_PTR;
322 			break;
323 		case SMC_OP_APU_LOG_BUF_R_PTR:
324 			reg_addr[i] = APU_LOG_BUF_R_PTR;
325 			break;
326 		case SMC_OP_APU_LOG_BUF_CON:
327 			reg_addr[i] = APU_LOGTOP_CON;
328 			break;
329 		default:
330 			ERROR("%s unknown op = 0x%08x\n", MODULE_TAG, smc_op);
331 			return -EINVAL;
332 		}
333 	}
334 
335 	ret = apu_hw_sema_ctl(HW_SEMA2, HW_SEMA_LOGGER_USER, 1, 0, 0);
336 	if (ret)
337 		return ret;
338 
339 	for (i = 0; i < MAX_SMC_OP_NUM; i++) {
340 		if (reg_addr[i] == 0)
341 			continue;
342 
343 		switch (i) {
344 		case 0:
345 			smccc_ret->a1 = mmio_read_32(reg_addr[i]);
346 			break;
347 		case 1:
348 			smccc_ret->a2 = mmio_read_32(reg_addr[i]);
349 			break;
350 		case 2:
351 			smccc_ret->a3 = mmio_read_32(reg_addr[i]);
352 			break;
353 		}
354 	}
355 
356 	ret = apu_hw_sema_ctl(HW_SEMA2, HW_SEMA_LOGGER_USER, 0, 0, 0);
357 	if (ret)
358 		ERROR("%s(%d): sem release timeout\n", __func__, op);
359 
360 	return ret;
361 }
362 
363 static int apusys_kernel_apusys_logtop_reg_rw(uint32_t op, uint32_t write_val,
364 					      bool w1c, struct smccc_res *smccc_ret)
365 {
366 	int ret = 0;
367 	uint32_t reg_addr = 0, reg_val = 0;
368 
369 	switch (op) {
370 	case SMC_OP_APU_LOG_BUF_R_PTR:
371 		reg_addr = APU_LOG_BUF_R_PTR;
372 		break;
373 	case SMC_OP_APU_LOG_BUF_CON:
374 		reg_addr = APU_LOGTOP_CON;
375 		break;
376 	default:
377 		ERROR("%s unknown or not support op = %x\n", MODULE_TAG, op);
378 		return -EINVAL;
379 	}
380 
381 	ret = apu_hw_sema_ctl(HW_SEMA2, HW_SEMA_LOGGER_USER, 1, 0, 0);
382 	if (ret)
383 		return ret;
384 
385 	if (w1c) {
386 		reg_val = mmio_read_32(reg_addr);
387 		mmio_write_32(reg_addr, reg_val);
388 		smccc_ret->a1 = reg_val;
389 	} else {
390 		mmio_write_32(reg_addr, write_val);
391 	}
392 
393 	ret = apu_hw_sema_ctl(HW_SEMA2, HW_SEMA_LOGGER_USER, 0, 0, 0);
394 	if (ret)
395 		ERROR("%s(%d): sem release timeout\n", __func__, op);
396 
397 	return ret;
398 }
399 
400 int apusys_kernel_apusys_logtop_reg_write(uint32_t op, uint32_t write_val,
401 					  struct smccc_res *smccc_ret)
402 {
403 	return apusys_kernel_apusys_logtop_reg_rw(op, write_val, false, smccc_ret);
404 }
405 
406 int apusys_kernel_apusys_logtop_reg_w1c(uint32_t op, struct smccc_res *smccc_ret)
407 {
408 	return apusys_kernel_apusys_logtop_reg_rw(op, 0, true, smccc_ret);
409 }
410 
411 #endif /* CONFIG_MTK_APUSYS_LOGTOP_SUPPORT */
412 
413 int apusys_rv_cold_boot_clr_mbox_dummy(void)
414 {
415 #ifdef SUPPORT_APU_CLEAR_MBOX_DUMMY
416 	mmio_write_32(APU_MBOX(APU_HW_SEM_SYS_APMCU) + APU_MBOX_DUMMY, 0);
417 #else
418 	WARN("Not support clear mbox dummy on this platform\n");
419 #endif
420 	return 0;
421 }
422 
423 int apusys_rv_setup_ce_bin(void)
424 {
425 #ifdef CONFIG_MTK_APUSYS_CE_SUPPORT
426 	uintptr_t apusys_rv_sec_buf_pa;
427 	struct apusys_secure_info_t *apusys_secure_info;
428 	struct ce_main_hdr_t *ce_main_hdr;
429 	struct ce_sub_hdr_t *ce_sub_hdr;
430 	unsigned int cnt, i, reg_val;
431 	uint64_t ce_sub_hdr_bin;
432 	int ret;
433 
434 	apusys_rv_sec_buf_pa = APU_RESERVE_MEMORY;
435 	/* create mapping */
436 	ret = mmap_add_dynamic_region(apusys_rv_sec_buf_pa, apusys_rv_sec_buf_pa,
437 				      round_up(APU_RESERVE_SIZE, PAGE_SIZE),
438 				      MT_MEMORY | MT_RW | MT_NS);
439 	if (ret) {
440 		ERROR("%s: mmap_add_dynamic_region() fail, ret=0x%x\n", __func__, ret);
441 		return ret;
442 	}
443 
444 	apusys_secure_info = (struct apusys_secure_info_t *)
445 				(apusys_rv_sec_buf_pa + APU_SEC_INFO_OFFSET);
446 
447 	ce_main_hdr = (struct ce_main_hdr_t *)(apusys_rv_sec_buf_pa +
448 		apusys_secure_info->ce_bin_ofs);
449 	ce_sub_hdr = (struct ce_sub_hdr_t *)((uintptr_t)ce_main_hdr + ce_main_hdr->hdr_size);
450 
451 	if (ce_main_hdr->magic != CE_MAIN_MAGIC) {
452 		ERROR("%s: invalid header\n", __func__);
453 		return -EINVAL;
454 	}
455 
456 	cnt = 0;
457 
458 	while (ce_sub_hdr->magic == CE_SUB_MAGIC && cnt < ce_main_hdr->bin_count) {
459 		VERBOSE("%s: job (%d), magic (0x%x)\n", __func__,
460 			ce_sub_hdr->ce_enum, ce_sub_hdr->magic);
461 
462 		ce_sub_hdr_bin = (uint64_t)ce_sub_hdr + ce_sub_hdr->bin_offset;
463 
464 		for (i = 0; i < ce_sub_hdr->bin_size; i += sizeof(uint32_t)) {
465 			reg_val = *(uint32_t *)(ce_sub_hdr_bin + i);
466 			mmio_write_32(ce_sub_hdr->mem_st + i, reg_val);
467 		}
468 
469 		if (ce_sub_hdr->hw_entry) {
470 			mmio_clrsetbits_32(ce_sub_hdr->hw_entry,
471 					   ce_sub_hdr->hw_entry_mask << ce_sub_hdr->hw_entry_bit,
472 					   (ce_sub_hdr->hw_entry_val & ce_sub_hdr->hw_entry_mask)
473 					   << ce_sub_hdr->hw_entry_bit);
474 		}
475 
476 		ce_sub_hdr = (struct ce_sub_hdr_t *)(ce_sub_hdr_bin + ce_sub_hdr->bin_size);
477 		cnt++;
478 	}
479 
480 	mmap_remove_dynamic_region(apusys_rv_sec_buf_pa,
481 				   round_up(APU_RESERVE_SIZE, PAGE_SIZE));
482 
483 	INFO("%s: setup CE binary done\n", __func__);
484 #else
485 	WARN("Not support CE on this platform\n");
486 #endif
487 	return 0;
488 }
489