diff --git a/plat/mediatek/drivers/cpu_pm/rules.mk b/plat/mediatek/drivers/cpu_pm/rules.mk
index 8df4f2189..d43b5a7ea 100644
--- a/plat/mediatek/drivers/cpu_pm/rules.mk
+++ b/plat/mediatek/drivers/cpu_pm/rules.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2022, MediaTek Inc. All rights reserved.
+# Copyright (c) 2025, MediaTek Inc. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -10,4 +10,10 @@ MODULE := cpu_pm
 
 SUB_RULES-${CONFIG_MTK_CPU_PM_SUPPORT} := $(LOCAL_DIR)/cpcv${CONFIG_MTK_CPU_PM_ARCH}
 
+ifneq ($(CPU_PWR_TOPOLOGY),)
+SUB_RULES-${CONFIG_MTK_CPU_PM_SUPPORT} += $(LOCAL_DIR)/topology/$(CPU_PWR_TOPOLOGY)
+else
+SUB_RULES-${CONFIG_MTK_CPU_PM_SUPPORT} += $(LOCAL_DIR)/topology/default
+endif
+
 $(eval $(call INCLUDE_MAKEFILE,$(SUB_RULES-y)))
diff --git a/plat/mediatek/drivers/cpu_pm/topology/default/pwr.c b/plat/mediatek/drivers/cpu_pm/topology/default/pwr.c
new file mode 100644
index 000000000..ce1793b6d
--- /dev/null
+++ b/plat/mediatek/drivers/cpu_pm/topology/default/pwr.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2025, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdint.h>
+
+#include <lib/spinlock.h>
+#include <platform_def.h>
+
+#include "../inc/pwr_topology.h"
+#include <lib/pm/mtk_pm.h>
+#include <lpm/mt_lp_rm.h>
+
+#ifdef MT_CPU_PM_USING_BAKERY_LOCK
+DEFINE_BAKERY_LOCK(mt_pwr_lock);
+
+#define plat_pwr_lock_init() bakery_lock_init(&mt_pwr_lock)
+
+#define plat_pwr_lock() bakery_lock_get(&mt_pwr_lock)
+
+#define plat_pwr_unlock() bakery_lock_release(&mt_pwr_lock)
+#else
+spinlock_t mt_pwr_lock;
+
+#define plat_pwr_lock_init()
+#define plat_pwr_lock() spin_lock(&mt_pwr_lock)
+
+#define plat_pwr_unlock() spin_unlock(&mt_pwr_lock)
+#endif
+
+enum mt_pwr_domain_node {
+	MT_PWR_NONMCUSYS = 0,
+	MT_PWR_MCUSYS_PDN,
+	MT_PWR_MAX
+};
+
+#if CONFIG_MTK_PM_SUPPORT && CONFIG_MTK_CPU_SUSPEND_EN && \
+!CPU_PM_DOMAIN_CORE_ONLY
+static int mt_pwr_domain_st[MT_PWR_MAX];
+#endif
+
+#define ALL_IN_ONE_GROUP	0xFF
+unsigned int pwr_domain_coordination(enum pwr_domain_status pwr,
+				     const mtk_pstate_type psci_state,
+				     const struct mtk_cpupm_pwrstate *state,
+				     afflv_prepare fn)
+{
+	unsigned int pstate = 0;
+
+#if CONFIG_MTK_PM_SUPPORT && CONFIG_MTK_CPU_SUSPEND_EN && \
+!CPU_PM_DOMAIN_CORE_ONLY
+	unsigned int is_flush = 0;
+	struct pwr_toplogy tp = {
+		.cur_group_bit = ALL_IN_ONE_GROUP,
+		.group = ALL_IN_ONE_GROUP,
+	};
+
+	/* Skip to process smp */
+	if (pwr > PWR_DOMAIN_OFF)
+		return pstate;
+
+	if (!IS_MT_PLAT_PWR_STATE_MCUSYS(state->pwr.state_id)) {
+		plat_pwr_lock();
+		if (pwr == PWR_DOMAIN_OFF)
+			mt_pwr_domain_st[MT_PWR_NONMCUSYS] += 1;
+		else
+			mt_pwr_domain_st[MT_PWR_NONMCUSYS] -= 1;
+		flush_dcache_range(
+			(uintptr_t)&mt_pwr_domain_st[MT_PWR_NONMCUSYS],
+			sizeof(mt_pwr_domain_st[MT_PWR_NONMCUSYS]));
+		plat_pwr_unlock();
+	}
+
+	plat_pwr_lock();
+	if (state->pwr.afflv >= PLAT_MT_CPU_SUSPEND_CLUSTER)
+		pstate |= MT_CPUPM_PWR_DOMAIN_CLUSTER;
+
+	if (psci_get_pstate_pwrlvl(psci_state) >= PLAT_MT_CPU_SUSPEND_CLUSTER)
+		pstate |= MT_CPUPM_PWR_DOMAIN_PERCORE_DSU;
+
+	if (pwr == PWR_DOMAIN_OFF) {
+		if (IS_PLAT_MCUSYSOFF_AFFLV(state->pwr.afflv) &&
+		    (mt_pwr_domain_st[MT_PWR_NONMCUSYS] == 0)) {
+			int ret = MTK_CPUPM_E_OK;
+
+			tp.group = ALL_IN_ONE_GROUP;
+			if (fn)
+				ret = fn(1, state, &tp);
+
+			if (ret == MTK_CPUPM_E_OK) {
+				pstate |= MT_CPUPM_PWR_DOMAIN_MCUSYS;
+				mt_pwr_domain_st[MT_PWR_MCUSYS_PDN] += 1;
+				is_flush = 1;
+			}
+		}
+	} else {
+		if (mt_pwr_domain_st[MT_PWR_MCUSYS_PDN]) {
+			tp.group = 0x0;
+			if (fn)
+				fn(1, state, &tp);
+			pstate |= MT_CPUPM_PWR_DOMAIN_MCUSYS;
+			mt_pwr_domain_st[MT_PWR_MCUSYS_PDN] -= 1;
+			is_flush = 1;
+		}
+		if (mt_pwr_domain_st[MT_PWR_NONMCUSYS] < 0)
+			assert(0);
+	}
+
+	if (is_flush)
+		flush_dcache_range(
+			(uintptr_t)&mt_pwr_domain_st[MT_PWR_MCUSYS_PDN],
+			sizeof(mt_pwr_domain_st[MT_PWR_MCUSYS_PDN]));
+
+	plat_pwr_unlock();
+#endif
+	return pstate;
+}
+
+void pwr_topology_init(void)
+{
+	plat_pwr_lock_init();
+}
diff --git a/plat/mediatek/drivers/cpu_pm/topology/default/rules.mk b/plat/mediatek/drivers/cpu_pm/topology/default/rules.mk
new file mode 100644
index 000000000..4fb2f56c9
--- /dev/null
+++ b/plat/mediatek/drivers/cpu_pm/topology/default/rules.mk
@@ -0,0 +1,13 @@
+#
+# Copyright (c) 2025, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+LOCAL_DIR := $(call GET_LOCAL_DIR)
+
+MODULE := pwr_topology_default
+
+LOCAL_SRCS-y := ${LOCAL_DIR}/pwr.c
+
+$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
diff --git a/plat/mediatek/drivers/cpu_pm/topology/group_4_3_1/pwr.c b/plat/mediatek/drivers/cpu_pm/topology/group_4_3_1/pwr.c
new file mode 100644
index 000000000..2eb518a35
--- /dev/null
+++ b/plat/mediatek/drivers/cpu_pm/topology/group_4_3_1/pwr.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2025, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdint.h>
+
+#include <lib/spinlock.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+#include "../inc/pwr_topology.h"
+#include <lib/pm/mtk_pm.h>
+#include <lpm/mt_lp_rm.h>
+
+#define GROUP_CPU_ALL		0x7
+#define GROUP_0_CPUID_MAX	3
+#define GROUP_1_CPUID_MAX	6
+#define GROUP_2_CPUID_MAX	7
+
+#define IS_ALL_GROUP_OFF(_mask) ((_mask & GROUP_CPU_ALL) == GROUP_CPU_ALL)
+
+#define GET_GROUPID(_cpuid, _gid) ({ \
+	if (_cpuid <= GROUP_0_CPUID_MAX) \
+		_gid = 0; \
+	else if (_cpuid <= GROUP_1_CPUID_MAX) \
+		_gid = 1; \
+	else \
+		_gid = 2; })
+
+#define GET_GROUPMASK(_cpuid, _gmask) ({ \
+	if (_cpuid <= GROUP_0_CPUID_MAX) \
+		_gmask = BIT(0); \
+	else if (_cpuid <= GROUP_1_CPUID_MAX) \
+		_gmask = BIT(1);\
+	else if (_cpuid <= GROUP_2_CPUID_MAX) \
+		_gmask = BIT(2); \
+	else \
+		_gmask = 0; })
+
+#ifdef MT_CPU_PM_USING_BAKERY_LOCK
+DEFINE_BAKERY_LOCK(mt_pwr_lock);
+#define plat_pwr_lock_init() bakery_lock_init(&mt_pwr_lock)
+#define plat_pwr_lock() bakery_lock_get(&mt_pwr_lock)
+#define plat_pwr_unlock() bakery_lock_release(&mt_pwr_lock)
+#else
+spinlock_t mt_pwr_lock;
+#define plat_pwr_lock_init()
+#define plat_pwr_lock() spin_lock(&mt_pwr_lock)
+#define plat_pwr_unlock() spin_unlock(&mt_pwr_lock)
+#endif /* MT_CPU_PM_USING_BAKERY_LOCK */
+
+#if CONFIG_MTK_PM_SUPPORT && CONFIG_MTK_CPU_SUSPEND_EN && \
+!CPU_PM_DOMAIN_CORE_ONLY
+static unsigned int cpu_groupmask;
+#endif
+
+unsigned int pwr_domain_coordination(enum pwr_domain_status pwr,
+				     const mtk_pstate_type psci_state,
+				     const struct mtk_cpupm_pwrstate *state,
+				     afflv_prepare fn)
+{
+	unsigned int pstate = MT_CPUPM_PWR_DOMAIN_CORE;
+
+#if CONFIG_MTK_PM_SUPPORT && CONFIG_MTK_CPU_SUSPEND_EN && \
+!CPU_PM_DOMAIN_CORE_ONLY
+	struct pwr_toplogy tp;
+
+	if (state->pwr.afflv >= PLAT_MT_CPU_SUSPEND_CLUSTER) {
+		unsigned int fgmask;
+
+		if (state->info.cpuid >= PLATFORM_CORE_COUNT)
+			assert(0);
+
+		GET_GROUPMASK(state->info.cpuid, tp.cur_group_bit);
+
+		plat_pwr_lock();
+		if ((pwr == PWR_DOMAIN_OFF) || (pwr == PWR_DOMAIN_SMP_OFF)) {
+			tp.group = (cpu_groupmask | tp.cur_group_bit);
+			fgmask = tp.group;
+		} else {
+			tp.group = (cpu_groupmask & ~tp.cur_group_bit);
+			fgmask = cpu_groupmask;
+		}
+		fn(1, state, &tp);
+		cpu_groupmask = tp.group;
+
+		plat_pwr_unlock();
+		if (IS_ALL_GROUP_OFF(fgmask))
+			pstate |= MT_CPUPM_PWR_DOMAIN_CLUSTER;
+	}
+
+	/* Skip to process smp */
+	if (pwr > PWR_DOMAIN_OFF)
+		return pstate;
+
+	if (psci_get_pstate_pwrlvl(psci_state) >= PLAT_MT_CPU_SUSPEND_CLUSTER)
+		pstate |= MT_CPUPM_PWR_DOMAIN_PERCORE_DSU;
+
+	if (IS_PLAT_MCUSYSOFF_AFFLV(state->pwr.afflv)) {
+		int ret = MTK_CPUPM_E_OK;
+
+		if (fn)
+			ret = fn(state->pwr.afflv, state, &tp);
+
+		if (ret == MTK_CPUPM_E_OK)
+			pstate |= MT_CPUPM_PWR_DOMAIN_MCUSYS;
+	}
+#endif
+	return pstate;
+}
+
+void pwr_topology_init(void)
+{
+#if CONFIG_MTK_PM_SUPPORT && CONFIG_MTK_CPU_SUSPEND_EN && \
+!CPU_PM_DOMAIN_CORE_ONLY
+	cpu_groupmask = GROUP_CPU_ALL;
+#endif
+
+	plat_pwr_lock_init();
+}
diff --git a/plat/mediatek/drivers/cpu_pm/topology/group_4_3_1/rules.mk b/plat/mediatek/drivers/cpu_pm/topology/group_4_3_1/rules.mk
new file mode 100644
index 000000000..0d5473bda
--- /dev/null
+++ b/plat/mediatek/drivers/cpu_pm/topology/group_4_3_1/rules.mk
@@ -0,0 +1,17 @@
+#
+# Copyright (c) 2025, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+#Prologue, init variable
+LOCAL_DIR := $(call GET_LOCAL_DIR)
+
+#Define your module name
+MODULE := pwr_topology_default
+
+#Add your source code here
+LOCAL_SRCS-y := ${LOCAL_DIR}/pwr.c
+
+#Epilogue, build as module
+$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
diff --git a/plat/mediatek/drivers/cpu_pm/topology/inc/pwr_topology.h b/plat/mediatek/drivers/cpu_pm/topology/inc/pwr_topology.h
new file mode 100644
index 000000000..24dd86dd2
--- /dev/null
+++ b/plat/mediatek/drivers/cpu_pm/topology/inc/pwr_topology.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2025, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PWR_TOPOLOGY_H
+#define PWR_TOPOLOGY_H
+
+#include <lib/pm/mtk_pm.h>
+
+enum pwr_domain_status {
+	PWR_DOMAIN_ON,
+	PWR_DOMAIN_OFF,
+	PWR_DOMAIN_SMP_ON,
+	PWR_DOMAIN_SMP_OFF,
+};
+
+struct pwr_toplogy {
+	unsigned int cur_group_bit;
+	unsigned int group;
+};
+
+typedef int (*afflv_prepare)(unsigned int,
+			     const struct mtk_cpupm_pwrstate *,
+			     const struct pwr_toplogy *);
+
+void pwr_topology_init(void);
+
+unsigned int pwr_domain_coordination(enum pwr_domain_status pwr,
+				     const mtk_pstate_type psci_state,
+				     const struct mtk_cpupm_pwrstate *state,
+				     afflv_prepare fn);
+
+#endif
diff --git a/plat/mediatek/topology/group_4_3_1/topology.c b/plat/mediatek/topology/group_4_3_1/topology.c
new file mode 100644
index 000000000..5ccdfd257
--- /dev/null
+++ b/plat/mediatek/topology/group_4_3_1/topology.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2025, Mediatek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+
+#include <lib/psci/psci.h>
+#include <platform_def.h>
+
+#pragma weak plat_get_power_domain_tree_desc
+
+#define PWR_DOMAIN_GROUP_COUNT		U(3)
+#define PWR_DOMAIN_GROUP_NODE_0		U(4)
+#define PWR_DOMAIN_GROUP_NODE_1		U(3)
+#define PWR_DOMAIN_GROUP_NODE_2		U(1)
+
+static const unsigned char mtk_power_domain_tree_desc[] = {
+	PLATFORM_SYSTEM_COUNT,
+	PWR_DOMAIN_GROUP_COUNT,
+	PWR_DOMAIN_GROUP_NODE_0,
+	PWR_DOMAIN_GROUP_NODE_1,
+	PWR_DOMAIN_GROUP_NODE_2
+};
+
+/*******************************************************************************
+ * This function returns the default topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+	return mtk_power_domain_tree_desc;
+}
diff --git a/plat/mediatek/topology/group_4_3_1/topology_conf.mk b/plat/mediatek/topology/group_4_3_1/topology_conf.mk
new file mode 100644
index 000000000..6b0bb27ec
--- /dev/null
+++ b/plat/mediatek/topology/group_4_3_1/topology_conf.mk
@@ -0,0 +1,20 @@
+#
+# Copyright (c) 2025, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+PLAT_MAX_PWR_LVL := 2
+$(eval $(call add_defined_option,PLAT_MAX_PWR_LVL))
+
+PLAT_MAX_OFF_STATE := 2
+$(eval $(call add_defined_option,PLAT_MAX_OFF_STATE))
+
+PLAT_AFFLV_SYSTEM := 2
+$(eval $(call add_defined_option,PLAT_AFFLV_SYSTEM))
+
+PLAT_AFFLV_CLUSTER := 1
+$(eval $(call add_defined_option,PLAT_AFFLV_CLUSTER))
+
+PLAT_AFFLV_MCUSYS := 2
+$(eval $(call add_defined_option,PLAT_AFFLV_MCUSYS))
diff --git a/plat/mediatek/topology/rules.mk b/plat/mediatek/topology/rules.mk
index 29f15bbb5..687654153 100644
--- a/plat/mediatek/topology/rules.mk
+++ b/plat/mediatek/topology/rules.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2022, MediaTek Inc. All rights reserved.
+# Copyright (c) 2025, MediaTek Inc. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -7,6 +7,15 @@
 LOCAL_DIR := $(call GET_LOCAL_DIR)
 
 MODULE := topology
+
+ifneq (,$(wildcard $(LOCAL_DIR)/$(CPU_PWR_TOPOLOGY)/topology_conf.mk))
+include $(LOCAL_DIR)/$(CPU_PWR_TOPOLOGY)/topology_conf.mk
+endif
+
+ifneq ($(CPU_PWR_TOPOLOGY),)
+LOCAL_SRCS-y := $(LOCAL_DIR)/$(CPU_PWR_TOPOLOGY)/topology.c
+else
 LOCAL_SRCS-y := $(LOCAL_DIR)/$(ARCH_VERSION)/topology.c
+endif
 
 $(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))