Merge changes from topics "mtk_cold_boot", "mtk_init_scheme", "smc_registration_use_case", "vendor_extend_pubsub_event" into integration

* changes:
  feat(mediatek): implement generic platform port
  refactor(mediatek): smc registration services
  feat(mediatek): introduce mtk init framework
  refactor(mediatek): partition MTK SiP SMC ID
  feat(mediatek): extend SiP vendor subscription events
diff --git a/plat/mediatek/build_helpers/mtk_build_helpers.mk b/plat/mediatek/build_helpers/mtk_build_helpers.mk
index 47d96fa..a5a4c3e 100644
--- a/plat/mediatek/build_helpers/mtk_build_helpers.mk
+++ b/plat/mediatek/build_helpers/mtk_build_helpers.mk
@@ -125,11 +125,10 @@
 MTK_COND_EVAL := $(MTK_PLAT)/build_helpers/conditional_eval_options.mk
 
 # Indicate which BL should be built in command line
-ifeq (${NEED_BL31},yes)
-MTK_BL := bl31
-endif
 ifeq (${NEED_BL32},yes)
 MTK_BL := bl32
+else
+MTK_BL := bl31
 endif
 # Include common, platform, board level config
 include $(MTK_COMMON_CFG)
diff --git a/plat/mediatek/build_helpers/options.mk b/plat/mediatek/build_helpers/options.mk
index 394a605..eb579e5 100644
--- a/plat/mediatek/build_helpers/options.mk
+++ b/plat/mediatek/build_helpers/options.mk
@@ -6,7 +6,7 @@
 
 # call add_defined_option to evaluate MTK defined value
 $(eval $(call add_defined_option,MTK_SIP_KERNEL_BOOT_ENABLE))
-$(eval $(call add_defined_option,PLAT_EXTRA_LD_SCRIPT))
+$(eval $(call add_defined_option,PLAT_EXTRA_RODATA_INCLUDES))
 $(eval $(call add_defined_option,MTK_EXTRA_LINKERFILE))
 $(eval $(call add_defined_option,MTK_BL31_AS_BL2))
 $(eval $(call add_defined_option,MTK_BL33_IS_64BIT))
diff --git a/plat/mediatek/common/cold_boot.c b/plat/mediatek/common/cold_boot.c
new file mode 100644
index 0000000..ff585fe
--- /dev/null
+++ b/plat/mediatek/common/cold_boot.c
@@ -0,0 +1,336 @@
+/*
+ * Copyright (c) 2022, Mediatek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <lib/el3_runtime/context_mgmt.h>
+
+/* Vendors headers */
+#include <cold_boot.h>
+#include <lib/mtk_init/mtk_init.h>
+#include <mtk_sip_svc.h>
+
+static struct kernel_info k_info;
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+static bool el1_is_2nd_bootloader = true;
+static struct atf_arg_t atfarg;
+
+static int init_mtk_bl32_arg(void)
+{
+	struct mtk_bl_param_t *p_mtk_bl_param;
+	struct atf_arg_t *p_atfarg;
+
+	p_mtk_bl_param = (struct mtk_bl_param_t *) get_mtk_bl31_fw_config(BOOT_ARG_FROM_BL2);
+	if (p_mtk_bl_param == NULL) {
+		ERROR("p_mtk_bl_param is NULL!\n");
+		return -1;
+	}
+	p_atfarg = (struct atf_arg_t *)p_mtk_bl_param->atf_arg_addr;
+	if (p_atfarg == NULL) {
+		ERROR("bl32 argument is NULL!\n");
+		return -1;
+	}
+	memcpy((void *)&atfarg, (void *)p_atfarg, sizeof(struct atf_arg_t));
+	return 0;
+}
+MTK_EARLY_PLAT_INIT(init_mtk_bl32_arg);
+
+static void save_kernel_info(uint64_t pc, uint64_t r0, uint64_t r1, uint64_t k32_64)
+{
+	k_info.k32_64 = k32_64;
+	k_info.pc = pc;
+
+	if (k32_64 == LINUX_KERNEL_32) {
+		/* for 32 bits kernel */
+		k_info.r0 = 0;
+		/* machtype */
+		k_info.r1 = r0;
+		/* tags */
+		k_info.r2 = r1;
+	} else {
+		/* for 64 bits kernel */
+		k_info.r0 = r0;
+		k_info.r1 = r1;
+	}
+}
+
+static uint32_t plat_get_spsr_for_bl32_64_entry(void)
+{
+	return SPSR_64(MODE_EL1, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+}
+
+#if MTK_BL33_IS_64BIT
+static uint32_t plat_get_spsr_for_bl33_entry(void)
+{
+	uint32_t spsr;
+	uint32_t mode;
+
+	mode = MODE_EL1;
+	spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+	return spsr;
+}
+#else
+static uint32_t plat_get_spsr_for_bl33_entry(void)
+{
+	unsigned int mode;
+	uint32_t spsr;
+	unsigned int ee;
+	unsigned long daif;
+
+	INFO("Secondary bootloader is AArch32\n");
+	mode = MODE32_svc;
+	ee = 0;
+	/*
+	 * TODO: Choose async. exception bits if HYP mode is not
+	 * implemented according to the values of SCR.{AW, FW} bits
+	 */
+	daif = DAIF_ABT_BIT | DAIF_IRQ_BIT | DAIF_FIQ_BIT;
+
+	spsr = SPSR_MODE32(mode, 0, ee, daif);
+	return spsr;
+}
+#endif
+
+static void populate_bl32_image_ep(entry_point_info_t *bl32_ep_instance,
+		struct mtk_bl_param_t *p_mtk_bl_param)
+{
+	entry_point_info_t *populated_ep_bl32 = bl32_ep_instance;
+
+	if (p_mtk_bl_param == NULL) {
+		ERROR("p_mtk_bl_param is NULL!\n");
+		panic();
+	}
+	SET_SECURITY_STATE(bl32_ep_instance->h.attr, SECURE);
+	SET_PARAM_HEAD(populated_ep_bl32,
+		       PARAM_EP,
+		       VERSION_1,
+		       populated_ep_bl32->h.attr);
+	populated_ep_bl32->pc = atfarg.tee_entry;
+	populated_ep_bl32->spsr = plat_get_spsr_for_bl32_64_entry();
+}
+
+static void populate_bl33_image_ep(entry_point_info_t *bl33_ep_instance,
+		struct mtk_bl_param_t *p_mtk_bl_param)
+{
+	entry_point_info_t *populated_ep_bl33 = bl33_ep_instance;
+
+	if (p_mtk_bl_param == NULL) {
+		ERROR("p_mtk_bl_param is NULL!\n");
+		panic();
+	}
+	SET_SECURITY_STATE(bl33_ep_instance->h.attr, NON_SECURE);
+	SET_PARAM_HEAD(populated_ep_bl33,
+		       PARAM_EP,
+		       VERSION_1,
+		       populated_ep_bl33->h.attr);
+	populated_ep_bl33->pc = p_mtk_bl_param->bl33_start_addr;
+	/* standardize 2nd bootloader input argument */
+	populated_ep_bl33->args.arg0 = p_mtk_bl_param->bootarg_loc;
+	/* compatible to old GZ version */
+	populated_ep_bl33->args.arg4 = p_mtk_bl_param->bootarg_loc;
+	populated_ep_bl33->args.arg5 = p_mtk_bl_param->bootarg_size;
+	populated_ep_bl33->spsr = plat_get_spsr_for_bl33_entry();
+}
+
+static int populate_bl_images_ep(struct mtk_bl_param_t *p_mtk_bl_param)
+{
+	/*
+	 * Tell BL31 where the non-trusted software image
+	 * is located and the entry state information
+	 */
+	populate_bl33_image_ep(&bl33_image_ep_info, p_mtk_bl_param);
+	populate_bl32_image_ep(&bl32_image_ep_info, p_mtk_bl_param);
+	return 0;
+}
+
+static int populate_bl_images_ep_init(void)
+{
+	return populate_bl_images_ep(get_mtk_bl31_fw_config(BOOT_ARG_FROM_BL2));
+}
+MTK_PLAT_SETUP_0_INIT(populate_bl_images_ep_init);
+
+static entry_point_info_t *bl31_plat_get_next_kernel64_ep_info(void)
+{
+	entry_point_info_t *next_image_info;
+	unsigned long el_status;
+	unsigned int mode;
+
+	el_status = 0;
+	mode = 0;
+
+	/* Kernel image is always non-secured */
+	next_image_info = &bl33_image_ep_info;
+
+	/* Figure out what mode we enter the non-secure world in */
+	el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT;
+	el_status &= ID_AA64PFR0_ELX_MASK;
+
+	INFO("Kernel_EL %d\n", el_status?2:1);
+	if (el_status) {
+		mode = MODE_EL2;
+	} else {
+		mode = MODE_EL1;
+	}
+	INFO("Kernel is 64Bit\n");
+	next_image_info->spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+	next_image_info->pc = k_info.pc;
+	next_image_info->args.arg0 = k_info.r0;
+	next_image_info->args.arg1 = k_info.r1;
+
+	INFO("pc=0x%lx, r0=0x%" PRIx64 ", r1=0x%" PRIx64 "\n",
+	     next_image_info->pc,
+	     next_image_info->args.arg0,
+	     next_image_info->args.arg1);
+
+	SET_SECURITY_STATE(next_image_info->h.attr, NON_SECURE);
+
+	/* None of the images on this platform can have 0x0 as the entrypoint */
+	if (next_image_info->pc) {
+		return next_image_info;
+	}
+
+	return NULL;
+}
+
+static entry_point_info_t *bl31_plat_get_next_kernel32_ep_info(void)
+{
+	entry_point_info_t *next_image_info;
+	unsigned int mode;
+
+	mode = 0;
+
+	/* Kernel image is always non-secured */
+	next_image_info = &bl33_image_ep_info;
+
+	/* Figure out what mode we enter the non-secure world in */
+	mode = MODE32_hyp;
+	/*
+	 * TODO: Consider the possibility of specifying the SPSR in
+	 * the FIP ToC and allowing the platform to have a say as
+	 * well.
+	 */
+
+	INFO("Kernel is 32Bit\n");
+	next_image_info->spsr = SPSR_MODE32(mode, SPSR_T_ARM, SPSR_E_LITTLE,
+					    (DAIF_FIQ_BIT | DAIF_IRQ_BIT | DAIF_ABT_BIT));
+	next_image_info->pc = k_info.pc;
+	next_image_info->args.arg0 = k_info.r0;
+	next_image_info->args.arg1 = k_info.r1;
+	next_image_info->args.arg2 = k_info.r2;
+
+	INFO("pc=0x%lx, r0=0x%" PRIx64 ", r1=0x%" PRIx64 ", r2=0x%" PRIx64 "\n",
+	     next_image_info->pc,
+	     next_image_info->args.arg0,
+	     next_image_info->args.arg1,
+	     next_image_info->args.arg2);
+
+	SET_SECURITY_STATE(next_image_info->h.attr, NON_SECURE);
+
+	/* None of the images on this platform can have 0x0 as the entrypoint */
+	if (next_image_info->pc) {
+		return next_image_info;
+	}
+
+	return NULL;
+}
+
+static void bl31_prepare_kernel_entry(uint64_t k32_64)
+{
+	entry_point_info_t *next_image_info = NULL;
+	uint32_t image_type;
+
+	/* Determine which image to execute next */
+	image_type = NON_SECURE; /* bl31_get_next_image_type(); */
+
+	/* Leave 2nd bootloader then jump to kernel */
+	el1_is_2nd_bootloader = false;
+
+	/* Program EL3 registers to enable entry into the next EL */
+	if (k32_64 == LINUX_KERNEL_32) {
+		next_image_info = bl31_plat_get_next_kernel32_ep_info();
+	} else {
+		next_image_info = bl31_plat_get_next_kernel64_ep_info();
+	}
+
+	assert(next_image_info);
+	assert(image_type == GET_SECURITY_STATE(next_image_info->h.attr));
+
+	INFO("BL31: Preparing for EL3 exit to %s world, Kernel\n",
+	     (image_type == SECURE) ? "secure" : "normal");
+	INFO("BL31: Next image address = 0x%" PRIx64 "\n",
+	     next_image_info->pc);
+	INFO("BL31: Next image spsr = 0x%x\n", next_image_info->spsr);
+	cm_init_my_context(next_image_info);
+	cm_prepare_el3_exit(image_type);
+}
+
+bool is_el1_2nd_bootloader(void)
+{
+	return el1_is_2nd_bootloader;
+}
+
+/*******************************************************************************
+ * 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_image_ep_info : &bl32_image_ep_info;
+
+	/* None of the images on this platform can have 0x0 as the entrypoint */
+	if (next_image_info->pc) {
+		return next_image_info;
+	}
+	return NULL;
+}
+
+u_register_t boot_to_kernel(u_register_t x1,
+			    u_register_t x2,
+			    u_register_t x3,
+			    u_register_t x4,
+			    void *handle,
+			    struct smccc_res *smccc_ret)
+{
+	static uint8_t kernel_boot_once_flag;
+
+	/* only support in booting flow */
+	if (kernel_boot_once_flag == 0) {
+		kernel_boot_once_flag = 1;
+
+		INFO("save kernel info\n");
+		save_kernel_info(x1, x2, x3, x4);
+		bl31_prepare_kernel_entry(x4);
+		INFO("el3_exit\n");
+		/*
+		 * FIXME: no better way so far to prevent from
+		 * SiP root handler wipe x0~x3 if not assign smccc_ret
+		 * return register
+		 */
+		smccc_ret->a1 = x3;
+
+		mtk_init_one_level(MTK_INIT_LVL_BL33_DEFER);
+
+#if MTK_CONSOLE_RUNTIME_DISABLE
+		INFO("Turn off BL31 console\n");
+		mtk_console_core_end();
+#endif
+
+		/* Re-assign as x0 register entering Linux kernel */
+		return x2;
+	}
+	return 0;
+}
+/* Register SiP SMC service */
+DECLARE_SMC_HANDLER(MTK_SIP_KERNEL_BOOT, boot_to_kernel);
diff --git a/plat/mediatek/common/common_config.mk b/plat/mediatek/common/common_config.mk
new file mode 100644
index 0000000..851eb2c
--- /dev/null
+++ b/plat/mediatek/common/common_config.mk
@@ -0,0 +1,34 @@
+#
+# Copyright (c) 2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# indicate the reset vector address can be programmed
+PROGRAMMABLE_RESET_ADDRESS := 1
+MULTI_CONSOLE_API := 1
+COLD_BOOT_SINGLE_CPU := 1
+# Build flag to include AArch32 registers in cpu context save and restore during
+# world switch. This flag must be set to 0 for AArch64-only platforms.
+CTX_INCLUDE_AARCH32_REGS := 0
+PLAT_XLAT_TABLES_DYNAMIC := 1
+# enable this definition to print irq dump status in tf-a
+GIC_DEBUG := 0
+# Enable stack protector.
+# Allowed values are "all", "strong", "default" and "none"
+ENABLE_STACK_PROTECTOR := strong
+# AMU, Kernel will access amuserenr_el0 if PE supported
+# Firmware _must_ implement AMU support
+ENABLE_AMU := 1
+VENDOR_EXTEND_PUBEVENT_ENABLE := 1
+
+# MTK define options
+MTK_BL33_IS_64BIT := 0
+MTK_ADAPTED := 1
+
+# MTK module config
+CONFIG_MTK_INTERRUPT := y
+CONFIG_MTK_UART := y
+
+# UART baudrate
+UART_BAUDRATE := 921600
diff --git a/plat/mediatek/common/mtk_bl31_setup.c b/plat/mediatek/common/mtk_bl31_setup.c
new file mode 100644
index 0000000..46f7a63
--- /dev/null
+++ b/plat/mediatek/common/mtk_bl31_setup.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <arch.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <drivers/generic_delay_timer.h>
+#if XLAT_TABLES_LIB_V2 && PLAT_XLAT_TABLES_DYNAMIC
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#endif
+#include <plat/common/platform.h>
+
+/* MTK headers */
+#if MTK_SIP_KERNEL_BOOT_ENABLE
+#include <cold_boot.h>
+#endif
+#include <lib/mtk_init/mtk_init.h>
+#include <mtk_mmap_pool.h>
+
+IMPORT_SYM(uintptr_t, __RW_START__, RW_START);
+IMPORT_SYM(uintptr_t, __DATA_START__, DATA_START);
+#ifndef MTK_BL31_AS_BL2
+static struct mtk_bl31_fw_config bl31_fw_config;
+#else
+struct mtk_bl31_fw_config bl31_fw_config;
+#endif
+/* In order to be accessed after MMU enable */
+static struct mtk_bl_param_t bl_param_clone;
+
+void *get_mtk_bl31_fw_config(int index)
+{
+	void *arg = NULL;
+
+	switch (index) {
+	case BOOT_ARG_FROM_BL2:
+		arg = bl31_fw_config.from_bl2;
+		break;
+	case BOOT_ARG_SOC_FW_CONFIG:
+		arg = bl31_fw_config.soc_fw_config;
+		break;
+	case BOOT_ARG_HW_CONFIG:
+		arg = bl31_fw_config.hw_config;
+		break;
+	case BOOT_ARG_RESERVED:
+		arg = bl31_fw_config.reserved;
+		break;
+	default:
+		WARN("Fail to get boot arg, index:%d", index);
+		break;
+	}
+	return arg;
+}
+
+/*****************************************************************************
+ * Perform the very early platform specific architectural setup shared between
+ * ARM standard platforms. This only does basic initialization. Later
+ * architectural setup (bl31_arch_setup()) does not do anything platform
+ * specific.
+ ******************************************************************************/
+void bl31_early_platform_setup2(u_register_t from_bl2,
+				u_register_t soc_fw_config,
+				u_register_t hw_config, u_register_t plat_params_from_bl2)
+
+{
+	struct mtk_bl_param_t *p_mtk_bl_param = (struct mtk_bl_param_t *)from_bl2;
+
+	if (p_mtk_bl_param == NULL) {
+		ERROR("from_bl2 should not be NULL\n");
+		panic();
+	}
+	memcpy(&bl_param_clone, p_mtk_bl_param, sizeof(struct mtk_bl_param_t));
+	bl31_fw_config.from_bl2 = (void *)&bl_param_clone;
+	bl31_fw_config.soc_fw_config = (void *)soc_fw_config;
+	bl31_fw_config.hw_config = (void *)hw_config;
+	bl31_fw_config.reserved = (void *)plat_params_from_bl2;
+
+	INFO("MTK BL31 start\n");
+	/* Init delay function */
+	generic_delay_timer_init();
+	/* Initialize module initcall */
+	mtk_init_one_level(MTK_INIT_LVL_EARLY_PLAT);
+}
+
+void bl31_plat_arch_setup(void)
+{
+	const mmap_region_t bl_regions[] = {
+		MAP_BL_RO,
+		MAP_BL_RW,
+#if USE_COHERENT_MEM
+		MAP_BL_COHERENT_RAM,
+#endif
+		{0},
+	};
+
+	mtk_xlat_init(bl_regions);
+	/* Initialize module initcall */
+	mtk_init_one_level(MTK_INIT_LVL_ARCH);
+}
+
+/*****************************************************************************
+ * Perform any BL31 platform setup common to ARM standard platforms
+ ******************************************************************************/
+
+void bl31_platform_setup(void)
+{
+	mtk_init_one_level(MTK_INIT_LVL_PLAT_SETUP_0);
+	mtk_init_one_level(MTK_INIT_LVL_PLAT_SETUP_1);
+}
+
+/*******************************************************************************
+ * Operations before cold CPU leave BL31.
+ * Switch console to runtime state.
+ ******************************************************************************/
+void bl31_plat_runtime_setup(void)
+{
+	mtk_init_one_level(MTK_INIT_LVL_PLAT_RUNTIME);
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+	return SYS_COUNTER_FREQ_IN_HZ;
+}
diff --git a/plat/mediatek/common/mtk_plat_common.c b/plat/mediatek/common/mtk_plat_common.c
index 142b5c9..76f74a9 100644
--- a/plat/mediatek/common/mtk_plat_common.c
+++ b/plat/mediatek/common/mtk_plat_common.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -19,8 +19,6 @@
 #include <mtk_sip_svc.h>
 #include <plat_private.h>
 
-struct atf_arg_t gteearg;
-
 void clean_top_32b_of_param(uint32_t smc_fid,
 				u_register_t *px1,
 				u_register_t *px2,
@@ -28,96 +26,13 @@
 				u_register_t *px4)
 {
 	/* if parameters from SMC32. Clean top 32 bits */
-	if (0 == (smc_fid & SMC_AARCH64_BIT)) {
+	if (GET_SMC_CC(smc_fid) == SMC_64) {
 		*px1 = *px1 & SMC32_PARAM_MASK;
 		*px2 = *px2 & SMC32_PARAM_MASK;
 		*px3 = *px3 & SMC32_PARAM_MASK;
 		*px4 = *px4 & SMC32_PARAM_MASK;
 	}
 }
-
-#if MTK_SIP_KERNEL_BOOT_ENABLE
-static struct kernel_info k_info;
-
-static void save_kernel_info(uint64_t pc,
-			uint64_t r0,
-			uint64_t r1,
-			uint64_t k32_64)
-{
-	k_info.k32_64 = k32_64;
-	k_info.pc = pc;
-
-	if (LINUX_KERNEL_32 ==  k32_64) {
-		/* for 32 bits kernel */
-		k_info.r0 = 0;
-		/* machtype */
-		k_info.r1 = r0;
-		/* tags */
-		k_info.r2 = r1;
-	} else {
-		/* for 64 bits kernel */
-		k_info.r0 = r0;
-		k_info.r1 = r1;
-	}
-}
-
-uint64_t get_kernel_info_pc(void)
-{
-	return k_info.pc;
-}
-
-uint64_t get_kernel_info_r0(void)
-{
-	return k_info.r0;
-}
-
-uint64_t get_kernel_info_r1(void)
-{
-	return k_info.r1;
-}
-
-uint64_t get_kernel_info_r2(void)
-{
-	return k_info.r2;
-}
-
-void boot_to_kernel(uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4)
-{
-	static uint8_t kernel_boot_once_flag;
-	/* only support in booting flow */
-	if (0 == kernel_boot_once_flag) {
-		kernel_boot_once_flag = 1;
-
-		console_init(gteearg.atf_log_port,
-			UART_CLOCK, UART_BAUDRATE);
-		INFO("save kernel info\n");
-		save_kernel_info(x1, x2, x3, x4);
-		bl31_prepare_kernel_entry(x4);
-		INFO("el3_exit\n");
-		console_uninit();
-	}
-}
-#endif
-
-uint32_t plat_get_spsr_for_bl33_entry(void)
-{
-	unsigned int mode;
-	uint32_t spsr;
-	unsigned int ee;
-	unsigned long daif;
-
-	INFO("Secondary bootloader is AArch32\n");
-	mode = MODE32_svc;
-	ee = 0;
-	/*
-	 * TODO: Choose async. exception bits if HYP mode is not
-	 * implemented according to the values of SCR.{AW, FW} bits
-	 */
-	daif = DAIF_ABT_BIT | DAIF_IRQ_BIT | DAIF_FIQ_BIT;
-
-	spsr = SPSR_MODE32(mode, 0, ee, daif);
-	return spsr;
-}
 
 /*****************************************************************************
  * plat_is_smccc_feature_available() - This function checks whether SMCCC
diff --git a/plat/mediatek/common/mtk_plat_common.h b/plat/mediatek/common/mtk_plat_common.h
index 919c173..4c14b9d 100644
--- a/plat/mediatek/common/mtk_plat_common.h
+++ b/plat/mediatek/common/mtk_plat_common.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -14,45 +14,11 @@
 /*******************************************************************************
  * Function and variable prototypes
  ******************************************************************************/
-#define DEVINFO_SIZE 4
-#define LINUX_KERNEL_32 0
 #define SMC32_PARAM_MASK		(0xFFFFFFFF)
 
 #define JEDEC_MTK_BKID U(4)
 #define JEDEC_MTK_MFID U(0x26)
 
-struct atf_arg_t {
-	unsigned int atf_magic;
-	unsigned int tee_support;
-	unsigned int tee_entry;
-	unsigned int tee_boot_arg_addr;
-	unsigned int hwuid[4];     /* HW Unique id for t-base used */
-	unsigned int HRID[2];      /* HW random id for t-base used */
-	unsigned int atf_log_port;
-	unsigned int atf_log_baudrate;
-	unsigned int atf_log_buf_start;
-	unsigned int atf_log_buf_size;
-	unsigned int atf_irq_num;
-	unsigned int devinfo[DEVINFO_SIZE];
-	unsigned int atf_aee_debug_buf_start;
-	unsigned int atf_aee_debug_buf_size;
-};
-
-struct kernel_info {
-	uint64_t pc;
-	uint64_t r0;
-	uint64_t r1;
-	uint64_t r2;
-	uint64_t k32_64;
-};
-
-struct mtk_bl_param_t {
-	uint64_t bootarg_loc;
-	uint64_t bootarg_size;
-	uint64_t bl33_start_addr;
-	uint64_t tee_info_addr;
-};
-
 struct mtk_bl31_params {
        param_header_t h;
        image_info_t *bl31_image_info;
diff --git a/plat/mediatek/common/mtk_sip_svc.h b/plat/mediatek/common/mtk_sip_svc.h
deleted file mode 100644
index 74b17b6..0000000
--- a/plat/mediatek/common/mtk_sip_svc.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-#ifndef MTK_SIP_SVC_H
-#define MTK_SIP_SVC_H
-
-#include <stdint.h>
-
-/* SMC function IDs for SiP Service queries */
-#define SIP_SVC_CALL_COUNT		0x8200ff00
-#define SIP_SVC_UID			0x8200ff01
-/*					0x8200ff02 is reserved */
-#define SIP_SVC_VERSION			0x8200ff03
-
-/* Mediatek SiP Service Calls version numbers */
-#define MTK_SIP_SVC_VERSION_MAJOR	0x0
-#define MTK_SIP_SVC_VERSION_MINOR	0x1
-
-#define SMC_AARCH64_BIT		0x40000000
-
-/* Number of Mediatek SiP Calls implemented */
-#define MTK_COMMON_SIP_NUM_CALLS	4
-
-/* Mediatek SiP Service Calls function IDs */
-#define MTK_SIP_SET_AUTHORIZED_SECURE_REG	0x82000001
-
-/* For MTK SMC from Secure OS */
-/* 0x82000000 - 0x820000FF & 0xC2000000 - 0xC20000FF */
-#define MTK_SIP_KERNEL_BOOT_AARCH32		0x82000200
-#define MTK_SIP_KERNEL_BOOT_AARCH64		0xC2000200
-
-/* VCORE */
-#define MTK_SIP_VCORE_CONTROL_ARCH32		0x82000506
-#define MTK_SIP_VCORE_CONTROL_ARCH64		0xC2000506
-
-/* APUSYS SMC call */
-#define MTK_SIP_APUSYS_CONTROL_AARCH32		0x8200051E
-#define MTK_SIP_APUSYS_CONTROL_AARCH64		0xC200051E
-
-/* Mediatek SiP Calls error code */
-enum {
-	MTK_SIP_E_SUCCESS = 0,
-	MTK_SIP_E_INVALID_PARAM = -1,
-	MTK_SIP_E_NOT_SUPPORTED = -2,
-	MTK_SIP_E_INVALID_RANGE = -3,
-	MTK_SIP_E_PERMISSION_DENY = -4,
-	MTK_SIP_E_LOCK_FAIL = -5
-};
-
-/*
- * This function should be implemented in Mediatek SOC directory. It fullfills
- * MTK_SIP_SET_AUTHORIZED_SECURE_REG SiP call by checking the sreg with the
- * predefined secure register list, if a match was found, set val to sreg.
- *
- * Return MTK_SIP_E_SUCCESS on success, and MTK_SIP_E_INVALID_PARAM on failure.
- */
-uint64_t mt_sip_set_authorized_sreg(uint32_t sreg, uint32_t val);
-
-#endif /* MTK_SIP_SVC_H */
diff --git a/plat/mediatek/common/mtk_smc_handlers.c b/plat/mediatek/common/mtk_smc_handlers.c
new file mode 100644
index 0000000..24b978c
--- /dev/null
+++ b/plat/mediatek/common/mtk_smc_handlers.c
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <cold_boot.h>
+#include <lib/mtk_init/mtk_init.h>
+#include <mtk_sip_svc.h>
+
+#define SMC_HANDLER_DEBUG(...) VERBOSE(__VA_ARGS__)
+#define SMC_HANDLER_DEBUG_NOT_IMP_MSG "%s[0x%x] smc handler not implemented\n"
+#define SMC_HANDLER_DEBUG_START_MSG "%s[0x%x] smc handler start, smc desc. index:%d\n"
+#define SMC_HANDLER_DEBUG_END_MSG "%s[0x%x] smc handler end\n"
+
+/*
+ * These macros below are used to identify SIP calls from Kernel,
+ * Hypervisor, or 2ndBootloader
+ */
+#define SIP_FID_ORI_MASK	(0xc000)
+#define SIP_FID_ORI_SHIFT	(14)
+#define SIP_FID_KERNEL		(0x0)
+#define SIP_FID_KERNEL_VIA_GZ	(0x1)
+#define SIP_FID_GZ		(0x2)
+
+#define GET_SMC_ORI(_fid)	(((_fid) & SIP_FID_ORI_MASK) >> SIP_FID_ORI_SHIFT)
+#define GET_SMC_ORI_NUM(_fid)	((_fid) & ~(SIP_FID_ORI_MASK))
+
+#define is_from_nsel2(_ori)	(_ori == SIP_FID_GZ)
+#define is_from_bl33(_ori) \
+	((_ori != SIP_FID_GZ) && (is_el1_2nd_bootloader() == 1))
+#define is_from_nsel1(_ori) \
+	(((_ori == SIP_FID_KERNEL) || \
+	 (_ori == SIP_FID_KERNEL_VIA_GZ)) && \
+	 (is_el1_2nd_bootloader() == 0))
+
+#define is_smc_forbidden(_ori) (_ori == SIP_FID_KERNEL_VIA_GZ)
+
+#define MASK_32_BIT (0xffffffffU)
+#define SMC_ID_EXPAND_AS_SMC_OPERATION(_smc_id, _smc_num) \
+	case _smc_id##_AARCH32: \
+	{ \
+		x1 = x1 & MASK_32_BIT; \
+		x2 = x2 & MASK_32_BIT; \
+		x3 = x3 & MASK_32_BIT; \
+		x4 = x4 & MASK_32_BIT; \
+	} \
+	case _smc_id##_AARCH64: \
+	{ \
+		if (_smc_id##_descriptor_index < 0) { \
+			SMC_HANDLER_DEBUG(SMC_HANDLER_DEBUG_NOT_IMP_MSG, #_smc_id, smc_id); \
+			break; \
+		} \
+		if (_smc_id##_descriptor_index >= smc_id_descriptor_max) { \
+			SMC_HANDLER_DEBUG("smc descriptor index[%d] exceed max[%d]\n", \
+					  _smc_id##_descriptor_index, smc_id_descriptor_max); \
+			break; \
+		} \
+		SMC_HANDLER_DEBUG(SMC_HANDLER_DEBUG_START_MSG, #_smc_id, smc_id, \
+				  _smc_id##_descriptor_index); \
+		ret  = smc_handler_pool[_smc_id##_descriptor_index].smc_handler(x1,\
+				x2, x3, x4, handle, &smc_ret); \
+		SMC_HANDLER_DEBUG(SMC_HANDLER_DEBUG_END_MSG, #_smc_id, smc_id); \
+		break; \
+	}
+
+#define SMC_ID_EXPAND_AS_DESCRIPTOR_INDEX(_smc_id, _smc_num) \
+	short _smc_id##_descriptor_index __section("mtk_plat_ro") = -1;
+
+MTK_SIP_SMC_FROM_BL33_TABLE(SMC_ID_EXPAND_AS_DESCRIPTOR_INDEX);
+MTK_SIP_SMC_FROM_NS_EL1_TABLE(SMC_ID_EXPAND_AS_DESCRIPTOR_INDEX);
+
+IMPORT_SYM(uintptr_t, __MTK_SMC_POOL_START__, MTK_SMC_POOL_START);
+IMPORT_SYM(uintptr_t, __MTK_SMC_POOL_END_UNALIGNED__, MTK_SMC_POOL_END_UNALIGNED);
+
+static const struct smc_descriptor *smc_handler_pool;
+static short smc_id_descriptor_max;
+
+#if !MTK_SIP_KERNEL_BOOT_ENABLE
+/*
+ * If there is no SMC request needs to be served in 2nd bootloader,
+ * disable the service path inherently.
+ */
+bool is_el1_2nd_bootloader(void)
+{
+	return false;
+}
+#endif
+
+static void print_smc_descriptor(const struct smc_descriptor pool[])
+{
+	const struct smc_descriptor *p_smc_desc;
+
+	INFO("print smc descriptor pool\n");
+	for (p_smc_desc = &pool[0];
+	     (char *)p_smc_desc < (char *)MTK_SMC_POOL_END_UNALIGNED;
+	     p_smc_desc++) {
+		INFO("descriptor name:%s\n", p_smc_desc->smc_name);
+		INFO("descriptor index:%d\n", *p_smc_desc->smc_descriptor_index);
+		INFO("smc id 32:0x%x, smc id 64:0x%x\n",
+		     p_smc_desc->smc_id_aarch32, p_smc_desc->smc_id_aarch64);
+	}
+}
+
+static int mtk_smc_handler_init(void)
+{
+	const struct smc_descriptor *iter;
+	short index_cnt;
+	int ret = 0;
+
+	smc_handler_pool = (const struct smc_descriptor *)MTK_SMC_POOL_START;
+	/* Designate descriptor index point to smc_handler_pool */
+	for (index_cnt = 0, iter = &smc_handler_pool[0];
+	     (char *)iter < (char *)MTK_SMC_POOL_END_UNALIGNED;
+	     iter++, index_cnt++) {
+		if (index_cnt < 0) {
+			SMC_HANDLER_DEBUG("smc handler pool index overflow!\n");
+			ret = -EPERM;
+			assert(0);
+			break;
+		}
+		*(iter->smc_descriptor_index) = index_cnt;
+	}
+	smc_id_descriptor_max = index_cnt;
+	print_smc_descriptor(smc_handler_pool);
+	return ret;
+}
+MTK_EARLY_PLAT_INIT(mtk_smc_handler_init);
+
+/* This function handles Mediatek defined SiP Calls from Bootloader */
+static uintptr_t mtk_smc_handler_bl33(uint32_t smc_id,
+				      u_register_t x1,
+				      u_register_t x2,
+				      u_register_t x3,
+				      u_register_t x4,
+				      void *cookie,
+				      void *handle,
+				      u_register_t flags)
+{
+	uintptr_t ret = MTK_SIP_E_SUCCESS;
+	struct smccc_res smc_ret = {0};
+
+	switch (smc_id) {
+		MTK_SIP_SMC_FROM_BL33_TABLE(SMC_ID_EXPAND_AS_SMC_OPERATION);
+	default:
+		INFO("BL33 SMC ID:0x%x not supported\n", smc_id);
+		ret = SMC_UNK;
+		break;
+	}
+	SMC_RET4(handle, ret, smc_ret.a1, smc_ret.a2, smc_ret.a3);
+}
+
+/* This function handles Mediatek defined SiP Calls from Kernel */
+static uintptr_t mtk_smc_handler_nsel1(uint32_t smc_id,
+				       u_register_t x1,
+				       u_register_t x2,
+				       u_register_t x3,
+				       u_register_t x4,
+				       void *cookie,
+				       void *handle,
+				       u_register_t flags)
+{
+	uintptr_t ret = MTK_SIP_E_SUCCESS;
+	struct smccc_res smc_ret = {0};
+
+	switch (smc_id) {
+		MTK_SIP_SMC_FROM_NS_EL1_TABLE(SMC_ID_EXPAND_AS_SMC_OPERATION);
+	default:
+		INFO("NSEL1 SMC ID:0x%x not supported\n", smc_id);
+		ret = SMC_UNK;
+		break;
+	}
+	SMC_RET4(handle, ret, smc_ret.a1, smc_ret.a2, smc_ret.a3);
+}
+
+static uintptr_t mtk_smc_handler(uint32_t smc_id,
+				 u_register_t x1,
+				 u_register_t x2,
+				 u_register_t x3,
+				 u_register_t x4,
+				 void *cookie,
+				 void *handle,
+				 u_register_t flags)
+{
+	uintptr_t ret = SMC_UNK;
+	uint32_t ns;
+	uint32_t smc_ori;
+	uint32_t smc_num;
+
+	/* Get SMC Originator bit 14.15 */
+	smc_ori = GET_SMC_ORI(smc_id);
+	/* Get SMC Number. Clean bit 14.15 */
+	smc_num = GET_SMC_ORI_NUM(smc_id);
+
+	/* Determine which security state this SMC originated from */
+	ns = is_caller_non_secure(flags);
+
+	if (ns && is_smc_forbidden(smc_ori)) {
+		ERROR("%s: Forbidden SMC call (0x%x)\n", __func__, smc_id);
+		SMC_RET1(handle, ret);
+	}
+
+	if (!ns) {
+		/* SiP SMC service secure world's call */
+		INFO("Secure SMC ID:0x%x not supported\n", smc_id);
+		SMC_RET1(handle, ret);
+	}
+	if (is_from_bl33(smc_ori)) {
+		/* SiP SMC service secure bootloader's call */
+		return mtk_smc_handler_bl33(smc_num, x1, x2, x3, x4,
+					    cookie, handle, flags);
+	} else if (is_from_nsel1(smc_ori)) {
+		/* SiP SMC service kernel's call */
+		return mtk_smc_handler_nsel1(smc_num, x1, x2, x3, x4,
+					     cookie, handle, flags);
+	}
+	INFO("SMC ID:0x%x not supported\n", smc_id);
+	SMC_RET1(handle, ret);
+}
+
+/* Define a runtime service descriptor for fast SMC calls */
+DECLARE_RT_SVC(
+	mtk_smc_handler,
+	OEN_SIP_START,
+	OEN_SIP_END,
+	SMC_TYPE_FAST,
+	NULL,
+	mtk_smc_handler
+);
diff --git a/plat/mediatek/common/rules.mk b/plat/mediatek/common/rules.mk
new file mode 100644
index 0000000..6acc731
--- /dev/null
+++ b/plat/mediatek/common/rules.mk
@@ -0,0 +1,15 @@
+#
+# Copyright (c) 2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+LOCAL_DIR := $(call GET_LOCAL_DIR)
+
+MODULE := mtk_common
+
+LOCAL_SRCS-y := ${LOCAL_DIR}/mtk_bl31_setup.c
+LOCAL_SRCS-y += ${LOCAL_DIR}/mtk_smc_handlers.c
+LOCAL_SRCS-$(MTK_SIP_KERNEL_BOOT_ENABLE) += ${LOCAL_DIR}/cold_boot.c
+
+$(eval $(call MAKE_LOCALS,$(LOCAL_SRCS-y),$(MTK_BL)))
diff --git a/plat/mediatek/include/cold_boot.h b/plat/mediatek/include/cold_boot.h
new file mode 100644
index 0000000..6b94b57
--- /dev/null
+++ b/plat/mediatek/include/cold_boot.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2022, Mediatek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef COLD_BOOT_H
+#define COLD_BOOT_H
+
+#include <stdint.h>
+
+/*******************************************************************************
+ * Function and variable prototypes
+ ******************************************************************************/
+#define LINUX_KERNEL_32	(0)
+#define LINUX_KERNEL_64	(1)
+#define DEVINFO_SIZE	(4)
+
+struct atf_arg_t {
+	uint32_t atf_magic;
+	uint32_t tee_support;
+	uint64_t tee_entry;
+	uint64_t tee_boot_arg_addr;
+	uint32_t hwuid[4]; /* HW Unique id for t-base used */
+	uint32_t HRID[8]; /* HW random id for t-base used */
+	uint32_t devinfo[DEVINFO_SIZE];
+};
+
+struct mtk_bl31_fw_config {
+	void *from_bl2; /* MTK boot tag */
+	void *soc_fw_config;
+	void *hw_config;
+	void *reserved;
+};
+
+enum {
+	BOOT_ARG_FROM_BL2,
+	BOOT_ARG_SOC_FW_CONFIG,
+	BOOT_ARG_HW_CONFIG,
+	BOOT_ARG_RESERVED
+};
+
+struct kernel_info {
+	uint64_t pc;
+	uint64_t r0;
+	uint64_t r1;
+	uint64_t r2;
+	uint64_t k32_64;
+};
+
+struct mtk_bl_param_t {
+	uint64_t bootarg_loc;
+	uint64_t bootarg_size;
+	uint64_t bl33_start_addr;
+	uint64_t atf_arg_addr;
+};
+
+void *get_mtk_bl31_fw_config(int index);
+bool is_el1_2nd_bootloader(void);
+
+#endif /* COLD_BOOT_H */
diff --git a/plat/mediatek/include/lib/mtk_init/mtk_init.h b/plat/mediatek/include/lib/mtk_init/mtk_init.h
new file mode 100644
index 0000000..6f23a9b
--- /dev/null
+++ b/plat/mediatek/include/lib/mtk_init/mtk_init.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTK_INIT_H
+#define MTK_INIT_H
+
+#include <cdefs.h>
+#include <lib/mtk_init/mtk_init_def.h>
+
+#define INIT_CALL_EXPAND_AS_ENUMERATION(_section_enum, _section_name, _level) \
+	_section_enum = _level,
+
+#define EXPAND_AS_LINK_SECTION(_section_enum, _section_name, _level) \
+	__##_section_enum##_START__ = .; \
+	KEEP(*(_section_name##_level));
+
+#define EXPAND_AS_EXTERN(_section_enum, _section_name, _level) \
+	extern struct initcall __##_section_enum##_START__[];
+
+#define EXPAND_AS_SYMBOL_ARR(_section_enum, _section_name, _level) \
+	__##_section_enum##_START__,
+
+#define DECLARE_MTK_INITCALL(_fn, _level) \
+	const struct initcall _mtk_initcall_##_fn \
+	__used \
+	__aligned(sizeof(void *)) \
+	__section(".mtk_plat_initcall_"#_level) \
+	= { \
+		.name = #_fn, \
+		.fn = _fn \
+	}
+
+/* initcall helpers  */
+#define MTK_EARLY_PLAT_INIT(_fn) DECLARE_MTK_INITCALL(_fn, 0)
+#define MTK_ARCH_INIT(_fn) DECLARE_MTK_INITCALL(_fn, 1)
+#define MTK_PLAT_SETUP_0_INIT(_fn) DECLARE_MTK_INITCALL(_fn, 2)
+#define MTK_PLAT_SETUP_1_INIT(_fn) DECLARE_MTK_INITCALL(_fn, 3)
+#define MTK_PLAT_RUNTIME_INIT(_fn) DECLARE_MTK_INITCALL(_fn, 4)
+#define MTK_PLAT_BL33_DEFER_INIT(_fn) DECLARE_MTK_INITCALL(_fn, 5)
+
+#ifndef __ASSEMBLER__
+struct initcall {
+	const char *name;
+	int (*fn)(void);
+};
+
+enum {
+	INIT_CALL_TABLE(INIT_CALL_EXPAND_AS_ENUMERATION)
+	MTK_INIT_LVL_MAX
+};
+
+void mtk_init_one_level(unsigned int level);
+#endif
+
+#endif /* MTK_INIT_H */
diff --git a/plat/mediatek/include/lib/mtk_init/mtk_init_def.h b/plat/mediatek/include/lib/mtk_init/mtk_init_def.h
new file mode 100644
index 0000000..8aae41d
--- /dev/null
+++ b/plat/mediatek/include/lib/mtk_init/mtk_init_def.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTK_INIT_DEF_H
+#define MTK_INIT_DEF_H
+
+/*
+ * Define init call sections here. _func is for 2nd level expansion, init
+ * section enum, and init section name.
+ */
+#define INIT_CALL_TABLE(_func) \
+	_func(MTK_INIT_LVL_EARLY_PLAT, .mtk_plat_initcall_, 0) \
+	_func(MTK_INIT_LVL_ARCH, .mtk_plat_initcall_, 1) \
+	_func(MTK_INIT_LVL_PLAT_SETUP_0, .mtk_plat_initcall_, 2) \
+	_func(MTK_INIT_LVL_PLAT_SETUP_1, .mtk_plat_initcall_, 3) \
+	_func(MTK_INIT_LVL_PLAT_RUNTIME, .mtk_plat_initcall_, 4) \
+	_func(MTK_INIT_LVL_BL33_DEFER, .mtk_plat_initcall_, 5)
+
+#endif /* MTK_INIT_DEF_H */
diff --git a/plat/mediatek/include/mtk_mmap_pool.h b/plat/mediatek/include/mtk_mmap_pool.h
new file mode 100644
index 0000000..99d1bff
--- /dev/null
+++ b/plat/mediatek/include/mtk_mmap_pool.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTK_MMAP_POOL_H
+#define MTK_MMAP_POOL_H
+
+#include <cdefs.h>
+#include <lib/xlat_tables/xlat_tables_compat.h>
+
+struct mtk_mmap_descriptor {
+	const char *mmap_name;
+	const mmap_region_t *mmap_ptr;
+	const uint32_t mmap_size;
+};
+
+#define MTK_MMAP_SECTION \
+	__used \
+	__aligned(sizeof(void *)) \
+	__section(".mtk_mmap_lists")
+
+#define DECLARE_MTK_MMAP_REGIONS(_mmap_array) \
+	static const struct mtk_mmap_descriptor _mtk_mmap_descriptor_##_mmap_array \
+	__used \
+	__aligned(sizeof(void *)) \
+	__section(".mtk_mmap_pool") \
+	= { \
+		.mmap_name = #_mmap_array, \
+		.mmap_ptr = _mmap_array, \
+		.mmap_size = ARRAY_SIZE(_mmap_array) \
+	}
+
+#define MAP_BL_RW MAP_REGION_FLAT( \
+		DATA_START, \
+		BL_END - DATA_START, \
+		MT_MEMORY | MT_RW | MT_SECURE)
+
+#if SEPARATE_CODE_AND_RODATA
+#define MAP_BL_RO \
+	MAP_REGION_FLAT( \
+		BL_CODE_BASE, \
+		BL_CODE_END - BL_CODE_BASE, \
+		MT_CODE | MT_SECURE), \
+	MAP_REGION_FLAT( \
+		BL_RO_DATA_BASE, \
+		BL_RO_DATA_END - BL_RO_DATA_BASE, \
+		MT_RO_DATA | MT_SECURE)
+#else
+#define MAP_BL_RO MAP_REGION_FLAT(BL_CODE_BASE, \
+				  BL_CODE_END - BL_CODE_BASE,	\
+				  MT_CODE | MT_SECURE)
+#endif
+
+void mtk_xlat_init(const mmap_region_t *bl_regions);
+
+#endif /* MTK_MMAP_POOL_H */
diff --git a/plat/mediatek/include/mtk_sip_def.h b/plat/mediatek/include/mtk_sip_def.h
new file mode 100644
index 0000000..b591499
--- /dev/null
+++ b/plat/mediatek/include/mtk_sip_def.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTK_SIP_DEF_H
+#define MTK_SIP_DEF_H
+
+/* Define SiP SMC ID here */
+#define MTK_SIP_SMC_FROM_NS_EL1_TABLE(_func) \
+	_func(MTK_SIP_KERNEL_TIME_SYNC, 0x202) \
+	_func(MTK_SIP_VCORE_CONTROL, 0x506) \
+	_func(MTK_SIP_APUSYS_CONTROL, 0x51E) \
+	_func(MTK_SIP_KERNEL_GIC_OP, 0x526)
+
+#define MTK_SIP_SMC_FROM_BL33_TABLE(_func) \
+	_func(MTK_SIP_KERNEL_BOOT, 0x115)
+
+#endif /* MTK_SIP_DEF_H */
diff --git a/plat/mediatek/include/mtk_sip_svc.h b/plat/mediatek/include/mtk_sip_svc.h
new file mode 100644
index 0000000..ce51048
--- /dev/null
+++ b/plat/mediatek/include/mtk_sip_svc.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTK_SIP_SVC_H
+#define MTK_SIP_SVC_H
+
+#include <stdint.h>
+#include <lib/smccc.h>
+#include <mtk_sip_def.h>
+
+/* SMC function IDs for SiP Service queries */
+#define SIP_SVC_CALL_COUNT		U(0x8200ff00)
+#define SIP_SVC_UID			U(0x8200ff01)
+/* 0x8200ff02 is reserved */
+#define SIP_SVC_VERSION			U(0x8200ff03)
+
+/* MediaTek SiP Service Calls version numbers */
+#define MTK_SIP_SVC_VERSION_MAJOR	U(0x0)
+#define MTK_SIP_SVC_VERSION_MINOR	U(0x1)
+
+/* Number of MediaTek SiP Calls implemented */
+#define MTK_COMMON_SIP_NUM_CALLS	U(4)
+
+/* MediaTek SiP Service Calls function IDs */
+#define MTK_SIP_SET_AUTHORIZED_SECURE_REG	U(0x82000001)
+
+#define SMC_ID_EXPAND_AS_ENUM(_smc_id, _smc_num) \
+	_smc_id##_AARCH32 = ((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT) | \
+		 ((0) << FUNCID_CC_SHIFT) | \
+		 (OEN_SIP_START << FUNCID_OEN_SHIFT) | \
+		 ((_smc_num) << FUNCID_NUM_SHIFT)), \
+	_smc_id##_AARCH64 = ((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT) | \
+		 ((1) << FUNCID_CC_SHIFT) | \
+		 (OEN_SIP_START << FUNCID_OEN_SHIFT) | \
+		 ((_smc_num) << FUNCID_NUM_SHIFT)),
+
+#define SMC_ID_EXPAND_AS_EXTERN_SMC_INDEX(_smc_id, _smc_num) \
+	extern short _smc_id##_descriptor_index;
+
+/* Bind SMC handler with SMC ID */
+#define DECLARE_SMC_HANDLER(_smc_id, _smc_handler) \
+	const struct smc_descriptor _smc_id##_descriptor \
+		__used \
+		__aligned(sizeof(void *)) \
+		__section(".mtk_smc_descriptor_pool") = { \
+			.smc_handler = _smc_handler, \
+			.smc_name = #_smc_id, \
+			.smc_id_aarch32 = _smc_id##_AARCH32, \
+			.smc_id_aarch64 = _smc_id##_AARCH64, \
+			.smc_descriptor_index = &_smc_id##_descriptor_index \
+		}
+
+MTK_SIP_SMC_FROM_BL33_TABLE(SMC_ID_EXPAND_AS_EXTERN_SMC_INDEX);
+MTK_SIP_SMC_FROM_NS_EL1_TABLE(SMC_ID_EXPAND_AS_EXTERN_SMC_INDEX);
+
+/* Expand SiP SMC ID table as enum */
+enum {
+	MTK_SIP_SMC_FROM_BL33_TABLE(SMC_ID_EXPAND_AS_ENUM)
+	MTK_SIP_SMC_FROM_NS_EL1_TABLE(SMC_ID_EXPAND_AS_ENUM)
+	MTK_SIP_SMC_MAX_NUMBER
+};
+
+/* MediaTek SiP Calls error code */
+enum {
+	MTK_SIP_E_SUCCESS = 0,
+	MTK_SIP_E_INVALID_PARAM = -1,
+	MTK_SIP_E_NOT_SUPPORTED = -2,
+	MTK_SIP_E_INVALID_RANGE = -3,
+	MTK_SIP_E_PERMISSION_DENY = -4,
+	MTK_SIP_E_LOCK_FAIL = -5,
+};
+
+struct smccc_res {
+	uint64_t a1;
+	uint64_t a2;
+	uint64_t a3;
+};
+
+typedef uintptr_t (*smc_handler_t)(u_register_t,
+				   u_register_t,
+				   u_register_t,
+				   u_register_t,
+				   void *,
+				   struct smccc_res *);
+
+struct smc_descriptor {
+	smc_handler_t smc_handler;
+	const uint32_t smc_id_aarch32;
+	const uint32_t smc_id_aarch64;
+	const char *smc_name;
+	short *const smc_descriptor_index;
+};
+
+/*
+ * This function should be implemented in MediaTek SOC directory. It fullfills
+ * MTK_SIP_SET_AUTHORIZED_SECURE_REG SiP call by checking the sreg with the
+ * predefined secure register list, if a match was found, set val to sreg.
+ *
+ * Return MTK_SIP_E_SUCCESS on success, and MTK_SIP_E_INVALID_PARAM on failure.
+ */
+uint64_t mt_sip_set_authorized_sreg(uint32_t sreg, uint32_t val);
+
+#endif /* MTK_SIP_SVC_H */
diff --git a/plat/mediatek/include/plat.ld.rodata.inc b/plat/mediatek/include/plat.ld.rodata.inc
new file mode 100644
index 0000000..06ad491
--- /dev/null
+++ b/plat/mediatek/include/plat.ld.rodata.inc
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_LD_RODATA_INC
+#define PLAT_LD_RODATA_INC
+
+#include <lib/mtk_init/mtk_init.h>
+	. = ALIGN(32);
+	INIT_CALL_TABLE(EXPAND_AS_LINK_SECTION);
+	__MTK_PLAT_INITCALL_END__ = .;
+	. = ALIGN(32);
+	__MTK_MMAP_POINTER_POOL_START__ = .;
+	KEEP(*(.mtk_mmap_pool))
+	__MTK_MMAP_POINTER_POOL_END_UNALIGNED__ = .;
+	. = ALIGN(8);
+	__MTK_MMAP_POOL_START__ = .;
+	KEEP(*(.mtk_mmap_lists))
+	__MTK_MMAP_POOL_END_UNALIGNED__ = .;
+	. = ALIGN(32);
+	__MTK_SMC_POOL_START__ = .;
+	KEEP(*(.mtk_smc_descriptor_pool))
+	__MTK_SMC_POOL_END_UNALIGNED__ = .;
+	. = ALIGN(8);
+#include <vendor_pubsub_events.h>
+	*(mtk_plat_ro)
+
+#endif /* PLAT_LD_RODATA_INC */
diff --git a/plat/mediatek/include/vendor_pubsub_events.h b/plat/mediatek/include/vendor_pubsub_events.h
new file mode 100644
index 0000000..cb8d878
--- /dev/null
+++ b/plat/mediatek/include/vendor_pubsub_events.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef VENDOR_PUBSUB_EVENTS_H
+#define VENDOR_PUBSUB_EVENTS_H
+
+#include <lib/el3_runtime/pubsub.h>
+
+REGISTER_PUBSUB_EVENT(lpm_publish_event);
+REGISTER_PUBSUB_EVENT(suspend_publish_event);
+REGISTER_PUBSUB_EVENT(mt_cpupm_publish_pwr_on);
+REGISTER_PUBSUB_EVENT(mt_cpupm_publish_pwr_off);
+REGISTER_PUBSUB_EVENT(mt_cpupm_publish_afflv_pwr_on);
+REGISTER_PUBSUB_EVENT(mt_cpupm_publish_afflv_pwr_off);
+REGISTER_PUBSUB_EVENT(publish_check_wakeup_irq);
+REGISTER_PUBSUB_EVENT(watchdog_timeout);
+
+#endif /* VENDOR_PUBSUB_EVENTS_H */
diff --git a/plat/mediatek/lib/mtk_init/mtk_init.c b/plat/mediatek/lib/mtk_init/mtk_init.c
new file mode 100644
index 0000000..2289659
--- /dev/null
+++ b/plat/mediatek/lib/mtk_init/mtk_init.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <lib/utils_def.h>
+#include <lib/mtk_init/mtk_init.h>
+
+INIT_CALL_TABLE(EXPAND_AS_EXTERN);
+extern struct initcall __MTK_PLAT_INITCALL_END__[];
+
+struct initcall *initcall_list[] = {
+	INIT_CALL_TABLE(EXPAND_AS_SYMBOL_ARR)
+	__MTK_PLAT_INITCALL_END__
+};
+
+void mtk_init_one_level(uint32_t level)
+{
+	const struct initcall *entry;
+	int error;
+
+	if (level >= MTK_INIT_LVL_MAX) {
+		ERROR("invalid level:%u\n", level);
+		panic();
+	}
+
+	INFO("init calling level:%u\n", level);
+	for (entry = initcall_list[level];
+	     (entry != NULL) && (entry < initcall_list[level + 1]);
+	     entry++) {
+		INFO("calling %s\n", entry->name);
+		error = entry->fn();
+		if (error != 0) {
+			ERROR("init %s fail, errno:%d\n", entry->name, error);
+		}
+	}
+}
diff --git a/plat/mediatek/lib/mtk_init/mtk_mmap_init.c b/plat/mediatek/lib/mtk_init/mtk_mmap_init.c
new file mode 100644
index 0000000..e3dada0
--- /dev/null
+++ b/plat/mediatek/lib/mtk_init/mtk_mmap_init.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <lib/xlat_tables/xlat_tables_compat.h>
+#include <mtk_mmap_pool.h>
+
+IMPORT_SYM(uintptr_t, __MTK_MMAP_POINTER_POOL_START__, MTK_MMAP_POINTER_POOL_START);
+IMPORT_SYM(uintptr_t, __MTK_MMAP_POINTER_POOL_END_UNALIGNED__, MTK_MMAP_POINTER_POOL_END_UNALIGNED);
+IMPORT_SYM(uintptr_t, __RW_START__, RW_START);
+IMPORT_SYM(uintptr_t, __DATA_START__, DATA_START);
+
+#define MAP_MTK_SECTIONS MAP_REGION_FLAT(RW_START, \
+					 DATA_START - RW_START, \
+					 MT_MEMORY | MT_RO | MT_SECURE)
+
+
+static void print_mmap(const mmap_region_t *regions)
+{
+	while (regions->size != 0U) {
+		VERBOSE("Region: 0x%lx - 0x%lx has attributes 0x%x\n",
+			regions->base_va,
+			regions->base_va + regions->size,
+			regions->attr);
+		regions++;
+	}
+}
+
+void mtk_xlat_init(const mmap_region_t *bl_regions)
+{
+	struct mtk_mmap_descriptor *iter;
+	const mmap_region_t *regions = bl_regions;
+
+	print_mmap(regions);
+	mmap_add(bl_regions);
+	if (MTK_MMAP_POINTER_POOL_START != MTK_MMAP_POINTER_POOL_END_UNALIGNED) {
+		for (iter = (struct mtk_mmap_descriptor *)MTK_MMAP_POINTER_POOL_START;
+		     (char *)iter < (char *)MTK_MMAP_POINTER_POOL_END_UNALIGNED;
+		     iter++) {
+			regions = iter->mmap_ptr;
+			INFO("mmap_name: %s\n", iter->mmap_name);
+			INFO("mmap_size: 0x%x\n", iter->mmap_size);
+			print_mmap(regions);
+			mmap_add(regions);
+		}
+	}
+	init_xlat_tables();
+	enable_mmu_el3(0);
+}
diff --git a/plat/mediatek/lib/mtk_init/rules.mk b/plat/mediatek/lib/mtk_init/rules.mk
new file mode 100644
index 0000000..cc6ca95
--- /dev/null
+++ b/plat/mediatek/lib/mtk_init/rules.mk
@@ -0,0 +1,14 @@
+#
+# Copyright (c) 2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+LOCAL_DIR := $(call GET_LOCAL_DIR)
+
+MODULE := mtk_init
+
+LOCAL_SRCS-y := $(LOCAL_DIR)/mtk_init.c
+LOCAL_SRCS-y += $(LOCAL_DIR)/mtk_mmap_init.c
+
+$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
diff --git a/plat/mediatek/mt8173/platform.mk b/plat/mediatek/mt8173/platform.mk
index f62802c..fa3605a 100644
--- a/plat/mediatek/mt8173/platform.mk
+++ b/plat/mediatek/mt8173/platform.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -8,6 +8,7 @@
 MTK_PLAT_SOC		:=	${MTK_PLAT}/${PLAT}
 
 PLAT_INCLUDES		:=	-I${MTK_PLAT}/common/				\
+				-I${MTK_PLAT}/include/				\
 				-Iinclude/plat/arm/common/aarch64		\
 				-I${MTK_PLAT_SOC}/drivers/crypt/		\
 				-I${MTK_PLAT_SOC}/drivers/mtcmos/		\
diff --git a/plat/mediatek/mt8183/platform.mk b/plat/mediatek/mt8183/platform.mk
index 1615cf9..653a0a6 100644
--- a/plat/mediatek/mt8183/platform.mk
+++ b/plat/mediatek/mt8183/platform.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2019, MediaTek Inc. All rights reserved.
+# Copyright (c) 2019-2022, MediaTek Inc. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -8,7 +8,8 @@
 MTK_PLAT_SOC  := ${MTK_PLAT}/${PLAT}
 
 PLAT_INCLUDES := -I${MTK_PLAT}/common/                            \
-                 -I${MTK_PLAT}/common/drivers/uart/                \
+                 -I${MTK_PLAT}/common/drivers/uart/               \
+                 -I${MTK_PLAT}/include/                           \
                  -I${MTK_PLAT_SOC}/drivers/                       \
                  -I${MTK_PLAT_SOC}/drivers/emi_mpu/               \
                  -I${MTK_PLAT_SOC}/drivers/devapc/                \
diff --git a/plat/mediatek/mt8186/plat_sip_calls.c b/plat/mediatek/mt8186/plat_sip_calls.c
index cb66218..d9144d8 100644
--- a/plat/mediatek/mt8186/plat_sip_calls.c
+++ b/plat/mediatek/mt8186/plat_sip_calls.c
@@ -23,8 +23,8 @@
 	uint64_t ret;
 
 	switch (smc_fid) {
-	case MTK_SIP_VCORE_CONTROL_ARCH32:
-	case MTK_SIP_VCORE_CONTROL_ARCH64:
+	case MTK_SIP_VCORE_CONTROL_AARCH32:
+	case MTK_SIP_VCORE_CONTROL_AARCH64:
 		ret = spm_vcorefs_args(x1, x2, x3, (uint64_t *)&x4);
 		SMC_RET2(handle, ret, x4);
 		break;
diff --git a/plat/mediatek/mt8186/platform.mk b/plat/mediatek/mt8186/platform.mk
index b6d9ca8..1492038 100644
--- a/plat/mediatek/mt8186/platform.mk
+++ b/plat/mediatek/mt8186/platform.mk
@@ -13,6 +13,7 @@
                  -I${MTK_PLAT}/common/drivers/uart/               \
                  -I${MTK_PLAT}/common/drivers/timer/              \
 		 -I${MTK_PLAT}/common/lpm/                        \
+                 -I${MTK_PLAT}/include/                           \
                  -I${MTK_PLAT_SOC}/drivers/spm/                   \
                  -I${MTK_PLAT_SOC}/drivers/dcm/                   \
                  -I${MTK_PLAT_SOC}/drivers/dfd/                    \
diff --git a/plat/mediatek/mt8192/plat_sip_calls.c b/plat/mediatek/mt8192/plat_sip_calls.c
index 353faf8..0fffed5 100644
--- a/plat/mediatek/mt8192/plat_sip_calls.c
+++ b/plat/mediatek/mt8192/plat_sip_calls.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -25,8 +25,8 @@
 	uint32_t rnd_val0 = 0U;
 
 	switch (smc_fid) {
-	case MTK_SIP_VCORE_CONTROL_ARCH32:
-	case MTK_SIP_VCORE_CONTROL_ARCH64:
+	case MTK_SIP_VCORE_CONTROL_AARCH32:
+	case MTK_SIP_VCORE_CONTROL_AARCH64:
 		ret = spm_vcorefs_args(x1, x2, x3, (uint64_t *)&x4);
 		SMC_RET2(handle, ret, x4);
 		break;
diff --git a/plat/mediatek/mt8192/platform.mk b/plat/mediatek/mt8192/platform.mk
index cbdaadd..4f61368 100644
--- a/plat/mediatek/mt8192/platform.mk
+++ b/plat/mediatek/mt8192/platform.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2020, MediaTek Inc. All rights reserved.
+# Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -14,6 +14,7 @@
                  -I${MTK_PLAT}/common/drivers/timer/              \
                  -I${MTK_PLAT}/common/drivers/uart/               \
                  -I${MTK_PLAT}/common/lpm/                        \
+                 -I${MTK_PLAT}/include/                           \
                  -I${MTK_PLAT_SOC}/include/                       \
                  -I${MTK_PLAT_SOC}/drivers/                       \
                  -I${MTK_PLAT_SOC}/drivers/apusys/                \
diff --git a/plat/mediatek/mt8195/plat_sip_calls.c b/plat/mediatek/mt8195/plat_sip_calls.c
index 7d3c512..1cdd622 100644
--- a/plat/mediatek/mt8195/plat_sip_calls.c
+++ b/plat/mediatek/mt8195/plat_sip_calls.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -32,8 +32,8 @@
 		ret = dp_secure_handler(x1, x2, &ret_val);
 		SMC_RET2(handle, ret, ret_val);
 		break;
-	case MTK_SIP_VCORE_CONTROL_ARCH32:
-	case MTK_SIP_VCORE_CONTROL_ARCH64:
+	case MTK_SIP_VCORE_CONTROL_AARCH32:
+	case MTK_SIP_VCORE_CONTROL_AARCH64:
 		ret = spm_vcorefs_v2_args(x1, x2, x3, &x4);
 		SMC_RET2(handle, ret, x4);
 		break;
diff --git a/plat/mediatek/mt8195/platform.mk b/plat/mediatek/mt8195/platform.mk
index a81c093..9d5b5c9 100644
--- a/plat/mediatek/mt8195/platform.mk
+++ b/plat/mediatek/mt8195/platform.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2021, MediaTek Inc. All rights reserved.
+# Copyright (c) 2021-2022, MediaTek Inc. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -14,6 +14,7 @@
                  -I${MTK_PLAT}/common/drivers/timer/              \
                  -I${MTK_PLAT}/common/drivers/uart/               \
                  -I${MTK_PLAT}/common/lpm/                        \
+                 -I${MTK_PLAT}/include/                           \
                  -I${MTK_PLAT_SOC}/drivers/apusys/                \
                  -I${MTK_PLAT_SOC}/drivers/dcm                    \
                  -I${MTK_PLAT_SOC}/drivers/dfd                    \