Merge "plat/arm: move compile time switch from source to dt file" into integration
diff --git a/docs/plat/index.rst b/docs/plat/index.rst
index 3cbb552..06c5c2b 100644
--- a/docs/plat/index.rst
+++ b/docs/plat/index.rst
@@ -20,6 +20,7 @@
    marvell/index
    mt8183
    mt8192
+   mt8195
    nvidia-tegra
    warp7
    imx8
diff --git a/docs/plat/mt8195.rst b/docs/plat/mt8195.rst
new file mode 100644
index 0000000..b2aeea2
--- /dev/null
+++ b/docs/plat/mt8195.rst
@@ -0,0 +1,21 @@
+MediaTek 8195
+=============
+
+MediaTek 8195 (MT8195) is a 64-bit ARM SoC introduced by MediaTek in 2021.
+The chip incorporates eight cores - four Cortex-A55 little cores and Cortex-A76.
+Cortex-A76 can operate at up to 2.2 GHz.
+Cortex-A55 can operate at up to 2.0 GHz.
+
+Boot Sequence
+-------------
+
+::
+
+    Boot Rom --> Coreboot --> TF-A BL31 --> Depthcharge --> Linux Kernel
+
+How to Build
+------------
+
+.. code:: shell
+
+    make CROSS_COMPILE=aarch64-linux-gnu- PLAT=mt8195 DEBUG=1 COREBOOT=1
diff --git a/plat/mediatek/mt8192/plat_mt_gic.c b/plat/mediatek/common/drivers/gic600/mt_gic_v3.c
similarity index 100%
rename from plat/mediatek/mt8192/plat_mt_gic.c
rename to plat/mediatek/common/drivers/gic600/mt_gic_v3.c
diff --git a/plat/mediatek/mt8192/include/mt_gic_v3.h b/plat/mediatek/common/drivers/gic600/mt_gic_v3.h
similarity index 100%
rename from plat/mediatek/mt8192/include/mt_gic_v3.h
rename to plat/mediatek/common/drivers/gic600/mt_gic_v3.h
diff --git a/plat/mediatek/common/drivers/gpio/mtgpio_common.c b/plat/mediatek/common/drivers/gpio/mtgpio_common.c
new file mode 100644
index 0000000..89977a5
--- /dev/null
+++ b/plat/mediatek/common/drivers/gpio/mtgpio_common.c
@@ -0,0 +1,298 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <drivers/gpio.h>
+#include <lib/mmio.h>
+#include <mtgpio.h>
+#include <platform_def.h>
+
+/******************************************************************************
+ *Macro Definition
+ ******************************************************************************/
+#define GPIO_MODE_BITS		4
+#define MAX_GPIO_MODE_PER_REG	8
+#define MAX_GPIO_REG_BITS	32
+#define DIR_BASE		(GPIO_BASE + 0x000)
+#define DOUT_BASE		(GPIO_BASE + 0x100)
+#define DIN_BASE		(GPIO_BASE + 0x200)
+#define MODE_BASE		(GPIO_BASE + 0x300)
+#define SET			0x4
+#define CLR			0x8
+
+static void mt_set_gpio_dir_chip(uint32_t pin, int dir)
+{
+	uint32_t pos, bit;
+
+	assert(pin < MAX_GPIO_PIN);
+	assert(dir < MT_GPIO_DIR_MAX);
+
+	pos = pin / MAX_GPIO_REG_BITS;
+	bit = pin % MAX_GPIO_REG_BITS;
+
+	if (dir == MT_GPIO_DIR_IN) {
+		mmio_write_32(DIR_BASE + 0x10U * pos + CLR, 1U << bit);
+	} else {
+		mmio_write_32(DIR_BASE + 0x10U * pos + SET, 1U << bit);
+	}
+}
+
+static int mt_get_gpio_dir_chip(uint32_t pin)
+{
+	uint32_t pos, bit;
+	uint32_t reg;
+
+	assert(pin < MAX_GPIO_PIN);
+
+	pos = pin / MAX_GPIO_REG_BITS;
+	bit = pin % MAX_GPIO_REG_BITS;
+
+	reg = mmio_read_32(DIR_BASE + 0x10U * pos);
+	return (((reg & (1U << bit)) != 0U) ? MT_GPIO_DIR_OUT : MT_GPIO_DIR_IN);
+}
+
+static void mt_set_gpio_out_chip(uint32_t pin, int output)
+{
+	uint32_t pos, bit;
+
+	assert(pin < MAX_GPIO_PIN);
+	assert(output < MT_GPIO_OUT_MAX);
+
+	pos = pin / MAX_GPIO_REG_BITS;
+	bit = pin % MAX_GPIO_REG_BITS;
+
+	if (output == MT_GPIO_OUT_ZERO) {
+		mmio_write_32(DOUT_BASE + 0x10U * pos + CLR, 1U << bit);
+	} else {
+		mmio_write_32(DOUT_BASE + 0x10U * pos + SET, 1U << bit);
+	}
+}
+
+static int mt_get_gpio_in_chip(uint32_t pin)
+{
+	uint32_t pos, bit;
+	uint32_t reg;
+
+	assert(pin < MAX_GPIO_PIN);
+
+	pos = pin / MAX_GPIO_REG_BITS;
+	bit = pin % MAX_GPIO_REG_BITS;
+
+	reg = mmio_read_32(DIN_BASE + 0x10U * pos);
+	return (((reg & (1U << bit)) != 0U) ? 1 : 0);
+}
+
+static void mt_gpio_set_spec_pull_pupd(uint32_t pin, int enable,
+			       int select)
+{
+	uintptr_t reg1;
+	uintptr_t reg2;
+	struct mt_pin_info gpio_info;
+
+	gpio_info = mt_pin_infos[pin];
+	uint32_t bit = gpio_info.bit;
+
+	reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset;
+	reg2 = reg1 + (gpio_info.base & 0xf0);
+	if (enable == MT_GPIO_PULL_ENABLE) {
+		mmio_write_32(reg2 + SET, (1U << bit));
+		if (select == MT_GPIO_PULL_DOWN) {
+			mmio_write_32(reg1 + SET, (1U << bit));
+		} else {
+			mmio_write_32(reg1 + CLR, (1U << bit));
+		}
+	} else {
+		mmio_write_32(reg2 + CLR, (1U << bit));
+		mmio_write_32((reg2 + 0x010U) + CLR, (1U << bit));
+	}
+}
+
+static void mt_gpio_set_pull_pu_pd(uint32_t pin, int enable,
+				 int select)
+{
+	uintptr_t reg1;
+	uintptr_t reg2;
+	struct mt_pin_info gpio_info;
+
+	gpio_info = mt_pin_infos[pin];
+	uint32_t bit = gpio_info.bit;
+
+	reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset;
+	reg2 = reg1 - (gpio_info.base & 0xf0);
+
+	if (enable == MT_GPIO_PULL_ENABLE) {
+		if (select == MT_GPIO_PULL_DOWN) {
+			mmio_write_32(reg1 + CLR, (1U << bit));
+			mmio_write_32(reg2 + SET, (1U << bit));
+		} else {
+			mmio_write_32(reg2 + CLR, (1U << bit));
+			mmio_write_32(reg1 + SET, (1U << bit));
+		}
+	} else {
+		mmio_write_32(reg1 + CLR, (1U << bit));
+		mmio_write_32(reg2 + CLR, (1U << bit));
+	}
+}
+
+static void mt_gpio_set_pull_chip(uint32_t pin, int enable,
+		   int select)
+{
+	struct mt_pin_info gpio_info;
+
+	gpio_info = mt_pin_infos[pin];
+	if (gpio_info.flag) {
+		mt_gpio_set_spec_pull_pupd(pin, enable, select);
+	} else {
+		mt_gpio_set_pull_pu_pd(pin, enable, select);
+	}
+}
+
+static int mt_gpio_get_spec_pull_pupd(uint32_t pin)
+{
+	uintptr_t reg1;
+	uintptr_t reg2;
+	uint32_t r0;
+	uint32_t r1;
+
+	struct mt_pin_info gpio_info;
+
+	gpio_info = mt_pin_infos[pin];
+	uint32_t bit = gpio_info.bit;
+
+	reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset;
+	reg2 = reg1 + (gpio_info.base & 0xf0);
+
+	r0 = (mmio_read_32(reg2) >> bit) & 1U;
+	r1 = (mmio_read_32(reg2 + 0x010) >> bit) & 1U;
+	if (r0 == 0U && r1 == 0U) {
+		return MT_GPIO_PULL_NONE;
+	} else {
+		if (mmio_read_32(reg1) & (1U << bit)) {
+			return MT_GPIO_PULL_DOWN;
+		} else {
+			return MT_GPIO_PULL_UP;
+		}
+	}
+}
+
+static int mt_gpio_get_pull_pu_pd(uint32_t pin)
+{
+	uintptr_t reg1;
+	uintptr_t reg2;
+	uint32_t pu;
+	uint32_t pd;
+
+	struct mt_pin_info gpio_info;
+
+	gpio_info = mt_pin_infos[pin];
+	uint32_t bit = gpio_info.bit;
+
+	reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset;
+	reg2 = reg1 - (gpio_info.base & 0xf0);
+	pu = (mmio_read_32(reg1) >> bit) & 1U;
+	pd = (mmio_read_32(reg2) >> bit) & 1U;
+	if (pu == 1U) {
+		return MT_GPIO_PULL_UP;
+	} else if (pd == 1U) {
+		return MT_GPIO_PULL_DOWN;
+	} else {
+		return MT_GPIO_PULL_NONE;
+	}
+}
+
+static int mt_gpio_get_pull_chip(uint32_t pin)
+{
+	struct mt_pin_info gpio_info;
+
+	gpio_info = mt_pin_infos[pin];
+	if (gpio_info.flag) {
+		return mt_gpio_get_spec_pull_pupd(pin);
+	} else {
+		return mt_gpio_get_pull_pu_pd(pin);
+	}
+}
+
+static void mt_set_gpio_pull_select_chip(uint32_t pin, int sel)
+{
+	assert(pin < MAX_GPIO_PIN);
+
+	if (sel == MT_GPIO_PULL_NONE) {
+		mt_gpio_set_pull_chip(pin, MT_GPIO_PULL_DISABLE, MT_GPIO_PULL_DOWN);
+	} else if (sel == MT_GPIO_PULL_UP) {
+		mt_gpio_set_pull_chip(pin, MT_GPIO_PULL_ENABLE, MT_GPIO_PULL_UP);
+	} else if (sel == MT_GPIO_PULL_DOWN) {
+		mt_gpio_set_pull_chip(pin, MT_GPIO_PULL_ENABLE, MT_GPIO_PULL_DOWN);
+	}
+}
+
+/* get pull-up or pull-down, regardless of resistor value */
+static int mt_get_gpio_pull_select_chip(uint32_t pin)
+{
+	assert(pin < MAX_GPIO_PIN);
+
+	return mt_gpio_get_pull_chip(pin);
+}
+
+static void mt_set_gpio_dir(int gpio, int direction)
+{
+	mt_set_gpio_dir_chip((uint32_t)gpio, direction);
+}
+
+static int mt_get_gpio_dir(int gpio)
+{
+	uint32_t pin;
+
+	pin = (uint32_t)gpio;
+	return mt_get_gpio_dir_chip(pin);
+}
+
+static void mt_set_gpio_pull(int gpio, int pull)
+{
+	uint32_t pin;
+
+	pin = (uint32_t)gpio;
+	mt_set_gpio_pull_select_chip(pin, pull);
+}
+
+static int mt_get_gpio_pull(int gpio)
+{
+	uint32_t pin;
+
+	pin = (uint32_t)gpio;
+	return mt_get_gpio_pull_select_chip(pin);
+}
+
+static void mt_set_gpio_out(int gpio, int value)
+{
+	uint32_t pin;
+
+	pin = (uint32_t)gpio;
+	mt_set_gpio_out_chip(pin, value);
+}
+
+static int mt_get_gpio_in(int gpio)
+{
+	uint32_t pin;
+
+	pin = (uint32_t)gpio;
+	return mt_get_gpio_in_chip(pin);
+}
+
+const gpio_ops_t mtgpio_ops = {
+	 .get_direction = mt_get_gpio_dir,
+	 .set_direction = mt_set_gpio_dir,
+	 .get_value = mt_get_gpio_in,
+	 .set_value = mt_set_gpio_out,
+	 .set_pull = mt_set_gpio_pull,
+	 .get_pull = mt_get_gpio_pull,
+};
+
+void mt_gpio_init(void)
+{
+	gpio_init(&mtgpio_ops);
+}
diff --git a/plat/mediatek/common/drivers/gpio/mtgpio_common.h b/plat/mediatek/common/drivers/gpio/mtgpio_common.h
new file mode 100644
index 0000000..bf51055
--- /dev/null
+++ b/plat/mediatek/common/drivers/gpio/mtgpio_common.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_GPIO_COMMON_H
+#define MT_GPIO_COMMON_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <plat/common/common_def.h>
+
+/*  Error Code No. */
+#define RSUCCESS        0
+#define ERACCESS        1
+#define ERINVAL         2
+#define ERWRAPPER       3
+#define MAX_GPIO_PIN    MT_GPIO_BASE_MAX
+
+/* GPIO MODE CONTROL VALUE*/
+typedef enum {
+	GPIO_MODE_UNSUPPORTED = -1,
+	GPIO_MODE_GPIO  = 0,
+	GPIO_MODE_00    = 0,
+	GPIO_MODE_01,
+	GPIO_MODE_02,
+	GPIO_MODE_03,
+	GPIO_MODE_04,
+	GPIO_MODE_05,
+	GPIO_MODE_06,
+	GPIO_MODE_07,
+
+	GPIO_MODE_MAX,
+	GPIO_MODE_DEFAULT = GPIO_MODE_00,
+} GPIO_MODE;
+
+/* GPIO DIRECTION */
+typedef enum {
+	MT_GPIO_DIR_UNSUPPORTED = -1,
+	MT_GPIO_DIR_OUT    = 0,
+	MT_GPIO_DIR_IN     = 1,
+	MT_GPIO_DIR_MAX,
+	MT_GPIO_DIR_DEFAULT = MT_GPIO_DIR_IN,
+} GPIO_DIR;
+
+/* GPIO PULL ENABLE*/
+typedef enum {
+	MT_GPIO_PULL_EN_UNSUPPORTED = -1,
+	MT_GPIO_PULL_DISABLE   = 0,
+	MT_GPIO_PULL_ENABLE    = 1,
+	MT_GPIO_PULL_ENABLE_R0 = 2,
+	MT_GPIO_PULL_ENABLE_R1 = 3,
+	MT_GPIO_PULL_ENABLE_R0R1 = 4,
+
+	MT_GPIO_PULL_EN_MAX,
+	MT_GPIO_PULL_EN_DEFAULT = MT_GPIO_PULL_ENABLE,
+} GPIO_PULL_EN;
+
+/* GPIO PULL-UP/PULL-DOWN*/
+typedef enum {
+	MT_GPIO_PULL_UNSUPPORTED = -1,
+	MT_GPIO_PULL_NONE        = 0,
+	MT_GPIO_PULL_UP          = 1,
+	MT_GPIO_PULL_DOWN        = 2,
+	MT_GPIO_PULL_MAX,
+	MT_GPIO_PULL_DEFAULT = MT_GPIO_PULL_DOWN
+} GPIO_PULL;
+
+/* GPIO OUTPUT */
+typedef enum {
+	MT_GPIO_OUT_UNSUPPORTED = -1,
+	MT_GPIO_OUT_ZERO = 0,
+	MT_GPIO_OUT_ONE  = 1,
+
+	MT_GPIO_OUT_MAX,
+	MT_GPIO_OUT_DEFAULT = MT_GPIO_OUT_ZERO,
+	MT_GPIO_DATA_OUT_DEFAULT = MT_GPIO_OUT_ZERO,  /*compatible with DCT*/
+} GPIO_OUT;
+
+/* GPIO INPUT */
+typedef enum {
+	MT_GPIO_IN_UNSUPPORTED = -1,
+	MT_GPIO_IN_ZERO = 0,
+	MT_GPIO_IN_ONE  = 1,
+
+	MT_GPIO_IN_MAX,
+} GPIO_IN;
+
+#define PIN(_id, _flag, _bit, _base, _offset) {		\
+		.id = _id,				\
+		.flag = _flag,				\
+		.bit = _bit,				\
+		.base = _base,				\
+		.offset = _offset,			\
+	}
+
+struct mt_pin_info {
+	uint8_t id;
+	uint8_t flag;
+	uint8_t bit;
+	uint16_t base;
+	uint16_t offset;
+};
+
+void mt_gpio_init(void);
+uintptr_t mt_gpio_find_reg_addr(uint32_t pin);
+#endif /* MT_GPIO_COMMON_H */
diff --git a/plat/mediatek/mt8192/drivers/rtc/rtc.c b/plat/mediatek/common/drivers/rtc/rtc_mt6359p.c
similarity index 100%
rename from plat/mediatek/mt8192/drivers/rtc/rtc.c
rename to plat/mediatek/common/drivers/rtc/rtc_mt6359p.c
diff --git a/plat/mediatek/mt8192/drivers/rtc/rtc.h b/plat/mediatek/common/drivers/rtc/rtc_mt6359p.h
similarity index 97%
rename from plat/mediatek/mt8192/drivers/rtc/rtc.h
rename to plat/mediatek/common/drivers/rtc/rtc_mt6359p.h
index 419bfe4..04726e3 100644
--- a/plat/mediatek/mt8192/drivers/rtc/rtc.h
+++ b/plat/mediatek/common/drivers/rtc/rtc_mt6359p.h
@@ -4,8 +4,8 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#ifndef RTC_H
-#define RTC_H
+#ifndef RTC_MT6359P_H
+#define RTC_MT6359P_H
 
 /* RTC registers */
 enum {
@@ -194,4 +194,4 @@
 int32_t Writeif_unlock(void);
 void rtc_power_off_sequence(void);
 
-#endif /* RTC_H */
+#endif /* RTC_MT6359P_H */
diff --git a/plat/mediatek/mt8192/drivers/timer/mt_timer.c b/plat/mediatek/common/drivers/timer/mt_timer.c
similarity index 100%
rename from plat/mediatek/mt8192/drivers/timer/mt_timer.c
rename to plat/mediatek/common/drivers/timer/mt_timer.c
diff --git a/plat/mediatek/mt8192/drivers/timer/mt_timer.h b/plat/mediatek/common/drivers/timer/mt_timer.h
similarity index 100%
rename from plat/mediatek/mt8192/drivers/timer/mt_timer.h
rename to plat/mediatek/common/drivers/timer/mt_timer.h
diff --git a/plat/mediatek/mt8192/plat_mt_cirq.c b/plat/mediatek/common/mtk_cirq.c
similarity index 99%
rename from plat/mediatek/mt8192/plat_mt_cirq.c
rename to plat/mediatek/common/mtk_cirq.c
index 9002b7e..de37986 100644
--- a/plat/mediatek/mt8192/plat_mt_cirq.c
+++ b/plat/mediatek/common/mtk_cirq.c
@@ -10,8 +10,7 @@
 #include <lib/mmio.h>
 
 #include <mt_gic_v3.h>
-#include <plat_mt_cirq.h>
-#include <platform_def.h>
+#include <mtk_cirq.h>
 
 static struct cirq_events cirq_all_events = {
 	.spi_start = CIRQ_SPI_START,
diff --git a/plat/mediatek/mt8192/include/plat_mt_cirq.h b/plat/mediatek/common/mtk_cirq.h
similarity index 93%
rename from plat/mediatek/mt8192/include/plat_mt_cirq.h
rename to plat/mediatek/common/mtk_cirq.h
index bb8b457..6e63bb8 100644
--- a/plat/mediatek/mt8192/include/plat_mt_cirq.h
+++ b/plat/mediatek/common/mtk_cirq.h
@@ -8,6 +8,7 @@
 #define PLAT_MT_CIRQ_H
 
 #include <stdint.h>
+#include <platform_def.h>
 
 enum {
 	IRQ_MASK_HEADER = 0xF1F1F1F1,
@@ -35,13 +36,6 @@
 /*
  * Define hardware register
  */
-
-#define  SYS_CIRQ_BASE         U(0x10204000)
-#define  CIRQ_REG_NUM          U(14)
-#define  CIRQ_IRQ_NUM          U(439)
-#define  CIRQ_SPI_START        U(64)
-#define  MD_WDT_IRQ_BIT_ID     U(110)
-
 #define  CIRQ_STA_BASE         (SYS_CIRQ_BASE + U(0x000))
 #define  CIRQ_ACK_BASE         (SYS_CIRQ_BASE + U(0x080))
 #define  CIRQ_MASK_BASE        (SYS_CIRQ_BASE + U(0x100))
diff --git a/plat/mediatek/mt8192/bl31_plat_setup.c b/plat/mediatek/mt8192/bl31_plat_setup.c
index 61215a8..c3cb9a5 100644
--- a/plat/mediatek/mt8192/bl31_plat_setup.c
+++ b/plat/mediatek/mt8192/bl31_plat_setup.c
@@ -102,7 +102,7 @@
 	mt_gic_driver_init();
 	mt_gic_init();
 
-	plat_mt8192_gpio_init();
+	mt_gpio_init();
 	mt_systimer_init();
 	generic_delay_timer_init();
 	spm_boot_init();
diff --git a/plat/mediatek/mt8192/drivers/gpio/mtgpio.c b/plat/mediatek/mt8192/drivers/gpio/mtgpio.c
index e07b75a..c78332d 100644
--- a/plat/mediatek/mt8192/drivers/gpio/mtgpio.c
+++ b/plat/mediatek/mt8192/drivers/gpio/mtgpio.c
@@ -5,94 +5,17 @@
  */
 
 #include <assert.h>
-#include <common/debug.h>
-#include <drivers/delay_timer.h>
-#include <drivers/gpio.h>
-#include <lib/mmio.h>
 #include <mtgpio.h>
 #include <platform_def.h>
 
-/******************************************************************************
- *Macro Definition
- ******************************************************************************/
-#define GPIO_MODE_BITS		4
-#define MAX_GPIO_MODE_PER_REG	8
-#define MAX_GPIO_REG_BITS	32
-#define DIR_BASE		(GPIO_BASE + 0x000)
-#define DOUT_BASE		(GPIO_BASE + 0x100)
-#define DIN_BASE		(GPIO_BASE + 0x200)
-#define MODE_BASE		(GPIO_BASE + 0x300)
-#define SET			0x4
-#define CLR			0x8
-
-static void mt_set_gpio_dir_chip(uint32_t pin, int dir)
-{
-	uint32_t pos, bit;
-
-	assert(pin < MAX_GPIO_PIN);
-	assert(dir < MT_GPIO_DIR_MAX);
-
-	pos = pin / MAX_GPIO_REG_BITS;
-	bit = pin % MAX_GPIO_REG_BITS;
-
-	if (dir == MT_GPIO_DIR_IN) {
-		mmio_write_32(DIR_BASE + 0x10U * pos + CLR, 1U << bit);
-	} else {
-		mmio_write_32(DIR_BASE + 0x10U * pos + SET, 1U << bit);
-	}
-}
-
-static int mt_get_gpio_dir_chip(uint32_t pin)
-{
-	uint32_t pos, bit;
-	uint32_t reg;
-
-	assert(pin < MAX_GPIO_PIN);
-
-	pos = pin / MAX_GPIO_REG_BITS;
-	bit = pin % MAX_GPIO_REG_BITS;
-
-	reg = mmio_read_32(DIR_BASE + 0x10U * pos);
-	return (((reg & (1U << bit)) != 0U) ? MT_GPIO_DIR_OUT : MT_GPIO_DIR_IN);
-}
-
-static void mt_set_gpio_out_chip(uint32_t pin, int output)
-{
-	uint32_t pos, bit;
-
-	assert(pin < MAX_GPIO_PIN);
-	assert(output < MT_GPIO_OUT_MAX);
-
-	pos = pin / MAX_GPIO_REG_BITS;
-	bit = pin % MAX_GPIO_REG_BITS;
-
-	if (output == MT_GPIO_OUT_ZERO) {
-		mmio_write_32(DOUT_BASE + 0x10U * pos + CLR, 1U << bit);
-	} else {
-		mmio_write_32(DOUT_BASE + 0x10U * pos + SET, 1U << bit);
-	}
-}
-
-static int mt_get_gpio_in_chip(uint32_t pin)
-{
-	uint32_t pos, bit;
-	uint32_t reg;
-
-	assert(pin < MAX_GPIO_PIN);
-
-	pos = pin / MAX_GPIO_REG_BITS;
-	bit = pin % MAX_GPIO_REG_BITS;
-
-	reg = mmio_read_32(DIN_BASE + 0x10U * pos);
-	return (((reg & (1U << bit)) != 0U) ? 1 : 0);
-}
-
-static uintptr_t mt_gpio_find_reg_addr(uint32_t pin)
+uintptr_t mt_gpio_find_reg_addr(uint32_t pin)
 {
 	uintptr_t reg_addr = 0U;
 	struct mt_pin_info gpio_info;
 
-	gpio_info = mt8192_pin_infos[pin];
+	assert(pin < MAX_GPIO_PIN);
+
+	gpio_info = mt_pin_infos[pin];
 
 	switch (gpio_info.base & 0x0f) {
 	case 0:
@@ -128,213 +51,3 @@
 
 	return reg_addr;
 }
-
-static void mt_gpio_set_spec_pull_pupd(uint32_t pin, int enable,
-			       int select)
-{
-	uintptr_t reg1;
-	uintptr_t reg2;
-	struct mt_pin_info gpio_info;
-
-	gpio_info = mt8192_pin_infos[pin];
-	uint32_t bit = gpio_info.bit;
-
-	reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset;
-	reg2 = reg1 + (gpio_info.base & 0xf0);
-	if (enable == MT_GPIO_PULL_ENABLE) {
-		mmio_write_32(reg2 + SET, (1U << bit));
-		if (select == MT_GPIO_PULL_DOWN) {
-			mmio_write_32(reg1 + SET, (1U << bit));
-		} else {
-			mmio_write_32(reg1 + CLR, (1U << bit));
-		}
-	} else {
-		mmio_write_32(reg2 + CLR, (1U << bit));
-		mmio_write_32((reg2 + 0x010U) + CLR, (1U << bit));
-	}
-}
-
-static void mt_gpio_set_pull_pu_pd(uint32_t pin, int enable,
-				 int select)
-{
-	uintptr_t reg1;
-	uintptr_t reg2;
-	struct mt_pin_info gpio_info;
-
-	gpio_info = mt8192_pin_infos[pin];
-	uint32_t bit = gpio_info.bit;
-
-	reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset;
-	reg2 = reg1 - (gpio_info.base & 0xf0);
-
-	if (enable == MT_GPIO_PULL_ENABLE) {
-		if (select == MT_GPIO_PULL_DOWN) {
-			mmio_write_32(reg1 + CLR, (1U << bit));
-			mmio_write_32(reg2 + SET, (1U << bit));
-		} else {
-			mmio_write_32(reg2 + CLR, (1U << bit));
-			mmio_write_32(reg1 + SET, (1U << bit));
-		}
-	} else {
-		mmio_write_32(reg1 + CLR, (1U << bit));
-		mmio_write_32(reg2 + CLR, (1U << bit));
-	}
-}
-
-static void mt_gpio_set_pull_chip(uint32_t pin, int enable,
-		   int select)
-{
-	struct mt_pin_info gpio_info;
-
-	gpio_info = mt8192_pin_infos[pin];
-	if (gpio_info.flag) {
-		mt_gpio_set_spec_pull_pupd(pin, enable, select);
-	} else {
-		mt_gpio_set_pull_pu_pd(pin, enable, select);
-	}
-}
-
-static int mt_gpio_get_spec_pull_pupd(uint32_t pin)
-{
-	uintptr_t reg1;
-	uintptr_t reg2;
-	uint32_t r0;
-	uint32_t r1;
-
-	struct mt_pin_info gpio_info;
-
-	gpio_info = mt8192_pin_infos[pin];
-	uint32_t bit = gpio_info.bit;
-
-	reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset;
-	reg2 = reg1 + (gpio_info.base & 0xf0);
-
-	r0 = (mmio_read_32(reg2) >> bit) & 1U;
-	r1 = (mmio_read_32(reg2 + 0x010) >> bit) & 1U;
-	if (r0 == 0U && r1 == 0U) {
-		return MT_GPIO_PULL_NONE;
-	} else {
-		if (mmio_read_32(reg1) & (1U << bit)) {
-			return MT_GPIO_PULL_DOWN;
-		} else {
-			return MT_GPIO_PULL_UP;
-		}
-	}
-}
-
-static int mt_gpio_get_pull_pu_pd(uint32_t pin)
-{
-	uintptr_t reg1;
-	uintptr_t reg2;
-	uint32_t pu;
-	uint32_t pd;
-
-	struct mt_pin_info gpio_info;
-
-	gpio_info = mt8192_pin_infos[pin];
-	uint32_t bit = gpio_info.bit;
-
-	reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset;
-	reg2 = reg1 - (gpio_info.base & 0xf0);
-	pu = (mmio_read_32(reg1) >> bit) & 1U;
-	pd = (mmio_read_32(reg2) >> bit) & 1U;
-	if (pu == 1U) {
-		return MT_GPIO_PULL_UP;
-	} else if (pd == 1U) {
-		return MT_GPIO_PULL_DOWN;
-	} else {
-		return MT_GPIO_PULL_NONE;
-	}
-}
-
-static int mt_gpio_get_pull_chip(uint32_t pin)
-{
-	struct mt_pin_info gpio_info;
-
-	gpio_info = mt8192_pin_infos[pin];
-	if (gpio_info.flag) {
-		return mt_gpio_get_spec_pull_pupd(pin);
-	} else {
-		return mt_gpio_get_pull_pu_pd(pin);
-	}
-}
-
-static void mt_set_gpio_pull_select_chip(uint32_t pin, int sel)
-{
-	assert(pin < MAX_GPIO_PIN);
-
-	if (sel == MT_GPIO_PULL_NONE) {
-		mt_gpio_set_pull_chip(pin, MT_GPIO_PULL_DISABLE, MT_GPIO_PULL_DOWN);
-	} else if (sel == MT_GPIO_PULL_UP) {
-		mt_gpio_set_pull_chip(pin, MT_GPIO_PULL_ENABLE, MT_GPIO_PULL_UP);
-	} else if (sel == MT_GPIO_PULL_DOWN) {
-		mt_gpio_set_pull_chip(pin, MT_GPIO_PULL_ENABLE, MT_GPIO_PULL_DOWN);
-	}
-}
-
-/* get pull-up or pull-down, regardless of resistor value */
-static int mt_get_gpio_pull_select_chip(uint32_t pin)
-{
-	assert(pin < MAX_GPIO_PIN);
-
-	return mt_gpio_get_pull_chip(pin);
-}
-
-static void mt_set_gpio_dir(int gpio, int direction)
-{
-	mt_set_gpio_dir_chip((uint32_t)gpio, direction);
-}
-
-static int mt_get_gpio_dir(int gpio)
-{
-	uint32_t pin;
-
-	pin = (uint32_t)gpio;
-	return mt_get_gpio_dir_chip(pin);
-}
-
-static void mt_set_gpio_pull(int gpio, int pull)
-{
-	uint32_t pin;
-
-	pin = (uint32_t)gpio;
-	mt_set_gpio_pull_select_chip(pin, pull);
-}
-
-static int mt_get_gpio_pull(int gpio)
-{
-	uint32_t pin;
-
-	pin = (uint32_t)gpio;
-	return mt_get_gpio_pull_select_chip(pin);
-}
-
-static void mt_set_gpio_out(int gpio, int value)
-{
-	uint32_t pin;
-
-	pin = (uint32_t)gpio;
-	mt_set_gpio_out_chip(pin, value);
-}
-
-static int mt_get_gpio_in(int gpio)
-{
-	uint32_t pin;
-
-	pin = (uint32_t)gpio;
-	return mt_get_gpio_in_chip(pin);
-}
-
-const gpio_ops_t mtgpio_ops = {
-	 .get_direction = mt_get_gpio_dir,
-	 .set_direction = mt_set_gpio_dir,
-	 .get_value = mt_get_gpio_in,
-	 .set_value = mt_set_gpio_out,
-	 .set_pull = mt_set_gpio_pull,
-	 .get_pull = mt_get_gpio_pull,
-};
-
-void plat_mt8192_gpio_init(void)
-{
-	gpio_init(&mtgpio_ops);
-}
diff --git a/plat/mediatek/mt8192/drivers/gpio/mtgpio.h b/plat/mediatek/mt8192/drivers/gpio/mtgpio.h
index ca0c964..d3aa24d 100644
--- a/plat/mediatek/mt8192/drivers/gpio/mtgpio.h
+++ b/plat/mediatek/mt8192/drivers/gpio/mtgpio.h
@@ -7,17 +7,7 @@
 #ifndef MT_GPIO_H
 #define MT_GPIO_H
 
-#include <stdbool.h>
-#include <stdint.h>
-
-#include <plat/common/common_def.h>
-
-/*  Error Code No. */
-#define RSUCCESS        0
-#define ERACCESS        1
-#define ERINVAL         2
-#define ERWRAPPER       3
-#define MAX_GPIO_PIN    MT_GPIO_BASE_MAX
+#include <mtgpio_common.h>
 
 /* Enumeration for GPIO pin */
 typedef enum GPIO_PIN {
@@ -54,110 +44,7 @@
 	MT_GPIO_BASE_MAX
 } GPIO_PIN;
 
-/* GPIO MODE CONTROL VALUE*/
-typedef enum {
-	GPIO_MODE_UNSUPPORTED = -1,
-	GPIO_MODE_GPIO  = 0,
-	GPIO_MODE_00    = 0,
-	GPIO_MODE_01,
-	GPIO_MODE_02,
-	GPIO_MODE_03,
-	GPIO_MODE_04,
-	GPIO_MODE_05,
-	GPIO_MODE_06,
-	GPIO_MODE_07,
-
-	GPIO_MODE_MAX,
-	GPIO_MODE_DEFAULT = GPIO_MODE_00,
-} GPIO_MODE;
-
-/* GPIO DIRECTION */
-typedef enum {
-	MT_GPIO_DIR_UNSUPPORTED = -1,
-	MT_GPIO_DIR_OUT    = 0,
-	MT_GPIO_DIR_IN     = 1,
-	MT_GPIO_DIR_MAX,
-	MT_GPIO_DIR_DEFAULT = MT_GPIO_DIR_IN,
-} GPIO_DIR;
-
-/* GPIO PULL ENABLE*/
-typedef enum {
-	MT_GPIO_PULL_EN_UNSUPPORTED = -1,
-	MT_GPIO_PULL_DISABLE   = 0,
-	MT_GPIO_PULL_ENABLE    = 1,
-	MT_GPIO_PULL_ENABLE_R0 = 2,
-	MT_GPIO_PULL_ENABLE_R1 = 3,
-	MT_GPIO_PULL_ENABLE_R0R1 = 4,
-
-	MT_GPIO_PULL_EN_MAX,
-	MT_GPIO_PULL_EN_DEFAULT = MT_GPIO_PULL_ENABLE,
-} GPIO_PULL_EN;
-
-/* GPIO PULL-UP/PULL-DOWN*/
-typedef enum {
-	MT_GPIO_PULL_UNSUPPORTED = -1,
-	MT_GPIO_PULL_NONE        = 0,
-	MT_GPIO_PULL_UP          = 1,
-	MT_GPIO_PULL_DOWN        = 2,
-	MT_GPIO_PULL_MAX,
-	MT_GPIO_PULL_DEFAULT = MT_GPIO_PULL_DOWN
-} GPIO_PULL;
-
-/* GPIO OUTPUT */
-typedef enum {
-	MT_GPIO_OUT_UNSUPPORTED = -1,
-	MT_GPIO_OUT_ZERO = 0,
-	MT_GPIO_OUT_ONE  = 1,
-
-	MT_GPIO_OUT_MAX,
-	MT_GPIO_OUT_DEFAULT = MT_GPIO_OUT_ZERO,
-	MT_GPIO_DATA_OUT_DEFAULT = MT_GPIO_OUT_ZERO,  /*compatible with DCT*/
-} GPIO_OUT;
-
-/* GPIO INPUT */
-typedef enum {
-	MT_GPIO_IN_UNSUPPORTED = -1,
-	MT_GPIO_IN_ZERO = 0,
-	MT_GPIO_IN_ONE  = 1,
-
-	MT_GPIO_IN_MAX,
-} GPIO_IN;
-
-typedef struct {
-	uint32_t val;
-	uint32_t set;
-	uint32_t rst;
-	uint32_t _align1;
-} VAL_REGS;
-
-typedef struct {
-	VAL_REGS dir[7];
-	uint8_t rsv00[144];
-	VAL_REGS dout[7];
-	uint8_t rsv01[144];
-	VAL_REGS din[7];
-	uint8_t rsv02[144];
-	VAL_REGS mode[28];
-} GPIO_REGS;
-
-
-#define PIN(_id, _flag, _bit, _base, _offset) {		\
-		.id = _id,				\
-		.flag = _flag,				\
-		.bit = _bit,				\
-		.base = _base,				\
-		.offset = _offset,			\
-	}
-
-struct mt_pin_info {
-	uint8_t id;
-	uint8_t flag;
-	uint8_t bit;
-	uint16_t base;
-	uint16_t offset;
-};
-
-static const struct mt_pin_info mt8192_pin_infos[] = {
+static const struct mt_pin_info mt_pin_infos[] = {
 	PIN(0, 0, 9, 0x23, 0xb0),
 	PIN(1, 0, 10, 0x23, 0xb0),
 	PIN(2, 0, 11, 0x23, 0xb0),
@@ -379,6 +266,4 @@
 	PIN(218, 0, 1, 0x14, 0x50),
 	PIN(219, 0, 2, 0x14, 0x50),
 };
-
-void plat_mt8192_gpio_init(void);
 #endif /* MT_GPIO_H */
diff --git a/plat/mediatek/mt8192/drivers/mcdi/mt_lp_irqremain.c b/plat/mediatek/mt8192/drivers/mcdi/mt_lp_irqremain.c
index 809518f..e74d3e7 100644
--- a/plat/mediatek/mt8192/drivers/mcdi/mt_lp_irqremain.c
+++ b/plat/mediatek/mt8192/drivers/mcdi/mt_lp_irqremain.c
@@ -6,8 +6,8 @@
 
 #include <mt_lp_rm.h>
 #include <mt_lp_irqremain.h>
+#include <mtk_cirq.h>
 #include <plat_mtk_lpm.h>
-#include <plat_mt_cirq.h>
 
 #define EDMA0_IRQ_ID		U(448)
 #define MDLA_IRQ_ID		U(446)
diff --git a/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_bus26m.c b/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_bus26m.c
index 92fd25f..f66b8ec 100644
--- a/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_bus26m.c
+++ b/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_bus26m.c
@@ -24,7 +24,7 @@
 
 #ifndef ATF_PLAT_CIRQ_UNSUPPORT
 #include <mt_gic_v3.h>
-#include <plat_mt_cirq.h>
+#include <mtk_cirq.h>
 #endif
 
 #define CONSTRAINT_BUS26M_ALLOW			\
diff --git a/plat/mediatek/mt8192/include/platform_def.h b/plat/mediatek/mt8192/include/platform_def.h
index 17e9a15..320124f 100644
--- a/plat/mediatek/mt8192/include/platform_def.h
+++ b/plat/mediatek/mt8192/include/platform_def.h
@@ -65,13 +65,19 @@
 #define SYS_COUNTER_FREQ_IN_MHZ      13
 
 /*******************************************************************************
- * GIC-400 & interrupt handling related constants
+ * GIC-600 & interrupt handling related constants
  ******************************************************************************/
 
 /* Base MTK_platform compatible GIC memory map */
 #define BASE_GICD_BASE        MT_GIC_BASE
 #define MT_GIC_RDIST_BASE     (MT_GIC_BASE + 0x40000)
 
+#define SYS_CIRQ_BASE         (IO_PHYS + 0x204000)
+#define CIRQ_REG_NUM          14
+#define CIRQ_IRQ_NUM          439
+#define CIRQ_SPI_START        64
+#define MD_WDT_IRQ_BIT_ID     110
+
 /*******************************************************************************
  * Platform binary types for linking
  ******************************************************************************/
diff --git a/plat/mediatek/mt8192/include/rtc.h b/plat/mediatek/mt8192/include/rtc.h
new file mode 100644
index 0000000..a9c7bc8
--- /dev/null
+++ b/plat/mediatek/mt8192/include/rtc.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RTC_H
+#define RTC_H
+
+#include <rtc_mt6359p.h>
+
+#endif  /* RTC_H */
diff --git a/plat/mediatek/mt8192/platform.mk b/plat/mediatek/mt8192/platform.mk
index c5a9ae0..1a57ea8 100644
--- a/plat/mediatek/mt8192/platform.mk
+++ b/plat/mediatek/mt8192/platform.mk
@@ -8,7 +8,11 @@
 MTK_PLAT_SOC  := ${MTK_PLAT}/${PLAT}
 
 PLAT_INCLUDES := -I${MTK_PLAT}/common/                            \
-                 -I${MTK_PLAT}/common/drivers/uart/                \
+                 -I${MTK_PLAT}/common/drivers/gic600/             \
+                 -I${MTK_PLAT}/common/drivers/gpio/               \
+                 -I${MTK_PLAT}/common/drivers/rtc/                \
+                 -I${MTK_PLAT}/common/drivers/timer/              \
+                 -I${MTK_PLAT}/common/drivers/uart/               \
                  -I${MTK_PLAT}/common/lpm/                        \
                  -I${MTK_PLAT_SOC}/include/                       \
                  -I${MTK_PLAT_SOC}/drivers/                       \
@@ -19,9 +23,7 @@
                  -I${MTK_PLAT_SOC}/drivers/mcdi/                  \
                  -I${MTK_PLAT_SOC}/drivers/pmic/                  \
                  -I${MTK_PLAT_SOC}/drivers/ptp3/                  \
-                 -I${MTK_PLAT_SOC}/drivers/rtc/                   \
-                 -I${MTK_PLAT_SOC}/drivers/spmc/                  \
-                 -I${MTK_PLAT_SOC}/drivers/timer/
+                 -I${MTK_PLAT_SOC}/drivers/spmc/
 
 GICV3_SUPPORT_GIC600        :=      1
 include drivers/arm/gic/v3/gicv3.mk
@@ -41,10 +43,15 @@
                    lib/cpus/aarch64/cortex_a55.S                         \
                    lib/cpus/aarch64/cortex_a76.S                         \
                    plat/common/plat_gicv3.c                              \
+                   ${MTK_PLAT}/common/drivers/gic600/mt_gic_v3.c         \
+                   ${MTK_PLAT}/common/drivers/gpio/mtgpio_common.c       \
                    ${MTK_PLAT}/common/drivers/pmic_wrap/pmic_wrap_init_v2.c \
                    ${MTK_PLAT}/common/drivers/rtc/rtc_common.c           \
+                   ${MTK_PLAT}/common/drivers/rtc/rtc_mt6359p.c          \
+                   ${MTK_PLAT}/common/drivers/timer/mt_timer.c           \
                    ${MTK_PLAT}/common/drivers/uart/uart.c                \
                    ${MTK_PLAT}/common/lpm/mt_lp_rm.c                     \
+                   ${MTK_PLAT}/common/mtk_cirq.c                         \
                    ${MTK_PLAT}/common/mtk_plat_common.c                  \
                    ${MTK_PLAT}/common/mtk_sip_svc.c                      \
                    ${MTK_PLAT}/common/params_setup.c                     \
@@ -52,11 +59,8 @@
                    ${MTK_PLAT_SOC}/aarch64/plat_helpers.S                \
                    ${MTK_PLAT_SOC}/bl31_plat_setup.c                     \
                    ${MTK_PLAT_SOC}/drivers/pmic/pmic.c                   \
-                   ${MTK_PLAT_SOC}/drivers/rtc/rtc.c                     \
                    ${MTK_PLAT_SOC}/plat_pm.c                             \
                    ${MTK_PLAT_SOC}/plat_topology.c                       \
-                   ${MTK_PLAT_SOC}/plat_mt_gic.c                         \
-                   ${MTK_PLAT_SOC}/plat_mt_cirq.c                        \
                    ${MTK_PLAT_SOC}/plat_sip_calls.c                      \
                    ${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm.c                 \
                    ${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm_utils.c           \
@@ -68,8 +72,7 @@
                    ${MTK_PLAT_SOC}/drivers/mcdi/mt_lp_irqremain.c        \
                    ${MTK_PLAT_SOC}/drivers/mcdi/mt_mcdi.c                \
                    ${MTK_PLAT_SOC}/drivers/ptp3/mtk_ptp3_main.c          \
-                   ${MTK_PLAT_SOC}/drivers/spmc/mtspmc.c                 \
-                   ${MTK_PLAT_SOC}/drivers/timer/mt_timer.c
+                   ${MTK_PLAT_SOC}/drivers/spmc/mtspmc.c
 
 # Build SPM drivers
 include ${MTK_PLAT_SOC}/drivers/spm/build.mk
diff --git a/plat/mediatek/mt8195/aarch64/plat_helpers.S b/plat/mediatek/mt8195/aarch64/plat_helpers.S
new file mode 100644
index 0000000..a973f4d
--- /dev/null
+++ b/plat/mediatek/mt8195/aarch64/plat_helpers.S
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+
+	.globl plat_is_my_cpu_primary
+	.globl plat_my_core_pos
+	.globl plat_mediatek_calc_core_pos
+
+func plat_is_my_cpu_primary
+	mrs	x0, mpidr_el1
+	and	x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+	cmp	x0, #PLAT_PRIMARY_CPU
+	cset	x0, eq
+	ret
+endfunc plat_is_my_cpu_primary
+
+	/* -----------------------------------------------------
+	 *  unsigned int plat_my_core_pos(void)
+	 *  This function uses the plat_mediatek_calc_core_pos()
+	 *  definition to get the index of the calling CPU.
+	 * -----------------------------------------------------
+	 */
+func plat_my_core_pos
+	mrs	x0, mpidr_el1
+	b	plat_mediatek_calc_core_pos
+endfunc plat_my_core_pos
+
+	/* -----------------------------------------------------
+	 * unsigned int plat_mediatek_calc_core_pos(u_register_t mpidr);
+	 *
+	 * In ARMv8.2, AFF2 is cluster id, AFF1 is core id and
+	 * AFF0 is thread id. There is only one cluster in ARMv8.2
+	 * and one thread in current implementation.
+	 *
+	 * With this function: CorePos = CoreID (AFF1)
+	 * we do it with x0 = (x0 >> 8) & 0xff
+	 * -----------------------------------------------------
+	 */
+func plat_mediatek_calc_core_pos
+	mov	x1, #MPIDR_AFFLVL_MASK
+	and	x0, x1, x0, lsr #MPIDR_AFF1_SHIFT
+	ret
+endfunc plat_mediatek_calc_core_pos
diff --git a/plat/mediatek/mt8195/aarch64/platform_common.c b/plat/mediatek/mt8195/aarch64/platform_common.c
new file mode 100644
index 0000000..745e547
--- /dev/null
+++ b/plat/mediatek/mt8195/aarch64/platform_common.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/xlat_tables/xlat_tables_v2.h>
+
+#include <platform_def.h>
+
+/* Table of regions to map using the MMU.  */
+const mmap_region_t plat_mmap[] = {
+	/* for TF text, RO, RW */
+	MAP_REGION_FLAT(MTK_DEV_RNG0_BASE, MTK_DEV_RNG0_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(MTK_DEV_RNG1_BASE, MTK_DEV_RNG1_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(MTK_DEV_RNG2_BASE, MTK_DEV_RNG2_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE),
+	{ 0 }
+};
+
+/*******************************************************************************
+ * Macro generating the code for the function setting up the pagetables as per
+ * the platform memory map & initialize the mmu, for the given exception level
+ ******************************************************************************/
+void plat_configure_mmu_el3(uintptr_t total_base,
+			    uintptr_t total_size,
+			    uintptr_t ro_start,
+			    uintptr_t ro_limit)
+{
+	mmap_add_region(total_base, total_base, total_size,
+			MT_RW_DATA | MT_SECURE);
+	mmap_add_region(ro_start, ro_start, ro_limit - ro_start,
+			MT_CODE | MT_SECURE);
+	mmap_add(plat_mmap);
+	init_xlat_tables();
+	enable_mmu_el3(0);
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+	return SYS_COUNTER_FREQ_IN_TICKS;
+}
diff --git a/plat/mediatek/mt8195/bl31_plat_setup.c b/plat/mediatek/mt8195/bl31_plat_setup.c
new file mode 100644
index 0000000..eaff349
--- /dev/null
+++ b/plat/mediatek/mt8195/bl31_plat_setup.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* System Includes */
+#include <assert.h>
+
+/* Project Includes */
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <drivers/generic_delay_timer.h>
+#include <drivers/ti/uart/uart_16550.h>
+#include <lib/coreboot.h>
+
+/* Platform Includes */
+#include <mt_gic_v3.h>
+#include <mt_timer.h>
+#include <mtgpio.h>
+#include <plat_params.h>
+#include <plat_private.h>
+
+static entry_point_info_t bl32_ep_info;
+static entry_point_info_t bl33_ep_info;
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image for
+ * the security state specified. BL33 corresponds to the non-secure image type
+ * while BL32 corresponds to the secure image type. A NULL pointer is returned
+ * if the image does not exist.
+ ******************************************************************************/
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+	entry_point_info_t *next_image_info;
+
+	next_image_info = (type == NON_SECURE) ? &bl33_ep_info : &bl32_ep_info;
+	assert(next_image_info->h.type == PARAM_EP);
+
+	/* None of the images on this platform can have 0x0 as the entrypoint */
+	if (next_image_info->pc) {
+		return next_image_info;
+	} else {
+		return NULL;
+	}
+}
+
+/*******************************************************************************
+ * Perform any BL31 early platform setup. Here is an opportunity to copy
+ * parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before they
+ * are lost (potentially). This needs to be done before the MMU is initialized
+ * so that the memory layout can be used while creating page tables.
+ * BL2 has flushed this information to memory, so we are guaranteed to pick up
+ * good data.
+ ******************************************************************************/
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+				u_register_t arg2, u_register_t arg3)
+{
+	static console_t console;
+
+	params_early_setup(arg1);
+
+#if COREBOOT
+	if (coreboot_serial.type) {
+		console_16550_register(coreboot_serial.baseaddr,
+				       coreboot_serial.input_hertz,
+				       coreboot_serial.baud,
+				       &console);
+	}
+#else
+	console_16550_register(UART0_BASE, UART_CLOCK, UART_BAUDRATE, &console);
+#endif
+
+	NOTICE("MT8195 bl31_setup\n");
+
+	bl31_params_parse_helper(arg0, &bl32_ep_info, &bl33_ep_info);
+}
+
+
+/*******************************************************************************
+ * Perform any BL31 platform setup code
+ ******************************************************************************/
+void bl31_platform_setup(void)
+{
+	/* Initialize the GIC driver, CPU and distributor interfaces */
+	mt_gic_driver_init();
+	mt_gic_init();
+
+	mt_gpio_init();
+	mt_systimer_init();
+	generic_delay_timer_init();
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only intializes the mmu in a quick and dirty way.
+ ******************************************************************************/
+void bl31_plat_arch_setup(void)
+{
+	plat_configure_mmu_el3(BL31_START,
+			       BL31_END - BL31_START,
+			       BL_CODE_BASE,
+			       BL_CODE_END);
+}
diff --git a/plat/mediatek/mt8195/drivers/gpio/mtgpio.c b/plat/mediatek/mt8195/drivers/gpio/mtgpio.c
new file mode 100644
index 0000000..daab84c
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/gpio/mtgpio.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <mtgpio.h>
+#include <platform_def.h>
+
+uintptr_t mt_gpio_find_reg_addr(uint32_t pin)
+{
+	uintptr_t reg_addr = 0U;
+	struct mt_pin_info gpio_info;
+
+	assert(pin < MAX_GPIO_PIN);
+
+	gpio_info = mt_pin_infos[pin];
+
+	switch (gpio_info.base & 0x0f) {
+	case 0:
+		reg_addr = IOCFG_BM_BASE;
+		break;
+	case 1:
+		reg_addr = IOCFG_BL_BASE;
+		break;
+	case 2:
+		reg_addr = IOCFG_BR_BASE;
+		break;
+	case 3:
+		reg_addr = IOCFG_LM_BASE;
+		break;
+	case 4:
+		reg_addr = IOCFG_RB_BASE;
+		break;
+	case 5:
+		reg_addr = IOCFG_TL_BASE;
+		break;
+	default:
+		break;
+	}
+
+	return reg_addr;
+}
diff --git a/plat/mediatek/mt8195/drivers/gpio/mtgpio.h b/plat/mediatek/mt8195/drivers/gpio/mtgpio.h
new file mode 100644
index 0000000..88b4706
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/gpio/mtgpio.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_GPIO_H
+#define MT_GPIO_H
+
+#include <mtgpio_common.h>
+
+/* Enumeration for GPIO pin */
+typedef enum GPIO_PIN {
+	GPIO_UNSUPPORTED = -1,
+
+	GPIO0, GPIO1, GPIO2, GPIO3, GPIO4, GPIO5, GPIO6, GPIO7,
+	GPIO8, GPIO9, GPIO10, GPIO11, GPIO12, GPIO13, GPIO14, GPIO15,
+	GPIO16, GPIO17, GPIO18, GPIO19, GPIO20, GPIO21, GPIO22, GPIO23,
+	GPIO24, GPIO25, GPIO26, GPIO27, GPIO28, GPIO29, GPIO30, GPIO31,
+	GPIO32, GPIO33, GPIO34, GPIO35, GPIO36, GPIO37, GPIO38, GPIO39,
+	GPIO40, GPIO41, GPIO42, GPIO43, GPIO44, GPIO45, GPIO46, GPIO47,
+	GPIO48, GPIO49, GPIO50, GPIO51, GPIO52, GPIO53, GPIO54, GPIO55,
+	GPIO56, GPIO57, GPIO58, GPIO59, GPIO60, GPIO61, GPIO62, GPIO63,
+	GPIO64, GPIO65, GPIO66, GPIO67, GPIO68, GPIO69, GPIO70, GPIO71,
+	GPIO72, GPIO73, GPIO74, GPIO75, GPIO76, GPIO77, GPIO78, GPIO79,
+	GPIO80, GPIO81, GPIO82, GPIO83, GPIO84, GPIO85, GPIO86, GPIO87,
+	GPIO88, GPIO89, GPIO90, GPIO91, GPIO92, GPIO93, GPIO94, GPIO95,
+	GPIO96, GPIO97, GPIO98, GPIO99, GPIO100, GPIO101, GPIO102, GPIO103,
+	GPIO104, GPIO105, GPIO106, GPIO107, GPIO108, GPIO109, GPIO110, GPIO111,
+	GPIO112, GPIO113, GPIO114, GPIO115, GPIO116, GPIO117, GPIO118, GPIO119,
+	GPIO120, GPIO121, GPIO122, GPIO123, GPIO124, GPIO125, GPIO126, GPIO127,
+	GPIO128, GPIO129, GPIO130, GPIO131, GPIO132, GPIO133, GPIO134, GPIO135,
+	GPIO136, GPIO137, GPIO138, GPIO139, GPIO140, GPIO141, GPIO142, GPIO143,
+	MT_GPIO_BASE_MAX
+} GPIO_PIN;
+
+static const struct mt_pin_info mt_pin_infos[] = {
+	PIN(0, 1, 0, 0x23, 0x60),
+	PIN(1, 1, 1, 0x23, 0x60),
+	PIN(2, 1, 2, 0x23, 0x60),
+	PIN(3, 1, 3, 0x23, 0x60),
+	PIN(4, 1, 4, 0x23, 0x60),
+	PIN(5, 1, 5, 0x23, 0x60),
+	PIN(6, 0, 6, 0x23, 0x70),
+	PIN(7, 0, 7, 0x23, 0x70),
+	PIN(8, 0, 13, 0x23, 0x70),
+	PIN(9, 0, 8, 0x23, 0x70),
+	PIN(10, 0, 14, 0x23, 0x70),
+	PIN(11, 0, 9, 0x23, 0x70),
+	PIN(12, 0, 15, 0x23, 0x70),
+	PIN(13, 0, 10, 0x23, 0x70),
+	PIN(14, 0, 16, 0x23, 0x70),
+	PIN(15, 0, 11, 0x23, 0x70),
+	PIN(16, 0, 17, 0x23, 0x70),
+	PIN(17, 0, 12, 0x23, 0x70),
+	PIN(18, 0, 5, 0x10, 0x60),
+	PIN(19, 0, 12, 0x10, 0x60),
+	PIN(20, 0, 11, 0x10, 0x60),
+	PIN(21, 0, 10, 0x10, 0x60),
+	PIN(22, 0, 0, 0x10, 0x60),
+	PIN(23, 0, 1, 0x10, 0x60),
+	PIN(24, 0, 2, 0x10, 0x60),
+	PIN(25, 0, 4, 0x10, 0x60),
+	PIN(26, 0, 3, 0x10, 0x60),
+	PIN(27, 0, 6, 0x10, 0x60),
+	PIN(28, 0, 7, 0x10, 0x60),
+	PIN(29, 0, 8, 0x10, 0x60),
+	PIN(30, 0, 9, 0x10, 0x60),
+	PIN(31, 0, 13, 0x21, 0xa0),
+	PIN(32, 0, 12, 0x21, 0xa0),
+	PIN(33, 0, 11, 0x21, 0xa0),
+	PIN(34, 0, 14, 0x21, 0xa0),
+	PIN(35, 0, 15, 0x21, 0xa0),
+	PIN(36, 0, 3, 0x21, 0xb0),
+	PIN(37, 0, 6, 0x21, 0xb0),
+	PIN(38, 0, 4, 0x21, 0xb0),
+	PIN(39, 0, 5, 0x21, 0xb0),
+	PIN(40, 0, 8, 0x21, 0xb0),
+	PIN(41, 0, 7, 0x21, 0xb0),
+	PIN(42, 0, 10, 0x21, 0xb0),
+	PIN(43, 0, 9, 0x21, 0xb0),
+	PIN(44, 0, 20, 0x21, 0xb0),
+	PIN(45, 0, 21, 0x21, 0xb0),
+	PIN(46, 0, 18, 0x21, 0xa0),
+	PIN(47, 0, 16, 0x21, 0xa0),
+	PIN(48, 0, 19, 0x21, 0xa0),
+	PIN(49, 0, 17, 0x21, 0xa0),
+	PIN(50, 0, 25, 0x21, 0xa0),
+	PIN(51, 0, 20, 0x21, 0xa0),
+	PIN(52, 0, 26, 0x21, 0xa0),
+	PIN(53, 0, 21, 0x21, 0xa0),
+	PIN(54, 0, 22, 0x21, 0xa0),
+	PIN(55, 0, 23, 0x21, 0xa0),
+	PIN(56, 0, 24, 0x21, 0xa0),
+	PIN(57, 0, 29, 0x21, 0xa0),
+	PIN(58, 0, 27, 0x21, 0xa0),
+	PIN(59, 0, 30, 0x21, 0xa0),
+	PIN(60, 0, 28, 0x21, 0xa0),
+	PIN(61, 0, 8, 0x21, 0xa0),
+	PIN(62, 0, 7, 0x21, 0xa0),
+	PIN(63, 0, 10, 0x21, 0xa0),
+	PIN(64, 0, 9, 0x21, 0xa0),
+	PIN(65, 0, 1, 0x21, 0xb0),
+	PIN(66, 0, 31, 0x21, 0xa0),
+	PIN(67, 0, 0, 0x21, 0xb0),
+	PIN(68, 0, 2, 0x21, 0xb0),
+	PIN(69, 0, 0, 0x21, 0xa0),
+	PIN(70, 0, 6, 0x21, 0xa0),
+	PIN(71, 0, 4, 0x21, 0xa0),
+	PIN(72, 0, 5, 0x21, 0xa0),
+	PIN(73, 0, 1, 0x21, 0xa0),
+	PIN(74, 0, 2, 0x21, 0xa0),
+	PIN(75, 0, 3, 0x21, 0xa0),
+	PIN(76, 0, 11, 0x21, 0xb0),
+	PIN(77, 1, 1, 0x22, 0x60),
+	PIN(78, 1, 2, 0x22, 0x60),
+	PIN(79, 1, 9, 0x22, 0x60),
+	PIN(80, 1, 10, 0x22, 0x60),
+	PIN(81, 1, 11, 0x22, 0x60),
+	PIN(82, 1, 12, 0x22, 0x60),
+	PIN(83, 1, 13, 0x22, 0x60),
+	PIN(84, 1, 14, 0x22, 0x60),
+	PIN(85, 1, 15, 0x22, 0x60),
+	PIN(86, 1, 16, 0x22, 0x60),
+	PIN(87, 1, 3, 0x22, 0x60),
+	PIN(88, 1, 4, 0x22, 0x60),
+	PIN(89, 1, 5, 0x22, 0x60),
+	PIN(90, 1, 6, 0x22, 0x60),
+	PIN(91, 1, 7, 0x22, 0x60),
+	PIN(92, 1, 8, 0x22, 0x60),
+	PIN(93, 1, 18, 0x22, 0x60),
+	PIN(94, 1, 19, 0x22, 0x60),
+	PIN(95, 1, 17, 0x22, 0x60),
+	PIN(96, 1, 0, 0x22, 0x60),
+	PIN(97, 0, 20, 0x22, 0x70),
+	PIN(98, 0, 28, 0x22, 0x70),
+	PIN(99, 0, 27, 0x22, 0x70),
+	PIN(100, 0, 30, 0x22, 0x70),
+	PIN(101, 0, 29, 0x22, 0x70),
+	PIN(102, 0, 0, 0x22, 0x70),
+	PIN(103, 0, 31, 0x22, 0x70),
+	PIN(104, 1, 25, 0x22, 0x60),
+	PIN(105, 1, 26, 0x22, 0x60),
+	PIN(106, 1, 23, 0x22, 0x60),
+	PIN(107, 1, 24, 0x22, 0x60),
+	PIN(108, 0, 22, 0x22, 0x70),
+	PIN(109, 0, 21, 0x22, 0x70),
+	PIN(110, 1, 1, 0x14, 0x20),
+	PIN(111, 1, 0, 0x14, 0x20),
+	PIN(112, 1, 2, 0x14, 0x20),
+	PIN(113, 1, 3, 0x14, 0x20),
+	PIN(114, 1, 4, 0x14, 0x20),
+	PIN(115, 1, 5, 0x14, 0x20),
+	PIN(116, 1, 9, 0x25, 0x50),
+	PIN(117, 1, 8, 0x25, 0x50),
+	PIN(118, 1, 7, 0x25, 0x50),
+	PIN(119, 1, 6, 0x25, 0x50),
+	PIN(120, 1, 11, 0x25, 0x50),
+	PIN(121, 1, 1, 0x25, 0x50),
+	PIN(122, 1, 0, 0x25, 0x50),
+	PIN(123, 1, 5, 0x25, 0x50),
+	PIN(124, 1, 4, 0x25, 0x50),
+	PIN(125, 1, 3, 0x25, 0x50),
+	PIN(126, 1, 2, 0x25, 0x50),
+	PIN(127, 1, 10, 0x25, 0x50),
+	PIN(128, 0, 3, 0x22, 0x70),
+	PIN(129, 0, 1, 0x22, 0x70),
+	PIN(130, 0, 4, 0x22, 0x70),
+	PIN(131, 0, 2, 0x22, 0x70),
+	PIN(132, 0, 13, 0x25, 0x60),
+	PIN(133, 0, 12, 0x25, 0x60),
+	PIN(134, 0, 15, 0x25, 0x60),
+	PIN(135, 0, 14, 0x25, 0x60),
+	PIN(136, 0, 13, 0x21, 0xb0),
+	PIN(137, 0, 12, 0x21, 0xb0),
+	PIN(138, 0, 15, 0x21, 0xb0),
+	PIN(139, 0, 14, 0x21, 0xb0),
+	PIN(140, 0, 17, 0x21, 0xb0),
+	PIN(141, 0, 16, 0x21, 0xb0),
+	PIN(142, 0, 19, 0x21, 0xb0),
+	PIN(143, 0, 18, 0x21, 0xb0),
+};
+#endif /* MT_GPIO_H */
diff --git a/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm.c b/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm.c
new file mode 100644
index 0000000..d6d4af7
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdint.h>
+
+#include <arch_helpers.h>
+#include <lib/psci/psci.h>
+#include <lib/spinlock.h>
+
+#include <mt_cpu_pm_cpc.h>
+#include <mt_mcdi.h>
+#include <plat_mtk_lpm.h>
+#include <plat_pm.h>
+
+DEFINE_SYSREG_RW_FUNCS(dbgprcr_el1);
+
+static int plat_mt_lp_cpu_rc;
+
+static int pwr_state_prompt(unsigned int cpu, const psci_power_state_t *state)
+{
+	return 0;
+}
+
+static int pwr_state_reflect(unsigned int cpu, const psci_power_state_t *state)
+{
+	mtk_cpc_core_on_hint_clr(cpu);
+
+	if (IS_SYSTEM_SUSPEND_STATE(state)) {
+		mtk_cpc_time_sync();
+	}
+
+	return 0;
+}
+
+static int pwr_cpu_pwron(unsigned int cpu, const psci_power_state_t *state)
+{
+	return 0;
+}
+
+static int pwr_cpu_pwrdwn(unsigned int cpu, const psci_power_state_t *state)
+{
+	/* clear DBGPRCR.CORENPDRQ to allow CPU power down  */
+	write_dbgprcr_el1(0ULL);
+
+	return 0;
+}
+
+static int pwr_cluster_pwron(unsigned int cpu, const psci_power_state_t *state)
+{
+	return 0;
+}
+
+static int pwr_cluster_pwrdwn(unsigned int cpu, const psci_power_state_t *state)
+{
+	return 0;
+}
+
+static int pwr_mcusys_pwron(unsigned int cpu, const psci_power_state_t *state)
+{
+	if (!IS_MCUSYS_OFF_STATE(state) || (plat_mt_lp_cpu_rc < 0)) {
+		return -1;
+	}
+
+	mtk_cpc_mcusys_off_reflect();
+
+	return 0;
+}
+
+static int pwr_mcusys_pwron_finished(unsigned int cpu,
+					const psci_power_state_t *state)
+{
+	if (!IS_MCUSYS_OFF_STATE(state) || (plat_mt_lp_cpu_rc < 0)) {
+		return -1;
+	}
+
+	return 0;
+}
+
+static int pwr_mcusys_pwrdwn(unsigned int cpu, const psci_power_state_t *state)
+{
+	if (!IS_MCUSYS_OFF_STATE(state)) {
+		goto mt_pwr_mcusysoff_break;
+	}
+
+	if (mcdi_try_init() != 0) { /* not ready to process mcusys-off */
+		goto mt_pwr_mcusysoff_break;
+	}
+
+	return 0;
+
+mt_pwr_mcusysoff_break:
+
+	plat_mt_lp_cpu_rc = -1;
+
+	return -1;
+}
+
+static const struct mt_lpm_tz plat_pm = {
+	.pwr_prompt			= pwr_state_prompt,
+	.pwr_reflect			= pwr_state_reflect,
+	.pwr_cpu_on			= pwr_cpu_pwron,
+	.pwr_cpu_dwn			= pwr_cpu_pwrdwn,
+	.pwr_cluster_on			= pwr_cluster_pwron,
+	.pwr_cluster_dwn		= pwr_cluster_pwrdwn,
+	.pwr_mcusys_dwn			= pwr_mcusys_pwrdwn,
+	.pwr_mcusys_on			= pwr_mcusys_pwron,
+	.pwr_mcusys_on_finished		= pwr_mcusys_pwron_finished
+};
+
+const struct mt_lpm_tz *mt_plat_cpu_pm_init(void)
+{
+	mtk_cpc_init();
+
+	if (mcdi_try_init() == 0) {
+		INFO("MCDI init done.\n");
+	}
+
+	return &plat_pm;
+}
diff --git a/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm_cpc.c b/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm_cpc.c
new file mode 100644
index 0000000..f8c51a1
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm_cpc.c
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+
+#include <drivers/delay_timer.h>
+
+#include <mt_cpu_pm_cpc.h>
+#include <mt_timer.h>
+
+struct mtk_cpc_dev {
+	int auto_off;
+	unsigned int auto_thres_tick;
+};
+
+static struct mtk_cpc_dev cpc;
+
+static int mtk_cpc_last_core_prot(uint32_t prot_req,
+				uint32_t resp_reg, uint32_t resp_ofs)
+{
+	uint32_t sta, retry;
+
+	retry = 0U;
+
+	while (retry++ < RETRY_CNT_MAX) {
+
+		mmio_write_32(CPC_MCUSYS_LAST_CORE_REQ, prot_req);
+
+		udelay(1U);
+
+		sta = (mmio_read_32(resp_reg) >> resp_ofs) & CPC_PROT_RESP_MASK;
+
+		if (sta == PROT_SUCCESS) {
+			return CPC_SUCCESS;
+		} else if (sta == PROT_GIVEUP) {
+			return CPC_ERR_FAIL;
+		}
+	}
+
+	return CPC_ERR_TIMEOUT;
+}
+
+int mtk_cpu_pm_mcusys_prot_aquire(void)
+{
+	return mtk_cpc_last_core_prot(
+			MCUSYS_PROT_SET,
+			CPC_MCUSYS_LAST_CORE_RESP,
+			MCUSYS_RESP_OFS);
+}
+
+void mtk_cpu_pm_mcusys_prot_release(void)
+{
+	mmio_write_32(CPC_MCUSYS_PWR_ON_MASK, MCUSYS_PROT_CLR);
+}
+
+int mtk_cpu_pm_cluster_prot_aquire(unsigned int cluster)
+{
+	return mtk_cpc_last_core_prot(
+			CPUSYS_PROT_SET,
+			CPC_MCUSYS_MP_LAST_CORE_RESP,
+			CPUSYS_RESP_OFS);
+}
+
+void mtk_cpu_pm_cluster_prot_release(unsigned int cluster)
+{
+	mmio_write_32(CPC_MCUSYS_PWR_ON_MASK, CPUSYS_PROT_CLR);
+}
+
+static void mtk_cpc_cluster_cnt_backup(void)
+{
+	uint32_t backup_cnt;
+	uint32_t curr_cnt;
+	uint32_t cnt_mask = GENMASK(14, 0);
+	uint32_t clr_mask = GENMASK(1, 0);
+
+	/* Single Cluster */
+	backup_cnt = mmio_read_32(CPC_CLUSTER_CNT_BACKUP);
+	curr_cnt = mmio_read_32(CPC_MCUSYS_CLUSTER_COUNTER);
+
+	/* Get off count if dormant count is 0 */
+	if ((curr_cnt & cnt_mask) == 0U) {
+		curr_cnt = (curr_cnt >> 16) & cnt_mask;
+	} else {
+		curr_cnt = curr_cnt & cnt_mask;
+	}
+
+	mmio_write_32(CPC_CLUSTER_CNT_BACKUP, backup_cnt + curr_cnt);
+	mmio_write_32(CPC_MCUSYS_CLUSTER_COUNTER_CLR, clr_mask);
+}
+
+static inline void mtk_cpc_mcusys_off_en(void)
+{
+	mmio_write_32(CPC_MCUSYS_PWR_CTRL, 1U);
+}
+
+static inline void mtk_cpc_mcusys_off_dis(void)
+{
+	mmio_write_32(CPC_MCUSYS_PWR_CTRL, 0U);
+}
+
+void mtk_cpc_mcusys_off_reflect(void)
+{
+	mtk_cpc_mcusys_off_dis();
+	mtk_cpu_pm_mcusys_prot_release();
+}
+
+int mtk_cpc_mcusys_off_prepare(void)
+{
+	if (mtk_cpu_pm_mcusys_prot_aquire() != CPC_SUCCESS) {
+		return CPC_ERR_FAIL;
+	}
+
+	mtk_cpc_cluster_cnt_backup();
+	mtk_cpc_mcusys_off_en();
+
+	return CPC_SUCCESS;
+}
+
+void mtk_cpc_core_on_hint_set(unsigned int cpu)
+{
+	mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_SET, BIT(cpu));
+}
+
+void mtk_cpc_core_on_hint_clr(unsigned int cpu)
+{
+	mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_CLR, BIT(cpu));
+}
+
+static void mtk_cpc_dump_timestamp(void)
+{
+	uint32_t id;
+
+	for (id = 0U; id < CPC_TRACE_ID_NUM; id++) {
+		mmio_write_32(CPC_MCUSYS_TRACE_SEL, id);
+
+		memcpy((void *)(uintptr_t)CPC_TRACE_SRAM(id),
+				(const void *)(uintptr_t)CPC_MCUSYS_TRACE_DATA,
+				CPC_TRACE_SIZE);
+	}
+}
+
+void mtk_cpc_time_sync(void)
+{
+	uint64_t kt;
+	uint32_t systime_l, systime_h;
+
+	kt = sched_clock();
+	systime_l = mmio_read_32(CNTSYS_L_REG);
+	systime_h = mmio_read_32(CNTSYS_H_REG);
+
+	/* sync kernel timer to cpc */
+	mmio_write_32(CPC_MCUSYS_CPC_KERNEL_TIME_L_BASE, (uint32_t)kt);
+	mmio_write_32(CPC_MCUSYS_CPC_KERNEL_TIME_H_BASE, (uint32_t)(kt >> 32));
+	/* sync system timer to cpc */
+	mmio_write_32(CPC_MCUSYS_CPC_SYSTEM_TIME_L_BASE, systime_l);
+	mmio_write_32(CPC_MCUSYS_CPC_SYSTEM_TIME_H_BASE, systime_h);
+}
+
+static void mtk_cpc_config(uint32_t cfg, uint32_t data)
+{
+	uint32_t val;
+	uint32_t reg = 0U;
+
+	switch (cfg) {
+	case CPC_SMC_CONFIG_PROF:
+		reg = CPC_MCUSYS_CPC_DBG_SETTING;
+		val = mmio_read_32(reg);
+		val = (data != 0U) ? (val | CPC_PROF_EN) : (val & ~CPC_PROF_EN);
+		break;
+	case CPC_SMC_CONFIG_AUTO_OFF:
+		reg = CPC_MCUSYS_CPC_FLOW_CTRL_CFG;
+		val = mmio_read_32(reg);
+		if (data != 0U) {
+			val |= CPC_AUTO_OFF_EN;
+			cpc.auto_off = 1;
+		} else {
+			val &= ~CPC_AUTO_OFF_EN;
+			cpc.auto_off = 0;
+		}
+		break;
+	case CPC_SMC_CONFIG_AUTO_OFF_THRES:
+		reg = CPC_MCUSYS_CPC_OFF_THRES;
+		cpc.auto_thres_tick = us_to_ticks(data);
+		val = cpc.auto_thres_tick;
+		break;
+	case CPC_SMC_CONFIG_CNT_CLR:
+		reg = CPC_MCUSYS_CLUSTER_COUNTER_CLR;
+		val = GENMASK(1, 0);	/* clr_mask */
+		break;
+	case CPC_SMC_CONFIG_TIME_SYNC:
+		mtk_cpc_time_sync();
+		break;
+	default:
+		break;
+	}
+
+	if (reg != 0U) {
+		mmio_write_32(reg, val);
+	}
+}
+
+static uint32_t mtk_cpc_read_config(uint32_t cfg)
+{
+	uint32_t res = 0U;
+
+	switch (cfg) {
+	case CPC_SMC_CONFIG_PROF:
+		res = (mmio_read_32(CPC_MCUSYS_CPC_DBG_SETTING) & CPC_PROF_EN) ?
+			1U : 0U;
+		break;
+	case CPC_SMC_CONFIG_AUTO_OFF:
+		res = cpc.auto_off;
+		break;
+	case CPC_SMC_CONFIG_AUTO_OFF_THRES:
+		res = ticks_to_us(cpc.auto_thres_tick);
+		break;
+	case CPC_SMC_CONFIG_CNT_CLR:
+		break;
+	default:
+		break;
+	}
+
+	return res;
+}
+
+uint64_t mtk_cpc_handler(uint64_t act, uint64_t arg1, uint64_t arg2)
+{
+	uint64_t res = 0ULL;
+
+	switch (act) {
+	case CPC_SMC_EVENT_DUMP_TRACE_DATA:
+		mtk_cpc_dump_timestamp();
+		break;
+	case CPC_SMC_EVENT_GIC_DPG_SET:
+		/* isolated_status = x2; */
+		break;
+	case CPC_SMC_EVENT_CPC_CONFIG:
+		mtk_cpc_config((uint32_t)arg1, (uint32_t)arg2);
+		break;
+	case CPC_SMC_EVENT_READ_CONFIG:
+		res = mtk_cpc_read_config((uint32_t)arg1);
+		break;
+	default:
+		break;
+	}
+
+	return res;
+}
+
+void mtk_cpc_init(void)
+{
+	mmio_write_32(CPC_MCUSYS_CPC_DBG_SETTING,
+			mmio_read_32(CPC_MCUSYS_CPC_DBG_SETTING)
+			| CPC_DBG_EN
+			| CPC_CALC_EN);
+
+	cpc.auto_off = 1;
+	cpc.auto_thres_tick = us_to_ticks(8000);
+
+	mmio_write_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG,
+			mmio_read_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG)
+			| CPC_OFF_PRE_EN
+			| (cpc.auto_off ? CPC_AUTO_OFF_EN : 0U));
+
+	mmio_write_32(CPC_MCUSYS_CPC_OFF_THRES, cpc.auto_thres_tick);
+}
diff --git a/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm_cpc.h b/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm_cpc.h
new file mode 100644
index 0000000..19dd6a2
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm_cpc.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_CPU_PM_CPC_H
+#define MT_CPU_PM_CPC_H
+
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+#include <mcucfg.h>
+#include <platform_def.h>
+
+#define NEED_CPUSYS_PROT_WORKAROUND	1
+
+/* system sram registers */
+#define CPUIDLE_SRAM_REG(r)	(uint32_t)(MTK_MCDI_SRAM_BASE + (r))
+
+/* db dump */
+#define CPC_TRACE_SIZE		U(0x20)
+#define CPC_TRACE_ID_NUM	U(10)
+#define CPC_TRACE_SRAM(id)	(CPUIDLE_SRAM_REG(0x10) + (id) * CPC_TRACE_SIZE)
+
+/* buckup off count */
+#define CPC_CLUSTER_CNT_BACKUP	CPUIDLE_SRAM_REG(0x1F0)
+#define CPC_MCUSYS_CNT		CPUIDLE_SRAM_REG(0x1F4)
+
+/* CPC_MCUSYS_CPC_FLOW_CTRL_CFG(0xA814): debug setting */
+#define CPC_PWR_ON_SEQ_DIS	BIT(1)
+#define CPC_PWR_ON_PRIORITY	BIT(2)
+#define CPC_AUTO_OFF_EN		BIT(5)
+#define CPC_DORMANT_WAIT_EN	BIT(14)
+#define CPC_CTRL_EN		BIT(16)
+#define CPC_OFF_PRE_EN		BIT(29)
+
+/* CPC_MCUSYS_LAST_CORE_REQ(0xA818) : last core protection */
+#define CPUSYS_PROT_SET		BIT(0)
+#define MCUSYS_PROT_SET		BIT(8)
+#define CPUSYS_PROT_CLR		BIT(8)
+#define MCUSYS_PROT_CLR		BIT(9)
+
+#define CPC_PROT_RESP_MASK	U(0x3)
+#define CPUSYS_RESP_OFS		U(16)
+#define MCUSYS_RESP_OFS		U(30)
+
+#define cpusys_resp(r)		(((r) >> CPUSYS_RESP_OFS) & CPC_PROT_RESP_MASK)
+#define mcusys_resp(r)		(((r) >> MCUSYS_RESP_OFS) & CPC_PROT_RESP_MASK)
+
+#define RETRY_CNT_MAX		U(1000)
+
+#define PROT_RETRY		U(0)
+#define PROT_SUCCESS		U(1)
+#define PROT_GIVEUP		U(2)
+
+/* CPC_MCUSYS_CPC_DBG_SETTING(0xAB00): debug setting */
+#define CPC_PROF_EN		BIT(0)
+#define CPC_DBG_EN		BIT(1)
+#define CPC_FREEZE		BIT(2)
+#define CPC_CALC_EN		BIT(3)
+
+enum {
+	CPC_SUCCESS = 0,
+
+	CPC_ERR_FAIL,
+	CPC_ERR_TIMEOUT,
+
+	NF_CPC_ERR
+};
+
+enum {
+	CPC_SMC_EVENT_DUMP_TRACE_DATA,
+	CPC_SMC_EVENT_GIC_DPG_SET,
+	CPC_SMC_EVENT_CPC_CONFIG,
+	CPC_SMC_EVENT_READ_CONFIG,
+
+	NF_CPC_SMC_EVENT
+};
+
+enum {
+	CPC_SMC_CONFIG_PROF,
+	CPC_SMC_CONFIG_AUTO_OFF,
+	CPC_SMC_CONFIG_AUTO_OFF_THRES,
+	CPC_SMC_CONFIG_CNT_CLR,
+	CPC_SMC_CONFIG_TIME_SYNC,
+
+	NF_CPC_SMC_CONFIG
+};
+
+#define us_to_ticks(us)		((us) * 13)
+#define ticks_to_us(tick)	((tick) / 13)
+
+int mtk_cpu_pm_cluster_prot_aquire(unsigned int cluster);
+void mtk_cpu_pm_cluster_prot_release(unsigned int cluster);
+
+void mtk_cpc_mcusys_off_reflect(void);
+int mtk_cpc_mcusys_off_prepare(void);
+
+void mtk_cpc_core_on_hint_set(unsigned int cpu);
+void mtk_cpc_core_on_hint_clr(unsigned int cpu);
+void mtk_cpc_time_sync(void);
+
+uint64_t mtk_cpc_handler(uint64_t act, uint64_t arg1, uint64_t arg2);
+void mtk_cpc_init(void);
+
+#endif /* MT_CPU_PM_CPC_H */
diff --git a/plat/mediatek/mt8195/drivers/mcdi/mt_mcdi.c b/plat/mediatek/mt8195/drivers/mcdi/mt_mcdi.c
new file mode 100644
index 0000000..df74122
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/mcdi/mt_mcdi.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <cdefs.h>
+
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+#include <mt_mcdi.h>
+
+/* Read/Write */
+#define APMCU_MCUPM_MBOX_AP_READY	U(0)
+#define APMCU_MCUPM_MBOX_RESERVED_1	U(1)
+#define APMCU_MCUPM_MBOX_RESERVED_2	U(2)
+#define APMCU_MCUPM_MBOX_RESERVED_3	U(3)
+#define APMCU_MCUPM_MBOX_PWR_CTRL_EN	U(4)
+#define APMCU_MCUPM_MBOX_L3_CACHE_MODE	U(5)
+#define APMCU_MCUPM_MBOX_BUCK_MODE	U(6)
+#define APMCU_MCUPM_MBOX_ARMPLL_MODE	U(7)
+/* Read only */
+#define APMCU_MCUPM_MBOX_TASK_STA	U(8)
+#define APMCU_MCUPM_MBOX_RESERVED_9	U(9)
+#define APMCU_MCUPM_MBOX_RESERVED_10	U(10)
+#define APMCU_MCUPM_MBOX_RESERVED_11	U(11)
+
+/* CPC mode - Read/Write */
+#define APMCU_MCUPM_MBOX_WAKEUP_CPU	U(12)
+
+/* Mbox Slot: APMCU_MCUPM_MBOX_PWR_CTRL_EN */
+#define MCUPM_MCUSYS_CTRL		BIT(0)
+#define MCUPM_BUCK_CTRL			BIT(1)
+#define MCUPM_ARMPLL_CTRL		BIT(2)
+#define MCUPM_CM_CTRL			BIT(3)
+#define MCUPM_PWR_CTRL_MASK		GENMASK(3, 0)
+
+/* Mbox Slot: APMCU_MCUPM_MBOX_BUCK_MODE */
+#define MCUPM_BUCK_NORMAL_MODE		U(0) /* default */
+#define MCUPM_BUCK_LP_MODE		U(1)
+#define MCUPM_BUCK_OFF_MODE		U(2)
+#define NF_MCUPM_BUCK_MODE		U(3)
+
+/* Mbox Slot: APMCU_MCUPM_MBOX_ARMPLL_MODE */
+#define MCUPM_ARMPLL_ON			U(0) /* default */
+#define MCUPM_ARMPLL_GATING		U(1)
+#define MCUPM_ARMPLL_OFF		U(2)
+#define NF_MCUPM_ARMPLL_MODE		U(3)
+
+/* Mbox Slot: APMCU_MCUPM_MBOX_TASK_STA */
+#define MCUPM_TASK_UNINIT		U(0)
+#define MCUPM_TASK_INIT			U(1)
+#define MCUPM_TASK_INIT_FINISH		U(2)
+#define MCUPM_TASK_WAIT			U(3)
+#define MCUPM_TASK_RUN			U(4)
+#define MCUPM_TASK_PAUSE		U(5)
+
+#define SSPM_MBOX_3_BASE		U(0x0c55fce0)
+
+#define MCDI_NOT_INIT			0
+#define MCDI_INIT_1			1
+#define MCDI_INIT_2			2
+#define MCDI_INIT_DONE			3
+
+static int mcdi_init_status __section("tzfw_coherent_mem");
+
+static inline uint32_t mcdi_mbox_read(uint32_t id)
+{
+	return mmio_read_32(SSPM_MBOX_3_BASE + (id << 2));
+}
+
+static inline void mcdi_mbox_write(uint32_t id, uint32_t val)
+{
+	mmio_write_32(SSPM_MBOX_3_BASE + (id << 2), val);
+}
+
+static void mtk_mcupm_pwr_ctrl_setting(uint32_t dev)
+{
+	mcdi_mbox_write(APMCU_MCUPM_MBOX_PWR_CTRL_EN, dev);
+}
+
+static void mtk_set_mcupm_pll_mode(uint32_t mode)
+{
+	if (mode < NF_MCUPM_ARMPLL_MODE) {
+		mcdi_mbox_write(APMCU_MCUPM_MBOX_ARMPLL_MODE, mode);
+	}
+}
+
+static void mtk_set_mcupm_buck_mode(uint32_t mode)
+{
+	if (mode < NF_MCUPM_BUCK_MODE) {
+		mcdi_mbox_write(APMCU_MCUPM_MBOX_BUCK_MODE, mode);
+	}
+}
+
+static int mtk_mcupm_is_ready(void)
+{
+	unsigned int sta = mcdi_mbox_read(APMCU_MCUPM_MBOX_TASK_STA);
+
+	return (sta == MCUPM_TASK_WAIT) || (sta == MCUPM_TASK_INIT_FINISH);
+}
+
+static int mcdi_init_1(void)
+{
+	unsigned int sta = mcdi_mbox_read(APMCU_MCUPM_MBOX_TASK_STA);
+
+	if (sta != MCUPM_TASK_INIT) {
+		return -1;
+	}
+
+	mtk_set_mcupm_pll_mode(MCUPM_ARMPLL_OFF);
+	mtk_set_mcupm_buck_mode(MCUPM_BUCK_OFF_MODE);
+
+	mtk_mcupm_pwr_ctrl_setting(
+			 MCUPM_MCUSYS_CTRL |
+			 MCUPM_BUCK_CTRL |
+			 MCUPM_ARMPLL_CTRL);
+
+	mcdi_mbox_write(APMCU_MCUPM_MBOX_AP_READY, 1);
+
+	return 0;
+}
+
+static int mcdi_init_2(void)
+{
+	return mtk_mcupm_is_ready() ? 0 : -1;
+}
+
+int mcdi_try_init(void)
+{
+	if (mcdi_init_status == MCDI_INIT_DONE) {
+		return 0;
+	}
+
+	if (mcdi_init_status == MCDI_NOT_INIT) {
+		mcdi_init_status = MCDI_INIT_1;
+	}
+
+	if (mcdi_init_status == MCDI_INIT_1 && mcdi_init_1() == 0) {
+		mcdi_init_status = MCDI_INIT_2;
+	}
+
+	if (mcdi_init_status == MCDI_INIT_2 && mcdi_init_2() == 0) {
+		mcdi_init_status = MCDI_INIT_DONE;
+	}
+
+	return (mcdi_init_status == MCDI_INIT_DONE) ? 0 : mcdi_init_status;
+}
diff --git a/plat/mediatek/mt8195/drivers/mcdi/mt_mcdi.h b/plat/mediatek/mt8195/drivers/mcdi/mt_mcdi.h
new file mode 100644
index 0000000..f3545aa
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/mcdi/mt_mcdi.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_MCDI_H
+#define MT_MCDI_H
+
+int mcdi_try_init(void);
+
+#endif /* MT_MCDI_H */
diff --git a/plat/mediatek/mt8195/drivers/pmic/pmic.c b/plat/mediatek/mt8195/drivers/pmic/pmic.c
new file mode 100644
index 0000000..cca4413
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/pmic/pmic.c
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <pmic.h>
+#include <pmic_wrap_init.h>
+
+void pmic_power_off(void)
+{
+	pwrap_write(PMIC_PWRHOLD, 0x0);
+}
diff --git a/plat/mediatek/mt8195/drivers/pmic/pmic.h b/plat/mediatek/mt8195/drivers/pmic/pmic.h
new file mode 100644
index 0000000..aac22af
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/pmic/pmic.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PMIC_H
+#define PMIC_H
+
+#define PMIC_PWRHOLD 0xa08
+
+/* external API */
+void pmic_power_off(void);
+
+#endif /* PMIC_H */
diff --git a/plat/mediatek/mt8195/drivers/pmic/pmic_wrap_init.h b/plat/mediatek/mt8195/drivers/pmic/pmic_wrap_init.h
new file mode 100644
index 0000000..39e78f5
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/pmic/pmic_wrap_init.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PMIC_WRAP_INIT_H
+#define PMIC_WRAP_INIT_H
+
+#include <stdint.h>
+
+#include "platform_def.h"
+
+/* external API */
+int32_t pwrap_read(uint32_t adr, uint32_t *rdata);
+int32_t pwrap_write(uint32_t adr, uint32_t wdata);
+
+static struct mt8195_pmic_wrap_regs *const mtk_pwrap = (void *)PMIC_WRAP_BASE;
+
+/* PMIC_WRAP registers */
+struct mt8195_pmic_wrap_regs {
+	uint32_t init_done;
+	uint32_t reserved[543];
+	uint32_t wacs2_cmd;
+	uint32_t wacs2_wdata;
+	uint32_t reserved1[3];
+	uint32_t wacs2_rdata;
+	uint32_t reserved2[3];
+	uint32_t wacs2_vldclr;
+	uint32_t wacs2_sta;
+};
+
+#define GET_WACS_FSM(x)	((x >> 1) & 0x7)
+
+/* macro for SWINF_FSM */
+#define SWINF_FSM_IDLE		(0x00)
+#define SWINF_FSM_REQ		(0x02)
+#define SWINF_FSM_WFDLE		(0x04)
+#define SWINF_FSM_WFVLDCLR	(0x06)
+#define SWINF_INIT_DONE		(0x01)
+
+/* timeout setting */
+#define PWRAP_READ_US	1000
+#define PWRAP_WAIT_IDLE_US	1000
+
+/* error information flag */
+enum pwrap_errno {
+	E_PWR_INVALID_ARG             = 1,
+	E_PWR_INVALID_RW              = 2,
+	E_PWR_INVALID_ADDR            = 3,
+	E_PWR_INVALID_WDAT            = 4,
+	E_PWR_INVALID_OP_MANUAL       = 5,
+	E_PWR_NOT_IDLE_STATE          = 6,
+	E_PWR_NOT_INIT_DONE           = 7,
+	E_PWR_NOT_INIT_DONE_READ      = 8,
+	E_PWR_WAIT_IDLE_TIMEOUT       = 9,
+	E_PWR_WAIT_IDLE_TIMEOUT_READ  = 10,
+	E_PWR_INIT_SIDLY_FAIL         = 11,
+	E_PWR_RESET_TIMEOUT           = 12,
+	E_PWR_TIMEOUT                 = 13,
+	E_PWR_INIT_RESET_SPI          = 20,
+	E_PWR_INIT_SIDLY              = 21,
+	E_PWR_INIT_REG_CLOCK          = 22,
+	E_PWR_INIT_ENABLE_PMIC        = 23,
+	E_PWR_INIT_DIO                = 24,
+	E_PWR_INIT_CIPHER             = 25,
+	E_PWR_INIT_WRITE_TEST         = 26,
+	E_PWR_INIT_ENABLE_CRC         = 27,
+	E_PWR_INIT_ENABLE_DEWRAP      = 28,
+	E_PWR_INIT_ENABLE_EVENT       = 29,
+	E_PWR_READ_TEST_FAIL          = 30,
+	E_PWR_WRITE_TEST_FAIL         = 31,
+	E_PWR_SWITCH_DIO              = 32
+};
+
+#endif /* PMIC_WRAP_INIT_H */
diff --git a/plat/mediatek/mt8195/drivers/spmc/mtspmc.c b/plat/mediatek/mt8195/drivers/spmc/mtspmc.c
new file mode 100644
index 0000000..9b332a0
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/spmc/mtspmc.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <mcucfg.h>
+#include <mtspmc.h>
+#include <mtspmc_private.h>
+
+
+void mcucfg_disable_gic_wakeup(unsigned int cluster, unsigned int cpu)
+{
+	mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(cpu));
+}
+
+void mcucfg_enable_gic_wakeup(unsigned int cluster, unsigned int cpu)
+{
+	mmio_clrbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(cpu));
+}
+
+void mcucfg_set_bootaddr(unsigned int cluster, unsigned int cpu, uintptr_t bootaddr)
+{
+	assert(cluster == 0U);
+
+	mmio_write_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR), bootaddr);
+}
+
+uintptr_t mcucfg_get_bootaddr(unsigned int cluster, unsigned int cpu)
+{
+	assert(cluster == 0U);
+
+	return (uintptr_t)mmio_read_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR));
+}
+
+void mcucfg_init_archstate(unsigned int cluster, unsigned int cpu, bool arm64)
+{
+	uint32_t reg;
+
+	assert(cluster == 0U);
+
+	reg = per_cluster(cluster, MCUCFG_INITARCH);
+
+	if (arm64) {
+		mmio_setbits_32(reg, MCUCFG_INITARCH_CPU_BIT(cpu));
+	} else {
+		mmio_clrbits_32(reg, MCUCFG_INITARCH_CPU_BIT(cpu));
+	}
+}
+
+/**
+ * Return subsystem's power state.
+ *
+ * @mask: mask to MCUCFG_CPC_SPMC_PWR_STATUS to query the power state
+ *        of one subsystem.
+ * RETURNS:
+ * 0 (the subsys was powered off)
+ * 1 (the subsys was powered on)
+ */
+bool spm_get_powerstate(uint32_t mask)
+{
+	return (mmio_read_32(MCUCFG_CPC_SPMC_PWR_STATUS) & mask) != 0U;
+}
+
+bool spm_get_cluster_powerstate(unsigned int cluster)
+{
+	assert(cluster == 0U);
+
+	return spm_get_powerstate(BIT(14));
+}
+
+bool spm_get_cpu_powerstate(unsigned int cluster, unsigned int cpu)
+{
+	uint32_t mask = BIT(cpu);
+
+	assert(cluster == 0U);
+
+	return spm_get_powerstate(mask);
+}
+
+int spmc_init(void)
+{
+	INFO("SPM: enable CPC mode\n");
+
+	mmio_write_32(SPM_POWERON_CONFIG_EN, PROJECT_CODE | BCLK_CG_EN);
+
+	mmio_setbits_32(per_cpu(0, 1, SPM_CPU_PWR), PWR_RST_B);
+	mmio_setbits_32(per_cpu(0, 2, SPM_CPU_PWR), PWR_RST_B);
+	mmio_setbits_32(per_cpu(0, 3, SPM_CPU_PWR), PWR_RST_B);
+	mmio_setbits_32(per_cpu(0, 4, SPM_CPU_PWR), PWR_RST_B);
+	mmio_setbits_32(per_cpu(0, 5, SPM_CPU_PWR), PWR_RST_B);
+	mmio_setbits_32(per_cpu(0, 6, SPM_CPU_PWR), PWR_RST_B);
+	mmio_setbits_32(per_cpu(0, 7, SPM_CPU_PWR), PWR_RST_B);
+
+	mmio_clrbits_32(SPM_MCUSYS_PWR_CON, RESETPWRON_CONFIG);
+	mmio_clrbits_32(SPM_MP0_CPUTOP_PWR_CON, RESETPWRON_CONFIG);
+	mmio_clrbits_32(per_cpu(0, 0, SPM_CPU_PWR), RESETPWRON_CONFIG);
+
+	mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, CPC_CTRL_ENABLE);
+	mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, SSPM_CORE_PWR_ON_EN);
+
+	return 0;
+}
+
+/**
+ * Power on a core with specified cluster and core index
+ *
+ * @cluster: the cluster ID of the CPU which to be powered on
+ * @cpu: the CPU ID of the CPU which to be powered on
+ */
+void spm_poweron_cpu(unsigned int cluster, unsigned int cpu)
+{
+	uintptr_t cpu_pwr_con = per_cpu(cluster, cpu, SPM_CPU_PWR);
+
+	/* set to 0 after BIG VPROC bulk on & before B-core power on seq. */
+	if (cpu >= 4U) {
+		mmio_write_32(DREQ20_BIG_VPROC_ISO, 0U);
+	}
+
+	mmio_setbits_32(cpu_pwr_con, PWR_ON);
+
+	while (!spm_get_cpu_powerstate(cluster, cpu)) {
+		mmio_clrbits_32(cpu_pwr_con, PWR_ON);
+		mmio_setbits_32(cpu_pwr_con, PWR_ON);
+	}
+}
+
+/**
+ * Power off a core with specified cluster and core index
+ *
+ * @cluster: the cluster ID of the CPU which to be powered off
+ * @cpu: the CPU ID of the CPU which to be powered off
+ */
+void spm_poweroff_cpu(unsigned int cluster, unsigned int cpu)
+{
+	/* Set mp0_spmc_pwr_on_cpuX = 0 */
+	mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWR_ON);
+}
+
+/**
+ * Power off a cluster with specified index
+ *
+ * @cluster: the cluster index which to be powered off
+ */
+void spm_poweroff_cluster(unsigned int cluster)
+{
+	/* No need to power on/off cluster on single cluster platform */
+	assert(false);
+}
+
+/**
+ * Power on a cluster with specified index
+ *
+ * @cluster: the cluster index which to be powered on
+ */
+void spm_poweron_cluster(unsigned int cluster)
+{
+	/* No need to power on/off cluster on single cluster platform */
+	assert(false);
+}
diff --git a/plat/mediatek/mt8195/drivers/spmc/mtspmc.h b/plat/mediatek/mt8195/drivers/spmc/mtspmc.h
new file mode 100644
index 0000000..34e93d0
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/spmc/mtspmc.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTSPMC_H
+#define MTSPMC_H
+
+#include <stdint.h>
+
+int spmc_init(void);
+
+void spm_poweron_cpu(unsigned int cluster, unsigned int cpu);
+void spm_poweroff_cpu(unsigned int cluster, unsigned int cpu);
+
+void spm_poweroff_cluster(unsigned int cluster);
+void spm_poweron_cluster(unsigned int cluster);
+
+bool spm_get_cpu_powerstate(unsigned int cluster, unsigned int cpu);
+bool spm_get_cluster_powerstate(unsigned int cluster);
+bool spm_get_powerstate(uint32_t mask);
+
+void mcucfg_init_archstate(unsigned int cluster, unsigned int cpu, bool arm64);
+void mcucfg_set_bootaddr(unsigned int cluster, unsigned int cpu, uintptr_t bootaddr);
+uintptr_t mcucfg_get_bootaddr(unsigned int cluster, unsigned int cpu);
+
+void mcucfg_disable_gic_wakeup(unsigned int cluster, unsigned int cpu);
+void mcucfg_enable_gic_wakeup(unsigned int cluster, unsigned int cpu);
+
+#endif /* MTSPMC_H */
diff --git a/plat/mediatek/mt8195/drivers/spmc/mtspmc_private.h b/plat/mediatek/mt8195/drivers/spmc/mtspmc_private.h
new file mode 100644
index 0000000..bf4092e
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/spmc/mtspmc_private.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTSPMC_PRIVATE_H
+#define MTSPMC_PRIVATE_H
+
+#include <lib/utils_def.h>
+#include <platform_def.h>
+
+unsigned long read_cpuectlr(void);
+void write_cpuectlr(unsigned long cpuectlr);
+
+unsigned long read_cpupwrctlr_el1(void);
+void write_cpupwrctlr_el1(unsigned long cpuectlr);
+
+/*
+ * per_cpu/cluster helper
+ */
+struct per_cpu_reg {
+	unsigned int cluster_addr;
+	unsigned int cpu_stride;
+};
+
+#define per_cpu(cluster, cpu, reg)	\
+	(reg[cluster].cluster_addr + (cpu << reg[cluster].cpu_stride))
+
+#define per_cluster(cluster, reg)	(reg[cluster].cluster_addr)
+
+#define SPM_REG(ofs)			(uint32_t)(SPM_BASE + (ofs))
+#define MCUCFG_REG(ofs)			(uint32_t)(MCUCFG_BASE + (ofs))
+#define INFRACFG_AO_REG(ofs)		(uint32_t)(INFRACFG_AO_BASE + (ofs))
+
+/* === SPMC related registers */
+#define SPM_POWERON_CONFIG_EN		SPM_REG(0x000)
+/* bit-fields of SPM_POWERON_CONFIG_EN */
+#define PROJECT_CODE			(U(0xb16) << 16)
+#define BCLK_CG_EN			BIT(0)
+
+#define SPM_PWR_STATUS			SPM_REG(0x16c)
+#define SPM_PWR_STATUS_2ND		SPM_REG(0x170)
+#define SPM_CPU_PWR_STATUS		SPM_REG(0x174)
+
+/* bit-fields of SPM_PWR_STATUS */
+#define MD				BIT(0)
+#define CONN				BIT(1)
+#define DDRPHY				BIT(2)
+#define DISP				BIT(3)
+#define MFG				BIT(4)
+#define ISP				BIT(5)
+#define INFRA				BIT(6)
+#define VDEC				BIT(7)
+#define MP0_CPUTOP			BIT(8)
+#define MP0_CPU0			BIT(9)
+#define MP0_CPU1			BIT(10)
+#define MP0_CPU2			BIT(11)
+#define MP0_CPU3			BIT(12)
+#define MCUSYS				BIT(14)
+#define MP0_CPU4			BIT(15)
+#define MP0_CPU5			BIT(16)
+#define MP0_CPU6			BIT(17)
+#define MP0_CPU7			BIT(18)
+#define VEN				BIT(21)
+
+/* === SPMC related registers */
+#define SPM_MCUSYS_PWR_CON		MCUCFG_REG(0xd200)
+#define SPM_MP0_CPUTOP_PWR_CON		MCUCFG_REG(0xd204)
+#define SPM_MP0_CPU0_PWR_CON		MCUCFG_REG(0xd208)
+#define SPM_MP0_CPU1_PWR_CON		MCUCFG_REG(0xd20c)
+#define SPM_MP0_CPU2_PWR_CON		MCUCFG_REG(0xd210)
+#define SPM_MP0_CPU3_PWR_CON		MCUCFG_REG(0xd214)
+#define SPM_MP0_CPU4_PWR_CON		MCUCFG_REG(0xd218)
+#define SPM_MP0_CPU5_PWR_CON		MCUCFG_REG(0xd21c)
+#define SPM_MP0_CPU6_PWR_CON		MCUCFG_REG(0xd220)
+#define SPM_MP0_CPU7_PWR_CON		MCUCFG_REG(0xd224)
+
+/* bit fields of SPM_*_PWR_CON */
+#define PWR_ON_ACK			BIT(31)
+#define VPROC_EXT_OFF			BIT(7)
+#define DORMANT_EN			BIT(6)
+#define RESETPWRON_CONFIG		BIT(5)
+#define PWR_CLK_DIS			BIT(4)
+#define PWR_ON				BIT(2)
+#define PWR_RST_B			BIT(0)
+
+/**** per_cpu registers for SPM_MP0_CPU?_PWR_CON */
+static const struct per_cpu_reg SPM_CPU_PWR[] = {
+	{ .cluster_addr = SPM_MP0_CPU0_PWR_CON, .cpu_stride = 2U }
+};
+
+/**** per_cluster registers for SPM_MP0_CPUTOP_PWR_CON */
+static const struct per_cpu_reg SPM_CLUSTER_PWR[] = {
+	{ .cluster_addr = SPM_MP0_CPUTOP_PWR_CON, .cpu_stride = 0U }
+};
+
+/* === MCUCFG related registers */
+/* aa64naa32 */
+#define MCUCFG_MP0_CLUSTER_CFG5		MCUCFG_REG(0xc8e4)
+/* reset vectors */
+#define MCUCFG_MP0_CLUSTER_CFG8		MCUCFG_REG(0xc900)
+#define MCUCFG_MP0_CLUSTER_CFG10	MCUCFG_REG(0xc908)
+#define MCUCFG_MP0_CLUSTER_CFG12	MCUCFG_REG(0xc910)
+#define MCUCFG_MP0_CLUSTER_CFG14	MCUCFG_REG(0xc918)
+#define MCUCFG_MP0_CLUSTER_CFG16	MCUCFG_REG(0xc920)
+#define MCUCFG_MP0_CLUSTER_CFG18	MCUCFG_REG(0xc928)
+#define MCUCFG_MP0_CLUSTER_CFG20	MCUCFG_REG(0xc930)
+#define MCUCFG_MP0_CLUSTER_CFG22	MCUCFG_REG(0xc938)
+
+/* MCUSYS DREQ BIG VPROC ISO control */
+#define DREQ20_BIG_VPROC_ISO		MCUCFG_REG(0xad8c)
+
+/**** per_cpu registers for MCUCFG_MP0_CLUSTER_CFG? */
+static const struct per_cpu_reg MCUCFG_BOOTADDR[] = {
+	{ .cluster_addr = MCUCFG_MP0_CLUSTER_CFG8, .cpu_stride = 3U }
+};
+
+/**** per_cpu registers for MCUCFG_MP0_CLUSTER_CFG5 */
+static const struct per_cpu_reg MCUCFG_INITARCH[] = {
+	{ .cluster_addr = MCUCFG_MP0_CLUSTER_CFG5, .cpu_stride = 0U }
+};
+
+#define MCUCFG_INITARCH_CPU_BIT(cpu)	BIT(16U + cpu)
+/* === CPC control */
+#define MCUCFG_CPC_FLOW_CTRL_CFG	MCUCFG_REG(0xa814)
+#define MCUCFG_CPC_SPMC_PWR_STATUS	MCUCFG_REG(0xa840)
+
+/* bit fields of CPC_FLOW_CTRL_CFG */
+#define CPC_CTRL_ENABLE			BIT(16)
+#define SSPM_CORE_PWR_ON_EN		BIT(7) /* for cpu-hotplug */
+#define SSPM_ALL_PWR_CTRL_EN		BIT(13) /* for cpu-hotplug */
+#define GIC_WAKEUP_IGNORE(cpu)		BIT(21 + cpu)
+
+/* bit fields of CPC_SPMC_PWR_STATUS */
+#define CORE_SPMC_PWR_ON_ACK		GENMASK(11, 0)
+
+/* === APB Module infracfg_ao */
+#define INFRA_TOPAXI_PROTECTEN		INFRACFG_AO_REG(0x0220)
+#define INFRA_TOPAXI_PROTECTEN_STA0	INFRACFG_AO_REG(0x0224)
+#define INFRA_TOPAXI_PROTECTEN_STA1	INFRACFG_AO_REG(0x0228)
+#define INFRA_TOPAXI_PROTECTEN_SET	INFRACFG_AO_REG(0x02a0)
+#define INFRA_TOPAXI_PROTECTEN_CLR	INFRACFG_AO_REG(0x02a4)
+#define INFRA_TOPAXI_PROTECTEN_1	INFRACFG_AO_REG(0x0250)
+#define INFRA_TOPAXI_PROTECTEN_STA0_1	INFRACFG_AO_REG(0x0254)
+#define INFRA_TOPAXI_PROTECTEN_STA1_1	INFRACFG_AO_REG(0x0258)
+#define INFRA_TOPAXI_PROTECTEN_1_SET	INFRACFG_AO_REG(0x02a8)
+#define INFRA_TOPAXI_PROTECTEN_1_CLR	INFRACFG_AO_REG(0x02ac)
+
+/* bit fields of INFRA_TOPAXI_PROTECTEN */
+#define MP0_SPMC_PROT_STEP1_0_MASK	BIT(12)
+#define MP0_SPMC_PROT_STEP1_1_MASK	(BIT(26) | BIT(12))
+
+/* === SPARK */
+#define VOLTAGE_04			U(0x40)
+#define VOLTAGE_05			U(0x60)
+
+#define PTP3_CPU0_SPMC_SW_CFG		MCUCFG_REG(0x200)
+#define CPU0_ILDO_CONTROL5		MCUCFG_REG(0x334)
+#define CPU0_ILDO_CONTROL8		MCUCFG_REG(0x340)
+
+/* bit fields of CPU0_ILDO_CONTROL5 */
+#define ILDO_RET_VOSEL			GENMASK(7, 0)
+
+/* bit fields of PTP3_CPU_SPMC_SW_CFG */
+#define SW_SPARK_EN			BIT(0)
+
+/* bit fields of CPU0_ILDO_CONTROL8 */
+#define ILDO_BYPASS_B			BIT(0)
+
+static const struct per_cpu_reg MCUCFG_SPARK[] = {
+	{ .cluster_addr = PTP3_CPU0_SPMC_SW_CFG, .cpu_stride = 11U }
+};
+
+static const struct per_cpu_reg ILDO_CONTROL5[] = {
+	{ .cluster_addr = CPU0_ILDO_CONTROL5, .cpu_stride = 11U }
+};
+
+static const struct per_cpu_reg ILDO_CONTROL8[] = {
+	{ .cluster_addr = CPU0_ILDO_CONTROL8, .cpu_stride = 11U }
+};
+
+#endif /* MTSPMC_PRIVATE_H */
diff --git a/plat/mediatek/mt8195/include/mcucfg.h b/plat/mediatek/mt8195/include/mcucfg.h
new file mode 100644
index 0000000..046cf73
--- /dev/null
+++ b/plat/mediatek/mt8195/include/mcucfg.h
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MCUCFG_H
+#define MCUCFG_H
+
+#ifndef __ASSEMBLER__
+#include <stdint.h>
+#endif /* __ASSEMBLER__ */
+
+#include <platform_def.h>
+
+#define MCUCFG_REG(ofs)			(uint32_t)(MCUCFG_BASE + (ofs))
+
+#define MP2_MISC_CONFIG_BOOT_ADDR_L(cpu) (MCUCFG_REG(0x2290) + ((cpu) * 8))
+#define MP2_MISC_CONFIG_BOOT_ADDR_H(cpu) (MCUCFG_REG(0x2294) + ((cpu) * 8))
+
+#define MP2_CPUCFG			MCUCFG_REG(0x2208)
+
+#define MP2_CPU0_STANDBYWFE		BIT(4)
+#define MP2_CPU1_STANDBYWFE		BIT(5)
+
+#define MP0_CPUTOP_SPMC_CTL		MCUCFG_REG(0x788)
+#define MP1_CPUTOP_SPMC_CTL		MCUCFG_REG(0x78C)
+#define MP1_CPUTOP_SPMC_SRAM_CTL	MCUCFG_REG(0x790)
+
+#define sw_spark_en			BIT(0)
+#define sw_no_wait_for_q_channel	BIT(1)
+#define sw_fsm_override			BIT(2)
+#define sw_logic_pre1_pdb		BIT(3)
+#define sw_logic_pre2_pdb		BIT(4)
+#define sw_logic_pdb			BIT(5)
+#define sw_iso				BIT(6)
+#define sw_sram_sleepb			(U(0x3F) << 7)
+#define sw_sram_isointb			BIT(13)
+#define sw_clk_dis			BIT(14)
+#define sw_ckiso			BIT(15)
+#define sw_pd				(U(0x3F) << 16)
+#define sw_hot_plug_reset		BIT(22)
+#define sw_pwr_on_override_en		BIT(23)
+#define sw_pwr_on			BIT(24)
+#define sw_coq_dis			BIT(25)
+#define logic_pdbo_all_off_ack		BIT(26)
+#define logic_pdbo_all_on_ack		BIT(27)
+#define logic_pre2_pdbo_all_on_ack	BIT(28)
+#define logic_pre1_pdbo_all_on_ack	BIT(29)
+
+
+#define CPUSYSx_CPUx_SPMC_CTL(cluster, cpu) \
+	(MCUCFG_REG(0x1c30) + cluster * 0x2000 + cpu * 4)
+
+#define CPUSYS0_CPU0_SPMC_CTL		MCUCFG_REG(0x1c30)
+#define CPUSYS0_CPU1_SPMC_CTL		MCUCFG_REG(0x1c34)
+#define CPUSYS0_CPU2_SPMC_CTL		MCUCFG_REG(0x1c38)
+#define CPUSYS0_CPU3_SPMC_CTL		MCUCFG_REG(0x1c3C)
+
+#define CPUSYS1_CPU0_SPMC_CTL		MCUCFG_REG(0x3c30)
+#define CPUSYS1_CPU1_SPMC_CTL		MCUCFG_REG(0x3c34)
+#define CPUSYS1_CPU2_SPMC_CTL		MCUCFG_REG(0x3c38)
+#define CPUSYS1_CPU3_SPMC_CTL		MCUCFG_REG(0x3c3C)
+
+#define cpu_sw_spark_en			BIT(0)
+#define cpu_sw_no_wait_for_q_channel	BIT(1)
+#define cpu_sw_fsm_override		BIT(2)
+#define cpu_sw_logic_pre1_pdb		BIT(3)
+#define cpu_sw_logic_pre2_pdb		BIT(4)
+#define cpu_sw_logic_pdb		BIT(5)
+#define cpu_sw_iso			BIT(6)
+#define cpu_sw_sram_sleepb		BIT(7)
+#define cpu_sw_sram_isointb		BIT(8)
+#define cpu_sw_clk_dis			BIT(9)
+#define cpu_sw_ckiso			BIT(10)
+#define cpu_sw_pd			(U(0x1F) << 11)
+#define cpu_sw_hot_plug_reset		BIT(16)
+#define cpu_sw_powr_on_override_en	BIT(17)
+#define cpu_sw_pwr_on			BIT(18)
+#define cpu_spark2ldo_allswoff		BIT(19)
+#define cpu_pdbo_all_on_ack		BIT(20)
+#define cpu_pre2_pdbo_allon_ack		BIT(21)
+#define cpu_pre1_pdbo_allon_ack		BIT(22)
+
+/* CPC related registers */
+#define CPC_MCUSYS_CPC_OFF_THRES	MCUCFG_REG(0xa714)
+#define CPC_MCUSYS_PWR_CTRL		MCUCFG_REG(0xa804)
+#define CPC_MCUSYS_CPC_FLOW_CTRL_CFG	MCUCFG_REG(0xa814)
+#define CPC_MCUSYS_LAST_CORE_REQ	MCUCFG_REG(0xa818)
+#define CPC_MCUSYS_MP_LAST_CORE_RESP	MCUCFG_REG(0xa81c)
+#define CPC_MCUSYS_LAST_CORE_RESP	MCUCFG_REG(0xa824)
+#define CPC_MCUSYS_PWR_ON_MASK		MCUCFG_REG(0xa828)
+#define CPC_MCUSYS_CPU_ON_SW_HINT_SET	MCUCFG_REG(0xa8a8)
+#define CPC_MCUSYS_CPU_ON_SW_HINT_CLR	MCUCFG_REG(0xa8ac)
+#define CPC_MCUSYS_CPC_DBG_SETTING	MCUCFG_REG(0xab00)
+#define CPC_MCUSYS_CPC_KERNEL_TIME_L_BASE	MCUCFG_REG(0xab04)
+#define CPC_MCUSYS_CPC_KERNEL_TIME_H_BASE	MCUCFG_REG(0xab08)
+#define CPC_MCUSYS_CPC_SYSTEM_TIME_L_BASE	MCUCFG_REG(0xab0c)
+#define CPC_MCUSYS_CPC_SYSTEM_TIME_H_BASE	MCUCFG_REG(0xab10)
+#define CPC_MCUSYS_TRACE_SEL		MCUCFG_REG(0xab14)
+#define CPC_MCUSYS_TRACE_DATA		MCUCFG_REG(0xab20)
+#define CPC_MCUSYS_CLUSTER_COUNTER	MCUCFG_REG(0xab70)
+#define CPC_MCUSYS_CLUSTER_COUNTER_CLR	MCUCFG_REG(0xab74)
+
+#define SPARK2LDO			MCUCFG_REG(0x2700)
+/* APB Module mcucfg */
+#define MP0_CA7_CACHE_CONFIG		MCUCFG_REG(0x000)
+#define MP0_AXI_CONFIG			MCUCFG_REG(0x02C)
+#define MP0_MISC_CONFIG0		MCUCFG_REG(0x030)
+#define MP0_MISC_CONFIG1		MCUCFG_REG(0x034)
+#define MP0_MISC_CONFIG2		MCUCFG_REG(0x038)
+#define MP0_MISC_CONFIG_BOOT_ADDR(cpu)	(MP0_MISC_CONFIG2 + ((cpu) * 8))
+#define MP0_MISC_CONFIG3		MCUCFG_REG(0x03C)
+#define MP0_MISC_CONFIG9		MCUCFG_REG(0x054)
+#define MP0_CA7_MISC_CONFIG		MCUCFG_REG(0x064)
+
+#define MP0_RW_RSVD0			MCUCFG_REG(0x06C)
+
+
+#define MP1_CA7_CACHE_CONFIG		MCUCFG_REG(0x200)
+#define MP1_AXI_CONFIG			MCUCFG_REG(0x22C)
+#define MP1_MISC_CONFIG0		MCUCFG_REG(0x230)
+#define MP1_MISC_CONFIG1		MCUCFG_REG(0x234)
+#define MP1_MISC_CONFIG2		MCUCFG_REG(0x238)
+#define MP1_MISC_CONFIG_BOOT_ADDR(cpu)	(MP1_MISC_CONFIG2 + ((cpu) * 8))
+#define MP1_MISC_CONFIG3		MCUCFG_REG(0x23C)
+#define MP1_MISC_CONFIG9		MCUCFG_REG(0x254)
+#define MP1_CA7_MISC_CONFIG		MCUCFG_REG(0x264)
+
+#define CCI_ADB400_DCM_CONFIG		MCUCFG_REG(0x740)
+#define SYNC_DCM_CONFIG			MCUCFG_REG(0x744)
+
+#define MP0_CLUSTER_CFG0		MCUCFG_REG(0xC8D0)
+
+#define MP0_SPMC			MCUCFG_REG(0x788)
+#define MP1_SPMC			MCUCFG_REG(0x78C)
+#define MP2_AXI_CONFIG			MCUCFG_REG(0x220C)
+#define MP2_AXI_CONFIG_ACINACTM		BIT(0)
+#define MP2_AXI_CONFIG_AINACTS		BIT(4)
+
+#define MPx_AXI_CONFIG_ACINACTM		BIT(4)
+#define MPx_AXI_CONFIG_AINACTS		BIT(5)
+
+#define MPx_CA7_MISC_CONFIG_standbywfil2	BIT(28)
+
+#define MP0_CPU0_STANDBYWFE		BIT(20)
+#define MP0_CPU1_STANDBYWFE		BIT(21)
+#define MP0_CPU2_STANDBYWFE		BIT(22)
+#define MP0_CPU3_STANDBYWFE		BIT(23)
+
+#define MP1_CPU0_STANDBYWFE		BIT(20)
+#define MP1_CPU1_STANDBYWFE		BIT(21)
+#define MP1_CPU2_STANDBYWFE		BIT(22)
+#define MP1_CPU3_STANDBYWFE		BIT(23)
+
+#define CPUSYS0_SPARKVRETCNTRL		MCUCFG_REG(0x1c00)
+#define CPUSYS0_SPARKEN			MCUCFG_REG(0x1c04)
+#define CPUSYS0_AMUXSEL			MCUCFG_REG(0x1c08)
+#define CPUSYS1_SPARKVRETCNTRL		MCUCFG_REG(0x3c00)
+#define CPUSYS1_SPARKEN			MCUCFG_REG(0x3c04)
+#define CPUSYS1_AMUXSEL			MCUCFG_REG(0x3c08)
+
+#define MP2_PWR_RST_CTL			MCUCFG_REG(0x2008)
+#define MP2_PTP3_CPUTOP_SPMC0		MCUCFG_REG(0x22A0)
+#define MP2_PTP3_CPUTOP_SPMC1		MCUCFG_REG(0x22A4)
+
+#define MP2_COQ				MCUCFG_REG(0x22BC)
+#define MP2_COQ_SW_DIS			BIT(0)
+
+#define MP2_CA15M_MON_SEL		MCUCFG_REG(0x2400)
+#define MP2_CA15M_MON_L			MCUCFG_REG(0x2404)
+
+#define CPUSYS2_CPU0_SPMC_CTL		MCUCFG_REG(0x2430)
+#define CPUSYS2_CPU1_SPMC_CTL		MCUCFG_REG(0x2438)
+#define CPUSYS2_CPU0_SPMC_STA		MCUCFG_REG(0x2434)
+#define CPUSYS2_CPU1_SPMC_STA		MCUCFG_REG(0x243C)
+
+#define MP0_CA7L_DBG_PWR_CTRL		MCUCFG_REG(0x068)
+#define MP1_CA7L_DBG_PWR_CTRL		MCUCFG_REG(0x268)
+#define BIG_DBG_PWR_CTRL		MCUCFG_REG(0x75C)
+
+#define MP2_SW_RST_B			BIT(0)
+#define MP2_TOPAON_APB_MASK		BIT(1)
+
+#define B_SW_HOT_PLUG_RESET		BIT(30)
+
+#define B_SW_PD_OFFSET			18U
+#define B_SW_PD				(U(0x3f) << B_SW_PD_OFFSET)
+
+#define B_SW_SRAM_SLEEPB_OFFSET		12U
+#define B_SW_SRAM_SLEEPB		(U(0x3f) << B_SW_SRAM_SLEEPB_OFFSET)
+
+#define B_SW_SRAM_ISOINTB		BIT(9)
+#define B_SW_ISO			BIT(8)
+#define B_SW_LOGIC_PDB			BIT(7)
+#define B_SW_LOGIC_PRE2_PDB		BIT(6)
+#define B_SW_LOGIC_PRE1_PDB		BIT(5)
+#define B_SW_FSM_OVERRIDE		BIT(4)
+#define B_SW_PWR_ON			BIT(3)
+#define B_SW_PWR_ON_OVERRIDE_EN		BIT(2)
+
+#define B_FSM_STATE_OUT_OFFSET		(6U)
+#define B_FSM_STATE_OUT_MASK		(U(0x1f) << B_FSM_STATE_OUT_OFFSET)
+#define B_SW_LOGIC_PDBO_ALL_OFF_ACK	BIT(5)
+#define B_SW_LOGIC_PDBO_ALL_ON_ACK	BIT(4)
+#define B_SW_LOGIC_PRE2_PDBO_ALL_ON_ACK	BIT(3)
+#define B_SW_LOGIC_PRE1_PDBO_ALL_ON_ACK	BIT(2)
+
+#define B_FSM_OFF			(0U << B_FSM_STATE_OUT_OFFSET)
+#define B_FSM_ON			(1U << B_FSM_STATE_OUT_OFFSET)
+#define B_FSM_RET			(2U << B_FSM_STATE_OUT_OFFSET)
+
+#ifndef __ASSEMBLER__
+/* cpu boot mode */
+enum {
+	MP0_CPUCFG_64BIT_SHIFT = 12U,
+	MP1_CPUCFG_64BIT_SHIFT = 28U,
+	MP0_CPUCFG_64BIT = U(0xf) << MP0_CPUCFG_64BIT_SHIFT,
+	MP1_CPUCFG_64BIT = U(0xf) << MP1_CPUCFG_64BIT_SHIFT
+};
+
+enum {
+	MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT = 0U,
+	MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT = 4U,
+	MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT = 8U,
+	MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT = 12U,
+	MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT = 16U,
+
+	MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK =
+		U(0xf) << MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT,
+	MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK =
+		U(0xf) << MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT,
+	MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK =
+		U(0xf) << MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT,
+	MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK =
+		U(0xf) << MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT,
+	MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK =
+		U(0xf) << MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT
+};
+
+enum {
+	MP1_AINACTS_SHIFT = 4U,
+	MP1_AINACTS = 1U << MP1_AINACTS_SHIFT
+};
+
+enum {
+	MP1_SW_CG_GEN_SHIFT = 12U,
+	MP1_SW_CG_GEN = 1U << MP1_SW_CG_GEN_SHIFT
+};
+
+enum {
+	MP1_L2RSTDISABLE_SHIFT = 14U,
+	MP1_L2RSTDISABLE = 1U << MP1_L2RSTDISABLE_SHIFT
+};
+#endif /* __ASSEMBLER__ */
+
+#endif  /* MCUCFG_H */
diff --git a/plat/mediatek/mt8195/include/plat_helpers.h b/plat/mediatek/mt8195/include/plat_helpers.h
new file mode 100644
index 0000000..ebc9fa0
--- /dev/null
+++ b/plat/mediatek/mt8195/include/plat_helpers.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLAT_HELPERS_H__
+#define __PLAT_HELPERS_H__
+
+unsigned int plat_mediatek_calc_core_pos(u_register_t mpidr);
+
+#endif /* __PLAT_HELPERS_H__ */
diff --git a/plat/mediatek/mt8195/include/plat_macros.S b/plat/mediatek/mt8195/include/plat_macros.S
new file mode 100644
index 0000000..39727ea
--- /dev/null
+++ b/plat/mediatek/mt8195/include/plat_macros.S
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+#include <platform_def.h>
+
+.section .rodata.gic_reg_name, "aS"
+gicc_regs:
+	.asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", ""
+gicd_pend_reg:
+	.asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n"	\
+		" Offset:\t\t\tvalue\n"
+newline:
+	.asciz "\n"
+spacer:
+	.asciz ":\t\t0x"
+
+.section .rodata.cci_reg_name, "aS"
+cci_iface_regs:
+	.asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , ""
+
+	/* ---------------------------------------------
+	 * The below macro prints out relevant GIC
+	 * registers whenever an unhandled exception
+	 * is taken in BL31.
+	 * Clobbers: x0 - x10, x26, x27, sp
+	 * ---------------------------------------------
+	 */
+	.macro plat_crash_print_regs
+	/* TODO: leave implementation to GIC owner */
+	.endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/mediatek/mt8195/include/plat_mtk_lpm.h b/plat/mediatek/mt8195/include/plat_mtk_lpm.h
new file mode 100644
index 0000000..8ba8b93
--- /dev/null
+++ b/plat/mediatek/mt8195/include/plat_mtk_lpm.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_MTK_LPM_H
+#define PLAT_MTK_LPM_H
+
+#include <lib/psci/psci.h>
+#include <lib/utils_def.h>
+
+#define MT_IRQ_REMAIN_MAX	U(8)
+#define MT_IRQ_REMAIN_CAT_LOG	BIT(31)
+
+struct mt_irqremain {
+	unsigned int count;
+	unsigned int irqs[MT_IRQ_REMAIN_MAX];
+	unsigned int wakeupsrc_cat[MT_IRQ_REMAIN_MAX];
+	unsigned int wakeupsrc[MT_IRQ_REMAIN_MAX];
+};
+
+#define PLAT_RC_STATUS_READY		BIT(0)
+#define PLAT_RC_STATUS_FEATURE_EN	BIT(1)
+#define PLAT_RC_STATUS_UART_NONSLEEP	BIT(31)
+
+struct mt_lpm_tz {
+	int (*pwr_prompt)(unsigned int cpu, const psci_power_state_t *state);
+	int (*pwr_reflect)(unsigned int cpu, const psci_power_state_t *state);
+
+	int (*pwr_cpu_on)(unsigned int cpu, const psci_power_state_t *state);
+	int (*pwr_cpu_dwn)(unsigned int cpu, const psci_power_state_t *state);
+
+	int (*pwr_cluster_on)(unsigned int cpu,
+					const psci_power_state_t *state);
+	int (*pwr_cluster_dwn)(unsigned int cpu,
+					const psci_power_state_t *state);
+
+	int (*pwr_mcusys_on)(unsigned int cpu, const psci_power_state_t *state);
+	int (*pwr_mcusys_on_finished)(unsigned int cpu,
+					const psci_power_state_t *state);
+	int (*pwr_mcusys_dwn)(unsigned int cpu,
+					const psci_power_state_t *state);
+};
+
+const struct mt_lpm_tz *mt_plat_cpu_pm_init(void);
+
+#endif /* PLAT_MTK_LPM_H */
diff --git a/plat/mediatek/mt8195/include/plat_pm.h b/plat/mediatek/mt8195/include/plat_pm.h
new file mode 100644
index 0000000..a2881ce
--- /dev/null
+++ b/plat/mediatek/mt8195/include/plat_pm.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_PM_H
+#define PLAT_PM_H
+
+#include <lib/utils_def.h>
+
+#define MT_PLAT_PWR_STATE_CPU			U(1)
+#define MT_PLAT_PWR_STATE_CLUSTER		U(2)
+#define MT_PLAT_PWR_STATE_MCUSYS		U(3)
+#define MT_PLAT_PWR_STATE_SUSPEND2IDLE		U(8)
+#define MT_PLAT_PWR_STATE_SYSTEM_SUSPEND	U(9)
+
+#define MTK_LOCAL_STATE_RUN			U(0)
+#define MTK_LOCAL_STATE_RET			U(1)
+#define MTK_LOCAL_STATE_OFF			U(2)
+
+#define MTK_AFFLVL_CPU				U(0)
+#define MTK_AFFLVL_CLUSTER			U(1)
+#define MTK_AFFLVL_MCUSYS			U(2)
+#define MTK_AFFLVL_SYSTEM			U(3)
+
+#define IS_CLUSTER_OFF_STATE(s)		\
+		is_local_state_off(s->pwr_domain_state[MTK_AFFLVL_CLUSTER])
+#define IS_MCUSYS_OFF_STATE(s)		\
+		is_local_state_off(s->pwr_domain_state[MTK_AFFLVL_MCUSYS])
+#define IS_SYSTEM_SUSPEND_STATE(s)	\
+		is_local_state_off(s->pwr_domain_state[MTK_AFFLVL_SYSTEM])
+
+#define IS_PLAT_SUSPEND_ID(stateid)\
+		((stateid == MT_PLAT_PWR_STATE_SUSPEND2IDLE)	\
+		|| (stateid == MT_PLAT_PWR_STATE_SYSTEM_SUSPEND))
+
+#endif /* PLAT_PM_H */
diff --git a/plat/mediatek/mt8195/include/plat_private.h b/plat/mediatek/mt8195/include/plat_private.h
new file mode 100644
index 0000000..7ef2b85
--- /dev/null
+++ b/plat/mediatek/mt8195/include/plat_private.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_PRIVATE_H
+#define PLAT_PRIVATE_H
+
+/*******************************************************************************
+ * Function and variable prototypes
+ ******************************************************************************/
+void plat_configure_mmu_el3(uintptr_t total_base,
+			    uintptr_t total_size,
+			    uintptr_t ro_start,
+			    uintptr_t ro_limit);
+
+#endif /* PLAT_PRIVATE_H */
diff --git a/plat/mediatek/mt8195/include/plat_sip_calls.h b/plat/mediatek/mt8195/include/plat_sip_calls.h
new file mode 100644
index 0000000..0e42322
--- /dev/null
+++ b/plat/mediatek/mt8195/include/plat_sip_calls.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_SIP_CALLS_H
+#define PLAT_SIP_CALLS_H
+
+/*******************************************************************************
+ * Plat SiP function constants
+ ******************************************************************************/
+#define MTK_PLAT_SIP_NUM_CALLS    0
+
+#endif /* PLAT_SIP_CALLS_H */
diff --git a/plat/mediatek/mt8195/include/platform_def.h b/plat/mediatek/mt8195/include/platform_def.h
new file mode 100644
index 0000000..f6eb742
--- /dev/null
+++ b/plat/mediatek/mt8195/include/platform_def.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#define PLAT_PRIMARY_CPU	0x0
+
+#define MT_GIC_BASE		(0x0C000000)
+#define MCUCFG_BASE		(0x0C530000)
+#define IO_PHYS			(0x10000000)
+
+/* Aggregate of all devices for MMU mapping */
+#define MTK_DEV_RNG0_BASE	IO_PHYS
+#define MTK_DEV_RNG0_SIZE	0x400000
+#define MTK_DEV_RNG1_BASE	(IO_PHYS + 0x1000000)
+#define MTK_DEV_RNG1_SIZE	0xa110000
+#define MTK_DEV_RNG2_BASE	MT_GIC_BASE
+#define MTK_DEV_RNG2_SIZE	0x600000
+#define MTK_MCDI_SRAM_BASE	0x11B000
+#define MTK_MCDI_SRAM_MAP_SIZE	0x1000
+
+#define SPM_BASE		(IO_PHYS + 0x00006000)
+
+/*******************************************************************************
+ * GPIO related constants
+ ******************************************************************************/
+#define GPIO_BASE		(IO_PHYS + 0x00005000)
+#define IOCFG_BM_BASE		(IO_PHYS + 0x01D10000)
+#define IOCFG_BL_BASE		(IO_PHYS + 0x01D30000)
+#define IOCFG_BR_BASE		(IO_PHYS + 0x01D40000)
+#define IOCFG_LM_BASE		(IO_PHYS + 0x01E20000)
+#define IOCFG_RB_BASE		(IO_PHYS + 0x01EB0000)
+#define IOCFG_TL_BASE		(IO_PHYS + 0x01F40000)
+
+/*******************************************************************************
+ * UART related constants
+ ******************************************************************************/
+#define UART0_BASE			(IO_PHYS + 0x01001100)
+#define UART1_BASE			(IO_PHYS + 0x01001200)
+
+#define UART_BAUDRATE			115200
+
+/*******************************************************************************
+ * PMIC related constants
+ ******************************************************************************/
+#define PMIC_WRAP_BASE			(IO_PHYS + 0x00024000)
+
+/*******************************************************************************
+ * System counter frequency related constants
+ ******************************************************************************/
+#define SYS_COUNTER_FREQ_IN_TICKS	13000000
+#define SYS_COUNTER_FREQ_IN_MHZ		13
+
+/*******************************************************************************
+ * GIC-600 & interrupt handling related constants
+ ******************************************************************************/
+/* Base MTK_platform compatible GIC memory map */
+#define BASE_GICD_BASE			MT_GIC_BASE
+#define MT_GIC_RDIST_BASE		(MT_GIC_BASE + 0x40000)
+
+#define SYS_CIRQ_BASE			(IO_PHYS + 0x204000)
+#define CIRQ_REG_NUM			23
+#define CIRQ_IRQ_NUM			730
+#define CIRQ_SPI_START			96
+#define MD_WDT_IRQ_BIT_ID		141
+/*******************************************************************************
+ * Platform binary types for linking
+ ******************************************************************************/
+#define PLATFORM_LINKER_FORMAT		"elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH		aarch64
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+#define PLATFORM_STACK_SIZE		0x800
+
+#define FIRMWARE_WELCOME_STR		"Booting Trusted Firmware\n"
+
+#define PLAT_MAX_PWR_LVL		U(3)
+#define PLAT_MAX_RET_STATE		U(1)
+#define PLAT_MAX_OFF_STATE		U(9)
+
+#define PLATFORM_SYSTEM_COUNT		U(1)
+#define PLATFORM_MCUSYS_COUNT		U(1)
+#define PLATFORM_CLUSTER_COUNT		U(1)
+#define PLATFORM_CLUSTER0_CORE_COUNT	U(8)
+#define PLATFORM_CLUSTER1_CORE_COUNT	U(0)
+
+#define PLATFORM_CORE_COUNT		(PLATFORM_CLUSTER0_CORE_COUNT)
+#define PLATFORM_MAX_CPUS_PER_CLUSTER	U(8)
+
+#define SOC_CHIP_ID			U(0x8195)
+
+/*******************************************************************************
+ * Platform memory map related constants
+ ******************************************************************************/
+#define TZRAM_BASE			0x54600000
+#define TZRAM_SIZE			0x00030000
+
+/*******************************************************************************
+ * BL31 specific defines.
+ ******************************************************************************/
+/*
+ * Put BL3-1 at the top of the Trusted SRAM (just below the shared memory, if
+ * present). BL31_BASE is calculated using the current BL3-1 debug size plus a
+ * little space for growth.
+ */
+#define BL31_BASE			(TZRAM_BASE + 0x1000)
+#define BL31_LIMIT			(TZRAM_BASE + TZRAM_SIZE)
+
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+#define PLAT_PHY_ADDR_SPACE_SIZE	(1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 32)
+#define MAX_XLAT_TABLES			16
+#define MAX_MMAP_REGIONS		16
+
+/*******************************************************************************
+ * Declarations and constants to access the mailboxes safely. Each mailbox is
+ * aligned on the biggest cache line size in the platform. This is known only
+ * to the platform as it might have a combination of integrated and external
+ * caches. Such alignment ensures that two maiboxes do not sit on the same cache
+ * line at any cache level. They could belong to different cpus/clusters &
+ * get written while being protected by different locks causing corruption of
+ * a valid mailbox address.
+ ******************************************************************************/
+#define CACHE_WRITEBACK_SHIFT		6
+#define CACHE_WRITEBACK_GRANULE		(1 << CACHE_WRITEBACK_SHIFT)
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/mediatek/mt8195/include/rtc.h b/plat/mediatek/mt8195/include/rtc.h
new file mode 100644
index 0000000..a9c7bc8
--- /dev/null
+++ b/plat/mediatek/mt8195/include/rtc.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RTC_H
+#define RTC_H
+
+#include <rtc_mt6359p.h>
+
+#endif  /* RTC_H */
diff --git a/plat/mediatek/mt8195/plat_pm.c b/plat/mediatek/mt8195/plat_pm.c
new file mode 100644
index 0000000..522d443
--- /dev/null
+++ b/plat/mediatek/mt8195/plat_pm.c
@@ -0,0 +1,398 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* common headers */
+#include <assert.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/gpio.h>
+#include <lib/psci/psci.h>
+
+/* platform specific headers */
+#include <mt_gic_v3.h>
+#include <mtspmc.h>
+#include <plat/common/platform.h>
+#include <plat_mtk_lpm.h>
+#include <plat_params.h>
+#include <plat_pm.h>
+#include <pmic.h>
+#include <rtc.h>
+
+/*
+ * Cluster state request:
+ * [0] : The CPU requires cluster power down
+ * [1] : The CPU requires cluster power on
+ */
+#define coordinate_cluster(onoff)	write_clusterpwrdn_el1(onoff)
+#define coordinate_cluster_pwron()	coordinate_cluster(1)
+#define coordinate_cluster_pwroff()	coordinate_cluster(0)
+
+/* platform secure entry point */
+static uintptr_t secure_entrypoint;
+/* per-CPU power state */
+static unsigned int plat_power_state[PLATFORM_CORE_COUNT];
+
+/* platform CPU power domain - ops */
+static const struct mt_lpm_tz *plat_mt_pm;
+
+#define plat_mt_pm_invoke(_name, _cpu, _state) ({ \
+	int ret = -1; \
+	if (plat_mt_pm != NULL && plat_mt_pm->_name != NULL) { \
+		ret = plat_mt_pm->_name(_cpu, _state); \
+	} \
+	ret; })
+
+#define plat_mt_pm_invoke_no_check(_name, _cpu, _state) ({ \
+	if (plat_mt_pm != NULL && plat_mt_pm->_name != NULL) { \
+		(void) plat_mt_pm->_name(_cpu, _state); \
+	} \
+	})
+
+/*
+ * Common MTK_platform operations to power on/off a
+ * CPU in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request.
+ */
+
+static void plat_cpu_pwrdwn_common(unsigned int cpu,
+		const psci_power_state_t *state, unsigned int req_pstate)
+{
+	assert(cpu == plat_my_core_pos());
+
+	plat_mt_pm_invoke_no_check(pwr_cpu_dwn, cpu, state);
+
+	if ((psci_get_pstate_pwrlvl(req_pstate) >= MTK_AFFLVL_CLUSTER) ||
+			(req_pstate == 0U)) { /* hotplug off */
+		coordinate_cluster_pwroff();
+	}
+
+	/* Prevent interrupts from spuriously waking up this CPU */
+	mt_gic_rdistif_save();
+	gicv3_cpuif_disable(cpu);
+	gicv3_rdistif_off(cpu);
+}
+
+static void plat_cpu_pwron_common(unsigned int cpu,
+		const psci_power_state_t *state, unsigned int req_pstate)
+{
+	assert(cpu == plat_my_core_pos());
+
+	plat_mt_pm_invoke_no_check(pwr_cpu_on, cpu, state);
+
+	coordinate_cluster_pwron();
+
+	/* Enable the GIC CPU interface */
+	gicv3_rdistif_on(cpu);
+	gicv3_cpuif_enable(cpu);
+	mt_gic_rdistif_init();
+
+	/*
+	 * If mcusys does power down before then restore
+	 * all CPUs' GIC Redistributors
+	 */
+	if (IS_MCUSYS_OFF_STATE(state)) {
+		mt_gic_rdistif_restore_all();
+	} else {
+		mt_gic_rdistif_restore();
+	}
+}
+
+/*
+ * Common MTK_platform operations to power on/off a
+ * cluster in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request.
+ */
+
+static void plat_cluster_pwrdwn_common(unsigned int cpu,
+		const psci_power_state_t *state, unsigned int req_pstate)
+{
+	assert(cpu == plat_my_core_pos());
+
+	if (plat_mt_pm_invoke(pwr_cluster_dwn, cpu, state) != 0) {
+		coordinate_cluster_pwron();
+
+		/* TODO: return on fail.
+		 *       Add a 'return' here before adding any code following
+		 *       the if-block.
+		 */
+	}
+}
+
+static void plat_cluster_pwron_common(unsigned int cpu,
+		const psci_power_state_t *state, unsigned int req_pstate)
+{
+	assert(cpu == plat_my_core_pos());
+
+	if (plat_mt_pm_invoke(pwr_cluster_on, cpu, state) != 0) {
+		/* TODO: return on fail.
+		 *       Add a 'return' here before adding any code following
+		 *       the if-block.
+		 */
+	}
+}
+
+/*
+ * Common MTK_platform operations to power on/off a
+ * mcusys in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request.
+ */
+
+static void plat_mcusys_pwrdwn_common(unsigned int cpu,
+		const psci_power_state_t *state, unsigned int req_pstate)
+{
+	assert(cpu == plat_my_core_pos());
+
+	if (plat_mt_pm_invoke(pwr_mcusys_dwn, cpu, state) != 0) {
+		return;		/* return on fail */
+	}
+
+	mt_gic_distif_save();
+	gic_sgi_save_all();
+}
+
+static void plat_mcusys_pwron_common(unsigned int cpu,
+		const psci_power_state_t *state, unsigned int req_pstate)
+{
+	assert(cpu == plat_my_core_pos());
+
+	if (plat_mt_pm_invoke(pwr_mcusys_on, cpu, state) != 0) {
+		return;		/* return on fail */
+	}
+
+	mt_gic_init();
+	mt_gic_distif_restore();
+	gic_sgi_restore_all();
+
+	plat_mt_pm_invoke_no_check(pwr_mcusys_on_finished, cpu, state);
+}
+
+/*
+ * plat_psci_ops implementation
+ */
+
+static void plat_cpu_standby(plat_local_state_t cpu_state)
+{
+	uint64_t scr;
+
+	scr = read_scr_el3();
+	write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT);
+
+	isb();
+	dsb();
+	wfi();
+
+	write_scr_el3(scr);
+}
+
+static int plat_power_domain_on(u_register_t mpidr)
+{
+	unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr);
+	unsigned int cluster = 0U;
+
+	if (cpu >= PLATFORM_CORE_COUNT) {
+		return PSCI_E_INVALID_PARAMS;
+	}
+
+	if (!spm_get_cluster_powerstate(cluster)) {
+		spm_poweron_cluster(cluster);
+	}
+
+	/* init CPU reset arch as AARCH64 */
+	mcucfg_init_archstate(cluster, cpu, true);
+	mcucfg_set_bootaddr(cluster, cpu, secure_entrypoint);
+	spm_poweron_cpu(cluster, cpu);
+
+	return PSCI_E_SUCCESS;
+}
+
+static void plat_power_domain_on_finish(const psci_power_state_t *state)
+{
+	unsigned long mpidr = read_mpidr_el1();
+	unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr);
+
+	assert(cpu < PLATFORM_CORE_COUNT);
+
+	/* Allow IRQs to wakeup this core in IDLE flow */
+	mcucfg_enable_gic_wakeup(0U, cpu);
+
+	if (IS_CLUSTER_OFF_STATE(state)) {
+		plat_cluster_pwron_common(cpu, state, 0U);
+	}
+
+	plat_cpu_pwron_common(cpu, state, 0U);
+}
+
+static void plat_power_domain_off(const psci_power_state_t *state)
+{
+	unsigned long mpidr = read_mpidr_el1();
+	unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr);
+
+	assert(cpu < PLATFORM_CORE_COUNT);
+
+	plat_cpu_pwrdwn_common(cpu, state, 0U);
+	spm_poweroff_cpu(0U, cpu);
+
+	/* prevent unintended IRQs from waking up the hot-unplugged core */
+	mcucfg_disable_gic_wakeup(0U, cpu);
+
+	if (IS_CLUSTER_OFF_STATE(state)) {
+		plat_cluster_pwrdwn_common(cpu, state, 0U);
+	}
+}
+
+static void plat_power_domain_suspend(const psci_power_state_t *state)
+{
+	unsigned int cpu = plat_my_core_pos();
+
+	assert(cpu < PLATFORM_CORE_COUNT);
+
+	plat_mt_pm_invoke_no_check(pwr_prompt, cpu, state);
+
+	/* Perform the common CPU specific operations */
+	plat_cpu_pwrdwn_common(cpu, state, plat_power_state[cpu]);
+
+	if (IS_CLUSTER_OFF_STATE(state)) {
+		/* Perform the common cluster specific operations */
+		plat_cluster_pwrdwn_common(cpu, state, plat_power_state[cpu]);
+	}
+
+	if (IS_MCUSYS_OFF_STATE(state)) {
+		/* Perform the common mcusys specific operations */
+		plat_mcusys_pwrdwn_common(cpu, state, plat_power_state[cpu]);
+	}
+}
+
+static void plat_power_domain_suspend_finish(const psci_power_state_t *state)
+{
+	unsigned int cpu = plat_my_core_pos();
+
+	assert(cpu < PLATFORM_CORE_COUNT);
+
+	if (IS_MCUSYS_OFF_STATE(state)) {
+		/* Perform the common mcusys specific operations */
+		plat_mcusys_pwron_common(cpu, state, plat_power_state[cpu]);
+	}
+
+	if (IS_CLUSTER_OFF_STATE(state)) {
+		/* Perform the common cluster specific operations */
+		plat_cluster_pwron_common(cpu, state, plat_power_state[cpu]);
+	}
+
+	/* Perform the common CPU specific operations */
+	plat_cpu_pwron_common(cpu, state, plat_power_state[cpu]);
+
+	plat_mt_pm_invoke_no_check(pwr_reflect, cpu, state);
+}
+
+static int plat_validate_power_state(unsigned int power_state,
+					psci_power_state_t *req_state)
+{
+	unsigned int pstate = psci_get_pstate_type(power_state);
+	unsigned int aff_lvl = psci_get_pstate_pwrlvl(power_state);
+	unsigned int cpu = plat_my_core_pos();
+
+	if (aff_lvl > PLAT_MAX_PWR_LVL) {
+		return PSCI_E_INVALID_PARAMS;
+	}
+
+	if (pstate == PSTATE_TYPE_STANDBY) {
+		req_state->pwr_domain_state[0] = PLAT_MAX_RET_STATE;
+	} else {
+		unsigned int i;
+		unsigned int pstate_id = psci_get_pstate_id(power_state);
+		plat_local_state_t s = MTK_LOCAL_STATE_OFF;
+
+		/* Use pstate_id to be power domain state */
+		if (pstate_id > s) {
+			s = (plat_local_state_t)pstate_id;
+		}
+
+		for (i = 0U; i <= aff_lvl; i++) {
+			req_state->pwr_domain_state[i] = s;
+		}
+	}
+
+	plat_power_state[cpu] = power_state;
+	return PSCI_E_SUCCESS;
+}
+
+static void plat_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+	unsigned int lv;
+	unsigned int cpu = plat_my_core_pos();
+
+	for (lv = PSCI_CPU_PWR_LVL; lv <= PLAT_MAX_PWR_LVL; lv++) {
+		req_state->pwr_domain_state[lv] = PLAT_MAX_OFF_STATE;
+	}
+
+	plat_power_state[cpu] =
+			psci_make_powerstate(
+				MT_PLAT_PWR_STATE_SYSTEM_SUSPEND,
+				PSTATE_TYPE_POWERDOWN, PLAT_MAX_PWR_LVL);
+
+	flush_dcache_range((uintptr_t)
+			&plat_power_state[cpu],
+			sizeof(plat_power_state[cpu]));
+}
+
+/*******************************************************************************
+ * MTK handlers to shutdown/reboot the system
+ ******************************************************************************/
+static void __dead2 plat_mtk_system_reset(void)
+{
+	struct bl_aux_gpio_info *gpio_reset = plat_get_mtk_gpio_reset();
+
+	INFO("MTK System Reset\n");
+
+	gpio_set_value(gpio_reset->index, gpio_reset->polarity);
+
+	wfi();
+	ERROR("MTK System Reset: operation not handled.\n");
+	panic();
+}
+
+static void __dead2 plat_mtk_system_off(void)
+{
+	INFO("MTK System Off\n");
+
+	rtc_power_off_sequence();
+	pmic_power_off();
+
+	wfi();
+	ERROR("MTK System Off: operation not handled.\n");
+	panic();
+}
+
+static const plat_psci_ops_t plat_psci_ops = {
+	.system_reset			= plat_mtk_system_reset,
+	.system_off			= plat_mtk_system_off,
+	.cpu_standby			= plat_cpu_standby,
+	.pwr_domain_on			= plat_power_domain_on,
+	.pwr_domain_on_finish		= plat_power_domain_on_finish,
+	.pwr_domain_off			= plat_power_domain_off,
+	.pwr_domain_suspend		= plat_power_domain_suspend,
+	.pwr_domain_suspend_finish	= plat_power_domain_suspend_finish,
+	.validate_power_state		= plat_validate_power_state,
+	.get_sys_suspend_power_state	= plat_get_sys_suspend_power_state
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+			const plat_psci_ops_t **psci_ops)
+{
+	*psci_ops = &plat_psci_ops;
+	secure_entrypoint = sec_entrypoint;
+
+	/*
+	 * init the warm reset config for boot CPU
+	 * reset arch as AARCH64
+	 * reset addr as function bl31_warm_entrypoint()
+	 */
+	mcucfg_init_archstate(0U, 0U, true);
+	mcucfg_set_bootaddr(0U, 0U, secure_entrypoint);
+
+	spmc_init();
+	plat_mt_pm = mt_plat_cpu_pm_init();
+
+	return 0;
+}
diff --git a/plat/mediatek/mt8195/plat_sip_calls.c b/plat/mediatek/mt8195/plat_sip_calls.c
new file mode 100644
index 0000000..a1e3c36
--- /dev/null
+++ b/plat/mediatek/mt8195/plat_sip_calls.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+
+uintptr_t mediatek_plat_sip_handler(uint32_t smc_fid,
+				u_register_t x1,
+				u_register_t x2,
+				u_register_t x3,
+				u_register_t x4,
+				void *cookie,
+				void *handle,
+				u_register_t flags)
+{
+	switch (smc_fid) {
+	default:
+		ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
+		break;
+	}
+
+	SMC_RET1(handle, SMC_UNK);
+}
diff --git a/plat/mediatek/mt8195/plat_topology.c b/plat/mediatek/mt8195/plat_topology.c
new file mode 100644
index 0000000..bc95c64
--- /dev/null
+++ b/plat/mediatek/mt8195/plat_topology.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <lib/psci/psci.h>
+
+#include <plat_helpers.h>
+#include <platform_def.h>
+
+const unsigned char mtk_power_domain_tree_desc[] = {
+	/* Number of root nodes */
+	PLATFORM_SYSTEM_COUNT,
+	/* Number of children for the root node */
+	PLATFORM_MCUSYS_COUNT,
+	/* Number of children for the mcusys node */
+	PLATFORM_CLUSTER_COUNT,
+	/* Number of children for the first cluster node */
+	PLATFORM_CLUSTER0_CORE_COUNT,
+};
+
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+	return mtk_power_domain_tree_desc;
+}
+
+/*******************************************************************************
+ * This function implements a part of the critical interface between the psci
+ * generic layer and the platform that allows the former to query the platform
+ * to convert an MPIDR to a unique linear index. An error code (-1) is returned
+ * in case the MPIDR is invalid.
+ ******************************************************************************/
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+	unsigned int cluster_id, cpu_id;
+
+	if ((read_mpidr() & MPIDR_MT_MASK) != 0) {
+		/* ARMv8.2 arch */
+		if ((mpidr & (MPIDR_AFFLVL_MASK << MPIDR_AFF0_SHIFT)) != 0) {
+			return -1;
+		}
+		return plat_mediatek_calc_core_pos(mpidr);
+	}
+
+	mpidr &= MPIDR_AFFINITY_MASK;
+
+	if ((mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) != 0) {
+		return -1;
+	}
+
+	cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
+	cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
+
+	if (cluster_id >= PLATFORM_CLUSTER_COUNT) {
+		return -1;
+	}
+
+	/*
+	 * Validate cpu_id by checking whether it represents a CPU in
+	 * one of the two clusters present on the platform.
+	 */
+	if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER) {
+		return -1;
+	}
+
+	return (cpu_id + (cluster_id * 8));
+}
diff --git a/plat/mediatek/mt8195/platform.mk b/plat/mediatek/mt8195/platform.mk
new file mode 100644
index 0000000..4d3ad59
--- /dev/null
+++ b/plat/mediatek/mt8195/platform.mk
@@ -0,0 +1,78 @@
+#
+# Copyright (c) 2021, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+MTK_PLAT     := plat/mediatek
+MTK_PLAT_SOC := ${MTK_PLAT}/${PLAT}
+
+PLAT_INCLUDES := -I${MTK_PLAT}/common/                            \
+                 -I${MTK_PLAT}/common/drivers/gic600/             \
+                 -I${MTK_PLAT}/common/drivers/gpio/               \
+                 -I${MTK_PLAT}/common/drivers/rtc/                \
+                 -I${MTK_PLAT}/common/drivers/timer/              \
+                 -I${MTK_PLAT_SOC}/drivers/gpio/                  \
+                 -I${MTK_PLAT_SOC}/drivers/mcdi/                  \
+                 -I${MTK_PLAT_SOC}/drivers/pmic/                  \
+                 -I${MTK_PLAT_SOC}/drivers/spmc/                  \
+                 -I${MTK_PLAT_SOC}/include/
+
+GICV3_SUPPORT_GIC600        :=      1
+include drivers/arm/gic/v3/gicv3.mk
+include lib/xlat_tables_v2/xlat_tables.mk
+
+PLAT_BL_COMMON_SOURCES := ${GICV3_SOURCES}                              \
+                          ${XLAT_TABLES_LIB_SRCS}                       \
+                          plat/common/aarch64/crash_console_helpers.S   \
+                          plat/common/plat_psci_common.c
+
+
+BL31_SOURCES += common/desc_image_load.c                              \
+                drivers/delay_timer/delay_timer.c                     \
+                drivers/gpio/gpio.c                                   \
+                drivers/delay_timer/generic_delay_timer.c             \
+                drivers/ti/uart/aarch64/16550_console.S               \
+                lib/bl_aux_params/bl_aux_params.c                     \
+                lib/cpus/aarch64/cortex_a55.S                         \
+                lib/cpus/aarch64/cortex_a78.S                         \
+                plat/common/plat_gicv3.c                              \
+                ${MTK_PLAT}/common/drivers/gic600/mt_gic_v3.c         \
+                ${MTK_PLAT}/common/drivers/gpio/mtgpio_common.c       \
+                ${MTK_PLAT}/common/drivers/pmic_wrap/pmic_wrap_init_v2.c \
+                ${MTK_PLAT}/common/drivers/rtc/rtc_common.c           \
+                ${MTK_PLAT}/common/drivers/rtc/rtc_mt6359p.c          \
+                ${MTK_PLAT}/common/drivers/timer/mt_timer.c           \
+                ${MTK_PLAT}/common/mtk_cirq.c                         \
+                ${MTK_PLAT}/common/mtk_plat_common.c                  \
+                ${MTK_PLAT}/common/mtk_sip_svc.c                      \
+                ${MTK_PLAT}/common/params_setup.c                     \
+                ${MTK_PLAT_SOC}/aarch64/platform_common.c             \
+                ${MTK_PLAT_SOC}/aarch64/plat_helpers.S                \
+                ${MTK_PLAT_SOC}/bl31_plat_setup.c                     \
+                ${MTK_PLAT_SOC}/drivers/gpio/mtgpio.c                 \
+                ${MTK_PLAT_SOC}/drivers/mcdi/mt_cpu_pm.c              \
+                ${MTK_PLAT_SOC}/drivers/mcdi/mt_cpu_pm_cpc.c          \
+                ${MTK_PLAT_SOC}/drivers/mcdi/mt_mcdi.c                \
+                ${MTK_PLAT_SOC}/drivers/gpio/mtgpio.c                 \
+                ${MTK_PLAT_SOC}/drivers/pmic/pmic.c                   \
+                ${MTK_PLAT_SOC}/drivers/spmc/mtspmc.c                 \
+                ${MTK_PLAT_SOC}/plat_pm.c                             \
+                ${MTK_PLAT_SOC}/plat_sip_calls.c                      \
+                ${MTK_PLAT_SOC}/plat_topology.c
+
+# Configs for A78 and A55
+HW_ASSISTED_COHERENCY := 1
+USE_COHERENT_MEM := 0
+CTX_INCLUDE_AARCH32_REGS := 0
+ERRATA_A55_1530923 := 1
+
+# indicate the reset vector address can be programmed
+PROGRAMMABLE_RESET_ADDRESS := 1
+
+COLD_BOOT_SINGLE_CPU := 1
+
+MACH_MT8195 := 1
+$(eval $(call add_define,MACH_MT8195))
+
+include lib/coreboot/coreboot.mk