refator(mediatek): move drivers folder in common to plat/mediatek

We plan to put some soc related drivers in common/drivers. To reduce
confision, we move them to plat/mediatek.

Signed-off-by: Bo-Chen Chen <rex-bc.chen@mediatek.com>
Change-Id: I6b344e660f40a23b15151aab073d3045b28f52aa
diff --git a/plat/mediatek/drivers/gic600/mt_gic_v3.c b/plat/mediatek/drivers/gic600/mt_gic_v3.c
new file mode 100644
index 0000000..7652c4f
--- /dev/null
+++ b/plat/mediatek/drivers/gic600/mt_gic_v3.c
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include "../drivers/arm/gic/v3/gicv3_private.h"
+#include <bl31/interrupt_mgmt.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+
+#include <mt_gic_v3.h>
+#include <mtk_plat_common.h>
+#include <plat/common/platform.h>
+#include <plat_private.h>
+#include <platform_def.h>
+
+#define SGI_MASK 0xffff
+
+uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
+static uint32_t rdist_has_saved[PLATFORM_CORE_COUNT];
+
+/* we save and restore the GICv3 context on system suspend */
+gicv3_dist_ctx_t dist_ctx;
+
+static unsigned int mt_mpidr_to_core_pos(u_register_t mpidr)
+{
+	return plat_core_pos_by_mpidr(mpidr);
+}
+
+gicv3_driver_data_t mt_gicv3_data = {
+	.gicd_base = MT_GIC_BASE,
+	.gicr_base = MT_GIC_RDIST_BASE,
+	.rdistif_num = PLATFORM_CORE_COUNT,
+	.rdistif_base_addrs = rdistif_base_addrs,
+	.mpidr_to_core_pos = mt_mpidr_to_core_pos,
+};
+
+struct gic_chip_data {
+	/* All cores share the same configuration */
+	unsigned int saved_group;
+	unsigned int saved_enable;
+	unsigned int saved_conf0;
+	unsigned int saved_conf1;
+	unsigned int saved_grpmod;
+	/* Per-core sgi */
+	unsigned int saved_sgi[PLATFORM_CORE_COUNT];
+};
+
+static struct gic_chip_data gic_data;
+
+void mt_gic_driver_init(void)
+{
+	gicv3_driver_init(&mt_gicv3_data);
+}
+
+void mt_gic_set_pending(uint32_t irq)
+{
+	gicv3_set_interrupt_pending(irq, plat_my_core_pos());
+}
+
+void mt_gic_distif_save(void)
+{
+	gicv3_distif_save(&dist_ctx);
+}
+
+void mt_gic_distif_restore(void)
+{
+	gicv3_distif_init_restore(&dist_ctx);
+}
+
+void mt_gic_rdistif_init(void)
+{
+	unsigned int proc_num;
+	unsigned int index;
+	uintptr_t gicr_base;
+
+	proc_num = plat_my_core_pos();
+	gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
+
+	/* set all SGI/PPI as non-secure GROUP1 by default */
+	mmio_write_32(gicr_base + GICR_IGROUPR0, ~0U);
+	mmio_write_32(gicr_base + GICR_IGRPMODR0, 0x0);
+
+	/* setup the default PPI/SGI priorities */
+	for (index = 0; index < TOTAL_PCPU_INTR_NUM; index += 4U)
+		gicr_write_ipriorityr(gicr_base, index,
+				GICD_IPRIORITYR_DEF_VAL);
+}
+
+void mt_gic_rdistif_save(void)
+{
+	unsigned int proc_num;
+	uintptr_t gicr_base;
+
+	proc_num = plat_my_core_pos();
+	gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
+
+	gic_data.saved_group = mmio_read_32(gicr_base + GICR_IGROUPR0);
+	gic_data.saved_enable = mmio_read_32(gicr_base + GICR_ISENABLER0);
+	gic_data.saved_conf0 = mmio_read_32(gicr_base + GICR_ICFGR0);
+	gic_data.saved_conf1 = mmio_read_32(gicr_base + GICR_ICFGR1);
+	gic_data.saved_grpmod = mmio_read_32(gicr_base + GICR_IGRPMODR0);
+
+	rdist_has_saved[proc_num] = 1;
+}
+
+void mt_gic_rdistif_restore(void)
+{
+	unsigned int proc_num;
+	uintptr_t gicr_base;
+
+	proc_num = plat_my_core_pos();
+	if (rdist_has_saved[proc_num] == 1) {
+		gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
+		mmio_write_32(gicr_base + GICR_IGROUPR0, gic_data.saved_group);
+		mmio_write_32(gicr_base + GICR_ISENABLER0,
+			gic_data.saved_enable);
+		mmio_write_32(gicr_base + GICR_ICFGR0, gic_data.saved_conf0);
+		mmio_write_32(gicr_base + GICR_ICFGR1, gic_data.saved_conf1);
+		mmio_write_32(gicr_base + GICR_IGRPMODR0,
+			gic_data.saved_grpmod);
+	}
+}
+
+void mt_gic_rdistif_restore_all(void)
+{
+	unsigned int proc_num;
+	uintptr_t gicr_base;
+
+	for (proc_num = 0; proc_num < PLATFORM_CORE_COUNT; proc_num++) {
+		gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
+		mmio_write_32(gicr_base + GICR_IGROUPR0, gic_data.saved_group);
+		mmio_write_32(gicr_base + GICR_ISENABLER0,
+			gic_data.saved_enable);
+		mmio_write_32(gicr_base + GICR_ICFGR0, gic_data.saved_conf0);
+		mmio_write_32(gicr_base + GICR_ICFGR1, gic_data.saved_conf1);
+		mmio_write_32(gicr_base + GICR_IGRPMODR0,
+			gic_data.saved_grpmod);
+	}
+}
+
+void gic_sgi_save_all(void)
+{
+	unsigned int proc_num;
+	uintptr_t gicr_base;
+
+	for (proc_num = 0; proc_num < PLATFORM_CORE_COUNT; proc_num++) {
+		gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
+		gic_data.saved_sgi[proc_num] =
+			mmio_read_32(gicr_base + GICR_ISPENDR0) & SGI_MASK;
+	}
+}
+
+void gic_sgi_restore_all(void)
+{
+	unsigned int proc_num;
+	uintptr_t gicr_base;
+
+	for (proc_num = 0; proc_num < PLATFORM_CORE_COUNT; proc_num++) {
+		gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
+		mmio_write_32(gicr_base + GICR_ICPENDR0, SGI_MASK);
+		mmio_write_32(gicr_base + GICR_ISPENDR0,
+			gic_data.saved_sgi[proc_num] & SGI_MASK);
+	}
+}
+
+void mt_gic_init(void)
+{
+	gicv3_distif_init();
+	gicv3_rdistif_init(plat_my_core_pos());
+	gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+uint32_t mt_irq_get_pending(uint32_t irq)
+{
+	uint32_t val;
+
+	val = mmio_read_32(BASE_GICD_BASE + GICD_ISPENDR +
+		irq / 32 * 4);
+	val = (val >> (irq % 32)) & 1U;
+	return val;
+}
+
+
+void mt_irq_set_pending(uint32_t irq)
+{
+	uint32_t bit = 1U << (irq % 32);
+
+	mmio_write_32(BASE_GICD_BASE + GICD_ISPENDR +
+		irq / 32 * 4, bit);
+}
diff --git a/plat/mediatek/drivers/gic600/mt_gic_v3.h b/plat/mediatek/drivers/gic600/mt_gic_v3.h
new file mode 100644
index 0000000..98835f0
--- /dev/null
+++ b/plat/mediatek/drivers/gic600/mt_gic_v3.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_GIC_V3_H
+#define MT_GIC_V3_H
+
+#include <drivers/arm/gicv3.h>
+#include <lib/mmio.h>
+
+void mt_gic_driver_init(void);
+void mt_gic_init(void);
+void mt_gic_set_pending(uint32_t irq);
+void mt_gic_distif_save(void);
+void mt_gic_distif_restore(void);
+void mt_gic_rdistif_init(void);
+void mt_gic_rdistif_save(void);
+void mt_gic_rdistif_restore(void);
+void mt_gic_rdistif_restore_all(void);
+void gic_sgi_save_all(void);
+void gic_sgi_restore_all(void);
+uint32_t mt_irq_get_pending(uint32_t irq);
+void mt_irq_set_pending(uint32_t irq);
+
+#endif /* MT_GIC_V3_H */
diff --git a/plat/mediatek/drivers/gpio/mtgpio_common.c b/plat/mediatek/drivers/gpio/mtgpio_common.c
new file mode 100644
index 0000000..90e5400
--- /dev/null
+++ b/plat/mediatek/drivers/gpio/mtgpio_common.c
@@ -0,0 +1,298 @@
+/*
+ * Copyright (c) 2020-2022, 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/drivers/gpio/mtgpio_common.h b/plat/mediatek/drivers/gpio/mtgpio_common.h
new file mode 100644
index 0000000..68d96e5
--- /dev/null
+++ b/plat/mediatek/drivers/gpio/mtgpio_common.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2020-2022, 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/drivers/lpm/mt_lp_rm.c b/plat/mediatek/drivers/lpm/mt_lp_rm.c
new file mode 100644
index 0000000..0bafc66
--- /dev/null
+++ b/plat/mediatek/drivers/lpm/mt_lp_rm.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <mt_lp_rm.h>
+#include <stddef.h>
+
+struct platform_mt_resource_manager {
+	unsigned int count;
+	struct mt_resource_manager *plat_rm;
+};
+
+static struct platform_mt_resource_manager plat_mt_rm;
+
+int mt_lp_rm_register(struct mt_resource_manager *rm)
+{
+	unsigned int i;
+	struct mt_resource_constraint *const *rc;
+
+	if ((rm == NULL) || (rm->consts == NULL) ||
+	    (plat_mt_rm.plat_rm != NULL)) {
+		return MT_RM_STATUS_BAD;
+	}
+
+	for (i = 0U, rc = rm->consts; *rc != NULL; i++, rc++) {
+		if ((*rc)->init != NULL) {
+			(*rc)->init();
+		}
+	}
+
+	plat_mt_rm.plat_rm = rm;
+	plat_mt_rm.count = i;
+
+	return MT_RM_STATUS_OK;
+}
+
+int mt_lp_rm_reset_constraint(int idx, unsigned int cpuid, int stateid)
+{
+	struct mt_resource_constraint const *rc = NULL;
+
+	if ((plat_mt_rm.plat_rm == NULL) || (idx < 0) ||
+	    (idx >= plat_mt_rm.count)) {
+		return MT_RM_STATUS_BAD;
+	}
+
+	rc = plat_mt_rm.plat_rm->consts[idx];
+
+	if ((rc == NULL) || (rc->reset == NULL)) {
+		return MT_RM_STATUS_BAD;
+	}
+
+	return rc->reset(cpuid, stateid);
+}
+
+int mt_lp_rm_find_and_run_constraint(int idx, unsigned int cpuid,
+				     int stateid, void *priv)
+{
+	int i, res = MT_RM_STATUS_BAD;
+	struct mt_resource_constraint *const *rc;
+	struct mt_resource_manager *rm = plat_mt_rm.plat_rm;
+
+	if ((rm == NULL) || (idx < 0) || (idx >= plat_mt_rm.count)) {
+		return res;
+	}
+
+	/* If subsys clk/mtcmos is on, add block-resource-off flag */
+	if (rm->update != NULL) {
+		res = rm->update(rm->consts, stateid, priv);
+		if (res != 0) {
+			return res;
+		}
+	}
+
+	for (i = idx, rc = (rm->consts + idx); *rc != NULL; i++, rc++) {
+		if (((*rc)->is_valid != NULL) &&
+		    ((*rc)->is_valid(cpuid, stateid))) {
+			if (((*rc)->run != NULL) &&
+			    ((*rc)->run(cpuid, stateid) == 0)) {
+				res = i;
+				break;
+			}
+		}
+	}
+
+	return res;
+}
+
+int mt_lp_rm_do_update(int stateid, int type, void const *p)
+{
+	int res = MT_RM_STATUS_BAD;
+	struct mt_resource_constraint *const *rc;
+	struct mt_resource_manager *rm = plat_mt_rm.plat_rm;
+
+	if (rm == NULL) {
+		return res;
+	}
+
+	for (rc = rm->consts; *rc != NULL; rc++) {
+		if ((*rc)->update != NULL) {
+			res = (*rc)->update(stateid, type, p);
+			if (res != MT_RM_STATUS_OK) {
+				break;
+			}
+		}
+	}
+
+	return res;
+}
diff --git a/plat/mediatek/drivers/lpm/mt_lp_rm.h b/plat/mediatek/drivers/lpm/mt_lp_rm.h
new file mode 100644
index 0000000..e93dac3
--- /dev/null
+++ b/plat/mediatek/drivers/lpm/mt_lp_rm.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_LP_RM_H
+#define MT_LP_RM_H
+
+#include <stdbool.h>
+
+#define MT_RM_STATUS_OK		0
+#define MT_RM_STATUS_BAD	-1
+
+enum PLAT_MT_LPM_RC_TYPE {
+	PLAT_RC_UPDATE_CONDITION,
+	PLAT_RC_UPDATE_REMAIN_IRQS
+};
+
+struct mt_resource_constraint {
+	int level;
+	int (*init)(void);
+	bool (*is_valid)(unsigned int cpu, int stateid);
+	int (*update)(int stateid, int type, const void *p);
+	int (*run)(unsigned int cpu, int stateid);
+	int (*reset)(unsigned int cpu, int stateid);
+	unsigned int (*allow)(int stateid);
+};
+
+struct mt_resource_manager {
+	int (*update)(struct mt_resource_constraint **con,
+		      int stateid, void *priv);
+	struct mt_resource_constraint **consts;
+};
+
+extern int mt_lp_rm_register(struct mt_resource_manager *rm);
+extern int mt_lp_rm_find_and_run_constraint(int idx, unsigned int cpuid,
+					    int stateid, void *priv);
+extern int mt_lp_rm_reset_constraint(int constraint_id, unsigned int cpuid,
+				     int stateid);
+extern int mt_lp_rm_do_update(int stateid, int type, void const *p);
+#endif /* MT_LP_RM_H */
diff --git a/plat/mediatek/drivers/pmic_wrap/pmic_wrap_init.c b/plat/mediatek/drivers/pmic_wrap/pmic_wrap_init.c
new file mode 100644
index 0000000..0ee1c64
--- /dev/null
+++ b/plat/mediatek/drivers/pmic_wrap/pmic_wrap_init.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2019-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <platform_def.h>
+#include <pmic_wrap_init.h>
+
+/* pmic wrap module wait_idle and read polling interval (in microseconds) */
+enum {
+	WAIT_IDLE_POLLING_DELAY_US	= 1,
+	READ_POLLING_DELAY_US		= 2
+};
+
+static inline uint32_t wait_for_state_idle(uint32_t timeout_us,
+					   void *wacs_register,
+					   void *wacs_vldclr_register,
+					   uint32_t *read_reg)
+{
+	uint32_t reg_rdata;
+	uint32_t retry;
+
+	retry = (timeout_us + WAIT_IDLE_POLLING_DELAY_US) /
+		WAIT_IDLE_POLLING_DELAY_US;
+
+	do {
+		udelay(WAIT_IDLE_POLLING_DELAY_US);
+		reg_rdata = mmio_read_32((uintptr_t)wacs_register);
+		/* if last read command timeout,clear vldclr bit
+		 * read command state machine:FSM_REQ-->wfdle-->WFVLDCLR;
+		 * write:FSM_REQ-->idle
+		 */
+		switch (((reg_rdata >> RDATA_WACS_FSM_SHIFT) &
+			RDATA_WACS_FSM_MASK)) {
+		case WACS_FSM_WFVLDCLR:
+			mmio_write_32((uintptr_t)wacs_vldclr_register, 1);
+			ERROR("WACS_FSM = PMIC_WRAP_WACS_VLDCLR\n");
+			break;
+		case WACS_FSM_WFDLE:
+			ERROR("WACS_FSM = WACS_FSM_WFDLE\n");
+			break;
+		case WACS_FSM_REQ:
+			ERROR("WACS_FSM = WACS_FSM_REQ\n");
+			break;
+		case WACS_FSM_IDLE:
+			goto done;
+		default:
+			break;
+		}
+
+		retry--;
+	} while (retry);
+
+done:
+	if (!retry)	/* timeout */
+		return E_PWR_WAIT_IDLE_TIMEOUT;
+
+	if (read_reg)
+		*read_reg = reg_rdata;
+	return 0;
+}
+
+static inline uint32_t wait_for_state_ready(uint32_t timeout_us,
+					    void *wacs_register,
+					    uint32_t *read_reg)
+{
+	uint32_t reg_rdata;
+	uint32_t retry;
+
+	retry = (timeout_us + READ_POLLING_DELAY_US) / READ_POLLING_DELAY_US;
+
+	do {
+		udelay(READ_POLLING_DELAY_US);
+		reg_rdata = mmio_read_32((uintptr_t)wacs_register);
+
+		if (((reg_rdata >> RDATA_WACS_FSM_SHIFT) & RDATA_WACS_FSM_MASK)
+		    == WACS_FSM_WFVLDCLR)
+			break;
+
+		retry--;
+	} while (retry);
+
+	if (!retry) {	/* timeout */
+		ERROR("timeout when waiting for idle\n");
+		return E_PWR_WAIT_IDLE_TIMEOUT_READ;
+	}
+
+	if (read_reg)
+		*read_reg = reg_rdata;
+	return 0;
+}
+
+static int32_t pwrap_wacs2(uint32_t write,
+		    uint32_t adr,
+		    uint32_t wdata,
+		    uint32_t *rdata,
+		    uint32_t init_check)
+{
+	uint32_t reg_rdata = 0;
+	uint32_t wacs_write = 0;
+	uint32_t wacs_adr = 0;
+	uint32_t wacs_cmd = 0;
+	uint32_t return_value = 0;
+
+	if (init_check) {
+		reg_rdata = mmio_read_32((uintptr_t)&mtk_pwrap->wacs2_rdata);
+		/* Prevent someone to used pwrap before pwrap init */
+		if (((reg_rdata >> RDATA_INIT_DONE_SHIFT) &
+		    RDATA_INIT_DONE_MASK) != WACS_INIT_DONE) {
+			ERROR("initialization isn't finished\n");
+			return E_PWR_NOT_INIT_DONE;
+		}
+	}
+	reg_rdata = 0;
+	/* Check IDLE in advance */
+	return_value = wait_for_state_idle(TIMEOUT_WAIT_IDLE,
+				&mtk_pwrap->wacs2_rdata,
+				&mtk_pwrap->wacs2_vldclr,
+				0);
+	if (return_value != 0) {
+		ERROR("wait_for_fsm_idle fail,return_value=%d\n", return_value);
+		goto FAIL;
+	}
+	wacs_write = write << 31;
+	wacs_adr = (adr >> 1) << 16;
+	wacs_cmd = wacs_write | wacs_adr | wdata;
+
+	mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_cmd, wacs_cmd);
+	if (write == 0) {
+		if (rdata == NULL) {
+			ERROR("rdata is a NULL pointer\n");
+			return_value = E_PWR_INVALID_ARG;
+			goto FAIL;
+		}
+		return_value = wait_for_state_ready(TIMEOUT_READ,
+					&mtk_pwrap->wacs2_rdata,
+					&reg_rdata);
+		if (return_value != 0) {
+			ERROR("wait_for_fsm_vldclr fail,return_value=%d\n",
+				 return_value);
+			goto FAIL;
+		}
+		*rdata = ((reg_rdata >> RDATA_WACS_RDATA_SHIFT)
+			  & RDATA_WACS_RDATA_MASK);
+		mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_vldclr, 1);
+	}
+FAIL:
+	return return_value;
+}
+
+/* external API for pmic_wrap user */
+
+int32_t pwrap_read(uint32_t adr, uint32_t *rdata)
+{
+	return pwrap_wacs2(0, adr, 0, rdata, 1);
+}
+
+int32_t pwrap_write(uint32_t adr, uint32_t wdata)
+{
+	return pwrap_wacs2(1, adr, wdata, 0, 1);
+}
diff --git a/plat/mediatek/drivers/pmic_wrap/pmic_wrap_init_v2.c b/plat/mediatek/drivers/pmic_wrap/pmic_wrap_init_v2.c
new file mode 100644
index 0000000..80f55de
--- /dev/null
+++ b/plat/mediatek/drivers/pmic_wrap/pmic_wrap_init_v2.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include "platform_def.h"
+#include "pmic_wrap_init.h"
+
+/* pmic wrap module wait_idle and read polling interval (in microseconds) */
+enum pwrap_polling_interval {
+	WAIT_IDLE_POLLING_DELAY_US	= 1,
+	READ_POLLING_DELAY_US		= 2
+};
+
+static uint32_t pwrap_check_idle(void *wacs_register, uint32_t timeout_us)
+{
+	uint32_t reg_rdata = 0U, retry;
+
+	retry = (timeout_us + WAIT_IDLE_POLLING_DELAY_US) /
+		WAIT_IDLE_POLLING_DELAY_US;
+	while (retry != 0) {
+		udelay(WAIT_IDLE_POLLING_DELAY_US);
+		reg_rdata = mmio_read_32((uintptr_t)wacs_register);
+		/* if last read command timeout,clear vldclr bit
+		 * read command state machine:FSM_REQ-->wfdle-->WFVLDCLR;
+		 * write:FSM_REQ-->idle
+		 */
+		switch (GET_WACS_FSM(reg_rdata)) {
+		case SWINF_FSM_WFVLDCLR:
+			mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_vldclr, 0x1);
+			INFO("WACS_FSM = SWINF_FSM_WFVLDCLR\n");
+			break;
+		case SWINF_FSM_WFDLE:
+			INFO("WACS_FSM = SWINF_FSM_WFDLE\n");
+			break;
+		case SWINF_FSM_REQ:
+			INFO("WACS_FSM = SWINF_FSM_REQ\n");
+			break;
+		case SWINF_FSM_IDLE:
+			goto done;
+		default:
+			break;
+		}
+		retry--;
+	};
+
+done:
+	if (retry == 0) {
+		/* timeout */
+		return E_PWR_WAIT_IDLE_TIMEOUT;
+	}
+
+	return 0U;
+}
+
+static uint32_t pwrap_check_vldclr(void *wacs_register, uint32_t timeout_us)
+{
+	uint32_t reg_rdata = 0U, retry;
+
+	retry = (timeout_us + READ_POLLING_DELAY_US) / READ_POLLING_DELAY_US;
+	while (retry != 0) {
+		udelay(READ_POLLING_DELAY_US);
+		reg_rdata = mmio_read_32((uintptr_t)wacs_register);
+		if (GET_WACS_FSM(reg_rdata) == SWINF_FSM_WFVLDCLR) {
+			break;
+		}
+		retry--;
+	};
+
+	if (retry == 0) {
+		/* timeout */
+		return E_PWR_WAIT_IDLE_TIMEOUT;
+	}
+
+	return 0U;
+}
+
+static int32_t pwrap_wacs2(uint32_t write, uint32_t adr, uint32_t wdata,
+			   uint32_t *rdata, uint32_t init_check)
+{
+	uint32_t reg_rdata, return_value;
+
+	if (init_check != 0) {
+		if ((mmio_read_32((uintptr_t)&mtk_pwrap->init_done) & 0x1) == 0) {
+			ERROR("initialization isn't finished\n");
+			return E_PWR_NOT_INIT_DONE;
+		}
+	}
+
+	/* Wait for Software Interface FSM state to be IDLE. */
+	return_value = pwrap_check_idle(&mtk_pwrap->wacs2_sta,
+					PWRAP_WAIT_IDLE_US);
+	if (return_value != 0) {
+		return return_value;
+	}
+
+	/* Set the write data */
+	if (write == 1) {
+		/* Set the write data. */
+		mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_wdata, wdata);
+	}
+
+	/* Send the command. */
+	mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_cmd, (write << 29) | adr);
+
+	if (write == 0) {
+		/*
+		 * Wait for Software Interface FSM state to be WFVLDCLR,
+		 * read the data and clear the valid flag.
+		 */
+		return_value = pwrap_check_vldclr(&mtk_pwrap->wacs2_sta,
+						  PWRAP_READ_US);
+		if (return_value != 0) {
+			return return_value;
+		}
+
+		if (rdata == NULL) {
+			return E_PWR_INVALID_ARG;
+		}
+
+		reg_rdata = mmio_read_32((uintptr_t)&mtk_pwrap->wacs2_rdata);
+		*rdata = reg_rdata;
+		mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_vldclr, 0x1);
+	}
+
+	return return_value;
+}
+
+/* external API for pmic_wrap user */
+int32_t pwrap_read(uint32_t adr, uint32_t *rdata)
+{
+	return pwrap_wacs2(0, adr, 0, rdata, 1);
+}
+
+int32_t pwrap_write(uint32_t adr, uint32_t wdata)
+{
+	return pwrap_wacs2(1, adr, wdata, 0, 1);
+}
diff --git a/plat/mediatek/drivers/rtc/rtc_common.c b/plat/mediatek/drivers/rtc/rtc_common.c
new file mode 100644
index 0000000..4efddff
--- /dev/null
+++ b/plat/mediatek/drivers/rtc/rtc_common.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2019-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+
+#include <pmic_wrap_init.h>
+#include <rtc.h>
+
+/* RTC busy status polling interval and retry count */
+enum {
+	RTC_WRTGR_POLLING_DELAY_MS	= 10,
+	RTC_WRTGR_POLLING_CNT		= 100
+};
+
+uint16_t RTC_Read(uint32_t addr)
+{
+	uint32_t rdata = 0;
+
+	pwrap_read((uint32_t)addr, &rdata);
+	return (uint16_t)rdata;
+}
+
+void RTC_Write(uint32_t addr, uint16_t data)
+{
+	pwrap_write((uint32_t)addr, (uint32_t)data);
+}
+
+int32_t rtc_busy_wait(void)
+{
+	uint64_t retry = RTC_WRTGR_POLLING_CNT;
+
+	do {
+		mdelay(RTC_WRTGR_POLLING_DELAY_MS);
+		if (!(RTC_Read(RTC_BBPU) & RTC_BBPU_CBUSY))
+			return 1;
+		retry--;
+	} while (retry);
+
+	ERROR("[RTC] rtc cbusy time out!\n");
+	return 0;
+}
+
+int32_t RTC_Write_Trigger(void)
+{
+	RTC_Write(RTC_WRTGR, 1);
+	return rtc_busy_wait();
+}
+
+int32_t Writeif_unlock(void)
+{
+	RTC_Write(RTC_PROT, RTC_PROT_UNLOCK1);
+	if (!RTC_Write_Trigger())
+		return 0;
+	RTC_Write(RTC_PROT, RTC_PROT_UNLOCK2);
+	if (!RTC_Write_Trigger())
+		return 0;
+
+	return 1;
+}
+
diff --git a/plat/mediatek/drivers/rtc/rtc_mt6359p.c b/plat/mediatek/drivers/rtc/rtc_mt6359p.c
new file mode 100644
index 0000000..3bf4337
--- /dev/null
+++ b/plat/mediatek/drivers/rtc/rtc_mt6359p.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <rtc.h>
+
+
+static void RTC_Config_Interface(uint32_t addr, uint16_t data,
+			    uint16_t mask, uint16_t shift)
+{
+	uint16_t pmic_reg;
+
+	pmic_reg = RTC_Read(addr);
+
+	pmic_reg &= ~(mask << shift);
+	pmic_reg |= (data << shift);
+
+	RTC_Write(addr, pmic_reg);
+}
+
+static int32_t rtc_disable_2sec_reboot(void)
+{
+	uint16_t reboot;
+
+	reboot = (RTC_Read(RTC_AL_SEC) & ~RTC_BBPU_2SEC_EN) &
+		 ~RTC_BBPU_AUTO_PDN_SEL;
+	RTC_Write(RTC_AL_SEC, reboot);
+
+	return RTC_Write_Trigger();
+}
+
+static int32_t rtc_enable_k_eosc(void)
+{
+	uint16_t alm_dow, alm_sec;
+	int16_t ret;
+
+	/* Turning on eosc cali mode clock */
+	RTC_Config_Interface(PMIC_RG_SCK_TOP_CKPDN_CON0_CLR, 1,
+			PMIC_RG_RTC_EOSC32_CK_PDN_MASK,
+			PMIC_RG_RTC_EOSC32_CK_PDN_SHIFT);
+
+	alm_sec = RTC_Read(RTC_AL_SEC) & (~RTC_LPD_OPT_MASK);
+	RTC_Write(RTC_AL_SEC, alm_sec);
+	ret = RTC_Write_Trigger();
+	if (ret == 0) {
+		return 0;
+	}
+
+	RTC_Write(RTC_CON, RTC_LPD_EN);
+	ret = RTC_Write_Trigger();
+	if (ret == 0) {
+		return 0;
+	}
+
+	RTC_Write(RTC_CON, RTC_LPD_RST);
+	ret = RTC_Write_Trigger();
+	if (ret == 0) {
+		return 0;
+	}
+
+	RTC_Write(RTC_CON, RTC_LPD_EN);
+	ret = RTC_Write_Trigger();
+	if (ret == 0) {
+		return 0;
+	}
+
+	RTC_Write(RTC_POWERKEY1, RTC_POWERKEY1_KEY);
+	RTC_Write(RTC_POWERKEY2, RTC_POWERKEY2_KEY);
+	ret = RTC_Write_Trigger();
+	if (ret == 0) {
+		return 0;
+	}
+
+	/* set RTC EOSC calibration period = 8sec */
+	alm_dow = (RTC_Read(RTC_AL_DOW) & (~RTC_RG_EOSC_CALI_TD_MASK)) |
+		  RTC_RG_EOSC_CALI_TD_8SEC;
+	RTC_Write(RTC_AL_DOW, alm_dow);
+	ret = RTC_Write_Trigger();
+	if (ret == 0) {
+		return 0;
+	}
+
+	RTC_Write(RTC_BBPU,
+		  RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD);
+	ret = RTC_Write_Trigger();
+	if (ret == 0) {
+		return 0;
+	}
+
+	/* Enable K EOSC mode :use solution1 of eosc cali to fix mt6359p 32K*/
+	RTC_Write(RTC_AL_YEA, (((RTC_Read(RTC_AL_YEA) | RTC_K_EOSC_RSV_0)
+				& (~RTC_K_EOSC_RSV_1)) | (RTC_K_EOSC_RSV_2)));
+	ret = RTC_Write_Trigger();
+	if (ret == 0) {
+		return 0;
+	}
+
+	INFO("[RTC] RTC_enable_k_eosc\n");
+
+	return 1;
+}
+
+void rtc_power_off_sequence(void)
+{
+	uint16_t bbpu;
+	int16_t ret;
+
+	ret = rtc_disable_2sec_reboot();
+	if (ret == 0) {
+		return;
+	}
+
+	ret = rtc_enable_k_eosc();
+	if (ret == 0) {
+		return;
+	}
+
+	bbpu = RTC_BBPU_KEY | RTC_BBPU_PWREN;
+
+	if (Writeif_unlock() != 0) {
+		RTC_Write(RTC_BBPU,
+			  bbpu | RTC_BBPU_RESET_ALARM | RTC_BBPU_RESET_SPAR);
+		RTC_Write(RTC_AL_MASK, RTC_AL_MASK_DOW);
+		ret = RTC_Write_Trigger();
+		if (ret == 0) {
+			return;
+		}
+		mdelay(1);
+
+		bbpu = RTC_Read(RTC_BBPU);
+
+		if (((bbpu & RTC_BBPU_RESET_ALARM) > 0) ||
+		    ((bbpu & RTC_BBPU_RESET_SPAR) > 0)) {
+			INFO("[RTC] timeout\n");
+		}
+
+		bbpu = RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD;
+		RTC_Write(RTC_BBPU, bbpu);
+		ret = RTC_Write_Trigger();
+		if (ret == 0) {
+			return;
+		}
+	}
+}
diff --git a/plat/mediatek/drivers/rtc/rtc_mt6359p.h b/plat/mediatek/drivers/rtc/rtc_mt6359p.h
new file mode 100644
index 0000000..199f152
--- /dev/null
+++ b/plat/mediatek/drivers/rtc/rtc_mt6359p.h
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RTC_MT6359P_H
+#define RTC_MT6359P_H
+
+/* RTC registers */
+enum {
+	RTC_BBPU = 0x0588,
+	RTC_IRQ_STA = 0x058A,
+	RTC_IRQ_EN = 0x058C,
+	RTC_CII_EN = 0x058E
+};
+
+enum {
+	RTC_AL_SEC = 0x05A0,
+	RTC_AL_MIN = 0x05A2,
+	RTC_AL_HOU = 0x05A4,
+	RTC_AL_DOM = 0x05A6,
+	RTC_AL_DOW = 0x05A8,
+	RTC_AL_MTH = 0x05AA,
+	RTC_AL_YEA = 0x05AC,
+	RTC_AL_MASK = 0x0590
+};
+
+enum {
+	RTC_OSC32CON = 0x05AE,
+	RTC_CON = 0x05C4,
+	RTC_WRTGR = 0x05C2
+};
+
+enum {
+	RTC_POWERKEY1 = 0x05B0,
+	RTC_POWERKEY2 = 0x05B2
+};
+
+enum {
+	RTC_POWERKEY1_KEY	= 0xA357,
+	RTC_POWERKEY2_KEY	= 0x67D2
+};
+
+enum {
+	RTC_PDN1 = 0x05B4,
+	RTC_PDN2 = 0x05B6,
+	RTC_SPAR0 = 0x05B8,
+	RTC_SPAR1 = 0x05BA,
+	RTC_PROT = 0x05BC,
+	RTC_DIFF = 0x05BE,
+	RTC_CALI = 0x05C0
+};
+
+enum {
+	RTC_OSC32CON_UNLOCK1 = 0x1A57,
+	RTC_OSC32CON_UNLOCK2 = 0x2B68
+};
+
+enum {
+	RTC_LPD_EN = 0x0406,
+	RTC_LPD_RST = 0x040E
+};
+
+enum {
+	RTC_LPD_OPT_XOSC_AND_EOSC_LPD	= 0U << 13,
+	RTC_LPD_OPT_EOSC_LPD		= 1U << 13,
+	RTC_LPD_OPT_XOSC_LPD		= 2U << 13,
+	RTC_LPD_OPT_F32K_CK_ALIVE	= 3U << 13,
+};
+
+#define RTC_LPD_OPT_MASK	(3U << 13)
+
+enum {
+	RTC_PROT_UNLOCK1 = 0x586A,
+	RTC_PROT_UNLOCK2 = 0x9136
+};
+
+enum {
+	RTC_BBPU_PWREN	= 1U << 0,
+	RTC_BBPU_SPAR_SW	= 1U << 1,
+	RTC_BBPU_RESET_SPAR	= 1U << 2,
+	RTC_BBPU_RESET_ALARM	= 1U << 3,
+	RTC_BBPU_CLRPKY	= 1U << 4,
+	RTC_BBPU_RELOAD	= 1U << 5,
+	RTC_BBPU_CBUSY	= 1U << 6
+};
+
+enum {
+	RTC_AL_MASK_SEC = 1U << 0,
+	RTC_AL_MASK_MIN = 1U << 1,
+	RTC_AL_MASK_HOU = 1U << 2,
+	RTC_AL_MASK_DOM = 1U << 3,
+	RTC_AL_MASK_DOW = 1U << 4,
+	RTC_AL_MASK_MTH = 1U << 5,
+	RTC_AL_MASK_YEA = 1U << 6
+};
+
+enum {
+	RTC_BBPU_AUTO_PDN_SEL = 1U << 6,
+	RTC_BBPU_2SEC_CK_SEL = 1U << 7,
+	RTC_BBPU_2SEC_EN = 1U << 8,
+	RTC_BBPU_2SEC_MODE = 0x3 << 9,
+	RTC_BBPU_2SEC_STAT_CLEAR = 1U << 11,
+	RTC_BBPU_2SEC_STAT_STA = 1U << 12
+};
+
+enum {
+	RTC_BBPU_KEY	= 0x43 << 8
+};
+
+enum {
+	RTC_EMBCK_SRC_SEL	= 1 << 8,
+	RTC_EMBCK_SEL_MODE	= 3 << 6,
+	RTC_XOSC32_ENB		= 1 << 5,
+	RTC_REG_XOSC32_ENB	= 1 << 15
+};
+
+enum {
+	RTC_K_EOSC_RSV_0	= 1 << 8,
+	RTC_K_EOSC_RSV_1	= 1 << 9,
+	RTC_K_EOSC_RSV_2	= 1 << 10
+};
+
+enum {
+	RTC_RG_EOSC_CALI_TD_1SEC	= 3 << 5,
+	RTC_RG_EOSC_CALI_TD_2SEC	= 4 << 5,
+	RTC_RG_EOSC_CALI_TD_4SEC	= 5 << 5,
+	RTC_RG_EOSC_CALI_TD_8SEC	= 6 << 5,
+	RTC_RG_EOSC_CALI_TD_16SEC	= 7 << 5,
+	RTC_RG_EOSC_CALI_TD_MASK	= 7 << 5
+};
+
+/* PMIC TOP Register Definition */
+enum {
+	PMIC_RG_TOP_CON = 0x0020,
+	PMIC_RG_TOP_CKPDN_CON1 = 0x0112,
+	PMIC_RG_TOP_CKPDN_CON1_SET = 0x0114,
+	PMIC_RG_TOP_CKPDN_CON1_CLR = 0x0116,
+	PMIC_RG_TOP_CKSEL_CON0 = 0x0118,
+	PMIC_RG_TOP_CKSEL_CON0_SET = 0x011A,
+	PMIC_RG_TOP_CKSEL_CON0_CLR = 0x011C
+};
+
+/* PMIC SCK Register Definition */
+enum {
+	PMIC_RG_SCK_TOP_CKPDN_CON0 = 0x0514,
+	PMIC_RG_SCK_TOP_CKPDN_CON0_SET = 0x0516,
+	PMIC_RG_SCK_TOP_CKPDN_CON0_CLR = 0x0518,
+	PMIC_RG_EOSC_CALI_CON0 = 0x53A
+};
+
+enum {
+	PMIC_EOSC_CALI_START_ADDR = 0x53A
+};
+
+enum {
+	PMIC_EOSC_CALI_START_MASK = 0x1,
+	PMIC_EOSC_CALI_START_SHIFT = 0
+};
+
+/* PMIC DCXO Register Definition */
+enum {
+	PMIC_RG_DCXO_CW00 = 0x0788,
+	PMIC_RG_DCXO_CW02 = 0x0790,
+	PMIC_RG_DCXO_CW08 = 0x079C,
+	PMIC_RG_DCXO_CW09 = 0x079E,
+	PMIC_RG_DCXO_CW09_CLR = 0x07A2,
+	PMIC_RG_DCXO_CW10 = 0x07A4,
+	PMIC_RG_DCXO_CW12 = 0x07A8,
+	PMIC_RG_DCXO_CW13 = 0x07AA,
+	PMIC_RG_DCXO_CW15 = 0x07AE,
+	PMIC_RG_DCXO_CW19 = 0x07B6,
+};
+
+enum {
+	PMIC_RG_SRCLKEN_IN0_HW_MODE_MASK = 0x1,
+	PMIC_RG_SRCLKEN_IN0_HW_MODE_SHIFT = 1,
+	PMIC_RG_SRCLKEN_IN1_HW_MODE_MASK = 0x1,
+	PMIC_RG_SRCLKEN_IN1_HW_MODE_SHIFT = 3,
+	PMIC_RG_RTC_EOSC32_CK_PDN_MASK = 0x1,
+	PMIC_RG_RTC_EOSC32_CK_PDN_SHIFT = 2,
+	PMIC_RG_EOSC_CALI_TD_MASK = 0x7,
+	PMIC_RG_EOSC_CALI_TD_SHIFT = 5,
+	PMIC_RG_XO_EN32K_MAN_MASK = 0x1,
+	PMIC_RG_XO_EN32K_MAN_SHIFT = 0
+};
+
+/* external API */
+uint16_t RTC_Read(uint32_t addr);
+void RTC_Write(uint32_t addr, uint16_t data);
+int32_t rtc_busy_wait(void);
+int32_t RTC_Write_Trigger(void);
+int32_t Writeif_unlock(void);
+void rtc_power_off_sequence(void);
+
+#endif /* RTC_MT6359P_H */
diff --git a/plat/mediatek/drivers/timer/mt_timer.c b/plat/mediatek/drivers/timer/mt_timer.c
new file mode 100644
index 0000000..ca4528a
--- /dev/null
+++ b/plat/mediatek/drivers/timer/mt_timer.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <lib/mmio.h>
+#include <mt_timer.h>
+#include <platform_def.h>
+
+
+uint64_t normal_time_base;
+uint64_t atf_time_base;
+
+void sched_clock_init(uint64_t normal_base, uint64_t atf_base)
+{
+	normal_time_base += normal_base;
+	atf_time_base = atf_base;
+}
+
+uint64_t sched_clock(void)
+{
+	uint64_t cval;
+	uint64_t rel_base;
+
+	rel_base = read_cntpct_el0() - atf_time_base;
+	cval = ((rel_base * 1000U) / SYS_COUNTER_FREQ_IN_MHZ)
+		- normal_time_base;
+	return cval;
+}
+
+void mt_systimer_init(void)
+{
+	/* Enable access in NS mode */
+	mmio_write_32(CNTWACR_REG, CNT_WRITE_ACCESS_CTL_MASK);
+	mmio_write_32(CNTRACR_REG, CNT_READ_ACCESS_CTL_MASK);
+}
diff --git a/plat/mediatek/drivers/timer/mt_timer.h b/plat/mediatek/drivers/timer/mt_timer.h
new file mode 100644
index 0000000..71dbeff
--- /dev/null
+++ b/plat/mediatek/drivers/timer/mt_timer.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_TIMER_H
+#define MT_TIMER_H
+
+#define SYSTIMER_BASE       (0x10017000)
+#define CNTCR_REG           (SYSTIMER_BASE + 0x0)
+#define CNTSR_REG           (SYSTIMER_BASE + 0x4)
+#define CNTSYS_L_REG        (SYSTIMER_BASE + 0x8)
+#define CNTSYS_H_REG        (SYSTIMER_BASE + 0xc)
+#define CNTWACR_REG         (SYSTIMER_BASE + 0x10)
+#define CNTRACR_REG         (SYSTIMER_BASE + 0x14)
+
+#define TIEO_EN             (1 << 3)
+#define COMP_15_EN          (1 << 10)
+#define COMP_20_EN          (1 << 11)
+#define COMP_25_EN          (1 << 12)
+
+#define COMP_FEATURE_MASK (COMP_15_EN | COMP_20_EN | COMP_25_EN | TIEO_EN)
+#define COMP_15_MASK (COMP_15_EN)
+#define COMP_20_MASK (COMP_20_EN | TIEO_EN)
+#define COMP_25_MASK (COMP_20_EN | COMP_25_EN)
+
+#define CNT_WRITE_ACCESS_CTL_MASK (0x3FFFFF0U)
+#define CNT_READ_ACCESS_CTL_MASK  (0x3FFFFFFU)
+
+void sched_clock_init(uint64_t normal_base, uint64_t atf_base);
+uint64_t sched_clock(void);
+void mt_systimer_init(void);
+
+#endif /* MT_TIMER_H */
diff --git a/plat/mediatek/drivers/uart/8250_console.S b/plat/mediatek/drivers/uart/8250_console.S
new file mode 100644
index 0000000..66f998d
--- /dev/null
+++ b/plat/mediatek/drivers/uart/8250_console.S
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <asm_macros.S>
+#include <uart8250.h>
+
+	.globl	console_core_init
+	.globl	console_core_putc
+	.globl	console_core_getc
+	.globl	console_core_flush
+
+	/* -----------------------------------------------
+	 * int console_core_init(unsigned long base_addr,
+	 * unsigned int uart_clk, unsigned int baud_rate)
+	 * Function to initialize the console without a
+	 * C Runtime to print debug information. This
+	 * function will be accessed by console_init and
+	 * crash reporting.
+	 * In: x0 - console base address
+	 *     w1 - Uart clock in Hz
+	 *     w2 - Baud rate
+	 * Out: return 1 on success else 0 on error
+	 * Clobber list : x1, x2, x3
+	 * -----------------------------------------------
+	 */
+func console_core_init
+	/* Check the input base address */
+	cbz	x0, core_init_fail
+	/* Check baud rate and uart clock for sanity */
+	cbz	w1, core_init_fail
+	cbz	w2, core_init_fail
+
+	/* Disable interrupt */
+	str	wzr, [x0, #UART_IER]
+
+	/* Force DTR and RTS to high */
+	mov	w3, #(UART_MCR_DTR | UART_MCR_RTS)
+	str	w3, [x0, #UART_MCR]
+
+	/* Check high speed */
+	movz	w3, #:abs_g1:115200
+	movk	w3, #:abs_g0_nc:115200
+	cmp	w2, w3
+	b.hi	1f
+
+	/* Non high speed */
+	lsl	w2, w2, #4
+	mov	w3, wzr
+	b	2f
+
+	/* High speed */
+1:	lsl	w2, w2, #2
+	mov	w3, #2
+
+	/* Set high speed UART register */
+2:	str	w3, [x0, #UART_HIGHSPEED]
+
+	/* Calculate divisor */
+	udiv	w3, w1, w2	/* divisor = uartclk / (quot * baudrate) */
+	msub	w1, w3, w2, w1	/* remainder = uartclk % (quot * baudrate) */
+	lsr	w2, w2, #1
+	cmp	w1, w2
+	cinc	w3, w3, hs
+
+	/* Set line configuration, access divisor latches */
+	mov	w1, #(UART_LCR_DLAB | UART_LCR_WLS_8)
+	str	w1, [x0, #UART_LCR]
+
+	/* Set the divisor */
+	and	w1, w3, #0xff
+	str	w1, [x0, #UART_DLL]
+	lsr	w1, w3, #8
+	and	w1, w1, #0xff
+	str	w1, [x0, #UART_DLH]
+
+	/* Hide the divisor latches */
+	mov	w1, #UART_LCR_WLS_8
+	str	w1, [x0, #UART_LCR]
+
+	/* Enable FIFOs, and clear receive and transmit */
+	mov	w1, #(UART_FCR_FIFO_EN | UART_FCR_CLEAR_RCVR |	\
+			UART_FCR_CLEAR_XMIT)
+	str	w1, [x0, #UART_FCR]
+
+	mov	w0, #1
+	ret
+core_init_fail:
+	mov	w0, wzr
+	ret
+endfunc console_core_init
+
+	/* --------------------------------------------------------
+	 * int console_core_putc(int c, unsigned long base_addr)
+	 * Function to output a character over the console. It
+	 * returns the character printed on success or -1 on error.
+	 * In : w0 - character to be printed
+	 *      x1 - console base address
+	 * Out : return -1 on error else return character.
+	 * Clobber list : x2
+	 * --------------------------------------------------------
+	 */
+func console_core_putc
+	/* Check the input parameter */
+	cbz	x1, putc_error
+	/* Prepend '\r' to '\n' */
+	cmp	w0, #0xA
+	b.ne	2f
+
+	/* Check if the transmit FIFO is full */
+1:	ldr	w2, [x1, #UART_LSR]
+	and	w2, w2, #UART_LSR_THRE
+	cbz	w2, 1b
+	mov	w2, #0xD
+	str	w2, [x1, #UART_THR]
+
+	/* Check if the transmit FIFO is full */
+2:	ldr	w2, [x1, #UART_LSR]
+	and	w2, w2, #UART_LSR_THRE
+	cbz	w2, 2b
+	str	w0, [x1, #UART_THR]
+	ret
+putc_error:
+	mov	w0, #-1
+	ret
+endfunc console_core_putc
+
+	/* ---------------------------------------------
+	 * int console_core_getc(unsigned long base_addr)
+	 * Function to get a character from the console.
+	 * It returns the character grabbed on success
+	 * or -1 on error.
+	 * In : x0 - console base address
+	 * Clobber list : x0, x1
+	 * ---------------------------------------------
+	 */
+func console_core_getc
+	cbz	x0, getc_error
+
+	/* Check if the receive FIFO is empty */
+1:	ldr	w1, [x0, #UART_LSR]
+	tbz	w1, #UART_LSR_DR, 1b
+	ldr	w0, [x0, #UART_RBR]
+	ret
+getc_error:
+	mov	w0, #-1
+	ret
+endfunc console_core_getc
+
+	/* ---------------------------------------------
+	 * void console_core_flush(uintptr_t base_addr)
+	 * Function to force a write of all buffered
+	 * data that hasn't been output.
+	 * In : x0 - console base address
+	 * Out : void.
+	 * Clobber list : x0, x1
+	 * ---------------------------------------------
+	 */
+func console_core_flush
+	/* Placeholder */
+	ret
+endfunc console_core_flush
diff --git a/plat/mediatek/drivers/uart/uart.c b/plat/mediatek/drivers/uart/uart.c
new file mode 100644
index 0000000..fdaa793
--- /dev/null
+++ b/plat/mediatek/drivers/uart/uart.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/mmio.h>
+#include <uart.h>
+
+static struct mt_uart uart_save_addr[DRV_SUPPORT_UART_PORTS];
+
+static const uint32_t uart_base_addr[DRV_SUPPORT_UART_PORTS] = {
+	UART0_BASE,
+	UART1_BASE
+};
+
+void mt_uart_restore(void)
+{
+	int uart_idx = UART_PORT0;
+	struct mt_uart *uart;
+	unsigned long base;
+
+	/* Must NOT print any debug log before UART restore */
+	for (uart_idx = UART_PORT0; uart_idx < HW_SUPPORT_UART_PORTS;
+	     uart_idx++) {
+
+		uart = &uart_save_addr[uart_idx];
+		base = uart->base;
+
+		mmio_write_32(UART_LCR(base), UART_LCR_MODE_B);
+		mmio_write_32(UART_EFR(base), uart->registers.efr);
+		mmio_write_32(UART_LCR(base), uart->registers.lcr);
+		mmio_write_32(UART_FCR(base), uart->registers.fcr);
+
+		/* baudrate */
+		mmio_write_32(UART_HIGHSPEED(base), uart->registers.highspeed);
+		mmio_write_32(UART_FRACDIV_L(base), uart->registers.fracdiv_l);
+		mmio_write_32(UART_FRACDIV_M(base), uart->registers.fracdiv_m);
+		mmio_write_32(UART_LCR(base),
+			      uart->registers.lcr | UART_LCR_DLAB);
+		mmio_write_32(UART_DLL(base), uart->registers.dll);
+		mmio_write_32(UART_DLH(base), uart->registers.dlh);
+		mmio_write_32(UART_LCR(base), uart->registers.lcr);
+		mmio_write_32(UART_SAMPLE_COUNT(base),
+			      uart->registers.sample_count);
+		mmio_write_32(UART_SAMPLE_POINT(base),
+			      uart->registers.sample_point);
+		mmio_write_32(UART_GUARD(base), uart->registers.guard);
+
+		/* flow control */
+		mmio_write_32(UART_ESCAPE_EN(base), uart->registers.escape_en);
+		mmio_write_32(UART_MCR(base), uart->registers.mcr);
+		mmio_write_32(UART_IER(base), uart->registers.ier);
+		mmio_write_32(UART_SCR(base), uart->registers.scr);
+	}
+}
+
+void mt_uart_save(void)
+{
+	int uart_idx = UART_PORT0;
+	struct mt_uart *uart;
+	unsigned long base;
+
+	for (uart_idx = UART_PORT0; uart_idx < HW_SUPPORT_UART_PORTS;
+	     uart_idx++) {
+
+		uart_save_addr[uart_idx].base = uart_base_addr[uart_idx];
+		base = uart_base_addr[uart_idx];
+		uart = &uart_save_addr[uart_idx];
+		uart->registers.lcr = mmio_read_32(UART_LCR(base));
+
+		mmio_write_32(UART_LCR(base), UART_LCR_MODE_B);
+		uart->registers.efr = mmio_read_32(UART_EFR(base));
+		mmio_write_32(UART_LCR(base), uart->registers.lcr);
+		uart->registers.fcr = mmio_read_32(UART_FCR_RD(base));
+
+		/* baudrate */
+		uart->registers.highspeed = mmio_read_32(UART_HIGHSPEED(base));
+		uart->registers.fracdiv_l = mmio_read_32(UART_FRACDIV_L(base));
+		uart->registers.fracdiv_m = mmio_read_32(UART_FRACDIV_M(base));
+		mmio_write_32(UART_LCR(base),
+			      uart->registers.lcr | UART_LCR_DLAB);
+		uart->registers.dll = mmio_read_32(UART_DLL(base));
+		uart->registers.dlh = mmio_read_32(UART_DLH(base));
+		mmio_write_32(UART_LCR(base), uart->registers.lcr);
+		uart->registers.sample_count = mmio_read_32(
+						UART_SAMPLE_COUNT(base));
+		uart->registers.sample_point = mmio_read_32(
+						UART_SAMPLE_POINT(base));
+		uart->registers.guard = mmio_read_32(UART_GUARD(base));
+
+		/* flow control */
+		uart->registers.escape_en = mmio_read_32(UART_ESCAPE_EN(base));
+		uart->registers.mcr = mmio_read_32(UART_MCR(base));
+		uart->registers.ier = mmio_read_32(UART_IER(base));
+		uart->registers.scr = mmio_read_32(UART_SCR(base));
+	}
+}
+
+void mt_console_uart_cg(int on)
+{
+	if (on == 1) {
+		mmio_write_32(UART_CLOCK_GATE_CLR, UART0_CLOCK_GATE_BIT);
+	} else {
+		mmio_write_32(UART_CLOCK_GATE_SET, UART0_CLOCK_GATE_BIT);
+	}
+}
+
+uint32_t mt_console_uart_cg_status(void)
+{
+	return mmio_read_32(UART_CLOCK_GATE_STA) & UART0_CLOCK_GATE_BIT;
+}
diff --git a/plat/mediatek/drivers/uart/uart.h b/plat/mediatek/drivers/uart/uart.h
new file mode 100644
index 0000000..2ca74fa
--- /dev/null
+++ b/plat/mediatek/drivers/uart/uart.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef UART_H
+#define UART_H
+
+#include <platform_def.h>
+
+/* UART HW information */
+#define HW_SUPPORT_UART_PORTS	2
+#define DRV_SUPPORT_UART_PORTS	2
+
+/* console UART clock cg */
+#define UART_CLOCK_GATE_SET		(INFRACFG_AO_BASE + 0x80)
+#define UART_CLOCK_GATE_CLR		(INFRACFG_AO_BASE + 0x84)
+#define UART_CLOCK_GATE_STA		(INFRACFG_AO_BASE + 0x90)
+#define UART0_CLOCK_GATE_BIT		(1U<<22)
+#define UART1_CLOCK_GATE_BIT		(1U<<23)
+
+/* UART registers */
+#define UART_RBR(_baseaddr)			(_baseaddr + 0x0)
+#define UART_THR(_baseaddr)			(_baseaddr + 0x0)
+#define UART_IER(_baseaddr)			(_baseaddr + 0x4)
+#define UART_IIR(_baseaddr)			(_baseaddr + 0x8)
+#define UART_FCR(_baseaddr)			(_baseaddr + 0x8)
+#define UART_LCR(_baseaddr)			(_baseaddr + 0xc)
+#define UART_MCR(_baseaddr)			(_baseaddr + 0x10)
+#define UART_LSR(_baseaddr)			(_baseaddr + 0x14)
+#define UART_MSR(_baseaddr)			(_baseaddr + 0x18)
+#define UART_SCR(_baseaddr)			(_baseaddr + 0x1c)
+#define UART_DLL(_baseaddr)			(_baseaddr + 0x0)
+#define UART_DLH(_baseaddr)			(_baseaddr + 0x4)
+#define UART_EFR(_baseaddr)			(_baseaddr + 0x8)
+#define UART_XON1(_baseaddr)			(_baseaddr + 0x10)
+#define UART_XON2(_baseaddr)			(_baseaddr + 0x14)
+#define UART_XOFF1(_baseaddr)			(_baseaddr + 0x18)
+#define UART_XOFF2(_baseaddr)			(_baseaddr + 0x1c)
+#define UART_AUTOBAUD(_baseaddr)		(_baseaddr + 0x20)
+#define UART_HIGHSPEED(_baseaddr)		(_baseaddr + 0x24)
+#define UART_SAMPLE_COUNT(_baseaddr)		(_baseaddr + 0x28)
+#define UART_SAMPLE_POINT(_baseaddr)		(_baseaddr + 0x2c)
+#define UART_AUTOBAUD_REG(_baseaddr)		(_baseaddr + 0x30)
+#define UART_RATE_FIX_REG(_baseaddr)		(_baseaddr + 0x34)
+#define UART_AUTO_BAUDSAMPLE(_baseaddr)		(_baseaddr + 0x38)
+#define UART_GUARD(_baseaddr)			(_baseaddr + 0x3c)
+#define UART_ESCAPE_DAT(_baseaddr)		(_baseaddr + 0x40)
+#define UART_ESCAPE_EN(_baseaddr)		(_baseaddr + 0x44)
+#define UART_SLEEP_EN(_baseaddr)		(_baseaddr + 0x48)
+#define UART_DMA_EN(_baseaddr)			(_baseaddr + 0x4c)
+#define UART_RXTRI_AD(_baseaddr)		(_baseaddr + 0x50)
+#define UART_FRACDIV_L(_baseaddr)		(_baseaddr + 0x54)
+#define UART_FRACDIV_M(_baseaddr)		(_baseaddr + 0x58)
+#define UART_FCR_RD(_baseaddr)			(_baseaddr + 0x5C)
+#define UART_USB_RX_SEL(_baseaddr)		(_baseaddr + 0xB0)
+#define UART_SLEEP_REQ(_baseaddr)		(_baseaddr + 0xB4)
+#define UART_SLEEP_ACK(_baseaddr)		(_baseaddr + 0xB8)
+#define UART_SPM_SEL(_baseaddr)			(_baseaddr + 0xBC)
+#define UART_LCR_DLAB				0x0080
+#define UART_LCR_MODE_B				0x00bf
+
+enum uart_port_ID {
+	UART_PORT0 = 0,
+	UART_PORT1
+};
+
+struct mt_uart_register {
+	uint32_t dll;
+	uint32_t dlh;
+	uint32_t ier;
+	uint32_t lcr;
+	uint32_t mcr;
+	uint32_t fcr;
+	uint32_t lsr;
+	uint32_t scr;
+	uint32_t efr;
+	uint32_t highspeed;
+	uint32_t sample_count;
+	uint32_t sample_point;
+	uint32_t fracdiv_l;
+	uint32_t fracdiv_m;
+	uint32_t escape_en;
+	uint32_t guard;
+	uint32_t rx_sel;
+};
+
+struct mt_uart {
+	unsigned long base;
+	struct mt_uart_register registers;
+};
+
+/* external API */
+void mt_uart_save(void);
+void mt_uart_restore(void);
+void mt_console_uart_cg(int on);
+uint32_t mt_console_uart_cg_status(void);
+
+#endif /* __UART_H__ */
diff --git a/plat/mediatek/drivers/uart/uart8250.h b/plat/mediatek/drivers/uart/uart8250.h
new file mode 100644
index 0000000..f0541d6
--- /dev/null
+++ b/plat/mediatek/drivers/uart/uart8250.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef UART8250_H
+#define UART8250_H
+
+/* UART register */
+#define UART_RBR		0x00	/* Receive buffer register */
+#define UART_DLL		0x00	/* Divisor latch lsb */
+#define UART_THR		0x00	/* Transmit holding register */
+#define UART_DLH		0x04	/* Divisor latch msb */
+#define UART_IER		0x04	/* Interrupt enable register */
+#define UART_FCR		0x08	/* FIFO control register */
+#define UART_LCR		0x0c	/* Line control register */
+#define UART_MCR		0x10	/* Modem control register */
+#define UART_LSR		0x14	/* Line status register */
+#define UART_HIGHSPEED		0x24	/* High speed UART */
+
+/* FCR */
+#define UART_FCR_FIFO_EN	0x01	/* enable FIFO */
+#define UART_FCR_CLEAR_RCVR	0x02	/* clear the RCVR FIFO */
+#define UART_FCR_CLEAR_XMIT	0x04	/* clear the XMIT FIFO */
+
+/* LCR */
+#define UART_LCR_WLS_8		0x03	/* 8 bit character length */
+#define UART_LCR_DLAB		0x80	/* divisor latch access bit */
+
+/* MCR */
+#define UART_MCR_DTR		0x01
+#define UART_MCR_RTS		0x02
+
+/* LSR */
+#define UART_LSR_DR		0x01	/* Data ready */
+#define UART_LSR_THRE		0x20	/* Xmit holding register empty */
+
+#endif /* UART8250_H */