Merge changes Ic746571b,I1926cab9,Id70162e9,I3a9b014e,Ic99adba1, ... into integration
* changes:
feat(mt8196): enable APU on mt8196
feat(mt8196): add APU SMMU hardware semaphore operations
feat(mt8196): add smpu protection for APU secure memory
feat(mt8196): add APU RCX DevAPC setting
feat(mt8196): add APU kernel control operations
feat(mt8196): add APU power on/off functions
feat(mt8196): add APUMMU setting
feat(mt8196): enable apusys mailbox mpu protection
feat(mt8196): enable apusys security control
feat(mt8196): add APUSYS AO DevAPC setting
feat(mt8196): add APU power-on init flow
diff --git a/plat/mediatek/drivers/apusys/apusys.c b/plat/mediatek/drivers/apusys/apusys.c
index dfe1dcf..87e8960 100644
--- a/plat/mediatek/drivers/apusys/apusys.c
+++ b/plat/mediatek/drivers/apusys/apusys.c
@@ -30,10 +30,10 @@
switch (request_ops) {
case MTK_APUSYS_KERNEL_OP_APUSYS_PWR_TOP_ON:
- ret = apusys_kernel_apusys_pwr_top_on();
+ ret = apusys_kernel_apusys_rv_pwr_ctrl(APU_PWR_ON);
break;
case MTK_APUSYS_KERNEL_OP_APUSYS_PWR_TOP_OFF:
- ret = apusys_kernel_apusys_pwr_top_off();
+ ret = apusys_kernel_apusys_rv_pwr_ctrl(APU_PWR_OFF);
break;
case MTK_APUSYS_KERNEL_OP_APUSYS_RV_SETUP_REVISER:
ret = apusys_kernel_apusys_rv_setup_reviser();
@@ -68,6 +68,27 @@
case MTK_APUSYS_KERNEL_OP_APUSYS_RV_CG_UNGATING:
ret = apusys_kernel_apusys_rv_cg_ungating();
break;
+ case MTK_APUSYS_KERNEL_OP_APUSYS_RV_SETUP_APUMMU:
+ ret = apusys_kernel_apusys_rv_setup_apummu();
+ break;
+#ifdef CONFIG_MTK_APUSYS_LOGTOP_SUPPORT
+ case MTK_APUSYS_KERNEL_OP_APUSYS_LOGTOP_REG_DUMP:
+ ret = apusys_kernel_apusys_logtop_reg_dump((uint32_t)x2, smccc_ret);
+ break;
+ case MTK_APUSYS_KERNEL_OP_APUSYS_LOGTOP_REG_WRITE:
+ ret = apusys_kernel_apusys_logtop_reg_write((uint32_t)x2, (uint32_t)x3,
+ smccc_ret);
+ break;
+ case MTK_APUSYS_KERNEL_OP_APUSYS_LOGTOP_REG_W1C:
+ ret = apusys_kernel_apusys_logtop_reg_w1c((uint32_t)x2, smccc_ret);
+ break;
+#endif
+ case MTK_APUSYS_KERNEL_OP_APUSYS_COLD_BOOT_CLR_MBOX_DUMMY:
+ ret = apusys_rv_cold_boot_clr_mbox_dummy();
+ break;
+ case MTK_APUSYS_KERNEL_OP_APUSYS_SETUP_CE_BIN:
+ ret = apusys_rv_setup_ce_bin();
+ break;
default:
ERROR(MODULE_TAG "%s unknown request_ops = %x\n", MODULE_TAG, request_ops);
break;
diff --git a/plat/mediatek/drivers/apusys/apusys.h b/plat/mediatek/drivers/apusys/apusys.h
index ed4e195..709379e 100644
--- a/plat/mediatek/drivers/apusys/apusys.h
+++ b/plat/mediatek/drivers/apusys/apusys.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, MediaTek Inc. All rights reserved.
+ * Copyright (c) 2023-2024, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -10,19 +10,25 @@
#define MODULE_TAG "[APUSYS]"
enum MTK_APUSYS_KERNEL_OP {
- MTK_APUSYS_KERNEL_OP_APUSYS_PWR_TOP_ON, /* 0 */
- MTK_APUSYS_KERNEL_OP_APUSYS_PWR_TOP_OFF, /* 1 */
- MTK_APUSYS_KERNEL_OP_APUSYS_RV_SETUP_REVISER, /* 2 */
- MTK_APUSYS_KERNEL_OP_APUSYS_RV_RESET_MP, /* 3 */
- MTK_APUSYS_KERNEL_OP_APUSYS_RV_SETUP_BOOT, /* 4 */
- MTK_APUSYS_KERNEL_OP_APUSYS_RV_START_MP, /* 5 */
- MTK_APUSYS_KERNEL_OP_APUSYS_RV_STOP_MP, /* 6 */
- MTK_APUSYS_KERNEL_OP_DEVAPC_INIT_RCX, /* 7 */
- MTK_APUSYS_KERNEL_OP_APUSYS_RV_SETUP_SEC_MEM, /* 8 */
- MTK_APUSYS_KERNEL_OP_APUSYS_RV_DISABLE_WDT_ISR, /* 9 */
- MTK_APUSYS_KERNEL_OP_APUSYS_RV_CLEAR_WDT_ISR, /* 10 */
- MTK_APUSYS_KERNEL_OP_APUSYS_RV_CG_GATING, /* 11 */
- MTK_APUSYS_KERNEL_OP_APUSYS_RV_CG_UNGATING, /* 12 */
+ MTK_APUSYS_KERNEL_OP_APUSYS_PWR_TOP_ON, /* 0 */
+ MTK_APUSYS_KERNEL_OP_APUSYS_PWR_TOP_OFF, /* 1 */
+ MTK_APUSYS_KERNEL_OP_APUSYS_RV_SETUP_REVISER, /* 2 */
+ MTK_APUSYS_KERNEL_OP_APUSYS_RV_RESET_MP, /* 3 */
+ MTK_APUSYS_KERNEL_OP_APUSYS_RV_SETUP_BOOT, /* 4 */
+ MTK_APUSYS_KERNEL_OP_APUSYS_RV_START_MP, /* 5 */
+ MTK_APUSYS_KERNEL_OP_APUSYS_RV_STOP_MP, /* 6 */
+ MTK_APUSYS_KERNEL_OP_DEVAPC_INIT_RCX, /* 7 */
+ MTK_APUSYS_KERNEL_OP_APUSYS_RV_SETUP_SEC_MEM, /* 8 */
+ MTK_APUSYS_KERNEL_OP_APUSYS_RV_DISABLE_WDT_ISR, /* 9 */
+ MTK_APUSYS_KERNEL_OP_APUSYS_RV_CLEAR_WDT_ISR, /* 10 */
+ MTK_APUSYS_KERNEL_OP_APUSYS_RV_CG_GATING, /* 11 */
+ MTK_APUSYS_KERNEL_OP_APUSYS_RV_CG_UNGATING, /* 12 */
+ MTK_APUSYS_KERNEL_OP_APUSYS_RV_SETUP_APUMMU, /* 13 */
+ MTK_APUSYS_KERNEL_OP_APUSYS_LOGTOP_REG_DUMP, /* 14 */
+ MTK_APUSYS_KERNEL_OP_APUSYS_LOGTOP_REG_WRITE, /* 15 */
+ MTK_APUSYS_KERNEL_OP_APUSYS_LOGTOP_REG_W1C, /* 16 */
+ MTK_APUSYS_KERNEL_OP_APUSYS_COLD_BOOT_CLR_MBOX_DUMMY, /* 17 */
+ MTK_APUSYS_KERNEL_OP_APUSYS_SETUP_CE_BIN, /* 18 */
MTK_APUSYS_KERNEL_OP_NUM,
};
diff --git a/plat/mediatek/drivers/apusys/apusys_rv/2.0/apusys_rv.c b/plat/mediatek/drivers/apusys/apusys_rv/2.0/apusys_rv.c
index cb57668..a9eebb5 100644
--- a/plat/mediatek/drivers/apusys/apusys_rv/2.0/apusys_rv.c
+++ b/plat/mediatek/drivers/apusys/apusys_rv/2.0/apusys_rv.c
@@ -1,9 +1,11 @@
/*
- * Copyright (c) 2023, MediaTek Inc. All rights reserved.
+ * Copyright (c) 2023-2024, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <errno.h>
+
/* TF-A system header */
#include <common/debug.h>
#include <drivers/delay_timer.h>
@@ -14,7 +16,19 @@
#include "apusys.h"
#include "apusys_rv.h"
#include "apusys_rv_mbox_mpu.h"
-#include "emi_mpu.h"
+#include "apusys_rv_pwr_ctrl.h"
+#include "apusys_rv_sec_info.h"
+#ifdef CONFIG_MTK_APUSYS_SEC_CTRL
+#include "apusys_security_ctrl_perm.h"
+#endif
+#include "apusys_security_ctrl_plat.h"
+#include <drivers/apusys_rv_public.h>
+#include <mtk_mmap_pool.h>
+#include <mtk_sip_svc.h>
+
+#ifdef CONFIG_MTK_APUSYS_RV_APUMMU_SUPPORT
+#include "apusys_ammu.h"
+#endif
static spinlock_t apusys_rv_lock;
@@ -94,6 +108,8 @@
(PREDEFINE_CACHE << PREDEF_2G_OFS) | (PREDEFINE_CACHE << PREDEF_3G_OFS) |
(PREDEFINE_CACHE << PREDEF_4G_OFS));
+ apusys_infra_dcm_setup();
+
spin_unlock(&apusys_rv_lock);
return 0;
}
@@ -104,28 +120,67 @@
mmio_write_32(MD32_RUNSTALL, MD32_RUN);
spin_unlock(&apusys_rv_lock);
+ return 0;
+}
+
+static int hw_sema2_release(uint32_t timeout)
+{
+#ifdef CONFIG_MTK_APUSYS_RV_COREDUMP_WA_SUPPORT
+ int ret;
+
+ ret = apu_hw_sema_ctl(HW_SEMA2, HW_SEMA_USER, 0, timeout, 0);
+ if (ret) {
+ ERROR("%s: HW semaphore release timeout\n", __func__);
+ }
+
+ return ret;
+#else
+ return 0;
+#endif
+}
+
+static int hw_sema2_acquire(uint32_t timeout)
+{
+#ifdef CONFIG_MTK_APUSYS_RV_COREDUMP_WA_SUPPORT
+ int ret;
+
+ ret = apu_hw_sema_ctl(HW_SEMA2, HW_SEMA_USER, 1, timeout, 0);
+ if (ret) {
+ ERROR("%s: HW semaphore acquire timeout\n", __func__);
+ }
+
+ return ret;
+#else
return 0;
+#endif
}
int apusys_kernel_apusys_rv_stop_mp(void)
{
+ int ret;
+
+ ret = hw_sema2_acquire(HW_SEM_TIMEOUT);
+ if (ret)
+ return ret;
+
spin_lock(&apusys_rv_lock);
mmio_write_32(MD32_RUNSTALL, MD32_STALL);
spin_unlock(&apusys_rv_lock);
- return 0;
+ ret = hw_sema2_release(HW_SEM_TIMEOUT);
+
+ return ret;
}
int apusys_kernel_apusys_rv_setup_sec_mem(void)
{
- int ret;
+ int ret = 0;
spin_lock(&apusys_rv_lock);
- ret = set_apu_emi_mpu_region();
- if (ret != 0) {
+ ret = apusys_plat_setup_sec_mem();
+ if (ret != 0)
ERROR(MODULE_TAG "%s: set emimpu protection failed\n", __func__);
- }
spin_unlock(&apusys_rv_lock);
return ret;
@@ -133,37 +188,312 @@
int apusys_kernel_apusys_rv_disable_wdt_isr(void)
{
+ int ret;
+
+ ret = hw_sema2_acquire(0);
+ if (ret)
+ return ret;
+
spin_lock(&apusys_rv_lock);
mmio_clrbits_32(WDT_CTRL0, WDT_EN);
spin_unlock(&apusys_rv_lock);
- return 0;
+ ret = hw_sema2_release(0);
+
+ return ret;
}
int apusys_kernel_apusys_rv_clear_wdt_isr(void)
{
+ int ret;
+
+ ret = hw_sema2_acquire(HW_SEM_TIMEOUT);
+ if (ret)
+ return ret;
+
spin_lock(&apusys_rv_lock);
mmio_clrbits_32(UP_INT_EN2, DBG_APB_EN);
mmio_write_32(WDT_INT, WDT_INT_W1C);
spin_unlock(&apusys_rv_lock);
- return 0;
+ ret = hw_sema2_release(HW_SEM_TIMEOUT);
+
+ return ret;
}
int apusys_kernel_apusys_rv_cg_gating(void)
{
+ int ret;
+
+ ret = hw_sema2_acquire(HW_SEM_TIMEOUT);
+ if (ret)
+ return ret;
+
spin_lock(&apusys_rv_lock);
mmio_write_32(MD32_CLK_CTRL, MD32_CLK_DIS);
spin_unlock(&apusys_rv_lock);
- return 0;
+ ret = hw_sema2_release(HW_SEM_TIMEOUT);
+
+ return ret;
}
int apusys_kernel_apusys_rv_cg_ungating(void)
{
+ int ret;
+
+ ret = hw_sema2_acquire(HW_SEM_TIMEOUT);
+ if (ret)
+ return ret;
+
spin_lock(&apusys_rv_lock);
mmio_write_32(MD32_CLK_CTRL, MD32_CLK_EN);
spin_unlock(&apusys_rv_lock);
+
+ ret = hw_sema2_release(HW_SEM_TIMEOUT);
+
+ return ret;
+}
+
+int apusys_kernel_apusys_rv_setup_apummu(void)
+{
+ spin_lock(&apusys_rv_lock);
+
+#ifdef CONFIG_MTK_APUSYS_SEC_CTRL
+ sec_set_rv_dns();
+#endif
+
+#ifdef CONFIG_MTK_APUSYS_RV_APUMMU_SUPPORT
+ uint32_t apummu_tcm_sz_select = 0;
+
+ if (APU_MD32_TCM_SZ <= 0x20000)
+ apummu_tcm_sz_select = APUMMU_PAGE_LEN_128KB;
+ else if (APU_MD32_TCM_SZ <= 0x40000)
+ apummu_tcm_sz_select = APUMMU_PAGE_LEN_256KB;
+ else if (APU_MD32_TCM_SZ <= 0x80000)
+ apummu_tcm_sz_select = APUMMU_PAGE_LEN_512KB;
+ else if (APU_MD32_TCM_SZ <= 0x100000)
+ apummu_tcm_sz_select = APUMMU_PAGE_LEN_1MB;
+ else {
+ ERROR("%s: APU_MD32_TCM_SZ = 0x%x > 1MB", __func__, APU_MD32_TCM_SZ);
+ spin_unlock(&apusys_rv_lock);
+ return -EINVAL;
+ }
+
+ INFO("%s: apummu_tcm_sz_select = %u\n", __func__, apummu_tcm_sz_select);
+ rv_boot(APU_SEC_FW_IOVA, 0, APUMMU_PAGE_LEN_1MB,
+ APU_MD32_TCM, apummu_tcm_sz_select);
+#endif
+
+ spin_unlock(&apusys_rv_lock);
+ return 0;
+}
+
+int apusys_kernel_apusys_rv_pwr_ctrl(enum APU_PWR_OP op)
+{
+ return apusys_rv_pwr_ctrl(op);
+}
+
+#ifdef CONFIG_MTK_APUSYS_LOGTOP_SUPPORT
+int apusys_kernel_apusys_logtop_reg_dump(uint32_t op, struct smccc_res *smccc_ret)
+{
+ int ret = 0;
+ uint8_t smc_op;
+ uint32_t reg_addr[MAX_SMC_OP_NUM];
+ uint32_t i;
+
+ if (op == 0) {
+ ERROR("%s empty op = 0x%08x\n", MODULE_TAG, op);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < MAX_SMC_OP_NUM; i++) {
+ smc_op = (op >> (LOGTOP_OP_SHIFT * i)) & LOGTOP_OP_MASK;
+ switch (smc_op) {
+ case SMC_OP_APU_LOG_BUF_NULL:
+ reg_addr[i] = 0x0;
+ break;
+ case SMC_OP_APU_LOG_BUF_T_SIZE:
+ reg_addr[i] = APU_LOG_BUF_T_SIZE;
+ break;
+ case SMC_OP_APU_LOG_BUF_W_PTR:
+ reg_addr[i] = APU_LOG_BUF_W_PTR;
+ break;
+ case SMC_OP_APU_LOG_BUF_R_PTR:
+ reg_addr[i] = APU_LOG_BUF_R_PTR;
+ break;
+ case SMC_OP_APU_LOG_BUF_CON:
+ reg_addr[i] = APU_LOGTOP_CON;
+ break;
+ default:
+ ERROR("%s unknown op = 0x%08x\n", MODULE_TAG, smc_op);
+ return -EINVAL;
+ }
+ }
+
+ ret = apu_hw_sema_ctl(HW_SEMA2, HW_SEMA_LOGGER_USER, 1, 0, 0);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < MAX_SMC_OP_NUM; i++) {
+ if (reg_addr[i] == 0)
+ continue;
+
+ switch (i) {
+ case 0:
+ smccc_ret->a1 = mmio_read_32(reg_addr[i]);
+ break;
+ case 1:
+ smccc_ret->a2 = mmio_read_32(reg_addr[i]);
+ break;
+ case 2:
+ smccc_ret->a3 = mmio_read_32(reg_addr[i]);
+ break;
+ }
+ }
+
+ ret = apu_hw_sema_ctl(HW_SEMA2, HW_SEMA_LOGGER_USER, 0, 0, 0);
+ if (ret)
+ ERROR("%s(%d): sem release timeout\n", __func__, op);
+
+ return ret;
+}
+
+static int apusys_kernel_apusys_logtop_reg_rw(uint32_t op, uint32_t write_val,
+ bool w1c, struct smccc_res *smccc_ret)
+{
+ int ret = 0;
+ uint32_t reg_addr = 0, reg_val = 0;
+
+ switch (op) {
+ case SMC_OP_APU_LOG_BUF_R_PTR:
+ reg_addr = APU_LOG_BUF_R_PTR;
+ break;
+ case SMC_OP_APU_LOG_BUF_CON:
+ reg_addr = APU_LOGTOP_CON;
+ break;
+ default:
+ ERROR("%s unknown or not support op = %x\n", MODULE_TAG, op);
+ return -EINVAL;
+ }
+
+ ret = apu_hw_sema_ctl(HW_SEMA2, HW_SEMA_LOGGER_USER, 1, 0, 0);
+ if (ret)
+ return ret;
+
+ if (w1c) {
+ reg_val = mmio_read_32(reg_addr);
+ mmio_write_32(reg_addr, reg_val);
+ smccc_ret->a1 = reg_val;
+ } else {
+ mmio_write_32(reg_addr, write_val);
+ }
+
+ ret = apu_hw_sema_ctl(HW_SEMA2, HW_SEMA_LOGGER_USER, 0, 0, 0);
+ if (ret)
+ ERROR("%s(%d): sem release timeout\n", __func__, op);
+
+ return ret;
+}
+
+int apusys_kernel_apusys_logtop_reg_write(uint32_t op, uint32_t write_val,
+ struct smccc_res *smccc_ret)
+{
+ return apusys_kernel_apusys_logtop_reg_rw(op, write_val, false, smccc_ret);
+}
+
+int apusys_kernel_apusys_logtop_reg_w1c(uint32_t op, struct smccc_res *smccc_ret)
+{
+ return apusys_kernel_apusys_logtop_reg_rw(op, 0, true, smccc_ret);
+}
+
+#endif /* CONFIG_MTK_APUSYS_LOGTOP_SUPPORT */
+
+int apusys_rv_cold_boot_clr_mbox_dummy(void)
+{
+#ifdef SUPPORT_APU_CLEAR_MBOX_DUMMY
+ mmio_write_32(APU_MBOX(APU_HW_SEM_SYS_APMCU) + APU_MBOX_DUMMY, 0);
+#else
+ WARN("Not support clear mbox dummy on this platform\n");
+#endif
+ return 0;
+}
+
+#ifdef CONFIG_MTK_APUSYS_RV_IOMMU_HW_SEM_SUPPORT
+int apusys_rv_iommu_hw_sem_trylock(void)
+{
+ return rv_iommu_hw_sem_trylock();
+}
+
+int apusys_rv_iommu_hw_sem_unlock(void)
+{
+ return rv_iommu_hw_sem_unlock();
+}
+#endif /* CONFIG_MTK_APUSYS_RV_IOMMU_HW_SEM_SUPPORT */
+
+int apusys_rv_setup_ce_bin(void)
+{
+#ifdef CONFIG_MTK_APUSYS_CE_SUPPORT
+ uintptr_t apusys_rv_sec_buf_pa;
+ struct apusys_secure_info_t *apusys_secure_info;
+ struct ce_main_hdr_t *ce_main_hdr;
+ struct ce_sub_hdr_t *ce_sub_hdr;
+ unsigned int cnt, i, reg_val;
+ uint64_t ce_sub_hdr_bin;
+ int ret;
+
+ apusys_rv_sec_buf_pa = APU_RESERVE_MEMORY;
+ /* create mapping */
+ ret = mmap_add_dynamic_region(apusys_rv_sec_buf_pa, apusys_rv_sec_buf_pa,
+ round_up(APU_RESERVE_SIZE, PAGE_SIZE),
+ MT_MEMORY | MT_RW | MT_NS);
+ if (ret) {
+ ERROR("%s: mmap_add_dynamic_region() fail, ret=0x%x\n", __func__, ret);
+ return ret;
+ }
+
+ apusys_secure_info = (struct apusys_secure_info_t *)
+ (apusys_rv_sec_buf_pa + APU_SEC_INFO_OFFSET);
+
+ ce_main_hdr = (struct ce_main_hdr_t *)(apusys_rv_sec_buf_pa +
+ apusys_secure_info->ce_bin_ofs);
+ ce_sub_hdr = (struct ce_sub_hdr_t *)((uintptr_t)ce_main_hdr + ce_main_hdr->hdr_size);
+
+ if (ce_main_hdr->magic != CE_MAIN_MAGIC) {
+ ERROR("%s: invalid header\n", __func__);
+ return -EINVAL;
+ }
+
+ cnt = 0;
+
+ while (ce_sub_hdr->magic == CE_SUB_MAGIC && cnt < ce_main_hdr->bin_count) {
+ VERBOSE("%s: job (%d), magic (0x%x)\n", __func__,
+ ce_sub_hdr->ce_enum, ce_sub_hdr->magic);
+
+ ce_sub_hdr_bin = (uint64_t)ce_sub_hdr + ce_sub_hdr->bin_offset;
+
+ for (i = 0; i < ce_sub_hdr->bin_size; i += sizeof(uint32_t)) {
+ reg_val = *(uint32_t *)(ce_sub_hdr_bin + i);
+ mmio_write_32(ce_sub_hdr->mem_st + i, reg_val);
+ }
+
+ if (ce_sub_hdr->hw_entry) {
+ mmio_clrsetbits_32(ce_sub_hdr->hw_entry,
+ ce_sub_hdr->hw_entry_mask << ce_sub_hdr->hw_entry_bit,
+ (ce_sub_hdr->hw_entry_val & ce_sub_hdr->hw_entry_mask)
+ << ce_sub_hdr->hw_entry_bit);
+ }
+
+ ce_sub_hdr = (struct ce_sub_hdr_t *)(ce_sub_hdr_bin + ce_sub_hdr->bin_size);
+ cnt++;
+ }
+
+ mmap_remove_dynamic_region(apusys_rv_sec_buf_pa,
+ round_up(APU_RESERVE_SIZE, PAGE_SIZE));
+ INFO("%s: setup CE binary done\n", __func__);
+#else
+ WARN("Not support CE on this platform\n");
+#endif
return 0;
}
diff --git a/plat/mediatek/drivers/apusys/apusys_rv/2.0/apusys_rv.h b/plat/mediatek/drivers/apusys/apusys_rv/2.0/apusys_rv.h
index 8a43890..506fcee 100644
--- a/plat/mediatek/drivers/apusys/apusys_rv/2.0/apusys_rv.h
+++ b/plat/mediatek/drivers/apusys/apusys_rv/2.0/apusys_rv.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, MediaTek Inc. All rights reserved.
+ * Copyright (c) 2023-2024, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -88,24 +88,35 @@
#define WDT_INT_W1C (1)
#define WDT_EN BIT(31)
-/* APU MBOX */
-#define MBOX_FUNC_CFG (0xb0)
-#define MBOX_DOMAIN_CFG (0xe0)
-#define MBOX_CTRL_LOCK BIT(0)
-#define MBOX_NO_MPU_SHIFT (16)
-#define MBOX_RX_NS_SHIFT (16)
-#define MBOX_RX_DOMAIN_SHIFT (17)
-#define MBOX_TX_NS_SHIFT (24)
-#define MBOX_TX_DOMAIN_SHIFT (25)
-#define MBOX_SIZE (0x100)
-#define MBOX_NUM (8)
+enum APU_PWR_OP {
+ APU_PWR_OFF = 0,
+ APU_PWR_ON = 1,
+};
-#define APU_MBOX(i) (((i) < MBOX_NUM) ? (APU_MBOX0 + MBOX_SIZE * (i)) : \
- (APU_MBOX1 + MBOX_SIZE * ((i) - MBOX_NUM)))
-#define APU_MBOX_FUNC_CFG(i) (APU_MBOX(i) + MBOX_FUNC_CFG)
-#define APU_MBOX_DOMAIN_CFG(i) (APU_MBOX(i) + MBOX_DOMAIN_CFG)
+/* APU_LOGTOP */
+#define APU_LOGTOP_CON (APU_LOGTOP + 0x0)
+#define APU_LOG_BUF_T_SIZE (APU_LOGTOP + 0x78)
+#define APU_LOG_BUF_W_PTR (APU_LOGTOP + 0x80)
+#define APU_LOG_BUF_R_PTR (APU_LOGTOP + 0x84)
+#define HW_SEMA2 (APU_ARE_REG_BASE + 0x0E08)
+#define HW_SEMA_USER (0x2)
+#define HW_SEMA_LOGGER_USER (0x3)
+#define MAX_SMC_OP_NUM (0x3)
+#define LOGTOP_OP_MASK (0xFF)
+#define LOGTOP_OP_SHIFT (8)
+enum {
+ SMC_OP_APU_LOG_BUF_NULL = 0,
+ SMC_OP_APU_LOG_BUF_T_SIZE,
+ SMC_OP_APU_LOG_BUF_W_PTR,
+ SMC_OP_APU_LOG_BUF_R_PTR,
+ SMC_OP_APU_LOG_BUF_CON,
+ SMC_OP_APU_LOG_BUF_NUM
+};
+
+struct smccc_res;
void apusys_rv_mbox_mpu_init(void);
+int apusys_infra_dcm_setup(void);
int apusys_kernel_apusys_rv_setup_reviser(void);
int apusys_kernel_apusys_rv_reset_mp(void);
int apusys_kernel_apusys_rv_setup_boot(void);
@@ -116,5 +127,13 @@
int apusys_kernel_apusys_rv_clear_wdt_isr(void);
int apusys_kernel_apusys_rv_cg_gating(void);
int apusys_kernel_apusys_rv_cg_ungating(void);
+int apusys_kernel_apusys_rv_setup_apummu(void);
+int apusys_kernel_apusys_rv_pwr_ctrl(enum APU_PWR_OP op);
+int apusys_kernel_apusys_logtop_reg_dump(uint32_t op, struct smccc_res *smccc_ret);
+int apusys_kernel_apusys_logtop_reg_write(uint32_t op, uint32_t write_val,
+ struct smccc_res *smccc_ret);
+int apusys_kernel_apusys_logtop_reg_w1c(uint32_t op, struct smccc_res *smccc_ret);
+int apusys_rv_cold_boot_clr_mbox_dummy(void);
+int apusys_rv_setup_ce_bin(void);
#endif /* APUSYS_RV_H */
diff --git a/plat/mediatek/drivers/apusys/apusys_rv/2.0/apusys_rv_sec_info.h b/plat/mediatek/drivers/apusys/apusys_rv/2.0/apusys_rv_sec_info.h
new file mode 100644
index 0000000..581ed0a
--- /dev/null
+++ b/plat/mediatek/drivers/apusys/apusys_rv/2.0/apusys_rv_sec_info.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2024, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef APUSYS_RV_SECURE_INFO_H
+#define APUSYS_RV_SECURE_INFO_H
+
+#define CE_MAIN_MAGIC (0xCEC0DE88)
+#define CE_SUB_MAGIC (0xCEC0DE00)
+
+struct apusys_secure_info_t {
+ unsigned int total_sz;
+ unsigned int up_code_buf_ofs;
+ unsigned int up_code_buf_sz;
+
+ unsigned int up_fw_ofs;
+ unsigned int up_fw_sz;
+ unsigned int up_xfile_ofs;
+ unsigned int up_xfile_sz;
+ unsigned int mdla_fw_boot_ofs;
+ unsigned int mdla_fw_boot_sz;
+ unsigned int mdla_fw_main_ofs;
+ unsigned int mdla_fw_main_sz;
+ unsigned int mdla_xfile_ofs;
+ unsigned int mdla_xfile_sz;
+ unsigned int mvpu_fw_ofs;
+ unsigned int mvpu_fw_sz;
+ unsigned int mvpu_xfile_ofs;
+ unsigned int mvpu_xfile_sz;
+ unsigned int mvpu_sec_fw_ofs;
+ unsigned int mvpu_sec_fw_sz;
+ unsigned int mvpu_sec_xfile_ofs;
+ unsigned int mvpu_sec_xfile_sz;
+
+ unsigned int up_coredump_ofs;
+ unsigned int up_coredump_sz;
+ unsigned int mdla_coredump_ofs;
+ unsigned int mdla_coredump_sz;
+ unsigned int mvpu_coredump_ofs;
+ unsigned int mvpu_coredump_sz;
+ unsigned int mvpu_sec_coredump_ofs;
+ unsigned int mvpu_sec_coredump_sz;
+
+ unsigned int ce_bin_ofs;
+ unsigned int ce_bin_sz;
+};
+
+struct ce_main_hdr_t {
+ unsigned int magic; /* magic number*/
+ unsigned int hdr_size; /* header size */
+ unsigned int img_size; /* img size */
+ unsigned int bin_count; /* bin count */
+};
+
+struct ce_sub_hdr_t {
+ unsigned int magic; /* magic number */
+ unsigned int bin_offset; /* binary offset */
+ unsigned int bin_size; /* binary size */
+ unsigned int ce_enum; /* ce enum */
+ char job_name[8]; /* job name */
+ unsigned int mem_st; /* ce enum */
+ unsigned int hw_entry; /* hw entry */
+ unsigned int hw_entry_bit; /* hw entry bit */
+ unsigned int hw_entry_mask; /* hw entry mask */
+ unsigned int hw_entry_val; /* hw entry val*/
+ unsigned int user_info; /* user_info */
+};
+
+#endif /* APUSYS_RV_SECURE_INFO_H */
diff --git a/plat/mediatek/drivers/apusys/devapc/apusys_dapc_v1.h b/plat/mediatek/drivers/apusys/devapc/apusys_dapc_v1.h
index 1b77942..a15daa2 100644
--- a/plat/mediatek/drivers/apusys/devapc/apusys_dapc_v1.h
+++ b/plat/mediatek/drivers/apusys/devapc/apusys_dapc_v1.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, MediaTek Inc. All rights reserved.
+ * Copyright (c) 2023-2024, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -13,8 +13,15 @@
* STRUCTURE DEFINITION
******************************************************************************/
enum apusys_apc_err_status {
- APUSYS_APC_OK = 0x0,
- APUSYS_APC_ERR_GENERIC = 0x1,
+ APUSYS_APC_OK = 0x0,
+ APUSYS_APC_ERR_GENERIC = 0x1000,
+ APUSYS_APC_ERR_INVALID_CMD = 0x1001,
+ APUSYS_APC_ERR_SLAVE_TYPE_NOT_SUPPORTED = 0x1002,
+ APUSYS_APC_ERR_SLAVE_IDX_NOT_SUPPORTED = 0x1003,
+ APUSYS_APC_ERR_DOMAIN_NOT_SUPPORTED = 0x1004,
+ APUSYS_APC_ERR_PERMISSION_NOT_SUPPORTED = 0x1005,
+ APUSYS_APC_ERR_OUT_OF_BOUNDARY = 0x1006,
+ APUSYS_APC_ERR_REQ_TYPE_NOT_SUPPORTED = 0x1007,
};
enum apusys_apc_perm_type {
@@ -155,4 +162,110 @@
FORBIDDEN, NO_PROTECTION, FORBIDDEN, FORBIDDEN, \
FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, \
FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN)
+
+#define SLAVE_FORBID_EXCEPT_D0_D11_NO_PROTECT_D3_D5_D8_SEC_RW(domain) \
+ APUSYS_APC_AO_ATTR(domain, \
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, SEC_RW_ONLY, \
+ FORBIDDEN, SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, \
+ SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, NO_PROTECTION, \
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN)
+
+#define SLAVE_FORBID_EXCEPT_D0_SEC_RW_NS_R_D3_D5_SEC_RW(domain) \
+ APUSYS_APC_AO_ATTR(domain, \
+ SEC_RW_NS_R, FORBIDDEN, FORBIDDEN, SEC_RW_ONLY, \
+ FORBIDDEN, SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, \
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, \
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN)
+
+#define SLAVE_FORBID_EXCEPT_D5_SEC_RW(domain) \
+ APUSYS_APC_AO_ATTR(domain, \
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, \
+ FORBIDDEN, SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, \
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, \
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN)
+
+#define SLAVE_FORBID_EXCEPT_D0_SEC_RW_NS_R_D5_SEC_RW(domain) \
+ APUSYS_APC_AO_ATTR(domain, \
+ SEC_RW_NS_R, FORBIDDEN, FORBIDDEN, FORBIDDEN, \
+ FORBIDDEN, SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, \
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, \
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN)
+
+#define SLAVE_FORBID_EXCEPT_D0_NO_PROTECT_D3_D5_SEC_RW(domain) \
+ APUSYS_APC_AO_ATTR(domain, \
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, SEC_RW_ONLY, \
+ FORBIDDEN, SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, \
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, \
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN)
+
+#define SLAVE_FORBID_EXCEPT_D3_D5_SEC_RW_D0_D4_D11_NO_PROTECT(domain) \
+ APUSYS_APC_AO_ATTR(domain, \
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, SEC_RW_ONLY, \
+ NO_PROTECTION, SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, \
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROTECTION, \
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN)
+
+#define SLAVE_FORBID_EXCEPT_D5_SEC_RW_D0_NO_PROTECT(domain) \
+ APUSYS_APC_AO_ATTR(domain, \
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, \
+ FORBIDDEN, SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, \
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, \
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN)
+
+#define SLAVE_FORBID_EXCEPT_D0_D5_SEC_RW(domain) \
+ APUSYS_APC_AO_ATTR(domain, \
+ SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN, \
+ FORBIDDEN, SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, \
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, \
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN)
+
+#define SLAVE_FORBID_EXCEPT_D0_NO_PROTECT_D5_SEC_RW(domain) \
+ APUSYS_APC_AO_ATTR(domain, \
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, \
+ FORBIDDEN, SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, \
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, \
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN)
+
+#define SLAVE_FORBID_EXCEPT_D3_D5_SEC_RW_D0_D11_NO_PROTECT(domain) \
+ APUSYS_APC_AO_ATTR(domain, \
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, SEC_RW_ONLY, \
+ FORBIDDEN, SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, \
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROTECTION, \
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN)
+
+#define SLAVE_FORBID_EXCEPT_D0_NO_PROTECT_D5_D8_SEC_RW(domain) \
+ APUSYS_APC_AO_ATTR(domain, \
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, \
+ FORBIDDEN, SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, \
+ SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN, \
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN)
+
+#define SLAVE_FORBID_EXCEPT_D0_D3_D5_SEC_RW(domain) \
+ APUSYS_APC_AO_ATTR(domain, \
+ SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, SEC_RW_ONLY, \
+ FORBIDDEN, SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, \
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, \
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN)
+
+#define SLAVE_FORBID_EXCEPT_D0_SEC_RW_NS_R_D5_D8_SEC_RW(domain) \
+ APUSYS_APC_AO_ATTR(domain, \
+ SEC_RW_NS_R, FORBIDDEN, FORBIDDEN, FORBIDDEN, \
+ FORBIDDEN, SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, \
+ SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN, \
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN)
+
+#define SLAVE_FORBID_EXCEPT_D5_D8_SEC_RW(domain) \
+ APUSYS_APC_AO_ATTR(domain, \
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, \
+ FORBIDDEN, SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, \
+ SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN, \
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN)
+
+#define SLAVE_FORBID_EXCEPT_D0_D5_D7_D14_NO_PROTECT(domain) \
+ APUSYS_APC_AO_ATTR(domain, \
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN, \
+ FORBIDDEN, NO_PROTECTION, FORBIDDEN, NO_PROTECTION, \
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN, \
+ FORBIDDEN, FORBIDDEN, NO_PROTECTION, FORBIDDEN)
+
#endif /* APUSYS_DAPC_V1_H */
diff --git a/plat/mediatek/drivers/apusys/mt8188/apusys_power.c b/plat/mediatek/drivers/apusys/mt8188/apusys_power.c
index 0a2781b..746c81f 100644
--- a/plat/mediatek/drivers/apusys/mt8188/apusys_power.c
+++ b/plat/mediatek/drivers/apusys/mt8188/apusys_power.c
@@ -1,9 +1,10 @@
/*
- * Copyright (c) 2023, MediaTek Inc. All rights reserved.
+ * Copyright (c) 2023-2024, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <errno.h>
#include <inttypes.h>
/* TF-A system header */
@@ -18,6 +19,7 @@
#include "apusys.h"
#include "apusys_power.h"
#include "apusys_rv.h"
+#include "apusys_rv_pwr_ctrl.h"
#include <mtk_mmap_pool.h>
static spinlock_t apu_lock;
@@ -118,7 +120,7 @@
mmio_write_32(APU_MBOX0_BASE + PWR_FLOW_SYNC_REG, (cfg & 0x1));
}
-int apusys_kernel_apusys_pwr_top_on(void)
+static int apusys_kernel_apusys_pwr_top_on(void)
{
int ret;
@@ -184,7 +186,7 @@
udelay(100);
}
-int apusys_kernel_apusys_pwr_top_off(void)
+static int apusys_kernel_apusys_pwr_top_off(void)
{
int ret;
@@ -221,6 +223,19 @@
return ret;
}
+int apusys_rv_pwr_ctrl(enum APU_PWR_OP op)
+{
+ if (op != APU_PWR_OFF && op != APU_PWR_ON) {
+ ERROR(MODULE_TAG "%s unknown request_ops = %d\n", __func__, op);
+ return -EINVAL;
+ }
+
+ if (op == APU_PWR_ON)
+ return apusys_kernel_apusys_pwr_top_on();
+
+ return apusys_kernel_apusys_pwr_top_off();
+}
+
static void get_pll_pcw(const uint32_t clk_rate, uint32_t *r1, uint32_t *r2)
{
unsigned int fvco = clk_rate;
@@ -481,3 +496,10 @@
return ret;
}
+
+int apusys_infra_dcm_setup(void)
+{
+ WARN(MODULE_TAG "%s not support\n", __func__);
+
+ return -EOPNOTSUPP;
+}
diff --git a/plat/mediatek/drivers/apusys/mt8188/apusys_power.h b/plat/mediatek/drivers/apusys/mt8188/apusys_power.h
index 460cc50..e1ce4a4 100644
--- a/plat/mediatek/drivers/apusys/mt8188/apusys_power.h
+++ b/plat/mediatek/drivers/apusys/mt8188/apusys_power.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, MediaTek Inc. All rights reserved.
+ * Copyright (c) 2023-2024, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -242,7 +242,5 @@
#define CG_CLR (0xffffffff)
int apusys_power_init(void);
-int apusys_kernel_apusys_pwr_top_on(void);
-int apusys_kernel_apusys_pwr_top_off(void);
#endif /* APUSYS_POWER_H */
diff --git a/plat/mediatek/drivers/apusys/apusys_rv/2.0/apusys_rv_mbox_mpu.h b/plat/mediatek/drivers/apusys/mt8188/apusys_rv_mbox_mpu.h
similarity index 95%
rename from plat/mediatek/drivers/apusys/apusys_rv/2.0/apusys_rv_mbox_mpu.h
rename to plat/mediatek/drivers/apusys/mt8188/apusys_rv_mbox_mpu.h
index 0ee4878..dbdf274 100644
--- a/plat/mediatek/drivers/apusys/apusys_rv/2.0/apusys_rv_mbox_mpu.h
+++ b/plat/mediatek/drivers/apusys/mt8188/apusys_rv_mbox_mpu.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, MediaTek Inc. All rights reserved.
+ * Copyright (c) 2023-2024, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
diff --git a/plat/mediatek/drivers/apusys/mt8188/apusys_rv_pwr_ctrl.h b/plat/mediatek/drivers/apusys/mt8188/apusys_rv_pwr_ctrl.h
new file mode 100644
index 0000000..329eadf
--- /dev/null
+++ b/plat/mediatek/drivers/apusys/mt8188/apusys_rv_pwr_ctrl.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2024, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef APUSYS_RV_PWR_CTL_H
+#define APUSYS_RV_PWR_CTL_H
+
+#include "apusys_rv.h"
+
+/* APU MBOX */
+#define MBOX_FUNC_CFG (0xb0)
+#define MBOX_DOMAIN_CFG (0xe0)
+#define MBOX_CTRL_LOCK BIT(0)
+#define MBOX_NO_MPU_SHIFT (16)
+#define MBOX_RX_NS_SHIFT (16)
+#define MBOX_RX_DOMAIN_SHIFT (17)
+#define MBOX_TX_NS_SHIFT (24)
+#define MBOX_TX_DOMAIN_SHIFT (25)
+#define MBOX_SIZE (0x100)
+#define MBOX_NUM (8)
+
+#define APU_MBOX(i) (((i) < MBOX_NUM) ? (APU_MBOX0 + MBOX_SIZE * (i)) : \
+ (APU_MBOX1 + MBOX_SIZE * ((i) - MBOX_NUM)))
+#define APU_MBOX_FUNC_CFG(i) (APU_MBOX(i) + MBOX_FUNC_CFG)
+#define APU_MBOX_DOMAIN_CFG(i) (APU_MBOX(i) + MBOX_DOMAIN_CFG)
+
+#define HW_SEM_TIMEOUT (0)
+
+int apusys_rv_pwr_ctrl(enum APU_PWR_OP op);
+
+#endif /* APUSYS_RV_PWR_CTL_H */
diff --git a/plat/mediatek/drivers/apusys/mt8188/apusys_security_ctrl_plat.c b/plat/mediatek/drivers/apusys/mt8188/apusys_security_ctrl_plat.c
index 86bebe5..8517db0 100644
--- a/plat/mediatek/drivers/apusys/mt8188/apusys_security_ctrl_plat.c
+++ b/plat/mediatek/drivers/apusys/mt8188/apusys_security_ctrl_plat.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, MediaTek Inc. All rights reserved.
+ * Copyright (c) 2023-2024, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -8,6 +8,8 @@
#include <common/debug.h>
#include <lib/mmio.h>
+#include "emi_mpu.h"
+
/* Vendor header */
#include "apusys_security_ctrl_plat.h"
@@ -41,3 +43,8 @@
{
apusys_domain_remap_init();
}
+
+int apusys_plat_setup_sec_mem(void)
+{
+ return set_apu_emi_mpu_region();
+}
diff --git a/plat/mediatek/drivers/apusys/mt8188/apusys_security_ctrl_plat.h b/plat/mediatek/drivers/apusys/mt8188/apusys_security_ctrl_plat.h
index f9181ae..f1b0a41 100644
--- a/plat/mediatek/drivers/apusys/mt8188/apusys_security_ctrl_plat.h
+++ b/plat/mediatek/drivers/apusys/mt8188/apusys_security_ctrl_plat.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, MediaTek Inc. All rights reserved.
+ * Copyright (c) 2023-2024, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -34,5 +34,6 @@
#define D15_REMAP_DOMAIN (15)
void apusys_security_ctrl_init(void);
+int apusys_plat_setup_sec_mem(void);
#endif /* APUSYS_SECURITY_CTRL_PLAT_H */
diff --git a/plat/mediatek/drivers/apusys/mt8196/apusys_ammu.c b/plat/mediatek/drivers/apusys/mt8196/apusys_ammu.c
new file mode 100644
index 0000000..fa1cd2c
--- /dev/null
+++ b/plat/mediatek/drivers/apusys/mt8196/apusys_ammu.c
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2024, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <errno.h>
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+
+#include "apusys_ammu.h"
+#include <apusys_security_ctrl_perm.h>
+#include <mtk_mmap_pool.h>
+
+static void apummu_set_segment_offset0(uint32_t vsid_idx, uint8_t seg_idx, uint32_t input_adr,
+ uint8_t res_bits, uint8_t page_sel, uint8_t page_len)
+{
+ mmio_write_32(APUMMU_VSID_SEGMENT_BASE(vsid_idx, seg_idx, APUMMU_SEG_OFFSET_0),
+ APUMMU_BUILD_SEGMENT_OFFSET0(input_adr, res_bits, page_sel, page_len));
+}
+
+static void apummu_set_segment_offset1(uint32_t vsid_idx, uint8_t seg_idx, uint32_t output_adr,
+ uint8_t res0, uint8_t iommu_en, uint8_t res1)
+{
+ mmio_write_32(APUMMU_VSID_SEGMENT_BASE(vsid_idx, seg_idx, APUMMU_SEG_OFFSET_1),
+ APUMMU_BUILD_SEGMENT_OFFSET1(output_adr, res0, iommu_en, res1));
+}
+
+static void apummu_set_segment_offset2(uint32_t vsid_idx, uint8_t seg_idx, uint8_t resv,
+ uint8_t domain, uint8_t acp_en, uint8_t aw_clr,
+ uint8_t aw_invalid, uint8_t ar_exclu, uint8_t ar_sepcu,
+ uint8_t aw_cache_allocate, uint8_t aw_slc_en,
+ uint8_t aw_slb_en, uint8_t ar_cache_allocate,
+ uint8_t ar_slc_en, uint8_t ar_slb_en, uint8_t ro,
+ uint8_t ns)
+{
+ mmio_write_32(APUMMU_VSID_SEGMENT_BASE(vsid_idx, seg_idx, APUMMU_SEG_OFFSET_2),
+ APUMMU_BUILD_SEGMENT_OFFSET2(resv, domain, acp_en, aw_clr, aw_invalid,
+ ar_exclu, ar_sepcu, aw_cache_allocate,
+ aw_slc_en, aw_slb_en, ar_cache_allocate,
+ ar_slc_en, ar_slb_en, ro, ns));
+}
+
+static void apummu_vsid_segment_enable_init(uint8_t vsid_idx)
+{
+ mmio_write_32(APUMMU_VSID_SEGMENT_ENABLE(vsid_idx), 0);
+}
+
+static void apummu_set_single_segment(uint8_t vsid_idx, uint8_t seg_idx)
+{
+ mmio_setbits_32(APUMMU_VSID_SEGMENT_ENABLE(vsid_idx), BIT(seg_idx));
+}
+
+static int apummu_enable_vsid(uint32_t vsid_idx)
+{
+ if (vsid_idx > (APUMMU_VSID_ACTIVE - 1) &&
+ vsid_idx < (APUMMU_RSV_VSID_IDX_END - APUMMU_VSID_RSV + 1)) {
+ ERROR("invalid vsid index %d\n", vsid_idx);
+ return -1;
+ }
+
+ mmio_write_32(APUMMU_VSID_ENABLE_BASE(vsid_idx), BIT(vsid_idx & APUMMU_VSID_EN_MASK));
+ mmio_write_32(APUMMU_VSID_VALID_BASE(vsid_idx), BIT(vsid_idx & APUMMU_VSID_EN_MASK));
+
+ return 0;
+}
+
+static void apummu_enable(void)
+{
+ mmio_setbits_32(APUMMU_CMU_TOP_BASE, 0x1);
+}
+
+static void apummu_vsid_sram_config(void)
+{
+ uint32_t idx;
+ uint32_t base = (APUMMU_VSID_SRAM_TOTAL - APUMMU_VSID_RSV);
+
+ for (idx = 0; idx < APUMMU_VSID_RSV; idx++) {
+ mmio_write_32(APUMMU_VSID(APUMMU_RSV_VSID_IDX_START + idx),
+ APUMMU_VSID_DESC(base + idx));
+ apummu_vsid_segment_enable_init(base + idx);
+ }
+}
+
+static void apummu_bind_vsid(uint32_t tcu_base, uint32_t vsid_idx, uint8_t cor_id,
+ uint8_t hw_thread, uint8_t cor_valid, uint8_t vsid_valid)
+{
+ mmio_write_32((tcu_base + hw_thread * VSID_THREAD_SZ),
+ (((cor_id & VSID_CORID_MASK) << VSID_CORID_OFF) |
+ ((vsid_idx & VSID_IDX_MASK) << VSID_IDX_OFF) |
+ ((cor_valid & VSID_VALID_MASK) << VSID_COR_VALID_OFF) |
+ ((vsid_valid & VSID_VALID_MASK) << VSID_VALID_OFF)));
+}
+
+static int apummu_rv_bind_vsid(uint8_t hw_thread)
+{
+ uint8_t cor_id = 0, cor_valid = 0, vsid_valid = 1;
+
+ if (hw_thread > APUMMU_HW_THREAD_MAX) {
+ ERROR("%s: the hw thread id (%d) is not valid for rv/logger\n", __func__,
+ hw_thread);
+ return -EINVAL;
+ }
+
+ apummu_bind_vsid(APUMMU_RCX_UPRV_TCU_BASE, APUMMU_UPRV_RSV_VSID, cor_id, hw_thread,
+ cor_valid, vsid_valid);
+
+ return 0;
+}
+
+static int apummu_apmcu_bind_vsid(uint8_t hw_thread)
+{
+ uint8_t cor_id = 0, cor_valid = 0, vsid_valid = 1;
+
+ if (hw_thread > APUMMU_HW_THREAD_MAX) {
+ ERROR("%s: the hw thread id (%d) is not valid for apmcu\n", __func__, hw_thread);
+ return -EINVAL;
+ }
+
+ apummu_bind_vsid(APUMMU_RCX_EXTM_TCU_BASE, APUMMU_APMCU_RSV_VSID, cor_id, hw_thread,
+ cor_valid, vsid_valid);
+
+ return 0;
+}
+
+static int apummu_add_map(uint32_t vsid_idx, uint8_t seg_idx, uint64_t input_adr,
+ uint64_t output_adr, uint8_t page_sel, uint8_t page_len,
+ uint8_t domain, uint8_t ns)
+{
+ uint8_t smmu_sid;
+ bool smmu_sec_id;
+
+ if (seg_idx > APUMMU_SEG_MAX) {
+ ERROR("seg_idx is illegal (0x%x)\n", seg_idx);
+ return -EINVAL;
+ }
+
+ smmu_sec_id = false;
+ if (ns == 0)
+ smmu_sid = SMMU_NORMAL_1_4G_SID;
+ else
+ smmu_sid = (output_adr > 0xFFFFFFFF) ? SMMU_NORMAL_4_16G_SID
+ : SMMU_NORMAL_1_4G_SID;
+
+ /* fill segment */
+ apummu_set_segment_offset0(vsid_idx, seg_idx, (input_adr >> APUMMU_ADDR_SHIFT), 0,
+ page_sel, page_len);
+ apummu_set_segment_offset1(vsid_idx, seg_idx, (output_adr >> APUMMU_ADDR_SHIFT),
+ smmu_sid, 0, smmu_sec_id);
+ apummu_set_segment_offset2(vsid_idx, seg_idx, 0, domain,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ns);
+ apummu_set_single_segment(vsid_idx, seg_idx);
+
+ return 0;
+}
+
+static int apummu_get_dns(enum apusys_dev_type engine_type, enum apusys_sec_level sec_level,
+ uint8_t *domain, uint8_t *ns)
+{
+ int ret = 0;
+
+ if (engine_type != APUSYS_DEVICE_NUM) {
+ ret = sec_get_dns(engine_type, sec_level, domain, ns);
+ if (ret)
+ ERROR("engine:%d, sec: %d\n", engine_type, sec_level);
+ } else {
+ *domain = 7;
+ *ns = 1;
+ }
+
+ return ret;
+}
+
+static void apummu_init(void)
+{
+ apummu_vsid_sram_config();
+ mmio_write_32((APU_VCORE_CONFIG_BASE + APUMMU_SSID_SID_WIDTH_CTRL),
+ CSR_SMMU_AXMMUSID_WIDTH);
+ apummu_enable();
+}
+
+static void virtual_engine_thread(void)
+{
+ mmio_write_32((APUMMU_RCX_EXTM_TCU_BASE + APUMMU_INT_D2T_TBL0_OFS), APUMMU_THD_ID_TEE);
+}
+
+static int apummu_add_apmcu_map(uint32_t seg0_input, uint32_t seg0_output,
+ enum apummu_page_size page_size)
+{
+ int i, ret;
+ uint8_t domain, ns, seg;
+
+ ret = apummu_get_dns(APUSYS_DEVICE_NUM, SEC_LEVEL_SECURE, &domain, &ns);
+ if (ret) {
+ return ret;
+ }
+
+ seg = 0;
+ ret = apummu_add_map(APUMMU_APMCU_RSV_DESC_IDX, seg, seg0_input, seg0_output, 0,
+ page_size, domain, ns);
+ seg += 1;
+ if (ret)
+ return ret;
+
+ for (i = 0; i < 4; i++) {
+ ret = apummu_add_map(APUMMU_APMCU_RSV_DESC_IDX, seg,
+ APUSYS_TCM + (i * APUMMU_1M_SIZE),
+ APUSYS_TCM + (i * APUMMU_1M_SIZE),
+ 0, APUMMU_PAGE_LEN_1MB, domain, ns);
+ seg += 1;
+ if (ret)
+ return ret;
+ }
+
+ ret = apummu_enable_vsid(APUMMU_APMCU_RSV_VSID);
+
+ return ret;
+}
+
+static int apummu_add_rv_boot_map(uint32_t seg0_output, uint32_t seg1_output, uint32_t seg2_output)
+{
+ int ret;
+ uint8_t domain, ns;
+
+ ret = apummu_get_dns(APUSYS_DEVICE_UP, SEC_LEVEL_SECURE, &domain, &ns);
+ if (ret) {
+ ERROR("sec get dns fail %d\n", ret);
+ return ret;
+ }
+
+ /* must be in order */
+ ret |= apummu_add_map(APUMMU_RSV_VSID_DESC_IDX_END, 0, 0, seg0_output, 0,
+ APUMMU_PAGE_LEN_1MB, domain, ns);
+ ret |= apummu_add_map(APUMMU_RSV_VSID_DESC_IDX_END, 1, 0, seg1_output, 0,
+ APUMMU_PAGE_LEN_512MB, domain, ns);
+
+ ret |= apummu_get_dns(APUSYS_DEVICE_UP, SEC_LEVEL_NORMAL, &domain, &ns);
+ if (ret) {
+ return ret;
+ }
+
+ ret |= apummu_add_map(APUMMU_RSV_VSID_DESC_IDX_END, 2,
+ 0, seg2_output, 0, APUMMU_PAGE_LEN_4GB,
+ domain, ns);
+ if (ret) {
+ ERROR("sec add map fail %d\n", ret);
+ return ret;
+ }
+
+ ret = apummu_enable_vsid(APUMMU_UPRV_RSV_VSID);
+
+ return ret;
+}
+
+int rv_boot(uint32_t uP_seg_output, uint8_t uP_hw_thread,
+ enum apummu_page_size logger_page_size,
+ uint32_t XPU_seg_output, enum apummu_page_size XPU_page_size)
+{
+ int ret = 0;
+
+ apummu_init();
+
+ ret = apummu_add_rv_boot_map(uP_seg_output, 0, 0);
+ if (ret) {
+ return ret;
+ }
+
+ ret = apummu_rv_bind_vsid(uP_hw_thread);
+ if (ret)
+ return ret;
+
+ ret = apummu_rv_bind_vsid(uP_hw_thread + 1);
+ if (ret)
+ return ret;
+
+ virtual_engine_thread();
+
+ ret = apummu_add_apmcu_map(XPU_seg_output, XPU_seg_output,
+ XPU_page_size);
+ if (ret)
+ return ret;
+
+ ret = apummu_apmcu_bind_vsid(APUMMU_THD_ID_TEE);
+
+ return ret;
+}
diff --git a/plat/mediatek/drivers/apusys/mt8196/apusys_ammu.h b/plat/mediatek/drivers/apusys/mt8196/apusys_ammu.h
new file mode 100644
index 0000000..61defc9
--- /dev/null
+++ b/plat/mediatek/drivers/apusys/mt8196/apusys_ammu.h
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2024, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef APUSYS_AMMU_H
+#define APUSYS_AMMU_H
+
+#include <platform_def.h>
+
+/* CMU */
+#define APUMMU_CMU_TOP_BASE (APU_CMU_TOP)
+#define APUMMU_CMU_TOP_TOPOLOGY (APUMMU_CMU_TOP_BASE + 0x04)
+#define APUMMU_VSID_ENABLE_OFFSET (0x50)
+#define APUMMU_VSID_VALID_OFFSET (0xb0)
+
+#define VSID_OFFSET(vsid_idx) (((vsid_idx) >> 5) * 0x4)
+
+#define APUMMU_VSID_ENABLE_BASE(vsid_idx) \
+ (APUMMU_CMU_TOP_BASE + VSID_OFFSET(vsid_idx) + APUMMU_VSID_ENABLE_OFFSET)
+#define APUMMU_VSID_VALID_BASE(vsid_idx) \
+ (APUMMU_CMU_TOP_BASE + VSID_OFFSET(vsid_idx) + APUMMU_VSID_VALID_OFFSET)
+
+/* VSID SRAM */
+#define APUMMU_VSID_BASE (APUMMU_CMU_TOP_BASE + 0x1000)
+#define APUMMU_VSID_DESC_BASE (APUMMU_VSID_BASE + 0x400)
+#define APUMMU_VSID_SRAM_SZIE (0x5C00)
+#define APUMMU_VSID_TBL_SZIE (0xF4)
+
+#define APUMMU_VSID(vsid_idx) (APUMMU_VSID_BASE + (vsid_idx) * 4)
+#define APUMMU_VSID_DESC(vsid_idx) \
+ (APUMMU_VSID_DESC_BASE + (vsid_idx) * APUMMU_VSID_TBL_SZIE)
+
+/* TCU RCX */
+#define APU_VCORE_CONFIG_BASE (APU_RCX_VCORE_CONFIG)
+#define APUMMU_RCX_EXTM_TCU_BASE (APU_RCX_EXTM_TCU)
+#define APUMMU_RCX_UPRV_TCU_BASE (APU_RCX_UPRV_TCU)
+
+#define APUMMU_SSID_SID_WIDTH_CTRL (0xCC0)
+#define CSR_SMMU_AXMMUSID_WIDTH BIT(7)
+#define APUMMU_1M_SIZE (0x100000)
+
+#define SMMU_NORMAL_0_1G_SID (0x8)
+#define SMMU_NORMAL_1_4G_SID (0x9)
+#define SMMU_NORMAL_4_16G_SID (0xA)
+
+enum apummu_page_size {
+ APUMMU_PAGE_LEN_128KB = 0,
+ APUMMU_PAGE_LEN_256KB,
+ APUMMU_PAGE_LEN_512KB,
+ APUMMU_PAGE_LEN_1MB,
+ APUMMU_PAGE_LEN_128MB,
+ APUMMU_PAGE_LEN_256MB,
+ APUMMU_PAGE_LEN_512MB,
+ APUMMU_PAGE_LEN_4GB,
+};
+
+#define APUMMU_VSID_SEGMENT_BASE(vsid_idx, seg_idx, seg_offset) \
+ (APUMMU_VSID_DESC(vsid_idx) + (seg_idx) * 0xC + (seg_offset) * 0x04 + 0x4)
+
+#define APUMMU_VSID_SEGMENT_ENABLE(vsid_idx) (APUMMU_VSID_DESC(vsid_idx))
+
+#define APUMMU_VSID_SRAM_TOTAL (APUMMU_VSID_SRAM_SZIE / APUMMU_VSID_TBL_SZIE)
+#define APUMMU_RSV_VSID_DESC_IDX_END (APUMMU_VSID_SRAM_TOTAL - 1)
+#define APUMMU_UPRV_RSV_DESC_IDX (APUMMU_RSV_VSID_DESC_IDX_END) /* 53 */
+#define APUMMU_LOGGER_RSV_DESC_IDX (APUMMU_RSV_VSID_DESC_IDX_END - 1)
+#define APUMMU_APMCU_RSV_DESC_IDX (APUMMU_RSV_VSID_DESC_IDX_END - 2)
+#define APUMMU_GPU_RSV_DESC_IDX (APUMMU_RSV_VSID_DESC_IDX_END - 3)
+
+#define APUMMU_SEG_OFFSET_0 (0)
+#define APUMMU_SEG_OFFSET_1 (1)
+#define APUMMU_SEG_OFFSET_2 (2)
+#define APUMMU_VSID_EN_MASK (0x1f)
+
+#define APUMMU_HW_THREAD_MAX (7)
+#define APUMMU_SEG_MAX (9)
+#define APUMMU_ADDR_SHIFT (12)
+
+#define VSID_THREAD_SZ (0x4)
+#define VSID_CORID_MASK (0x7f)
+#define VSID_CORID_OFF (11)
+#define VSID_IDX_MASK (0xff)
+#define VSID_IDX_OFF (3)
+#define VSID_VALID_MASK (0x1)
+#define VSID_COR_VALID_OFF (1)
+#define VSID_VALID_OFF (0)
+
+#define APUMMU_VSID_ACTIVE (32)
+#define APUMMU_VSID_RSV (4)
+#define APUMMU_VSID_UNUSED (12)
+#define APUMMU_VSID_USE_MAX (APUMMU_VSID_ACTIVE + APUMMU_VSID_RSV)
+
+#if ((APUMMU_VSID_RSV + APUMMU_VSID_ACTIVE + APUMMU_VSID_UNUSED + 1) > APUMMU_VSID_SRAM_TOTAL)
+#error APUMMU VSID Overflow
+#endif
+
+#define APUMMU_RSV_VSID_IDX_END (254)
+#define APUMMU_RSV_VSID_IDX_START (APUMMU_RSV_VSID_IDX_END - APUMMU_VSID_RSV + 1)
+
+#if ((APUMMU_RSV_VSID_IDX_END - APUMMU_RSV_VSID_IDX_START) > APUMMU_VSID_RSV)
+#error APUMMU VSID RSV Overflow
+#endif
+
+/* Reserve */
+#define APUMMU_UPRV_RSV_VSID (APUMMU_RSV_VSID_IDX_END)
+#define APUMMU_LOGGER_RSV_VSID (APUMMU_RSV_VSID_IDX_END - 1)
+#define APUMMU_APMCU_RSV_VSID (APUMMU_RSV_VSID_IDX_END - 2)
+#define APUMMU_GPU_RSV_VSID (APUMMU_RSV_VSID_IDX_END - 3)
+
+/* VSID bit mask */
+#define APUMMU_VSID_MAX_MASK_WORD ((APUMMU_VSID_USE_MAX + 32 - 1) / 32)
+
+/* VSID fields */
+#define READ_VSID_FIELD(vids, sg, offset, shift, mask) \
+ ((mmio_read_32(APUMMU_VSID_SEGMENT_BASE(vsid, seg, offset)) >> sift) & mask)
+#define READ_VSID_FIELD_OFFESET0(vids, sg, shift, mask) \
+ READ_VSID_FIELD(vids, sg, 0, shift, mask)
+#define READ_VSID_FIELD_OFFESET1(vids, sg, shift, mask) \
+ READ_VSID_FIELD(vids, sg, 1, shift, mask)
+#define READ_VSID_FIELD_OFFESET2(vids, sg, shift, mask) \
+ READ_VSID_FIELD(vids, sg, 2, shift, mask)
+
+/* Get segment offset 0 data - 0x00 */
+#define APUMMU_SEGMENT_GET_INPUT(vsid, seg) \
+ READ_VSID_FIELD_OFFESET0(vsid, seg, 10, 0x3FFFFF)
+#define APUMMU_SEGMENT_GET_OFFSET0_RSRV(vsid, seg) \
+ READ_VSID_FIELD_OFFESET0(vsid, seg, 6, 0xF)
+#define APUMMU_SEGMENT_GET_PAGELEN(vsid, seg) \
+ READ_VSID_FIELD_OFFESET0(vsid, seg, 0, 0x7)
+#define APUMMU_SEGMENT_GET_PAGESEL(vsid, seg) \
+ READ_VSID_FIELD_OFFESET0(vsid, seg, 3, 0x7)
+
+/* Get segment offset 1 data - 0x04 */
+#define APUMMU_SEGMENT_GET_IOMMU_EN(vsid, seg) \
+ READ_VSID_FIELD_OFFESET1(vsid, seg, 1, 0x1)
+#define APUMMU_SEGMENT_GET_OFFSET1_RSRV0(vsid, seg) \
+ READ_VSID_FIELD_OFFESET1(vsid, seg, 2, 0xFF)
+#define APUMMU_SEGMENT_GET_OFFSET1_RSRV1(vsid, seg) \
+ READ_VSID_FIELD_OFFESET1(vsid, seg, 0, 0x1)
+#define APUMMU_SEGMENT_GET_OUTPUT(vsid, seg) \
+ READ_VSID_FIELD_OFFESET1(vsid, seg, 10, 0x3FFFFF)
+
+/* Get segment offset 2 data - 0x08 */
+#define APUMMU_SEGMENT_GET_ACP_EN(vsid, seg) \
+ READ_VSID_FIELD_OFFESET2(vsid, seg, 12, 0x1)
+#define APUMMU_SEGMENT_GET_AR_CACHE_ALLOC(vsid, seg) \
+ READ_VSID_FIELD_OFFESET2(vsid, seg, 4, 0x1)
+#define APUMMU_SEGMENT_GET_AR_EXCLU(vsid, seg) \
+ READ_VSID_FIELD_OFFESET2(vsid, seg, 9, 0x1)
+#define APUMMU_SEGMENT_GET_AR_SEPCU(vsid, seg) \
+ READ_VSID_FIELD_OFFESET2(vsid, seg, 8, 0x1)
+#define APUMMU_SEGMENT_GET_AR_SLB_EN(vsid, seg) \
+ READ_VSID_FIELD_OFFESET2(vsid, seg, 2, 0x1)
+#define APUMMU_SEGMENT_GET_AR_SLC_EN(vsid, seg) \
+ READ_VSID_FIELD_OFFESET2(vsid, seg, 3, 0x1)
+#define APUMMU_SEGMENT_GET_AW_CACHE_ALLOC(vsid, seg) \
+ READ_VSID_FIELD_OFFESET2(vsid, seg, 7, 0x1)
+#define APUMMU_SEGMENT_GET_AW_CLR(vsid, seg) \
+ READ_VSID_FIELD_OFFESET2(vsid, seg, 11, 0x1)
+#define APUMMU_SEGMENT_GET_AW_INVALID(vsid, seg) \
+ READ_VSID_FIELD_OFFESET2(vsid, seg, 10, 0x1)
+#define APUMMU_SEGMENT_GET_AW_SLB_EN(vsid, seg) \
+ READ_VSID_FIELD_OFFESET2(vsid, seg, 5, 0x1)
+#define APUMMU_SEGMENT_GET_AW_SLC_EN(vsid, seg) \
+ READ_VSID_FIELD_OFFESET2(vsid, seg, 6, 0x1)
+#define APUMMU_SEGMENT_GET_DOMAIN(vsid, seg) \
+ READ_VSID_FIELD_OFFESET2(vsid, seg, 13, 0xF)
+#define APUMMU_SEGMENT_GET_NS(vsid, seg) \
+ READ_VSID_FIELD_OFFESET2(vsid, seg, 0, 0x1)
+
+/* Build segment data */
+/* Build segment offset 0 (0x00) data */
+#define APUMMU_VSID_SEGMENT_00_INPUT(input_adr) (((input_adr) & 0x3fffff) << 10)
+#define APUMMU_VSID_SEGMENT_00_PAGESEL(page_sel) (((page_sel) & 0x7) << 3)
+#define APUMMU_VSID_SEGMENT_00_PAGELEN(page_len) (((page_len) & 0x7) << 0)
+#define APUMMU_VSID_SEGMENT_00_RESV(resv) (((resv) & 0xf) << 6)
+
+#define APUMMU_BUILD_SEGMENT_OFFSET0(input_adr, resv, page_sel, page_len) \
+ (APUMMU_VSID_SEGMENT_00_INPUT(input_adr) | \
+ APUMMU_VSID_SEGMENT_00_RESV(resv) | \
+ APUMMU_VSID_SEGMENT_00_PAGESEL(page_sel) | \
+ APUMMU_VSID_SEGMENT_00_PAGELEN(page_len))
+
+/* Build segment offset 1 (0x04) data */
+#define APUMMU_VSID_SEGMENT_04_IOMMU_EN(iommu_en) (((iommu_en) & 0x1) << 1)
+#define APUMMU_VSID_SEGMENT_04_OUTPUT(output_adr) (((output_adr) & 0x3fffff) << 10)
+#define APUMMU_VSID_SEGMENT_04_RESV0(resv0) (((resv0) & 0xff) << 2)
+#define APUMMU_VSID_SEGMENT_04_RESV1(resv1) (((resv1) & 0x1) << 0)
+
+#define APUMMU_BUILD_SEGMENT_OFFSET1(output_adr, resv0, iommu_en, resv1) \
+ (APUMMU_VSID_SEGMENT_04_OUTPUT(output_adr) | \
+ APUMMU_VSID_SEGMENT_04_RESV0(resv0) | \
+ APUMMU_VSID_SEGMENT_04_IOMMU_EN(iommu_en) | \
+ APUMMU_VSID_SEGMENT_04_RESV1(resv1))
+
+/* Build segment offset 2 (0x08) data */
+#define APUMMU_VSID_SEGMENT_08_DOMAIN_MASK (0xf)
+#define APUMMU_VSID_SEGMENT_08_DOMAIN_SHIFT (13)
+#define APUMMU_VSID_SEGMENT_08_RESV_MASK (0x7fff)
+#define APUMMU_VSID_SEGMENT_08_RESV_SHIFT (17)
+
+#define APUMMU_VSID_SEGMENT_08_DOMAIN(domain) \
+ (((domain) & APUMMU_VSID_SEGMENT_08_DOMAIN_MASK) << APUMMU_VSID_SEGMENT_08_DOMAIN_SHIFT)
+#define APUMMU_VSID_SEGMENT_08_RESV(resv) \
+ (((resv) & APUMMU_VSID_SEGMENT_08_RESV_MASK) << APUMMU_VSID_SEGMENT_08_RESV_SHIFT)
+
+#define APUMMU_VSID_SEGMENT_08_ACP_EN(acp_en) (((acp_en) & 0x1) << 12)
+#define APUMMU_VSID_SEGMENT_08_AR_EXCLU(ar_exclu) (((ar_exclu) & 0x1) << 9)
+#define APUMMU_VSID_SEGMENT_08_AR_SEPCU(ar_sepcu) (((ar_sepcu) & 0x1) << 8)
+#define APUMMU_VSID_SEGMENT_08_AR_SLB_EN(ar_slb_en) (((ar_slb_en) & 0x1) << 2)
+#define APUMMU_VSID_SEGMENT_08_AR_SLC_EN(ar_slc_en) (((ar_slc_en) & 0x1) << 3)
+#define APUMMU_VSID_SEGMENT_08_AW_CLR(aw_clr) (((aw_clr) & 0x1) << 11)
+#define APUMMU_VSID_SEGMENT_08_AW_INVALID(aw_invalid) (((aw_invalid) & 0x1) << 10)
+#define APUMMU_VSID_SEGMENT_08_AW_SLB_EN(aw_slb_en) (((aw_slb_en) & 0x1) << 5)
+#define APUMMU_VSID_SEGMENT_08_AW_SLC_EN(aw_slc_en) (((aw_slc_en) & 0x1) << 6)
+#define APUMMU_VSID_SEGMENT_08_NS(ns) (((ns) & 0x1) << 0)
+#define APUMMU_VSID_SEGMENT_08_RO(ro) (((ro) & 0x1) << 1)
+
+#define APUMMU_VSID_SEGMENT_08_AR_CACHE_ALLOCATE(ar_cache_allocate) \
+ (((ar_cache_allocate) & 0x1) << 4)
+#define APUMMU_VSID_SEGMENT_08_AW_CACHE_ALLOCATE(aw_cache_allocate) \
+ (((aw_cache_allocate) & 0x1) << 7)
+
+#define APUMMU_BUILD_SEGMENT_OFFSET2(resv, domain, acp_en, aw_clr, \
+ aw_invalid, ar_exclu, ar_sepcu, \
+ aw_cache_allocate, aw_slc_en, aw_slb_en, ar_cache_allocate, \
+ ar_slc_en, ar_slb_en, ro, ns) \
+ ((APUMMU_VSID_SEGMENT_08_RESV(resv)) |\
+ (APUMMU_VSID_SEGMENT_08_DOMAIN(domain)) |\
+ (APUMMU_VSID_SEGMENT_08_ACP_EN(acp_en)) |\
+ (APUMMU_VSID_SEGMENT_08_AW_CLR(aw_clr)) |\
+ (APUMMU_VSID_SEGMENT_08_AW_INVALID(aw_invalid)) |\
+ (APUMMU_VSID_SEGMENT_08_AR_EXCLU(ar_exclu)) |\
+ (APUMMU_VSID_SEGMENT_08_AR_SEPCU(ar_sepcu)) |\
+ (APUMMU_VSID_SEGMENT_08_AW_CACHE_ALLOCATE(aw_cache_allocate)) |\
+ (APUMMU_VSID_SEGMENT_08_AW_SLC_EN(aw_slc_en)) |\
+ (APUMMU_VSID_SEGMENT_08_AW_SLB_EN(aw_slb_en)) |\
+ (APUMMU_VSID_SEGMENT_08_AR_CACHE_ALLOCATE(ar_cache_allocate)) |\
+ (APUMMU_VSID_SEGMENT_08_AR_SLC_EN(ar_slc_en)) |\
+ (APUMMU_VSID_SEGMENT_08_AR_SLB_EN(ar_slb_en)) |\
+ (APUMMU_VSID_SEGMENT_08_RO(ro)) | (APUMMU_VSID_SEGMENT_08_NS(ns)))
+
+/* Build segment offset 3 (0x0c) data */
+#define APUMMU_VSID_SEGMENT_0C_RESV(rsv) (((rsv) & 0x7fffffff) << 0)
+#define APUMMU_VSID_SEGMENT_0C_SEG_VALID(seg_valid) (((seg_valid) & 0x1U) << 31)
+#define APUMMU_BUILD_SEGMENT_OFFSET3(seg_valid, rsv) \
+ ((uint32_t)APUMMU_VSID_SEGMENT_0C_SEG_VALID(seg_valid) | \
+ APUMMU_VSID_SEGMENT_0C_RESV(rsv))
+
+#define APUMMU_INT_D2T_TBL0_OFS (0x40)
+
+#define APUSYS_TCM (0x4d100000)
+
+enum {
+ APUMMU_THD_ID_APMCU_NORMAL = 0,
+ APUMMU_THD_ID_TEE,
+};
+
+int rv_boot(uint32_t uP_seg_output, uint8_t uP_hw_thread,
+ enum apummu_page_size logger_page_size, uint32_t XPU_seg_output,
+ enum apummu_page_size XPU_page_size);
+
+#endif
diff --git a/plat/mediatek/drivers/apusys/mt8196/apusys_devapc.c b/plat/mediatek/drivers/apusys/mt8196/apusys_devapc.c
new file mode 100644
index 0000000..09e35f1
--- /dev/null
+++ b/plat/mediatek/drivers/apusys/mt8196/apusys_devapc.c
@@ -0,0 +1,337 @@
+/*
+ * Copyright (c) 2024, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <lib/utils_def.h>
+#include <platform_def.h>
+
+#include <apusys_devapc.h>
+#include <apusys_devapc_def.h>
+#include <mtk_mmap_pool.h>
+
+/* AO CONTROL DEVAPC - apu_rcx_ao_infra_dapc_con */
+static const struct apc_dom_16 APUSYS_CTRL_DAPC_AO[] = {
+ /* ctrl index = 0 */
+ SLAVE_RCX_BULK0("apu_ao_ctl_o-0"),
+ SLAVE_MD32_APB("apu_ao_ctl_o-1"),
+ SLAVE_ACP_TCU_SSC("apu_ao_ctl_o-2"),
+ SLAVE_PTP_THM("apu_ao_ctl_o-3"),
+ SLAVE_VCORE("apu_ao_ctl_o-4"),
+ SLAVE_IOMMU0_BANK0("apu_ao_ctl_o-5"),
+ SLAVE_IOMMU0_BANK1("apu_ao_ctl_o-6"),
+ SLAVE_IOMMU0_BANK2("apu_ao_ctl_o-7"),
+ SLAVE_IOMMU0_BANK3("apu_ao_ctl_o-8"),
+ SLAVE_IOMMU0_BANK4("apu_ao_ctl_o-9"),
+
+ /* ctrl index = 10 */
+ SLAVE_IOMMU1_BANK0("apu_ao_ctl_o-10"),
+ SLAVE_IOMMU1_BANK1("apu_ao_ctl_o-11"),
+ SLAVE_IOMMU1_BANK2("apu_ao_ctl_o-12"),
+ SLAVE_IOMMU1_BANK3("apu_ao_ctl_o-13"),
+ SLAVE_IOMMU1_BANK4("apu_ao_ctl_o-14"),
+ SLAVE_S0_SSC("apu_ao_ctl_o-15"),
+ SLAVE_N0_SSC("apu_ao_ctl_o-16"),
+ SLAVE_S1_SSC("apu_ao_ctl_o-17"),
+ SLAVE_N1_SSC("apu_ao_ctl_o-18"),
+ SLAVE_ACP_SSC("apu_ao_ctl_o-19"),
+
+ /* ctrl index = 20 */
+ SLAVE_WDEC("apu_ao_ctl_o-20"),
+ SLAVE_SMMU_IP_REG("apu_ao_ctl_o-21"),
+ SLAVE_SMMU_NSEC("apu_ao_ctl_o-22"),
+ SLAVE_SMMU_SEC("apu_ao_ctl_o-23"),
+ SLAVE_ARE0("apu_ao_ctl_o-24"),
+ SLAVE_ARE1("apu_ao_ctl_o-25"),
+ SLAVE_SONC("apu_ao_ctl_o-26"),
+ SLAVE_RPC("apu_ao_ctl_o-28"),
+ SLAVE_PCU("apu_ao_ctl_o-29"),
+ SLAVE_AO_CTRL("apu_ao_ctl_o-30"),
+
+ /* ctrl index = 30 */
+ SLAVE_AO_CTRL("apu_ao_ctl_o-31"),
+ SLAVE_ACC("apu_ao_ctl_o-32"),
+ SLAVE_SEC("apu_ao_ctl_o-33"),
+ SLAVE_PLL("apu_ao_ctl_o-34"),
+ SLAVE_RPC_MDLA("apu_ao_ctl_o-35"),
+ SLAVE_TOP_PMU("apu_ao_ctl_o-36"),
+ SLAVE_AO_BCRM("apu_ao_ctl_o-37"),
+ SLAVE_AO_DAPC_WRAP("apu_ao_ctl_o-38"),
+ SLAVE_AO_DAPC_CON("apu_ao_ctl_o-39"),
+ SLAVE_UNDEFINE0("apu_ao_ctl_o-40"),
+
+ /* ctrl index = 40 */
+ SLAVE_UNDEFINE1("apu_ao_ctl_o-41"),
+ SLAVE_RCX_BULK0("apu_ao_ctl_o-42"),
+ SLAVE_UNDEFINE2("apu_ao_ctl_o-43"),
+ SLAVE_UNDEFINE3("apu_ao_ctl_o-44"),
+ SLAVE_UNDEFINE4("apu_ao_ctl_o-45"),
+ SLAVE_UNDEFINE5("apu_ao_ctl_o-46"),
+ SLAVE_UNDEFINE6("apu_ao_ctl_o-47"),
+ SLAVE_UNDEFINE7("apu_ao_ctl_o-48"),
+ SLAVE_DATA_BULK("apu_ao_ctl_o-49"),
+ SLAVE_ACX0_BULK("apu_ao_ctl_o-50"),
+
+ /* ctrl index = 50 */
+ SLAVE_ACX0_AO("apu_ao_ctl_o-51"),
+ SLAVE_ACX1_BULK("apu_ao_ctl_o-52"),
+ SLAVE_ACX1_AO("apu_ao_ctl_o-53"),
+ SLAVE_NCX_BULK("apu_ao_ctl_o-54"),
+ SLAVE_NCX_AO("apu_ao_ctl_o-55"),
+ SLAVE_ACX0_BULK("apu_rcx2acx0_o-0"),
+ SLAVE_ACX0_AO("apu_rcx2acx0_o-1"),
+ SLAVE_ACX0_BULK("apu_sae2acx0_o-0"),
+ SLAVE_ACX0_AO("apu_sae2acx0_o-1"),
+ SLAVE_ACX1_BULK("apu_rcx2acx1_o-0"),
+
+ /* ctrl index = 60 */
+ SLAVE_ACX1_AO("apu_rcx2acx1_o-1"),
+ SLAVE_ACX1_BULK("apu_sae2acx1_o-0"),
+ SLAVE_ACX1_AO("apu_sae2acx1_o-1"),
+ SLAVE_NCX_BULK("apu_rcx2ncx_o-0"),
+ SLAVE_NCX_AO("apu_rcx2ncx_o-1"),
+ SLAVE_NCX_BULK("apu_sae2ncx_o-0"),
+ SLAVE_NCX_AO("apu_sae2ncx_o-1"),
+};
+
+
+/* RCX CONTROL DEVAPC - apu_rcx_infra_dapc_con */
+static const struct apc_dom_16 APUSYS_CTRL_DAPC_RCX[] = {
+ /* ctrl index = 0 */
+ SLAVE_ACX0_BULK("acx0_apbs-0"),
+ SLAVE_ACX0_RPC("acx0_apbs-1"),
+ SLAVE_ACX0_AO_CTRL("acx0_apbs-2"),
+ SLAVE_UNDEFINE8("acx0_apbs-3"),
+ SLAVE_ACX1_BULK("acx1_apbs-0"),
+ SLAVE_ACX1_RPC("acx1_apbs-1"),
+ SLAVE_ACX1_AO_CTRL("acx1_apbs-2"),
+ SLAVE_UNDEFINE9("acx1_apbs-3"),
+ SLAVE_NCX_BULK("ncx_apbs-0"),
+ SLAVE_NCX_RPC("ncx_apbs-1"),
+
+ /* ctrl index = 10 */
+ SLAVE_NCX_AO_CTRL("ncx_apbs-2"),
+ SLAVE_UNDEFINE10("ncx_apbs-3"),
+ SLAVE_MD32_SYSCTRL("md32_apb_s-0"),
+ SLAVE_MD32_PMU("md32_apb_s-1"),
+ SLAVE_MD32_WDT("md32_apb_s-2"),
+ SLAVE_MD32_CACHE("md32_apb_s-3"),
+ SLAVE_ARE0("apusys_ao-0"),
+ SLAVE_ARE1("apusys_ao-1"),
+ SLAVE_SONC("apusys_ao-2"),
+ SLAVE_RPC("apusys_ao-3"),
+
+ /* ctrl index = 20 */
+ SLAVE_PCU("apusys_ao-4"),
+ SLAVE_AO_CTRL("apusys_ao-5"),
+ SLAVE_AO_CTRL("apusys_ao-6"),
+ SLAVE_SEC("apusys_ao-7"),
+ SLAVE_PLL("apusys_ao-8"),
+ SLAVE_RPC_MDLA("apusys_ao-9"),
+ SLAVE_TOP_PMU("apusys_ao-10"),
+ SLAVE_AO_BCRM("apusys_ao-11"),
+ SLAVE_AO_DAPC_WRAP("apusys_ao-12"),
+ SLAVE_AO_DAPC_CON("apusys_ao-13"),
+
+ /* ctrl index = 30 */
+ SLAVE_VCORE("apusys_ao-14"),
+ SLAVE_IOMMU0_BANK0("apusys_ao-15"),
+ SLAVE_IOMMU0_BANK1("apusys_ao-16"),
+ SLAVE_IOMMU0_BANK2("apusys_ao-17"),
+ SLAVE_IOMMU0_BANK3("apusys_ao-18"),
+ SLAVE_IOMMU0_BANK4("apusys_ao-19"),
+ SLAVE_IOMMU1_BANK0("apu_ao_ctl_o-20"),
+ SLAVE_IOMMU1_BANK1("apu_ao_ctl_o-21"),
+ SLAVE_IOMMU1_BANK2("apu_ao_ctl_o-22"),
+ SLAVE_IOMMU1_BANK3("apu_ao_ctl_o-23"),
+
+ /* ctrl index = 40 */
+ SLAVE_IOMMU1_BANK4("apu_ao_ctl_o-24"),
+ SLAVE_S0_SSC("apu_ao_ctl_o-25"),
+ SLAVE_N0_SSC("apu_ao_ctl_o-26"),
+ SLAVE_S1_SSC("apu_ao_ctl_o-27"),
+ SLAVE_N1_SSC("apu_ao_ctl_o-28"),
+ SLAVE_ACP_SSC("apu_ao_ctl_o-29"),
+ SLAVE_ACP_TCU_SSC("apu_ao_ctl_o-30"),
+ SLAVE_PTP_THM("apu_ao_ctl_o-31"),
+ SLAVE_WDEC("apu_ao_ctl_o-32"),
+ SLAVE_SMMU_IP_REG("apu_ao_ctl_o-33"),
+
+ /* ctrl index = 50 */
+ SLAVE_SMMU_NSEC("apu_ao_ctl_o-34"),
+ SLAVE_SMMU_SEC("apu_ao_ctl_o-35"),
+ SLAVE_DATA_BULK("noc_axi"),
+ SLAVE_MD32_DBG("md32_dbg"),
+ SLAVE_MDLA_DBG("mdla_dbg"),
+ SLAVE_INFRA_DBG("apb_infra_dbg"),
+ SLAVE_LOG_TOP0("apu_logtop-0"),
+ SLAVE_LOG_TOP1("apu_logtop-1"),
+ SLAVE_RCX_CFG("apu_rcx_cfg"),
+ SLAVE_ACX_IPS("apu_acx_ips"),
+
+ /* ctrl index = 60 */
+ SLAVE_SEMA_STIMER("apu_sema_stimer"),
+ SLAVE_EMI_CFG("apu_emi_cfg"),
+ SLAVE_CPE_SENSOR("apu_cpe_sensor"),
+ SLAVE_CPE_COEF("apu_cpe_coef"),
+ SLAVE_CPE_CTRL("apu_cpe_ctrl"),
+ SLAVE_TPPA("apu_dfd"),
+ SLAVE_SENSOR_ACX0_DLA0("apu_sen_acx0_dla0"),
+ SLAVE_SENSOR_ACX0_VPU("apu_sen_acx0_vpu"),
+ SLAVE_SENSOR_ACX1_DLA0("apu_sen_acx1_dla0"),
+ SLAVE_SENSOR_ACX1_VPU("apu_sen_acx1_vpu"),
+
+ /* ctrl index = 70 */
+ SLAVE_SENSOR_NCX_DLA0("apu_sen_ncx_dla0"),
+ SLAVE_SENSOR_NCX_NVE("apu_sen_ncx_nve"),
+ SLAVE_RCX_TCU0("noc_cfg-0"),
+ SLAVE_RCX_TCU1("noc_cfg-1"),
+ SLAVE_RCX_TCU2("noc_cfg-2"),
+ SLAVE_RCX_TCU3("noc_cfg-3"),
+ SLAVE_RCX_TCU4("noc_cfg-4"),
+ SLAVE_RCX_TCU5("noc_cfg-5"),
+ SLAVE_RCX_TCU6("noc_cfg-6"),
+ SLAVE_RCX_NOC_CFG("noc_cfg-7"),
+
+ /* ctrl index = 80 */
+ SLAVE_SCMDQ("apu_hse-0"),
+ SLAVE_HSE("apu_hse-1"),
+ SLAVE_MDLA_CORE_CTRL("mdla_cfg-0"),
+ SLAVE_MDLA_BIU("mdla_cfg-1"),
+ SLAVE_MDLA_PMU("mdla_cfg-2"),
+ SLAVE_MDLA_CMDE("mdla_cfg-3"),
+ SLAVE_EDPA0("apu_edpa-0"),
+ SLAVE_EDPA1("apu_edpa-1"),
+ SLAVE_RCX_BCRM("infra_bcrm"),
+ SLAVE_RCX_DAPC_WRAP("infra_dpac_wrap"),
+
+ /* ctrl index = 90 */
+ SLAVE_RCX_DAPC_CON("infra_dapc_con"),
+ SLAVE_RCX_CMU("rcx_cmu"),
+ SLAVE_RCX_ACS("apu_rcx_acs"),
+ SLAVE_RCX_CBFC("rcx_cbfc"),
+ SLAVE_ACC("acc"),
+};
+
+static enum apusys_apc_err_status set_slave_ctrl_apc(uint32_t slave,
+ enum apusys_apc_type type,
+ enum apusys_apc_domain_id domain_id,
+ enum apusys_apc_perm_type perm)
+{
+ uint32_t apc_register_index;
+ uint32_t apc_set_index;
+ uint32_t base = 0;
+ uint32_t clr_bit;
+ uint32_t set_bit;
+ uint32_t slave_num_in_1_dom;
+ uint32_t slave_num, dom_num;
+ uint32_t dapc_base;
+
+ if (perm >= PERM_NUM) {
+ ERROR("%s: permission type:0x%x is not supported!\n", __func__, perm);
+ return APUSYS_APC_ERR_PERMISSION_NOT_SUPPORTED;
+ }
+
+ switch (type) {
+ case DAPC_AO:
+ slave_num_in_1_dom = APUSYS_CTRL_DAPC_AO_SLAVE_NUM_IN_1_DOM;
+ slave_num = APUSYS_CTRL_DAPC_AO_SLAVE_NUM;
+ dom_num = APUSYS_CTRL_DAPC_AO_DOM_NUM;
+ dapc_base = APUSYS_CTRL_DAPC_AO_BASE;
+ break;
+ case DAPC_RCX:
+ slave_num_in_1_dom = APUSYS_CTRL_DAPC_RCX_SLAVE_NUM_IN_1_DOM;
+ slave_num = APUSYS_CTRL_DAPC_RCX_SLAVE_NUM;
+ dom_num = APUSYS_CTRL_DAPC_RCX_DOM_NUM;
+ dapc_base = APUSYS_CTRL_DAPC_RCX_BASE;
+ break;
+ default:
+ ERROR("%s: unsupported devapc type: %u\n", __func__, type);
+ return APUSYS_APC_ERR_GENERIC;
+ }
+
+ apc_register_index = slave / slave_num_in_1_dom;
+ apc_set_index = slave % slave_num_in_1_dom;
+
+ clr_bit = DEVAPC_MASK << (apc_set_index * DEVAPC_DOM_SHIFT);
+ set_bit = (uint32_t)perm << (apc_set_index * DEVAPC_DOM_SHIFT);
+
+ if (slave < slave_num && domain_id < dom_num) {
+ base = dapc_base + domain_id * DEVAPC_DOM_SIZE
+ + apc_register_index * DEVAPC_REG_SIZE;
+ } else {
+ ERROR("%s: out of boundary, devapc type: %d, slave: 0x%x, domain_id: 0x%x\n",
+ __func__, type, slave, domain_id);
+ return APUSYS_APC_ERR_OUT_OF_BOUNDARY;
+ }
+
+ if (!base)
+ return APUSYS_APC_ERR_GENERIC;
+
+ mmio_clrsetbits_32(base, clr_bit, set_bit);
+ return APUSYS_APC_OK;
+}
+
+static enum apusys_apc_err_status set_slave_ao_ctrl_apc(uint32_t slave,
+ enum apusys_apc_domain_id domain_id,
+ enum apusys_apc_perm_type perm)
+{
+ return set_slave_ctrl_apc(slave, DAPC_AO, domain_id, perm);
+}
+
+static enum apusys_apc_err_status set_slave_rcx_ctrl_apc(uint32_t slave,
+ enum apusys_apc_domain_id domain_id,
+ enum apusys_apc_perm_type perm)
+{
+ return set_slave_ctrl_apc(slave, DAPC_RCX, domain_id, perm);
+}
+
+static void apusys_devapc_init(uint32_t base)
+{
+ mmio_write_32(APUSYS_DAPC_CON(base), APUSYS_DAPC_CON_VIO_MASK);
+}
+
+int apusys_devapc_ao_init(void)
+{
+ int32_t ret = APUSYS_APC_OK;
+
+ apusys_devapc_init(APUSYS_CTRL_DAPC_AO_BASE);
+
+ ret = SET_APUSYS_DAPC_V1(APUSYS_CTRL_DAPC_AO, set_slave_ao_ctrl_apc);
+
+ if (ret) {
+ ERROR("[APUAPC_AO] %s: set_apusys_ao_ctrl_dapc failed\n", __func__);
+ return ret;
+ }
+
+#ifdef DUMP_CFG
+ DUMP_APUSYS_DAPC_V1(APUSYS_CTRL_DAPC_AO);
+#endif
+
+ INFO("[APUAPC_AO] %s done\n", __func__);
+
+ return ret;
+}
+
+int apusys_devapc_rcx_init(void)
+{
+ int32_t ret = APUSYS_APC_OK;
+
+ apusys_devapc_init(APUSYS_CTRL_DAPC_RCX_BASE);
+
+ ret = SET_APUSYS_DAPC_V1(APUSYS_CTRL_DAPC_RCX, set_slave_rcx_ctrl_apc);
+ if (ret) {
+ ERROR("[APUAPC_RCX] %s: set_slave_rcx_ctrl_apc failed\n", __func__);
+ return ret;
+ }
+
+#ifdef DUMP_CFG
+ DUMP_APUSYS_DAPC_V1(APUSYS_CTRL_DAPC_RCX);
+#endif
+
+ INFO("[APUAPC_RCX] %s done\n", __func__);
+
+ return ret;
+}
diff --git a/plat/mediatek/drivers/apusys/mt8196/apusys_devapc.h b/plat/mediatek/drivers/apusys/mt8196/apusys_devapc.h
new file mode 100644
index 0000000..8d6204e
--- /dev/null
+++ b/plat/mediatek/drivers/apusys/mt8196/apusys_devapc.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2024, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef APUSYS_DEVAPC_H
+#define APUSYS_DEVAPC_H
+
+enum apusys_apc_type {
+ DAPC_AO = 0,
+ DAPC_RCX
+};
+
+int apusys_devapc_ao_init(void);
+int apusys_devapc_rcx_init(void);
+
+#endif /* APUSYS_DEVAPC_H */
diff --git a/plat/mediatek/drivers/apusys/mt8196/apusys_devapc_def.h b/plat/mediatek/drivers/apusys/mt8196/apusys_devapc_def.h
new file mode 100644
index 0000000..af63c0c
--- /dev/null
+++ b/plat/mediatek/drivers/apusys/mt8196/apusys_devapc_def.h
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2024, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef APUSYS_DEVAPC_DEF_H
+#define APUSYS_DEVAPC_DEF_H
+
+#include <lib/mmio.h>
+
+#include <devapc/apusys_dapc_v1.h>
+
+/* Control */
+#define SLAVE_RCX_BULK0 SLAVE_FORBID_EXCEPT_D0_D11_NO_PROTECT_D3_D5_D8_SEC_RW
+#define SLAVE_RCX_BULK1 SLAVE_FORBID_EXCEPT_D0_NO_PROTECT_D5_D8_SEC_RW
+#define SLAVE_MD32_APB SLAVE_FORBID_EXCEPT_D0_SEC_RW_NS_R_D3_D5_SEC_RW
+#define SLAVE_ACP_TCU_SSC SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_VCORE SLAVE_FORBID_EXCEPT_D0_NO_PROTECT_D3_D5_SEC_RW
+#define SLAVE_WDEC SLAVE_FORBID_EXCEPT_D0_D5_SEC_RW
+#define SLAVE_SMMU_IP_REG SLAVE_FORBID_EXCEPT_D3_D5_SEC_RW_D0_D4_D11_NO_PROTECT
+#define SLAVE_SMMU_NSEC SLAVE_FORBID_EXCEPT_D5_SEC_RW_D0_NO_PROTECT
+#define SLAVE_SMMU_SEC SLAVE_FORBID_EXCEPT_D0_D5_SEC_RW
+#define SLAVE_RPC SLAVE_FORBID_EXCEPT_D3_D5_SEC_RW_D0_D11_NO_PROTECT
+#define SLAVE_PCU SLAVE_FORBID_EXCEPT_D0_SEC_RW_NS_R_D3_D5_SEC_RW
+#define SLAVE_AO_CTRL SLAVE_FORBID_EXCEPT_D0_D3_D5_SEC_RW
+#define SLAVE_ACC SLAVE_FORBID_EXCEPT_D0_SEC_RW_NS_R_D3_D5_SEC_RW
+#define SLAVE_PLL SLAVE_FORBID_EXCEPT_D0_SEC_RW_NS_R_D5_D8_SEC_RW
+#define SLAVE_SEC SLAVE_FORBID_EXCEPT_D0_D5_SEC_RW
+#define SLAVE_ARE0 SLAVE_FORBID_EXCEPT_D0_SEC_RW_NS_R_D5_SEC_RW
+#define SLAVE_ARE1 SLAVE_FORBID_EXCEPT_D0_D11_NO_PROTECT_D3_D5_D8_SEC_RW
+#define SLAVE_RPC_MDLA SLAVE_FORBID_EXCEPT_D5_D8_SEC_RW
+#define SLAVE_MDLA_DBG SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_TOP_PMU SLAVE_FORBID_EXCEPT_D5_D8_SEC_RW
+#define SLAVE_UNDEFINE0 SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_UNDEFINE1 SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_UNDEFINE2 SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_UNDEFINE3 SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_UNDEFINE4 SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_UNDEFINE5 SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_UNDEFINE6 SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_UNDEFINE7 SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_UNDEFINE8 SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_UNDEFINE9 SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_UNDEFINE10 SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_DATA_BULK SLAVE_FORBID_EXCEPT_D0_D5_SEC_RW
+#define SLAVE_AO_BCRM SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_AO_DAPC_WRAP SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_AO_DAPC_CON SLAVE_FORBID_EXCEPT_D0_D5_SEC_RW
+#define SLAVE_ACX0_AO SLAVE_FORBID_EXCEPT_D0_SEC_RW_NS_R_D5_SEC_RW
+#define SLAVE_ACX0_BULK SLAVE_FORBID_EXCEPT_D0_SEC_RW_NS_R_D5_SEC_RW
+#define SLAVE_ACX0_RPC SLAVE_FORBID_EXCEPT_D0_SEC_RW_NS_R_D5_SEC_RW
+#define SLAVE_ACX0_AO_CTRL SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_ACX1_AO SLAVE_FORBID_EXCEPT_D0_SEC_RW_NS_R_D5_SEC_RW
+#define SLAVE_ACX1_BULK SLAVE_FORBID_EXCEPT_D0_SEC_RW_NS_R_D5_SEC_RW
+#define SLAVE_ACX1_RPC SLAVE_FORBID_EXCEPT_D0_SEC_RW_NS_R_D5_SEC_RW
+#define SLAVE_ACX1_AO_CTRL SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_NCX_AO SLAVE_FORBID_EXCEPT_D0_SEC_RW_NS_R_D5_SEC_RW
+#define SLAVE_NCX_BULK SLAVE_FORBID_EXCEPT_D0_SEC_RW_NS_R_D5_SEC_RW
+#define SLAVE_NCX_RPC SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_NCX_AO_CTRL SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_MD32_SYSCTRL SLAVE_FORBID_EXCEPT_D0_D3_D5_SEC_RW
+#define SLAVE_MD32_PMU SLAVE_FORBID_EXCEPT_D0_SEC_RW_NS_R_D3_D5_SEC_RW
+#define SLAVE_LOG_TOP0 SLAVE_FORBID_EXCEPT_D0_D5_D7_D14_NO_PROTECT
+#define SLAVE_LOG_TOP1 SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_RCX_CFG SLAVE_FORBID_EXCEPT_D0_NO_PROTECT_D3_D5_SEC_RW
+#define SLAVE_ACX_IPS SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_RCX_TCU0 SLAVE_FORBID_EXCEPT_D0_D5_SEC_RW
+#define SLAVE_RCX_TCU1 SLAVE_FORBID_EXCEPT_D0_D5_SEC_RW
+#define SLAVE_RCX_TCU2 SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_RCX_TCU3 SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_RCX_TCU4 SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_RCX_TCU5 SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_RCX_TCU6 SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_RCX_NOC_CFG SLAVE_FORBID_EXCEPT_D0_D5_SEC_RW
+#define SLAVE_MDLA_CORE_CTRL SLAVE_FORBID_EXCEPT_D0_D5_SEC_RW
+#define SLAVE_MDLA_BIU SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_MDLA_PMU SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_MDLA_CMDE SLAVE_FORBID_EXCEPT_D0_D5_SEC_RW
+#define SLAVE_EDPA0 SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_EDPA1 SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_RCX_CMU SLAVE_FORBID_EXCEPT_D0_D5_SEC_RW
+#define SLAVE_RCX_ACS SLAVE_FORBID_EXCEPT_D0_D5_SEC_RW
+#define SLAVE_MD32_WDT SLAVE_FORBID_EXCEPT_D0_D3_D5_SEC_RW
+#define SLAVE_MD32_CACHE SLAVE_FORBID_EXCEPT_D0_D5_SEC_RW
+#define SLAVE_MD32_DBG SLAVE_FORBID_EXCEPT_D0_NO_PROTECT_D5_SEC_RW
+#define SLAVE_INFRA_DBG SLAVE_FORBID_EXCEPT_D0_D5_SEC_RW
+#define SLAVE_IOMMU0_BANK0 SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_IOMMU0_BANK1 SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_IOMMU0_BANK2 SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_IOMMU0_BANK3 SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_IOMMU0_BANK4 SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_IOMMU1_BANK0 SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_IOMMU1_BANK1 SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_IOMMU1_BANK2 SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_IOMMU1_BANK3 SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_IOMMU1_BANK4 SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_S0_SSC SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_N0_SSC SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_ACP_SSC SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_S1_SSC SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_N1_SSC SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_SEMA_STIMER SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_EMI_CFG SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_CPE_SENSOR SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_CPE_COEF SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_CPE_CTRL SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_TPPA SLAVE_FORBID_EXCEPT_D5_D8_SEC_RW
+#define SLAVE_SENSOR_ACX0_DLA0 SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_SENSOR_ACX0_VPU SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_SENSOR_ACX1_DLA0 SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_SENSOR_ACX1_VPU SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_SENSOR_NCX_DLA0 SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_SENSOR_NCX_NVE SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_RCX_BCRM SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_RCX_DAPC_WRAP SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_RCX_DAPC_CON SLAVE_FORBID_EXCEPT_D0_D5_SEC_RW
+#define SLAVE_HSE SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_RCX_CBFC SLAVE_FORBID_EXCEPT_D5_SEC_RW
+#define SLAVE_SONC SLAVE_FORBID_EXCEPT_D0_D5_SEC_RW
+#define SLAVE_SCMDQ SLAVE_FORBID_EXCEPT_D5_SEC_RW
+
+#if DEBUG
+#define SLAVE_PTP_THM SLAVE_FORBID_EXCEPT_D0_NO_PROTECT_D5_SEC_RW
+#else
+#define SLAVE_PTP_THM SLAVE_FORBID_EXCEPT_D0_SEC_RW_NS_R_D5_SEC_RW
+#endif
+
+/* Power Domain: AO */
+#define APUSYS_CTRL_DAPC_AO_SLAVE_NUM_IN_1_DOM (16)
+#define APUSYS_CTRL_DAPC_AO_DOM_NUM (16)
+#define APUSYS_CTRL_DAPC_AO_SLAVE_NUM (67) /* 0~66 */
+#define DEVAPC_MASK (0x3U)
+#define DEVAPC_DOM_SHIFT (2)
+
+/* Power Domain: RCX */
+#define APUSYS_CTRL_DAPC_RCX_SLAVE_NUM_IN_1_DOM (16)
+#define APUSYS_CTRL_DAPC_RCX_DOM_NUM (16)
+#define APUSYS_CTRL_DAPC_RCX_SLAVE_NUM (95) /* 0~94 */
+
+/* Dump Config */
+#define DUMP_CFG
+
+#endif
diff --git a/plat/mediatek/drivers/apusys/mt8196/apusys_power.c b/plat/mediatek/drivers/apusys/mt8196/apusys_power.c
new file mode 100644
index 0000000..4262d63
--- /dev/null
+++ b/plat/mediatek/drivers/apusys/mt8196/apusys_power.c
@@ -0,0 +1,390 @@
+/*
+ * Copyright (c) 2024, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <inttypes.h>
+
+#define SPMI_ENABLE (0)
+
+#if SPMI_ENABLE
+#include <include/drivers/spmi_api.h>
+#endif
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/spinlock.h>
+#include <lib/utils_def.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+
+#include "apusys_power.h"
+
+static void apu_w_are(int entry, uint32_t reg, uint32_t data)
+{
+ uint32_t are_entry_addr;
+
+ are_entry_addr = APUSYS_BASE + APU_ARE + ARE_REG_SIZE * ARE_ENTRY(entry);
+ mmio_write_32(are_entry_addr, reg);
+ mmio_write_32((are_entry_addr + ARE_REG_SIZE), data);
+}
+
+static void get_pll_pcw(uint32_t clk_rate, uint32_t *r1, uint32_t *r2)
+{
+ unsigned int fvco = clk_rate;
+ unsigned int pcw_val;
+ unsigned int postdiv_val = 1;
+ unsigned int postdiv_reg = 0;
+
+ while (fvco <= OUT_CLK_FREQ_MIN) {
+ postdiv_val = postdiv_val << 1;
+ postdiv_reg = postdiv_reg + 1;
+ fvco = fvco << 1;
+ }
+
+ pcw_val = (fvco * (1 << DDS_SHIFT)) / BASIC_CLK_FREQ;
+
+ if (postdiv_reg == 0) {
+ pcw_val = pcw_val * 2;
+ postdiv_val = postdiv_val << 1;
+ postdiv_reg = postdiv_reg + 1;
+ }
+
+ *r1 = postdiv_reg;
+ *r2 = pcw_val;
+}
+
+static void buck_off_by_pcu(uint32_t ofs, uint32_t shift, uint32_t slv_id)
+{
+ uint32_t pmif_id = 0x0;
+ int retry = 10;
+
+ mmio_setbits_32(APUSYS_PCU + APU_PCUTOP_CTRL_SET, PMIC_IRQ_EN);
+ mmio_write_32(APUSYS_PCU + APU_PCU_PMIC_TAR_BUF1,
+ (ofs << PMIC_OFF_ADDR_OFF) | BIT(shift));
+ mmio_write_32(APUSYS_PCU + APU_PCU_PMIC_TAR_BUF2,
+ (slv_id << PMIC_SLVID_OFF) | (pmif_id << PMIC_PMIFID_OFF) | PCU_BUCK_OFF_CMD);
+ mmio_write_32(APUSYS_PCU + APU_PCU_PMIC_CMD, PMIC_CMD_EN);
+
+ while ((mmio_read_32(APUSYS_PCU + APU_PCU_PMIC_IRQ) & PMIC_CMD_IRQ) == 0) {
+ udelay(10);
+ if (--retry < 0)
+ ERROR("%s wait APU_PCU_PMIC_IRQ timeout !\n", __func__);
+ }
+
+ mmio_write_32(APUSYS_PCU + APU_PCU_PMIC_IRQ, PMIC_CMD_IRQ);
+}
+
+static void apu_buck_off_cfg(void)
+{
+ mmio_setbits_32(APUSYS_AO_CTL + APUSYS_AO_SRAM_SET, BIT(10));
+ mmio_setbits_32(APUSYS_AO_CTL + APUSYS_AO_SRAM_CLR, BIT(9));
+ mmio_setbits_32(APUSYS_AO_CTL + APUSYS_AO_SRAM_CLR, BIT(12));
+ mmio_setbits_32(APUSYS_AO_CTL + APUSYS_AO_SRAM_CLR, BIT(14));
+
+ mmio_clrbits_32(APUSYS_AO_CTL + APUSYS_AO_SRAM_SET, BIT(10));
+ mmio_clrbits_32(APUSYS_AO_CTL + APUSYS_AO_SRAM_CLR, BIT(9));
+ mmio_clrbits_32(APUSYS_AO_CTL + APUSYS_AO_SRAM_CLR, BIT(12));
+ mmio_clrbits_32(APUSYS_AO_CTL + APUSYS_AO_SRAM_CLR, BIT(14));
+ udelay(1);
+
+ mmio_write_32(APUSYS_RPC + APU_RPC_HW_CON, BUCK_PROT_REQ_SET);
+ udelay(1);
+
+ mmio_write_32(APUSYS_RPC + APU_RPC_HW_CON, SRAM_AOC_LHENB_SET);
+ udelay(1);
+
+ mmio_write_32(APUSYS_RPC + APU_RPC_HW_CON, SRAM_AOC_ISO_SET);
+ udelay(1);
+
+ mmio_write_32(APUSYS_RPC + APU_RPC_HW_CON, PLL_AOC_ISO_EN_SET);
+ udelay(1);
+
+ mmio_write_32(APUSYS_RPC + APU_RPC_HW_CON, BUCK_ELS_EN_SET);
+ udelay(1);
+
+ mmio_write_32(APUSYS_RPC + APU_RPC_HW_CON, BUCK_AO_RST_B_CLR);
+ udelay(1);
+
+ buck_off_by_pcu(BUCK_VAPU_PMIC_REG_EN_CLR_ADDR, BUCK_VAPU_PMIC_REG_EN_SHIFT,
+ BUCK_VAPU_PMIC_ID);
+
+ mmio_setbits_32(APUSYS_AO_CTL + APUSYS_AO_SRAM_SET, BIT(6));
+ udelay(1);
+ mmio_setbits_32(APUSYS_AO_CTL + APUSYS_AO_SRAM_SET, BIT(7));
+ udelay(1);
+ mmio_clrbits_32(APUSYS_AO_CTL + APUSYS_AO_SRAM_SET, BIT(6));
+ udelay(1);
+ mmio_clrbits_32(APUSYS_AO_CTL + APUSYS_AO_SRAM_SET, BIT(7));
+ udelay(1);
+}
+
+static void apu_acc_init(void)
+{
+ uint32_t top_acc_base_arr[] = {MNOC_ACC_BASE, UP_ACC_BASE};
+ uint32_t eng_acc_base_arr[] = {MVPU_ACC_BASE, MDLA_ACC_BASE};
+ int acc_idx;
+ int are_idx = ACC_ENTRY_BEGIN;
+ uint32_t base_reg;
+
+ for (acc_idx = 0 ; acc_idx < ARRAY_SIZE(top_acc_base_arr) ; acc_idx++) {
+ base_reg = APUSYS_ACC + top_acc_base_arr[acc_idx];
+#if CFG_APU_ARDCM_ENABLE
+ apu_w_are(are_idx++, base_reg + APU_ARDCM_CTRL1, APU_ARDCM_CTRL1_VAL_0);
+ apu_w_are(are_idx++, base_reg + APU_ARDCM_CTRL0, APU_ARDCM_CTRL0_VAL_0);
+ apu_w_are(are_idx++, base_reg + APU_ARDCM_CTRL1, APU_ARDCM_CTRL1_VAL_1);
+ apu_w_are(are_idx++, base_reg + APU_ARDCM_CTRL0, APU_ARDCM_CTRL0_VAL_1);
+#endif
+ apu_w_are(are_idx++, base_reg + APU_ACC_CONFG_CLR0, CGEN_SOC);
+ apu_w_are(are_idx++, base_reg + APU_ACC_CONFG_SET0, HW_CTRL_EN);
+ }
+
+ for (acc_idx = 0 ; acc_idx < ARRAY_SIZE(eng_acc_base_arr) ; acc_idx++) {
+ base_reg = APUSYS_ACC + eng_acc_base_arr[acc_idx];
+#if CFG_APU_ARDCM_ENABLE
+ apu_w_are(are_idx++, base_reg + APU_ARDCM_CTRL1, APU_ARDCM_CTRL1_VAL_0);
+ apu_w_are(are_idx++, base_reg + APU_ARDCM_CTRL0, APU_ARDCM_CTRL0_VAL_0);
+ apu_w_are(are_idx++, base_reg + APU_ARDCM_CTRL1, APU_ARDCM_CTRL1_VAL_1);
+ apu_w_are(are_idx++, base_reg + APU_ARDCM_CTRL0, APU_ARDCM_CTRL0_VAL_1);
+#endif
+ apu_w_are(are_idx++, base_reg + APU_ACC_CONFG_CLR0, CGEN_SOC);
+ apu_w_are(are_idx++, base_reg + APU_ACC_CONFG_SET0, HW_CTRL_EN);
+ apu_w_are(are_idx++, base_reg + APU_ACC_AUTO_CTRL_SET0, CLK_REQ_SW_EN);
+ }
+}
+
+static void apu_pll_init(void)
+{
+ uint32_t pll_base_arr[] = {MNOC_PLL_BASE, UP_PLL_BASE, MVPU_PLL_BASE, MDLA_PLL_BASE};
+ int32_t pll_freq_out[] = {
+ APUPLL0_DEFAULT_FREQ,
+ APUPLL1_DEFAULT_FREQ,
+ APUPLL2_DEFAULT_FREQ,
+ APUPLL3_DEFAULT_FREQ
+ };
+ uint32_t pcw_val, posdiv_val;
+ int pll_idx, are_idx;
+ uint32_t base_reg;
+
+ mmio_setbits_32(APUSYS_BASE + APU_ARE, ARE_RCX_AO_EN);
+ mmio_setbits_32(APUSYS_BASE + APU_ARE_REG, ARE_RCX_AO_EN);
+
+ mmio_write_32(APUSYS_BASE + APU_ARE + ARE_RCX_AO_CONFIG, ARE_ENTRY(RCX_AO_BEGIN) |
+ (ARE_ENTRIES(RCX_AO_BEGIN, RCX_AO_END) << ARE_RCX_AO_CONFIG_HIGH_OFF));
+
+ are_idx = PLL_ENTRY_BEGIN;
+ for (pll_idx = 0 ; pll_idx < ARRAY_SIZE(pll_base_arr) ; pll_idx++) {
+ base_reg = APUSYS_PLL + pll_base_arr[pll_idx];
+
+ apu_w_are(are_idx++, base_reg + RG_PLLGP_LVR_REFSEL, RG_PLLGP_LVR_REFSEL_VAL);
+ apu_w_are(are_idx++, base_reg + PLL1CPLL_FHCTL_HP_EN, FHCTL_CTRL);
+ apu_w_are(are_idx++, base_reg + PLL1CPLL_FHCTL_RST_CON, FHCTL_NO_RESET);
+ apu_w_are(are_idx++, base_reg + PLL1CPLL_FHCTL_CLK_CON, FHCTL_CLKEN);
+ apu_w_are(are_idx++, base_reg + PLL1CPLL_FHCTL0_CFG,
+ FHCTL_HOPPING_EN | FHCTL_SFSTR0_EN);
+
+ posdiv_val = 0;
+ pcw_val = 0;
+ get_pll_pcw(pll_freq_out[pll_idx], &posdiv_val, &pcw_val);
+
+ apu_w_are(are_idx++, base_reg + PLL1C_PLL1_CON1,
+ ((0x1U << RG_PLL_SDM_PCW_CHG_OFF) |
+ (posdiv_val << RG_PLL_POSDIV_OFF) | pcw_val));
+
+ apu_w_are(are_idx++, base_reg + PLL1CPLL_FHCTL0_DDS,
+ ((0x1U << FHCTL0_PLL_TGL_ORG) | pcw_val));
+ }
+}
+
+static void apu_are_init(void)
+{
+ int entry = 0;
+
+ mmio_clrbits_32(APUSYS_BASE + APU_ARE, 0xFFFU << ARE_VCORE_OFF);
+
+ mmio_setbits_32(APUSYS_BASE + APU_ARE, ARE_VCORE_EN);
+ mmio_setbits_32(APUSYS_BASE + APU_ARE_REG, ARE_VCORE_EN);
+
+ for (entry = ARE_CONF_START; entry < ARE_CONF_END; entry += 4)
+ mmio_write_32(APUSYS_BASE + APU_ARE + entry, 0);
+}
+
+static void apu_rpclite_init(void)
+{
+ uint32_t sleep_type_offset[] = {
+ APU_RPC_SW_TYPE1_OFF,
+ APU_RPC_SW_TYPE2_OFF,
+ APU_RPC_SW_TYPE3_OFF,
+ APU_RPC_SW_TYPE4_OFF
+ };
+ uint32_t rpc_lite_base[] = {
+ APU_ACX0_RPC_LITE,
+ APU_ACX1_RPC_LITE,
+ APU_ACX2_RPC_LITE,
+ };
+ int ofs_idx, rpc_lite_idx;
+ uint32_t base;
+
+ for (rpc_lite_idx = 0; rpc_lite_idx < ARRAY_SIZE(rpc_lite_base); rpc_lite_idx++) {
+ base = APUSYS_BASE + rpc_lite_base[rpc_lite_idx];
+ for (ofs_idx = 0; ofs_idx < ARRAY_SIZE(sleep_type_offset); ofs_idx++)
+ mmio_clrbits_32(base + sleep_type_offset[ofs_idx],
+ SW_TYPE_MVPU_MDLA_RV);
+ mmio_setbits_32(base + APU_RPC_TOP_SEL, TOP_SEL_VAL);
+ }
+}
+
+static void apu_rpc_mdla_init(void)
+{
+ mmio_clrbits_32(APUSYS_BASE + APU_RPCTOP_MDLA + APU_RPC_SW_TYPE0_OFF, SW_TYPE_MVPU_MDLA_RV);
+}
+
+static void apu_rpc_init(void)
+{
+ mmio_write_32(APUSYS_RPC + APU_RPC_SW_TYPE0_OFF, RPC_TYPE_INIT_VAL);
+ mmio_setbits_32(APUSYS_RPC + APU_RPC_TOP_SEL, RPC_TOP_SEL_VAL);
+
+#if !CFG_CTL_RPC_BY_CE
+ mmio_clrbits_32(APUSYS_RPC + APU_RPC_TOP_SEL, CE_ENABLE);
+#endif
+
+ mmio_setbits_32(APUSYS_RPC + APU_RPC_TOP_SEL_1, BUCK_PROT_SEL);
+}
+
+static int apu_pcu_init(void)
+{
+ uint32_t pmif_id = 0x0;
+ uint32_t slave_id = BUCK_VAPU_PMIC_ID;
+ uint32_t en_set_offset = BUCK_VAPU_PMIC_REG_EN_SET_ADDR;
+ uint32_t en_clr_offset = BUCK_VAPU_PMIC_REG_EN_CLR_ADDR;
+ uint32_t en_shift = BUCK_VAPU_PMIC_REG_EN_SHIFT;
+#if SPMI_ENABLE
+ struct spmi_device *vsram_sdev;
+#endif
+ unsigned char vsram = 0;
+
+ mmio_write_32(APUSYS_PCU + APU_PCUTOP_CTRL_SET, AUTO_BUCK_EN);
+
+ mmio_write_32((APUSYS_PCU + APU_PCU_BUCK_STEP_SEL), BUCK_STEP_SEL_VAL);
+
+#if SPMI_ENABLE
+ vsram_sdev = get_spmi_device(SPMI_MASTER_1, SPMI_SLAVE_4);
+ if (!vsram_sdev) {
+ ERROR("[APUPW] VSRAM BUCK4 get device fail\n");
+ return -1;
+ }
+
+ if (spmi_ext_register_readl(vsram_sdev, MT6363_RG_BUCK_VBUCK4_VOSEL_ADDR, &vsram, 1)) {
+ ERROR("[APUPW] VSRAM BUCK4 read fail\n");
+ return -1;
+ }
+#endif
+
+ mmio_write_32(APUSYS_PCU + APU_PCU_BUCK_ON_DAT0_L,
+ (BUCK_VAPU_PMIC_REG_VOSEL_ADDR << PMIC_OFF_ADDR_OFF) | vsram);
+
+ mmio_write_32(APUSYS_PCU + APU_PCU_BUCK_ON_DAT0_H,
+ (slave_id << PMIC_SLVID_OFF) | (pmif_id << PMIC_PMIFID_OFF) | PCU_CMD_OP_W);
+
+ mmio_write_32(APUSYS_PCU + APU_PCU_BUCK_ON_DAT1_L,
+ (en_set_offset << PMIC_OFF_ADDR_OFF) | (0x1U << en_shift));
+ mmio_write_32(APUSYS_PCU + APU_PCU_BUCK_ON_DAT1_H,
+ (slave_id << PMIC_SLVID_OFF) | (pmif_id << PMIC_PMIFID_OFF) | PCU_CMD_OP_W);
+
+ mmio_write_32(APUSYS_PCU + APU_PCU_BUCK_OFF_DAT0_L,
+ (en_clr_offset << PMIC_OFF_ADDR_OFF) | (0x1U << en_shift));
+ mmio_write_32(APUSYS_PCU + APU_PCU_BUCK_OFF_DAT0_H,
+ (slave_id << PMIC_SLVID_OFF) | (pmif_id << PMIC_PMIFID_OFF) | PCU_CMD_OP_W);
+
+ mmio_write_32(APUSYS_PCU + APU_PCU_BUCK_ON_SLE0, 0);
+ mmio_write_32(APUSYS_PCU + APU_PCU_BUCK_ON_SLE1, VAPU_BUCK_ON_SETTLE_TIME);
+
+ return 0;
+}
+
+static void apu_aoc_init(void)
+{
+ uint32_t reg;
+
+ mmio_setbits_32(SPM_BASE + 0xF6C, BIT(4));
+ mmio_clrbits_32(SPM_BASE + 0x414, BIT(1));
+
+ mmio_write_32(APUSYS_AO_CTL + APUSYS_AO_SRAM_CONFIG, APUSYS_AO_SRAM_EN);
+ udelay(1);
+
+ reg = APUSYS_AO_CTL + APUSYS_AO_SRAM_SET;
+
+#if !CFG_CTL_RPC_BY_CE
+ mmio_setbits_32(reg, BIT(8));
+ udelay(1);
+ mmio_setbits_32(reg, BIT(11));
+ udelay(1);
+ mmio_setbits_32(reg, BIT(13));
+ udelay(1);
+
+ mmio_clrbits_32(reg, BIT(8));
+ udelay(1);
+ mmio_clrbits_32(reg, BIT(11));
+ udelay(1);
+ mmio_clrbits_32(reg, BIT(13));
+#else
+ mmio_setbits_32(reg, BIT(9));
+ mmio_setbits_32(reg, BIT(12));
+ mmio_setbits_32(reg, BIT(14));
+
+ mmio_clrbits_32(reg, BIT(9));
+ mmio_clrbits_32(reg, BIT(12));
+ mmio_clrbits_32(reg, BIT(14));
+ udelay(1);
+#endif
+
+ reg = APUSYS_RPC + APU_RPC_HW_CON;
+
+ mmio_write_32(reg, BUCK_ELS_EN_CLR);
+ udelay(1);
+
+ mmio_write_32(reg, BUCK_AO_RST_B_SET);
+ udelay(1);
+
+ mmio_write_32(reg, BUCK_PROT_REQ_CLR);
+ udelay(1);
+
+ mmio_write_32(reg, SRAM_AOC_ISO_CLR);
+ udelay(1);
+
+ mmio_write_32(reg, PLL_AOC_ISO_EN_CLR);
+ udelay(1);
+}
+
+static int init_hw_setting(void)
+{
+ int ret;
+
+ apu_aoc_init();
+ ret = apu_pcu_init();
+ apu_rpc_init();
+ apu_rpc_mdla_init();
+ apu_rpclite_init();
+ apu_are_init();
+ apu_pll_init();
+ apu_acc_init();
+ apu_buck_off_cfg();
+
+ return ret;
+}
+
+int apusys_power_init(void)
+{
+ int ret;
+
+ ret = init_hw_setting();
+ if (ret != 0)
+ ERROR("%s init HW failed\n", __func__);
+ else
+ INFO("%s init HW done\n", __func__);
+
+ mmio_write_32(APU_ACE_HW_FLAG_DIS, APU_ACE_DIS_FLAG_VAL);
+
+ return ret;
+}
diff --git a/plat/mediatek/drivers/apusys/mt8196/apusys_power.h b/plat/mediatek/drivers/apusys/mt8196/apusys_power.h
new file mode 100644
index 0000000..ddf35c5
--- /dev/null
+++ b/plat/mediatek/drivers/apusys/mt8196/apusys_power.h
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2024, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef APUSYS_POWER_H
+#define APUSYS_POWER_H
+
+#include <platform_def.h>
+
+#define CFG_APU_ARDCM_ENABLE (0)
+#define CFG_CTL_RPC_BY_CE (1)
+
+#define APUPLL0_DEFAULT_FREQ (800)
+#define APUPLL1_DEFAULT_FREQ (960)
+#define APUPLL2_DEFAULT_FREQ (1200)
+#define APUPLL3_DEFAULT_FREQ (1230)
+
+enum t_acx_id {
+ D_ACX0 = 0,
+ ACX0,
+ ACX1,
+ ACX2,
+ CLUSTER_NUM,
+ RCX,
+};
+
+enum rcx_ao_range {
+ RCX_AO_BEGIN = 0,
+ PLL_ENTRY_BEGIN = 0,
+ PLL_ENTRY_END = 27,
+ ACC_ENTRY_BEGIN = 28,
+ ACC_ENTRY_END = 37,
+ RCX_AO_END = 37,
+};
+
+#define SYS_VLP (0x000000)
+#define SYS_SPM (0x000000)
+#define APU_RCX (0x020000)
+#define APU_RCX_DLA (0x040000)
+#define APU_ARE (0x0a0000)
+#define APU_ARE_REG (0x0b0000)
+#define APU_VCORE (0x0e0000)
+#define APU_MD32_MBOX (0x0e1000)
+#define APU_RPC (0x0f0000)
+#define APU_PCU (0x0f1000)
+#define APU_AO_CTL (0x0f2000)
+#define APU_ACC (0x0f3000)
+#define APU_PLL (0x0f6000)
+#define APU_RPCTOP_MDLA (0x0F7400)
+#define APU_ACX0 (0x100000)
+#define APU_ACX0_RPC_LITE (0x140000)
+#define APU_ACX1 (0x200000)
+#define APU_ACX1_RPC_LITE (0x240000)
+#define APU_ACX2 (0x300000)
+#define APU_ACX2_RPC_LITE (0x340000)
+
+/* APU GRP offset define */
+#define APU_GRP_0_BASE (0x0000)
+#define APU_GRP_1_BASE (0x0400)
+#define APU_GRP_2_BASE (0x0800)
+#define APU_GRP_3_BASE (0x0C00)
+
+#define MDLA_PLL_BASE APU_GRP_0_BASE
+#define MVPU_PLL_BASE APU_GRP_1_BASE
+#define MNOC_PLL_BASE APU_GRP_2_BASE
+#define UP_PLL_BASE APU_GRP_3_BASE
+
+#define MDLA_ACC_BASE APU_GRP_0_BASE
+#define MVPU_ACC_BASE APU_GRP_1_BASE
+#define MNOC_ACC_BASE APU_GRP_2_BASE
+#define UP_ACC_BASE APU_GRP_3_BASE
+
+/* RPC / RPC_LITE control */
+#define APU_RPC_SW_TYPE0_OFF (0x200)
+#define APU_RPC_SW_TYPE1_OFF (0x204)
+#define APU_RPC_SW_TYPE2_OFF (0x208)
+#define APU_RPC_SW_TYPE3_OFF (0x20C)
+#define APU_RPC_SW_TYPE4_OFF (0x210)
+#define SW_TYPE_MVPU_MDLA_RV BIT(0)
+#define CE_ENABLE BIT(10)
+#define BUCK_PROT_SEL BIT(20)
+#define RPC_TYPE_INIT_VAL (0x18)
+#define TOP_SEL_VAL (0xB2)
+#define RPC_TOP_SEL_VAL (0xB800D50F)
+
+#define APUSYS_AO_CTL (APUSYS_BASE + APU_AO_CTL)
+#define APUSYS_RPC (APUSYS_BASE + APU_RPC)
+#define APUSYS_ACC (APUSYS_BASE + APU_ACC)
+#define APUSYS_PLL (APUSYS_BASE + APU_PLL)
+#define APUSYS_PCU (APUSYS_BASE + APU_PCU)
+
+/* ARE control */
+#define ARE_VCORE_EN BIT(20)
+#define ARE_RCX_AO_EN BIT(21)
+#define ARE_VCORE_OFF (20)
+#define ARE_CONF_START (0x04)
+#define ARE_CONF_END (0x6C)
+#define ARE_REG_SIZE (4)
+
+/* ACC offset */
+#define APU_ACC_CONFG_SET0 (0x000)
+#define APU_ACC_CONFG_CLR0 (0x010)
+#define APU_ACC_AUTO_CTRL_SET0 (0x084)
+#define APU_ARDCM_CTRL0 (0x100)
+#define APU_ARDCM_CTRL1 (0x104)
+
+/* ACC control */
+#define APU_ARDCM_CTRL0_VAL_0 (0x00000016)
+#define APU_ARDCM_CTRL0_VAL_1 (0x00000036)
+#define APU_ARDCM_CTRL1_VAL_0 (0x00001006)
+#define APU_ARDCM_CTRL1_VAL_1 (0x07F0F006)
+#define CGEN_SOC BIT(2)
+#define CLK_REQ_SW_EN BIT(8)
+#define HW_CTRL_EN BIT(15)
+
+/* APU PLL1C offset */
+#define RG_PLLGP_LVR_REFSEL (0x204)
+#define PLL1C_PLL1_CON1 (0x20C)
+#define PLL1CPLL_FHCTL_HP_EN (0x300)
+#define PLL1CPLL_FHCTL_CLK_CON (0x308)
+#define PLL1CPLL_FHCTL_RST_CON (0x30C)
+#define PLL1CPLL_FHCTL0_CFG (0x314)
+#define PLL1CPLL_FHCTL0_DDS (0x31C)
+
+/* PLL control */
+#define RG_PLLGP_LVR_REFSEL_VAL (0x3)
+#define FHCTL_CTRL (0x1)
+#define FHCTL_NO_RESET (0x1)
+#define FHCTL_CLKEN (0x1)
+#define FHCTL_HOPPING_EN BIT(0)
+#define FHCTL_SFSTR0_EN BIT(2)
+#define RG_PLL_SDM_PCW_CHG_OFF (31)
+#define RG_PLL_POSDIV_OFF (24)
+#define FHCTL0_PLL_TGL_ORG (31)
+
+/* RPC offset define */
+#define APU_RPC_TOP_SEL (0x0004)
+#define APU_RPC_TOP_SEL_1 (0x0018)
+#define APU_RPC_HW_CON (0x001C)
+#define APU_RPC_STATUS_1 (0x0034)
+#define APU_RPC_INTF_PWR_RDY (0x0044)
+
+/* RPC control */
+#define SRAM_AOC_LHENB_SET BIT(4)
+#define SRAM_AOC_ISO_SET BIT(6)
+#define SRAM_AOC_ISO_CLR BIT(7)
+#define PLL_AOC_ISO_EN_SET BIT(8)
+#define PLL_AOC_ISO_EN_CLR BIT(9)
+#define BUCK_ELS_EN_SET BIT(10)
+#define BUCK_ELS_EN_CLR BIT(11)
+#define BUCK_AO_RST_B_SET BIT(12)
+#define BUCK_AO_RST_B_CLR BIT(13)
+#define BUCK_PROT_REQ_SET BIT(14)
+#define BUCK_PROT_REQ_CLR BIT(15)
+
+/* mt6373_vbuck2 */
+#define MT6373_SLAVE_ID (0x5)
+#define MT6373_RG_BUCK_VBUCK2_SET (0x241)
+#define MT6373_RG_BUCK_VBUCK2_CLR (0x242)
+#define MT6373_RG_BUCK_VBUCK2_EN_SHIFT (2)
+#define MT6373_RG_BUCK_VBUCK2_VOSEL_ADDR (0x24e)
+
+/* PCU initial data */
+#define APU_PCUTOP_CTRL_SET (0x0)
+#define APU_PCU_BUCK_STEP_SEL (0x0030)
+#define APU_PCU_BUCK_ON_DAT0_L (0x0080)
+#define APU_PCU_BUCK_ON_DAT0_H (0x0084)
+#define APU_PCU_BUCK_ON_DAT1_L (0x0088)
+#define APU_PCU_BUCK_ON_DAT1_H (0x008C)
+#define APU_PCU_BUCK_OFF_DAT0_L (0x00A0)
+#define APU_PCU_BUCK_OFF_DAT0_H (0x00A4)
+#define APU_PCU_BUCK_ON_SLE0 (0x00C0)
+#define APU_PCU_BUCK_ON_SLE1 (0x00C4)
+#define VAPU_BUCK_ON_SETTLE_TIME (0x00C8)
+#define APU_PCU_PMIC_TAR_BUF1 (0x0190)
+#define APU_PCU_PMIC_TAR_BUF2 (0x0194)
+#define APU_PCU_PMIC_CMD (0x0184)
+#define APU_PCU_PMIC_IRQ (0x0180)
+
+/* PCU control */
+#define PMIC_CMD_IRQ BIT(0)
+#define PMIC_IRQ_EN BIT(2)
+#define AUTO_BUCK_EN BIT(3)
+#define PMIC_PMIFID_OFF (3)
+#define PMIC_SLVID_OFF (4)
+#define PCU_CMD_OP_W (0x7)
+#define PMIC_OFF_ADDR_OFF (16)
+#define PMIC_CMD_EN (0x1)
+#define BUCK_STEP_SEL_VAL (0x13)
+#define PCU_BUCK_OFF_CMD (0x7)
+
+/* sram_core: mt6363_vbuck4 */
+#define MT6363_RG_BUCK_VBUCK4_VOSEL_ADDR (0x250)
+
+/* sub_pmic */
+#define BUCK_VAPU_PMIC_ID MT6373_SLAVE_ID
+#define BUCK_VAPU_PMIC_REG_VOSEL_ADDR MT6373_RG_BUCK_VBUCK2_VOSEL_ADDR
+#define BUCK_VAPU_PMIC_REG_EN_SET_ADDR MT6373_RG_BUCK_VBUCK2_SET
+#define BUCK_VAPU_PMIC_REG_EN_CLR_ADDR MT6373_RG_BUCK_VBUCK2_CLR
+#define BUCK_VAPU_PMIC_REG_EN_SHIFT MT6373_RG_BUCK_VBUCK2_EN_SHIFT
+
+/* vlp offset define */
+#define APUSYS_AO_SRAM_CONFIG (0x70)
+#define APUSYS_AO_SRAM_SET (0x74)
+#define APUSYS_AO_SRAM_CLR (0x78)
+
+#define APUSYS_AO_SRAM_EN (0x1)
+
+#define ARE_ENTRIES(x, y) ((((y) - (x)) + 1) * 2)
+#define ARE_ENTRY(x) (((x) * 2) + 36)
+#define ARE_RCX_AO_CONFIG (0x0014)
+#define ARE_RCX_AO_CONFIG_HIGH_OFF (16)
+
+#define APU_ACE_HW_FLAG_DIS (APUSYS_CE_BASE + 0x05D4)
+#define APU_ACE_DIS_FLAG_VAL (0xffff7ff8)
+
+#define OUT_CLK_FREQ_MIN (1500)
+#define DDS_SHIFT (14)
+#define BASIC_CLK_FREQ (26)
+
+int apusys_power_init(void);
+
+#endif /* APUSYS_POWER_H */
diff --git a/plat/mediatek/drivers/apusys/mt8196/apusys_rv_mbox_mpu.h b/plat/mediatek/drivers/apusys/mt8196/apusys_rv_mbox_mpu.h
new file mode 100644
index 0000000..7a5b212
--- /dev/null
+++ b/plat/mediatek/drivers/apusys/mt8196/apusys_rv_mbox_mpu.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2024, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef APUSYS_RV_MBOX_MPU_H
+#define APUSYS_RV_MBOX_MPU_H
+
+#define MPU_EN (0)
+#define MPU_DIS (1)
+#define MBOX0_TX_DOMAIN (0)
+#define MBOX0_TX_NS (1)
+#define MBOX1_TX_DOMAIN (11)
+#define MBOX1_TX_NS (1)
+#define MBOX3_TX_DOMAIN (3)
+#define MBOX3_TX_NS (0)
+#define MBOX4_RX_DOMAIN (0)
+#define MBOX4_RX_NS (0)
+#define MBOX5_TX_DOMAIN (8)
+#define MBOX5_TX_NS (0)
+#define MBOX6_TX_DOMAIN (4)
+#define MBOX6_TX_NS (1)
+#define MBOX7_RX_DOMAIN (0)
+#define MBOX7_RX_NS (0)
+#define MBOXN_RX_DOMAIN (5)
+#define MBOXN_RX_NS (0)
+#define MBOXN_TX_DOMAIN (0)
+#define MBOXN_TX_NS (0)
+
+struct mbox_mpu_setting {
+ uint32_t no_mpu;
+ uint32_t rx_ns;
+ uint32_t rx_domain;
+ uint32_t tx_ns;
+ uint32_t tx_domain;
+};
+
+static const struct mbox_mpu_setting mbox_mpu_setting_tab[] = {
+ /* no_mpu, rx_ns, rx_domain, tx_ns, tx_domain */
+ {MPU_EN, MBOXN_RX_NS, MBOXN_RX_DOMAIN, MBOX0_TX_NS, MBOX0_TX_DOMAIN},
+ {MPU_EN, MBOXN_RX_NS, MBOXN_RX_DOMAIN, MBOX1_TX_NS, MBOX1_TX_DOMAIN},
+ {MPU_EN, MBOXN_RX_NS, MBOXN_RX_DOMAIN, MBOXN_TX_NS, MBOXN_TX_DOMAIN},
+ {MPU_EN, MBOXN_RX_NS, MBOXN_RX_DOMAIN, MBOX3_TX_NS, MBOX3_TX_DOMAIN},
+ {MPU_DIS, MBOX4_RX_NS, MBOX4_RX_DOMAIN, MBOXN_TX_NS, MBOXN_TX_DOMAIN},
+ {MPU_EN, MBOXN_RX_NS, MBOXN_RX_DOMAIN, MBOX5_TX_NS, MBOX5_TX_DOMAIN},
+ {MPU_EN, MBOXN_RX_NS, MBOXN_RX_DOMAIN, MBOX6_TX_NS, MBOX6_TX_DOMAIN},
+ {MPU_DIS, MBOX7_RX_NS, MBOX7_RX_DOMAIN, MBOXN_TX_NS, MBOXN_TX_DOMAIN},
+ {MPU_EN, MBOXN_RX_NS, MBOXN_RX_DOMAIN, MBOXN_TX_NS, MBOXN_TX_DOMAIN},
+ {MPU_EN, MBOXN_RX_NS, MBOXN_RX_DOMAIN, MBOXN_TX_NS, MBOXN_TX_DOMAIN},
+};
+
+#define APU_MBOX_NUM ARRAY_SIZE(mbox_mpu_setting_tab)
+
+#endif /* APUSYS_RV_MBOX_MPU_H */
diff --git a/plat/mediatek/drivers/apusys/mt8196/apusys_rv_pwr_ctrl.c b/plat/mediatek/drivers/apusys/mt8196/apusys_rv_pwr_ctrl.c
new file mode 100644
index 0000000..632af52
--- /dev/null
+++ b/plat/mediatek/drivers/apusys/mt8196/apusys_rv_pwr_ctrl.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2024, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include "apusys_power.h"
+#include "apusys_rv.h"
+#include "apusys_rv_pwr_ctrl.h"
+
+#define RPC_POWER_OFF_TIMEOUT_CNT (100000) /* 100ms */
+
+static int wait_for_state_ready(uint32_t reg, uint32_t mask, uint32_t expect,
+ uint32_t retry_times, uint32_t set_reg, uint32_t set_val)
+{
+ uint32_t count = 0;
+
+ while ((mmio_read_32(reg) & mask) != expect) {
+ if (count > retry_times) {
+ ERROR("%s: timed out, reg = %x, mask = %x, expect = %x\n",
+ __func__, reg, mask, expect);
+ return -EBUSY;
+ }
+ count += 1;
+
+ if (set_reg)
+ mmio_write_32(set_reg, set_val);
+ udelay(1);
+ }
+
+ return 0;
+}
+
+int apu_hw_sema_ctl_per_mbox(uint32_t sem_ctrl_addr, uint32_t sem_sta_addr,
+ uint8_t usr_bit, enum apu_hw_sem_op ctl, uint32_t timeout,
+ uint8_t bypass)
+{
+ int ret;
+ uint8_t ctl_bit = 0;
+
+ if (ctl == HW_SEM_GET)
+ ctl_bit = 0x1;
+ else if (ctl == HW_SEM_PUT)
+ ctl_bit = 0x2;
+ else
+ return -EINVAL;
+
+ /* return fail if semaphore is currently not held by this user */
+ if (ctl == HW_SEM_PUT && ((mmio_read_32(sem_sta_addr) & BIT(usr_bit)) == 0)
+ && !bypass) {
+ ERROR("%s release error: usr_bit:%d ctl:%d (sem_addr(0x%08x) = 0x%08x)\n",
+ __func__, usr_bit, ctl, sem_sta_addr, mmio_read_32(sem_sta_addr));
+ return -EINVAL;
+ }
+
+ mmio_write_32(sem_ctrl_addr, ctl_bit);
+
+ if (ctl == HW_SEM_PUT)
+ return 0;
+
+ ret = wait_for_state_ready(sem_sta_addr, BIT(usr_bit), BIT(usr_bit), timeout,
+ sem_ctrl_addr, ctl_bit);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+int apusys_rv_pwr_ctrl(enum APU_PWR_OP op)
+{
+ int ret;
+ uint32_t global_ref_cnt;
+
+ ret = apu_hw_sema_ctl_per_mbox(APU_MBOX(APU_HW_SEM_SYS_APMCU) + APU_MBOX_SEMA0_CTRL,
+ APU_MBOX(APU_HW_SEM_SYS_APMCU) + APU_MBOX_SEMA0_STA,
+ APU_HW_SEM_SYS_APMCU, HW_SEM_GET, HW_SEM_TIMEOUT, 0);
+
+ if (ret) {
+ ERROR("%s(%d): sem acquire timeout\n", __func__, op);
+ return ret;
+ }
+
+ global_ref_cnt = mmio_read_32(APU_MBOX(APU_HW_SEM_SYS_APMCU) + APU_MBOX_DUMMY);
+
+ if (global_ref_cnt > 2) {
+ ERROR("%s: global_ref_cnt(%d) > 2\n", __func__, global_ref_cnt);
+ } else if (op == APU_PWR_OFF) {
+ global_ref_cnt--;
+ mmio_write_32(APU_MBOX(APU_HW_SEM_SYS_APMCU) + APU_MBOX_DUMMY, global_ref_cnt);
+ if (global_ref_cnt == 0)
+ mmio_write_32(APU_MBOX_WKUP_CFG(11), 0);
+ } else if (op == APU_PWR_ON) {
+ global_ref_cnt++;
+ mmio_write_32(APU_MBOX(APU_HW_SEM_SYS_APMCU) + APU_MBOX_DUMMY, global_ref_cnt);
+ if (global_ref_cnt == 1)
+ mmio_write_32(APU_MBOX_WKUP_CFG(11), 1);
+ }
+
+ ret = apu_hw_sema_ctl_per_mbox(APU_MBOX(APU_HW_SEM_SYS_APMCU) + APU_MBOX_SEMA0_CTRL,
+ APU_MBOX(APU_HW_SEM_SYS_APMCU) + APU_MBOX_SEMA0_STA,
+ APU_HW_SEM_SYS_APMCU, HW_SEM_PUT, HW_SEM_TIMEOUT, 0);
+
+ if (ret)
+ ERROR("%s(%d): sem release timeout\n", __func__, op);
+
+ return ret;
+}
+
+int rv_iommu_hw_sem_trylock(void)
+{
+ return apu_hw_sema_ctl_per_mbox(APU_MBOX(APU_HW_SEM_SYS_APMCU) + APU_MBOX_SEMA1_CTRL,
+ APU_MBOX(APU_HW_SEM_SYS_APMCU) + APU_MBOX_SEMA1_STA,
+ APU_HW_SEM_SYS_APMCU, HW_SEM_GET, 0, 0);
+}
+
+int rv_iommu_hw_sem_unlock(void)
+{
+ return apu_hw_sema_ctl_per_mbox(APU_MBOX(APU_HW_SEM_SYS_APMCU) + APU_MBOX_SEMA1_CTRL,
+ APU_MBOX(APU_HW_SEM_SYS_APMCU) + APU_MBOX_SEMA1_STA,
+ APU_HW_SEM_SYS_APMCU, HW_SEM_PUT, 0, 0);
+}
+
+int apu_hw_sema_ctl(uint32_t sem_addr, uint8_t usr_bit, uint8_t ctl, uint32_t timeout,
+ uint8_t bypass)
+{
+ int ret;
+ uint8_t ctl_bit = 0;
+
+ if (ctl == HW_SEM_GET)
+ ctl_bit = usr_bit;
+ else if (ctl == HW_SEM_PUT)
+ ctl_bit = usr_bit + HW_SEM_PUT_BIT_SHIFT;
+ else
+ return -EINVAL;
+
+ if (ctl == HW_SEM_PUT && ((mmio_read_32(sem_addr) & BIT(ctl_bit)) == 0) && !bypass) {
+ ERROR("%s release error: usr_bit:%d ctl:%d (sem_addr(0x%08x) = 0x%08x)\n",
+ __func__, usr_bit, ctl, sem_addr, mmio_read_32(sem_addr));
+ return -EINVAL;
+ }
+
+ mmio_write_32(sem_addr, BIT(ctl_bit));
+
+ if (ctl == HW_SEM_PUT)
+ goto end;
+
+ ret = wait_for_state_ready(sem_addr, BIT(ctl_bit), BIT(ctl_bit), timeout,
+ sem_addr, BIT(ctl_bit));
+ if (ret)
+ return ret;
+
+end:
+ VERBOSE("%s: sem_addr = 0x%x, usr_bit: %d, ctl: %d, sem_addr = 0x%08x\n",
+ __func__, sem_addr, usr_bit, ctl, mmio_read_32(sem_addr));
+
+ return 0;
+}
+
+int apusys_infra_dcm_setup(void)
+{
+ mmio_write_32(APU_REG_AO_GLUE_CONFG,
+ mmio_read_32(APU_REG_AO_GLUE_CONFG) | BIT(24) | BIT(26));
+
+ return 0;
+}
diff --git a/plat/mediatek/drivers/apusys/mt8196/apusys_rv_pwr_ctrl.h b/plat/mediatek/drivers/apusys/mt8196/apusys_rv_pwr_ctrl.h
new file mode 100644
index 0000000..b5a48e2
--- /dev/null
+++ b/plat/mediatek/drivers/apusys/mt8196/apusys_rv_pwr_ctrl.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2024, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef APUSYS_RV_PWR_CTL_H
+#define APUSYS_RV_PWR_CTL_H
+
+#include <platform_def.h>
+
+#include "apusys_rv.h"
+
+#define SUPPORT_APU_CLEAR_MBOX_DUMMY (1)
+
+enum apu_hw_sem_sys_id {
+ APU_HW_SEM_SYS_APU = 0UL, /* mbox0 */
+ APU_HW_SEM_SYS_GZ = 1UL, /* mbox1 */
+ APU_HW_SEM_SYS_SCP = 3UL, /* mbox3 */
+ APU_HW_SEM_SYS_APMCU = 11UL, /* mbox11 */
+};
+
+int apusys_rv_pwr_ctrl(enum APU_PWR_OP op);
+int rv_iommu_hw_sem_unlock(void);
+int rv_iommu_hw_sem_trylock(void);
+int apu_hw_sema_ctl(uint32_t sem_addr, uint8_t usr_bit, uint8_t ctl, uint32_t timeout,
+ uint8_t bypass);
+
+#define HW_SEM_TIMEOUT (300) /* 300 us */
+
+/* APU MBOX */
+#define MBOX_WKUP_CFG (0x80)
+#define MBOX_WKUP_MASK (0x84)
+#define MBOX_FUNC_CFG (0xb0)
+#define MBOX_DOMAIN_CFG (0xe0)
+
+#define MBOX_CTRL_LOCK BIT(0)
+#define MBOX_NO_MPU_SHIFT (16)
+#define MBOX_RC_SHIFT (24)
+
+#define MBOX_RX_NS_SHIFT (16)
+#define MBOX_RX_DOMAIN_SHIFT (17)
+#define MBOX_TX_NS_SHIFT (24)
+#define MBOX_TX_DOMAIN_SHIFT (25)
+
+#define APU_REG_AO_GLUE_CONFG (APU_AO_CTRL + 0x20)
+
+#define ENABLE_INFRA_WA
+
+enum apu_infra_bit_id {
+ APU_INFRA_SYS_APMCU = 1UL,
+ APU_INFRA_SYS_GZ = 2UL,
+ APU_INFRA_SYS_SCP = 3UL,
+};
+
+#define APU_MBOX(i) (APU_MBOX0 + 0x10000 * i)
+
+#define APU_MBOX_FUNC_CFG(i) (APU_MBOX(i) + MBOX_FUNC_CFG)
+#define APU_MBOX_DOMAIN_CFG(i) (APU_MBOX(i) + MBOX_DOMAIN_CFG)
+#define APU_MBOX_WKUP_CFG(i) (APU_MBOX(i) + MBOX_WKUP_CFG)
+
+enum apu_hw_sem_op {
+ HW_SEM_PUT = 0,
+ HW_SEM_GET = 1,
+};
+
+#define HW_SEM_PUT_BIT_SHIFT (16)
+
+/* bypass mbox register Dump for secure master */
+#define APU_MBOX_DBG_EN (0x190f2380)
+
+/* apu_mbox register definition for mbox addr change*/
+#define APU_MBOX_SEMA0_CTRL (0x090)
+#define APU_MBOX_SEMA0_RST (0x094)
+#define APU_MBOX_SEMA0_STA (0x098)
+#define APU_MBOX_SEMA1_CTRL (0x0A0)
+#define APU_MBOX_SEMA1_RST (0x0A4)
+#define APU_MBOX_SEMA1_STA (0x0A8)
+#define APU_MBOX_DUMMY (0x040)
+#define APU_MBOX_OFFSET(i) (0x10000 * i)
+
+/* apu infra workaround */
+#define APU_INFRA_DISABLE (APU_INFRA_BASE + 0xC18)
+#define APU_INFRA_ENABLE (APU_INFRA_BASE + 0xC14)
+#define APU_INFRA_STATUS (APU_INFRA_BASE + 0xC10)
+#define APU_INFRA_STATUS_MASK (0x1fffe)
+#define APU_INFRA_HW_SEM (APUSYS_CE_BASE + 0xE00)
+#define APU_RPC_STATUS (0x190f0044)
+
+#define APU_INFRA_BIT_OFF (16)
+#define APU_RPC_STATUS_BIT BIT(0)
+
+#endif /* APUSYS_RV_PWR_CTL_H */
diff --git a/plat/mediatek/drivers/apusys/mt8196/apusys_security_ctrl_perm_plat.c b/plat/mediatek/drivers/apusys/mt8196/apusys_security_ctrl_perm_plat.c
new file mode 100644
index 0000000..f6c8f58
--- /dev/null
+++ b/plat/mediatek/drivers/apusys/mt8196/apusys_security_ctrl_perm_plat.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2024, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include "apusys_security_ctrl_perm.h"
+#include "apusys_security_ctrl_perm_plat.h"
+
+#define SEC_CTRL_APU_SEC_CON_BASE (0x190F5000)
+#define SEC_CTRL_RV_DOMAIN_OFS (0x60)
+#define SEC_CTRL_RV_NS_OFS (0x64)
+#define SEC_CTRL_RV_DOMAIN_SHF (4)
+#define SEC_CTRL_RV_NS_SHF (1)
+
+#define SEC_LEVEL_NORMAL_DOMAIN (7)
+#define SEC_LEVEL_NORMAL_NS (1)
+#define SEC_LEVEL_SAPU_DOMAIN (5)
+#define SEC_LEVEL_SAPU_NS (1)
+#define SEC_LEVEL_AOV_DOMAIN (14)
+#define SEC_LEVEL_AOV_NS (1)
+#define SEC_LEVEL_UP_SECURE_DOMAIN (5)
+#define SEC_LEVEL_UP_SECURE_NS (0)
+#define SEC_LEVEL_MVPU_SECURE_DOMAIN (7)
+#define SEC_LEVEL_MVPU_SECURE_NS (0)
+#define SEC_LEVEL_MDLA_SECURE_DOMAIN (14)
+#define SEC_LEVEL_MDLA_SECURE_NS (0)
+#define DOMAIN(SEC_LVL) SEC_LEVEL_##SEC_LVL##_DOMAIN
+#define NS(SEC_LVL) SEC_LEVEL_##SEC_LVL##_NS
+
+int sec_get_dns(enum apusys_dev_type dev_type, enum apusys_sec_level sec_level,
+ uint8_t *domain, uint8_t *ns)
+{
+ if ((dev_type < 0) || (dev_type >= APUSYS_DEVICE_NUM)) {
+ ERROR("invalid dev type %d\n", dev_type);
+ return -EINVAL;
+ }
+
+ if ((sec_level < 0) || (sec_level >= SEC_LEVEL_NUM)) {
+ ERROR("invalid sec_level %d\n", sec_level);
+ return -EINVAL;
+ }
+
+ switch (sec_level) {
+ case SEC_LEVEL_NORMAL:
+ *domain = DOMAIN(NORMAL);
+ *ns = NS(NORMAL);
+ break;
+ case SEC_LEVEL_SECURE:
+ switch (dev_type) {
+ case APUSYS_DEVICE_MVPU:
+ *domain = DOMAIN(MVPU_SECURE);
+ *ns = NS(MVPU_SECURE);
+ break;
+ case APUSYS_DEVICE_MDLA:
+ *domain = DOMAIN(MDLA_SECURE);
+ *ns = NS(MDLA_SECURE);
+ break;
+ case APUSYS_DEVICE_UP:
+ *domain = DOMAIN(UP_SECURE);
+ *ns = NS(UP_SECURE);
+ break;
+ default:
+ ERROR("invalid dev type %d\n", dev_type);
+ return -EINVAL;
+ };
+ break;
+ case SEC_LEVEL_SAPU:
+ *domain = DOMAIN(SAPU);
+ *ns = NS(SAPU);
+ break;
+ case SEC_LEVEL_AOV:
+ *domain = DOMAIN(AOV);
+ *ns = NS(AOV);
+ break;
+ default:
+ ERROR("invalid sec_level %d\n", sec_level);
+ return -EINVAL;
+ };
+
+ return 0;
+}
+
+int sec_set_rv_dns(void)
+{
+ uint8_t normal_domain;
+ uint8_t normal_ns;
+ uint8_t sec_domain;
+ uint8_t sec_ns;
+ int ret;
+
+ ret = sec_get_dns(APUSYS_DEVICE_UP, SEC_LEVEL_SECURE, &sec_domain, &sec_ns);
+ if (ret) {
+ ERROR("%s failed.\n", __func__);
+ return ret;
+ }
+
+ ret = sec_get_dns(APUSYS_DEVICE_UP, SEC_LEVEL_NORMAL, &normal_domain, &normal_ns);
+ if (ret) {
+ ERROR("%s failed.\n", __func__);
+ return ret;
+ }
+
+ mmio_write_32(SEC_CTRL_APU_SEC_CON_BASE + SEC_CTRL_RV_DOMAIN_OFS,
+ (sec_domain << SEC_CTRL_RV_DOMAIN_SHF) | normal_domain);
+ mmio_write_32(SEC_CTRL_APU_SEC_CON_BASE + SEC_CTRL_RV_NS_OFS,
+ (sec_ns << SEC_CTRL_RV_NS_SHF) | normal_ns);
+
+ return 0;
+}
diff --git a/plat/mediatek/drivers/apusys/mt8196/apusys_security_ctrl_perm_plat.h b/plat/mediatek/drivers/apusys/mt8196/apusys_security_ctrl_perm_plat.h
new file mode 100644
index 0000000..d57a536
--- /dev/null
+++ b/plat/mediatek/drivers/apusys/mt8196/apusys_security_ctrl_perm_plat.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2024, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef APUSYS_SECURITY_CTRL_PERM_PLAT_H
+#define APUSYS_SECURITY_CTRL_PERM_PLAT_H
+
+enum apusys_dev_type {
+ APUSYS_DEVICE_MDLA,
+ APUSYS_DEVICE_EDPA,
+ APUSYS_DEVICE_MVPU,
+ APUSYS_DEVICE_UP,
+ APUSYS_DEVICE_NUM,
+};
+
+#endif /* APUSYS_SECURITY_CTRL_PERM_PLAT_H */
diff --git a/plat/mediatek/drivers/apusys/mt8196/apusys_security_ctrl_plat.c b/plat/mediatek/drivers/apusys/mt8196/apusys_security_ctrl_plat.c
new file mode 100644
index 0000000..fbd2aa0
--- /dev/null
+++ b/plat/mediatek/drivers/apusys/mt8196/apusys_security_ctrl_plat.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2024, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#define ENABLE_SMPU_PROTECT (0)
+
+#if ENABLE_SMPU_PROTECT
+#include "emi.h"
+#include "mt_emi.h"
+#endif
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include <apusys_security_ctrl_plat.h>
+
+#define APUSYS_SEC_FW_EMI_REGION (23)
+
+#define bits_clr(x, m, o) (x & (~(m << o)))
+#define bits_set(x, v, m, o) ((bits_clr(x, m, o)) | ((v & m) << o))
+
+static void sec_sideband_init(void)
+{
+ uint32_t value = mmio_read_32(SEC_CTRL_SIDE_BAND);
+
+ value = bits_set(value, SEC_CTRL_NARE_DOMAIN, SEC_CTRL_DOMAIN_MASK,
+ SEC_CTRL_NARE_DOMAIN_SHF);
+ value = bits_set(value, SEC_CTRL_NARE_NS, SEC_CTRL_NS_MASK, SEC_CTRL_NARE_NS_SHF);
+ value = bits_set(value, SEC_CTRL_SARE0_DOMAIN, SEC_CTRL_DOMAIN_MASK,
+ SEC_CTRL_SARE0_DOMAIN_SHF);
+ value = bits_set(value, SEC_CTRL_SARE0_NS, SEC_CTRL_NS_MASK, SEC_CTRL_SARE0_NS_SHF);
+ value = bits_set(value, SEC_CTRL_SARE1_DOMAIN, SEC_CTRL_DOMAIN_MASK,
+ SEC_CTRL_SARE1_DOMAIN_SHF);
+ value = bits_set(value, SEC_CTRL_SARE1_NS, SEC_CTRL_NS_MASK, SEC_CTRL_SARE1_NS_SHF);
+
+ mmio_write_32(SEC_CTRL_SIDE_BAND, value);
+}
+
+static void domain_remap_init(void)
+{
+ const uint32_t remap_domains[] = {
+ D0_REMAP_DOMAIN, D1_REMAP_DOMAIN, D2_REMAP_DOMAIN, D3_REMAP_DOMAIN,
+ D4_REMAP_DOMAIN, D5_REMAP_DOMAIN, D6_REMAP_DOMAIN, D7_REMAP_DOMAIN,
+ D8_REMAP_DOMAIN, D9_REMAP_DOMAIN, D10_REMAP_DOMAIN, D11_REMAP_DOMAIN,
+ D12_REMAP_DOMAIN, D13_REMAP_DOMAIN, D14_REMAP_DOMAIN, D15_REMAP_DOMAIN,
+ };
+ uint32_t lower_domain = 0;
+ uint32_t higher_domain = 0;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(remap_domains); i++) {
+ if (i < SEC_CTRL_REG_DOMAIN_NUM)
+ lower_domain |= (remap_domains[i] << (i * REG_DOMAIN_BITS));
+ else
+ higher_domain |= (remap_domains[i] <<
+ ((i - SEC_CTRL_REG_DOMAIN_NUM) * REG_DOMAIN_BITS));
+ }
+
+ mmio_write_32(SEC_CTRL_SOC2APU_SET1_0, lower_domain);
+ mmio_write_32(SEC_CTRL_SOC2APU_SET1_1, higher_domain);
+ mmio_setbits_32(APU_SEC_CON, SEC_CTRL_DOMAIN_REMAP_SEL);
+}
+
+void apusys_security_ctrl_init(void)
+{
+ domain_remap_init();
+ sec_sideband_init();
+}
+
+int apusys_plat_setup_sec_mem(void)
+{
+#if ENABLE_SMPU_PROTECT
+ return sip_emi_mpu_set_protection(APU_RESERVE_MEMORY >> EMI_MPU_ALIGN_BITS,
+ (APU_RESERVE_MEMORY + APU_RESERVE_SIZE) >> EMI_MPU_ALIGN_BITS,
+ APUSYS_SEC_FW_EMI_REGION);
+#else
+ INFO("%s: Bypass SMPU protection setup.\n", __func__);
+ return 0;
+#endif
+}
diff --git a/plat/mediatek/drivers/apusys/mt8196/apusys_security_ctrl_plat.h b/plat/mediatek/drivers/apusys/mt8196/apusys_security_ctrl_plat.h
new file mode 100644
index 0000000..5e69777
--- /dev/null
+++ b/plat/mediatek/drivers/apusys/mt8196/apusys_security_ctrl_plat.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2024, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef APUSYS_SECURITY_CTRL_PLAT_H
+#define APUSYS_SECURITY_CTRL_PLAT_H
+
+#include <lib/utils_def.h>
+#include <platform_def.h>
+
+#define SEC_CTRL_SOC2APU_SET1_0 (APU_SEC_CON + 0xC)
+#define SEC_CTRL_SOC2APU_SET1_1 (APU_SEC_CON + 0x10)
+#define SEC_CTRL_SIDE_BAND (APU_SEC_CON + 0x24)
+
+#define SEC_CTRL_REG_DOMAIN_NUM (8)
+#define SEC_CTRL_DOMAIN_REMAP_SEL BIT(6)
+#define SEC_CTRL_DOMAIN_MASK (0xF)
+#define SEC_CTRL_NS_MASK (0x1)
+
+#define SEC_CTRL_NARE_DOMAIN (5)
+#define SEC_CTRL_NARE_NS (0)
+#define SEC_CTRL_NARE_DOMAIN_SHF (0)
+#define SEC_CTRL_NARE_NS_SHF (4)
+
+#define SEC_CTRL_SARE0_DOMAIN (5)
+#define SEC_CTRL_SARE0_NS (0)
+#define SEC_CTRL_SARE0_DOMAIN_SHF (5)
+#define SEC_CTRL_SARE0_NS_SHF (9)
+
+#define SEC_CTRL_SARE1_DOMAIN (5)
+#define SEC_CTRL_SARE1_NS (0)
+#define SEC_CTRL_SARE1_DOMAIN_SHF (10)
+#define SEC_CTRL_SARE1_NS_SHF (14)
+
+#define REG_DOMAIN_BITS (4)
+
+#define D0_REMAP_DOMAIN (0)
+#define D1_REMAP_DOMAIN (1)
+#define D2_REMAP_DOMAIN (2)
+#define D3_REMAP_DOMAIN (3)
+#define D4_REMAP_DOMAIN (4)
+#define D5_REMAP_DOMAIN (6)
+#define D6_REMAP_DOMAIN (6)
+#define D7_REMAP_DOMAIN (6)
+#define D8_REMAP_DOMAIN (8)
+#define D9_REMAP_DOMAIN (9)
+#define D10_REMAP_DOMAIN (10)
+#define D11_REMAP_DOMAIN (11)
+#define D12_REMAP_DOMAIN (12)
+#define D13_REMAP_DOMAIN (13)
+#define D14_REMAP_DOMAIN (6)
+#define D15_REMAP_DOMAIN (15)
+
+void apusys_security_ctrl_init(void);
+int apusys_plat_setup_sec_mem(void);
+
+#endif /* APUSYS_SECURITY_CTRL_PLAT_H */
diff --git a/plat/mediatek/drivers/apusys/mt8196/rules.mk b/plat/mediatek/drivers/apusys/mt8196/rules.mk
new file mode 100644
index 0000000..4ffaf73
--- /dev/null
+++ b/plat/mediatek/drivers/apusys/mt8196/rules.mk
@@ -0,0 +1,23 @@
+#
+# Copyright (c) 2024, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+LOCAL_DIR := $(call GET_LOCAL_DIR)
+
+MODULE := apusys_${MTK_SOC}
+
+ifeq (${CONFIG_MTK_APUSYS_EMI_SUPPORT}, y)
+PLAT_INCLUDES += -I${MTK_PLAT}/drivers/emi/common
+PLAT_INCLUDES += -I${MTK_PLAT}/drivers/emi/${MTK_SOC}
+endif
+
+LOCAL_SRCS-y := ${LOCAL_DIR}/apusys_ammu.c
+LOCAL_SRCS-y += ${LOCAL_DIR}/apusys_devapc.c
+LOCAL_SRCS-y += ${LOCAL_DIR}/apusys_power.c
+LOCAL_SRCS-y += ${LOCAL_DIR}/apusys_rv_pwr_ctrl.c
+LOCAL_SRCS-y += ${LOCAL_DIR}/apusys_security_ctrl_plat.c
+LOCAL_SRCS-y += ${LOCAL_DIR}/apusys_security_ctrl_perm_plat.c
+
+$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
diff --git a/plat/mediatek/drivers/apusys/rules.mk b/plat/mediatek/drivers/apusys/rules.mk
index 498925c..24cc79c 100644
--- a/plat/mediatek/drivers/apusys/rules.mk
+++ b/plat/mediatek/drivers/apusys/rules.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2023, MediaTek Inc. All rights reserved.
+# Copyright (c) 2023-2024, MediaTek Inc. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -12,10 +12,19 @@
PLAT_INCLUDES += -I${LOCAL_DIR} -I${LOCAL_DIR}/${MTK_SOC} -I${LOCAL_DIR}/apusys_rv/2.0
+$(eval $(call add_defined_option,CONFIG_MTK_APUSYS_CE_SUPPORT))
+$(eval $(call add_defined_option,CONFIG_MTK_APUSYS_EMI_SUPPORT))
+$(eval $(call add_defined_option,CONFIG_MTK_APUSYS_LOGTOP_SUPPORT))
+$(eval $(call add_defined_option,CONFIG_MTK_APUSYS_RV_APUMMU_SUPPORT))
+$(eval $(call add_defined_option,CONFIG_MTK_APUSYS_RV_COREDUMP_WA_SUPPORT))
+$(eval $(call add_defined_option,CONFIG_MTK_APUSYS_RV_IOMMU_HW_SEM_SUPPORT))
+$(eval $(call add_defined_option,CONFIG_MTK_APUSYS_SEC_CTRL))
+
$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
SUB_RULES-y := ${LOCAL_DIR}/${MTK_SOC}
SUB_RULES-y += ${LOCAL_DIR}/devapc
SUB_RULES-y += ${LOCAL_DIR}/apusys_rv/2.0
+SUB_RULES-${CONFIG_MTK_APUSYS_SEC_CTRL} += $(LOCAL_DIR)/security_ctrl
$(eval $(call INCLUDE_MAKEFILE,$(SUB_RULES-y)))
diff --git a/plat/mediatek/drivers/apusys/security_ctrl/apusys_security_ctrl_perm.h b/plat/mediatek/drivers/apusys/security_ctrl/apusys_security_ctrl_perm.h
new file mode 100644
index 0000000..17ccacf
--- /dev/null
+++ b/plat/mediatek/drivers/apusys/security_ctrl/apusys_security_ctrl_perm.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2024, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SECURITY_CTRL_PERM_H
+#define SECURITY_CTRL_PERM_H
+
+#include "apusys_security_ctrl_perm_plat.h"
+
+enum apusys_sec_level {
+ SEC_LEVEL_NORMAL,
+ SEC_LEVEL_SECURE,
+ SEC_LEVEL_SAPU,
+ SEC_LEVEL_AOV,
+ SEC_LEVEL_NUM,
+};
+
+int sec_set_rv_dns(void);
+int sec_get_dns(enum apusys_dev_type dev_type, enum apusys_sec_level sec_level,
+ uint8_t *domain, uint8_t *ns);
+
+#endif
diff --git a/plat/mediatek/drivers/apusys/security_ctrl/rules.mk b/plat/mediatek/drivers/apusys/security_ctrl/rules.mk
new file mode 100644
index 0000000..a7ed5c9
--- /dev/null
+++ b/plat/mediatek/drivers/apusys/security_ctrl/rules.mk
@@ -0,0 +1,8 @@
+#
+# Copyright (c) 2024, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+PLAT_INCLUDES += -I${MTK_PLAT}/drivers/apusys/security_ctrl
+PLAT_INCLUDES += -I${MTK_PLAT}/drivers/apusys/${MTK_SOC}
diff --git a/plat/mediatek/include/drivers/apusys_rv_public.h b/plat/mediatek/include/drivers/apusys_rv_public.h
new file mode 100644
index 0000000..485453f
--- /dev/null
+++ b/plat/mediatek/include/drivers/apusys_rv_public.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2024, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef APUSYS_RV_PUBLIC_H
+#define APUSYS_RV_PUBLIC_H
+
+#ifdef CONFIG_MTK_APUSYS_RV_IOMMU_HW_SEM_SUPPORT
+int apusys_rv_iommu_hw_sem_trylock(void);
+int apusys_rv_iommu_hw_sem_unlock(void);
+#else
+#define apusys_rv_iommu_hw_sem_trylock() 0
+#define apusys_rv_iommu_hw_sem_unlock() 0
+#endif /* CONFIG_MTK_APUSYS_RV_IOMMU_HW_SEM_SUPPORT */
+
+#endif /* APUSYS_RV_PUBLIC_H */
diff --git a/plat/mediatek/mt8196/include/platform_def.h b/plat/mediatek/mt8196/include/platform_def.h
index 630a3f0..4f40890 100644
--- a/plat/mediatek/mt8196/include/platform_def.h
+++ b/plat/mediatek/mt8196/include/platform_def.h
@@ -31,6 +31,37 @@
#define AUDIO_BASE (IO_PHYS + 0x0a110000)
/*******************************************************************************
+ * APUSYS related constants
+ ******************************************************************************/
+#define APUSYS_BASE (IO_PHYS + 0x09000000)
+#define APU_MD32_SYSCTRL (IO_PHYS + 0x09001000)
+#define APU_MD32_WDT (IO_PHYS + 0x09002000)
+#define APU_LOGTOP (IO_PHYS + 0x09024000)
+#define APUSYS_CTRL_DAPC_RCX_BASE (IO_PHYS + 0x09030000)
+#define APU_REVISER (IO_PHYS + 0x0903C000)
+#define APU_RCX_UPRV_TCU (IO_PHYS + 0x09060000)
+#define APU_RCX_EXTM_TCU (IO_PHYS + 0x09061000)
+#define APU_CMU_TOP (IO_PHYS + 0x09067000)
+#define APUSYS_CE_BASE (IO_PHYS + 0x090B0000)
+#define APU_ARE_REG_BASE (IO_PHYS + 0x090B0000)
+#define APU_RCX_VCORE_CONFIG (IO_PHYS + 0x090E0000)
+#define APU_AO_CTRL (IO_PHYS + 0x090F2000)
+#define APU_SEC_CON (IO_PHYS + 0x090F5000)
+#define APUSYS_CTRL_DAPC_AO_BASE (IO_PHYS + 0x090FC000)
+
+#define APU_MBOX0 (0x4C200000)
+#define APU_MD32_TCM (0x4D000000)
+
+#define APU_MD32_TCM_SZ (0x50000)
+#define APU_MBOX0_SZ (0x100000)
+#define APU_INFRA_BASE (0x1002C000)
+#define APU_INFRA_SZ (0x1000)
+
+#define APU_RESERVE_MEMORY (0x95000000)
+#define APU_SEC_INFO_OFFSET (0x100000)
+#define APU_RESERVE_SIZE (0x1400000)
+
+/*******************************************************************************
* SPM related constants
******************************************************************************/
#define SPM_BASE (IO_PHYS + 0x0C004000)
diff --git a/plat/mediatek/mt8196/plat_config.mk b/plat/mediatek/mt8196/plat_config.mk
index dc78701..0239a3f 100644
--- a/plat/mediatek/mt8196/plat_config.mk
+++ b/plat/mediatek/mt8196/plat_config.mk
@@ -26,6 +26,14 @@
CTX_INCLUDE_AARCH32_REGS := 0
CONFIG_ARCH_ARM_V9 := y
+CONFIG_MTK_APUSYS_CE_SUPPORT := y
+CONFIG_MTK_APUSYS_EMI_SUPPORT := n
+CONFIG_MTK_APUSYS_LOGTOP_SUPPORT := y
+CONFIG_MTK_APUSYS_RV_APUMMU_SUPPORT := y
+CONFIG_MTK_APUSYS_RV_COREDUMP_WA_SUPPORT := y
+CONFIG_MTK_APUSYS_RV_IOMMU_HW_SEM_SUPPORT := y
+CONFIG_MTK_APUSYS_SEC_CTRL := y
+CONFIG_MTK_APUSYS_SETUP_CE := y
CONFIG_MTK_MCUSYS := y
MCUSYS_VERSION := v1
CONFIG_MTK_PM_SUPPORT := y
diff --git a/plat/mediatek/mt8196/plat_mmap.c b/plat/mediatek/mt8196/plat_mmap.c
index 3d7be87..d32f4ee 100644
--- a/plat/mediatek/mt8196/plat_mmap.c
+++ b/plat/mediatek/mt8196/plat_mmap.c
@@ -21,6 +21,8 @@
MT_DEVICE | MT_RW | MT_SECURE),
MAP_REGION_FLAT(EDP_SEC_BASE, EDP_SEC_SIZE,
MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(APU_MBOX0, APU_MBOX0_SZ,
+ MT_DEVICE | MT_RW | MT_SECURE),
{ 0 }
};
DECLARE_MTK_MMAP_REGIONS(plat_mmap);
diff --git a/plat/mediatek/mt8196/platform.mk b/plat/mediatek/mt8196/platform.mk
index 0d6ca24..3c827c9 100644
--- a/plat/mediatek/mt8196/platform.mk
+++ b/plat/mediatek/mt8196/platform.mk
@@ -25,6 +25,7 @@
MODULES-y += $(MTK_PLAT)/common
MODULES-y += $(MTK_PLAT)/lib/mtk_init
MODULES-y += $(MTK_PLAT)/lib/pm
+MODULES-y += $(MTK_PLAT)/drivers/apusys
MODULES-y += $(MTK_PLAT)/drivers/dp
MODULES-y += $(MTK_PLAT)/drivers/mcusys
MODULES-y += $(MTK_PLAT)/drivers/timer