feat(mt8196): add APUSYS AO DevAPC setting

Apusys AO DevAPC is a set of control registers inside APU, controlling
the access permission of APU AO (Always On) domain.

This patch add the mt8196 APU AO DevAPC setting to setup the protection.

Change-Id: I975a92795031cd1813442302890e29b671ef16f1
Signed-off-by: Karl Li <karl.li@mediatek.com>
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/mt8196/apusys_devapc.c b/plat/mediatek/drivers/apusys/mt8196/apusys_devapc.c
new file mode 100644
index 0000000..32eaa84
--- /dev/null
+++ b/plat/mediatek/drivers/apusys/mt8196/apusys_devapc.c
@@ -0,0 +1,184 @@
+/*
+ * 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"),
+};
+
+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;
+	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 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;
+}
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..a583fe4
--- /dev/null
+++ b/plat/mediatek/drivers/apusys/mt8196/apusys_devapc.h
@@ -0,0 +1,16 @@
+/*
+ * 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,
+};
+
+int apusys_devapc_ao_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/rules.mk b/plat/mediatek/drivers/apusys/mt8196/rules.mk
index c8ca531..03a7c29 100644
--- a/plat/mediatek/drivers/apusys/mt8196/rules.mk
+++ b/plat/mediatek/drivers/apusys/mt8196/rules.mk
@@ -8,6 +8,7 @@
 
 MODULE := apusys_${MTK_SOC}
 
+LOCAL_SRCS-y += ${LOCAL_DIR}/apusys_devapc.c
 LOCAL_SRCS-y += ${LOCAL_DIR}/apusys_power.c
 
 $(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
diff --git a/plat/mediatek/mt8196/include/platform_def.h b/plat/mediatek/mt8196/include/platform_def.h
index abc9d8f..d17d637 100644
--- a/plat/mediatek/mt8196/include/platform_def.h
+++ b/plat/mediatek/mt8196/include/platform_def.h
@@ -35,6 +35,7 @@
  ******************************************************************************/
 #define APUSYS_BASE			(IO_PHYS + 0x09000000)
 #define APUSYS_CE_BASE			(IO_PHYS + 0x090B0000)
+#define APUSYS_CTRL_DAPC_AO_BASE	(IO_PHYS + 0x090FC000)
 
 #define APU_MBOX0			(0x4C200000)