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