Merge changes from topic "xilinx-sd-tap-delay" into integration

* changes:
  plat: zynqmp: Disable ITAPDLYENA bit for zero ITAP delay
  plat: zynqmp: Check for DLL status before doing reset
diff --git a/.editorconfig b/.editorconfig
index f523ca1..12f786d 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2017-2019, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2017-2020, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -38,10 +38,10 @@
 insert_final_newline = true
 
 # [LCS] Chapter 2: Breaking long lines and strings
-#       "The limit on the length of lines is 80 columns"
+#       "The limit on the length of lines is 100 columns"
 #   This is a "soft" requirement for Arm-TF, and should not be the sole
 #   reason for changes.
-max_line_length = 80
+max_line_length = 100
 
 # [LCS] Chapter 1: Indentation
 #       "Tabs are 8 characters"
diff --git a/Makefile b/Makefile
index 9614238..2d5a5bb 100644
--- a/Makefile
+++ b/Makefile
@@ -8,7 +8,7 @@
 # Trusted Firmware Version
 #
 VERSION_MAJOR			:= 2
-VERSION_MINOR			:= 3
+VERSION_MINOR			:= 4
 
 # Default goal is build all images
 .DEFAULT_GOAL			:= all
@@ -185,13 +185,14 @@
 else
 target32-directive	= 	-target armv8a-none-eabi
 
-# Set the compiler's target architecture profile based on ARM_ARCH_MINOR option
+# Set the compiler's target architecture profile based on
+# ARM_ARCH_MAJOR ARM_ARCH_MINOR options
 ifeq (${ARM_ARCH_MINOR},0)
-march32-directive	= 	-march=armv8-a
-march64-directive	= 	-march=armv8-a
+march32-directive	= 	-march=armv${ARM_ARCH_MAJOR}-a
+march64-directive	= 	-march=armv${ARM_ARCH_MAJOR}-a
 else
-march32-directive	= 	-march=armv8.${ARM_ARCH_MINOR}-a
-march64-directive	= 	-march=armv8.${ARM_ARCH_MINOR}-a
+march32-directive	= 	-march=armv${ARM_ARCH_MAJOR}.${ARM_ARCH_MINOR}-a
+march64-directive	= 	-march=armv${ARM_ARCH_MAJOR}.${ARM_ARCH_MINOR}-a
 endif
 endif
 
@@ -203,23 +204,43 @@
 endif
 endif
 
-# Enabled required option for memory stack tagging. Currently, these options are
-# enabled only for clang and armclang compiler.
+# Get architecture feature modifiers
+arch-features		=	${ARM_ARCH_FEATURE}
+
+# Enable required options for memory stack tagging.
+# Currently, these options are enabled only for clang and armclang compiler.
 ifeq (${SUPPORT_STACK_MEMTAG},yes)
 ifdef mem_tag_arch_support
+# Check for armclang and clang compilers
 ifneq ( ,$(filter $(notdir $(CC)),armclang clang))
-march64-directive       =       -march=armv${ARM_ARCH_MAJOR}.${ARM_ARCH_MINOR}-a+memtag
+# Add "memtag" architecture feature modifier if not specified
+ifeq ( ,$(findstring memtag,$(arch-features)))
+arch-features       	:=       $(arch-features)+memtag
+endif	# memtag
 ifeq ($(notdir $(CC)),armclang)
 TF_CFLAGS		+=	-mmemtag-stack
 else ifeq ($(notdir $(CC)),clang)
 TF_CFLAGS		+=	-fsanitize=memtag
-endif
-endif
+endif	# armclang
+endif	# armclang clang
 else
 $(error "Error: stack memory tagging is not supported for architecture \
 	${ARCH},armv${ARM_ARCH_MAJOR}.${ARM_ARCH_MINOR}-a")
-endif
+endif	# mem_tag_arch_support
+endif	# SUPPORT_STACK_MEMTAG
+
+# Set the compiler's architecture feature modifiers
+ifneq ($(arch-features), none)
+# Strip "none+" from arch-features
+arch-features		:=	$(subst none+,,$(arch-features))
+ifeq ($(ARCH), aarch32)
+march32-directive	:=	$(march32-directive)+$(arch-features)
+else
+march64-directive	:=	$(march64-directive)+$(arch-features)
 endif
+# Print features
+$(info Arm Architecture Features specified: $(subst +, ,$(arch-features)))
+endif	# arch-features
 
 ifneq ($(findstring armclang,$(notdir $(CC))),)
 TF_CFLAGS_aarch32	=	-target arm-arm-none-eabi $(march32-directive)
@@ -867,6 +888,7 @@
         CTX_INCLUDE_EL2_REGS \
         CTX_INCLUDE_NEVE_REGS \
         DEBUG \
+        DISABLE_MTPMU \
         DYN_DISABLE_AUTH \
         EL3_EXCEPTION_HANDLING \
         ENABLE_AMU \
@@ -956,6 +978,7 @@
         CTX_INCLUDE_EL2_REGS \
         CTX_INCLUDE_NEVE_REGS \
         DECRYPTION_SUPPORT_${DECRYPTION_SUPPORT} \
+        DISABLE_MTPMU \
         ENABLE_AMU \
         ENABLE_ASSERTIONS \
         ENABLE_BTI \
diff --git a/bl1/bl1.mk b/bl1/bl1.mk
index b839990..d11b4ab 100644
--- a/bl1/bl1.mk
+++ b/bl1/bl1.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -16,6 +16,10 @@
 				plat/common/${ARCH}/platform_up_stack.S \
 				${MBEDTLS_SOURCES}
 
+ifeq (${DISABLE_MTPMU},1)
+BL1_SOURCES		+=	lib/extensions/mtpmu/${ARCH}/mtpmu.S
+endif
+
 ifeq (${ARCH},aarch64)
 BL1_SOURCES		+=	lib/cpus/aarch64/dsu_helpers.S		\
 				lib/el3_runtime/aarch64/context.S
diff --git a/bl2/bl2.mk b/bl2/bl2.mk
index 6dc0f18..735e7e0 100644
--- a/bl2/bl2.mk
+++ b/bl2/bl2.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -25,6 +25,10 @@
 				lib/cpus/${ARCH}/cpu_helpers.S		\
 				lib/cpus/errata_report.c
 
+ifeq (${DISABLE_MTPMU},1)
+BL2_SOURCES		+=	lib/extensions/mtpmu/${ARCH}/mtpmu.S
+endif
+
 ifeq (${ARCH},aarch64)
 BL2_SOURCES		+=	lib/cpus/aarch64/dsu_helpers.S
 endif
diff --git a/bl31/bl31.mk b/bl31/bl31.mk
index cd6549b..e299fe1 100644
--- a/bl31/bl31.mk
+++ b/bl31/bl31.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -40,6 +40,9 @@
 				${SPMD_SOURCES}					\
 				${SPM_SOURCES}
 
+ifeq (${DISABLE_MTPMU},1)
+BL31_SOURCES		+=	lib/extensions/mtpmu/aarch64/mtpmu.S
+endif
 
 ifeq (${ENABLE_PMF}, 1)
 BL31_SOURCES		+=	lib/pmf/pmf_main.c
diff --git a/bl32/sp_min/sp_min.mk b/bl32/sp_min/sp_min.mk
index 6233299..afd7ae1 100644
--- a/bl32/sp_min/sp_min.mk
+++ b/bl32/sp_min/sp_min.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -19,6 +19,10 @@
 				services/std_svc/std_svc_setup.c	\
 				${PSCI_LIB_SOURCES}
 
+ifeq (${DISABLE_MTPMU},1)
+BL32_SOURCES		+=	lib/extensions/mtpmu/aarch32/mtpmu.S
+endif
+
 ifeq (${ENABLE_PMF}, 1)
 BL32_SOURCES		+=	lib/pmf/pmf_main.c
 endif
diff --git a/bl32/tsp/aarch64/tsp_request.S b/bl32/tsp/aarch64/tsp_request.S
index 5ad16da..6e238ea 100644
--- a/bl32/tsp/aarch64/tsp_request.S
+++ b/bl32/tsp/aarch64/tsp_request.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,28 +9,19 @@
 
 	.globl tsp_get_magic
 
-
 /*
  * This function raises an SMC to retrieve arguments from secure
  * monitor/dispatcher, saves the returned arguments the array received in x0,
  * and then returns to the caller
  */
 func tsp_get_magic
-	/* Save address to stack */
-	stp	x0, xzr, [sp, #-16]!
-
 	/* Load arguments */
 	ldr	w0, _tsp_fid_get_magic
 
 	/* Raise SMC */
 	smc	#0
 
-	/* Restore address from stack */
-	ldp	x4, xzr, [sp], #16
-
-	/* Store returned arguments to the array */
-	stp	x0, x1, [x4, #0]
-
+	/* Return arguments in x1:x0 */
 	ret
 endfunc tsp_get_magic
 
diff --git a/bl32/tsp/tsp_main.c b/bl32/tsp/tsp_main.c
index e947838..01c9ec5 100644
--- a/bl32/tsp/tsp_main.c
+++ b/bl32/tsp/tsp_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -363,8 +363,10 @@
 			       uint64_t arg6,
 			       uint64_t arg7)
 {
+	uint128_t service_args;
+	uint64_t service_arg0;
+	uint64_t service_arg1;
 	uint64_t results[2];
-	uint64_t service_args[2];
 	uint32_t linear_id = plat_my_core_pos();
 
 	/* Update this cpu's statistics */
@@ -387,10 +389,12 @@
 	results[1] = arg2;
 
 	/*
-	 * Request a service back from dispatcher/secure monitor. This call
-	 * return and thereafter resume execution
+	 * Request a service back from dispatcher/secure monitor.
+	 * This call returns and thereafter resumes execution.
 	 */
-	tsp_get_magic(service_args);
+	service_args = tsp_get_magic();
+	service_arg0 = (uint64_t)service_args;
+	service_arg1 = (uint64_t)(service_args >> 64U);
 
 #if CTX_INCLUDE_MTE_REGS
 	/*
@@ -403,20 +407,20 @@
 	/* Determine the function to perform based on the function ID */
 	switch (TSP_BARE_FID(func)) {
 	case TSP_ADD:
-		results[0] += service_args[0];
-		results[1] += service_args[1];
+		results[0] += service_arg0;
+		results[1] += service_arg1;
 		break;
 	case TSP_SUB:
-		results[0] -= service_args[0];
-		results[1] -= service_args[1];
+		results[0] -= service_arg0;
+		results[1] -= service_arg1;
 		break;
 	case TSP_MUL:
-		results[0] *= service_args[0];
-		results[1] *= service_args[1];
+		results[0] *= service_arg0;
+		results[1] *= service_arg1;
 		break;
 	case TSP_DIV:
-		results[0] /= service_args[0] ? service_args[0] : 1;
-		results[1] /= service_args[1] ? service_args[1] : 1;
+		results[0] /= service_arg0 ? service_arg0 : 1;
+		results[1] /= service_arg1 ? service_arg1 : 1;
 		break;
 	default:
 		break;
diff --git a/bl32/tsp/tsp_private.h b/bl32/tsp/tsp_private.h
index cbd527f..38d9732 100644
--- a/bl32/tsp/tsp_private.h
+++ b/bl32/tsp/tsp_private.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -61,7 +61,7 @@
  */
 CASSERT(TSP_ARGS_SIZE == sizeof(tsp_args_t), assert_sp_args_size_mismatch);
 
-void tsp_get_magic(uint64_t args[4]);
+uint128_t tsp_get_magic(void);
 
 tsp_args_t *tsp_cpu_resume_main(uint64_t max_off_pwrlvl,
 				uint64_t arg1,
diff --git a/docs/about/maintainers.rst b/docs/about/maintainers.rst
index ab2d3f9..91a5621 100644
--- a/docs/about/maintainers.rst
+++ b/docs/about/maintainers.rst
@@ -516,8 +516,8 @@
 
 Texas Instruments platform port
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Andrew F. Davis <afd@ti.com>
-:G: `glneo`_
+:M: Nishanth Menon <nm@ti.com>
+:G: `nmenon`_
 :F: docs/plat/ti-k3.rst
 :F: plat/ti/
 
@@ -529,8 +529,10 @@
 
 Xilinx platform port
 ^^^^^^^^^^^^^^^^^^^^
-:M: Siva Durga Prasad Paladugu <siva.durga.paladugu@xilinx.com>
-:G: `sivadur`_
+:M: Michal Simek <michal.simek@xilinx.com>
+:G: `michalsimek`_
+:M: Venkatesh Yadav Abbarapu <venkatesh.abbarapu@xilinx.com>
+:G: `venkatesh`_
 :F: docs/plat/xilinx-zynqmp.rst
 :F: plat/xilinx/
 
@@ -614,6 +616,7 @@
 .. _ldts: https://github.com/ldts
 .. _marex: https://github.com/marex
 .. _masahir0y: https://github.com/masahir0y
+.. _michalsimek: https://github.com/michalsimek
 .. _mmind: https://github.com/mmind
 .. _mtk09422: https://github.com/mtk09422
 .. _niej: https://github.com/niej
@@ -624,13 +627,13 @@
 .. _sandrine-bailleux-arm: https://github.com/sandrine-bailleux-arm
 .. _sgorecha: https://github.com/sgorecha
 .. _shawnguo2: https://github.com/shawnguo2
-.. _sivadur: https://github.com/sivadur
 .. _smaeul: https://github.com/smaeul
 .. _soby-mathew: https://github.com/soby-mathew
 .. _thloh85-intel: https://github.com/thloh85-intel
 .. _thomas-arm: https://github.com/thomas-arm
 .. _TonyXie06: https://github.com/TonyXie06
 .. _vwadekar: https://github.com/vwadekar
+.. _venkatesh: https://github.com/vabbarap
 .. _Yann-lms: https://github.com/Yann-lms
 .. _manish-pandey-arm: https://github.com/manish-pandey-arm
 .. _mardyk01: https://github.com/mardyk01
@@ -648,5 +651,6 @@
 .. _john-powell-arm: https://github.com/john-powell-arm
 .. _raghuncstate: https://github.com/raghuncstate
 .. _CJKay: https://github.com/cjkay
+.. _nmenon: https://github.com/nmenon
 
 .. _Project Maintenance Process: https://developer.trustedfirmware.org/w/collaboration/project-maintenance-process/
diff --git a/docs/change-log.rst b/docs/change-log.rst
index 7befba4..3b8f836 100644
--- a/docs/change-log.rst
+++ b/docs/change-log.rst
@@ -4,6 +4,560 @@
 This document contains a summary of the new features, changes, fixes and known
 issues in each release of Trusted Firmware-A.
 
+Version 2.4
+-----------
+
+New Features
+^^^^^^^^^^^^
+
+- Architecture support
+    - Armv8.6-A
+        - Added support for Armv8.6 Enhanced Counter Virtualization (ECV)
+        - Added support for Armv8.6 Fine Grained Traps (FGT)
+        - Added support for Armv8.6 WFE trap delays
+
+- Bootloader images
+    - Added support for Measured Boot
+
+- Build System
+    - Added build option ``COT_DESC_IN_DTB`` to create Chain of Trust at runtime
+    - Added build option ``OPENSSL_DIR`` to direct tools to OpenSSL libraries
+    - Added build option ``RAS_TRAP_LOWER_EL_ERR_ACCESS`` to enable trapping RAS
+      register accesses from EL1/EL2 to EL3
+    - Extended build option ``BRANCH_PROTECTION`` to support branch target
+      identification
+
+- Common components
+    - Added support for exporting CPU nodes to the device tree
+    - Added support for single and dual-root Chains of Trust in secure
+      partitions
+
+- Drivers
+    - Added Broadcom RNG driver
+    - Added Marvell ``mg_conf_cm3`` driver
+    - Added System Control and Management Interface (SCMI) driver
+    - Added STMicroelectronics ETZPC driver
+
+    - Arm GICv3
+        - Added support for detecting topology at runtime
+
+    - Dual Root
+        - Added support for platform certificates
+
+    - Marvell Cache LLC
+        - Added support for mapping the entire LLC into SRAM
+
+    - Marvell CCU
+        - Added workaround for erratum 3033912
+
+    - Marvell CP110 COMPHY
+        - Added support for SATA COMPHY polarity inversion
+        - Added support for USB COMPHY polarity inversion
+        - Added workaround for erratum IPCE_COMPHY-1353
+
+    - STM32MP1 Clocks
+        - Added ``RTC`` as a gateable clock
+        - Added support for shifted clock selector bit masks
+        - Added support for using additional clocks as parents
+
+- Libraries
+    - C standard library
+        - Added support for hexadecimal and pointer format specifiers in
+          ``snprint()``
+        - Added assembly alternatives for various library functions
+
+    - CPU support
+        - Arm Cortex-A53
+            - Added workaround for erratum 1530924
+
+        - Arm Cortex-A55
+            - Added workaround for erratum 1530923
+
+        - Arm Cortex-A57
+            - Added workaround for erratum 1319537
+
+        - Arm Cortex-A76
+            - Added workaround for erratum 1165522
+            - Added workaround for erratum 1791580
+            - Added workaround for erratum 1868343
+
+        - Arm Cortex-A72
+            - Added workaround for erratum 1319367
+
+        - Arm Cortex-A77
+            - Added workaround for erratum 1508412
+            - Added workaround for erratum 1800714
+            - Added workaround for erratum 1925769
+
+        - Arm Neoverse N1
+            - Added workaround for erratum 1868343
+
+    - EL3 Runtime
+        - Added support for saving/restoring registers related to nested
+          virtualization in EL2 context switches if the architecture supports it
+
+    - FCONF
+        - Added support for Measured Boot
+        - Added support for populating Chain of Trust properties
+        - Added support for loading the ``fw_config`` image
+
+    - Measured Boot
+        - Added support for event logging
+
+- Platforms
+    - Added support for Arm Morello
+    - Added support for Arm TC0
+    - Added support for iEi PUZZLE-M801
+    - Added support for Marvell OCTEON TX2 T9130
+    - Added support for MediaTek MT8192
+    - Added support for NXP i.MX 8M Nano
+    - Added support for NXP i.MX 8M Plus
+    - Added support for QTI CHIP SC7180
+    - Added support for STM32MP151F
+    - Added support for STM32MP153F
+    - Added support for STM32MP157F
+    - Added support for STM32MP151D
+    - Added support for STM32MP153D
+    - Added support for STM32MP157D
+
+    - Arm
+        - Added support for platform-owned SPs
+        - Added support for resetting to BL31
+
+    - Arm FPGA
+        - Added support for Klein
+        - Added support for Matterhorn
+        - Added support for additional CPU clusters
+
+    - Arm FVP
+        - Added support for performing SDEI platform setup at runtime
+        - Added support for SMCCC's ``SMCCC_ARCH_SOC_ID`` command
+        - Added an ``id`` field under the NV-counter node in the device tree to
+          differentiate between trusted and non-trusted NV-counters
+        - Added support for extracting the clock frequency from the timer node
+          in the device tree
+
+    - Arm Juno
+        - Added support for SMCCC's ``SMCCC_ARCH_SOC_ID`` command
+
+    - Arm N1SDP
+        - Added support for cross-chip PCI-e
+
+    - Marvell
+        - Added support for AVS reduction
+
+    - Marvell ARMADA
+        - Added support for twin-die combined memory device
+
+    - Marvell ARMADA A8K
+        - Added support for DDR with 32-bit bus width (both ECC and non-ECC)
+
+    - Marvell AP806
+        - Added workaround for erratum FE-4265711
+
+    - Marvell AP807
+        - Added workaround for erratum 3033912
+
+    - Nvidia Tegra
+        - Added debug printouts indicating SC7 entry sequence completion
+        - Added support for SDEI
+        - Added support for stack protection
+        - Added support for GICv3
+        - Added support for SMCCC's ``SMCCC_ARCH_SOC_ID`` command
+
+    - Nvidia Tegra194
+        - Added support for RAS exception handling
+        - Added support for SPM
+
+    - NXP i.MX
+        - Added support for SDEI
+
+    - QEMU SBSA
+        - Added support for the Secure Partition Manager
+
+    - QTI
+        - Added RNG driver
+        - Added SPMI PMIC arbitrator driver
+        - Added support for SMCCC's ``SMCCC_ARCH_SOC_ID`` command
+
+    - STM32MP1
+        - Added support for exposing peripheral interfaces to the non-secure
+          world at runtime
+        - Added support for SCMI clock and reset services
+        - Added support for STM32MP15x CPU revision Z
+        - Added support for SMCCC services in ``SP_MIN``
+
+- Services
+    - Secure Payload Dispatcher
+        - Added a provision to allow clients to retrieve the service UUID
+
+    - SPMC
+        - Added secondary core endpoint information to the SPMC context
+          structure
+
+    - SPMD
+        - Added support for booting OP-TEE as a guest S-EL1 Secure Partition on
+          top of Hafnium in S-EL2
+        - Added a provision for handling SPMC messages to register secondary
+          core entry points
+        - Added support for power management operations
+
+- Tools
+    - CertCreate
+        - Added support for secure partitions
+
+    - CertTool
+        - Added support for the ``fw_config`` image
+
+    - FIPTool
+        - Added support for the ``fw_config`` image
+
+Changed
+^^^^^^^
+
+- Architecture support
+
+- Bootloader images
+
+- Build System
+    - The top-level Makefile now supports building FipTool on Windows
+    - The default value of ``KEY_SIZE`` has been changed to to 2048 when RSA is
+      in use
+    - The previously-deprecated macro ``__ASSEMBLY__`` has now been removed
+
+- Common components
+    - Certain functions that flush the console will no longer return error
+      information
+
+- Drivers
+    - Arm GIC
+        - Usage of ``drivers/arm/gic/common/gic_common.c`` has now been
+          deprecated in favour of ``drivers/arm/gic/vX/gicvX.mk``
+        - Added support for detecting the presence of a GIC600-AE
+        - Added support for detecting the presence of a GIC-Clayton
+
+    - Marvell MCI
+        - Now performs link tuning for all MCI interfaces to improve performance
+
+    - Marvell MoChi
+        - PIDI masters are no longer forced into a non-secure access level when
+          ``LLC_SRAM`` is enabled
+        - The SD/MMC controllers are now accessible from guest virtual machines
+
+    - Mbed TLS
+        - Migrated to Mbed TLS v2.24.0
+
+    - STM32 FMC2 NAND
+        - Adjusted FMC node bindings to include an EBI controller node
+
+    - STM32 Reset
+        - Added an optional timeout argument to assertion functions
+
+    - STM32MP1 Clocks
+        - Enabled several additional system clocks during initialization
+
+- Libraries
+    - C Standard Library
+        - Improved ``memset`` performance by avoiding single-byte writes
+        - Added optimized assembly variants of ``memset``
+
+    - CPU support
+        - Renamed Cortex-Hercules to Cortex-A78
+        - Renamed Cortex-Hercules AE to Cortex-A78 AE
+        - Renamed Neoverse Zeus to Neoverse V1
+
+    - Coreboot
+        - Updated ‘coreboot_get_memory_type’ API to take an extra argument as a
+          ’memory size’ that used to return a valid memory type.
+
+    - libfdt
+        - Updated to latest upstream version
+
+- Platforms
+    - Allwinner
+        - Disabled non-secure access to PRCM power control registers
+
+    - Arm
+        - ``BL32_BASE`` is now platform-dependent when ``SPD_spmd`` is enabled
+        - Added support for loading the Chain of Trust from the device tree
+        - The firmware update check is now executed only once
+        - NV-counter base addresses are now loaded from the device tree when
+          ``COT_DESC_IN_DTB`` is enabled
+        - Now loads and populates ``fw_config`` and ``tb_fw_config``
+        - FCONF population now occurs after caches have been enabled in order
+          to reduce boot times
+
+    - Arm Corstone-700
+        - Platform support has been split into both an FVP and an FPGA variant
+
+    - Arm FPGA
+        - DTB and BL33 load addresses have been given sensible default values
+        - Now reads generic timer counter frequency, GICD and GICR base
+          addresses, and UART address from DT
+        - Now treats the primary PL011 UART as an SBSA Generic UART
+
+    - Arm FVP
+        - Secure interrupt descriptions, UART parameters, clock frequencies and
+          GICv3 parameters are now queried through FCONF
+        - UART parameters are now queried through the device tree
+        - Added an owner field to Cactus secure partitions
+        - Increased the maximum size of BL2 when the Chain of Trust is loaded
+          from the device tree
+        - Reduces the maximum size of BL31
+        - The ``FVP_USE_SP804_TIMER`` and ``FVP_VE_USE_SP804_TIMER`` build
+          options have been removed in favour of a common ``USE_SP804_TIMER``
+          option
+        - Added a third Cactus partition to manifests
+        - Device tree nodes now store UUIDs in big-endian
+
+    - Arm Juno
+        - Increased the maximum size of BL2 when optimizations have not been
+          applied
+        - Reduced the maximum size of BL31 and BL32
+
+    - Marvell AP807
+        - Enabled snoop filters
+
+    - Marvell ARMADA A3K
+        - UART recovery images are now suffixed with ``.bin``
+
+    - Marvell ARMADA A8K
+        - Option ``BL31_CACHE_DISABLE`` is now disabled (``0``) by default
+
+    - Nvidia Tegra
+        - Added VPR resize supported check when processing video memory resize
+          requests
+        - Added SMMU verification to prevent potential issues caused by
+          undetected corruption of the SMMU configuration during boot
+        - The GIC CPU interface is now properly disabled after CPU off
+        - The GICv2 sources list and the ``BL31_SIZE`` definition have been made
+          platform-specific
+        - The SPE driver will no longer flush the console when writing
+          individual characters
+
+    - Nvidia Tegra194
+        - TZDRAM setup has been moved to platform-specific early boot handlers
+        - Increased verbosity of debug prints for RAS SErrors
+        - Support for powering down CPUs during CPU suspend has been removed
+        - Now verifies firewall settings before using resources
+
+    - TI K3
+        - The UART number has been made configurable through ``K3_USART``
+
+    - Rockchip RK3368
+        - The maximum number of memory map regions has been increased to 20
+
+    - Socionext Uniphier
+        - The maximum size of BL33 has been increased to support larger
+          bootloaders
+
+    - STM32
+        - Removed platform-specific DT functions in favour of using existing
+          generic alternatives
+
+    - STM32MP1
+        - Increased verbosity of exception reports in debug builds
+        - Device trees have been updated to align with the Linux kernel
+        - Now uses the ETZPC driver to configure secure-aware interfaces for
+          assignment to the non-secure world
+        - Finished good variants have been added to the board identifier
+          enumerations
+        - Non-secure access to clocks and reset domains now depends on their
+          state of registration
+        - NEON is now disabled in ``SP_MIN``
+        - The last page of ``SYSRAM`` is now used as SCMI shared memory
+        - Checks to verify platform compatibility have been added to verify that
+          an image is compatible with the chip ID of the running platform
+
+    - QEMU SBSA
+        - Removed support for Arm's Cortex-A53
+
+- Services
+    - Renamed SPCI to FF-A
+
+    - SPMD
+        - No longer forwards requests to the non-secure world when retrieving
+          partition information
+        - SPMC manifest size is now retrieved directly from SPMD instead of the
+          device tree
+        - The FF-A version handler now returns SPMD's version when the origin
+          of the call is secure, and SPMC's version when the origin of the call
+          is non-secure
+
+    - SPMC
+        - Updated the manifest to declare CPU nodes in descending order as per
+          the SPM (Hafnium) multicore requirement
+        - Updated the device tree to mark 2GB as device memory for the first
+          partition excluding trusted DRAM region (which is reserved for SPMC)
+        - Increased the number of EC contexts to the maximum number of PEs as
+          per the FF-A specification
+
+- Tools
+    - FIPTool
+        - Now returns ``0`` on ``help`` and ``help <command>``
+
+    - Marvell DoImage
+        - Updated Mbed TLS support to v2.8
+
+    - SPTool
+        - Now appends CertTool arguments
+
+Resolved Issues
+^^^^^^^^^^^^^^^
+
+- Bootloader images
+    - Fixed compilation errors for dual-root Chains of Trust caused by symbol
+      collision
+
+    - BL31
+        - Fixed compilation errors on platforms with fewer than 4 cores caused
+          by initialization code exceeding the end of the stacks
+        - Fixed compilation errors when building a position-independent image
+
+- Build System
+    - Fixed invalid empty version strings
+    - Fixed compilation errors on Windows caused by a non-portable architecture
+      revision comparison
+
+- Drivers
+    - Arm GIC
+        - Fixed spurious interrupts caused by a missing barrier
+
+    - STM32 Flexible Memory Controller 2 (FMC2) NAND driver
+        - Fixed runtime instability caused by incorrect error detection logic
+
+    - STM32MP1 Clock driver
+        - Fixed incorrectly-formatted log messages
+        - Fixed runtime instability caused by improper clock gating procedures
+
+    - STMicroelectronics Raw NAND driver
+        - Fixed runtime instability caused by incorrect unit conversion when
+          waiting for NAND readiness
+
+- Libraries
+    - AMU
+        - Fixed timeout errors caused by excess error logging
+
+    - EL3 Runtime
+        - Fixed runtime instability caused by improper register save/restore
+          routine in EL2
+
+    - FCONF
+        - Fixed failure to initialize GICv3 caused by overly-strict device tree
+          requirements
+
+    - Measured Boot
+        - Fixed driver errors caused by a missing default value for the
+          ``HASH_ALG`` build option
+
+    - SPE
+        - Fixed feature detection check that prevented CPUs supporting SVE from
+          detecting support for SPE in the non-secure world
+
+    - Translation Tables
+        - Fixed various MISRA-C 2012 static analysis violations
+
+- Platforms
+    - Allwinner A64
+        - Fixed USB issues on certain battery-powered device caused by
+          improperly activated USB power rail
+
+    - Arm
+        - Fixed compilation errors caused by increase in BL2 size
+        - Fixed compilation errors caused by missing Makefile dependencies to
+          generated files when building the FIP
+        - Fixed MISRA-C 2012 static analysis violations caused by unused
+          structures in include directives intended to be feature-gated
+
+    - Arm FPGA
+        - Fixed initialization issues caused by incorrect MPIDR topology mapping
+          logic
+
+    - Arm RD-N1-edge
+        - Fixed compilation errors caused by mismatched parentheses in Makefile
+
+    - Arm SGI
+        - Fixed crashes due to the flash memory used for cold reboot attack
+          protection not being mapped
+
+    - Intel Agilex
+        - Fixed initialization issues caused by several compounding bugs
+
+    - Marvell
+        - Fixed compilation warnings caused by multiple Makefile inclusions
+
+    - Marvell ARMADA A3K
+        - Fixed boot issue in debug builds caused by checks on the BL33 load
+          address that are not appropriate for this platform
+
+    - Nvidia Tegra
+        - Fixed incorrect delay timer reads
+        - Fixed spurious interrupts in the non-secure world during cold boot
+          caused by the arbitration bit in the memory controller not being
+          cleared
+        - Fixed faulty video memory resize sequence
+
+    - Nvidia Tegra194
+        - Fixed incorrect alignment of TZDRAM base address
+
+    - NXP iMX8M
+        - Fixed CPU hot-plug issues caused by race condition
+
+    - STM32MP1
+        - Fixed compilation errors in highly-parallel builds caused by incorrect
+          Makefile dependencies
+
+    - STM32MP157C-ED1
+        - Fixed initialization issues caused by missing device tree hash node
+
+    - Raspberry Pi 3
+        - Fixed compilation errors caused by incorrect dependency ordering in
+          Makefile
+
+    - Rockchip
+        - Fixed initialization issues caused by non-critical errors when parsing
+          FDT being treated as critical
+
+    - Rockchip RK3368
+        - Fixed runtime instability caused by incorrect CPUID shift value
+
+    - QEMU
+        - Fixed compilation errors caused by incorrect dependency ordering in
+          Makefile
+
+    - QEMU SBSA
+        - Fixed initialization issues caused by FDT exceeding reserved memory
+          size
+
+    - QTI
+        - Fixed compilation errors caused by inclusion of a non-existent file
+
+- Services
+    - FF-A (previously SPCI)
+        - Fixed SPMD aborts caused by incorrect behaviour when the manifest is
+          page-aligned
+
+- Tools
+    - Fixed compilation issues when compiling tools from within their respective
+      directories
+
+    - FIPTool
+        - Fixed command line parsing issues on Windows when using arguments
+          whose names also happen to be a subset of another's
+
+    - Marvell DoImage
+        - Fixed PKCS signature verification errors at boot on some platforms
+          caused by generation of misaligned images
+
+Known Issues
+^^^^^^^^^^^^
+
+- Platforms
+    - NVIDIA Tegra
+        - Signed comparison compiler warnings occurring in libfdt are currently
+          being worked around by disabling the warning for the platform until
+          the underlying issue is resolved in libfdt
+
 Version 2.3
 -----------
 
@@ -32,7 +586,7 @@
 - Build System
    - Add support for documentation build as a target in Makefile
 
-   - Add ``COT`` build option to select the chain of trust to use when the
+   - Add ``COT`` build option to select the Chain of Trust to use when the
      Trusted Boot feature is enabled (default: ``tbbr``).
 
    - Added creation and injection of secure partition packages into the FIP.
diff --git a/docs/components/psa-ffa-manifest-binding.rst b/docs/components/psa-ffa-manifest-binding.rst
index 09894ae..af79074 100644
--- a/docs/components/psa-ffa-manifest-binding.rst
+++ b/docs/components/psa-ffa-manifest-binding.rst
@@ -13,7 +13,7 @@
 - compatible [mandatory]
    - value type: <string>
    - Must be the string "arm,ffa-manifest-X.Y" which specifies the major and
-     minor versions fo the device tree binding for the FFA manifest represented
+     minor versions of the device tree binding for the FFA manifest represented
      by this node. The minor number is incremented if the binding changes in a
      backwards compatible manner.
 
@@ -240,7 +240,7 @@
 - exclusive-access
    - value type: <empty>
    - Presence of this field implies that this endpoint must be granted exclusive
-     access and ownership of this devices's MMIO region.
+     access and ownership of this device's MMIO region.
 
 --------------
 
diff --git a/docs/design/cpu-specific-build-macros.rst b/docs/design/cpu-specific-build-macros.rst
index c976b8b..d859cc5 100644
--- a/docs/design/cpu-specific-build-macros.rst
+++ b/docs/design/cpu-specific-build-macros.rst
@@ -241,9 +241,6 @@
 -  ``ERRATA_A76_1791580``: This applies errata 1791580 workaround to Cortex-A76
    CPU. This needs to be enabled only for revision <= r4p0 of the CPU.
 
--  ``ERRATA_A76_1800710``: This applies errata 1800710 workaround to Cortex-A76
-   CPU. This needs to be enabled only for revision <= r4p0 of the CPU.
-
 -  ``ERRATA_A76_1165522``: This applies errata 1165522 workaround to all
    revisions of Cortex-A76 CPU. This errata is fixed in r3p0 but due to
    limitation of errata framework this errata is applied to all revisions
@@ -252,14 +249,14 @@
 -  ``ERRATA_A76_1868343``: This applies errata 1868343 workaround to Cortex-A76
    CPU. This needs to be enabled only for revision <= r4p0 of the CPU.
 
+-  ``ERRATA_A76_1946160``: This applies errata 1946160 workaround to Cortex-A76
+   CPU. This needs to be enabled only for revisions r3p0 - r4p1 of the CPU.
+
 For Cortex-A77, the following errata build flags are defined :
 
 -  ``ERRATA_A77_1508412``: This applies errata 1508412 workaround to Cortex-A77
    CPU. This needs to be enabled only for revision <= r1p0 of the CPU.
 
--  ``ERRATA_A77_1800714``: This applies errata 1800714 workaround to Cortex-A77
-   CPU. This needs to be enabled only for revision <= r1p1 of the CPU.
-
 -  ``ERRATA_A77_1925769``: This applies errata 1925769 workaround to Cortex-A77
    CPU. This needs to be enabled only for revision <= r1p1 of the CPU.
 
@@ -369,10 +366,11 @@
    Cortex-A57 based platform must make its own decision on whether to use
    the optimization. This flag is disabled by default.
 
--  ``NEOVERSE_N1_EXTERNAL_LLC``: This flag indicates that an external last
+-  ``NEOVERSE_Nx_EXTERNAL_LLC``: This flag indicates that an external last
    level cache(LLC) is present in the system, and that the DataSource field
    on the master CHI interface indicates when data is returned from the LLC.
    This is used to control how the LL_CACHE* PMU events count.
+   Default value is 0 (Disabled).
 
 --------------
 
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index 8adf4ad..16de410 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -26,6 +26,12 @@
    ``aarch64`` or ``aarch32`` as values. By default, it is defined to
    ``aarch64``.
 
+-  ``ARM_ARCH_FEATURE``: Optional Arm Architecture build option which specifies
+   one or more feature modifiers. This option has the form ``[no]feature+...``
+   and defaults to ``none``. It translates into compiler option
+   ``-march=armvX[.Y]-a+[no]feature+...``. See compiler's documentation for the
+   list of supported feature modifiers.
+
 -  ``ARM_ARCH_MAJOR``: The major version of Arm Architecture to target when
    compiling TF-A. Its value must be numeric, and defaults to 8 . See also,
    *Armv8 Architecture Extensions* and *Armv7 Architecture Extensions* in
@@ -185,6 +191,11 @@
    of the binary image. If set to 1, then only the ELF image is built.
    0 is the default.
 
+-  ``DISABLE_MTPMU``: Boolean option to disable FEAT_MTPMU if implemented
+   (Armv8.6 onwards). Its default value is 0 to keep consistency with platforms
+   that do not implement FEAT_MTPMU. For more information on FEAT_MTPMU,
+   check the latest Arm ARM.
+
 -  ``DYN_DISABLE_AUTH``: Provides the capability to dynamically disable Trusted
    Board Boot authentication at runtime. This option is meant to be enabled only
    for development platforms. ``TRUSTED_BOARD_BOOT`` flag must be set if this
diff --git a/docs/getting_started/porting-guide.rst b/docs/getting_started/porting-guide.rst
index 19e26e4..d063ec7 100644
--- a/docs/getting_started/porting-guide.rst
+++ b/docs/getting_started/porting-guide.rst
@@ -116,7 +116,7 @@
    by ``plat/common/aarch64/platform_mp_stack.S`` and
    ``plat/common/aarch64/platform_up_stack.S``.
 
--  **define : CACHE_WRITEBACK_GRANULE**
+-  **#define : CACHE_WRITEBACK_GRANULE**
 
    Defines the size in bits of the largest cache line across all the cache
    levels in the platform.
diff --git a/docs/plat/arm/arm-build-options.rst b/docs/plat/arm/arm-build-options.rst
index 2e50068..a1d2313 100644
--- a/docs/plat/arm/arm-build-options.rst
+++ b/docs/plat/arm/arm-build-options.rst
@@ -94,6 +94,10 @@
 -  ``ARM_SPMC_MANIFEST_DTS`` : path to an alternate manifest file used as the
    SPMC Core manifest. Valid when ``SPD=spmd`` is selected.
 
+-  ``OPTEE_SP_FW_CONFIG``: DTC build flag to include OP-TEE as SP in tb_fw_config
+   device tree. This flag is defined only when ``ARM_SPMC_MANIFEST_DTS`` manifest
+   file name contains pattern optee_sp.
+
 For a better understanding of these options, the Arm development platform memory
 map is explained in the :ref:`Firmware Design`.
 
diff --git a/docs/plat/arm/fvp/index.rst b/docs/plat/arm/fvp/index.rst
index 3a13268..f643f6b 100644
--- a/docs/plat/arm/fvp/index.rst
+++ b/docs/plat/arm/fvp/index.rst
@@ -50,6 +50,7 @@
 -  ``FVP_RD_N1_edge``      (Version 11.10 build 36)
 -  ``FVP_RD_N1_edge_dual`` (Version 11.10 build 36)
 -  ``FVP_RD_Daniel``       (Version 11.10 build 36)
+-  ``FVP_RD_N2``           (Version 11.13 build 10)
 -  ``FVP_TC0``             (Version 0.0 build 6114)
 -  ``Foundation_Platform``
 
diff --git a/docs/plat/marvell/armada/build.rst b/docs/plat/marvell/armada/build.rst
index e21fb3c..54182cb 100644
--- a/docs/plat/marvell/armada/build.rst
+++ b/docs/plat/marvell/armada/build.rst
@@ -61,17 +61,17 @@
 
         Defines the level of logging which will be purged to the default output port.
 
-        LOG_LEVEL_NONE		0
-        LOG_LEVEL_ERROR		10
-        LOG_LEVEL_NOTICE	20
-        LOG_LEVEL_WARNING	30
-        LOG_LEVEL_INFO		40
-        LOG_LEVEL_VERBOSE	50
+            -  0 - LOG_LEVEL_NONE
+            - 10 - LOG_LEVEL_ERROR
+            - 20 - LOG_LEVEL_NOTICE (default for DEBUG=0)
+            - 30 - LOG_LEVEL_WARNING
+            - 40 - LOG_LEVEL_INFO (default for DEBUG=1)
+            - 50 - LOG_LEVEL_VERBOSE
 
 - USE_COHERENT_MEM
 
         This flag determines whether to include the coherent memory region in the
-        BL memory map or not.
+        BL memory map or not. Enabled by default.
 
 - LLC_ENABLE
 
@@ -122,25 +122,25 @@
         For Armada37x0 only, the DDR topology map index/name, default is 0.
 
         Supported Options:
-            - DDR3 1CS (0): DB-88F3720-DDR3-Modular (512MB); EspressoBIN (512MB)
-            - DDR4 1CS (1): DB-88F3720-DDR4-Modular (512MB)
-            - DDR3 2CS (2): EspressoBIN V3-V5 (1GB 2CS)
-            - DDR4 2CS (3): DB-88F3720-DDR4-Modular (4GB)
-            - DDR3 1CS (4): DB-88F3720-DDR3-Modular (1GB); EspressoBIN V3-V5 (1GB 1CS)
-            - DDR4 1CS (5): EspressoBin V7 (1GB)
-            - DDR4 2CS (6): EspressoBin V7 (2GB)
-            - DDR3 2CS (7): EspressoBin V3-V5 (2GB)
-            - CUSTOMER (CUST): Customer board, DDR3 1CS 512MB
+            -    0 - DDR3 1CS: DB-88F3720-DDR3-Modular (512MB); EspressoBIN (512MB)
+            -    1 - DDR4 1CS: DB-88F3720-DDR4-Modular (512MB)
+            -    2 - DDR3 2CS: EspressoBIN V3-V5 (1GB 2CS)
+            -    3 - DDR4 2CS: DB-88F3720-DDR4-Modular (4GB)
+            -    4 - DDR3 1CS: DB-88F3720-DDR3-Modular (1GB); EspressoBIN V3-V5 (1GB 1CS)
+            -    5 - DDR4 1CS: EspressoBin V7 (1GB)
+            -    6 - DDR4 2CS: EspressoBin V7 (2GB)
+            -    7 - DDR3 2CS: EspressoBin V3-V5 (2GB)
+            - CUST - CUSTOMER: Customer board, DDR3 1CS 512MB
 
 - CLOCKSPRESET
 
         For Armada37x0 only, the clock tree configuration preset including CPU and DDR frequency,
         default is CPU_800_DDR_800.
 
-            - CPU_600_DDR_600	-	CPU at 600 MHz, DDR at 600 MHz
-            - CPU_800_DDR_800	-	CPU at 800 MHz, DDR at 800 MHz
-            - CPU_1000_DDR_800	-	CPU at 1000 MHz, DDR at 800 MHz
-            - CPU_1200_DDR_750	-	CPU at 1200 MHz, DDR at 750 MHz
+            - CPU_600_DDR_600  - CPU at 600 MHz, DDR at 600 MHz
+            - CPU_800_DDR_800  - CPU at 800 MHz, DDR at 800 MHz
+            - CPU_1000_DDR_800 - CPU at 1000 MHz, DDR at 800 MHz
+            - CPU_1200_DDR_750 - CPU at 1200 MHz, DDR at 750 MHz
 
 - BOOTDEV
 
@@ -176,33 +176,48 @@
 
 - WTP
 
-    For Armada37x0 only, use this parameter to point to wtptools source code
-    directory, which can be found as a3700_utils.zip in the release. Usage
-    example: ``WTP=/path/to/a3700_utils``
+        For Armada37x0 only, use this parameter to point to wtptools source code
+        directory, which can be found as a3700_utils.zip in the release. Usage
+        example: ``WTP=/path/to/a3700_utils``
 
-    For example, in order to build the image in debug mode with log level up to 'notice' level run
+- CRYPTOPP_PATH
 
-    .. code:: shell
+        For Armada37x0 only, use this parameter tp point to Crypto++ source code
+        directory, which is required for building WTP image tool.
 
-        > make DEBUG=1 USE_COHERENT_MEM=0 LOG_LEVEL=20 PLAT=<MARVELL_PLATFORM> all fip
 
-    And if we want to build a Armada37x0 image in debug mode with log level up to 'notice' level,
-    the image has the preset CPU at 1000 MHz, preset DDR3 at 800 MHz, the DDR topology of DDR4 2CS,
-    the image boot from SPI NOR flash partition 0, and the image is non trusted in WTP, the command
-    line is as following
+For example, in order to build the image in debug mode with log level up to 'notice' level run
 
-    .. code:: shell
+.. code:: shell
+
+    > make DEBUG=1 USE_COHERENT_MEM=0 LOG_LEVEL=20 PLAT=<MARVELL_PLATFORM> mrvl_flash
 
-        > make DEBUG=1 USE_COHERENT_MEM=0 LOG_LEVEL=20 CLOCKSPRESET=CPU_1000_DDR_800 \
-            MARVELL_SECURE_BOOT=0 DDR_TOPOLOGY=3 BOOTDEV=SPINOR PARTNUM=0 PLAT=a3700 all fip
+And if we want to build a Armada37x0 image in debug mode with log level up to 'notice' level,
+the image has the preset CPU at 1000 MHz, preset DDR3 at 800 MHz, the DDR topology of DDR4 2CS,
+the image boot from SPI NOR flash partition 0, and the image is non trusted in WTP, the command
+line is as following
 
-    Supported MARVELL_PLATFORM are:
-        - a3700 (for both A3720 DB and EspressoBin)
-        - a70x0
-        - a70x0_amc (for AMC board)
-        - a80x0
-        - a80x0_mcbin (for MacchiatoBin)
-        - t9130 (OcteonTX2 CN913x)
+.. code:: shell
+
+    > make DEBUG=1 USE_COHERENT_MEM=0 LOG_LEVEL=20 CLOCKSPRESET=CPU_1000_DDR_800 \
+        MARVELL_SECURE_BOOT=0 DDR_TOPOLOGY=3 BOOTDEV=SPINOR PARTNUM=0 PLAT=a3700 \
+        MV_DDR_PATH=/path/to/mv-ddr-marvell/ WTP=/path/to/A3700-utils-marvell/ \
+        CRYPTOPP_PATH=/path/to/cryptopp/ BL33=/path/to/u-boot.bin \
+        all fip mrvl_bootimage mrvl_flash
+
+To build just TF-A without WTMI image (useful for A3720 Turris MOX board), run following command:
+
+.. code:: shell
+
+    > make USE_COHERENT_MEM=0 PLAT=a3700 BL33=/path/to/u-boot.bin CROSS_COMPILE=aarch64-linux-gnu- mrvl_bootimage
+
+Supported MARVELL_PLATFORM are:
+    - a3700 (for both A3720 DB and EspressoBin)
+    - a70x0
+    - a70x0_amc (for AMC board)
+    - a80x0
+    - a80x0_mcbin (for MacchiatoBin)
+    - t9130 (OcteonTX2 CN913x)
 
 Special Build Flags
 --------------------
@@ -224,7 +239,7 @@
 
 Build output
 ------------
-Marvell's TF-A compilation generates 7 files:
+Marvell's TF-A compilation generates 8 files:
 
     - ble.bin		- BLe image
     - bl1.bin		- BL1 image
@@ -234,7 +249,13 @@
     - boot-image.bin	- TF-A image (contains BL1 and FIP images)
     - flash-image.bin	- Image which contains boot-image.bin and SPL image.
       Should be placed on the boot flash/device.
+    - uart-images.tgz.bin - GZIPed TAR archive which contains Armada37x0 images
+      for booting via UART. Could be loaded via Marvell's WtpDownload tool from
+      A3700-utils-marvell repository.
 
+Additional make target ``mrvl_bootimage`` produce ``boot-image.bin`` file and target
+``mrvl_flash`` produce final ``flash-image.bin`` and ``uart-images.tgz.bin`` files.
+
 
 Tools and external components installation
 ------------------------------------------
@@ -269,6 +290,10 @@
 
     https://github.com/MarvellEmbeddedProcessors/A3700-utils-marvell.git
 
+(4) Crypto++ library available at the following repository:
+
+    https://github.com/weidai11/cryptopp.git
+
 Armada70x0 and Armada80x0 Builds require installation of an additional component
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
diff --git a/docs/process/coding-style.rst b/docs/process/coding-style.rst
index 94fd85e..be13b14 100644
--- a/docs/process/coding-style.rst
+++ b/docs/process/coding-style.rst
@@ -101,7 +101,7 @@
 parentheses.
 
 Control statements (``if``, ``for``, ``switch``, ``while``, etc) must be
-separated from the following open paranthesis by a single space. The previous
+separated from the following open parenthesis by a single space. The previous
 example illustrates this for an ``if`` statement.
 
 Line Length
diff --git a/docs/resources/diagrams/plantuml/fip-secure-partitions.puml b/docs/resources/diagrams/plantuml/fip-secure-partitions.puml
index 40621db..9457e32 100644
--- a/docs/resources/diagrams/plantuml/fip-secure-partitions.puml
+++ b/docs/resources/diagrams/plantuml/fip-secure-partitions.puml
@@ -13,6 +13,7 @@
  ===
  UUID = xxx
  load_address = 0xaaa
+ owner = "Sip"
  ...
  ]
 }
@@ -24,9 +25,26 @@
  ===
  UUID = yyy
  load_address = 0xbbb
+ owner = "Plat"
  ]
 }
 
+artifact tb_fw_config.dts [
+ tb_fw_config.dts
+ ----
+ secure-partitions
+ ===
+ spkg_1 UUID
+ spkg_1 load_address
+ ---
+ spkg_2 UUID
+ spkg_2 load_address
+ ---
+ ...
+ ===
+ ...<rest of the nodes>
+]
+
 artifact config.json [
  SP_LAYOUT.json
  ===
@@ -41,31 +59,22 @@
 
 control sp_mk_generator
 
-artifact fconf_node [
- fconf_sp.dts
- ===
- spkg_1 UUID
- spkg_1 load_address
- ---
- spkg_2 UUID
- spkg_2 load_address
-]
-
 artifact sp_gen [
  sp_gen.mk
  ===
  FDT_SOURCE = ...
  SPTOOL_ARGS = ...
- FIP_ARG = ...
+ FIP_ARGS = ...
+ CRT_ARGS = ...
 ]
 
 control dtc
 control sptool
 
-artifact FW_CONFIG
+artifact tb_fw_config.dtb
 
 artifact spkg_1 [
- spkg_1.bin
+ sp1.pkg
  ===
  <i>header</i>
  ---
@@ -75,27 +84,56 @@
 ]
 
 artifact spkg_2 [
- spkg_2.bin
+ sp2.pkg
+ ===
+ <i>header</i>
+ ---
+ manifest
+ ---
+ binary
+]
+
+artifact signed_tb_fw_config.dtb [
+ tb_fw_config.dtb (signed)
+]
+
+artifact signed_spkg_1 [
+ sp1.pkg (signed)
+ ===
+ <i>header</i>
+ ---
+ manifest
+ ---
+ binary
+ ---
+ <i>signature</I>
+]
+
+artifact signed_spkg_2 [
+ sp2.pkg (signed)
  ===
  <i>header</i>
  ---
  manifest
  ---
  binary
+ ---
+ <i>signature</I>
 ]
 
+control crttool
 control fiptool
 
 artifact fip [
  fip.bin
  ===
- FW_CONFIG.dtb
+ tb_fw_config.dtb (signed)
  ---
  ...
  ---
- SPKG1
+ sp1.pkg  (signed & SiP owned)
  ---
- SPKG2
+ sp2.pkg  (signed & Platform owned)
  ---
  ...
 ]
@@ -103,20 +141,27 @@
 config.json .up.> SP_vendor_1
 config.json .up.> SP_vendor_2
 config.json --> sp_mk_generator
-sp_mk_generator --> fconf_node
 sp_mk_generator --> sp_gen
-
+sp_gen --> fiptool
+sp_gen --> cert_create
 sp_gen --> sptool
+
 sptool --> spkg_1
 sptool --> spkg_2
 
-fconf_node -down-> dtc
-dtc --> FW_CONFIG
+spkg_1 --> cert_create
+spkg_2 --> cert_create
+cert_create --> signed_spkg_1
+cert_create --> signed_spkg_2
 
-sp_gen --> fiptool
-FW_CONFIG --> fiptool
-spkg_1 -down-> fiptool
-spkg_2 -down-> fiptool
+tb_fw_config.dts --> dtc
+dtc --> tb_fw_config.dtb
+tb_fw_config.dtb --> cert_create
+cert_create --> signed_tb_fw_config.dtb
+
+signed_tb_fw_config.dtb --> fiptool
+signed_spkg_1 -down-> fiptool
+signed_spkg_2 -down-> fiptool
 fiptool -down-> fip
 
 @enduml
diff --git a/drivers/marvell/uart/a3700_console.S b/drivers/marvell/uart/a3700_console.S
index d184a2d..dc374ee 100644
--- a/drivers/marvell/uart/a3700_console.S
+++ b/drivers/marvell/uart/a3700_console.S
@@ -232,6 +232,11 @@
 	 * ---------------------------------------------
 	 */
 func console_a3700_core_flush
+	/* Wait for the TX FIFO to be empty */
+1:	ldr	w1, [x0, #UART_STATUS_REG]
+	and	w1, w1, #UARTLSR_TXFIFOEMPTY
+	cmp	w1, #UARTLSR_TXFIFOEMPTY
+	b.ne	1b
 	ret
 endfunc console_a3700_core_flush
 
diff --git a/drivers/renesas/rcar/console/rcar_printf.c b/drivers/renesas/rcar/console/rcar_printf.c
index e75b9f4..ad074fe 100644
--- a/drivers/renesas/rcar/console/rcar_printf.c
+++ b/drivers/renesas/rcar/console/rcar_printf.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved.
+ * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -19,11 +19,22 @@
 
 #define INDEX_TIMER_COUNT	(4U)
 
+#define RCAR_LOG_HEAD	(('T' << 0) | ('L' << 8) | ('O' << 16) | ('G' << 24))
+
+/*
+ * The log is initialized and used before BL31 xlat tables are initialized,
+ * therefore the log memory is a device memory at that point. Make sure the
+ * memory is correclty aligned and accessed only with up-to 32bit, aligned,
+ * writes.
+ */
+CASSERT((RCAR_BL31_LOG_BASE & 0x7) == 0, assert_bl31_log_base_unaligned);
+CASSERT((RCAR_BL31_LOG_MAX & 0x7) == 0, assert_bl31_log_max_unaligned);
+
 extern RCAR_INSTANTIATE_LOCK typedef struct log_head {
-	uint8_t head[4];
+	uint32_t head;
 	uint32_t index;
 	uint32_t size;
-	uint8_t res[4];
+	uint32_t res;
 } loghead_t;
 
 typedef struct log_map {
@@ -66,15 +77,12 @@
 
 int32_t rcar_log_init(void)
 {
-
-	static const uint8_t const_header[] = "TLOG";
-	logmap_t *t_log;
+	logmap_t *t_log = (logmap_t *)RCAR_BL31_LOG_BASE;
+	uint32_t *log_data = (uint32_t *)t_log->log_data;
 	int16_t init_flag = 0;
+	int i;
 
-	t_log = (logmap_t *) RCAR_BL31_LOG_BASE;
-	if (memcmp
-	    ((const void *)t_log->header.head, (const void *)const_header,
-	     sizeof(t_log->header.head)) != 0) {
+	if (t_log->header.head != RCAR_LOG_HEAD) {
 		/*
 		 * Log header is not "TLOG", then log area initialize
 		 */
@@ -87,11 +95,10 @@
 		init_flag = 1;
 	}
 	if (init_flag == 1) {
-		(void)memset((void *)t_log->log_data, 0,
-			     (size_t) RCAR_BL31_LOG_MAX);
-		(void)memcpy((void *)t_log->header.head,
-			     (const void *)const_header,
-			     sizeof(t_log->header.head));
+		for (i = 0; i < RCAR_BL31_LOG_MAX; i += 4)
+			*log_data++ = 0;
+
+		t_log->header.head = RCAR_LOG_HEAD;
 		t_log->header.index = 0U;
 		t_log->header.size = 0U;
 	}
diff --git a/fdts/morello-fvp.dts b/fdts/morello-fvp.dts
index 2218b2a..699dc23 100644
--- a/fdts/morello-fvp.dts
+++ b/fdts/morello-fvp.dts
@@ -80,8 +80,14 @@
 		interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
 	};
 
+	virtio_net@1c180000 {
+		compatible = "virtio,mmio";
+		reg = <0x0 0x1c180000 0x0 0x200>;
+		interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
 	virtio_rng@1c190000 {
-		compatible = "virtio,mmio","virtio-rng";
+		compatible = "virtio,mmio";
 		reg = <0x0 0x1c190000 0x0 0x200>;
 		interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
 	};
diff --git a/fdts/tc0.dts b/fdts/tc0.dts
index 763c813..5438474 100644
--- a/fdts/tc0.dts
+++ b/fdts/tc0.dts
@@ -109,6 +109,17 @@
 		reg = <0x0 0x80000000 0x0 0x7d000000>;
 	};
 
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		optee@0xfce00000 {
+			reg = <0x00000000 0xfce00000 0 0x00200000>;
+			no-map;
+		};
+	};
+
 	psci {
 		compatible = "arm,psci-1.0", "arm,psci-0.2", "arm,psci";
 		method = "smc";
@@ -370,4 +381,17 @@
 			};
 		};
 	};
+
+	ffa {
+		compatible = "arm,ffa";
+		conduit = "smc";
+		mem_share_buffer = "tx";
+	};
+
+	firmware {
+		optee {
+		      compatible = "linaro,optee-tz";
+		      method = "ffa";
+		};
+	};
 };
diff --git a/include/arch/aarch32/arch.h b/include/arch/aarch32/arch.h
index db8938f..c30073b 100644
--- a/include/arch/aarch32/arch.h
+++ b/include/arch/aarch32/arch.h
@@ -102,6 +102,11 @@
 /* CSSELR definitions */
 #define LEVEL_SHIFT		U(1)
 
+/* ID_DFR1_EL1 definitions */
+#define ID_DFR1_MTPMU_SHIFT	U(0)
+#define ID_DFR1_MTPMU_MASK	U(0xf)
+#define ID_DFR1_MTPMU_SUPPORTED	U(1)
+
 /* ID_MMFR4 definitions */
 #define ID_MMFR4_CNP_SHIFT	U(12)
 #define ID_MMFR4_CNP_LENGTH	U(4)
@@ -126,6 +131,9 @@
 #define ID_PFR1_GENTIMER_MASK	U(0xf)
 #define ID_PFR1_GIC_SHIFT	U(28)
 #define ID_PFR1_GIC_MASK	U(0xf)
+#define ID_PFR1_SEC_SHIFT	U(4)
+#define ID_PFR1_SEC_MASK	U(0xf)
+#define ID_PFR1_ELx_ENABLED	U(1)
 
 /* SCTLR definitions */
 #define SCTLR_RES1_DEF		((U(1) << 23) | (U(1) << 22) | (U(1) << 4) | \
@@ -164,6 +172,7 @@
 #define SDCR_SCCD_BIT		(U(1) << 23)
 #define SDCR_SPME_BIT		(U(1) << 17)
 #define SDCR_RESET_VAL		U(0x0)
+#define SDCR_MTPME_BIT		(U(1) << 28)
 
 /* HSCTLR definitions */
 #define HSCTLR_RES1	((U(1) << 29) | (U(1) << 28) | (U(1) << 23) | \
@@ -244,6 +253,7 @@
 #define VTTBR_BADDR_SHIFT	U(0)
 
 /* HDCR definitions */
+#define HDCR_MTPME_BIT		(U(1) << 28)
 #define HDCR_HLP_BIT		(U(1) << 26)
 #define HDCR_HPME_BIT		(U(1) << 7)
 #define HDCR_RESET_VAL		U(0x0)
@@ -503,6 +513,7 @@
 #define CTR		p15, 0, c0, c0, 1
 #define CNTFRQ		p15, 0, c14, c0, 0
 #define ID_MMFR4	p15, 0, c0, c2, 6
+#define ID_DFR1		p15, 0, c0, c3, 5
 #define ID_PFR0		p15, 0, c0, c1, 0
 #define ID_PFR1		p15, 0, c0, c1, 1
 #define MAIR0		p15, 0, c10, c2, 0
diff --git a/include/arch/aarch32/el3_common_macros.S b/include/arch/aarch32/el3_common_macros.S
index 4fd746d..580dd95 100644
--- a/include/arch/aarch32/el3_common_macros.S
+++ b/include/arch/aarch32/el3_common_macros.S
@@ -242,6 +242,10 @@
 	cps	#MODE32_mon
 	isb
 
+#if DISABLE_MTPMU
+	bl	mtpmu_disable
+#endif
+
 	.if \_warm_boot_mailbox
 		/* -------------------------------------------------------------
 		 * This code will be executed for both warm and cold resets.
diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h
index 33e1134..09e598a 100644
--- a/include/arch/aarch64/arch.h
+++ b/include/arch/aarch64/arch.h
@@ -188,6 +188,11 @@
 #define ID_AA64DFR0_PMS_SHIFT	U(32)
 #define ID_AA64DFR0_PMS_MASK	ULL(0xf)
 
+/* ID_AA64DFR0_EL1.MTPMU definitions (for ARMv8.6+) */
+#define ID_AA64DFR0_MTPMU_SHIFT		U(48)
+#define ID_AA64DFR0_MTPMU_MASK		ULL(0xf)
+#define ID_AA64DFR0_MTPMU_SUPPORTED	ULL(1)
+
 /* ID_AA64ISAR1_EL1 definitions */
 #define ID_AA64ISAR1_EL1	S3_0_C0_C6_1
 #define ID_AA64ISAR1_GPI_SHIFT	U(28)
@@ -243,6 +248,13 @@
 #define ID_AA64MMFR1_EL1_TWED_SUPPORTED		ULL(0x1)
 #define ID_AA64MMFR1_EL1_TWED_NOT_SUPPORTED	ULL(0x0)
 
+#define ID_AA64MMFR1_EL1_PAN_SHIFT		U(20)
+#define ID_AA64MMFR1_EL1_PAN_MASK		ULL(0xf)
+#define ID_AA64MMFR1_EL1_PAN_NOT_SUPPORTED	ULL(0x0)
+#define ID_AA64MMFR1_EL1_PAN_SUPPORTED		ULL(0x1)
+#define ID_AA64MMFR1_EL1_PAN2_SUPPORTED		ULL(0x2)
+#define ID_AA64MMFR1_EL1_PAN3_SUPPORTED		ULL(0x3)
+
 /* ID_AA64MMFR2_EL1 definitions */
 #define ID_AA64MMFR2_EL1		S3_0_C0_C7_2
 
@@ -266,9 +278,17 @@
 #define ID_AA64PFR1_EL1_MTE_SHIFT	U(8)
 #define ID_AA64PFR1_EL1_MTE_MASK	ULL(0xf)
 
-#define MTE_UNIMPLEMENTED	ULL(0)
-#define MTE_IMPLEMENTED_EL0	ULL(1)	/* MTE is only implemented at EL0 */
-#define MTE_IMPLEMENTED_ELX	ULL(2)	/* MTE is implemented at all ELs */
+/* Memory Tagging Extension is not implemented */
+#define MTE_UNIMPLEMENTED	U(0)
+/* FEAT_MTE: MTE instructions accessible at EL0 are implemented */
+#define MTE_IMPLEMENTED_EL0	U(1)
+/* FEAT_MTE2: Full MTE is implemented */
+#define MTE_IMPLEMENTED_ELX	U(2)
+/*
+ * FEAT_MTE3: MTE is implemented with support for
+ * asymmetric Tag Check Fault handling
+ */
+#define MTE_IMPLEMENTED_ASY	U(3)
 
 #define ID_AA64PFR1_MPAM_FRAC_SHIFT	ULL(16)
 #define ID_AA64PFR1_MPAM_FRAC_MASK	ULL(0xf)
@@ -286,6 +306,7 @@
 
 #define SCTLR_EL1_RES1	((UL(1) << 29) | (UL(1) << 28) | (UL(1) << 23) | \
 			 (UL(1) << 22) | (UL(1) << 20) | (UL(1) << 11))
+
 #define SCTLR_AARCH32_EL1_RES1 \
 			((U(1) << 23) | (U(1) << 22) | (U(1) << 11) | \
 			 (U(1) << 4) | (U(1) << 3))
@@ -300,9 +321,12 @@
 #define SCTLR_SA_BIT		(ULL(1) << 3)
 #define SCTLR_SA0_BIT		(ULL(1) << 4)
 #define SCTLR_CP15BEN_BIT	(ULL(1) << 5)
+#define SCTLR_nAA_BIT		(ULL(1) << 6)
 #define SCTLR_ITD_BIT		(ULL(1) << 7)
 #define SCTLR_SED_BIT		(ULL(1) << 8)
 #define SCTLR_UMA_BIT		(ULL(1) << 9)
+#define SCTLR_EnRCTX_BIT	(ULL(1) << 10)
+#define SCTLR_EOS_BIT		(ULL(1) << 11)
 #define SCTLR_I_BIT		(ULL(1) << 12)
 #define SCTLR_EnDB_BIT		(ULL(1) << 13)
 #define SCTLR_DZE_BIT		(ULL(1) << 14)
@@ -310,21 +334,65 @@
 #define SCTLR_NTWI_BIT		(ULL(1) << 16)
 #define SCTLR_NTWE_BIT		(ULL(1) << 18)
 #define SCTLR_WXN_BIT		(ULL(1) << 19)
-#define SCTLR_UWXN_BIT		(ULL(1) << 20)
+#define SCTLR_TSCXT_BIT		(ULL(1) << 20)
 #define SCTLR_IESB_BIT		(ULL(1) << 21)
+#define SCTLR_EIS_BIT		(ULL(1) << 22)
+#define SCTLR_SPAN_BIT		(ULL(1) << 23)
 #define SCTLR_E0E_BIT		(ULL(1) << 24)
 #define SCTLR_EE_BIT		(ULL(1) << 25)
 #define SCTLR_UCI_BIT		(ULL(1) << 26)
 #define SCTLR_EnDA_BIT		(ULL(1) << 27)
+#define SCTLR_nTLSMD_BIT	(ULL(1) << 28)
+#define SCTLR_LSMAOE_BIT	(ULL(1) << 29)
 #define SCTLR_EnIB_BIT		(ULL(1) << 30)
 #define SCTLR_EnIA_BIT		(ULL(1) << 31)
 #define SCTLR_BT0_BIT		(ULL(1) << 35)
 #define SCTLR_BT1_BIT		(ULL(1) << 36)
 #define SCTLR_BT_BIT		(ULL(1) << 36)
+#define SCTLR_ITFSB_BIT		(ULL(1) << 37)
+#define SCTLR_TCF0_SHIFT	U(38)
+#define SCTLR_TCF0_MASK		ULL(3)
+
+/* Tag Check Faults in EL0 have no effect on the PE */
+#define	SCTLR_TCF0_NO_EFFECT	U(0)
+/* Tag Check Faults in EL0 cause a synchronous exception */
+#define	SCTLR_TCF0_SYNC		U(1)
+/* Tag Check Faults in EL0 are asynchronously accumulated */
+#define	SCTLR_TCF0_ASYNC	U(2)
+/*
+ * Tag Check Faults in EL0 cause a synchronous exception on reads,
+ * and are asynchronously accumulated on writes
+ */
+#define	SCTLR_TCF0_SYNCR_ASYNCW	U(3)
+
+#define SCTLR_TCF_SHIFT		U(40)
+#define SCTLR_TCF_MASK		ULL(3)
+
+/* Tag Check Faults in EL1 have no effect on the PE */
+#define	SCTLR_TCF_NO_EFFECT	U(0)
+/* Tag Check Faults in EL1 cause a synchronous exception */
+#define	SCTLR_TCF_SYNC		U(1)
+/* Tag Check Faults in EL1 are asynchronously accumulated */
+#define	SCTLR_TCF_ASYNC		U(2)
+/*
+ * Tag Check Faults in EL1 cause a synchronous exception on reads,
+ * and are asynchronously accumulated on writes
+ */
+#define	SCTLR_TCF_SYNCR_ASYNCW	U(3)
+
+#define SCTLR_ATA0_BIT		(ULL(1) << 42)
+#define SCTLR_ATA_BIT		(ULL(1) << 43)
 #define SCTLR_DSSBS_BIT		(ULL(1) << 44)
+#define SCTLR_TWEDEn_BIT	(ULL(1) << 45)
+#define SCTLR_TWEDEL_SHIFT	U(46)
+#define SCTLR_TWEDEL_MASK	ULL(0xf)
+#define SCTLR_EnASR_BIT		(ULL(1) << 54)
+#define SCTLR_EnAS0_BIT		(ULL(1) << 55)
+#define SCTLR_EnALS_BIT		(ULL(1) << 56)
+#define SCTLR_EPAN_BIT		(ULL(1) << 57)
 #define SCTLR_RESET_VAL		SCTLR_EL3_RES1
 
-/* CPACR_El1 definitions */
+/* CPACR_EL1 definitions */
 #define CPACR_EL1_FPEN(x)	((x) << 20)
 #define CPACR_EL1_FP_TRAP_EL0	UL(0x1)
 #define CPACR_EL1_FP_TRAP_ALL	UL(0x2)
@@ -358,6 +426,7 @@
 #define SCR_RESET_VAL		SCR_RES1_BITS
 
 /* MDCR_EL3 definitions */
+#define MDCR_MTPME_BIT		(ULL(1) << 28)
 #define MDCR_SCCD_BIT		(ULL(1) << 23)
 #define MDCR_SPME_BIT		(ULL(1) << 17)
 #define MDCR_SDD_BIT		(ULL(1) << 16)
@@ -373,6 +442,7 @@
 #define MDCR_EL3_RESET_VAL	ULL(0x0)
 
 /* MDCR_EL2 definitions */
+#define MDCR_EL2_MTPME		(U(1) << 28)
 #define MDCR_EL2_HLP		(U(1) << 26)
 #define MDCR_EL2_HCCD		(U(1) << 23)
 #define MDCR_EL2_TTRF		(U(1) << 19)
diff --git a/include/arch/aarch64/el3_common_macros.S b/include/arch/aarch64/el3_common_macros.S
index 6f4143c..f759983 100644
--- a/include/arch/aarch64/el3_common_macros.S
+++ b/include/arch/aarch64/el3_common_macros.S
@@ -277,6 +277,10 @@
 		isb
 	.endif /* _init_sctlr */
 
+#if DISABLE_MTPMU
+		bl	mtpmu_disable
+#endif
+
 	.if \_warm_boot_mailbox
 		/* -------------------------------------------------------------
 		 * This code will be executed for both warm and cold resets.
diff --git a/include/drivers/allwinner/axp.h b/include/drivers/allwinner/axp.h
index 9c0035f..222820b 100644
--- a/include/drivers/allwinner/axp.h
+++ b/include/drivers/allwinner/axp.h
@@ -9,6 +9,10 @@
 
 #include <stdint.h>
 
+#define AXP20X_MODE_REG 0x3e
+#define AXP20X_MODE_I2C 0x00
+#define AXP20X_MODE_RSB 0x7c
+
 #define NA 0xff
 
 enum {
diff --git a/include/lib/cpus/aarch64/cortex_a76.h b/include/lib/cpus/aarch64/cortex_a76.h
index b522e8e..a61825f 100644
--- a/include/lib/cpus/aarch64/cortex_a76.h
+++ b/include/lib/cpus/aarch64/cortex_a76.h
@@ -20,7 +20,6 @@
 
 #define CORTEX_A76_CPUECTLR_EL1_WS_THR_L2	(ULL(3) << 24)
 #define CORTEX_A76_CPUECTLR_EL1_BIT_51		(ULL(1) << 51)
-#define CORTEX_A76_CPUECTLR_EL1_BIT_53		(ULL(1) << 53)
 
 /*******************************************************************************
  * CPU Auxiliary Control register specific definitions.
diff --git a/include/lib/cpus/aarch64/cortex_a77.h b/include/lib/cpus/aarch64/cortex_a77.h
index ed84c0f..0a42a5d 100644
--- a/include/lib/cpus/aarch64/cortex_a77.h
+++ b/include/lib/cpus/aarch64/cortex_a77.h
@@ -17,7 +17,6 @@
  ******************************************************************************/
 #define CORTEX_A77_CPUECTLR_EL1				S3_0_C15_C1_4
 #define CORTEX_A77_CPUECTLR_EL1_BIT_8			(ULL(1) << 8)
-#define CORTEX_A77_CPUECTLR_EL1_BIT_53			(ULL(1) << 53)
 
 /*******************************************************************************
  * CPU Power Control register specific definitions.
diff --git a/include/lib/cpus/aarch64/neoverse_n1.h b/include/lib/cpus/aarch64/neoverse_n1.h
index 9998b93..b50befa 100644
--- a/include/lib/cpus/aarch64/neoverse_n1.h
+++ b/include/lib/cpus/aarch64/neoverse_n1.h
@@ -64,12 +64,4 @@
 #define CPUPOR_EL3	S3_6_C15_C8_2
 #define CPUPMR_EL3	S3_6_C15_C8_3
 
-/******************************************************************************
- * CPU Configuration register definitions.
- *****************************************************************************/
-#define CPUCFR_EL1	S3_0_C15_C0_0
-
-/* SCU bit of CPU Configuration Register, EL1 */
-#define SCU_SHIFT	U(2)
-
 #endif /* NEOVERSE_N1_H */
diff --git a/include/lib/cpus/aarch64/neoverse_n2.h b/include/lib/cpus/aarch64/neoverse_n2.h
new file mode 100644
index 0000000..7cbd8c1
--- /dev/null
+++ b/include/lib/cpus/aarch64/neoverse_n2.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef NEOVERSE_N2_H
+#define NEOVERSE_N2_H
+
+/* Neoverse N2 ID register for revision r0p0 */
+#define NEOVERSE_N2_MIDR			U(0x410FD490)
+
+/*******************************************************************************
+ * CPU Power control register
+ ******************************************************************************/
+#define NEOVERSE_N2_CPUPWRCTLR_EL1		S3_0_C15_C2_7
+#define NEOVERSE_N2_CORE_PWRDN_EN_BIT		(ULL(1) << 0)
+
+/*******************************************************************************
+ * CPU Extended Control register specific definitions.
+ ******************************************************************************/
+#define NEOVERSE_N2_CPUECTLR_EL1		S3_0_C15_C1_4
+#define NEOVERSE_N2_CPUECTLR_EL1_EXTLLC_BIT	(ULL(1) << 0)
+
+/*******************************************************************************
+ * CPU Auxiliary Control register specific definitions.
+ ******************************************************************************/
+#define NEOVERSE_N2_CPUACTLR2_EL1		S3_0_C15_C1_1
+#define NEOVERSE_N2_CPUACTLR2_EL1_BIT_2		(ULL(1) << 2)
+
+#endif /* NEOVERSE_N2_H */
diff --git a/include/lib/cpus/aarch64/neoverse_n_common.h b/include/lib/cpus/aarch64/neoverse_n_common.h
new file mode 100644
index 0000000..7cb91cd
--- /dev/null
+++ b/include/lib/cpus/aarch64/neoverse_n_common.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef NEOVERSE_N_COMMON_H
+#define NEOVERSE_N_COMMON_H
+
+/******************************************************************************
+ * Neoverse Nx CPU Configuration register definitions
+ *****************************************************************************/
+#define CPUCFR_EL1		S3_0_C15_C0_0
+
+/* SCU bit of CPU Configuration Register, EL1 */
+#define SCU_SHIFT		U(2)
+
+#endif /* NEOVERSE_N_COMMON_H */
diff --git a/include/plat/arm/common/fconf_arm_sp_getter.h b/include/plat/arm/common/fconf_arm_sp_getter.h
index c6315be..aa628df 100644
--- a/include/plat/arm/common/fconf_arm_sp_getter.h
+++ b/include/plat/arm/common/fconf_arm_sp_getter.h
@@ -13,7 +13,7 @@
 /* arm_sp getter */
 #define arm__sp_getter(prop)	arm_sp.prop
 
-#define ARM_SP_MAX_SIZE		U(0x80000)
+#define ARM_SP_MAX_SIZE		U(0xb0000)
 #define ARM_SP_OWNER_NAME_LEN	U(8)
 
 struct arm_sp_t {
diff --git a/lib/cpus/aarch64/cortex_a76.S b/lib/cpus/aarch64/cortex_a76.S
index 98a1183..4f7f4bb 100644
--- a/lib/cpus/aarch64/cortex_a76.S
+++ b/lib/cpus/aarch64/cortex_a76.S
@@ -382,35 +382,6 @@
 endfunc check_errata_1791580
 
 	/* --------------------------------------------------
-	 * Errata Workaround for Cortex A76 Errata #1800710.
-	 * This applies to revision <= r4p0 of Cortex A76.
-	 * Inputs:
-	 * x0: variant[4:7] and revision[0:3] of current cpu.
-	 * Shall clobber: x0-x17
-	 * --------------------------------------------------
-	 */
-func errata_a76_1800710_wa
-	/* Compare x0 against revision <= r4p0 */
-	mov	x17, x30
-	bl	check_errata_1800710
-	cbz	x0, 1f
-
-	/* Disable allocation of splintered pages in the L2 TLB */
-	mrs	x1, CORTEX_A76_CPUECTLR_EL1
-	orr	x1, x1, CORTEX_A76_CPUECTLR_EL1_BIT_53
-	msr	CORTEX_A76_CPUECTLR_EL1, x1
-	isb
-1:
-	ret	x17
-endfunc errata_a76_1800710_wa
-
-func check_errata_1800710
-	/* Applies to everything <= r4p0 */
-	mov	x1, #0x40
-	b	cpu_rev_var_ls
-endfunc check_errata_1800710
-
-	/* --------------------------------------------------
 	 * Errata Workaround for Cortex A76 Errata #1262606,
 	 * #1275112, and #1868343.  #1262606 and #1275112
 	 * apply to revisions <= r3p0 and #1868343 applies to
@@ -459,6 +430,61 @@
 	b	cpu_rev_var_ls
 endfunc check_errata_1868343
 
+/* --------------------------------------------------
+ * Errata Workaround for A76 Erratum 1946160.
+ * This applies to revisions r3p0 - r4p1 of A76.
+ * It also exists in r0p0 - r2p0 but there is no fix
+ * in those revisions.
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x17
+ * --------------------------------------------------
+ */
+func errata_a76_1946160_wa
+	/* Compare x0 against revisions r3p0 - r4p1 */
+	mov	x17, x30
+	bl	check_errata_1946160
+	cbz	x0, 1f
+
+	mov	x0, #3
+	msr	S3_6_C15_C8_0, x0
+	ldr	x0, =0x10E3900002
+	msr	S3_6_C15_C8_2, x0
+	ldr	x0, =0x10FFF00083
+	msr	S3_6_C15_C8_3, x0
+	ldr	x0, =0x2001003FF
+	msr	S3_6_C15_C8_1, x0
+
+	mov	x0, #4
+	msr	S3_6_C15_C8_0, x0
+	ldr	x0, =0x10E3800082
+	msr	S3_6_C15_C8_2, x0
+	ldr	x0, =0x10FFF00083
+	msr	S3_6_C15_C8_3, x0
+	ldr	x0, =0x2001003FF
+	msr	S3_6_C15_C8_1, x0
+
+	mov	x0, #5
+	msr	S3_6_C15_C8_0, x0
+	ldr	x0, =0x10E3800200
+	msr	S3_6_C15_C8_2, x0
+	ldr	x0, =0x10FFF003E0
+	msr	S3_6_C15_C8_3, x0
+	ldr	x0, =0x2001003FF
+	msr	S3_6_C15_C8_1, x0
+
+	isb
+1:
+	ret	x17
+endfunc errata_a76_1946160_wa
+
+func check_errata_1946160
+	/* Applies to revisions r3p0 - r4p1. */
+	mov	x1, #0x30
+	mov	x2, #0x41
+	b	cpu_rev_var_range
+endfunc check_errata_1946160
+
 func check_errata_cve_2018_3639
 #if WORKAROUND_CVE_2018_3639
 	mov	x0, #ERRATA_APPLIES
@@ -538,9 +564,9 @@
 	bl	errata_a76_1791580_wa
 #endif
 
-#if ERRATA_A76_1800710
+#if ERRATA_A76_1946160
 	mov	x0, x18
-	bl	errata_a76_1800710_wa
+	bl	errata_a76_1946160_wa
 #endif
 
 #if WORKAROUND_CVE_2018_3639
@@ -624,9 +650,9 @@
 	report_errata ERRATA_A76_1275112, cortex_a76, 1275112
 	report_errata ERRATA_A76_1286807, cortex_a76, 1286807
 	report_errata ERRATA_A76_1791580, cortex_a76, 1791580
-	report_errata ERRATA_A76_1800710, cortex_a76, 1800710
 	report_errata ERRATA_A76_1165522, cortex_a76, 1165522
 	report_errata ERRATA_A76_1868343, cortex_a76, 1868343
+	report_errata ERRATA_A76_1946160, cortex_a76, 1946160
 	report_errata WORKAROUND_CVE_2018_3639, cortex_a76, cve_2018_3639
 	report_errata ERRATA_DSU_798953, cortex_a76, dsu_798953
 	report_errata ERRATA_DSU_936184, cortex_a76, dsu_936184
diff --git a/lib/cpus/aarch64/cortex_a77.S b/lib/cpus/aarch64/cortex_a77.S
index 04a610e..e3a6f5f 100644
--- a/lib/cpus/aarch64/cortex_a77.S
+++ b/lib/cpus/aarch64/cortex_a77.S
@@ -86,35 +86,6 @@
 endfunc check_errata_1508412_0
 
 	/* --------------------------------------------------
-	 * Errata Workaround for Cortex A77 Errata #1800714.
-	 * This applies to revision <= r1p1 of Cortex A77.
-	 * Inputs:
-	 * x0: variant[4:7] and revision[0:3] of current cpu.
-	 * Shall clobber: x0-x17
-	 * --------------------------------------------------
-	 */
-func errata_a77_1800714_wa
-	/* Compare x0 against revision <= r1p1 */
-	mov	x17, x30
-	bl	check_errata_1800714
-	cbz	x0, 1f
-
-	/* Disable allocation of splintered pages in the L2 TLB */
-	mrs	x1, CORTEX_A77_CPUECTLR_EL1
-	orr	x1, x1, CORTEX_A77_CPUECTLR_EL1_BIT_53
-	msr	CORTEX_A77_CPUECTLR_EL1, x1
-	isb
-1:
-	ret	x17
-endfunc errata_a77_1800714_wa
-
-func check_errata_1800714
-	/* Applies to everything <= r1p1 */
-	mov	x1, #0x11
-	b	cpu_rev_var_ls
-endfunc check_errata_1800714
-
-	/* --------------------------------------------------
 	 * Errata Workaround for Cortex A77 Errata #1925769.
 	 * This applies to revision <= r1p1 of Cortex A77.
 	 * Inputs:
@@ -158,11 +129,6 @@
 	bl	errata_a77_1508412_wa
 #endif
 
-#if ERRATA_A77_1800714
-	mov	x0, x18
-	bl	errata_a77_1800714_wa
-#endif
-
 #if ERRATA_A77_1925769
 	mov	x0, x18
 	bl	errata_a77_1925769_wa
@@ -202,7 +168,6 @@
 	 * checking functions of each errata.
 	 */
 	report_errata ERRATA_A77_1508412, cortex_a77, 1508412
-	report_errata ERRATA_A77_1800714, cortex_a77, 1800714
 	report_errata ERRATA_A77_1925769, cortex_a77, 1925769
 
 	ldp	x8, x30, [sp], #16
diff --git a/lib/cpus/aarch64/neoverse_n1.S b/lib/cpus/aarch64/neoverse_n1.S
index 03ee472..96891be 100644
--- a/lib/cpus/aarch64/neoverse_n1.S
+++ b/lib/cpus/aarch64/neoverse_n1.S
@@ -1,15 +1,15 @@
 /*
- * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2020, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include <arch.h>
 #include <asm_macros.S>
-#include <neoverse_n1.h>
 #include <cpuamu.h>
 #include <cpu_macros.S>
 #include <context.h>
+#include <neoverse_n1.h>
 
 /* Hardware handled coherency */
 #if HW_ASSISTED_COHERENCY == 0
@@ -22,19 +22,6 @@
 #endif
 
 	.global neoverse_n1_errata_ic_trap_handler
-	.global is_scu_present_in_dsu
-
-/*
- * Check DSU is configured with SCU and L3 unit
- * 1-> SCU present
- * 0-> SCU not present
- */
-func is_scu_present_in_dsu
-	mrs	x0, CPUCFR_EL1
-	ubfx	x0, x0, #SCU_SHIFT, #1
-	eor	x0, x0, #1
-	ret
-endfunc is_scu_present_in_dsu
 
 /* --------------------------------------------------
  * Errata Workaround for Neoverse N1 Erratum 1043202.
@@ -515,7 +502,7 @@
 	msr	CPUAMCNTENSET_EL0, x0
 #endif
 
-#if NEOVERSE_N1_EXTERNAL_LLC
+#if NEOVERSE_Nx_EXTERNAL_LLC
 	/* Some system may have External LLC, core needs to be made aware */
 	mrs     x0, NEOVERSE_N1_CPUECTLR_EL1
 	orr     x0, x0, NEOVERSE_N1_CPUECTLR_EL1_EXTLLC_BIT
diff --git a/lib/cpus/aarch64/neoverse_n2.S b/lib/cpus/aarch64/neoverse_n2.S
new file mode 100644
index 0000000..8d646cb
--- /dev/null
+++ b/lib/cpus/aarch64/neoverse_n2.S
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <cpu_macros.S>
+#include <neoverse_n2.h>
+
+/* Hardware handled coherency */
+#if HW_ASSISTED_COHERENCY == 0
+#error "Neoverse N2 must be compiled with HW_ASSISTED_COHERENCY enabled"
+#endif
+
+/* 64-bit only core */
+#if CTX_INCLUDE_AARCH32_REGS == 1
+#error "Neoverse-N2 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
+#endif
+
+	/* -------------------------------------------------
+	 * The CPU Ops reset function for Neoverse N2.
+	 * -------------------------------------------------
+	 */
+func neoverse_n2_reset_func
+	/* Check if the PE implements SSBS */
+	mrs	x0, id_aa64pfr1_el1
+	tst	x0, #(ID_AA64PFR1_EL1_SSBS_MASK << ID_AA64PFR1_EL1_SSBS_SHIFT)
+	b.eq	1f
+
+	/* Disable speculative loads */
+	msr	SSBS, xzr
+1:
+	/* Force all cacheable atomic instructions to be near */
+	mrs	x0, NEOVERSE_N2_CPUACTLR2_EL1
+	orr	x0, x0, #NEOVERSE_N2_CPUACTLR2_EL1_BIT_2
+	msr	NEOVERSE_N2_CPUACTLR2_EL1, x0
+
+#if ENABLE_AMU
+	/* Make sure accesses from EL0/EL1 and EL2 are not trapped to EL3 */
+	mrs	x0, cptr_el3
+	orr	x0, x0, #TAM_BIT
+	msr	cptr_el3, x0
+
+	/* Make sure accesses from EL0/EL1 are not trapped to EL2 */
+	mrs	x0, cptr_el2
+	orr	x0, x0, #TAM_BIT
+	msr	cptr_el2, x0
+
+	/* No need to enable the counters as this would be done at el3 exit */
+#endif
+
+#if NEOVERSE_Nx_EXTERNAL_LLC
+	/* Some systems may have External LLC, core needs to be made aware */
+	mrs     x0, NEOVERSE_N2_CPUECTLR_EL1
+	orr     x0, x0, NEOVERSE_N2_CPUECTLR_EL1_EXTLLC_BIT
+	msr     NEOVERSE_N2_CPUECTLR_EL1, x0
+#endif
+
+	isb
+	ret
+endfunc neoverse_n2_reset_func
+
+func neoverse_n2_core_pwr_dwn
+	/* ---------------------------------------------
+	 * Enable CPU power down bit in power control register
+	 * No need to do cache maintenance here.
+	 * ---------------------------------------------
+	 */
+	mrs	x0, NEOVERSE_N2_CPUPWRCTLR_EL1
+	orr	x0, x0, #NEOVERSE_N2_CORE_PWRDN_EN_BIT
+	msr	NEOVERSE_N2_CPUPWRCTLR_EL1, x0
+	isb
+	ret
+endfunc neoverse_n2_core_pwr_dwn
+
+#if REPORT_ERRATA
+/*
+ * Errata printing function for Neoverse N2 cores. Must follow AAPCS.
+ */
+func neoverse_n2_errata_report
+	/* No errata reported for Neoverse N2 cores */
+	ret
+endfunc neoverse_n2_errata_report
+#endif
+
+	/* ---------------------------------------------
+	 * This function provides Neoverse N2 specific
+	 * register information for crash reporting.
+	 * It needs to return with x6 pointing to
+	 * a list of register names in ASCII and
+	 * x8 - x15 having values of registers to be
+	 * reported.
+	 * ---------------------------------------------
+	 */
+.section .rodata.neoverse_n2_regs, "aS"
+neoverse_n2_regs:  /* The ASCII list of register names to be reported */
+	.asciz	"cpupwrctlr_el1", ""
+
+func neoverse_n2_cpu_reg_dump
+	adr	x6, neoverse_n2_regs
+	mrs	x8, NEOVERSE_N2_CPUPWRCTLR_EL1
+	ret
+endfunc neoverse_n2_cpu_reg_dump
+
+declare_cpu_ops neoverse_n2, NEOVERSE_N2_MIDR, \
+	neoverse_n2_reset_func, \
+	neoverse_n2_core_pwr_dwn
diff --git a/lib/cpus/aarch64/neoverse_n_common.S b/lib/cpus/aarch64/neoverse_n_common.S
new file mode 100644
index 0000000..b816342
--- /dev/null
+++ b/lib/cpus/aarch64/neoverse_n_common.S
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+#include <neoverse_n_common.h>
+
+	.global is_scu_present_in_dsu
+
+/*
+ * Check if the SCU L3 Unit is present on the DSU
+ * 1-> SCU present
+ * 0-> SCU not present
+ *
+ * This function is implemented as weak on dsu_helpers.S and must be
+ * overwritten for Neoverse Nx cores.
+ */
+
+func is_scu_present_in_dsu
+	mrs	x0, CPUCFR_EL1
+	ubfx	x0, x0, #SCU_SHIFT, #1
+	eor	x0, x0, #1
+	ret
+endfunc is_scu_present_in_dsu
diff --git a/lib/cpus/cpu-ops.mk b/lib/cpus/cpu-ops.mk
index 1210538..da0157f 100644
--- a/lib/cpus/cpu-ops.mk
+++ b/lib/cpus/cpu-ops.mk
@@ -25,9 +25,9 @@
 WORKAROUND_CVE_2018_3639	?=1
 DYNAMIC_WORKAROUND_CVE_2018_3639	?=0
 
-# Flag to indicate internal or external Last level cache
+# Flags to indicate internal or external Last level cache
 # By default internal
-NEOVERSE_N1_EXTERNAL_LLC	?=0
+NEOVERSE_Nx_EXTERNAL_LLC	?=0
 
 # Process A57_ENABLE_NONCACHEABLE_LOAD_FWD flag
 $(eval $(call assert_boolean,A57_ENABLE_NONCACHEABLE_LOAD_FWD))
@@ -56,8 +56,8 @@
 $(eval $(call assert_boolean,DYNAMIC_WORKAROUND_CVE_2018_3639))
 $(eval $(call add_define,DYNAMIC_WORKAROUND_CVE_2018_3639))
 
-$(eval $(call assert_boolean,NEOVERSE_N1_EXTERNAL_LLC))
-$(eval $(call add_define,NEOVERSE_N1_EXTERNAL_LLC))
+$(eval $(call assert_boolean,NEOVERSE_Nx_EXTERNAL_LLC))
+$(eval $(call add_define,NEOVERSE_Nx_EXTERNAL_LLC))
 
 ifneq (${DYNAMIC_WORKAROUND_CVE_2018_3639},0)
     ifeq (${WORKAROUND_CVE_2018_3639},0)
@@ -270,10 +270,6 @@
 # only to revision <= r4p0 of the Cortex A76 cpu.
 ERRATA_A76_1791580	?=0
 
-# Flag to apply erratum 1800710 workaround during reset. This erratum applies
-# only to revision <= r4p0 of the Cortex A76 cpu.
-ERRATA_A76_1800710	?=0
-
 # Flag to apply erratum 1165522 workaround during reset. This erratum applies
 # to all revisions of Cortex A76 cpu.
 ERRATA_A76_1165522	?=0
@@ -282,14 +278,14 @@
 # only to revision <= r4p0 of the Cortex A76 cpu.
 ERRATA_A76_1868343	?=0
 
+# Flag to apply erratum 1946160 workaround during reset. This erratum applies
+# only to revisions r3p0 - r4p1 of the Cortex A76 cpu.
+ERRATA_A76_1946160	?=0
+
 # Flag to apply erratum 1508412 workaround during reset. This erratum applies
 # only to revision <= r1p0 of the Cortex A77 cpu.
 ERRATA_A77_1508412	?=0
 
-# Flag to apply erratum 1800714 workaround during reset. This erratum applies
-# only to revision <= r1p1 of the Cortex A77 cpu.
-ERRATA_A77_1800714	?=0
-
 # Flag to apply erratum 1925769 workaround during reset. This erratum applies
 # only to revision <= r1p1 of the Cortex A77 cpu.
 ERRATA_A77_1925769	?=0
@@ -555,10 +551,6 @@
 $(eval $(call assert_boolean,ERRATA_A76_1791580))
 $(eval $(call add_define,ERRATA_A76_1791580))
 
-# Process ERRATA_A76_1800710 flag
-$(eval $(call assert_boolean,ERRATA_A76_1800710))
-$(eval $(call add_define,ERRATA_A76_1800710))
-
 # Process ERRATA_A76_1165522 flag
 $(eval $(call assert_boolean,ERRATA_A76_1165522))
 $(eval $(call add_define,ERRATA_A76_1165522))
@@ -567,14 +559,14 @@
 $(eval $(call assert_boolean,ERRATA_A76_1868343))
 $(eval $(call add_define,ERRATA_A76_1868343))
 
+# Process ERRATA_A76_1946160 flag
+$(eval $(call assert_boolean,ERRATA_A76_1946160))
+$(eval $(call add_define,ERRATA_A76_1946160))
+
 # Process ERRATA_A77_1508412 flag
 $(eval $(call assert_boolean,ERRATA_A77_1508412))
 $(eval $(call add_define,ERRATA_A77_1508412))
 
-# Process ERRATA_A77_1800714 flag
-$(eval $(call assert_boolean,ERRATA_A77_1800714))
-$(eval $(call add_define,ERRATA_A77_1800714))
-
 # Process ERRATA_A77_1925769 flag
 $(eval $(call assert_boolean,ERRATA_A77_1925769))
 $(eval $(call add_define,ERRATA_A77_1925769))
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index b460731..72d463b 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -144,30 +144,33 @@
 		scr_el3 |= SCR_API_BIT | SCR_APK_BIT;
 #endif /* !CTX_INCLUDE_PAUTH_REGS */
 
+#if !CTX_INCLUDE_MTE_REGS || ENABLE_ASSERTIONS
+	/* Get Memory Tagging Extension support level */
+	unsigned int mte = get_armv8_5_mte_support();
+#endif
 	/*
 	 * Enable MTE support. Support is enabled unilaterally for the normal
 	 * world, and only for the secure world when CTX_INCLUDE_MTE_REGS is
 	 * set.
 	 */
 #if CTX_INCLUDE_MTE_REGS
-	assert(get_armv8_5_mte_support() == MTE_IMPLEMENTED_ELX);
+	assert((mte == MTE_IMPLEMENTED_ELX) || (mte == MTE_IMPLEMENTED_ASY));
 	scr_el3 |= SCR_ATA_BIT;
 #else
-	unsigned int mte = get_armv8_5_mte_support();
-	if (mte == MTE_IMPLEMENTED_EL0) {
-		/*
-		 * Can enable MTE across both worlds as no MTE registers are
-		 * used
-		 */
-		scr_el3 |= SCR_ATA_BIT;
-	} else if (mte == MTE_IMPLEMENTED_ELX && security_state == NON_SECURE) {
-		/*
-		 * Can only enable MTE in Non-Secure world without register
-		 * saving
-		 */
+	/*
+	 * When MTE is only implemented at EL0, it can be enabled
+	 * across both worlds as no MTE registers are used.
+	 */
+	if ((mte == MTE_IMPLEMENTED_EL0) ||
+	/*
+	 * When MTE is implemented at all ELs, it can be only enabled
+	 * in Non-Secure world without register saving.
+	 */
+	  (((mte == MTE_IMPLEMENTED_ELX) || (mte == MTE_IMPLEMENTED_ASY)) &&
+	    (security_state == NON_SECURE))) {
 		scr_el3 |= SCR_ATA_BIT;
 	}
-#endif
+#endif	/* CTX_INCLUDE_MTE_REGS */
 
 #ifdef IMAGE_BL31
 	/*
diff --git a/lib/extensions/mtpmu/aarch32/mtpmu.S b/lib/extensions/mtpmu/aarch32/mtpmu.S
new file mode 100644
index 0000000..834cee3
--- /dev/null
+++ b/lib/extensions/mtpmu/aarch32/mtpmu.S
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+
+	.global	mtpmu_disable
+
+/* -------------------------------------------------------------
+ * The functions in this file are called at entrypoint, before
+ * the CPU has decided whether this is a cold or a warm boot.
+ * Therefore there are no stack yet to rely on for a C function
+ * call.
+ * -------------------------------------------------------------
+ */
+
+/*
+ * bool mtpmu_supported(void)
+ *
+ * Return a boolean indicating whether FEAT_MTPMU is supported or not.
+ *
+ * Trash registers: r0.
+ */
+func mtpmu_supported
+	ldcopr	r0, ID_DFR1
+	and	r0, r0, #(ID_DFR1_MTPMU_MASK >> ID_DFR1_MTPMU_SHIFT)
+	cmp	r0, #ID_DFR1_MTPMU_SUPPORTED
+	mov	r0, #0
+	addeq	r0, r0, #1
+	bx	lr
+endfunc mtpmu_supported
+
+/*
+ * bool el_implemented(unsigned int el)
+ *
+ * Return a boolean indicating if the specified EL (2 or 3) is implemented.
+ *
+ * Trash registers: r0
+ */
+func el_implemented
+	cmp	r0, #3
+	ldcopr	r0, ID_PFR1
+	lsreq	r0, r0, #ID_PFR1_SEC_SHIFT
+	lsrne	r0, r0, #ID_PFR1_VIRTEXT_SHIFT
+	/*
+	 * ID_PFR1_VIRTEXT_MASK is the same as ID_PFR1_SEC_MASK
+	 * so use any one of them
+	 */
+	and	r0, r0, #ID_PFR1_VIRTEXT_MASK
+	cmp	r0, #ID_PFR1_ELx_ENABLED
+	mov	r0, #0
+	addeq	r0, r0, #1
+	bx	lr
+endfunc el_implemented
+
+/*
+ * void mtpmu_disable(void)
+ *
+ * Disable mtpmu feature if supported.
+ *
+ * Trash register: r0, r1, r2
+ */
+func mtpmu_disable
+	mov	r2, lr
+	bl	mtpmu_supported
+	cmp	r0, #0
+	bxeq	r2	/* FEAT_MTPMU not supported */
+
+	/* FEAT_MTMPU Supported */
+	mov	r0, #3
+	bl	el_implemented
+	cmp	r0, #0
+	beq	1f
+
+	/* EL3 implemented */
+	ldcopr	r0, SDCR
+	ldr	r1, =SDCR_MTPME_BIT
+	bic	r0, r0, r1
+	stcopr	r0, SDCR
+
+	/*
+	 * If EL3 is implemented, HDCR.MTPME is implemented as Res0 and
+	 * FEAT_MTPMU is controlled only from EL3, so no need to perform
+	 * any operations for EL2.
+	 */
+	isb
+	bx	r2
+1:
+	/* EL3 not implemented */
+	mov	r0, #2
+	bl	el_implemented
+	cmp	r0, #0
+	bxeq	r2	/* No EL2 or EL3 implemented */
+
+	/* EL2 implemented */
+	ldcopr	r0, HDCR
+	ldr	r1, =HDCR_MTPME_BIT
+	orr	r0, r0, r1
+	stcopr	r0, HDCR
+	isb
+	bx	r2
+endfunc mtpmu_disable
diff --git a/lib/extensions/mtpmu/aarch64/mtpmu.S b/lib/extensions/mtpmu/aarch64/mtpmu.S
new file mode 100644
index 0000000..0a1d57b
--- /dev/null
+++ b/lib/extensions/mtpmu/aarch64/mtpmu.S
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+
+	.global	mtpmu_disable
+
+/* -------------------------------------------------------------
+ * The functions in this file are called at entrypoint, before
+ * the CPU has decided whether this is a cold or a warm boot.
+ * Therefore there are no stack yet to rely on for a C function
+ * call.
+ * -------------------------------------------------------------
+ */
+
+/*
+ * bool mtpmu_supported(void)
+ *
+ * Return a boolean indicating whether FEAT_MTPMU is supported or not.
+ *
+ * Trash registers: x0, x1
+ */
+func mtpmu_supported
+	mrs	x0, id_aa64dfr0_el1
+	mov_imm	x1, ID_AA64DFR0_MTPMU_MASK
+	and	x0, x1, x0, LSR #ID_AA64DFR0_MTPMU_SHIFT
+	cmp	x0, ID_AA64DFR0_MTPMU_SUPPORTED
+	cset	x0, eq
+	ret
+endfunc mtpmu_supported
+
+/*
+ * bool el_implemented(unsigned int el_shift)
+ *
+ * Return a boolean indicating if the specified EL is implemented.
+ * The EL is represented as the bitmask shift on id_aa64pfr0_el1 register.
+ *
+ * Trash registers: x0, x1
+ */
+func el_implemented
+	mrs	x1, id_aa64pfr0_el1
+	lsr	x1, x1, x0
+	cmp	x1, #ID_AA64PFR0_ELX_MASK
+	cset	x0, eq
+	ret
+endfunc el_implemented
+
+/*
+ * void mtpmu_disable(void)
+ *
+ * Disable mtpmu feature if supported.
+ *
+ * Trash register: x0, x1, x30
+ */
+func mtpmu_disable
+	mov	x10, x30
+	bl	mtpmu_supported
+	cbz	x0, exit_disable
+
+	/* FEAT_MTMPU Supported */
+	mov_imm	x0, ID_AA64PFR0_EL3_SHIFT
+	bl	el_implemented
+	cbz	x0, 1f
+
+	/* EL3 implemented */
+	mrs	x0, mdcr_el3
+	mov_imm x1, MDCR_MTPME_BIT
+	bic	x0, x0, x1
+	msr	mdcr_el3, x0
+
+	/*
+	 * If EL3 is implemented, MDCR_EL2.MTPME is implemented as Res0 and
+	 * FEAT_MTPMU is controlled only from EL3, so no need to perform
+	 * any operations for EL2.
+	 */
+	isb
+exit_disable:
+	ret	x10
+1:
+	/* EL3 not implemented */
+	mov_imm	x0, ID_AA64PFR0_EL2_SHIFT
+	bl	el_implemented
+	cbz	x0, exit_disable
+
+	/* EL2 implemented */
+	mrs	x0, mdcr_el2
+	mov_imm x1, MDCR_EL2_MTPME
+	bic	x0, x0, x1
+	msr	mdcr_el2, x0
+	isb
+	ret	x10
+endfunc mtpmu_disable
diff --git a/lib/psci/psci_private.h b/lib/psci/psci_private.h
index e2dcfa8..72bd6bd 100644
--- a/lib/psci/psci_private.h
+++ b/lib/psci/psci_private.h
@@ -42,6 +42,11 @@
 			define_psci_cap(PSCI_SYSTEM_RESET2_AARCH64) |	\
 			define_psci_cap(PSCI_MEM_CHK_RANGE_AARCH64))
 
+/* Internally PSCI uses a uint16_t for various cpu indexes so
+ * define a limit to number of CPUs that can be initialised.
+ */
+#define PSCI_MAX_CPUS_INDEX	0xFFFFU
+
 /*
  * Helper functions to get/set the fields of PSCI per-cpu data.
  */
@@ -134,7 +139,7 @@
 	unsigned char level;
 
 	/* For indexing the psci_lock array*/
-	unsigned char lock_index;
+	uint16_t lock_index;
 } non_cpu_pd_node_t;
 
 typedef struct cpu_pwr_domain_node {
@@ -239,7 +244,7 @@
 #endif /* HW_ASSISTED_COHERENCY */
 
 static inline void psci_lock_init(non_cpu_pd_node_t *non_cpu_pd_node,
-				  unsigned char idx)
+				  uint16_t idx)
 {
 	non_cpu_pd_node[idx].lock_index = idx;
 }
diff --git a/lib/psci/psci_setup.c b/lib/psci/psci_setup.c
index d1ec998..9c37d63 100644
--- a/lib/psci/psci_setup.c
+++ b/lib/psci/psci_setup.c
@@ -17,6 +17,12 @@
 
 #include "psci_private.h"
 
+/*
+ * Check that PLATFORM_CORE_COUNT fits into the number of cores
+ * that can be represented by PSCI_MAX_CPUS_INDEX.
+ */
+CASSERT(PLATFORM_CORE_COUNT <= (PSCI_MAX_CPUS_INDEX + 1U), assert_psci_cores_overflow);
+
 /*******************************************************************************
  * Per cpu non-secure contexts used to program the architectural state prior
  * return to the normal world.
@@ -34,11 +40,13 @@
  * Function which initializes the 'psci_non_cpu_pd_nodes' or the
  * 'psci_cpu_pd_nodes' corresponding to the power level.
  ******************************************************************************/
-static void __init psci_init_pwr_domain_node(unsigned char node_idx,
+static void __init psci_init_pwr_domain_node(uint16_t node_idx,
 					unsigned int parent_idx,
 					unsigned char level)
 {
 	if (level > PSCI_CPU_PWR_LVL) {
+		assert(node_idx < PSCI_NUM_NON_CPU_PWR_DOMAINS);
+
 		psci_non_cpu_pd_nodes[node_idx].level = level;
 		psci_lock_init(psci_non_cpu_pd_nodes, node_idx);
 		psci_non_cpu_pd_nodes[node_idx].parent_node = parent_idx;
@@ -47,6 +55,8 @@
 	} else {
 		psci_cpu_data_t *svc_cpu_data;
 
+		assert(node_idx < PLATFORM_CORE_COUNT);
+
 		psci_cpu_pd_nodes[node_idx].parent_node = parent_idx;
 
 		/* Initialize with an invalid mpidr */
@@ -144,7 +154,7 @@
 
 			for (j = node_index;
 				j < (node_index + num_children); j++)
-				psci_init_pwr_domain_node((unsigned char)j,
+				psci_init_pwr_domain_node((uint16_t)j,
 						  parent_node_index - 1U,
 						  (unsigned char)level);
 
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index 578bd59..5217a85 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -19,6 +19,9 @@
 # The Target build architecture. Supported values are: aarch64, aarch32.
 ARCH				:= aarch64
 
+# ARM Architecture feature modifiers: none by default
+ARM_ARCH_FEATURE		:= none
+
 # ARM Architecture major and minor versions: 8.0 by default.
 ARM_ARCH_MAJOR			:= 8
 ARM_ARCH_MINOR			:= 0
@@ -79,6 +82,10 @@
 # Disable the generation of the binary image (ELF only).
 DISABLE_BIN_GENERATION		:= 0
 
+# Disable MTPMU if FEAT_MTPMU is supported. Default is 0 to keep backwards
+# compatibility.
+DISABLE_MTPMU			:= 0
+
 # Enable capability to disable authentication dynamically. Only meant for
 # development platforms.
 DYN_DISABLE_AUTH		:= 0
diff --git a/plat/allwinner/common/allwinner-common.mk b/plat/allwinner/common/allwinner-common.mk
index 997aaa6..901d888 100644
--- a/plat/allwinner/common/allwinner-common.mk
+++ b/plat/allwinner/common/allwinner-common.mk
@@ -48,6 +48,10 @@
 ERRATA_A53_835769		:=	1
 ERRATA_A53_843419		:=	1
 ERRATA_A53_855873		:=	1
+ERRATA_A53_1530924		:=	1
+
+# The traditional U-Boot load address is 160MB into DRAM.
+PRELOADED_BL33_BASE		?=	0x4a000000
 
 # The reset vector can be changed for each CPU.
 PROGRAMMABLE_RESET_ADDRESS	:=	1
diff --git a/plat/allwinner/common/include/platform_def.h b/plat/allwinner/common/include/platform_def.h
index 975cc48..93720ff 100644
--- a/plat/allwinner/common/include/platform_def.h
+++ b/plat/allwinner/common/include/platform_def.h
@@ -25,9 +25,6 @@
 #define BL31_NOBITS_BASE		(SUNXI_SRAM_A1_BASE + 0x1000)
 #define BL31_NOBITS_LIMIT		(SUNXI_SRAM_A1_BASE + SUNXI_SRAM_A1_SIZE)
 
-/* The traditional U-Boot load address is 160MB into DRAM, so at 0x4a000000 */
-#define PLAT_SUNXI_NS_IMAGE_OFFSET	(SUNXI_DRAM_BASE + (160U << 20))
-
 /* How much memory to reserve as secure for BL32, if configured */
 #define SUNXI_DRAM_SEC_SIZE		(32U << 20)
 
diff --git a/plat/allwinner/common/sunxi_bl31_setup.c b/plat/allwinner/common/sunxi_bl31_setup.c
index e836a34..9c8eaa4 100644
--- a/plat/allwinner/common/sunxi_bl31_setup.c
+++ b/plat/allwinner/common/sunxi_bl31_setup.c
@@ -57,7 +57,7 @@
 	for (i = 0; i < 2048 / sizeof(uint64_t); i++) {
 		uint32_t *dtb_base;
 
-		if (u_boot_base[i] != PLAT_SUNXI_NS_IMAGE_OFFSET)
+		if (u_boot_base[i] != PRELOADED_BL33_BASE)
 			continue;
 
 		/* Does the suspected U-Boot size look anyhow reasonable? */
@@ -96,7 +96,7 @@
 	 * Tell BL31 where the non-trusted software image
 	 * is located and the entry state information
 	 */
-	bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
+	bl33_image_ep_info.pc = PRELOADED_BL33_BASE;
 	bl33_image_ep_info.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX,
 					  DISABLE_ALL_EXCEPTIONS);
 	SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
diff --git a/plat/allwinner/common/sunxi_common.c b/plat/allwinner/common/sunxi_common.c
index 0ca18ad..5b536a0 100644
--- a/plat/allwinner/common/sunxi_common.c
+++ b/plat/allwinner/common/sunxi_common.c
@@ -27,7 +27,7 @@
 			MT_DEVICE | MT_RW | MT_SECURE | MT_EXECUTE_NEVER),
 	MAP_REGION(SUNXI_DRAM_BASE, SUNXI_DRAM_VIRT_BASE, SUNXI_DRAM_SEC_SIZE,
 		   MT_RW_DATA | MT_SECURE),
-	MAP_REGION(PLAT_SUNXI_NS_IMAGE_OFFSET,
+	MAP_REGION(PRELOADED_BL33_BASE,
 		   SUNXI_DRAM_VIRT_BASE + SUNXI_DRAM_SEC_SIZE,
 		   SUNXI_DRAM_MAP_SIZE,
 		   MT_RO_DATA | MT_NS),
@@ -39,15 +39,6 @@
 	return SUNXI_OSC24M_CLK_IN_HZ;
 }
 
-uintptr_t plat_get_ns_image_entrypoint(void)
-{
-#ifdef PRELOADED_BL33_BASE
-	return PRELOADED_BL33_BASE;
-#else
-	return PLAT_SUNXI_NS_IMAGE_OFFSET;
-#endif
-}
-
 void sunxi_configure_mmu_el3(int flags)
 {
 	mmap_add_region(BL_CODE_BASE, BL_CODE_BASE,
@@ -125,11 +116,9 @@
 		device_bit = BIT(6);
 		break;
 	case SUNXI_SOC_H6:
-		if (use_rsb)
-			return -ENODEV;
-		pin_func = 0x33;
+		pin_func = use_rsb ? 0x22 : 0x33;
 		device_bit = BIT(16);
-		reset_offset = 0x19c;
+		reset_offset = use_rsb ? 0x1bc : 0x19c;
 		break;
 	case SUNXI_SOC_A64:
 		pin_func = use_rsb ? 0x22 : 0x33;
@@ -157,7 +146,7 @@
 	if (socid != SUNXI_SOC_H6)
 		mmio_setbits_32(SUNXI_R_PRCM_BASE + 0x28, device_bit);
 	else
-		mmio_setbits_32(SUNXI_R_PRCM_BASE + 0x19c, device_bit | BIT(0));
+		mmio_setbits_32(SUNXI_R_PRCM_BASE + reset_offset, BIT(0));
 
 	/* assert, then de-assert reset of I2C/RSB controller */
 	mmio_clrbits_32(SUNXI_R_PRCM_BASE + reset_offset, device_bit);
diff --git a/plat/allwinner/common/sunxi_security.c b/plat/allwinner/common/sunxi_security.c
index 92c83b0..98b91c3 100644
--- a/plat/allwinner/common/sunxi_security.c
+++ b/plat/allwinner/common/sunxi_security.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -7,16 +7,11 @@
 #include <common/debug.h>
 #include <lib/mmio.h>
 
+#include <sunxi_ccu.h>
 #include <sunxi_mmap.h>
 #include <sunxi_private.h>
+#include <sunxi_spc.h>
 
-#ifdef SUNXI_SPC_BASE
-#define SPC_DECPORT_STA_REG(p)	(SUNXI_SPC_BASE + ((p) * 0x0c) + 0x4)
-#define SPC_DECPORT_SET_REG(p)	(SUNXI_SPC_BASE + ((p) * 0x0c) + 0x8)
-#define SPC_DECPORT_CLR_REG(p)	(SUNXI_SPC_BASE + ((p) * 0x0c) + 0xc)
-#endif
-
-#define R_PRCM_SEC_SWITCH_REG	0x1d0
 #define DMA_SEC_REG		0x20
 
 /*
@@ -27,20 +22,18 @@
  */
 void sunxi_security_setup(void)
 {
-#ifdef SUNXI_SPC_BASE
 	int i;
 
 	INFO("Configuring SPC Controller\n");
 	/* SPC setup: set all devices to non-secure */
-	for (i = 0; i < 6; i++)
-		mmio_write_32(SPC_DECPORT_SET_REG(i), 0xff);
-#endif
+	for (i = 0; i < SUNXI_SPC_NUM_PORTS; i++)
+		mmio_write_32(SUNXI_SPC_DECPORT_SET_REG(i), 0xffffffff);
 
 	/* set MBUS clocks, bus clocks (AXI/AHB/APB) and PLLs to non-secure */
 	mmio_write_32(SUNXI_CCU_SEC_SWITCH_REG, 0x7);
 
 	/* Set R_PRCM bus clocks to non-secure */
-	mmio_write_32(SUNXI_R_PRCM_BASE + R_PRCM_SEC_SWITCH_REG, 0x1);
+	mmio_write_32(SUNXI_R_PRCM_SEC_SWITCH_REG, 0x1);
 
 	/* Set all DMA channels (16 max.) to non-secure */
 	mmio_write_32(SUNXI_DMA_BASE + DMA_SEC_REG, 0xffff);
diff --git a/plat/allwinner/sun50i_a64/include/sunxi_ccu.h b/plat/allwinner/sun50i_a64/include/sunxi_ccu.h
new file mode 100644
index 0000000..2a24886
--- /dev/null
+++ b/plat/allwinner/sun50i_a64/include/sunxi_ccu.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUNXI_CCU_H
+#define SUNXI_CCU_H
+
+#define SUNXI_CCU_SEC_SWITCH_REG	(SUNXI_CCU_BASE + 0x02f0)
+
+#define SUNXI_R_PRCM_SEC_SWITCH_REG	(SUNXI_R_PRCM_BASE + 0x01d0)
+
+#endif /* SUNXI_CCU_H */
diff --git a/plat/allwinner/sun50i_a64/include/sunxi_mmap.h b/plat/allwinner/sun50i_a64/include/sunxi_mmap.h
index 9d2542f..6c847d3 100644
--- a/plat/allwinner/sun50i_a64/include/sunxi_mmap.h
+++ b/plat/allwinner/sun50i_a64/include/sunxi_mmap.h
@@ -36,7 +36,6 @@
 #define SUNXI_MSGBOX_BASE		0x01c17000
 #define SUNXI_SPINLOCK_BASE		0x01c18000
 #define SUNXI_CCU_BASE			0x01c20000
-#define SUNXI_CCU_SEC_SWITCH_REG	(SUNXI_CCU_BASE + 0x2f0)
 #define SUNXI_PIO_BASE			0x01c20800
 #define SUNXI_TIMER_BASE		0x01c20c00
 #define SUNXI_WDOG_BASE			0x01c20ca0
diff --git a/plat/allwinner/sun50i_a64/include/sunxi_spc.h b/plat/allwinner/sun50i_a64/include/sunxi_spc.h
new file mode 100644
index 0000000..5ba7e18
--- /dev/null
+++ b/plat/allwinner/sun50i_a64/include/sunxi_spc.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUNXI_SPC_H
+#define SUNXI_SPC_H
+
+#define SUNXI_SPC_NUM_PORTS		6
+
+#define SUNXI_SPC_DECPORT_STA_REG(p)	(SUNXI_SPC_BASE + 0x0004 + 0x0c * (p))
+#define SUNXI_SPC_DECPORT_SET_REG(p)	(SUNXI_SPC_BASE + 0x0008 + 0x0c * (p))
+#define SUNXI_SPC_DECPORT_CLR_REG(p)	(SUNXI_SPC_BASE + 0x000c + 0x0c * (p))
+
+#endif /* SUNXI_SPC_H */
diff --git a/plat/allwinner/sun50i_a64/sunxi_power.c b/plat/allwinner/sun50i_a64/sunxi_power.c
index 5b7d76a..80a69c3 100644
--- a/plat/allwinner/sun50i_a64/sunxi_power.c
+++ b/plat/allwinner/sun50i_a64/sunxi_power.c
@@ -92,21 +92,13 @@
 	if (ret)
 		return ret;
 
-	/* Start with 400 KHz to issue the I2C->RSB switch command. */
-	ret = rsb_set_bus_speed(SUNXI_OSC24M_CLK_IN_HZ, 400000);
-	if (ret)
-		return ret;
-
-	/*
-	 * Initiate an I2C transaction to write 0x7c into register 0x3e,
-	 * switching the PMIC to RSB mode.
-	 */
-	ret = rsb_set_device_mode(0x7c3e00);
+	/* Switch to the recommended 3 MHz bus clock. */
+	ret = rsb_set_bus_speed(SUNXI_OSC24M_CLK_IN_HZ, 3000000);
 	if (ret)
 		return ret;
 
-	/* Now in RSB mode, switch to the recommended 3 MHz. */
-	ret = rsb_set_bus_speed(SUNXI_OSC24M_CLK_IN_HZ, 3000000);
+	/* Initiate an I2C transaction to switch the PMIC to RSB mode. */
+	ret = rsb_set_device_mode(AXP20X_MODE_RSB << 16 | AXP20X_MODE_REG << 8);
 	if (ret)
 		return ret;
 
@@ -156,6 +148,11 @@
 		pmic = AXP803_RSB;
 		axp_setup_regulators(fdt);
 
+		/* Switch the PMIC back to I2C mode. */
+		ret = axp_write(AXP20X_MODE_REG, AXP20X_MODE_I2C);
+		if (ret)
+			return ret;
+
 		break;
 	default:
 		return -ENODEV;
diff --git a/plat/allwinner/sun50i_h6/include/sunxi_ccu.h b/plat/allwinner/sun50i_h6/include/sunxi_ccu.h
new file mode 100644
index 0000000..85fbb90
--- /dev/null
+++ b/plat/allwinner/sun50i_h6/include/sunxi_ccu.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUNXI_CCU_H
+#define SUNXI_CCU_H
+
+#define SUNXI_CCU_SEC_SWITCH_REG	(SUNXI_CCU_BASE + 0x0f00)
+
+#define SUNXI_R_PRCM_SEC_SWITCH_REG	(SUNXI_R_PRCM_BASE + 0x0290)
+
+#endif /* SUNXI_CCU_H */
diff --git a/plat/allwinner/sun50i_h6/include/sunxi_mmap.h b/plat/allwinner/sun50i_h6/include/sunxi_mmap.h
index 702db77..2d7b098 100644
--- a/plat/allwinner/sun50i_h6/include/sunxi_mmap.h
+++ b/plat/allwinner/sun50i_h6/include/sunxi_mmap.h
@@ -30,8 +30,8 @@
 #define SUNXI_DMA_BASE			0x03002000
 #define SUNXI_MSGBOX_BASE		0x03003000
 #define SUNXI_CCU_BASE			0x03001000
-#define SUNXI_CCU_SEC_SWITCH_REG	(SUNXI_CCU_BASE + 0xf00)
 #define SUNXI_PIO_BASE			0x0300b000
+#define SUNXI_SPC_BASE			0x03008000
 #define SUNXI_TIMER_BASE		0x03009000
 #define SUNXI_WDOG_BASE			0x030090a0
 #define SUNXI_THS_BASE			0x05070400
@@ -55,6 +55,7 @@
 #define SUNXI_R_TWD_BASE		0x07020800
 #define SUNXI_R_CPUCFG_BASE		0x07000400
 #define SUNXI_R_I2C_BASE		0x07081400
+#define SUNXI_R_RSB_BASE		0x07083000
 #define SUNXI_R_UART_BASE		0x07080000
 #define SUNXI_R_PIO_BASE		0x07022000
 
diff --git a/plat/allwinner/sun50i_h6/include/sunxi_spc.h b/plat/allwinner/sun50i_h6/include/sunxi_spc.h
new file mode 100644
index 0000000..0f5965b
--- /dev/null
+++ b/plat/allwinner/sun50i_h6/include/sunxi_spc.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUNXI_SPC_H
+#define SUNXI_SPC_H
+
+#define SUNXI_SPC_NUM_PORTS		14
+
+#define SUNXI_SPC_DECPORT_STA_REG(p)	(SUNXI_SPC_BASE + 0x0000 + 0x10 * (p))
+#define SUNXI_SPC_DECPORT_SET_REG(p)	(SUNXI_SPC_BASE + 0x0004 + 0x10 * (p))
+#define SUNXI_SPC_DECPORT_CLR_REG(p)	(SUNXI_SPC_BASE + 0x0008 + 0x10 * (p))
+
+#endif /* SUNXI_SPC_H */
diff --git a/plat/allwinner/sun50i_h6/platform.mk b/plat/allwinner/sun50i_h6/platform.mk
index 4ecc57c..1c98919 100644
--- a/plat/allwinner/sun50i_h6/platform.mk
+++ b/plat/allwinner/sun50i_h6/platform.mk
@@ -8,4 +8,4 @@
 include plat/allwinner/common/allwinner-common.mk
 
 BL31_SOURCES		+=	drivers/allwinner/axp/axp805.c		\
-				drivers/mentor/i2c/mi2cv.c
+				drivers/allwinner/sunxi_rsb.c
diff --git a/plat/allwinner/sun50i_h6/sunxi_power.c b/plat/allwinner/sun50i_h6/sunxi_power.c
index 443015b..a7865a5 100644
--- a/plat/allwinner/sun50i_h6/sunxi_power.c
+++ b/plat/allwinner/sun50i_h6/sunxi_power.c
@@ -6,20 +6,17 @@
  */
 
 #include <errno.h>
-#include <string.h>
 
-#include <arch_helpers.h>
 #include <common/debug.h>
 #include <drivers/allwinner/axp.h>
-#include <drivers/delay_timer.h>
-#include <drivers/mentor/mi2cv.h>
-#include <lib/mmio.h>
+#include <drivers/allwinner/sunxi_rsb.h>
 
 #include <sunxi_def.h>
 #include <sunxi_mmap.h>
 #include <sunxi_private.h>
 
-#define AXP805_ADDR	0x36
+#define AXP805_HW_ADDR	0x745
+#define AXP805_RT_ADDR	0x3a
 
 static enum pmic_type {
 	UNKNOWN,
@@ -28,67 +25,67 @@
 
 int axp_read(uint8_t reg)
 {
-	uint8_t val;
-	int ret;
-
-	ret = i2c_write(AXP805_ADDR, 0, 0, &reg, 1);
-	if (ret == 0)
-		ret = i2c_read(AXP805_ADDR, 0, 0, &val, 1);
-	if (ret) {
-		ERROR("PMIC: Cannot read AXP805 register %02x\n", reg);
-		return ret;
-	}
-
-	return val;
+	return rsb_read(AXP805_RT_ADDR, reg);
 }
 
 int axp_write(uint8_t reg, uint8_t val)
 {
-	int ret;
-
-	ret = i2c_write(AXP805_ADDR, reg, 1, &val, 1);
-	if (ret)
-		ERROR("PMIC: Cannot write AXP805 register %02x\n", reg);
-
-	return ret;
+	return rsb_write(AXP805_RT_ADDR, reg, val);
 }
 
-static int axp805_probe(void)
+static int rsb_init(void)
 {
 	int ret;
 
-	/* Switch the AXP805 to master/single-PMIC mode. */
-	ret = axp_write(0xff, 0x0);
+	ret = rsb_init_controller();
 	if (ret)
 		return ret;
 
-	ret = axp_check_id();
+	/* Switch to the recommended 3 MHz bus clock. */
+	ret = rsb_set_bus_speed(SUNXI_OSC24M_CLK_IN_HZ, 3000000);
 	if (ret)
 		return ret;
 
-	return 0;
+	/* Initiate an I2C transaction to switch the PMIC to RSB mode. */
+	ret = rsb_set_device_mode(AXP20X_MODE_RSB << 16 | AXP20X_MODE_REG << 8);
+	if (ret)
+		return ret;
+
+	/* Associate the 8-bit runtime address with the 12-bit bus address. */
+	ret = rsb_assign_runtime_address(AXP805_HW_ADDR, AXP805_RT_ADDR);
+	if (ret)
+		return ret;
+
+	return axp_check_id();
 }
 
 int sunxi_pmic_setup(uint16_t socid, const void *fdt)
 {
 	int ret;
 
-	INFO("PMIC: Probing AXP805 on I2C\n");
+	INFO("PMIC: Probing AXP805 on RSB\n");
 
-	ret = sunxi_init_platform_r_twi(SUNXI_SOC_H6, false);
+	ret = sunxi_init_platform_r_twi(socid, true);
 	if (ret)
 		return ret;
 
-	/* initialise mi2cv driver */
-	i2c_init((void *)SUNXI_R_I2C_BASE);
+	ret = rsb_init();
+	if (ret)
+		return ret;
 
-	ret = axp805_probe();
+	/* Switch the AXP805 to master/single-PMIC mode. */
+	ret = axp_write(0xff, 0x0);
 	if (ret)
 		return ret;
 
 	pmic = AXP805;
 	axp_setup_regulators(fdt);
 
+	/* Switch the PMIC back to I2C mode. */
+	ret = axp_write(AXP20X_MODE_REG, AXP20X_MODE_I2C);
+	if (ret)
+		return ret;
+
 	return 0;
 }
 
@@ -96,10 +93,9 @@
 {
 	switch (pmic) {
 	case AXP805:
-		/* Re-initialise after rich OS might have used it. */
-		sunxi_init_platform_r_twi(SUNXI_SOC_H6, false);
-		/* initialise mi2cv driver */
-		i2c_init((void *)SUNXI_R_I2C_BASE);
+		/* (Re-)init RSB in case the rich OS has disabled it. */
+		sunxi_init_platform_r_twi(SUNXI_SOC_H6, true);
+		rsb_init();
 		axp_power_off();
 		break;
 	default:
diff --git a/plat/amlogic/axg/include/platform_def.h b/plat/amlogic/axg/include/platform_def.h
index a47cf73..c97687e 100644
--- a/plat/amlogic/axg/include/platform_def.h
+++ b/plat/amlogic/axg/include/platform_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -24,7 +24,7 @@
 
 #define AML_PRIMARY_CPU			U(0)
 
-#define PLAT_MAX_PWR_LVL		MPIDR_AFFLVL1
+#define PLAT_MAX_PWR_LVL		MPIDR_AFFLVL2
 #define PLAT_NUM_PWR_DOMAINS		(PLATFORM_CLUSTER_COUNT + \
 					 PLATFORM_CORE_COUNT)
 
diff --git a/plat/arm/board/arm_fpga/platform.mk b/plat/arm/board/arm_fpga/platform.mk
index 4b751fb..3ac1c01 100644
--- a/plat/arm/board/arm_fpga/platform.mk
+++ b/plat/arm/board/arm_fpga/platform.mk
@@ -59,7 +59,9 @@
 				lib/cpus/aarch64/cortex_a76ae.S		\
 				lib/cpus/aarch64/cortex_a77.S		\
 				lib/cpus/aarch64/cortex_a78.S		\
+				lib/cpus/aarch64/neoverse_n_common.S	\
 				lib/cpus/aarch64/neoverse_n1.S		\
+				lib/cpus/aarch64/neoverse_n2.S		\
 				lib/cpus/aarch64/neoverse_e1.S		\
 				lib/cpus/aarch64/neoverse_v1.S		\
 				lib/cpus/aarch64/cortex_a78_ae.S	\
diff --git a/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts b/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
index 8b9c281..f4805db 100644
--- a/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
+++ b/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
@@ -27,17 +27,14 @@
 		binary_size = <0x80000>;
 	};
 
-	chosen {
-		linux,initrd-start = <0>;
-		linux,initrd-end = <0>;
-	};
-
 	hypervisor {
 		compatible = "hafnium,hafnium";
 		vm1 {
 			is_ffa_partition;
 			debug_name = "cactus-primary";
 			load_address = <0x7000000>;
+			vcpu_count = <8>;
+			mem_size = <1048576>;
 		};
 		vm2 {
 			is_ffa_partition;
@@ -74,11 +71,6 @@
 		CPU_1
 	};
 
-	device-memory@0 {
-		device_type = "device-memory";
-		reg = <0x0 0x0 0x6000000 0x0 0x8000000 0x78000000>;
-	};
-
 	memory@6000000 {
 		device_type = "memory";
 		reg = <0x0 0x6000000 0x2000000>; /* Trusted DRAM */
diff --git a/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts b/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts
index 266adfc..57d6792 100644
--- a/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts
+++ b/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts
@@ -27,11 +27,6 @@
 		binary_size = <0x80000>;
 	};
 
-	chosen {
-		linux,initrd-start = <0>;
-		linux,initrd-end = <0>;
-	};
-
 	hypervisor {
 		compatible = "hafnium,hafnium";
 		vm1 {
@@ -39,6 +34,8 @@
 			debug_name = "op-tee";
 			load_address = <0x6280000>;
 			smc_whitelist = <0xbe000000>;
+			vcpu_count = <8>;
+			mem_size = <1048576>;
 		};
 	};
 
@@ -61,11 +58,6 @@
 		CPU_1
 	};
 
-	device-memory@0 {
-		device_type = "device-memory";
-		reg = <0x0 0x0 0x6000000 0x0 0x8000000 0x78000000>;
-	};
-
 	memory@6000000 {
 		device_type = "memory";
 		reg = <0x0 0x6000000 0x2000000>; /* Trusted DRAM */
diff --git a/fdts/optee_sp_manifest.dts b/plat/arm/board/fvp/fdts/optee_sp_manifest.dts
similarity index 72%
rename from fdts/optee_sp_manifest.dts
rename to plat/arm/board/fvp/fdts/optee_sp_manifest.dts
index 02a5ef3..928d0d3 100644
--- a/fdts/optee_sp_manifest.dts
+++ b/plat/arm/board/fvp/fdts/optee_sp_manifest.dts
@@ -30,4 +30,20 @@
 
 	/* Boot protocol */
 	gp-register-num = <0x0>;
+
+	device-regions {
+		compatible = "arm,ffa-manifest-device-regions";
+
+		uart1 {
+			base-address = <0x00000000 0x1c0a0000>;
+			pages-count = <1>;
+			attributes = <0x3>; /* read-write */
+		};
+
+		gicd {
+			base-address = <0x00000000 0x2f000000>;
+			pages-count = <16>;
+			attributes = <0x3>; /* read-write */
+		};
+	};
 };
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 4da0d76..0a6fa56 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -118,7 +118,9 @@
 					lib/cpus/aarch64/cortex_a76ae.S		\
 					lib/cpus/aarch64/cortex_a77.S		\
 					lib/cpus/aarch64/cortex_a78.S		\
+					lib/cpus/aarch64/neoverse_n_common.S	\
 					lib/cpus/aarch64/neoverse_n1.S		\
+					lib/cpus/aarch64/neoverse_n2.S		\
 					lib/cpus/aarch64/neoverse_e1.S		\
 					lib/cpus/aarch64/neoverse_v1.S		\
 					lib/cpus/aarch64/cortex_a78_ae.S	\
diff --git a/plat/arm/board/n1sdp/platform.mk b/plat/arm/board/n1sdp/platform.mk
index 4b621e3..f20397a 100644
--- a/plat/arm/board/n1sdp/platform.mk
+++ b/plat/arm/board/n1sdp/platform.mk
@@ -69,7 +69,7 @@
 USE_COHERENT_MEM			:=	0
 
 # Enable the flag since N1SDP has a system level cache
-NEOVERSE_N1_EXTERNAL_LLC		:=	1
+NEOVERSE_Nx_EXTERNAL_LLC		:=	1
 include plat/arm/common/arm_common.mk
 include plat/arm/css/common/css_common.mk
 include plat/arm/board/common/board_common.mk
diff --git a/plat/arm/board/rddaniel/include/platform_def.h b/plat/arm/board/rddaniel/include/platform_def.h
index a118ca3..5b98b4e 100644
--- a/plat/arm/board/rddaniel/include/platform_def.h
+++ b/plat/arm/board/rddaniel/include/platform_def.h
@@ -9,7 +9,7 @@
 
 #include <lib/utils_def.h>
 
-#include <sgi_base_platform_def.h>
+#include <sgi_soc_platform_def.h>
 
 #define PLAT_ARM_CLUSTER_COUNT		U(16)
 #define CSS_SGI_MAX_CPUS_PER_CLUSTER	U(1)
diff --git a/plat/arm/board/rddaniel/platform.mk b/plat/arm/board/rddaniel/platform.mk
index 7422d63..6553ae2 100644
--- a/plat/arm/board/rddaniel/platform.mk
+++ b/plat/arm/board/rddaniel/platform.mk
@@ -14,6 +14,8 @@
 
 SGI_CPU_SOURCES		:=	lib/cpus/aarch64/neoverse_v1.S
 
+PLAT_BL_COMMON_SOURCES	+=	${CSS_ENT_BASE}/sgi_plat.c
+
 BL1_SOURCES		+=	${SGI_CPU_SOURCES}			\
 				${RDDANIEL_BASE}/rddaniel_err.c
 
diff --git a/plat/arm/board/rddanielxlr/include/platform_def.h b/plat/arm/board/rddanielxlr/include/platform_def.h
index b1376b8..112b210 100644
--- a/plat/arm/board/rddanielxlr/include/platform_def.h
+++ b/plat/arm/board/rddanielxlr/include/platform_def.h
@@ -8,7 +8,7 @@
 #define PLATFORM_DEF_H
 
 #include <lib/utils_def.h>
-#include <sgi_base_platform_def.h>
+#include <sgi_soc_platform_def.h>
 
 #define PLAT_ARM_CLUSTER_COUNT		U(4)
 #define CSS_SGI_MAX_CPUS_PER_CLUSTER	U(1)
diff --git a/plat/arm/board/rddanielxlr/platform.mk b/plat/arm/board/rddanielxlr/platform.mk
index 8cbad52..2f41e2e 100644
--- a/plat/arm/board/rddanielxlr/platform.mk
+++ b/plat/arm/board/rddanielxlr/platform.mk
@@ -15,6 +15,8 @@
 
 SGI_CPU_SOURCES		:=	lib/cpus/aarch64/neoverse_v1.S
 
+PLAT_BL_COMMON_SOURCES	+=	${CSS_ENT_BASE}/sgi_plat.c
+
 BL1_SOURCES		+=	${SGI_CPU_SOURCES}			\
 				${RDDANIELXLR_BASE}/rddanielxlr_err.c
 
diff --git a/plat/arm/board/rddanielxlr/rddanielxlr_plat.c b/plat/arm/board/rddanielxlr/rddanielxlr_plat.c
index 4b5f16a..a1a4876 100644
--- a/plat/arm/board/rddanielxlr/rddanielxlr_plat.c
+++ b/plat/arm/board/rddanielxlr/rddanielxlr_plat.c
@@ -8,7 +8,7 @@
 #include <drivers/arm/gic600_multichip.h>
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
-#include <sgi_base_platform_def.h>
+#include <sgi_soc_platform_def.h>
 #include <sgi_plat.h>
 
 #if defined(IMAGE_BL31)
diff --git a/plat/arm/board/rde1edge/include/platform_def.h b/plat/arm/board/rde1edge/include/platform_def.h
index 3fb6409..c39fe2b 100644
--- a/plat/arm/board/rde1edge/include/platform_def.h
+++ b/plat/arm/board/rde1edge/include/platform_def.h
@@ -9,7 +9,7 @@
 
 #include <lib/utils_def.h>
 
-#include <sgi_base_platform_def.h>
+#include <sgi_soc_platform_def.h>
 
 #define PLAT_ARM_CLUSTER_COUNT		U(2)
 #define CSS_SGI_MAX_CPUS_PER_CLUSTER	U(8)
diff --git a/plat/arm/board/rde1edge/platform.mk b/plat/arm/board/rde1edge/platform.mk
index a7c0434..53074f4 100644
--- a/plat/arm/board/rde1edge/platform.mk
+++ b/plat/arm/board/rde1edge/platform.mk
@@ -12,6 +12,8 @@
 
 SGI_CPU_SOURCES		:=	lib/cpus/aarch64/neoverse_e1.S
 
+PLAT_BL_COMMON_SOURCES	+=	${CSS_ENT_BASE}/sgi_plat.c
+
 BL1_SOURCES		+=	${SGI_CPU_SOURCES}			\
 				${RDE1EDGE_BASE}/rde1edge_err.c
 
diff --git a/plat/arm/board/rdn1edge/include/platform_def.h b/plat/arm/board/rdn1edge/include/platform_def.h
index ab63e23..b167c46 100644
--- a/plat/arm/board/rdn1edge/include/platform_def.h
+++ b/plat/arm/board/rdn1edge/include/platform_def.h
@@ -9,7 +9,7 @@
 
 #include <lib/utils_def.h>
 
-#include <sgi_base_platform_def.h>
+#include <sgi_soc_platform_def.h>
 
 #define PLAT_ARM_CLUSTER_COUNT		U(2)
 #define CSS_SGI_MAX_CPUS_PER_CLUSTER	U(4)
diff --git a/plat/arm/board/rdn1edge/platform.mk b/plat/arm/board/rdn1edge/platform.mk
index b313426..d65854f 100644
--- a/plat/arm/board/rdn1edge/platform.mk
+++ b/plat/arm/board/rdn1edge/platform.mk
@@ -15,6 +15,8 @@
 
 SGI_CPU_SOURCES		:=	lib/cpus/aarch64/neoverse_n1.S
 
+PLAT_BL_COMMON_SOURCES	+=	${CSS_ENT_BASE}/sgi_plat.c
+
 BL1_SOURCES		+=	${SGI_CPU_SOURCES}			\
 				${RDN1EDGE_BASE}/rdn1edge_err.c
 
diff --git a/plat/arm/board/rdn1edge/rdn1edge_plat.c b/plat/arm/board/rdn1edge/rdn1edge_plat.c
index f62c6f4..1dbbf26 100644
--- a/plat/arm/board/rdn1edge/rdn1edge_plat.c
+++ b/plat/arm/board/rdn1edge/rdn1edge_plat.c
@@ -8,7 +8,7 @@
 #include <drivers/arm/gic600_multichip.h>
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
-#include <sgi_base_platform_def.h>
+#include <sgi_soc_platform_def.h>
 #include <sgi_plat.h>
 
 #if defined(IMAGE_BL31)
diff --git a/plat/arm/board/rdn2/fdts/rdn2_fw_config.dts b/plat/arm/board/rdn2/fdts/rdn2_fw_config.dts
new file mode 100644
index 0000000..9c9cefe
--- /dev/null
+++ b/plat/arm/board/rdn2/fdts/rdn2_fw_config.dts
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/tbbr/tbbr_img_def.h>
+
+/dts-v1/;
+
+/ {
+	dtb-registry {
+		compatible = "fconf,dyn_cfg-dtb_registry";
+
+		tb_fw-config {
+			load-address = <0x0 0x4001300>;
+			max-size = <0x200>;
+			id = <TB_FW_CONFIG_ID>;
+		};
+
+		nt_fw-config {
+			load-address = <0x0 0xFEF00000>;
+			max-size = <0x0100000>;
+			id = <NT_FW_CONFIG_ID>;
+		};
+	};
+};
diff --git a/plat/arm/board/rdn2/fdts/rdn2_nt_fw_config.dts b/plat/arm/board/rdn2/fdts/rdn2_nt_fw_config.dts
new file mode 100644
index 0000000..bbc36fc
--- /dev/null
+++ b/plat/arm/board/rdn2/fdts/rdn2_nt_fw_config.dts
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+/ {
+	/* compatible string */
+	compatible = "arm,rd-n2";
+
+	/*
+	 * Place holder for system-id node with default values. The
+	 * value of platform-id and config-id will be set to the
+	 * correct values during the BL2 stage of boot.
+	 */
+	system-id {
+		platform-id = <0x0>;
+		config-id = <0x0>;
+		multi-chip-mode = <0x0>;
+	};
+};
diff --git a/plat/arm/board/rdn2/fdts/rdn2_tb_fw_config.dts b/plat/arm/board/rdn2/fdts/rdn2_tb_fw_config.dts
new file mode 100644
index 0000000..49eda27
--- /dev/null
+++ b/plat/arm/board/rdn2/fdts/rdn2_tb_fw_config.dts
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+	tb_fw-config {
+		compatible = "arm,tb_fw";
+
+		/* Disable authentication for development */
+		disable_auth = <0x0>;
+
+		/*
+		 * The following two entries are placeholders for Mbed TLS
+		 * heap information. The default values don't matter since
+		 * they will be overwritten by BL1.
+		 * In case of having shared Mbed TLS heap between BL1 and BL2,
+		 * BL1 will populate these two properties with the respective
+		 * info about the shared heap. This info will be available for
+		 * BL2 in order to locate and re-use the heap.
+		 */
+		mbedtls_heap_addr = <0x0 0x0>;
+		mbedtls_heap_size = <0x0>;
+	};
+};
diff --git a/plat/arm/board/rdn2/include/platform_def.h b/plat/arm/board/rdn2/include/platform_def.h
new file mode 100644
index 0000000..5561f8c
--- /dev/null
+++ b/plat/arm/board/rdn2/include/platform_def.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <lib/utils_def.h>
+
+#include <sgi_soc_platform_def_v2.h>
+
+#define PLAT_ARM_CLUSTER_COUNT		U(16)
+#define CSS_SGI_MAX_CPUS_PER_CLUSTER	U(1)
+#define CSS_SGI_MAX_PE_PER_CPU		U(1)
+
+#define PLAT_CSS_MHU_BASE		UL(0x2A920000)
+#define PLAT_MHUV2_BASE			PLAT_CSS_MHU_BASE
+
+#define CSS_SYSTEM_PWR_DMN_LVL		ARM_PWR_LVL2
+#define PLAT_MAX_PWR_LVL		ARM_PWR_LVL1
+
+/* TZC Related Constants */
+#define PLAT_ARM_TZC_BASE		UL(0x10820000)
+#define PLAT_ARM_TZC_FILTERS		TZC_400_REGION_ATTR_FILTER_BIT(0)
+
+#define TZC400_OFFSET			UL(0x1000000)
+#define TZC400_COUNT			U(8)
+
+#define TZC400_BASE(n)			(PLAT_ARM_TZC_BASE + \
+						(n * TZC400_OFFSET))
+
+#define TZC_NSAID_ALL_AP		U(0)
+#define TZC_NSAID_PCI			U(1)
+#define TZC_NSAID_HDLCD0		U(2)
+#define TZC_NSAID_CLCD			U(7)
+#define TZC_NSAID_AP			U(9)
+#define TZC_NSAID_VIRTIO		U(15)
+
+#define PLAT_ARM_TZC_NS_DEV_ACCESS	\
+		(TZC_REGION_ACCESS_RDWR(TZC_NSAID_ALL_AP)) | \
+		(TZC_REGION_ACCESS_RDWR(TZC_NSAID_HDLCD0)) | \
+		(TZC_REGION_ACCESS_RDWR(TZC_NSAID_PCI))    | \
+		(TZC_REGION_ACCESS_RDWR(TZC_NSAID_AP))     | \
+		(TZC_REGION_ACCESS_RDWR(TZC_NSAID_CLCD))   | \
+		(TZC_REGION_ACCESS_RDWR(TZC_NSAID_VIRTIO))
+
+/*
+ * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes
+ */
+#ifdef __aarch64__
+#define PLAT_PHY_ADDR_SPACE_SIZE	(1ULL << 42)
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 42)
+#else
+#define PLAT_PHY_ADDR_SPACE_SIZE	(1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 32)
+#endif
+
+/* GIC related constants */
+#define PLAT_ARM_GICD_BASE		UL(0x30000000)
+#define PLAT_ARM_GICC_BASE		UL(0x2C000000)
+#define PLAT_ARM_GICR_BASE		UL(0x301C0000)
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/rdn2/platform.mk b/plat/arm/board/rdn2/platform.mk
new file mode 100644
index 0000000..6be6113
--- /dev/null
+++ b/plat/arm/board/rdn2/platform.mk
@@ -0,0 +1,59 @@
+# Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# RD-N2 platform uses GIC-Clayton which is based on GICv4.1
+GIC_ENABLE_V4_EXTN	:=	1
+
+include plat/arm/css/sgi/sgi-common.mk
+
+RDN2_BASE		=	plat/arm/board/rdn2
+
+PLAT_INCLUDES		+=	-I${RDN2_BASE}/include/
+
+SGI_CPU_SOURCES		:=	lib/cpus/aarch64/neoverse_n2.S
+
+PLAT_BL_COMMON_SOURCES	+=	${CSS_ENT_BASE}/sgi_plat_v2.c
+
+BL1_SOURCES		+=	${SGI_CPU_SOURCES}			\
+				${RDN2_BASE}/rdn2_err.c
+
+BL2_SOURCES		+=	${RDN2_BASE}/rdn2_plat.c		\
+				${RDN2_BASE}/rdn2_security.c		\
+				${RDN2_BASE}/rdn2_err.c			\
+				lib/utils/mem_region.c			\
+				drivers/arm/tzc/tzc400.c		\
+				plat/arm/common/arm_tzc400.c		\
+				plat/arm/common/arm_nor_psci_mem_protect.c
+
+BL31_SOURCES		+=	${SGI_CPU_SOURCES}			\
+				${RDN2_BASE}/rdn2_plat.c		\
+				${RDN2_BASE}/rdn2_topology.c		\
+				drivers/cfi/v2m/v2m_flash.c		\
+				lib/utils/mem_region.c			\
+				plat/arm/common/arm_nor_psci_mem_protect.c
+
+ifeq (${TRUSTED_BOARD_BOOT}, 1)
+BL1_SOURCES		+=	${RDN2_BASE}/rdn2_trusted_boot.c
+BL2_SOURCES		+=	${RDN2_BASE}/rdn2_trusted_boot.c
+endif
+
+# Add the FDT_SOURCES and options for Dynamic Config
+FDT_SOURCES		+=	${RDN2_BASE}/fdts/${PLAT}_fw_config.dts	\
+				${RDN2_BASE}/fdts/${PLAT}_tb_fw_config.dts
+FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
+
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG}))
+# Add the TB_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG}))
+
+FDT_SOURCES		+=	${RDN2_BASE}/fdts/${PLAT}_nt_fw_config.dts
+NT_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_nt_fw_config.dtb
+
+# Add the NT_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config))
+
+override CTX_INCLUDE_AARCH32_REGS	:= 0
diff --git a/plat/arm/board/rdn2/rdn2_err.c b/plat/arm/board/rdn2/rdn2_err.c
new file mode 100644
index 0000000..802ac21
--- /dev/null
+++ b/plat/arm/board/rdn2/rdn2_err.c
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * rdn2 error handler
+ */
+void __dead2 plat_arm_error_handler(int err)
+{
+	while (1) {
+		wfi();
+	}
+}
diff --git a/plat/arm/board/rdn2/rdn2_plat.c b/plat/arm/board/rdn2/rdn2_plat.c
new file mode 100644
index 0000000..5bf14e3
--- /dev/null
+++ b/plat/arm/board/rdn2/rdn2_plat.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/common/platform.h>
+#include <sgi_plat.h>
+
+unsigned int plat_arm_sgi_get_platform_id(void)
+{
+	return mmio_read_32(SID_REG_BASE + SID_SYSTEM_ID_OFFSET)
+			    & SID_SYSTEM_ID_PART_NUM_MASK;
+}
+
+unsigned int plat_arm_sgi_get_config_id(void)
+{
+	return mmio_read_32(SID_REG_BASE + SID_SYSTEM_CFG_OFFSET);
+}
+
+unsigned int plat_arm_sgi_get_multi_chip_mode(void)
+{
+	return (mmio_read_32(SID_REG_BASE + SID_NODE_ID_OFFSET) &
+			     SID_MULTI_CHIP_MODE_MASK) >>
+			     SID_MULTI_CHIP_MODE_SHIFT;
+}
+
+void bl31_platform_setup(void)
+{
+	sgi_bl31_common_platform_setup();
+}
diff --git a/plat/arm/board/rdn2/rdn2_security.c b/plat/arm/board/rdn2/rdn2_security.c
new file mode 100644
index 0000000..9568b60
--- /dev/null
+++ b/plat/arm/board/rdn2/rdn2_security.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+#include <platform_def.h>
+
+
+static const arm_tzc_regions_info_t tzc_regions[] = {
+	ARM_TZC_REGIONS_DEF,
+	{}
+};
+
+/* Initialize the secure environment */
+void plat_arm_security_setup(void)
+{
+
+	int i;
+
+	for (i = 0; i < TZC400_COUNT; i++)
+		arm_tzc400_setup(TZC400_BASE(i), tzc_regions);
+
+}
diff --git a/plat/arm/board/rdn2/rdn2_topology.c b/plat/arm/board/rdn2/rdn2_topology.c
new file mode 100644
index 0000000..5c2e287
--- /dev/null
+++ b/plat/arm/board/rdn2/rdn2_topology.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+#include <plat/arm/css/common/css_pm.h>
+
+/******************************************************************************
+ * The power domain tree descriptor.
+ ******************************************************************************/
+const unsigned char rd_n2_pd_tree_desc[] = {
+	PLAT_ARM_CLUSTER_COUNT,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+};
+
+/*******************************************************************************
+ * This function returns the topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+	return rd_n2_pd_tree_desc;
+}
+
+/*******************************************************************************
+ * The array mapping platform core position (implemented by plat_my_core_pos())
+ * to the SCMI power domain ID implemented by SCP.
+ ******************************************************************************/
+const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[] = {
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x0)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x1)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x2)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x3)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x4)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x5)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x6)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x7)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x8)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x9)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xA)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xB)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xC)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xD)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xE)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xF)),
+};
diff --git a/plat/arm/board/rdn2/rdn2_trusted_boot.c b/plat/arm/board/rdn2/rdn2_trusted_boot.c
new file mode 100644
index 0000000..4592b8f
--- /dev/null
+++ b/plat/arm/board/rdn2/rdn2_trusted_boot.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * Return the ROTPK hash in the following ASN.1 structure in DER format:
+ *
+ * AlgorithmIdentifier  ::=  SEQUENCE  {
+ *     algorithm         OBJECT IDENTIFIER,
+ *     parameters        ANY DEFINED BY algorithm OPTIONAL
+ * }
+ *
+ * DigestInfo ::= SEQUENCE {
+ *     digestAlgorithm   AlgorithmIdentifier,
+ *     digest            OCTET STRING
+ * }
+ */
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+			unsigned int *flags)
+{
+	return arm_get_rotpk_info(cookie, key_ptr, key_len, flags);
+}
diff --git a/plat/arm/board/sgi575/include/platform_def.h b/plat/arm/board/sgi575/include/platform_def.h
index 95986cf..c929334 100644
--- a/plat/arm/board/sgi575/include/platform_def.h
+++ b/plat/arm/board/sgi575/include/platform_def.h
@@ -9,7 +9,7 @@
 
 #include <lib/utils_def.h>
 
-#include <sgi_base_platform_def.h>
+#include <sgi_soc_platform_def.h>
 
 #define PLAT_ARM_CLUSTER_COUNT		U(2)
 #define CSS_SGI_MAX_CPUS_PER_CLUSTER	U(4)
diff --git a/plat/arm/board/sgi575/platform.mk b/plat/arm/board/sgi575/platform.mk
index 56f5733..89abcfe 100644
--- a/plat/arm/board/sgi575/platform.mk
+++ b/plat/arm/board/sgi575/platform.mk
@@ -12,6 +12,8 @@
 
 SGI_CPU_SOURCES		:=	lib/cpus/aarch64/cortex_a75.S
 
+PLAT_BL_COMMON_SOURCES	+=	${CSS_ENT_BASE}/sgi_plat.c
+
 BL1_SOURCES		+=	${SGI_CPU_SOURCES}			\
 				${SGI575_BASE}/sgi575_err.c
 
diff --git a/plat/arm/board/tc0/fdts/tc0_spmc_optee_sp_manifest.dts b/plat/arm/board/tc0/fdts/tc0_spmc_optee_sp_manifest.dts
new file mode 100644
index 0000000..a58b911
--- /dev/null
+++ b/plat/arm/board/tc0/fdts/tc0_spmc_optee_sp_manifest.dts
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+/dts-v1/;
+
+#define	AFF	00
+
+#include "fvp-defs.dtsi"
+#undef POST
+#define	POST \
+	};
+
+/ {
+	compatible = "arm,ffa-core-manifest-1.0";
+	#address-cells = <2>;
+	#size-cells = <1>;
+
+	attribute {
+		spmc_id = <0x8000>;
+		maj_ver = <0x1>;
+		min_ver = <0x0>;
+		exec_state = <0x0>;
+		load_address = <0x0 0xfd000000>;
+		entrypoint = <0x0 0xfd000000>;
+		binary_size = <0x80000>;
+	};
+
+	/*
+	 * temporary: This entry is added based on v2.4 hafnium and will be
+	 * removed when rebased to upstream master.
+	 */
+	chosen {
+	       linux,initrd-start = <0>;
+	       linux,initrd-end = <0>;
+	};
+
+	hypervisor {
+		compatible = "hafnium,hafnium";
+		vm1 {
+			is_ffa_partition;
+			debug_name = "op-tee";
+			load_address = <0xfd280000>;
+		};
+	};
+
+	cpus {
+		#address-cells = <0x2>;
+		#size-cells = <0x0>;
+
+		CPU_0
+
+		/*
+		 * SPMC (Hafnium) requires secondary core nodes are declared
+		 * in descending order.
+		 */
+		CPU_3
+		CPU_2
+		CPU_1
+	};
+
+	/*
+	 * temporary: This device-memory region is added based on v2.4 hafnium
+	 * and will be removed when rebased to upstream master. As first
+	 * Secure Partition no longer maps device memory.
+	 */
+	device-memory@21000000 {
+		device_type = "device-memory";
+		reg = <0x0 0x21000000 0x5f000000>;
+	};
+
+	/* 32MB of TC0_TZC_DRAM1_BASE */
+	memory@fd000000 {
+		device_type = "memory";
+		reg = <0x0 0xfd000000 0x2000000>;
+	};
+};
diff --git a/plat/arm/board/tc0/fdts/tc0_tb_fw_config.dts b/plat/arm/board/tc0/fdts/tc0_tb_fw_config.dts
index 3df94bf..de5f95d 100644
--- a/plat/arm/board/tc0/fdts/tc0_tb_fw_config.dts
+++ b/plat/arm/board/tc0/fdts/tc0_tb_fw_config.dts
@@ -27,6 +27,12 @@
 
 	secure-partitions {
 		compatible = "arm,sp";
+#if OPTEE_SP_FW_CONFIG
+		op-tee {
+		       uuid = <0x486178e0 0xe7f811e3 0xbc5e0002 0xa5d5c51b>;
+		       load-address = <0xfd280000>;
+		};
+#else
 		cactus-primary {
 			uuid = <0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>;
 			load-address = <0xfe000000>;
@@ -43,5 +49,6 @@
 			uuid = <0x79b55c73 0x1d8c44b9 0x859361e1 0x770ad8d2>;
 			load-address = <0xfe200000>;
 		};
+#endif
 	};
 };
diff --git a/plat/arm/board/tc0/include/platform_def.h b/plat/arm/board/tc0/include/platform_def.h
index 72a035f..2ff2699 100644
--- a/plat/arm/board/tc0/include/platform_def.h
+++ b/plat/arm/board/tc0/include/platform_def.h
@@ -112,7 +112,7 @@
  * little space for growth.
  */
 #if TRUSTED_BOARD_BOOT
-# define PLAT_ARM_MAX_BL2_SIZE		0x1E000
+# define PLAT_ARM_MAX_BL2_SIZE		0x20000
 #else
 # define PLAT_ARM_MAX_BL2_SIZE		0x14000
 #endif
diff --git a/plat/arm/board/tc0/platform.mk b/plat/arm/board/tc0/platform.mk
index 5d2cc38..6cc5f46 100644
--- a/plat/arm/board/tc0/platform.mk
+++ b/plat/arm/board/tc0/platform.mk
@@ -86,8 +86,12 @@
 $(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG}))
 
 ifeq (${SPD},spmd)
-FDT_SOURCES		+=	${TC0_BASE}/fdts/${PLAT}_spmc_manifest.dts
-TC0_TOS_FW_CONFIG	:=	${BUILD_PLAT}/fdts/${PLAT}_spmc_manifest.dtb
+ifeq ($(ARM_SPMC_MANIFEST_DTS),)
+ARM_SPMC_MANIFEST_DTS	:=	${TC0_BASE}/fdts/${PLAT}_spmc_manifest.dts
+endif
+
+FDT_SOURCES		+=	${ARM_SPMC_MANIFEST_DTS}
+TC0_TOS_FW_CONFIG	:=	${BUILD_PLAT}/fdts/$(notdir $(basename ${ARM_SPMC_MANIFEST_DTS})).dtb
 
 # Add the TOS_FW_CONFIG to FIP and specify the same to certtool
 $(eval $(call TOOL_ADD_PAYLOAD,${TC0_TOS_FW_CONFIG},--tos-fw-config,${TC0_TOS_FW_CONFIG}))
diff --git a/plat/arm/board/tc0/tc0_plat.c b/plat/arm/board/tc0/tc0_plat.c
index e12ad56..b5698c0 100644
--- a/plat/arm/board/tc0/tc0_plat.c
+++ b/plat/arm/board/tc0/tc0_plat.c
@@ -51,6 +51,10 @@
 #if TRUSTED_BOARD_BOOT && !BL2_AT_EL3
 	ARM_MAP_BL1_RW,
 #endif
+#ifdef SPD_opteed
+	ARM_MAP_OPTEE_CORE_MEM,
+	ARM_OPTEE_PAGEABLE_LOAD_MEM,
+#endif
 	{0}
 };
 #endif
diff --git a/plat/arm/css/sgi/include/sgi_base_platform_def.h b/plat/arm/css/sgi/include/sgi_base_platform_def.h
index 159084f..b805746 100644
--- a/plat/arm/css/sgi/include/sgi_base_platform_def.h
+++ b/plat/arm/css/sgi/include/sgi_base_platform_def.h
@@ -9,12 +9,9 @@
 
 #include <lib/utils_def.h>
 #include <lib/xlat_tables/xlat_tables_defs.h>
-#include <plat/arm/board/common/board_css_def.h>
-#include <plat/arm/board/common/v2m_def.h>
 #include <plat/arm/common/arm_def.h>
 #include <plat/arm/common/arm_spm_def.h>
 #include <plat/arm/css/common/css_def.h>
-#include <plat/arm/soc/common/soc_css_def.h>
 #include <plat/common/common_def.h>
 
 #define PLATFORM_CORE_COUNT		(CSS_SGI_CHIP_COUNT *		\
diff --git a/plat/arm/css/sgi/include/sgi_soc_css_def_v2.h b/plat/arm/css/sgi/include/sgi_soc_css_def_v2.h
new file mode 100644
index 0000000..03f1073
--- /dev/null
+++ b/plat/arm/css/sgi/include/sgi_soc_css_def_v2.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SGI_SOC_CSS_DEF_V2_H
+#define SGI_SOC_CSS_DEF_V2_H
+
+#include <lib/utils_def.h>
+#include <plat/common/common_def.h>
+
+/*
+ * Definitions common to all ARM CSS SoCs
+ */
+
+/* Following covers ARM CSS SoC Peripherals */
+
+#define SOC_SYSTEM_PERIPH_BASE		UL(0x0C000000)
+#define SOC_SYSTEM_PERIPH_SIZE		UL(0x02000000)
+
+#define SOC_PLATFORM_PERIPH_BASE	UL(0x0E000000)
+#define SOC_PLATFORM_PERIPH_SIZE	UL(0x02000000)
+
+#define SOC_CSS_PCIE_CONTROL_BASE	UL(0x0ef20000)
+
+/* PL011 UART related constants */
+#define SOC_CSS_UART1_BASE		UL(0x0ef80000)
+#define SOC_CSS_UART0_BASE		UL(0x0ef70000)
+
+/* Memory controller */
+#define SOC_MEMCNTRL_BASE		UL(0x10000000)
+#define SOC_MEMCNTRL_SIZE		UL(0x10000000)
+
+#define SOC_CSS_UART0_CLK_IN_HZ		UL(7372800)
+#define SOC_CSS_UART1_CLK_IN_HZ		UL(7372800)
+
+/* SoC NIC-400 Global Programmers View (GPV) */
+#define SOC_CSS_NIC400_BASE		UL(0x0ED00000)
+
+#define SOC_CSS_NIC400_USB_EHCI		U(0)
+#define SOC_CSS_NIC400_TLX_MASTER	U(1)
+#define SOC_CSS_NIC400_USB_OHCI		U(2)
+#define SOC_CSS_NIC400_PL354_SMC	U(3)
+/*
+ * The apb4_bridge controls access to:
+ *   - the PCIe configuration registers
+ *   - the MMU units for USB, HDLCD and DMA
+ */
+#define SOC_CSS_NIC400_APB4_BRIDGE	U(4)
+
+/* Non-volatile counters */
+#define SOC_TRUSTED_NVCTR_BASE		UL(0x0EE70000)
+#define TFW_NVCTR_BASE			(SOC_TRUSTED_NVCTR_BASE + 0x0000)
+#define TFW_NVCTR_SIZE			U(4)
+#define NTFW_CTR_BASE			(SOC_TRUSTED_NVCTR_BASE + 0x0004)
+#define NTFW_CTR_SIZE			U(4)
+
+/* Keys */
+#define SOC_KEYS_BASE			UL(0x0EE80000)
+#define TZ_PUB_KEY_HASH_BASE		(SOC_KEYS_BASE + 0x0000)
+#define TZ_PUB_KEY_HASH_SIZE		U(32)
+#define HU_KEY_BASE			(SOC_KEYS_BASE + 0x0020)
+#define HU_KEY_SIZE			U(16)
+#define END_KEY_BASE			(SOC_KEYS_BASE + 0x0044)
+#define END_KEY_SIZE			U(32)
+
+#define SOC_PLATFORM_PERIPH_MAP_DEVICE	MAP_REGION_FLAT(			\
+						SOC_PLATFORM_PERIPH_BASE, 	\
+						SOC_PLATFORM_PERIPH_SIZE, 	\
+						MT_DEVICE | MT_RW | MT_SECURE)
+
+#define SOC_SYSTEM_PERIPH_MAP_DEVICE	MAP_REGION_FLAT(			\
+						SOC_SYSTEM_PERIPH_BASE,		\
+						SOC_SYSTEM_PERIPH_SIZE,		\
+						MT_DEVICE | MT_RW | MT_SECURE)
+
+#define SOC_MEMCNTRL_MAP_DEVICE		MAP_REGION_FLAT(			\
+						SOC_MEMCNTRL_BASE,		\
+						SOC_MEMCNTRL_SIZE,		\
+						MT_DEVICE | MT_RW | MT_SECURE)
+
+/*
+ * The bootsec_bridge controls access to a bunch of peripherals, e.g. the UARTs.
+ */
+#define SOC_CSS_NIC400_BOOTSEC_BRIDGE		U(5)
+#define SOC_CSS_NIC400_BOOTSEC_BRIDGE_UART1	UL(1 << 12)
+
+/*
+ * Required platform porting definitions common to all ARM CSS SoCs
+ */
+/* 2MB used for SCP DDR retraining */
+#define PLAT_ARM_SCP_TZC_DRAM1_SIZE	UL(0x00200000)
+
+/* V2M motherboard system registers & offsets */
+#define V2M_SYSREGS_BASE		UL(0x0C010000)
+#define V2M_SYS_LED			U(0x8)
+
+/*
+ * V2M sysled bit definitions. The values written to this
+ * register are defined in arch.h & runtime_svc.h. Only
+ * used by the primary cpu to diagnose any cold boot issues.
+ *
+ * SYS_LED[0]   - Security state (S=0/NS=1)
+ * SYS_LED[2:1] - Exception Level (EL3-EL0)
+ * SYS_LED[7:3] - Exception Class (Sync/Async & origin)
+ *
+ */
+#define V2M_SYS_LED_SS_SHIFT		U(0)
+#define V2M_SYS_LED_EL_SHIFT		U(1)
+#define V2M_SYS_LED_EC_SHIFT		U(3)
+
+#define V2M_SYS_LED_SS_MASK		U(0x01)
+#define V2M_SYS_LED_EL_MASK		U(0x03)
+#define V2M_SYS_LED_EC_MASK		U(0x1f)
+
+/* NOR Flash */
+#define V2M_FLASH0_BASE			UL(0x08000000)
+#define V2M_FLASH0_SIZE			UL(0x04000000)
+#define V2M_FLASH_BLOCK_SIZE		UL(0x00040000)	/* 256 KB */
+
+/*
+ * The flash can be mapped either as read-only or read-write.
+ *
+ * If it is read-write then it should also be mapped as device memory because
+ * NOR flash programming involves sending a fixed, ordered sequence of commands.
+ *
+ * If it is read-only then it should also be mapped as:
+ * - Normal memory, because reading from NOR flash is transparent, it is like
+ *   reading from RAM.
+ * - Non-executable by default. If some parts of the flash need to be executable
+ *   then platform code is responsible for re-mapping the appropriate portion
+ *   of it as executable.
+ */
+#define V2M_MAP_FLASH0_RW		MAP_REGION_FLAT(V2M_FLASH0_BASE,\
+						V2M_FLASH0_SIZE,	\
+						MT_DEVICE | MT_RW | MT_SECURE)
+
+#define V2M_MAP_FLASH0_RO		MAP_REGION_FLAT(V2M_FLASH0_BASE,\
+						V2M_FLASH0_SIZE,	\
+						MT_RO_DATA | MT_SECURE)
+
+#define SGI_MAP_FLASH0_RO		MAP_REGION_FLAT(V2M_FLASH0_BASE,\
+						V2M_FLASH0_SIZE,	\
+						MT_DEVICE | MT_RO | MT_SECURE)
+
+/* Platform ID address */
+#define BOARD_CSS_PLAT_ID_REG_ADDR		UL(0x0EFE00E0)
+
+/* Platform ID related accessors */
+#define BOARD_CSS_PLAT_ID_REG_ID_MASK		U(0x0F)
+#define BOARD_CSS_PLAT_ID_REG_ID_SHIFT		U(0x00)
+#define BOARD_CSS_PLAT_ID_REG_VERSION_MASK	U(0xF00)
+#define BOARD_CSS_PLAT_ID_REG_VERSION_SHIFT	U(0x08)
+#define BOARD_CSS_PLAT_TYPE_RTL			U(0x00)
+#define BOARD_CSS_PLAT_TYPE_FPGA		U(0x01)
+#define BOARD_CSS_PLAT_TYPE_EMULATOR		U(0x02)
+#define BOARD_CSS_PLAT_TYPE_FVP			U(0x03)
+
+#ifndef __ASSEMBLER__
+
+#include <lib/mmio.h>
+
+#define BOARD_CSS_GET_PLAT_TYPE(addr)					\
+	((mmio_read_32(addr) & BOARD_CSS_PLAT_ID_REG_ID_MASK)		\
+	>> BOARD_CSS_PLAT_ID_REG_ID_SHIFT)
+
+#endif /* __ASSEMBLER__ */
+
+
+#define MAX_IO_DEVICES			U(3)
+#define MAX_IO_HANDLES			U(4)
+
+/* Reserve the last block of flash for PSCI MEM PROTECT flag */
+#define PLAT_ARM_FIP_BASE		V2M_FLASH0_BASE
+#define PLAT_ARM_FIP_MAX_SIZE		(V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE)
+
+#define PLAT_ARM_NVM_BASE		V2M_FLASH0_BASE
+#define PLAT_ARM_NVM_SIZE		(V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE)
+
+/* UART related constants */
+#define PLAT_ARM_BOOT_UART_BASE			SOC_CSS_UART0_BASE
+#define PLAT_ARM_BOOT_UART_CLK_IN_HZ		SOC_CSS_UART0_CLK_IN_HZ
+
+#define PLAT_ARM_RUN_UART_BASE			SOC_CSS_UART1_BASE
+#define PLAT_ARM_RUN_UART_CLK_IN_HZ		SOC_CSS_UART1_CLK_IN_HZ
+
+#define PLAT_ARM_SP_MIN_RUN_UART_BASE		SOC_CSS_UART1_BASE
+#define PLAT_ARM_SP_MIN_RUN_UART_CLK_IN_HZ	SOC_CSS_UART1_CLK_IN_HZ
+
+#define PLAT_ARM_CRASH_UART_BASE		PLAT_ARM_RUN_UART_BASE
+#define PLAT_ARM_CRASH_UART_CLK_IN_HZ		PLAT_ARM_RUN_UART_CLK_IN_HZ
+
+#endif /* SGI_SOC_CSS_DEF_V2_H */
diff --git a/plat/arm/css/sgi/include/sgi_soc_platform_def.h b/plat/arm/css/sgi/include/sgi_soc_platform_def.h
new file mode 100644
index 0000000..d7a839a
--- /dev/null
+++ b/plat/arm/css/sgi/include/sgi_soc_platform_def.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SGI_SOC_PLATFORM_DEF_H
+#define SGI_SOC_PLATFORM_DEF_H
+
+#include <sgi_base_platform_def.h>
+#include <plat/arm/board/common/board_css_def.h>
+#include <plat/arm/board/common/v2m_def.h>
+#include <plat/arm/soc/common/soc_css_def.h>
+
+#endif /* SGI_SOC_PLATFORM_DEF_H */
diff --git a/plat/arm/css/sgi/include/sgi_soc_platform_def_v2.h b/plat/arm/css/sgi/include/sgi_soc_platform_def_v2.h
new file mode 100644
index 0000000..cb747c3
--- /dev/null
+++ b/plat/arm/css/sgi/include/sgi_soc_platform_def_v2.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SGI_SOC_PLATFORM_DEF_V2_H
+#define SGI_SOC_PLATFORM_DEF_V2_H
+
+#include <sgi_base_platform_def.h>
+#include <sgi_soc_css_def_v2.h>
+
+#endif /* SGI_SOC_PLATFORM_DEF_V2_H */
diff --git a/plat/arm/css/sgi/include/sgi_variant.h b/plat/arm/css/sgi/include/sgi_variant.h
index f4c5300..eb12f3f 100644
--- a/plat/arm/css/sgi/include/sgi_variant.h
+++ b/plat/arm/css/sgi/include/sgi_variant.h
@@ -17,6 +17,9 @@
 /* SID Version values for RD-Daniel */
 #define RD_DANIEL_SID_VER_PART_NUM		0x078a
 
+/* SID Version values for RD-N2 */
+#define RD_N2_SID_VER_PART_NUM			0x07B7
+
 /* Structure containing SGI platform variant information */
 typedef struct sgi_platform_info {
 	unsigned int platform_id;	/* Part Number of the platform */
diff --git a/plat/arm/css/sgi/sgi-common.mk b/plat/arm/css/sgi/sgi-common.mk
index 6b9e0cd..615f53d 100644
--- a/plat/arm/css/sgi/sgi-common.mk
+++ b/plat/arm/css/sgi/sgi-common.mk
@@ -32,8 +32,7 @@
 				plat/common/plat_gicv3.c	\
 				plat/arm/common/arm_gicv3.c
 
-PLAT_BL_COMMON_SOURCES	+=	${CSS_ENT_BASE}/sgi_plat.c	\
-				${CSS_ENT_BASE}/aarch64/sgi_helper.S
+PLAT_BL_COMMON_SOURCES	+=	${CSS_ENT_BASE}/aarch64/sgi_helper.S
 
 BL1_SOURCES		+=	${INTERCONNECT_SOURCES}			\
 				drivers/arm/sbsa/sbsa.c
diff --git a/plat/arm/css/sgi/sgi_bl31_setup.c b/plat/arm/css/sgi/sgi_bl31_setup.c
index a4aed00..d5c7593 100644
--- a/plat/arm/css/sgi/sgi_bl31_setup.c
+++ b/plat/arm/css/sgi/sgi_bl31_setup.c
@@ -74,7 +74,8 @@
 scmi_channel_plat_info_t *plat_css_get_scmi_info(int channel_id)
 {
 	if (sgi_plat_info.platform_id == RD_N1E1_EDGE_SID_VER_PART_NUM ||
-		sgi_plat_info.platform_id == RD_DANIEL_SID_VER_PART_NUM) {
+		sgi_plat_info.platform_id == RD_DANIEL_SID_VER_PART_NUM ||
+		sgi_plat_info.platform_id == RD_N2_SID_VER_PART_NUM) {
 		if (channel_id >= ARRAY_SIZE(rd_n1e1_edge_scmi_plat_info))
 			panic();
 		return &rd_n1e1_edge_scmi_plat_info[channel_id];
diff --git a/plat/arm/css/sgi/sgi_plat_v2.c b/plat/arm/css/sgi/sgi_plat_v2.c
new file mode 100644
index 0000000..a770255
--- /dev/null
+++ b/plat/arm/css/sgi/sgi_plat_v2.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+#include <drivers/arm/sbsa.h>
+
+/*
+ * Table of regions for different BL stages to map using the MMU.
+ */
+#if IMAGE_BL1
+const mmap_region_t plat_arm_mmap[] = {
+	ARM_MAP_SHARED_RAM,
+	SGI_MAP_FLASH0_RO,
+	CSS_SGI_MAP_DEVICE,
+	SOC_PLATFORM_PERIPH_MAP_DEVICE,
+	SOC_SYSTEM_PERIPH_MAP_DEVICE,
+	{0}
+};
+#endif
+
+#if IMAGE_BL2
+const mmap_region_t plat_arm_mmap[] = {
+	ARM_MAP_SHARED_RAM,
+	SGI_MAP_FLASH0_RO,
+#ifdef PLAT_ARM_MEM_PROT_ADDR
+	ARM_V2M_MAP_MEM_PROTECT,
+#endif
+	CSS_SGI_MAP_DEVICE,
+	SOC_MEMCNTRL_MAP_DEVICE,
+	SOC_PLATFORM_PERIPH_MAP_DEVICE,
+	SOC_SYSTEM_PERIPH_MAP_DEVICE,
+	ARM_MAP_NS_DRAM1,
+#if ARM_BL31_IN_DRAM
+	ARM_MAP_BL31_SEC_DRAM,
+#endif
+#if TRUSTED_BOARD_BOOT && !BL2_AT_EL3
+	ARM_MAP_BL1_RW,
+#endif
+	{0}
+};
+#endif
+
+#if IMAGE_BL31
+const mmap_region_t plat_arm_mmap[] = {
+	ARM_MAP_SHARED_RAM,
+#ifdef PLAT_ARM_MEM_PROT_ADDR
+	ARM_V2M_MAP_MEM_PROTECT,
+#endif
+	CSS_SGI_MAP_DEVICE,
+	SOC_PLATFORM_PERIPH_MAP_DEVICE,
+	SOC_SYSTEM_PERIPH_MAP_DEVICE,
+	{0}
+};
+
+#endif
+
+ARM_CASSERT_MMAP
+
+#if TRUSTED_BOARD_BOOT
+int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
+{
+	assert(heap_addr != NULL);
+	assert(heap_size != NULL);
+
+	return arm_get_mbedtls_heap(heap_addr, heap_size);
+}
+#endif
+
+void plat_arm_secure_wdt_start(void)
+{
+	sbsa_wdog_start(SBSA_SECURE_WDOG_BASE, SBSA_SECURE_WDOG_TIMEOUT);
+}
+
+void plat_arm_secure_wdt_stop(void)
+{
+	sbsa_wdog_stop(SBSA_SECURE_WDOG_BASE);
+}
diff --git a/plat/common/aarch64/platform_mp_stack.S b/plat/common/aarch64/platform_mp_stack.S
index c34a4cf..c0668ea 100644
--- a/plat/common/aarch64/platform_mp_stack.S
+++ b/plat/common/aarch64/platform_mp_stack.S
@@ -14,7 +14,7 @@
 	.weak	plat_set_my_stack
 
 	/* ---------------------------------------------------------------------
-	 * When the compatility layer is disabled, the platform APIs
+	 * When the compatibility layer is disabled, the platform APIs
 	 * plat_get_my_stack() and plat_set_my_stack() are supported by the
 	 * platform and the previous APIs platform_get_stack() and
 	 * platform_set_stack() are defined in terms of new APIs making use of
diff --git a/plat/marvell/armada/a3k/common/a3700_common.mk b/plat/marvell/armada/a3k/common/a3700_common.mk
index 2050d59..e2022fa 100644
--- a/plat/marvell/armada/a3k/common/a3700_common.mk
+++ b/plat/marvell/armada/a3k/common/a3700_common.mk
@@ -15,6 +15,8 @@
 MARVELL_COMMON_BASE		:= $(MARVELL_PLAT_BASE)/common
 HANDLE_EA_EL3_FIRST		:= 1
 
+include plat/marvell/marvell.mk
+
 #*********** A3700 *************
 
 # GICV3
@@ -62,12 +64,10 @@
 				$(PLAT_COMMON_BASE)/a3700_sip_svc.c	\
 				$(MARVELL_DRV)
 
-ifneq (${WTP},)
+ifdef WTP
 
 DOIMAGEPATH	:= $(WTP)
-DOIMAGETOOL	:= $(DOIMAGEPATH)/wtptp/linux/tbb_linux
-
-include plat/marvell/marvell.mk
+DOIMAGETOOL	:= $(DOIMAGEPATH)/wtptp/src/TBB_Linux/release/TBB_linux
 
 ifeq ($(MARVELL_SECURE_BOOT),1)
 DOIMAGE_CFG	:= $(DOIMAGEPATH)/atf-tim.txt
@@ -85,6 +85,9 @@
 
 TIMBUILD	:= $(DOIMAGEPATH)/script/buildtim.sh
 TIM2IMG		:= $(DOIMAGEPATH)/script/tim2img.pl
+TIMDDRTOOL	:= $(DOIMAGEPATH)/tim/ddr/ddr_tool
+
+$(TIMBUILD): $(TIMDDRTOOL)
 
 # WTMI_IMG is used to specify the customized RTOS image running over
 # Service CPU (CM3 processor). By the default, it points to a
@@ -101,7 +104,7 @@
 # and sys-init image (WTMI_SYSINIT_IMG).
 WTMI_MULTI_IMG		:= $(DOIMAGEPATH)/wtmi/build/wtmi.bin
 
-WTMI_ENC_IMG		:= $(DOIMAGEPATH)/wtmi/build/wtmi-enc.bin
+WTMI_ENC_IMG		:= $(BUILD_PLAT)/wtmi-enc.bin
 BUILD_UART		:= uart-images
 
 SRCPATH			:= $(dir $(BL33))
@@ -120,13 +123,20 @@
 				$(DDR_TOPOLOGY) 0 0 $(DOIMAGE_CFG) $(TIMNCFG) $(TIMNSIG) 0
 DOIMAGE_FLAGS		:= -r $(DOIMAGE_CFG) -v -D
 
+$(DOIMAGETOOL): FORCE
+	$(if $(value CRYPTOPP_PATH),,$(error "Platform '${PLAT}' for WTP image tool requires CRYPTOPP_PATH. Please set CRYPTOPP_PATH to point to the right directory"))
+	$(Q)$(MAKE) --no-print-directory -C $(CRYPTOPP_PATH) -f GNUmakefile
+	$(Q)$(MAKE) --no-print-directory -C $(DOIMAGEPATH)/wtptp/src/TBB_Linux -f TBB_linux.mak LIBDIR=$(CRYPTOPP_PATH)
+
+$(WTMI_MULTI_IMG): FORCE
+	$(Q)$(MAKE) --no-print-directory -C $(DOIMAGEPATH) WTMI_IMG=$(WTMI_IMG) WTMI
+
+$(TIMDDRTOOL): FORCE
+	$(if $(value MV_DDR_PATH),,$(error "Platform '${PLAT}' for ddr tool requires MV_DDR_PATH. Please set MV_DDR_PATH to point to the right directory"))
+	$(Q)$(MAKE) --no-print-directory -C $(DOIMAGEPATH) MV_DDR_PATH=$(MV_DDR_PATH) mv_ddr
+
-mrvl_flash: ${BUILD_PLAT}/${FIP_NAME} ${DOIMAGETOOL}
-	$(shell truncate -s %128K ${BUILD_PLAT}/bl1.bin)
-	$(shell cat ${BUILD_PLAT}/bl1.bin ${BUILD_PLAT}/${FIP_NAME} > ${BUILD_PLAT}/${BOOT_IMAGE})
-	$(shell truncate -s %4 ${BUILD_PLAT}/${BOOT_IMAGE})
-	$(if $(value MV_DDR_PATH),,$(error "Platform '${PLAT}' for target '$@' requires MV_DDR_PATH. Please set MV_DDR_PATH to point to the right directory"))
-	${Q}${MAKE} --no-print-directory -C ${DOIMAGEPATH} WTMI_IMG=$(WTMI_IMG) MV_DDR_PATH=$(MV_DDR_PATH)
-	$(shell truncate -s %4 $(WTMI_IMG))
+.PHONY: mrvl_flash
+mrvl_flash: ${BUILD_PLAT}/${BOOT_IMAGE} ${WTMI_MULTI_IMG} ${DOIMAGETOOL} ${TIMBUILD}
 	@echo
 	@echo "Building uart images"
 	$(TIMBUILD) $(TIMBLDUARTARGS)
@@ -155,8 +165,9 @@
 	@echo -e "\n\t=======================================================\n";
 	@echo -e "\t  Secure boot. Encrypting wtmi and boot-image \n";
 	@echo -e "\t=======================================================\n";
-	@truncate -s %16 $(WTMI_MULTI_IMG)
-	@openssl enc -aes-256-cbc -e -in $(WTMI_MULTI_IMG) \
+	@cp $(WTMI_MULTI_IMG) $(BUILD_PLAT)/wtmi-align.bin
+	@truncate -s %16 $(BUILD_PLAT)/wtmi-align.bin
+	@openssl enc -aes-256-cbc -e -in $(BUILD_PLAT)/wtmi-align.bin \
 	-out $(WTMI_ENC_IMG) \
 	-K `cat $(IMAGESPATH)/aes-256.txt` -nosalt \
 	-iv `cat $(IMAGESPATH)/iv.txt` -p
@@ -168,15 +179,34 @@
 endif
 	$(DOIMAGETOOL) $(DOIMAGE_FLAGS)
 	@if [ -e "$(TIMNCFG)" ]; then $(DOIMAGETOOL) -r $(TIMNCFG); fi
-	@if [ "$(MARVELL_SECURE_BOOT)" = "1" ]; then sed -i 's|$(WTMI_MULTI_IMG)|$(WTMI_ENC_IMG)|1;s|$(BOOT_IMAGE)|$(BOOT_ENC_IMAGE)|1;' $(TIMNCFG); fi
+ifeq ($(MARVELL_SECURE_BOOT),1)
+	@sed -i 's|$(WTMI_MULTI_IMG)|$(WTMI_ENC_IMG)|1;s|$(BOOT_IMAGE)|$(BOOT_ENC_IMAGE)|1;' $(TIMNCFG)
+endif
 	$(TIM2IMG) $(TIM2IMGARGS) -o $(BUILD_PLAT)/$(FLASH_IMAGE)
-	@mv -t $(BUILD_PLAT) $(TIM_IMAGE) $(DOIMAGE_CFG) $(TIMN_IMAGE) $(TIMNCFG) $(WTMI_IMG) $(WTMI_SYSINIT_IMG) $(WTMI_MULTI_IMG)
-	@if [ "$(MARVELL_SECURE_BOOT)" = "1" ]; then mv -t $(BUILD_PLAT) $(WTMI_ENC_IMG) OtpHash.txt; fi
+	@mv -t $(BUILD_PLAT) $(TIM_IMAGE) $(DOIMAGE_CFG) $(TIMN_IMAGE) $(TIMNCFG)
+	@cp -t $(BUILD_PLAT) $(WTMI_IMG) $(WTMI_SYSINIT_IMG) $(WTMI_MULTI_IMG)
+ifeq ($(MARVELL_SECURE_BOOT),1)
+	@mv -t $(BUILD_PLAT) OtpHash.txt
+endif
 	@find . -name "*.txt" | grep -E "CSK[[:alnum:]]_KeyHash.txt|Tim_msg.txt|TIMHash.txt" | xargs rm -f
 
-else # ${WTP}
+clean realclean distclean: mrvl_clean
 
+.PHONY: mrvl_clean
+mrvl_clean:
+	-$(Q)$(MAKE) --no-print-directory -C $(DOIMAGEPATH) MV_DDR_PATH=$(MV_DDR_PATH) clean
+	-$(Q)$(MAKE) --no-print-directory -C $(DOIMAGEPATH)/wtptp/src/TBB_Linux -f TBB_linux.mak LIBDIR=$(CRYPTOPP_PATH) clean
+ifdef CRYPTOPP_PATH
+	-$(Q)$(MAKE) --no-print-directory -C $(CRYPTOPP_PATH) -f GNUmakefile clean
+endif
+
+else # WTP
+
+.PHONY: mrvl_flash
 mrvl_flash:
 	$(error "Platform '${PLAT}' for target '$@' requires WTP. Please set WTP to point to the right directory")
 
-endif # ${WTP}
+endif # WTP
+
+.PHONY: FORCE
+FORCE:;
diff --git a/plat/marvell/armada/a8k/common/a8k_common.mk b/plat/marvell/armada/a8k/common/a8k_common.mk
index c827326..cf1516a 100644
--- a/plat/marvell/armada/a8k/common/a8k_common.mk
+++ b/plat/marvell/armada/a8k/common/a8k_common.mk
@@ -152,16 +152,20 @@
 include ${BLE_PATH}/ble.mk
 $(eval $(call MAKE_BL,e))
 
+clean realclean distclean: mrvl_clean
+
+.PHONY: mrvl_clean
 mrvl_clean:
 	@echo "  Doimage CLEAN"
 	${Q}${MAKE} PLAT=${PLAT} --no-print-directory -C ${DOIMAGEPATH} clean
 
-${DOIMAGETOOL}: mrvl_clean
+${DOIMAGETOOL}: FORCE
 	@$(DOIMAGE_LIBS_CHECK)
 	${Q}${MAKE} --no-print-directory -C ${DOIMAGEPATH}
 
-mrvl_flash: ${BUILD_PLAT}/${FIP_NAME} ${DOIMAGETOOL} ${BUILD_PLAT}/ble.bin
-	$(shell truncate -s %128K ${BUILD_PLAT}/bl1.bin)
-	$(shell cat ${BUILD_PLAT}/bl1.bin ${BUILD_PLAT}/${FIP_NAME} > ${BUILD_PLAT}/${BOOT_IMAGE})
+.PHONY: mrvl_flash
+mrvl_flash: ${BUILD_PLAT}/${BOOT_IMAGE} ${DOIMAGETOOL}
 	${DOIMAGETOOL} ${DOIMAGE_FLAGS} ${BUILD_PLAT}/${BOOT_IMAGE} ${BUILD_PLAT}/${FLASH_IMAGE}
 
+.PHONY: FORCE
+FORCE:;
diff --git a/plat/marvell/armada/common/marvell_common.mk b/plat/marvell/armada/common/marvell_common.mk
index af149fa..e5ee710 100644
--- a/plat/marvell/armada/common/marvell_common.mk
+++ b/plat/marvell/armada/common/marvell_common.mk
@@ -85,3 +85,14 @@
 ifeq (${MSS_SUPPORT}, 1)
 include $(MARVELL_PLAT_BASE)/common/mss/mss_common.mk
 endif
+
+$(BUILD_PLAT)/$(BOOT_IMAGE): $(BUILD_PLAT)/bl1.bin $(BUILD_PLAT)/$(FIP_NAME)
+	$(if $(shell find $(BUILD_PLAT)/bl1.bin -type f -size +128k),$(error "Image '$(BUILD_PLAT)/bl1.bin' is bigger than 128kB"))
+	@cp $(BUILD_PLAT)/bl1.bin $(BUILD_PLAT)/$(BOOT_IMAGE) || { rm -f $(BUILD_PLAT)/$(BOOT_IMAGE); false; }
+	@truncate -s %128K $(BUILD_PLAT)/$(BOOT_IMAGE) || { rm -f $(BUILD_PLAT)/$(BOOT_IMAGE); false; }
+	@cat $(BUILD_PLAT)/$(FIP_NAME) >> $(BUILD_PLAT)/$(BOOT_IMAGE) || { rm -f $(BUILD_PLAT)/$(BOOT_IMAGE); false; }
+	@truncate -s %4 $(BUILD_PLAT)/$(BOOT_IMAGE) || { rm -f $(BUILD_PLAT)/$(BOOT_IMAGE); false; }
+	@echo "Built $@ successfully"
+
+.PHONY: mrvl_bootimage
+mrvl_bootimage: $(BUILD_PLAT)/$(BOOT_IMAGE)
diff --git a/plat/marvell/version.mk b/plat/marvell/version.mk
index e072e12..bb22255 100644
--- a/plat/marvell/version.mk
+++ b/plat/marvell/version.mk
@@ -1 +1 @@
-SUBVERSION = devel-18.12.0
+SUBVERSION = devel-18.12.2
diff --git a/plat/mediatek/common/drivers/pmic_wrap/pmic_wrap_init_v2.c b/plat/mediatek/common/drivers/pmic_wrap/pmic_wrap_init_v2.c
new file mode 100644
index 0000000..fca6913
--- /dev/null
+++ b/plat/mediatek/common/drivers/pmic_wrap/pmic_wrap_init_v2.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2020, 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 (GET_WACS_FSM(reg_rdata) == SWINF_FSM_IDLE) {
+			break;
+		}
+		retry--;
+	};
+
+	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/mt8183/drivers/uart/uart.c b/plat/mediatek/common/drivers/uart/uart.c
similarity index 94%
rename from plat/mediatek/mt8183/drivers/uart/uart.c
rename to plat/mediatek/common/drivers/uart/uart.c
index 3c6a980..b940eb3 100644
--- a/plat/mediatek/mt8183/drivers/uart/uart.c
+++ b/plat/mediatek/common/drivers/uart/uart.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,7 +9,7 @@
 
 static struct mt_uart uart_save_addr[DRV_SUPPORT_UART_PORTS];
 
-static const unsigned int uart_base_addr[DRV_SUPPORT_UART_PORTS] = {
+static const uint32_t uart_base_addr[DRV_SUPPORT_UART_PORTS] = {
 	UART0_BASE,
 	UART1_BASE
 };
@@ -99,13 +99,14 @@
 
 void mt_console_uart_cg(int on)
 {
-	if (on)
+	if (on == 1) {
 		mmio_write_32(UART_CLOCK_GATE_CLR, UART0_CLOCK_GATE_BIT);
-	else
+	} else {
 		mmio_write_32(UART_CLOCK_GATE_SET, UART0_CLOCK_GATE_BIT);
+	}
 }
 
-int mt_console_uart_cg_status(void)
+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/mt8183/bl31_plat_setup.c b/plat/mediatek/mt8183/bl31_plat_setup.c
index e96b4ad..7dac8a4 100644
--- a/plat/mediatek/mt8183/bl31_plat_setup.c
+++ b/plat/mediatek/mt8183/bl31_plat_setup.c
@@ -16,6 +16,7 @@
 #include <drivers/generic_delay_timer.h>
 #include <mcucfg.h>
 #include <mt_gic_v3.h>
+#include <mt_timer.h>
 #include <lib/coreboot.h>
 #include <lib/mmio.h>
 #include <mtk_mcdi.h>
@@ -148,6 +149,8 @@
 	mt_gic_driver_init();
 	mt_gic_init();
 
+	mt_systimer_init();
+
 	/* Init mcsi SF */
 	plat_mtk_cci_init_sf();
 
diff --git a/plat/mediatek/mt8183/drivers/timer/mt_timer.c b/plat/mediatek/mt8183/drivers/timer/mt_timer.c
new file mode 100644
index 0000000..0da4815
--- /dev/null
+++ b/plat/mediatek/mt8183/drivers/timer/mt_timer.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <mcucfg.h>
+#include <mt_timer.h>
+#include <platform_def.h>
+
+static void enable_systimer_compensation(void)
+{
+	unsigned int reg;
+
+	reg = mmio_read_32(CNTCR_REG);
+	reg &= ~COMP_15_EN;
+	reg |= COMP_20_EN;
+	mmio_write_32(CNTCR_REG, reg);
+
+	NOTICE("[systimer] CNTCR_REG(0x%x)\n", mmio_read_32(CNTCR_REG));
+}
+
+void mt_systimer_init(void)
+{
+	/* systimer is default on, so we only enable systimer compensation */
+	enable_systimer_compensation();
+}
diff --git a/plat/mediatek/mt8183/drivers/timer/mt_timer.h b/plat/mediatek/mt8183/drivers/timer/mt_timer.h
new file mode 100644
index 0000000..0b8edc5
--- /dev/null
+++ b/plat/mediatek/mt8183/drivers/timer/mt_timer.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2020, 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 COMP_15_EN          (1 << 10)
+#define COMP_20_EN          (1 << 11)
+
+void mt_systimer_init(void);
+
+#endif /* MT_TIMER_H */
diff --git a/plat/mediatek/mt8183/drivers/uart/uart.h b/plat/mediatek/mt8183/drivers/uart/uart.h
index be04c35..062ce3a 100644
--- a/plat/mediatek/mt8183/drivers/uart/uart.h
+++ b/plat/mediatek/mt8183/drivers/uart/uart.h
@@ -95,6 +95,6 @@
 void mt_uart_save(void);
 void mt_uart_restore(void);
 void mt_console_uart_cg(int on);
-int mt_console_uart_cg_status(void);
+uint32_t mt_console_uart_cg_status(void);
 
 #endif /* __UART_H__ */
diff --git a/plat/mediatek/mt8183/platform.mk b/plat/mediatek/mt8183/platform.mk
index 3ccc928..07da1af 100644
--- a/plat/mediatek/mt8183/platform.mk
+++ b/plat/mediatek/mt8183/platform.mk
@@ -14,6 +14,7 @@
                  -I${MTK_PLAT_SOC}/drivers/mcdi/                  \
                  -I${MTK_PLAT_SOC}/drivers/spmc/                  \
                  -I${MTK_PLAT_SOC}/drivers/gpio/                  \
+                 -I${MTK_PLAT_SOC}/drivers/timer/                 \
                  -I${MTK_PLAT_SOC}/drivers/pmic/                  \
                  -I${MTK_PLAT_SOC}/drivers/spm/                   \
                  -I${MTK_PLAT_SOC}/drivers/sspm/                  \
@@ -44,6 +45,7 @@
                    ${MTK_PLAT}/common/mtk_plat_common.c                  \
                    ${MTK_PLAT}/common/drivers/pmic_wrap/pmic_wrap_init.c \
                    ${MTK_PLAT}/common/drivers/rtc/rtc_common.c           \
+                   ${MTK_PLAT}/common/drivers/uart/uart.c                \
                    ${MTK_PLAT}/common/params_setup.c                     \
                    ${MTK_PLAT_SOC}/aarch64/plat_helpers.S                \
                    ${MTK_PLAT_SOC}/aarch64/platform_common.c             \
@@ -57,7 +59,7 @@
                    ${MTK_PLAT_SOC}/drivers/spm/spm_pmic_wrap.c           \
                    ${MTK_PLAT_SOC}/drivers/spm/spm_suspend.c             \
                    ${MTK_PLAT_SOC}/drivers/gpio/mtgpio.c                 \
-                   ${MTK_PLAT_SOC}/drivers/uart/uart.c                   \
+                   ${MTK_PLAT_SOC}/drivers/timer/mt_timer.c              \
                    ${MTK_PLAT_SOC}/drivers/emi_mpu/emi_mpu.c             \
                    ${MTK_PLAT_SOC}/plat_pm.c                             \
                    ${MTK_PLAT_SOC}/plat_topology.c                       \
diff --git a/plat/mediatek/mt8192/bl31_plat_setup.c b/plat/mediatek/mt8192/bl31_plat_setup.c
index 9a01bef..9de4a2e 100644
--- a/plat/mediatek/mt8192/bl31_plat_setup.c
+++ b/plat/mediatek/mt8192/bl31_plat_setup.c
@@ -11,12 +11,16 @@
 #include <common/bl_common.h>
 #include <common/debug.h>
 #include <common/desc_image_load.h>
+#include <drivers/generic_delay_timer.h>
 #include <drivers/ti/uart/uart_16550.h>
 #include <lib/coreboot.h>
 
 /* Platform Includes */
+#include <emi_mpu/emi_mpu.h>
 #include <gpio/mtgpio.h>
 #include <mt_gic_v3.h>
+#include <mt_timer.h>
+#include <mtk_dcm.h>
 #include <plat_params.h>
 #include <plat_private.h>
 
@@ -81,10 +85,21 @@
  ******************************************************************************/
 void bl31_platform_setup(void)
 {
+	/* Set dcm on */
+	if (!dcm_set_default()) {
+		ERROR("Failed to set default dcm on!!\n");
+	}
+
+	/* MPU Init */
+	emi_mpu_init();
+
 	/* Initialize the GIC driver, CPU and distributor interfaces */
 	mt_gic_driver_init();
 	mt_gic_init();
+
 	plat_mt8192_gpio_init();
+	mt_systimer_init();
+	generic_delay_timer_init();
 }
 
 /*******************************************************************************
diff --git a/plat/mediatek/mt8192/drivers/dcm/mtk_dcm.c b/plat/mediatek/mt8192/drivers/dcm/mtk_dcm.c
new file mode 100644
index 0000000..dd8bf4e
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/dcm/mtk_dcm.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <mtk_dcm.h>
+#include <mtk_dcm_utils.h>
+
+static void dcm_armcore(bool mode)
+{
+	dcm_mp_cpusys_top_bus_pll_div_dcm(mode);
+	dcm_mp_cpusys_top_cpu_pll_div_0_dcm(mode);
+	dcm_mp_cpusys_top_cpu_pll_div_1_dcm(mode);
+}
+
+static void dcm_mcusys(bool on)
+{
+	dcm_mp_cpusys_top_adb_dcm(on);
+	dcm_mp_cpusys_top_apb_dcm(on);
+	dcm_mp_cpusys_top_cpubiu_dcm(on);
+	dcm_mp_cpusys_top_misc_dcm(on);
+	dcm_mp_cpusys_top_mp0_qdcm(on);
+	dcm_cpccfg_reg_emi_wfifo(on);
+	dcm_mp_cpusys_top_last_cor_idle_dcm(on);
+}
+
+static void dcm_stall(bool on)
+{
+	dcm_mp_cpusys_top_core_stall_dcm(on);
+	dcm_mp_cpusys_top_fcm_stall_dcm(on);
+}
+
+static bool check_dcm_state(void)
+{
+	bool ret = true;
+
+	ret &= dcm_mp_cpusys_top_bus_pll_div_dcm_is_on();
+	ret &= dcm_mp_cpusys_top_cpu_pll_div_0_dcm_is_on();
+	ret &= dcm_mp_cpusys_top_cpu_pll_div_1_dcm_is_on();
+
+	ret &= dcm_mp_cpusys_top_adb_dcm_is_on();
+	ret &= dcm_mp_cpusys_top_apb_dcm_is_on();
+	ret &= dcm_mp_cpusys_top_cpubiu_dcm_is_on();
+	ret &= dcm_mp_cpusys_top_misc_dcm_is_on();
+	ret &= dcm_mp_cpusys_top_mp0_qdcm_is_on();
+	ret &= dcm_cpccfg_reg_emi_wfifo_is_on();
+	ret &= dcm_mp_cpusys_top_last_cor_idle_dcm_is_on();
+
+	ret &= dcm_mp_cpusys_top_core_stall_dcm_is_on();
+	ret &= dcm_mp_cpusys_top_fcm_stall_dcm_is_on();
+
+	return ret;
+}
+
+bool dcm_set_default(void)
+{
+	dcm_armcore(true);
+	dcm_mcusys(true);
+	dcm_stall(true);
+
+	return check_dcm_state();
+}
diff --git a/plat/mediatek/mt8192/drivers/dcm/mtk_dcm.h b/plat/mediatek/mt8192/drivers/dcm/mtk_dcm.h
new file mode 100644
index 0000000..ee98d0e
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/dcm/mtk_dcm.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTK_DCM_H
+#define MTK_DCM_H
+
+#include <stdbool.h>
+
+bool dcm_set_default(void);
+
+#endif /* #ifndef MTK_DCM_H */
diff --git a/plat/mediatek/mt8192/drivers/dcm/mtk_dcm_utils.c b/plat/mediatek/mt8192/drivers/dcm/mtk_dcm_utils.c
new file mode 100644
index 0000000..15a700c
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/dcm/mtk_dcm_utils.c
@@ -0,0 +1,562 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+#include <mtk_dcm_utils.h>
+
+#define MP_CPUSYS_TOP_ADB_DCM_REG0_MASK (BIT(17))
+#define MP_CPUSYS_TOP_ADB_DCM_REG1_MASK (BIT(15) | \
+			BIT(16) | \
+			BIT(17) | \
+			BIT(18) | \
+			BIT(21))
+#define MP_CPUSYS_TOP_ADB_DCM_REG2_MASK (BIT(15) | \
+			BIT(16) | \
+			BIT(17) | \
+			BIT(18))
+#define MP_CPUSYS_TOP_ADB_DCM_REG0_ON (BIT(17))
+#define MP_CPUSYS_TOP_ADB_DCM_REG1_ON (BIT(15) | \
+			BIT(16) | \
+			BIT(17) | \
+			BIT(18) | \
+			BIT(21))
+#define MP_CPUSYS_TOP_ADB_DCM_REG2_ON (BIT(15) | \
+			BIT(16) | \
+			BIT(17) | \
+			BIT(18))
+#define MP_CPUSYS_TOP_ADB_DCM_REG0_OFF ((0x0 << 17))
+#define MP_CPUSYS_TOP_ADB_DCM_REG1_OFF ((0x0 << 15) | \
+			(0x0 << 16) | \
+			(0x0 << 17) | \
+			(0x0 << 18) | \
+			(0x0 << 21))
+#define MP_CPUSYS_TOP_ADB_DCM_REG2_OFF ((0x0 << 15) | \
+			(0x0 << 16) | \
+			(0x0 << 17) | \
+			(0x0 << 18))
+
+bool dcm_mp_cpusys_top_adb_dcm_is_on(void)
+{
+	bool ret = true;
+
+	ret &= ((mmio_read_32(MP_ADB_DCM_CFG0) &
+		MP_CPUSYS_TOP_ADB_DCM_REG0_MASK) ==
+		(unsigned int) MP_CPUSYS_TOP_ADB_DCM_REG0_ON);
+	ret &= ((mmio_read_32(MP_ADB_DCM_CFG4) &
+		MP_CPUSYS_TOP_ADB_DCM_REG1_MASK) ==
+		(unsigned int) MP_CPUSYS_TOP_ADB_DCM_REG1_ON);
+	ret &= ((mmio_read_32(MCUSYS_DCM_CFG0) &
+		MP_CPUSYS_TOP_ADB_DCM_REG2_MASK) ==
+		(unsigned int) MP_CPUSYS_TOP_ADB_DCM_REG2_ON);
+
+	return ret;
+}
+
+void dcm_mp_cpusys_top_adb_dcm(bool on)
+{
+	if (on) {
+		/* TINFO = "Turn ON DCM 'mp_cpusys_top_adb_dcm'" */
+		mmio_clrsetbits_32(MP_ADB_DCM_CFG0,
+			MP_CPUSYS_TOP_ADB_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_ADB_DCM_REG0_ON);
+		mmio_clrsetbits_32(MP_ADB_DCM_CFG4,
+			MP_CPUSYS_TOP_ADB_DCM_REG1_MASK,
+			MP_CPUSYS_TOP_ADB_DCM_REG1_ON);
+		mmio_clrsetbits_32(MCUSYS_DCM_CFG0,
+			MP_CPUSYS_TOP_ADB_DCM_REG2_MASK,
+			MP_CPUSYS_TOP_ADB_DCM_REG2_ON);
+	} else {
+		/* TINFO = "Turn OFF DCM 'mp_cpusys_top_adb_dcm'" */
+		mmio_clrsetbits_32(MP_ADB_DCM_CFG0,
+			MP_CPUSYS_TOP_ADB_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_ADB_DCM_REG0_OFF);
+		mmio_clrsetbits_32(MP_ADB_DCM_CFG4,
+			MP_CPUSYS_TOP_ADB_DCM_REG1_MASK,
+			MP_CPUSYS_TOP_ADB_DCM_REG1_OFF);
+		mmio_clrsetbits_32(MCUSYS_DCM_CFG0,
+			MP_CPUSYS_TOP_ADB_DCM_REG2_MASK,
+			MP_CPUSYS_TOP_ADB_DCM_REG2_OFF);
+	}
+}
+
+#define MP_CPUSYS_TOP_APB_DCM_REG0_MASK (BIT(5))
+#define MP_CPUSYS_TOP_APB_DCM_REG1_MASK (BIT(8))
+#define MP_CPUSYS_TOP_APB_DCM_REG2_MASK (BIT(16))
+#define MP_CPUSYS_TOP_APB_DCM_REG0_ON (BIT(5))
+#define MP_CPUSYS_TOP_APB_DCM_REG1_ON (BIT(8))
+#define MP_CPUSYS_TOP_APB_DCM_REG2_ON (BIT(16))
+#define MP_CPUSYS_TOP_APB_DCM_REG0_OFF ((0x0 << 5))
+#define MP_CPUSYS_TOP_APB_DCM_REG1_OFF ((0x0 << 8))
+#define MP_CPUSYS_TOP_APB_DCM_REG2_OFF ((0x0 << 16))
+
+bool dcm_mp_cpusys_top_apb_dcm_is_on(void)
+{
+	bool ret = true;
+
+	ret &= ((mmio_read_32(MP_MISC_DCM_CFG0) &
+		MP_CPUSYS_TOP_APB_DCM_REG0_MASK) ==
+		(unsigned int) MP_CPUSYS_TOP_APB_DCM_REG0_ON);
+	ret &= ((mmio_read_32(MCUSYS_DCM_CFG0) &
+		MP_CPUSYS_TOP_APB_DCM_REG1_MASK) ==
+		(unsigned int) MP_CPUSYS_TOP_APB_DCM_REG1_ON);
+	ret &= ((mmio_read_32(MP0_DCM_CFG0) &
+		MP_CPUSYS_TOP_APB_DCM_REG2_MASK) ==
+		(unsigned int) MP_CPUSYS_TOP_APB_DCM_REG2_ON);
+
+	return ret;
+}
+
+void dcm_mp_cpusys_top_apb_dcm(bool on)
+{
+	if (on) {
+		/* TINFO = "Turn ON DCM 'mp_cpusys_top_apb_dcm'" */
+		mmio_clrsetbits_32(MP_MISC_DCM_CFG0,
+			MP_CPUSYS_TOP_APB_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_APB_DCM_REG0_ON);
+		mmio_clrsetbits_32(MCUSYS_DCM_CFG0,
+			MP_CPUSYS_TOP_APB_DCM_REG1_MASK,
+			MP_CPUSYS_TOP_APB_DCM_REG1_ON);
+		mmio_clrsetbits_32(MP0_DCM_CFG0,
+			MP_CPUSYS_TOP_APB_DCM_REG2_MASK,
+			MP_CPUSYS_TOP_APB_DCM_REG2_ON);
+	} else {
+		/* TINFO = "Turn OFF DCM 'mp_cpusys_top_apb_dcm'" */
+		mmio_clrsetbits_32(MP_MISC_DCM_CFG0,
+			MP_CPUSYS_TOP_APB_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_APB_DCM_REG0_OFF);
+		mmio_clrsetbits_32(MCUSYS_DCM_CFG0,
+			MP_CPUSYS_TOP_APB_DCM_REG1_MASK,
+			MP_CPUSYS_TOP_APB_DCM_REG1_OFF);
+		mmio_clrsetbits_32(MP0_DCM_CFG0,
+			MP_CPUSYS_TOP_APB_DCM_REG2_MASK,
+			MP_CPUSYS_TOP_APB_DCM_REG2_OFF);
+	}
+}
+
+#define MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK (BIT(11))
+#define MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_ON (BIT(11))
+#define MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_OFF ((0x0 << 11))
+
+bool dcm_mp_cpusys_top_bus_pll_div_dcm_is_on(void)
+{
+	bool ret = true;
+
+	ret &= ((mmio_read_32(BUS_PLLDIV_CFG) &
+		MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK) ==
+		(unsigned int) MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_ON);
+
+	return ret;
+}
+
+void dcm_mp_cpusys_top_bus_pll_div_dcm(bool on)
+{
+	if (on) {
+		/* TINFO = "Turn ON DCM 'mp_cpusys_top_bus_pll_div_dcm'" */
+		mmio_clrsetbits_32(BUS_PLLDIV_CFG,
+			MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_ON);
+	} else {
+		/* TINFO = "Turn OFF DCM 'mp_cpusys_top_bus_pll_div_dcm'" */
+		mmio_clrsetbits_32(BUS_PLLDIV_CFG,
+			MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_OFF);
+	}
+}
+
+#define MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK (BIT(0))
+#define MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_ON (BIT(0))
+#define MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_OFF ((0x0 << 0))
+
+bool dcm_mp_cpusys_top_core_stall_dcm_is_on(void)
+{
+	bool ret = true;
+
+	ret &= ((mmio_read_32(MP0_DCM_CFG7) &
+		MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK) ==
+		(unsigned int) MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_ON);
+
+	return ret;
+}
+
+void dcm_mp_cpusys_top_core_stall_dcm(bool on)
+{
+	if (on) {
+		/* TINFO = "Turn ON DCM 'mp_cpusys_top_core_stall_dcm'" */
+		mmio_clrsetbits_32(MP0_DCM_CFG7,
+			MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_ON);
+	} else {
+		/* TINFO = "Turn OFF DCM 'mp_cpusys_top_core_stall_dcm'" */
+		mmio_clrsetbits_32(MP0_DCM_CFG7,
+			MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_OFF);
+	}
+}
+
+#define MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK ((0xffff << 0))
+#define MP_CPUSYS_TOP_CPUBIU_DCM_REG0_ON ((0xffff << 0))
+#define MP_CPUSYS_TOP_CPUBIU_DCM_REG0_OFF ((0x0 << 0))
+
+bool dcm_mp_cpusys_top_cpubiu_dcm_is_on(void)
+{
+	bool ret = true;
+
+	ret &= ((mmio_read_32(MCSI_DCM0) &
+		MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK) ==
+		(unsigned int) MP_CPUSYS_TOP_CPUBIU_DCM_REG0_ON);
+
+	return ret;
+}
+
+void dcm_mp_cpusys_top_cpubiu_dcm(bool on)
+{
+	if (on) {
+		/* TINFO = "Turn ON DCM 'mp_cpusys_top_cpubiu_dcm'" */
+		mmio_clrsetbits_32(MCSI_DCM0,
+			MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_CPUBIU_DCM_REG0_ON);
+	} else {
+		/* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpubiu_dcm'" */
+		mmio_clrsetbits_32(MCSI_DCM0,
+			MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_CPUBIU_DCM_REG0_OFF);
+	}
+}
+
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK (BIT(11))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_ON (BIT(11))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_OFF ((0x0 << 11))
+
+bool dcm_mp_cpusys_top_cpu_pll_div_0_dcm_is_on(void)
+{
+	bool ret = true;
+
+	ret &= ((mmio_read_32(CPU_PLLDIV_CFG0) &
+		MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK) ==
+		(unsigned int) MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_ON);
+
+	return ret;
+}
+
+void dcm_mp_cpusys_top_cpu_pll_div_0_dcm(bool on)
+{
+	if (on) {
+		/* TINFO = "Turn ON DCM 'mp_cpusys_top_cpu_pll_div_0_dcm'" */
+		mmio_clrsetbits_32(CPU_PLLDIV_CFG0,
+			MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_ON);
+	} else {
+		/* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpu_pll_div_0_dcm'" */
+		mmio_clrsetbits_32(CPU_PLLDIV_CFG0,
+			MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_OFF);
+	}
+}
+
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK (BIT(11))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_ON (BIT(11))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_OFF ((0x0 << 11))
+
+bool dcm_mp_cpusys_top_cpu_pll_div_1_dcm_is_on(void)
+{
+	bool ret = true;
+
+	ret &= ((mmio_read_32(CPU_PLLDIV_CFG1) &
+		MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK) ==
+		(unsigned int) MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_ON);
+
+	return ret;
+}
+
+void dcm_mp_cpusys_top_cpu_pll_div_1_dcm(bool on)
+{
+	if (on) {
+		/* TINFO = "Turn ON DCM 'mp_cpusys_top_cpu_pll_div_1_dcm'" */
+		mmio_clrsetbits_32(CPU_PLLDIV_CFG1,
+			MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_ON);
+	} else {
+		/* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpu_pll_div_1_dcm'" */
+		mmio_clrsetbits_32(CPU_PLLDIV_CFG1,
+			MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_OFF);
+	}
+}
+
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_2_DCM_REG0_MASK (BIT(11))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_2_DCM_REG0_ON (BIT(11))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_2_DCM_REG0_OFF ((0x0 << 11))
+
+bool dcm_mp_cpusys_top_cpu_pll_div_2_dcm_is_on(void)
+{
+	bool ret = true;
+
+	ret &= ((mmio_read_32(CPU_PLLDIV_CFG2) &
+		MP_CPUSYS_TOP_CPU_PLL_DIV_2_DCM_REG0_MASK) ==
+		(unsigned int) MP_CPUSYS_TOP_CPU_PLL_DIV_2_DCM_REG0_ON);
+
+	return ret;
+}
+
+void dcm_mp_cpusys_top_cpu_pll_div_2_dcm(bool on)
+{
+	if (on) {
+		/* TINFO = "Turn ON DCM 'mp_cpusys_top_cpu_pll_div_2_dcm'" */
+		mmio_clrsetbits_32(CPU_PLLDIV_CFG2,
+			MP_CPUSYS_TOP_CPU_PLL_DIV_2_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_CPU_PLL_DIV_2_DCM_REG0_ON);
+	} else {
+		/* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpu_pll_div_2_dcm'" */
+		mmio_clrsetbits_32(CPU_PLLDIV_CFG2,
+			MP_CPUSYS_TOP_CPU_PLL_DIV_2_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_CPU_PLL_DIV_2_DCM_REG0_OFF);
+	}
+}
+
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_3_DCM_REG0_MASK (BIT(11))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_3_DCM_REG0_ON (BIT(11))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_3_DCM_REG0_OFF ((0x0 << 11))
+
+bool dcm_mp_cpusys_top_cpu_pll_div_3_dcm_is_on(void)
+{
+	bool ret = true;
+
+	ret &= ((mmio_read_32(CPU_PLLDIV_CFG3) &
+		MP_CPUSYS_TOP_CPU_PLL_DIV_3_DCM_REG0_MASK) ==
+		(unsigned int) MP_CPUSYS_TOP_CPU_PLL_DIV_3_DCM_REG0_ON);
+
+	return ret;
+}
+
+void dcm_mp_cpusys_top_cpu_pll_div_3_dcm(bool on)
+{
+	if (on) {
+		/* TINFO = "Turn ON DCM 'mp_cpusys_top_cpu_pll_div_3_dcm'" */
+		mmio_clrsetbits_32(CPU_PLLDIV_CFG3,
+			MP_CPUSYS_TOP_CPU_PLL_DIV_3_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_CPU_PLL_DIV_3_DCM_REG0_ON);
+	} else {
+		/* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpu_pll_div_3_dcm'" */
+		mmio_clrsetbits_32(CPU_PLLDIV_CFG3,
+			MP_CPUSYS_TOP_CPU_PLL_DIV_3_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_CPU_PLL_DIV_3_DCM_REG0_OFF);
+	}
+}
+
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_4_DCM_REG0_MASK (BIT(11))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_4_DCM_REG0_ON (BIT(11))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_4_DCM_REG0_OFF ((0x0 << 11))
+
+bool dcm_mp_cpusys_top_cpu_pll_div_4_dcm_is_on(void)
+{
+	bool ret = true;
+
+	ret &= ((mmio_read_32(CPU_PLLDIV_CFG4) &
+		MP_CPUSYS_TOP_CPU_PLL_DIV_4_DCM_REG0_MASK) ==
+		(unsigned int) MP_CPUSYS_TOP_CPU_PLL_DIV_4_DCM_REG0_ON);
+
+	return ret;
+}
+
+void dcm_mp_cpusys_top_cpu_pll_div_4_dcm(bool on)
+{
+	if (on) {
+		/* TINFO = "Turn ON DCM 'mp_cpusys_top_cpu_pll_div_4_dcm'" */
+		mmio_clrsetbits_32(CPU_PLLDIV_CFG4,
+			MP_CPUSYS_TOP_CPU_PLL_DIV_4_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_CPU_PLL_DIV_4_DCM_REG0_ON);
+	} else {
+		/* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpu_pll_div_4_dcm'" */
+		mmio_clrsetbits_32(CPU_PLLDIV_CFG4,
+			MP_CPUSYS_TOP_CPU_PLL_DIV_4_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_CPU_PLL_DIV_4_DCM_REG0_OFF);
+	}
+}
+
+#define MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK (BIT(4))
+#define MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_ON (BIT(4))
+#define MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_OFF ((0x0 << 4))
+
+bool dcm_mp_cpusys_top_fcm_stall_dcm_is_on(void)
+{
+	bool ret = true;
+
+	ret &= ((mmio_read_32(MP0_DCM_CFG7) &
+		MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK) ==
+		(unsigned int) MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_ON);
+
+	return ret;
+}
+
+void dcm_mp_cpusys_top_fcm_stall_dcm(bool on)
+{
+	if (on) {
+		/* TINFO = "Turn ON DCM 'mp_cpusys_top_fcm_stall_dcm'" */
+		mmio_clrsetbits_32(MP0_DCM_CFG7,
+			MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_ON);
+	} else {
+		/* TINFO = "Turn OFF DCM 'mp_cpusys_top_fcm_stall_dcm'" */
+		mmio_clrsetbits_32(MP0_DCM_CFG7,
+			MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_OFF);
+	}
+}
+
+#define MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK ((0x1U << 31))
+#define MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_ON ((0x1U << 31))
+#define MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_OFF ((0x0U << 31))
+
+bool dcm_mp_cpusys_top_last_cor_idle_dcm_is_on(void)
+{
+	bool ret = true;
+
+	ret &= ((mmio_read_32(BUS_PLLDIV_CFG) &
+		MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK) ==
+		(unsigned int) MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_ON);
+
+	return ret;
+}
+
+void dcm_mp_cpusys_top_last_cor_idle_dcm(bool on)
+{
+	if (on) {
+		/* TINFO = "Turn ON DCM 'mp_cpusys_top_last_cor_idle_dcm'" */
+		mmio_clrsetbits_32(BUS_PLLDIV_CFG,
+			MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_ON);
+	} else {
+		/* TINFO = "Turn OFF DCM 'mp_cpusys_top_last_cor_idle_dcm'" */
+		mmio_clrsetbits_32(BUS_PLLDIV_CFG,
+			MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_OFF);
+	}
+}
+
+#define MP_CPUSYS_TOP_MISC_DCM_REG0_MASK (BIT(1) | \
+			BIT(4))
+#define MP_CPUSYS_TOP_MISC_DCM_REG0_ON (BIT(1) | \
+			BIT(4))
+#define MP_CPUSYS_TOP_MISC_DCM_REG0_OFF ((0x0 << 1) | \
+			(0x0 << 4))
+
+bool dcm_mp_cpusys_top_misc_dcm_is_on(void)
+{
+	bool ret = true;
+
+	ret &= ((mmio_read_32(MP_MISC_DCM_CFG0) &
+		MP_CPUSYS_TOP_MISC_DCM_REG0_MASK) ==
+		(unsigned int) MP_CPUSYS_TOP_MISC_DCM_REG0_ON);
+
+	return ret;
+}
+
+void dcm_mp_cpusys_top_misc_dcm(bool on)
+{
+	if (on) {
+		/* TINFO = "Turn ON DCM 'mp_cpusys_top_misc_dcm'" */
+		mmio_clrsetbits_32(MP_MISC_DCM_CFG0,
+			MP_CPUSYS_TOP_MISC_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_MISC_DCM_REG0_ON);
+	} else {
+		/* TINFO = "Turn OFF DCM 'mp_cpusys_top_misc_dcm'" */
+		mmio_clrsetbits_32(MP_MISC_DCM_CFG0,
+			MP_CPUSYS_TOP_MISC_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_MISC_DCM_REG0_OFF);
+	}
+}
+
+#define MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK (BIT(3))
+#define MP_CPUSYS_TOP_MP0_QDCM_REG1_MASK (BIT(0) | \
+			BIT(1) | \
+			BIT(2) | \
+			BIT(3))
+#define MP_CPUSYS_TOP_MP0_QDCM_REG0_ON (BIT(3))
+#define MP_CPUSYS_TOP_MP0_QDCM_REG1_ON (BIT(0) | \
+			BIT(1) | \
+			BIT(2) | \
+			BIT(3))
+#define MP_CPUSYS_TOP_MP0_QDCM_REG0_OFF ((0x0 << 3))
+#define MP_CPUSYS_TOP_MP0_QDCM_REG1_OFF ((0x0 << 0) | \
+			(0x0 << 1) | \
+			(0x0 << 2) | \
+			(0x0 << 3))
+
+bool dcm_mp_cpusys_top_mp0_qdcm_is_on(void)
+{
+	bool ret = true;
+
+	ret &= ((mmio_read_32(MP_MISC_DCM_CFG0) &
+		MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK) ==
+		(unsigned int) MP_CPUSYS_TOP_MP0_QDCM_REG0_ON);
+	ret &= ((mmio_read_32(MP0_DCM_CFG0) &
+		MP_CPUSYS_TOP_MP0_QDCM_REG1_MASK) ==
+		(unsigned int) MP_CPUSYS_TOP_MP0_QDCM_REG1_ON);
+
+	return ret;
+}
+
+void dcm_mp_cpusys_top_mp0_qdcm(bool on)
+{
+	if (on) {
+		/* TINFO = "Turn ON DCM 'mp_cpusys_top_mp0_qdcm'" */
+		mmio_clrsetbits_32(MP_MISC_DCM_CFG0,
+			MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK,
+			MP_CPUSYS_TOP_MP0_QDCM_REG0_ON);
+		mmio_clrsetbits_32(MP0_DCM_CFG0,
+			MP_CPUSYS_TOP_MP0_QDCM_REG1_MASK,
+			MP_CPUSYS_TOP_MP0_QDCM_REG1_ON);
+	} else {
+		/* TINFO = "Turn OFF DCM 'mp_cpusys_top_mp0_qdcm'" */
+		mmio_clrsetbits_32(MP_MISC_DCM_CFG0,
+			MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK,
+			MP_CPUSYS_TOP_MP0_QDCM_REG0_OFF);
+		mmio_clrsetbits_32(MP0_DCM_CFG0,
+			MP_CPUSYS_TOP_MP0_QDCM_REG1_MASK,
+			MP_CPUSYS_TOP_MP0_QDCM_REG1_OFF);
+	}
+}
+
+#define CPCCFG_REG_EMI_WFIFO_REG0_MASK (BIT(0) | \
+			BIT(1) | \
+			BIT(2) | \
+			BIT(3))
+#define CPCCFG_REG_EMI_WFIFO_REG0_ON (BIT(0) | \
+			BIT(1) | \
+			BIT(2) | \
+			BIT(3))
+#define CPCCFG_REG_EMI_WFIFO_REG0_OFF ((0x0 << 0) | \
+			(0x0 << 1) | \
+			(0x0 << 2) | \
+			(0x0 << 3))
+
+bool dcm_cpccfg_reg_emi_wfifo_is_on(void)
+{
+	bool ret = true;
+
+	ret &= ((mmio_read_32(EMI_WFIFO) &
+		CPCCFG_REG_EMI_WFIFO_REG0_MASK) ==
+		(unsigned int) CPCCFG_REG_EMI_WFIFO_REG0_ON);
+
+	return ret;
+}
+
+void dcm_cpccfg_reg_emi_wfifo(bool on)
+{
+	if (on) {
+		/* TINFO = "Turn ON DCM 'cpccfg_reg_emi_wfifo'" */
+		mmio_clrsetbits_32(EMI_WFIFO,
+			CPCCFG_REG_EMI_WFIFO_REG0_MASK,
+			CPCCFG_REG_EMI_WFIFO_REG0_ON);
+	} else {
+		/* TINFO = "Turn OFF DCM 'cpccfg_reg_emi_wfifo'" */
+		mmio_clrsetbits_32(EMI_WFIFO,
+			CPCCFG_REG_EMI_WFIFO_REG0_MASK,
+			CPCCFG_REG_EMI_WFIFO_REG0_OFF);
+	}
+}
+
diff --git a/plat/mediatek/mt8192/drivers/dcm/mtk_dcm_utils.h b/plat/mediatek/mt8192/drivers/dcm/mtk_dcm_utils.h
new file mode 100644
index 0000000..1cf7834
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/dcm/mtk_dcm_utils.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTK_DCM_UTILS_H
+#define MTK_DCM_UTILS_H
+
+#include <stdbool.h>
+
+#include <mtk_dcm.h>
+#include <platform_def.h>
+
+/* Base */
+#define MP_CPUSYS_TOP_BASE	(MCUCFG_BASE + 0x8000)
+#define CPCCFG_REG_BASE		(MCUCFG_BASE + 0xA800)
+
+/* Register Definition */
+#define CPU_PLLDIV_CFG0		(MP_CPUSYS_TOP_BASE + 0x22a0)
+#define CPU_PLLDIV_CFG1		(MP_CPUSYS_TOP_BASE + 0x22a4)
+#define CPU_PLLDIV_CFG2		(MP_CPUSYS_TOP_BASE + 0x22a8)
+#define CPU_PLLDIV_CFG3		(MP_CPUSYS_TOP_BASE + 0x22ac)
+#define CPU_PLLDIV_CFG4		(MP_CPUSYS_TOP_BASE + 0x22b0)
+#define BUS_PLLDIV_CFG		(MP_CPUSYS_TOP_BASE + 0x22e0)
+#define MCSI_DCM0		(MP_CPUSYS_TOP_BASE + 0x2440)
+#define MP_ADB_DCM_CFG0		(MP_CPUSYS_TOP_BASE + 0x2500)
+#define MP_ADB_DCM_CFG4		(MP_CPUSYS_TOP_BASE + 0x2510)
+#define MP_MISC_DCM_CFG0	(MP_CPUSYS_TOP_BASE + 0x2518)
+#define MCUSYS_DCM_CFG0		(MP_CPUSYS_TOP_BASE + 0x25c0)
+#define EMI_WFIFO		(CPCCFG_REG_BASE + 0x100)
+#define MP0_DCM_CFG0		(MP_CPUSYS_TOP_BASE + 0x4880)
+#define MP0_DCM_CFG7		(MP_CPUSYS_TOP_BASE + 0x489c)
+
+/* MP_CPUSYS_TOP */
+bool dcm_mp_cpusys_top_adb_dcm_is_on(void);
+void dcm_mp_cpusys_top_adb_dcm(bool on);
+bool dcm_mp_cpusys_top_apb_dcm_is_on(void);
+void dcm_mp_cpusys_top_apb_dcm(bool on);
+bool dcm_mp_cpusys_top_bus_pll_div_dcm_is_on(void);
+void dcm_mp_cpusys_top_bus_pll_div_dcm(bool on);
+bool dcm_mp_cpusys_top_core_stall_dcm_is_on(void);
+void dcm_mp_cpusys_top_core_stall_dcm(bool on);
+bool dcm_mp_cpusys_top_cpubiu_dcm_is_on(void);
+void dcm_mp_cpusys_top_cpubiu_dcm(bool on);
+bool dcm_mp_cpusys_top_cpu_pll_div_0_dcm_is_on(void);
+void dcm_mp_cpusys_top_cpu_pll_div_0_dcm(bool on);
+bool dcm_mp_cpusys_top_cpu_pll_div_1_dcm_is_on(void);
+void dcm_mp_cpusys_top_cpu_pll_div_1_dcm(bool on);
+bool dcm_mp_cpusys_top_cpu_pll_div_2_dcm_is_on(void);
+void dcm_mp_cpusys_top_cpu_pll_div_2_dcm(bool on);
+bool dcm_mp_cpusys_top_cpu_pll_div_3_dcm_is_on(void);
+void dcm_mp_cpusys_top_cpu_pll_div_3_dcm(bool on);
+bool dcm_mp_cpusys_top_cpu_pll_div_4_dcm_is_on(void);
+void dcm_mp_cpusys_top_cpu_pll_div_4_dcm(bool on);
+bool dcm_mp_cpusys_top_fcm_stall_dcm_is_on(void);
+void dcm_mp_cpusys_top_fcm_stall_dcm(bool on);
+bool dcm_mp_cpusys_top_last_cor_idle_dcm_is_on(void);
+void dcm_mp_cpusys_top_last_cor_idle_dcm(bool on);
+bool dcm_mp_cpusys_top_misc_dcm_is_on(void);
+void dcm_mp_cpusys_top_misc_dcm(bool on);
+bool dcm_mp_cpusys_top_mp0_qdcm_is_on(void);
+void dcm_mp_cpusys_top_mp0_qdcm(bool on);
+/* CPCCFG_REG */
+bool dcm_cpccfg_reg_emi_wfifo_is_on(void);
+void dcm_cpccfg_reg_emi_wfifo(bool on);
+
+#endif
diff --git a/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.c b/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.c
new file mode 100644
index 0000000..d5d7e2e
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <emi_mpu.h>
+#include <lib/mmio.h>
+
+/*
+ * emi_mpu_set_region_protection: protect a region.
+ * @start: start address of the region
+ * @end: end address of the region
+ * @access_permission: EMI MPU access permission
+ * Return 0 for success, otherwise negative status code.
+ */
+static int _emi_mpu_set_protection(
+	unsigned long start, unsigned long end,
+	unsigned int apc)
+{
+	unsigned int dgroup;
+	unsigned int region;
+
+	region = (start >> 24) & 0xFF;
+	start &= 0x00FFFFFF;
+	dgroup = (end >> 24) & 0xFF;
+	end &= 0x00FFFFFF;
+
+	if  ((region >= EMI_MPU_REGION_NUM) || (dgroup > EMI_MPU_DGROUP_NUM)) {
+		WARN("Region:%u or dgroup:%u is wrong!\n", region, dgroup);
+		return -1;
+	}
+
+	apc &= 0x80FFFFFF;
+
+	if ((start >= DRAM_OFFSET) && (end >= start)) {
+		start -= DRAM_OFFSET;
+		end -= DRAM_OFFSET;
+	} else {
+		WARN("start:0x%lx or end:0x%lx address is wrong!\n",
+		     start, end);
+		return -2;
+	}
+
+	mmio_write_32(EMI_MPU_SA(region), start);
+	mmio_write_32(EMI_MPU_EA(region), end);
+	mmio_write_32(EMI_MPU_APC(region, dgroup), apc);
+
+	return 0;
+}
+
+void dump_emi_mpu_regions(void)
+{
+	unsigned long apc[EMI_MPU_DGROUP_NUM], sa, ea;
+
+	int region, i;
+
+	/* Only dump 8 regions(max: EMI_MPU_REGION_NUM --> 32) */
+	for (region = 0; region < 8; ++region) {
+		for (i = 0; i < EMI_MPU_DGROUP_NUM; ++i)
+			apc[i] = mmio_read_32(EMI_MPU_APC(region, i));
+		sa = mmio_read_32(EMI_MPU_SA(region));
+		ea = mmio_read_32(EMI_MPU_EA(region));
+
+		WARN("region %d:\n", region);
+		WARN("\tsa:0x%lx, ea:0x%lx, apc0: 0x%lx apc1: 0x%lx\n",
+		     sa, ea, apc[0], apc[1]);
+	}
+}
+
+int emi_mpu_set_protection(struct emi_region_info_t *region_info)
+{
+	unsigned long start, end;
+	int i;
+
+	if (region_info->region >= EMI_MPU_REGION_NUM)
+		return -1;
+
+	start = (unsigned long)(region_info->start >> EMI_MPU_ALIGN_BITS) |
+		(region_info->region << 24);
+
+	for (i = EMI_MPU_DGROUP_NUM - 1; i >= 0; i--) {
+		end = (unsigned long)(region_info->end >> EMI_MPU_ALIGN_BITS) |
+			(i << 24);
+		_emi_mpu_set_protection(start, end, region_info->apc[i]);
+	}
+
+	return 0;
+}
+
+void emi_mpu_init(void)
+{
+	/* Set permission */
+	struct emi_region_info_t region_info;
+
+	/* PCE-e protect address(TODO) */
+	region_info.start = 0x80000000ULL;
+	region_info.end = 0x83FF0000ULL;
+	region_info.region = 1;
+	SET_ACCESS_PERMISSION(region_info.apc, 1,
+			      FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+			      FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+			      FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+			      FORBIDDEN, FORBIDDEN, NO_PROT,
+			      NO_PROT /*FORBIDDEN*/);
+	emi_mpu_set_protection(&region_info);
+
+	/* Forbidden All */
+	region_info.start = 0x40000000ULL;	/* dram base addr */
+	region_info.end = 0x1FFFF0000ULL;
+	region_info.region = 2;
+	SET_ACCESS_PERMISSION(region_info.apc, 1,
+			      NO_PROT, NO_PROT, NO_PROT, NO_PROT,
+			      NO_PROT, NO_PROT, NO_PROT, NO_PROT,
+			      NO_PROT, NO_PROT, NO_PROT, NO_PROT,
+			      NO_PROT, FORBIDDEN, NO_PROT, NO_PROT);
+	emi_mpu_set_protection(&region_info);
+
+	dump_emi_mpu_regions();
+}
+
diff --git a/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.h b/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.h
new file mode 100644
index 0000000..0b15431
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef EMI_MPU_H
+#define EMI_MPU_H
+
+#include <platform_def.h>
+
+#define EMI_MPUP		(EMI_BASE + 0x01D8)
+#define EMI_MPUQ		(EMI_BASE + 0x01E0)
+#define EMI_MPUR		(EMI_BASE + 0x01E8)
+#define EMI_MPUS		(EMI_BASE + 0x01F0)
+#define EMI_MPUT		(EMI_BASE + 0x01F8)
+#define EMI_MPUY		(EMI_BASE + 0x0220)
+#define EMI_MPU_CTRL		(EMI_MPU_BASE + 0x0000)
+#define EMI_MPUD0_ST		(EMI_BASE + 0x0160)
+#define EMI_MPUD1_ST		(EMI_BASE + 0x0164)
+#define EMI_MPUD2_ST		(EMI_BASE + 0x0168)
+#define EMI_MPUD3_ST		(EMI_BASE + 0x016C)
+#define EMI_MPUD0_ST2		(EMI_BASE + 0x0200)
+#define EMI_MPUD1_ST2		(EMI_BASE + 0x0204)
+#define EMI_MPUD2_ST2		(EMI_BASE + 0x0208)
+#define EMI_MPUD3_ST2		(EMI_BASE + 0x020C)
+
+#define EMI_PHY_OFFSET		(0x40000000UL)
+
+#define NO_PROT 		(0)
+#define SEC_RW			(1)
+#define SEC_RW_NSEC_R		(2)
+#define SEC_RW_NSEC_W		(3)
+#define SEC_R_NSEC_R		(4)
+#define FORBIDDEN		(5)
+#define SEC_R_NSEC_RW		(6)
+
+#define SECURE_OS_MPU_REGION_ID	(0)
+#define ATF_MPU_REGION_ID	(1)
+
+#define EMI_MPU_SA0		(EMI_MPU_BASE + 0x100)
+#define EMI_MPU_EA0		(EMI_MPU_BASE + 0x200)
+#define EMI_MPU_SA(region)	(EMI_MPU_SA0 + (region) * 4)
+#define EMI_MPU_EA(region)	(EMI_MPU_EA0 + (region) * 4)
+
+#define EMI_MPU_APC0			(EMI_MPU_BASE + 0x300)
+#define EMI_MPU_APC(region, dgroup)	(EMI_MPU_APC0 + (region) * 4 + \
+					(dgroup) * 0x100)
+
+#define EMI_MPU_CTRL_D0		(EMI_MPU_BASE + 0x800)
+#define EMI_MPU_CTRL_D(domain)	(EMI_MPU_CTRL_D0 + domain * 4)
+#define EMI_RG_MASK_D0		(EMI_MPU_BASE + 0x900)
+#define EMI_RG_MASK_D(domain)	(EMI_RG_MASK_D0 + domain * 4)
+
+#define EMI_MPU_DOMAIN_NUM	16
+#define EMI_MPU_REGION_NUM	32
+#define EMI_MPU_ALIGN_BITS	16
+#define DRAM_OFFSET		(0x40000000 >> EMI_MPU_ALIGN_BITS)
+
+#define EMI_MPU_DGROUP_NUM	(EMI_MPU_DOMAIN_NUM / 8)
+
+#if (EMI_MPU_DGROUP_NUM == 1)
+#define SET_ACCESS_PERMISSION(apc_ary, lock, d7, d6, d5, d4, d3, d2, d1, d0) \
+do { \
+	apc_ary[0] = 0; \
+	apc_ary[0] = \
+		(((unsigned int)    d7) << 21) | (((unsigned int)  d6) << 18) \
+		| (((unsigned int)  d5) << 15) | (((unsigned int)  d4) << 12) \
+		| (((unsigned int)  d3) <<  9) | (((unsigned int)  d2) <<  6) \
+		| (((unsigned int)  d1) <<  3) | ((unsigned int)   d0) \
+		| (((unsigned int) lock) << 31); \
+} while (0)
+#elif (EMI_MPU_DGROUP_NUM == 2)
+#define SET_ACCESS_PERMISSION(apc_ary, lock, d15, d14, d13, d12, d11, d10, \
+			      d9, d8, d7, d6, d5, d4, d3, d2, d1, d0) \
+do { \
+	apc_ary[1] = \
+		(((unsigned int)   d15) << 21) | (((unsigned int) d14) << 18) \
+		| (((unsigned int) d13) << 15) | (((unsigned int) d12) << 12) \
+		| (((unsigned int) d11) <<  9) | (((unsigned int) d10) <<  6) \
+		| (((unsigned int)  d9) <<  3) |  ((unsigned int)  d8); \
+	apc_ary[0] = \
+		(((unsigned int)    d7) << 21) | (((unsigned int)  d6) << 18) \
+		| (((unsigned int)  d5) << 15) | (((unsigned int)  d4) << 12) \
+		| (((unsigned int)  d3) <<  9) | (((unsigned int)  d2) <<  6) \
+		| (((unsigned int)  d1) <<  3) |  ((unsigned int)  d0) \
+		| (((unsigned int) lock) << 31); \
+} while (0)
+#endif
+
+struct emi_region_info_t {
+	unsigned long long	start;
+	unsigned long long	end;
+	unsigned int		region;
+	unsigned long		apc[EMI_MPU_DGROUP_NUM];
+};
+
+void emi_mpu_init(void);
+int emi_mpu_set_protection(struct emi_region_info_t *region_info);
+void dump_emi_mpu_regions(void);
+
+#endif  /* __EMI_MPU_H */
diff --git a/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm.c b/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm.c
new file mode 100644
index 0000000..d6d4af7
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdint.h>
+
+#include <arch_helpers.h>
+#include <lib/psci/psci.h>
+#include <lib/spinlock.h>
+
+#include <mt_cpu_pm_cpc.h>
+#include <mt_mcdi.h>
+#include <plat_mtk_lpm.h>
+#include <plat_pm.h>
+
+DEFINE_SYSREG_RW_FUNCS(dbgprcr_el1);
+
+static int plat_mt_lp_cpu_rc;
+
+static int pwr_state_prompt(unsigned int cpu, const psci_power_state_t *state)
+{
+	return 0;
+}
+
+static int pwr_state_reflect(unsigned int cpu, const psci_power_state_t *state)
+{
+	mtk_cpc_core_on_hint_clr(cpu);
+
+	if (IS_SYSTEM_SUSPEND_STATE(state)) {
+		mtk_cpc_time_sync();
+	}
+
+	return 0;
+}
+
+static int pwr_cpu_pwron(unsigned int cpu, const psci_power_state_t *state)
+{
+	return 0;
+}
+
+static int pwr_cpu_pwrdwn(unsigned int cpu, const psci_power_state_t *state)
+{
+	/* clear DBGPRCR.CORENPDRQ to allow CPU power down  */
+	write_dbgprcr_el1(0ULL);
+
+	return 0;
+}
+
+static int pwr_cluster_pwron(unsigned int cpu, const psci_power_state_t *state)
+{
+	return 0;
+}
+
+static int pwr_cluster_pwrdwn(unsigned int cpu, const psci_power_state_t *state)
+{
+	return 0;
+}
+
+static int pwr_mcusys_pwron(unsigned int cpu, const psci_power_state_t *state)
+{
+	if (!IS_MCUSYS_OFF_STATE(state) || (plat_mt_lp_cpu_rc < 0)) {
+		return -1;
+	}
+
+	mtk_cpc_mcusys_off_reflect();
+
+	return 0;
+}
+
+static int pwr_mcusys_pwron_finished(unsigned int cpu,
+					const psci_power_state_t *state)
+{
+	if (!IS_MCUSYS_OFF_STATE(state) || (plat_mt_lp_cpu_rc < 0)) {
+		return -1;
+	}
+
+	return 0;
+}
+
+static int pwr_mcusys_pwrdwn(unsigned int cpu, const psci_power_state_t *state)
+{
+	if (!IS_MCUSYS_OFF_STATE(state)) {
+		goto mt_pwr_mcusysoff_break;
+	}
+
+	if (mcdi_try_init() != 0) { /* not ready to process mcusys-off */
+		goto mt_pwr_mcusysoff_break;
+	}
+
+	return 0;
+
+mt_pwr_mcusysoff_break:
+
+	plat_mt_lp_cpu_rc = -1;
+
+	return -1;
+}
+
+static const struct mt_lpm_tz plat_pm = {
+	.pwr_prompt			= pwr_state_prompt,
+	.pwr_reflect			= pwr_state_reflect,
+	.pwr_cpu_on			= pwr_cpu_pwron,
+	.pwr_cpu_dwn			= pwr_cpu_pwrdwn,
+	.pwr_cluster_on			= pwr_cluster_pwron,
+	.pwr_cluster_dwn		= pwr_cluster_pwrdwn,
+	.pwr_mcusys_dwn			= pwr_mcusys_pwrdwn,
+	.pwr_mcusys_on			= pwr_mcusys_pwron,
+	.pwr_mcusys_on_finished		= pwr_mcusys_pwron_finished
+};
+
+const struct mt_lpm_tz *mt_plat_cpu_pm_init(void)
+{
+	mtk_cpc_init();
+
+	if (mcdi_try_init() == 0) {
+		INFO("MCDI init done.\n");
+	}
+
+	return &plat_pm;
+}
diff --git a/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm_cpc.c b/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm_cpc.c
new file mode 100644
index 0000000..f8c51a1
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm_cpc.c
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+
+#include <drivers/delay_timer.h>
+
+#include <mt_cpu_pm_cpc.h>
+#include <mt_timer.h>
+
+struct mtk_cpc_dev {
+	int auto_off;
+	unsigned int auto_thres_tick;
+};
+
+static struct mtk_cpc_dev cpc;
+
+static int mtk_cpc_last_core_prot(uint32_t prot_req,
+				uint32_t resp_reg, uint32_t resp_ofs)
+{
+	uint32_t sta, retry;
+
+	retry = 0U;
+
+	while (retry++ < RETRY_CNT_MAX) {
+
+		mmio_write_32(CPC_MCUSYS_LAST_CORE_REQ, prot_req);
+
+		udelay(1U);
+
+		sta = (mmio_read_32(resp_reg) >> resp_ofs) & CPC_PROT_RESP_MASK;
+
+		if (sta == PROT_SUCCESS) {
+			return CPC_SUCCESS;
+		} else if (sta == PROT_GIVEUP) {
+			return CPC_ERR_FAIL;
+		}
+	}
+
+	return CPC_ERR_TIMEOUT;
+}
+
+int mtk_cpu_pm_mcusys_prot_aquire(void)
+{
+	return mtk_cpc_last_core_prot(
+			MCUSYS_PROT_SET,
+			CPC_MCUSYS_LAST_CORE_RESP,
+			MCUSYS_RESP_OFS);
+}
+
+void mtk_cpu_pm_mcusys_prot_release(void)
+{
+	mmio_write_32(CPC_MCUSYS_PWR_ON_MASK, MCUSYS_PROT_CLR);
+}
+
+int mtk_cpu_pm_cluster_prot_aquire(unsigned int cluster)
+{
+	return mtk_cpc_last_core_prot(
+			CPUSYS_PROT_SET,
+			CPC_MCUSYS_MP_LAST_CORE_RESP,
+			CPUSYS_RESP_OFS);
+}
+
+void mtk_cpu_pm_cluster_prot_release(unsigned int cluster)
+{
+	mmio_write_32(CPC_MCUSYS_PWR_ON_MASK, CPUSYS_PROT_CLR);
+}
+
+static void mtk_cpc_cluster_cnt_backup(void)
+{
+	uint32_t backup_cnt;
+	uint32_t curr_cnt;
+	uint32_t cnt_mask = GENMASK(14, 0);
+	uint32_t clr_mask = GENMASK(1, 0);
+
+	/* Single Cluster */
+	backup_cnt = mmio_read_32(CPC_CLUSTER_CNT_BACKUP);
+	curr_cnt = mmio_read_32(CPC_MCUSYS_CLUSTER_COUNTER);
+
+	/* Get off count if dormant count is 0 */
+	if ((curr_cnt & cnt_mask) == 0U) {
+		curr_cnt = (curr_cnt >> 16) & cnt_mask;
+	} else {
+		curr_cnt = curr_cnt & cnt_mask;
+	}
+
+	mmio_write_32(CPC_CLUSTER_CNT_BACKUP, backup_cnt + curr_cnt);
+	mmio_write_32(CPC_MCUSYS_CLUSTER_COUNTER_CLR, clr_mask);
+}
+
+static inline void mtk_cpc_mcusys_off_en(void)
+{
+	mmio_write_32(CPC_MCUSYS_PWR_CTRL, 1U);
+}
+
+static inline void mtk_cpc_mcusys_off_dis(void)
+{
+	mmio_write_32(CPC_MCUSYS_PWR_CTRL, 0U);
+}
+
+void mtk_cpc_mcusys_off_reflect(void)
+{
+	mtk_cpc_mcusys_off_dis();
+	mtk_cpu_pm_mcusys_prot_release();
+}
+
+int mtk_cpc_mcusys_off_prepare(void)
+{
+	if (mtk_cpu_pm_mcusys_prot_aquire() != CPC_SUCCESS) {
+		return CPC_ERR_FAIL;
+	}
+
+	mtk_cpc_cluster_cnt_backup();
+	mtk_cpc_mcusys_off_en();
+
+	return CPC_SUCCESS;
+}
+
+void mtk_cpc_core_on_hint_set(unsigned int cpu)
+{
+	mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_SET, BIT(cpu));
+}
+
+void mtk_cpc_core_on_hint_clr(unsigned int cpu)
+{
+	mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_CLR, BIT(cpu));
+}
+
+static void mtk_cpc_dump_timestamp(void)
+{
+	uint32_t id;
+
+	for (id = 0U; id < CPC_TRACE_ID_NUM; id++) {
+		mmio_write_32(CPC_MCUSYS_TRACE_SEL, id);
+
+		memcpy((void *)(uintptr_t)CPC_TRACE_SRAM(id),
+				(const void *)(uintptr_t)CPC_MCUSYS_TRACE_DATA,
+				CPC_TRACE_SIZE);
+	}
+}
+
+void mtk_cpc_time_sync(void)
+{
+	uint64_t kt;
+	uint32_t systime_l, systime_h;
+
+	kt = sched_clock();
+	systime_l = mmio_read_32(CNTSYS_L_REG);
+	systime_h = mmio_read_32(CNTSYS_H_REG);
+
+	/* sync kernel timer to cpc */
+	mmio_write_32(CPC_MCUSYS_CPC_KERNEL_TIME_L_BASE, (uint32_t)kt);
+	mmio_write_32(CPC_MCUSYS_CPC_KERNEL_TIME_H_BASE, (uint32_t)(kt >> 32));
+	/* sync system timer to cpc */
+	mmio_write_32(CPC_MCUSYS_CPC_SYSTEM_TIME_L_BASE, systime_l);
+	mmio_write_32(CPC_MCUSYS_CPC_SYSTEM_TIME_H_BASE, systime_h);
+}
+
+static void mtk_cpc_config(uint32_t cfg, uint32_t data)
+{
+	uint32_t val;
+	uint32_t reg = 0U;
+
+	switch (cfg) {
+	case CPC_SMC_CONFIG_PROF:
+		reg = CPC_MCUSYS_CPC_DBG_SETTING;
+		val = mmio_read_32(reg);
+		val = (data != 0U) ? (val | CPC_PROF_EN) : (val & ~CPC_PROF_EN);
+		break;
+	case CPC_SMC_CONFIG_AUTO_OFF:
+		reg = CPC_MCUSYS_CPC_FLOW_CTRL_CFG;
+		val = mmio_read_32(reg);
+		if (data != 0U) {
+			val |= CPC_AUTO_OFF_EN;
+			cpc.auto_off = 1;
+		} else {
+			val &= ~CPC_AUTO_OFF_EN;
+			cpc.auto_off = 0;
+		}
+		break;
+	case CPC_SMC_CONFIG_AUTO_OFF_THRES:
+		reg = CPC_MCUSYS_CPC_OFF_THRES;
+		cpc.auto_thres_tick = us_to_ticks(data);
+		val = cpc.auto_thres_tick;
+		break;
+	case CPC_SMC_CONFIG_CNT_CLR:
+		reg = CPC_MCUSYS_CLUSTER_COUNTER_CLR;
+		val = GENMASK(1, 0);	/* clr_mask */
+		break;
+	case CPC_SMC_CONFIG_TIME_SYNC:
+		mtk_cpc_time_sync();
+		break;
+	default:
+		break;
+	}
+
+	if (reg != 0U) {
+		mmio_write_32(reg, val);
+	}
+}
+
+static uint32_t mtk_cpc_read_config(uint32_t cfg)
+{
+	uint32_t res = 0U;
+
+	switch (cfg) {
+	case CPC_SMC_CONFIG_PROF:
+		res = (mmio_read_32(CPC_MCUSYS_CPC_DBG_SETTING) & CPC_PROF_EN) ?
+			1U : 0U;
+		break;
+	case CPC_SMC_CONFIG_AUTO_OFF:
+		res = cpc.auto_off;
+		break;
+	case CPC_SMC_CONFIG_AUTO_OFF_THRES:
+		res = ticks_to_us(cpc.auto_thres_tick);
+		break;
+	case CPC_SMC_CONFIG_CNT_CLR:
+		break;
+	default:
+		break;
+	}
+
+	return res;
+}
+
+uint64_t mtk_cpc_handler(uint64_t act, uint64_t arg1, uint64_t arg2)
+{
+	uint64_t res = 0ULL;
+
+	switch (act) {
+	case CPC_SMC_EVENT_DUMP_TRACE_DATA:
+		mtk_cpc_dump_timestamp();
+		break;
+	case CPC_SMC_EVENT_GIC_DPG_SET:
+		/* isolated_status = x2; */
+		break;
+	case CPC_SMC_EVENT_CPC_CONFIG:
+		mtk_cpc_config((uint32_t)arg1, (uint32_t)arg2);
+		break;
+	case CPC_SMC_EVENT_READ_CONFIG:
+		res = mtk_cpc_read_config((uint32_t)arg1);
+		break;
+	default:
+		break;
+	}
+
+	return res;
+}
+
+void mtk_cpc_init(void)
+{
+	mmio_write_32(CPC_MCUSYS_CPC_DBG_SETTING,
+			mmio_read_32(CPC_MCUSYS_CPC_DBG_SETTING)
+			| CPC_DBG_EN
+			| CPC_CALC_EN);
+
+	cpc.auto_off = 1;
+	cpc.auto_thres_tick = us_to_ticks(8000);
+
+	mmio_write_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG,
+			mmio_read_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG)
+			| CPC_OFF_PRE_EN
+			| (cpc.auto_off ? CPC_AUTO_OFF_EN : 0U));
+
+	mmio_write_32(CPC_MCUSYS_CPC_OFF_THRES, cpc.auto_thres_tick);
+}
diff --git a/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm_cpc.h b/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm_cpc.h
new file mode 100644
index 0000000..19dd6a2
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm_cpc.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_CPU_PM_CPC_H
+#define MT_CPU_PM_CPC_H
+
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+#include <mcucfg.h>
+#include <platform_def.h>
+
+#define NEED_CPUSYS_PROT_WORKAROUND	1
+
+/* system sram registers */
+#define CPUIDLE_SRAM_REG(r)	(uint32_t)(MTK_MCDI_SRAM_BASE + (r))
+
+/* db dump */
+#define CPC_TRACE_SIZE		U(0x20)
+#define CPC_TRACE_ID_NUM	U(10)
+#define CPC_TRACE_SRAM(id)	(CPUIDLE_SRAM_REG(0x10) + (id) * CPC_TRACE_SIZE)
+
+/* buckup off count */
+#define CPC_CLUSTER_CNT_BACKUP	CPUIDLE_SRAM_REG(0x1F0)
+#define CPC_MCUSYS_CNT		CPUIDLE_SRAM_REG(0x1F4)
+
+/* CPC_MCUSYS_CPC_FLOW_CTRL_CFG(0xA814): debug setting */
+#define CPC_PWR_ON_SEQ_DIS	BIT(1)
+#define CPC_PWR_ON_PRIORITY	BIT(2)
+#define CPC_AUTO_OFF_EN		BIT(5)
+#define CPC_DORMANT_WAIT_EN	BIT(14)
+#define CPC_CTRL_EN		BIT(16)
+#define CPC_OFF_PRE_EN		BIT(29)
+
+/* CPC_MCUSYS_LAST_CORE_REQ(0xA818) : last core protection */
+#define CPUSYS_PROT_SET		BIT(0)
+#define MCUSYS_PROT_SET		BIT(8)
+#define CPUSYS_PROT_CLR		BIT(8)
+#define MCUSYS_PROT_CLR		BIT(9)
+
+#define CPC_PROT_RESP_MASK	U(0x3)
+#define CPUSYS_RESP_OFS		U(16)
+#define MCUSYS_RESP_OFS		U(30)
+
+#define cpusys_resp(r)		(((r) >> CPUSYS_RESP_OFS) & CPC_PROT_RESP_MASK)
+#define mcusys_resp(r)		(((r) >> MCUSYS_RESP_OFS) & CPC_PROT_RESP_MASK)
+
+#define RETRY_CNT_MAX		U(1000)
+
+#define PROT_RETRY		U(0)
+#define PROT_SUCCESS		U(1)
+#define PROT_GIVEUP		U(2)
+
+/* CPC_MCUSYS_CPC_DBG_SETTING(0xAB00): debug setting */
+#define CPC_PROF_EN		BIT(0)
+#define CPC_DBG_EN		BIT(1)
+#define CPC_FREEZE		BIT(2)
+#define CPC_CALC_EN		BIT(3)
+
+enum {
+	CPC_SUCCESS = 0,
+
+	CPC_ERR_FAIL,
+	CPC_ERR_TIMEOUT,
+
+	NF_CPC_ERR
+};
+
+enum {
+	CPC_SMC_EVENT_DUMP_TRACE_DATA,
+	CPC_SMC_EVENT_GIC_DPG_SET,
+	CPC_SMC_EVENT_CPC_CONFIG,
+	CPC_SMC_EVENT_READ_CONFIG,
+
+	NF_CPC_SMC_EVENT
+};
+
+enum {
+	CPC_SMC_CONFIG_PROF,
+	CPC_SMC_CONFIG_AUTO_OFF,
+	CPC_SMC_CONFIG_AUTO_OFF_THRES,
+	CPC_SMC_CONFIG_CNT_CLR,
+	CPC_SMC_CONFIG_TIME_SYNC,
+
+	NF_CPC_SMC_CONFIG
+};
+
+#define us_to_ticks(us)		((us) * 13)
+#define ticks_to_us(tick)	((tick) / 13)
+
+int mtk_cpu_pm_cluster_prot_aquire(unsigned int cluster);
+void mtk_cpu_pm_cluster_prot_release(unsigned int cluster);
+
+void mtk_cpc_mcusys_off_reflect(void);
+int mtk_cpc_mcusys_off_prepare(void);
+
+void mtk_cpc_core_on_hint_set(unsigned int cpu);
+void mtk_cpc_core_on_hint_clr(unsigned int cpu);
+void mtk_cpc_time_sync(void);
+
+uint64_t mtk_cpc_handler(uint64_t act, uint64_t arg1, uint64_t arg2);
+void mtk_cpc_init(void);
+
+#endif /* MT_CPU_PM_CPC_H */
diff --git a/plat/mediatek/mt8192/drivers/mcdi/mt_mcdi.c b/plat/mediatek/mt8192/drivers/mcdi/mt_mcdi.c
new file mode 100644
index 0000000..df74122
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/mcdi/mt_mcdi.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <cdefs.h>
+
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+#include <mt_mcdi.h>
+
+/* Read/Write */
+#define APMCU_MCUPM_MBOX_AP_READY	U(0)
+#define APMCU_MCUPM_MBOX_RESERVED_1	U(1)
+#define APMCU_MCUPM_MBOX_RESERVED_2	U(2)
+#define APMCU_MCUPM_MBOX_RESERVED_3	U(3)
+#define APMCU_MCUPM_MBOX_PWR_CTRL_EN	U(4)
+#define APMCU_MCUPM_MBOX_L3_CACHE_MODE	U(5)
+#define APMCU_MCUPM_MBOX_BUCK_MODE	U(6)
+#define APMCU_MCUPM_MBOX_ARMPLL_MODE	U(7)
+/* Read only */
+#define APMCU_MCUPM_MBOX_TASK_STA	U(8)
+#define APMCU_MCUPM_MBOX_RESERVED_9	U(9)
+#define APMCU_MCUPM_MBOX_RESERVED_10	U(10)
+#define APMCU_MCUPM_MBOX_RESERVED_11	U(11)
+
+/* CPC mode - Read/Write */
+#define APMCU_MCUPM_MBOX_WAKEUP_CPU	U(12)
+
+/* Mbox Slot: APMCU_MCUPM_MBOX_PWR_CTRL_EN */
+#define MCUPM_MCUSYS_CTRL		BIT(0)
+#define MCUPM_BUCK_CTRL			BIT(1)
+#define MCUPM_ARMPLL_CTRL		BIT(2)
+#define MCUPM_CM_CTRL			BIT(3)
+#define MCUPM_PWR_CTRL_MASK		GENMASK(3, 0)
+
+/* Mbox Slot: APMCU_MCUPM_MBOX_BUCK_MODE */
+#define MCUPM_BUCK_NORMAL_MODE		U(0) /* default */
+#define MCUPM_BUCK_LP_MODE		U(1)
+#define MCUPM_BUCK_OFF_MODE		U(2)
+#define NF_MCUPM_BUCK_MODE		U(3)
+
+/* Mbox Slot: APMCU_MCUPM_MBOX_ARMPLL_MODE */
+#define MCUPM_ARMPLL_ON			U(0) /* default */
+#define MCUPM_ARMPLL_GATING		U(1)
+#define MCUPM_ARMPLL_OFF		U(2)
+#define NF_MCUPM_ARMPLL_MODE		U(3)
+
+/* Mbox Slot: APMCU_MCUPM_MBOX_TASK_STA */
+#define MCUPM_TASK_UNINIT		U(0)
+#define MCUPM_TASK_INIT			U(1)
+#define MCUPM_TASK_INIT_FINISH		U(2)
+#define MCUPM_TASK_WAIT			U(3)
+#define MCUPM_TASK_RUN			U(4)
+#define MCUPM_TASK_PAUSE		U(5)
+
+#define SSPM_MBOX_3_BASE		U(0x0c55fce0)
+
+#define MCDI_NOT_INIT			0
+#define MCDI_INIT_1			1
+#define MCDI_INIT_2			2
+#define MCDI_INIT_DONE			3
+
+static int mcdi_init_status __section("tzfw_coherent_mem");
+
+static inline uint32_t mcdi_mbox_read(uint32_t id)
+{
+	return mmio_read_32(SSPM_MBOX_3_BASE + (id << 2));
+}
+
+static inline void mcdi_mbox_write(uint32_t id, uint32_t val)
+{
+	mmio_write_32(SSPM_MBOX_3_BASE + (id << 2), val);
+}
+
+static void mtk_mcupm_pwr_ctrl_setting(uint32_t dev)
+{
+	mcdi_mbox_write(APMCU_MCUPM_MBOX_PWR_CTRL_EN, dev);
+}
+
+static void mtk_set_mcupm_pll_mode(uint32_t mode)
+{
+	if (mode < NF_MCUPM_ARMPLL_MODE) {
+		mcdi_mbox_write(APMCU_MCUPM_MBOX_ARMPLL_MODE, mode);
+	}
+}
+
+static void mtk_set_mcupm_buck_mode(uint32_t mode)
+{
+	if (mode < NF_MCUPM_BUCK_MODE) {
+		mcdi_mbox_write(APMCU_MCUPM_MBOX_BUCK_MODE, mode);
+	}
+}
+
+static int mtk_mcupm_is_ready(void)
+{
+	unsigned int sta = mcdi_mbox_read(APMCU_MCUPM_MBOX_TASK_STA);
+
+	return (sta == MCUPM_TASK_WAIT) || (sta == MCUPM_TASK_INIT_FINISH);
+}
+
+static int mcdi_init_1(void)
+{
+	unsigned int sta = mcdi_mbox_read(APMCU_MCUPM_MBOX_TASK_STA);
+
+	if (sta != MCUPM_TASK_INIT) {
+		return -1;
+	}
+
+	mtk_set_mcupm_pll_mode(MCUPM_ARMPLL_OFF);
+	mtk_set_mcupm_buck_mode(MCUPM_BUCK_OFF_MODE);
+
+	mtk_mcupm_pwr_ctrl_setting(
+			 MCUPM_MCUSYS_CTRL |
+			 MCUPM_BUCK_CTRL |
+			 MCUPM_ARMPLL_CTRL);
+
+	mcdi_mbox_write(APMCU_MCUPM_MBOX_AP_READY, 1);
+
+	return 0;
+}
+
+static int mcdi_init_2(void)
+{
+	return mtk_mcupm_is_ready() ? 0 : -1;
+}
+
+int mcdi_try_init(void)
+{
+	if (mcdi_init_status == MCDI_INIT_DONE) {
+		return 0;
+	}
+
+	if (mcdi_init_status == MCDI_NOT_INIT) {
+		mcdi_init_status = MCDI_INIT_1;
+	}
+
+	if (mcdi_init_status == MCDI_INIT_1 && mcdi_init_1() == 0) {
+		mcdi_init_status = MCDI_INIT_2;
+	}
+
+	if (mcdi_init_status == MCDI_INIT_2 && mcdi_init_2() == 0) {
+		mcdi_init_status = MCDI_INIT_DONE;
+	}
+
+	return (mcdi_init_status == MCDI_INIT_DONE) ? 0 : mcdi_init_status;
+}
diff --git a/plat/mediatek/mt8192/drivers/mcdi/mt_mcdi.h b/plat/mediatek/mt8192/drivers/mcdi/mt_mcdi.h
new file mode 100644
index 0000000..f3545aa
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/mcdi/mt_mcdi.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_MCDI_H
+#define MT_MCDI_H
+
+int mcdi_try_init(void);
+
+#endif /* MT_MCDI_H */
diff --git a/plat/mediatek/mt8192/drivers/pmic/pmic.c b/plat/mediatek/mt8192/drivers/pmic/pmic.c
new file mode 100644
index 0000000..cca4413
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/pmic/pmic.c
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <pmic.h>
+#include <pmic_wrap_init.h>
+
+void pmic_power_off(void)
+{
+	pwrap_write(PMIC_PWRHOLD, 0x0);
+}
diff --git a/plat/mediatek/mt8192/drivers/pmic/pmic.h b/plat/mediatek/mt8192/drivers/pmic/pmic.h
new file mode 100644
index 0000000..aac22af
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/pmic/pmic.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PMIC_H
+#define PMIC_H
+
+#define PMIC_PWRHOLD 0xa08
+
+/* external API */
+void pmic_power_off(void);
+
+#endif /* PMIC_H */
diff --git a/plat/mediatek/mt8192/drivers/pmic/pmic_wrap_init.h b/plat/mediatek/mt8192/drivers/pmic/pmic_wrap_init.h
new file mode 100644
index 0000000..ae892ed
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/pmic/pmic_wrap_init.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PMIC_WRAP_INIT_H
+#define PMIC_WRAP_INIT_H
+
+#include <stdint.h>
+
+#include "platform_def.h"
+
+/* external API */
+int32_t pwrap_read(uint32_t adr, uint32_t *rdata);
+int32_t pwrap_write(uint32_t adr, uint32_t wdata);
+
+static struct mt8192_pmic_wrap_regs *const mtk_pwrap = (void *)PMIC_WRAP_BASE;
+
+/* PMIC_WRAP registers */
+struct mt8192_pmic_wrap_regs {
+	uint32_t init_done;
+	uint32_t reserved[799];
+	uint32_t wacs2_cmd;
+	uint32_t wacs2_wdata;
+	uint32_t reserved1[3];
+	uint32_t wacs2_rdata;
+	uint32_t reserved2[3];
+	uint32_t wacs2_vldclr;
+	uint32_t wacs2_sta;
+};
+
+#define GET_WACS_FSM(x)	((x >> 1) & 0x7)
+
+/* macro for SWINF_FSM */
+#define SWINF_FSM_IDLE		(0x00)
+#define SWINF_FSM_REQ		(0x02)
+#define SWINF_FSM_WFDLE		(0x04)
+#define SWINF_FSM_WFVLDCLR	(0x06)
+#define SWINF_INIT_DONE		(0x01)
+
+/* timeout setting */
+#define PWRAP_READ_US	1000
+#define PWRAP_WAIT_IDLE_US	1000
+
+/* error information flag */
+enum pwrap_errno {
+	E_PWR_INVALID_ARG             = 1,
+	E_PWR_INVALID_RW              = 2,
+	E_PWR_INVALID_ADDR            = 3,
+	E_PWR_INVALID_WDAT            = 4,
+	E_PWR_INVALID_OP_MANUAL       = 5,
+	E_PWR_NOT_IDLE_STATE          = 6,
+	E_PWR_NOT_INIT_DONE           = 7,
+	E_PWR_NOT_INIT_DONE_READ      = 8,
+	E_PWR_WAIT_IDLE_TIMEOUT       = 9,
+	E_PWR_WAIT_IDLE_TIMEOUT_READ  = 10,
+	E_PWR_INIT_SIDLY_FAIL         = 11,
+	E_PWR_RESET_TIMEOUT           = 12,
+	E_PWR_TIMEOUT                 = 13,
+	E_PWR_INIT_RESET_SPI          = 20,
+	E_PWR_INIT_SIDLY              = 21,
+	E_PWR_INIT_REG_CLOCK          = 22,
+	E_PWR_INIT_ENABLE_PMIC        = 23,
+	E_PWR_INIT_DIO                = 24,
+	E_PWR_INIT_CIPHER             = 25,
+	E_PWR_INIT_WRITE_TEST         = 26,
+	E_PWR_INIT_ENABLE_CRC         = 27,
+	E_PWR_INIT_ENABLE_DEWRAP      = 28,
+	E_PWR_INIT_ENABLE_EVENT       = 29,
+	E_PWR_READ_TEST_FAIL          = 30,
+	E_PWR_WRITE_TEST_FAIL         = 31,
+	E_PWR_SWITCH_DIO              = 32
+};
+
+#endif /* PMIC_WRAP_INIT_H */
diff --git a/plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_common.h b/plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_common.h
new file mode 100644
index 0000000..92c71bc
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_common.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTK_PTP3_H
+#define MTK_PTP3_H
+
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+
+/************************************************
+ * BIT Operation and REG r/w
+ ************************************************/
+#define ptp3_read(addr)		mmio_read_32((uintptr_t)addr)
+#define ptp3_write(addr, val)	mmio_write_32((uintptr_t)addr, val)
+
+/************************************************
+ * CPU info
+ ************************************************/
+#define NR_PTP3_CFG1_CPU	U(8)
+#define PTP3_CFG1_CPU_START_ID	U(0)
+#define PTP3_CFG1_MASK		0x00100000
+
+#define NR_PTP3_CFG2_CPU	U(4)
+#define PTP3_CFG2_CPU_START_ID	U(4)
+
+#define NR_PTP3_CFG3_CPU	U(4)
+#define PTP3_CFG3_CPU_START_ID	U(4)
+
+/************************************************
+ * config enum
+ ************************************************/
+enum PTP3_CFG {
+	PTP3_CFG_ADDR,
+	PTP3_CFG_VALUE,
+	NR_PTP3_CFG,
+};
+
+/************************************
+ * prototype
+ ************************************/
+/* init trigger for ptp3 feature */
+extern void ptp3_init(unsigned int core);
+extern void ptp3_deinit(unsigned int core);
+
+#endif /* MTK_PTP3_H */
diff --git a/plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_main.c b/plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_main.c
new file mode 100644
index 0000000..f1d8493
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_main.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved. \
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "mtk_ptp3_common.h"
+
+/************************************************
+ * Central control: turn on sysPi protection
+ ************************************************/
+static unsigned int ptp3_cfg1[NR_PTP3_CFG1_CPU][NR_PTP3_CFG] = {
+	{0x0C530610, 0x110842},
+	{0x0C530E10, 0x110842},
+	{0x0C531610, 0x110842},
+	{0x0C531E10, 0x110842},
+	{0x0C532610, 0x110842},
+	{0x0C532E10, 0x110842},
+	{0x0C533610, 0x110842},
+	{0x0C533E10, 0x110842}
+};
+static unsigned int ptp3_cfg2[NR_PTP3_CFG2_CPU][NR_PTP3_CFG] = {
+	{0x0C53B830, 0x68000},
+	{0x0C53BA30, 0x68000},
+	{0x0C53BC30, 0x68000},
+	{0x0C53BE30, 0x68000}
+};
+static unsigned int ptp3_cfg3[NR_PTP3_CFG3_CPU][NR_PTP3_CFG] = {
+	{0x0C532480, 0x7C607C6},
+	{0x0C532C80, 0x7C607C6},
+	{0x0C533480, 0x7C607C6},
+	{0x0C533C80, 0x7C607C6}
+};
+
+/************************************************
+ * API
+ ************************************************/
+void ptp3_init(unsigned int core)
+{
+	unsigned int _core;
+
+	/* Apply ptp3_cfg1 for core 0 to 7 */
+	if (core < NR_PTP3_CFG1_CPU) {
+		/* update ptp3_cfg1 */
+		ptp3_write(
+			ptp3_cfg1[core][PTP3_CFG_ADDR],
+			ptp3_cfg1[core][PTP3_CFG_VALUE]);
+	}
+
+	/* Apply ptp3_cfg2 for core 4 to 7 */
+	if (core >= PTP3_CFG2_CPU_START_ID) {
+		_core = core - PTP3_CFG2_CPU_START_ID;
+
+		if (_core < NR_PTP3_CFG2_CPU) {
+			/* update ptp3_cfg2 */
+			ptp3_write(
+				ptp3_cfg2[_core][PTP3_CFG_ADDR],
+				ptp3_cfg2[_core][PTP3_CFG_VALUE]);
+		}
+	}
+
+	/* Apply ptp3_cfg3 for core 4 to 7 */
+	if (core >= PTP3_CFG3_CPU_START_ID) {
+		_core = core - PTP3_CFG3_CPU_START_ID;
+
+		if (_core < NR_PTP3_CFG3_CPU) {
+			/* update ptp3_cfg3 */
+			ptp3_write(
+				ptp3_cfg3[_core][PTP3_CFG_ADDR],
+				ptp3_cfg3[_core][PTP3_CFG_VALUE]);
+		}
+	}
+}
+
+void ptp3_deinit(unsigned int core)
+{
+	if (core < NR_PTP3_CFG1_CPU) {
+		/* update ptp3_cfg1 */
+		ptp3_write(
+			ptp3_cfg1[core][PTP3_CFG_ADDR],
+			ptp3_cfg1[core][PTP3_CFG_VALUE] &
+				 ~PTP3_CFG1_MASK);
+	}
+}
diff --git a/plat/mediatek/mt8192/drivers/rtc/rtc.c b/plat/mediatek/mt8192/drivers/rtc/rtc.c
new file mode 100644
index 0000000..124bc8f
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/rtc/rtc.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2020, 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/mt8192/drivers/rtc/rtc.h b/plat/mediatek/mt8192/drivers/rtc/rtc.h
new file mode 100644
index 0000000..419bfe4
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/rtc/rtc.h
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RTC_H
+#define RTC_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_H */
diff --git a/plat/mediatek/mt8192/drivers/spmc/mtspmc.c b/plat/mediatek/mt8192/drivers/spmc/mtspmc.c
new file mode 100644
index 0000000..7ccebd6
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/spmc/mtspmc.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <mcucfg.h>
+#include <mtspmc.h>
+#include <mtspmc_private.h>
+
+
+void mcucfg_disable_gic_wakeup(uint32_t cluster, uint32_t cpu)
+{
+	mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(cpu));
+}
+
+void mcucfg_enable_gic_wakeup(uint32_t cluster, uint32_t cpu)
+{
+	mmio_clrbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(cpu));
+}
+
+void mcucfg_set_bootaddr(uint32_t cluster, uint32_t cpu, uintptr_t bootaddr)
+{
+	assert(cluster == 0U);
+
+	mmio_write_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR), bootaddr);
+}
+
+uintptr_t mcucfg_get_bootaddr(uint32_t cluster, uint32_t cpu)
+{
+	assert(cluster == 0U);
+
+	return (uintptr_t)mmio_read_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR));
+}
+
+void mcucfg_init_archstate(uint32_t cluster, uint32_t cpu, bool arm64)
+{
+	uint32_t reg;
+
+	assert(cluster == 0U);
+
+	reg = per_cluster(cluster, MCUCFG_INITARCH);
+
+	if (arm64) {
+		mmio_setbits_32(reg, MCUCFG_INITARCH_CPU_BIT(cpu));
+	} else {
+		mmio_clrbits_32(reg, MCUCFG_INITARCH_CPU_BIT(cpu));
+	}
+}
+
+/**
+ * Return subsystem's power state.
+ *
+ * @mask: mask to SPM_CPU_PWR_STATUS to query the power state
+ *        of one subsystem.
+ * RETURNS:
+ * 0 (the subsys was powered off)
+ * 1 (the subsys was powered on)
+ */
+bool spm_get_powerstate(uint32_t mask)
+{
+	return (mmio_read_32(SPM_CPU_PWR_STATUS) & mask) != 0U;
+}
+
+bool spm_get_cluster_powerstate(uint32_t cluster)
+{
+	assert(cluster == 0U);
+
+	return spm_get_powerstate(MP0_CPUTOP);
+}
+
+bool spm_get_cpu_powerstate(uint32_t cluster, uint32_t cpu)
+{
+	uint32_t mask = BIT(cpu);
+
+	assert(cluster == 0U);
+
+	return spm_get_powerstate(mask);
+}
+
+int spmc_init(void)
+{
+	INFO("SPM: enable CPC mode\n");
+
+	mmio_write_32(SPM_POWERON_CONFIG_EN, PROJECT_CODE | BCLK_CG_EN);
+
+	mmio_setbits_32(per_cpu(0, 1, SPM_CPU_PWR), PWR_RST_B);
+	mmio_setbits_32(per_cpu(0, 2, SPM_CPU_PWR), PWR_RST_B);
+	mmio_setbits_32(per_cpu(0, 3, SPM_CPU_PWR), PWR_RST_B);
+	mmio_setbits_32(per_cpu(0, 4, SPM_CPU_PWR), PWR_RST_B);
+	mmio_setbits_32(per_cpu(0, 5, SPM_CPU_PWR), PWR_RST_B);
+	mmio_setbits_32(per_cpu(0, 6, SPM_CPU_PWR), PWR_RST_B);
+	mmio_setbits_32(per_cpu(0, 7, SPM_CPU_PWR), PWR_RST_B);
+
+	mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(1));
+	mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(2));
+	mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(3));
+	mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(4));
+	mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(5));
+	mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(6));
+	mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(7));
+
+	mmio_clrbits_32(SPM_MCUSYS_PWR_CON, RESETPWRON_CONFIG);
+	mmio_clrbits_32(SPM_MP0_CPUTOP_PWR_CON, RESETPWRON_CONFIG);
+	mmio_clrbits_32(per_cpu(0, 0, SPM_CPU_PWR), RESETPWRON_CONFIG);
+
+	mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, CPC_CTRL_ENABLE);
+
+	return 0;
+}
+
+/**
+ * Power on a core with specified cluster and core index
+ *
+ * @cluster: the cluster ID of the CPU which to be powered on
+ * @cpu: the CPU ID of the CPU which to be powered on
+ */
+void spm_poweron_cpu(uint32_t cluster, uint32_t cpu)
+{
+	/* set to 0 after BIG VPROC bulk on & before B-core power on seq. */
+	if (cpu >= 4U) {
+		mmio_write_32(DREQ20_BIG_VPROC_ISO, 0U);
+	}
+
+	mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, SSPM_ALL_PWR_CTRL_EN);
+	mmio_setbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWR_ON);
+
+	while (!spm_get_cpu_powerstate(cluster, cpu)) {
+	}
+
+	mmio_clrbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, SSPM_ALL_PWR_CTRL_EN);
+
+	/* Enable Big CPU Last PC */
+	if (cpu >= 4U) {
+		mmio_clrbits_32(LAST_PC_REG(cpu), BIT(3));
+	}
+}
+
+/**
+ * Power off a core with specified cluster and core index
+ *
+ * @cluster: the cluster ID of the CPU which to be powered off
+ * @cpu: the CPU ID of the CPU which to be powered off
+ */
+void spm_poweroff_cpu(uint32_t cluster, uint32_t cpu)
+{
+	/* Set mp0_spmc_pwr_on_cpuX = 0 */
+	mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWR_ON);
+}
+
+/**
+ * Power off a cluster with specified index
+ *
+ * @cluster: the cluster index which to be powered off
+ */
+void spm_poweroff_cluster(uint32_t cluster)
+{
+	/* No need to power on/off cluster on single cluster platform */
+	assert(false);
+}
+
+/**
+ * Power on a cluster with specified index
+ *
+ * @cluster: the cluster index which to be powered on
+ */
+void spm_poweron_cluster(uint32_t cluster)
+{
+	/* No need to power on/off cluster on single cluster platform */
+	assert(false);
+}
diff --git a/plat/mediatek/mt8192/drivers/spmc/mtspmc.h b/plat/mediatek/mt8192/drivers/spmc/mtspmc.h
new file mode 100644
index 0000000..7ed2e62
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/spmc/mtspmc.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTSPMC_H
+#define MTSPMC_H
+
+#include <stdint.h>
+
+int spmc_init(void);
+
+void spm_poweron_cpu(uint32_t cluster, uint32_t cpu);
+void spm_poweroff_cpu(uint32_t cluster, uint32_t cpu);
+
+void spm_poweroff_cluster(uint32_t cluster);
+void spm_poweron_cluster(uint32_t cluster);
+
+bool spm_get_cpu_powerstate(uint32_t cluster, uint32_t cpu);
+bool spm_get_cluster_powerstate(uint32_t cluster);
+bool spm_get_powerstate(uint32_t mask);
+
+void mcucfg_init_archstate(uint32_t cluster, uint32_t cpu, bool arm64);
+void mcucfg_set_bootaddr(uint32_t cluster, uint32_t cpu, uintptr_t bootaddr);
+uintptr_t mcucfg_get_bootaddr(uint32_t cluster, uint32_t cpu);
+
+void mcucfg_disable_gic_wakeup(uint32_t cluster, uint32_t cpu);
+void mcucfg_enable_gic_wakeup(uint32_t cluster, uint32_t cpu);
+
+#endif /* MTSPMC_H */
diff --git a/plat/mediatek/mt8192/drivers/spmc/mtspmc_private.h b/plat/mediatek/mt8192/drivers/spmc/mtspmc_private.h
new file mode 100644
index 0000000..ad78295
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/spmc/mtspmc_private.h
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTSPMC_PRIVATE_H
+#define MTSPMC_PRIVATE_H
+
+#include <lib/utils_def.h>
+#include <platform_def.h>
+
+unsigned long read_cpuectlr(void);
+void write_cpuectlr(unsigned long cpuectlr);
+
+unsigned long read_cpupwrctlr_el1(void);
+void write_cpupwrctlr_el1(unsigned long cpuectlr);
+
+/*
+ * per_cpu/cluster helper
+ */
+struct per_cpu_reg {
+	unsigned int cluster_addr;
+	unsigned int cpu_stride;
+};
+
+#define per_cpu(cluster, cpu, reg)	\
+	(reg[cluster].cluster_addr + (cpu << reg[cluster].cpu_stride))
+
+#define per_cluster(cluster, reg)	(reg[cluster].cluster_addr)
+
+#define SPM_REG(ofs)			(uint32_t)(SPM_BASE + (ofs))
+#define MCUCFG_REG(ofs)			(uint32_t)(MCUCFG_BASE + (ofs))
+#define INFRACFG_AO_REG(ofs)		(uint32_t)(INFRACFG_AO_BASE + (ofs))
+
+/* === SPMC related registers */
+#define SPM_POWERON_CONFIG_EN		SPM_REG(0x000)
+/* bit-fields of SPM_POWERON_CONFIG_EN */
+#define PROJECT_CODE			(U(0xb16) << 16)
+#define BCLK_CG_EN			BIT(0)
+
+#define SPM_PWR_STATUS			SPM_REG(0x16c)
+#define SPM_PWR_STATUS_2ND		SPM_REG(0x170)
+#define SPM_CPU_PWR_STATUS		SPM_REG(0x174)
+
+/* bit-fields of SPM_PWR_STATUS */
+#define MD				BIT(0)
+#define CONN				BIT(1)
+#define DDRPHY				BIT(2)
+#define DISP				BIT(3)
+#define MFG				BIT(4)
+#define ISP				BIT(5)
+#define INFRA				BIT(6)
+#define VDEC				BIT(7)
+#define MP0_CPUTOP			BIT(8)
+#define MP0_CPU0			BIT(9)
+#define MP0_CPU1			BIT(10)
+#define MP0_CPU2			BIT(11)
+#define MP0_CPU3			BIT(12)
+#define MCUSYS				BIT(14)
+#define MP0_CPU4			BIT(15)
+#define MP0_CPU5			BIT(16)
+#define MP0_CPU6			BIT(17)
+#define MP0_CPU7			BIT(18)
+#define VEN				BIT(21)
+
+/* === SPMC related registers */
+#define SPM_MCUSYS_PWR_CON		MCUCFG_REG(0xd200)
+#define SPM_MP0_CPUTOP_PWR_CON		MCUCFG_REG(0xd204)
+#define SPM_MP0_CPU0_PWR_CON		MCUCFG_REG(0xd208)
+#define SPM_MP0_CPU1_PWR_CON		MCUCFG_REG(0xd20c)
+#define SPM_MP0_CPU2_PWR_CON		MCUCFG_REG(0xd210)
+#define SPM_MP0_CPU3_PWR_CON		MCUCFG_REG(0xd214)
+#define SPM_MP0_CPU4_PWR_CON		MCUCFG_REG(0xd218)
+#define SPM_MP0_CPU5_PWR_CON		MCUCFG_REG(0xd21c)
+#define SPM_MP0_CPU6_PWR_CON		MCUCFG_REG(0xd220)
+#define SPM_MP0_CPU7_PWR_CON		MCUCFG_REG(0xd224)
+
+/* bit fields of SPM_*_PWR_CON */
+#define PWR_ON_ACK			BIT(31)
+#define VPROC_EXT_OFF			BIT(7)
+#define DORMANT_EN			BIT(6)
+#define RESETPWRON_CONFIG		BIT(5)
+#define PWR_CLK_DIS			BIT(4)
+#define PWR_ON				BIT(2)
+#define PWR_RST_B			BIT(0)
+
+/**** per_cpu registers for SPM_MP0_CPU?_PWR_CON */
+static const struct per_cpu_reg SPM_CPU_PWR[] = {
+	{ .cluster_addr = SPM_MP0_CPU0_PWR_CON, .cpu_stride = 2U }
+};
+
+/**** per_cluster registers for SPM_MP0_CPUTOP_PWR_CON */
+static const struct per_cpu_reg SPM_CLUSTER_PWR[] = {
+	{ .cluster_addr = SPM_MP0_CPUTOP_PWR_CON, .cpu_stride = 0U }
+};
+
+/* === MCUCFG related registers */
+/* aa64naa32 */
+#define MCUCFG_MP0_CLUSTER_CFG5		MCUCFG_REG(0xc8e4)
+/* reset vectors */
+#define MCUCFG_MP0_CLUSTER_CFG8		MCUCFG_REG(0xc900)
+#define MCUCFG_MP0_CLUSTER_CFG10	MCUCFG_REG(0xc908)
+#define MCUCFG_MP0_CLUSTER_CFG12	MCUCFG_REG(0xc910)
+#define MCUCFG_MP0_CLUSTER_CFG14	MCUCFG_REG(0xc918)
+#define MCUCFG_MP0_CLUSTER_CFG16	MCUCFG_REG(0xc920)
+#define MCUCFG_MP0_CLUSTER_CFG18	MCUCFG_REG(0xc928)
+#define MCUCFG_MP0_CLUSTER_CFG20	MCUCFG_REG(0xc930)
+#define MCUCFG_MP0_CLUSTER_CFG22	MCUCFG_REG(0xc938)
+
+/* MCUSYS DREQ BIG VPROC ISO control */
+#define DREQ20_BIG_VPROC_ISO		MCUCFG_REG(0xad8c)
+
+/**** per_cpu registers for MCUCFG_MP0_CLUSTER_CFG? */
+static const struct per_cpu_reg MCUCFG_BOOTADDR[] = {
+	{ .cluster_addr = MCUCFG_MP0_CLUSTER_CFG8, .cpu_stride = 3U }
+};
+
+/**** per_cpu registers for MCUCFG_MP0_CLUSTER_CFG5 */
+static const struct per_cpu_reg MCUCFG_INITARCH[] = {
+	{ .cluster_addr = MCUCFG_MP0_CLUSTER_CFG5, .cpu_stride = 0U }
+};
+
+#define MCUCFG_INITARCH_CPU_BIT(cpu)	BIT(16U + cpu)
+#define LAST_PC_REG(cpu)		(MCUCFG_REG(0x308) + (cpu * 0x800))
+
+/* === CPC control */
+#define MCUCFG_CPC_FLOW_CTRL_CFG	MCUCFG_REG(0xa814)
+#define MCUCFG_CPC_SPMC_PWR_STATUS	MCUCFG_REG(0xa840)
+
+/* bit fields of CPC_FLOW_CTRL_CFG */
+#define CPC_CTRL_ENABLE			BIT(16)
+#define SSPM_ALL_PWR_CTRL_EN		BIT(13) /* for cpu-hotplug */
+#define GIC_WAKEUP_IGNORE(cpu)		BIT(21 + cpu)
+
+/* bit fields of CPC_SPMC_PWR_STATUS */
+#define CORE_SPMC_PWR_ON_ACK		GENMASK(15, 0)
+
+/* === APB Module infracfg_ao */
+#define INFRA_TOPAXI_PROTECTEN		INFRACFG_AO_REG(0x0220)
+#define INFRA_TOPAXI_PROTECTEN_STA0	INFRACFG_AO_REG(0x0224)
+#define INFRA_TOPAXI_PROTECTEN_STA1	INFRACFG_AO_REG(0x0228)
+#define INFRA_TOPAXI_PROTECTEN_SET	INFRACFG_AO_REG(0x02a0)
+#define INFRA_TOPAXI_PROTECTEN_CLR	INFRACFG_AO_REG(0x02a4)
+#define INFRA_TOPAXI_PROTECTEN_1	INFRACFG_AO_REG(0x0250)
+#define INFRA_TOPAXI_PROTECTEN_STA0_1	INFRACFG_AO_REG(0x0254)
+#define INFRA_TOPAXI_PROTECTEN_STA1_1	INFRACFG_AO_REG(0x0258)
+#define INFRA_TOPAXI_PROTECTEN_1_SET	INFRACFG_AO_REG(0x02a8)
+#define INFRA_TOPAXI_PROTECTEN_1_CLR	INFRACFG_AO_REG(0x02ac)
+
+/* bit fields of INFRA_TOPAXI_PROTECTEN */
+#define MP0_SPMC_PROT_STEP1_0_MASK	BIT(12)
+#define MP0_SPMC_PROT_STEP1_1_MASK	(BIT(26) | BIT(12))
+
+/* === SPARK */
+#define VOLTAGE_04			U(0x40)
+#define VOLTAGE_05			U(0x60)
+
+#define PTP3_CPU0_SPMC_SW_CFG		MCUCFG_REG(0x200)
+#define CPU0_ILDO_CONTROL5		MCUCFG_REG(0x334)
+#define CPU0_ILDO_CONTROL8		MCUCFG_REG(0x340)
+
+/* bit fields of CPU0_ILDO_CONTROL5 */
+#define ILDO_RET_VOSEL			GENMASK(7, 0)
+
+/* bit fields of PTP3_CPU_SPMC_SW_CFG */
+#define SW_SPARK_EN			BIT(0)
+
+/* bit fields of CPU0_ILDO_CONTROL8 */
+#define ILDO_BYPASS_B			BIT(0)
+
+static const struct per_cpu_reg MCUCFG_SPARK[] = {
+	{ .cluster_addr = PTP3_CPU0_SPMC_SW_CFG, .cpu_stride = 11U }
+};
+
+static const struct per_cpu_reg ILDO_CONTROL5[] = {
+	{ .cluster_addr = CPU0_ILDO_CONTROL5, .cpu_stride = 11U }
+};
+
+static const struct per_cpu_reg ILDO_CONTROL8[] = {
+	{ .cluster_addr = CPU0_ILDO_CONTROL8, .cpu_stride = 11U }
+};
+
+#endif /* MTSPMC_PRIVATE_H */
diff --git a/plat/mediatek/mt8192/drivers/timer/mt_timer.c b/plat/mediatek/mt8192/drivers/timer/mt_timer.c
index 781f940..0860885 100644
--- a/plat/mediatek/mt8192/drivers/timer/mt_timer.c
+++ b/plat/mediatek/mt8192/drivers/timer/mt_timer.c
@@ -5,6 +5,7 @@
  */
 
 #include <arch_helpers.h>
+#include <lib/mmio.h>
 #include <mt_timer.h>
 #include <platform_def.h>
 
@@ -28,3 +29,10 @@
 		- 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/mt8192/drivers/timer/mt_timer.h b/plat/mediatek/mt8192/drivers/timer/mt_timer.h
index 7aca4a3..b353177 100644
--- a/plat/mediatek/mt8192/drivers/timer/mt_timer.h
+++ b/plat/mediatek/mt8192/drivers/timer/mt_timer.h
@@ -12,6 +12,8 @@
 #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)
@@ -23,8 +25,11 @@
 #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/mt8192/drivers/uart/uart.h b/plat/mediatek/mt8192/drivers/uart/uart.h
new file mode 100644
index 0000000..ac8b94d
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/uart/uart.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2020, 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/mt8192/include/mcucfg.h b/plat/mediatek/mt8192/include/mcucfg.h
new file mode 100644
index 0000000..046cf73
--- /dev/null
+++ b/plat/mediatek/mt8192/include/mcucfg.h
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MCUCFG_H
+#define MCUCFG_H
+
+#ifndef __ASSEMBLER__
+#include <stdint.h>
+#endif /* __ASSEMBLER__ */
+
+#include <platform_def.h>
+
+#define MCUCFG_REG(ofs)			(uint32_t)(MCUCFG_BASE + (ofs))
+
+#define MP2_MISC_CONFIG_BOOT_ADDR_L(cpu) (MCUCFG_REG(0x2290) + ((cpu) * 8))
+#define MP2_MISC_CONFIG_BOOT_ADDR_H(cpu) (MCUCFG_REG(0x2294) + ((cpu) * 8))
+
+#define MP2_CPUCFG			MCUCFG_REG(0x2208)
+
+#define MP2_CPU0_STANDBYWFE		BIT(4)
+#define MP2_CPU1_STANDBYWFE		BIT(5)
+
+#define MP0_CPUTOP_SPMC_CTL		MCUCFG_REG(0x788)
+#define MP1_CPUTOP_SPMC_CTL		MCUCFG_REG(0x78C)
+#define MP1_CPUTOP_SPMC_SRAM_CTL	MCUCFG_REG(0x790)
+
+#define sw_spark_en			BIT(0)
+#define sw_no_wait_for_q_channel	BIT(1)
+#define sw_fsm_override			BIT(2)
+#define sw_logic_pre1_pdb		BIT(3)
+#define sw_logic_pre2_pdb		BIT(4)
+#define sw_logic_pdb			BIT(5)
+#define sw_iso				BIT(6)
+#define sw_sram_sleepb			(U(0x3F) << 7)
+#define sw_sram_isointb			BIT(13)
+#define sw_clk_dis			BIT(14)
+#define sw_ckiso			BIT(15)
+#define sw_pd				(U(0x3F) << 16)
+#define sw_hot_plug_reset		BIT(22)
+#define sw_pwr_on_override_en		BIT(23)
+#define sw_pwr_on			BIT(24)
+#define sw_coq_dis			BIT(25)
+#define logic_pdbo_all_off_ack		BIT(26)
+#define logic_pdbo_all_on_ack		BIT(27)
+#define logic_pre2_pdbo_all_on_ack	BIT(28)
+#define logic_pre1_pdbo_all_on_ack	BIT(29)
+
+
+#define CPUSYSx_CPUx_SPMC_CTL(cluster, cpu) \
+	(MCUCFG_REG(0x1c30) + cluster * 0x2000 + cpu * 4)
+
+#define CPUSYS0_CPU0_SPMC_CTL		MCUCFG_REG(0x1c30)
+#define CPUSYS0_CPU1_SPMC_CTL		MCUCFG_REG(0x1c34)
+#define CPUSYS0_CPU2_SPMC_CTL		MCUCFG_REG(0x1c38)
+#define CPUSYS0_CPU3_SPMC_CTL		MCUCFG_REG(0x1c3C)
+
+#define CPUSYS1_CPU0_SPMC_CTL		MCUCFG_REG(0x3c30)
+#define CPUSYS1_CPU1_SPMC_CTL		MCUCFG_REG(0x3c34)
+#define CPUSYS1_CPU2_SPMC_CTL		MCUCFG_REG(0x3c38)
+#define CPUSYS1_CPU3_SPMC_CTL		MCUCFG_REG(0x3c3C)
+
+#define cpu_sw_spark_en			BIT(0)
+#define cpu_sw_no_wait_for_q_channel	BIT(1)
+#define cpu_sw_fsm_override		BIT(2)
+#define cpu_sw_logic_pre1_pdb		BIT(3)
+#define cpu_sw_logic_pre2_pdb		BIT(4)
+#define cpu_sw_logic_pdb		BIT(5)
+#define cpu_sw_iso			BIT(6)
+#define cpu_sw_sram_sleepb		BIT(7)
+#define cpu_sw_sram_isointb		BIT(8)
+#define cpu_sw_clk_dis			BIT(9)
+#define cpu_sw_ckiso			BIT(10)
+#define cpu_sw_pd			(U(0x1F) << 11)
+#define cpu_sw_hot_plug_reset		BIT(16)
+#define cpu_sw_powr_on_override_en	BIT(17)
+#define cpu_sw_pwr_on			BIT(18)
+#define cpu_spark2ldo_allswoff		BIT(19)
+#define cpu_pdbo_all_on_ack		BIT(20)
+#define cpu_pre2_pdbo_allon_ack		BIT(21)
+#define cpu_pre1_pdbo_allon_ack		BIT(22)
+
+/* CPC related registers */
+#define CPC_MCUSYS_CPC_OFF_THRES	MCUCFG_REG(0xa714)
+#define CPC_MCUSYS_PWR_CTRL		MCUCFG_REG(0xa804)
+#define CPC_MCUSYS_CPC_FLOW_CTRL_CFG	MCUCFG_REG(0xa814)
+#define CPC_MCUSYS_LAST_CORE_REQ	MCUCFG_REG(0xa818)
+#define CPC_MCUSYS_MP_LAST_CORE_RESP	MCUCFG_REG(0xa81c)
+#define CPC_MCUSYS_LAST_CORE_RESP	MCUCFG_REG(0xa824)
+#define CPC_MCUSYS_PWR_ON_MASK		MCUCFG_REG(0xa828)
+#define CPC_MCUSYS_CPU_ON_SW_HINT_SET	MCUCFG_REG(0xa8a8)
+#define CPC_MCUSYS_CPU_ON_SW_HINT_CLR	MCUCFG_REG(0xa8ac)
+#define CPC_MCUSYS_CPC_DBG_SETTING	MCUCFG_REG(0xab00)
+#define CPC_MCUSYS_CPC_KERNEL_TIME_L_BASE	MCUCFG_REG(0xab04)
+#define CPC_MCUSYS_CPC_KERNEL_TIME_H_BASE	MCUCFG_REG(0xab08)
+#define CPC_MCUSYS_CPC_SYSTEM_TIME_L_BASE	MCUCFG_REG(0xab0c)
+#define CPC_MCUSYS_CPC_SYSTEM_TIME_H_BASE	MCUCFG_REG(0xab10)
+#define CPC_MCUSYS_TRACE_SEL		MCUCFG_REG(0xab14)
+#define CPC_MCUSYS_TRACE_DATA		MCUCFG_REG(0xab20)
+#define CPC_MCUSYS_CLUSTER_COUNTER	MCUCFG_REG(0xab70)
+#define CPC_MCUSYS_CLUSTER_COUNTER_CLR	MCUCFG_REG(0xab74)
+
+#define SPARK2LDO			MCUCFG_REG(0x2700)
+/* APB Module mcucfg */
+#define MP0_CA7_CACHE_CONFIG		MCUCFG_REG(0x000)
+#define MP0_AXI_CONFIG			MCUCFG_REG(0x02C)
+#define MP0_MISC_CONFIG0		MCUCFG_REG(0x030)
+#define MP0_MISC_CONFIG1		MCUCFG_REG(0x034)
+#define MP0_MISC_CONFIG2		MCUCFG_REG(0x038)
+#define MP0_MISC_CONFIG_BOOT_ADDR(cpu)	(MP0_MISC_CONFIG2 + ((cpu) * 8))
+#define MP0_MISC_CONFIG3		MCUCFG_REG(0x03C)
+#define MP0_MISC_CONFIG9		MCUCFG_REG(0x054)
+#define MP0_CA7_MISC_CONFIG		MCUCFG_REG(0x064)
+
+#define MP0_RW_RSVD0			MCUCFG_REG(0x06C)
+
+
+#define MP1_CA7_CACHE_CONFIG		MCUCFG_REG(0x200)
+#define MP1_AXI_CONFIG			MCUCFG_REG(0x22C)
+#define MP1_MISC_CONFIG0		MCUCFG_REG(0x230)
+#define MP1_MISC_CONFIG1		MCUCFG_REG(0x234)
+#define MP1_MISC_CONFIG2		MCUCFG_REG(0x238)
+#define MP1_MISC_CONFIG_BOOT_ADDR(cpu)	(MP1_MISC_CONFIG2 + ((cpu) * 8))
+#define MP1_MISC_CONFIG3		MCUCFG_REG(0x23C)
+#define MP1_MISC_CONFIG9		MCUCFG_REG(0x254)
+#define MP1_CA7_MISC_CONFIG		MCUCFG_REG(0x264)
+
+#define CCI_ADB400_DCM_CONFIG		MCUCFG_REG(0x740)
+#define SYNC_DCM_CONFIG			MCUCFG_REG(0x744)
+
+#define MP0_CLUSTER_CFG0		MCUCFG_REG(0xC8D0)
+
+#define MP0_SPMC			MCUCFG_REG(0x788)
+#define MP1_SPMC			MCUCFG_REG(0x78C)
+#define MP2_AXI_CONFIG			MCUCFG_REG(0x220C)
+#define MP2_AXI_CONFIG_ACINACTM		BIT(0)
+#define MP2_AXI_CONFIG_AINACTS		BIT(4)
+
+#define MPx_AXI_CONFIG_ACINACTM		BIT(4)
+#define MPx_AXI_CONFIG_AINACTS		BIT(5)
+
+#define MPx_CA7_MISC_CONFIG_standbywfil2	BIT(28)
+
+#define MP0_CPU0_STANDBYWFE		BIT(20)
+#define MP0_CPU1_STANDBYWFE		BIT(21)
+#define MP0_CPU2_STANDBYWFE		BIT(22)
+#define MP0_CPU3_STANDBYWFE		BIT(23)
+
+#define MP1_CPU0_STANDBYWFE		BIT(20)
+#define MP1_CPU1_STANDBYWFE		BIT(21)
+#define MP1_CPU2_STANDBYWFE		BIT(22)
+#define MP1_CPU3_STANDBYWFE		BIT(23)
+
+#define CPUSYS0_SPARKVRETCNTRL		MCUCFG_REG(0x1c00)
+#define CPUSYS0_SPARKEN			MCUCFG_REG(0x1c04)
+#define CPUSYS0_AMUXSEL			MCUCFG_REG(0x1c08)
+#define CPUSYS1_SPARKVRETCNTRL		MCUCFG_REG(0x3c00)
+#define CPUSYS1_SPARKEN			MCUCFG_REG(0x3c04)
+#define CPUSYS1_AMUXSEL			MCUCFG_REG(0x3c08)
+
+#define MP2_PWR_RST_CTL			MCUCFG_REG(0x2008)
+#define MP2_PTP3_CPUTOP_SPMC0		MCUCFG_REG(0x22A0)
+#define MP2_PTP3_CPUTOP_SPMC1		MCUCFG_REG(0x22A4)
+
+#define MP2_COQ				MCUCFG_REG(0x22BC)
+#define MP2_COQ_SW_DIS			BIT(0)
+
+#define MP2_CA15M_MON_SEL		MCUCFG_REG(0x2400)
+#define MP2_CA15M_MON_L			MCUCFG_REG(0x2404)
+
+#define CPUSYS2_CPU0_SPMC_CTL		MCUCFG_REG(0x2430)
+#define CPUSYS2_CPU1_SPMC_CTL		MCUCFG_REG(0x2438)
+#define CPUSYS2_CPU0_SPMC_STA		MCUCFG_REG(0x2434)
+#define CPUSYS2_CPU1_SPMC_STA		MCUCFG_REG(0x243C)
+
+#define MP0_CA7L_DBG_PWR_CTRL		MCUCFG_REG(0x068)
+#define MP1_CA7L_DBG_PWR_CTRL		MCUCFG_REG(0x268)
+#define BIG_DBG_PWR_CTRL		MCUCFG_REG(0x75C)
+
+#define MP2_SW_RST_B			BIT(0)
+#define MP2_TOPAON_APB_MASK		BIT(1)
+
+#define B_SW_HOT_PLUG_RESET		BIT(30)
+
+#define B_SW_PD_OFFSET			18U
+#define B_SW_PD				(U(0x3f) << B_SW_PD_OFFSET)
+
+#define B_SW_SRAM_SLEEPB_OFFSET		12U
+#define B_SW_SRAM_SLEEPB		(U(0x3f) << B_SW_SRAM_SLEEPB_OFFSET)
+
+#define B_SW_SRAM_ISOINTB		BIT(9)
+#define B_SW_ISO			BIT(8)
+#define B_SW_LOGIC_PDB			BIT(7)
+#define B_SW_LOGIC_PRE2_PDB		BIT(6)
+#define B_SW_LOGIC_PRE1_PDB		BIT(5)
+#define B_SW_FSM_OVERRIDE		BIT(4)
+#define B_SW_PWR_ON			BIT(3)
+#define B_SW_PWR_ON_OVERRIDE_EN		BIT(2)
+
+#define B_FSM_STATE_OUT_OFFSET		(6U)
+#define B_FSM_STATE_OUT_MASK		(U(0x1f) << B_FSM_STATE_OUT_OFFSET)
+#define B_SW_LOGIC_PDBO_ALL_OFF_ACK	BIT(5)
+#define B_SW_LOGIC_PDBO_ALL_ON_ACK	BIT(4)
+#define B_SW_LOGIC_PRE2_PDBO_ALL_ON_ACK	BIT(3)
+#define B_SW_LOGIC_PRE1_PDBO_ALL_ON_ACK	BIT(2)
+
+#define B_FSM_OFF			(0U << B_FSM_STATE_OUT_OFFSET)
+#define B_FSM_ON			(1U << B_FSM_STATE_OUT_OFFSET)
+#define B_FSM_RET			(2U << B_FSM_STATE_OUT_OFFSET)
+
+#ifndef __ASSEMBLER__
+/* cpu boot mode */
+enum {
+	MP0_CPUCFG_64BIT_SHIFT = 12U,
+	MP1_CPUCFG_64BIT_SHIFT = 28U,
+	MP0_CPUCFG_64BIT = U(0xf) << MP0_CPUCFG_64BIT_SHIFT,
+	MP1_CPUCFG_64BIT = U(0xf) << MP1_CPUCFG_64BIT_SHIFT
+};
+
+enum {
+	MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT = 0U,
+	MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT = 4U,
+	MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT = 8U,
+	MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT = 12U,
+	MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT = 16U,
+
+	MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK =
+		U(0xf) << MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT,
+	MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK =
+		U(0xf) << MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT,
+	MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK =
+		U(0xf) << MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT,
+	MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK =
+		U(0xf) << MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT,
+	MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK =
+		U(0xf) << MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT
+};
+
+enum {
+	MP1_AINACTS_SHIFT = 4U,
+	MP1_AINACTS = 1U << MP1_AINACTS_SHIFT
+};
+
+enum {
+	MP1_SW_CG_GEN_SHIFT = 12U,
+	MP1_SW_CG_GEN = 1U << MP1_SW_CG_GEN_SHIFT
+};
+
+enum {
+	MP1_L2RSTDISABLE_SHIFT = 14U,
+	MP1_L2RSTDISABLE = 1U << MP1_L2RSTDISABLE_SHIFT
+};
+#endif /* __ASSEMBLER__ */
+
+#endif  /* MCUCFG_H */
diff --git a/plat/mediatek/mt8192/include/plat_mt_cirq.h b/plat/mediatek/mt8192/include/plat_mt_cirq.h
index 5818601..bb8b457 100644
--- a/plat/mediatek/mt8192/include/plat_mt_cirq.h
+++ b/plat/mediatek/mt8192/include/plat_mt_cirq.h
@@ -7,24 +7,53 @@
 #ifndef PLAT_MT_CIRQ_H
 #define PLAT_MT_CIRQ_H
 
-#define SYS_CIRQ_BASE        U(0x10204000)
-#define CIRQ_IRQ_NUM         U(439)
-#define CIRQ_SPI_START       U(96)
+#include <stdint.h>
+
+enum {
+	IRQ_MASK_HEADER = 0xF1F1F1F1,
+	IRQ_MASK_FOOTER = 0xF2F2F2F2
+};
+
+struct mtk_irq_mask {
+	uint32_t header;	/* for error checking */
+	uint32_t mask0;
+	uint32_t mask1;
+	uint32_t mask2;
+	uint32_t mask3;
+	uint32_t mask4;
+	uint32_t mask5;
+	uint32_t mask6;
+	uint32_t mask7;
+	uint32_t mask8;
+	uint32_t mask9;
+	uint32_t mask10;
+	uint32_t mask11;
+	uint32_t mask12;
+	uint32_t footer;	/* for error checking */
+};
+
 /*
  * Define hardware register
  */
-#define  CIRQ_STA_BASE         U(0x000)
-#define  CIRQ_ACK_BASE         U(0x080)
-#define  CIRQ_MASK_BASE        U(0x100)
-#define  CIRQ_MASK_SET_BASE    U(0x180)
-#define  CIRQ_MASK_CLR_BASE    U(0x200)
-#define  CIRQ_SENS_BASE        U(0x280)
-#define  CIRQ_SENS_SET_BASE    U(0x300)
-#define  CIRQ_SENS_CLR_BASE    U(0x380)
-#define  CIRQ_POL_BASE         U(0x400)
-#define  CIRQ_POL_SET_BASE     U(0x480)
-#define  CIRQ_POL_CLR_BASE     U(0x500)
-#define  CIRQ_CON              U(0x600)
+
+#define  SYS_CIRQ_BASE         U(0x10204000)
+#define  CIRQ_REG_NUM          U(14)
+#define  CIRQ_IRQ_NUM          U(439)
+#define  CIRQ_SPI_START        U(64)
+#define  MD_WDT_IRQ_BIT_ID     U(110)
+
+#define  CIRQ_STA_BASE         (SYS_CIRQ_BASE + U(0x000))
+#define  CIRQ_ACK_BASE         (SYS_CIRQ_BASE + U(0x080))
+#define  CIRQ_MASK_BASE        (SYS_CIRQ_BASE + U(0x100))
+#define  CIRQ_MASK_SET_BASE    (SYS_CIRQ_BASE + U(0x180))
+#define  CIRQ_MASK_CLR_BASE    (SYS_CIRQ_BASE + U(0x200))
+#define  CIRQ_SENS_BASE        (SYS_CIRQ_BASE + U(0x280))
+#define  CIRQ_SENS_SET_BASE    (SYS_CIRQ_BASE + U(0x300))
+#define  CIRQ_SENS_CLR_BASE    (SYS_CIRQ_BASE + U(0x380))
+#define  CIRQ_POL_BASE         (SYS_CIRQ_BASE + U(0x400))
+#define  CIRQ_POL_SET_BASE     (SYS_CIRQ_BASE + U(0x480))
+#define  CIRQ_POL_CLR_BASE     (SYS_CIRQ_BASE + U(0x500))
+#define  CIRQ_CON              (SYS_CIRQ_BASE + U(0x600))
 
 /*
  * Register placement
@@ -32,8 +61,8 @@
 #define  CIRQ_CON_EN_BITS           U(0)
 #define  CIRQ_CON_EDGE_ONLY_BITS    U(1)
 #define  CIRQ_CON_FLUSH_BITS        U(2)
-#define  CIRQ_CON_EVENT_BITS        U(31)
 #define  CIRQ_CON_SW_RST_BITS       U(20)
+#define  CIRQ_CON_EVENT_BITS        U(31)
 #define  CIRQ_CON_BITS_MASK         U(0x7)
 
 /*
@@ -41,42 +70,59 @@
  */
 #define  CIRQ_CON_EN            U(0x1)
 #define  CIRQ_CON_EDGE_ONLY     U(0x1)
-#define  CIRQ_SW_RESET          U(0x1)
 #define  CIRQ_CON_FLUSH         U(0x1)
+#define  CIRQ_SW_RESET          U(0x1)
 
 /*
  * Define constant
  */
 #define  CIRQ_CTRL_REG_NUM      ((CIRQ_IRQ_NUM + 31U) / 32U)
-#define  MT_CIRQ_POL_NEG               U(0)
-#define  MT_CIRQ_POL_POS               U(1)
-#define  MT_CIRQ_EDGE_SENSITIVE        U(0)
-#define  MT_CIRQ_LEVEL_SENSITIVE       U(1)
 
-/*
- * Define macro
- */
-#define  IRQ_TO_CIRQ_NUM(irq)       ((irq) - (CIRQ_SPI_START))
-#define  CIRQ_TO_IRQ_NUM(cirq)      ((cirq) + (CIRQ_SPI_START))
+#define  MT_CIRQ_POL_NEG        U(0)
+#define  MT_CIRQ_POL_POS        U(1)
 
-/*
- * Define cirq events
- */
-struct cirq_events {
-	uint32_t spi_start;
-	uint32_t num_of_events;
-	uint32_t *wakeup_events;
-};
+#define IRQ_TO_CIRQ_NUM(irq)  ((irq) - (32U + CIRQ_SPI_START))
+#define CIRQ_TO_IRQ_NUM(cirq) ((cirq) + (32U + CIRQ_SPI_START))
+
+/* GIC sensitive */
+#define SENS_EDGE	U(0x2)
+#define SENS_LEVEL	U(0x1)
+
 
 /*
  * Define function prototypes.
  */
-void mt_cirq_enable(void);
-void mt_cirq_disable(void);
+int mt_cirq_test(void);
+void mt_cirq_dump_reg(void);
+int mt_irq_mask_restore(struct mtk_irq_mask *mask);
+int mt_irq_mask_all(struct mtk_irq_mask *mask);
 void mt_cirq_clone_gic(void);
+void mt_cirq_enable(void);
 void mt_cirq_flush(void);
-void mt_cirq_sw_reset(void);
+void mt_cirq_disable(void);
+void mt_irq_unmask_for_sleep_ex(uint32_t irq);
 void set_wakeup_sources(uint32_t *list, uint32_t num_of_events);
-void mt_cirq_dump_reg(void);
+void mt_cirq_sw_reset(void);
+
+struct cirq_reg {
+	uint32_t reg_num;
+	uint32_t used;
+	uint32_t mask;
+	uint32_t pol;
+	uint32_t sen;
+	uint32_t pending;
+	uint32_t the_link;
+};
+
+struct cirq_events {
+	uint32_t num_reg;
+	uint32_t spi_start;
+	uint32_t num_of_events;
+	uint32_t *wakeup_events;
+	struct cirq_reg table[CIRQ_REG_NUM];
+	uint32_t dist_base;
+	uint32_t cirq_base;
+	uint32_t used_reg_head;
+};
 
-#endif  /* PLAT_MT_CIRQ_H */
+#endif /* PLAT_MT_CIRQ_H */
diff --git a/plat/mediatek/mt8192/include/plat_mtk_lpm.h b/plat/mediatek/mt8192/include/plat_mtk_lpm.h
new file mode 100644
index 0000000..8ba8b93
--- /dev/null
+++ b/plat/mediatek/mt8192/include/plat_mtk_lpm.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_MTK_LPM_H
+#define PLAT_MTK_LPM_H
+
+#include <lib/psci/psci.h>
+#include <lib/utils_def.h>
+
+#define MT_IRQ_REMAIN_MAX	U(8)
+#define MT_IRQ_REMAIN_CAT_LOG	BIT(31)
+
+struct mt_irqremain {
+	unsigned int count;
+	unsigned int irqs[MT_IRQ_REMAIN_MAX];
+	unsigned int wakeupsrc_cat[MT_IRQ_REMAIN_MAX];
+	unsigned int wakeupsrc[MT_IRQ_REMAIN_MAX];
+};
+
+#define PLAT_RC_STATUS_READY		BIT(0)
+#define PLAT_RC_STATUS_FEATURE_EN	BIT(1)
+#define PLAT_RC_STATUS_UART_NONSLEEP	BIT(31)
+
+struct mt_lpm_tz {
+	int (*pwr_prompt)(unsigned int cpu, const psci_power_state_t *state);
+	int (*pwr_reflect)(unsigned int cpu, const psci_power_state_t *state);
+
+	int (*pwr_cpu_on)(unsigned int cpu, const psci_power_state_t *state);
+	int (*pwr_cpu_dwn)(unsigned int cpu, const psci_power_state_t *state);
+
+	int (*pwr_cluster_on)(unsigned int cpu,
+					const psci_power_state_t *state);
+	int (*pwr_cluster_dwn)(unsigned int cpu,
+					const psci_power_state_t *state);
+
+	int (*pwr_mcusys_on)(unsigned int cpu, const psci_power_state_t *state);
+	int (*pwr_mcusys_on_finished)(unsigned int cpu,
+					const psci_power_state_t *state);
+	int (*pwr_mcusys_dwn)(unsigned int cpu,
+					const psci_power_state_t *state);
+};
+
+const struct mt_lpm_tz *mt_plat_cpu_pm_init(void);
+
+#endif /* PLAT_MTK_LPM_H */
diff --git a/plat/mediatek/mt8192/include/plat_pm.h b/plat/mediatek/mt8192/include/plat_pm.h
new file mode 100644
index 0000000..a2881ce
--- /dev/null
+++ b/plat/mediatek/mt8192/include/plat_pm.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_PM_H
+#define PLAT_PM_H
+
+#include <lib/utils_def.h>
+
+#define MT_PLAT_PWR_STATE_CPU			U(1)
+#define MT_PLAT_PWR_STATE_CLUSTER		U(2)
+#define MT_PLAT_PWR_STATE_MCUSYS		U(3)
+#define MT_PLAT_PWR_STATE_SUSPEND2IDLE		U(8)
+#define MT_PLAT_PWR_STATE_SYSTEM_SUSPEND	U(9)
+
+#define MTK_LOCAL_STATE_RUN			U(0)
+#define MTK_LOCAL_STATE_RET			U(1)
+#define MTK_LOCAL_STATE_OFF			U(2)
+
+#define MTK_AFFLVL_CPU				U(0)
+#define MTK_AFFLVL_CLUSTER			U(1)
+#define MTK_AFFLVL_MCUSYS			U(2)
+#define MTK_AFFLVL_SYSTEM			U(3)
+
+#define IS_CLUSTER_OFF_STATE(s)		\
+		is_local_state_off(s->pwr_domain_state[MTK_AFFLVL_CLUSTER])
+#define IS_MCUSYS_OFF_STATE(s)		\
+		is_local_state_off(s->pwr_domain_state[MTK_AFFLVL_MCUSYS])
+#define IS_SYSTEM_SUSPEND_STATE(s)	\
+		is_local_state_off(s->pwr_domain_state[MTK_AFFLVL_SYSTEM])
+
+#define IS_PLAT_SUSPEND_ID(stateid)\
+		((stateid == MT_PLAT_PWR_STATE_SUSPEND2IDLE)	\
+		|| (stateid == MT_PLAT_PWR_STATE_SYSTEM_SUSPEND))
+
+#endif /* PLAT_PM_H */
diff --git a/plat/mediatek/mt8192/include/plat_sip_calls.h b/plat/mediatek/mt8192/include/plat_sip_calls.h
new file mode 100644
index 0000000..0e42322
--- /dev/null
+++ b/plat/mediatek/mt8192/include/plat_sip_calls.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_SIP_CALLS_H
+#define PLAT_SIP_CALLS_H
+
+/*******************************************************************************
+ * Plat SiP function constants
+ ******************************************************************************/
+#define MTK_PLAT_SIP_NUM_CALLS    0
+
+#endif /* PLAT_SIP_CALLS_H */
diff --git a/plat/mediatek/mt8192/include/platform_def.h b/plat/mediatek/mt8192/include/platform_def.h
index 768e7cf..3e44414 100644
--- a/plat/mediatek/mt8192/include/platform_def.h
+++ b/plat/mediatek/mt8192/include/platform_def.h
@@ -23,8 +23,15 @@
 #define MTK_DEV_RNG1_SIZE    0x10000000
 #define MTK_DEV_RNG2_BASE    0x0c000000
 #define MTK_DEV_RNG2_SIZE    0x600000
+#define MTK_MCDI_SRAM_BASE      0x11B000
+#define MTK_MCDI_SRAM_MAP_SIZE  0x1000
 
+#define INFRACFG_AO_BASE (IO_PHYS + 0x00001000)
 #define GPIO_BASE        (IO_PHYS + 0x00005000)
+#define SPM_BASE         (IO_PHYS + 0x00006000)
+#define PMIC_WRAP_BASE   (IO_PHYS + 0x00026000)
+#define EMI_BASE         (IO_PHYS + 0x00219000)
+#define EMI_MPU_BASE     (IO_PHYS + 0x00226000)
 #define IOCFG_RM_BASE    (IO_PHYS + 0x01C20000)
 #define IOCFG_BM_BASE    (IO_PHYS + 0x01D10000)
 #define IOCFG_BL_BASE    (IO_PHYS + 0x01D30000)
@@ -67,11 +74,12 @@
  ******************************************************************************/
 #define PLATFORM_STACK_SIZE    0x800
 
-#define PLAT_MAX_PWR_LVL        U(2)
+#define PLAT_MAX_PWR_LVL        U(3)
 #define PLAT_MAX_RET_STATE      U(1)
-#define PLAT_MAX_OFF_STATE      U(2)
+#define PLAT_MAX_OFF_STATE      U(9)
 
 #define PLATFORM_SYSTEM_COUNT           U(1)
+#define PLATFORM_MCUSYS_COUNT           U(1)
 #define PLATFORM_CLUSTER_COUNT          U(1)
 #define PLATFORM_CLUSTER0_CORE_COUNT    U(8)
 #define PLATFORM_CORE_COUNT             (PLATFORM_CLUSTER0_CORE_COUNT)
diff --git a/plat/mediatek/mt8192/plat_mt_cirq.c b/plat/mediatek/mt8192/plat_mt_cirq.c
index 7fc0607..9002b7e 100644
--- a/plat/mediatek/mt8192/plat_mt_cirq.c
+++ b/plat/mediatek/mt8192/plat_mt_cirq.c
@@ -7,137 +7,255 @@
 #include <arch_helpers.h>
 #include <common/debug.h>
 #include <drivers/arm/gic_common.h>
-#include <drivers/console.h>
 #include <lib/mmio.h>
 
 #include <mt_gic_v3.h>
-#include <mtk_plat_common.h>
 #include <plat_mt_cirq.h>
 #include <platform_def.h>
 
 static struct cirq_events cirq_all_events = {
-	.spi_start = CIRQ_SPI_START
+	.spi_start = CIRQ_SPI_START,
 };
-
-static inline void  mt_cirq_write32(uint32_t val, uint32_t addr)
-{
-	mmio_write_32(addr + SYS_CIRQ_BASE, val);
-}
-
-static inline uint32_t mt_cirq_read32(uint32_t addr)
-{
-	return mmio_read_32(addr + SYS_CIRQ_BASE);
-}
-
+static uint32_t already_cloned;
 /*
- * cirq_clone_flush_check_store:
- * set 1 if we need to enable clone/flush value's check
+ * mt_irq_mask_restore: restore all interrupts
+ * @mask: pointer to struct mtk_irq_mask for storing the original mask value.
+ * Return 0 for success; return negative values for failure.
+ * (This is ONLY used for the idle current measurement by the factory mode.)
  */
-static int32_t cirq_clone_flush_check_val;
+int mt_irq_mask_restore(struct mtk_irq_mask *mask)
+{
+	if (mask == NULL) {
+		return -1;
+	}
+	if (mask->header != IRQ_MASK_HEADER) {
+		return -1;
+	}
+	if (mask->footer != IRQ_MASK_FOOTER) {
+		return -1;
+	}
 
-/*
- * cirq_pattern_clone_flush_check_show:  set 1 if we need to do pattern test.
- */
-static int32_t cirq_pattern_clone_flush_check_val;
+	 mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x4),
+		mask->mask1);
+	 mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x8),
+		mask->mask2);
+	 mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0xc),
+		mask->mask3);
+	 mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x10),
+		mask->mask4);
+	 mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x14),
+		mask->mask5);
+	 mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x18),
+		mask->mask6);
+	 mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x1c),
+		mask->mask7);
+	 mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x20),
+		mask->mask8);
+	 mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x24),
+		mask->mask9);
+	 mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x28),
+		mask->mask10);
+	 mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x2c),
+		mask->mask11);
+	 mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x30),
+		mask->mask12);
+	/* make sure dist changes happen */
+	dsb();
 
-/*
- * cirq_pattern_clone_flush_check_show:  set 1 if we need to do pattern test.
- */
-static int32_t cirq_pattern_list;
+	return 0;
+}
 
 /*
- * mt_cirq_ack_all: Ack all the interrupt on SYS_CIRQ
+ * mt_irq_mask_all: disable all interrupts
+ * @mask: pointer to struct mtk_irq_mask for storing the original mask value.
+ * Return 0 for success; return negative values for failure.
+ * (This is ONLY used for the idle current measurement by the factory mode.)
  */
-void mt_cirq_ack_all(void)
+int mt_irq_mask_all(struct mtk_irq_mask *mask)
 {
-	unsigned int i;
+	if (mask != NULL) {
+		/* for SPI */
+		mask->mask1 = mmio_read_32((BASE_GICD_BASE +
+			GICD_ISENABLER + 0x4));
+		mask->mask2 = mmio_read_32((BASE_GICD_BASE +
+			GICD_ISENABLER + 0x8));
+		mask->mask3 = mmio_read_32((BASE_GICD_BASE +
+			GICD_ISENABLER + 0xc));
+		mask->mask4 = mmio_read_32((BASE_GICD_BASE +
+			GICD_ISENABLER + 0x10));
+		mask->mask5 = mmio_read_32((BASE_GICD_BASE +
+			GICD_ISENABLER + 0x14));
+		mask->mask6 = mmio_read_32((BASE_GICD_BASE +
+			GICD_ISENABLER + 0x18));
+		mask->mask7 = mmio_read_32((BASE_GICD_BASE +
+			GICD_ISENABLER + 0x1c));
+		mask->mask8 = mmio_read_32((BASE_GICD_BASE +
+			GICD_ISENABLER + 0x20));
+		mask->mask9 = mmio_read_32((BASE_GICD_BASE +
+			GICD_ISENABLER + 0x24));
+		mask->mask10 = mmio_read_32((BASE_GICD_BASE +
+			GICD_ISENABLER + 0x28));
+		mask->mask11 = mmio_read_32((BASE_GICD_BASE +
+			GICD_ISENABLER + 0x2c));
+		mask->mask12 = mmio_read_32((BASE_GICD_BASE +
+			GICD_ISENABLER + 0x30));
 
-	for (i = 0U; i < CIRQ_CTRL_REG_NUM; i++) {
-		mt_cirq_write32(0xFFFFFFFF, CIRQ_ACK_BASE + (i * 4U));
+		/* for SPI */
+		mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x4),
+			0xFFFFFFFF);
+		mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x8),
+			0xFFFFFFFF);
+		mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0xC),
+			0xFFFFFFFF);
+		mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x10),
+			0xFFFFFFFF);
+		mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x14),
+			0xFFFFFFFF);
+		mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x18),
+			0xFFFFFFFF);
+		mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x1C),
+			0xFFFFFFFF);
+		mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x20),
+			0xFFFFFFFF);
+		mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x24),
+			0xFFFFFFFF);
+		mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x28),
+			0xFFFFFFFF);
+		mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x2c),
+			0xFFFFFFFF);
+		mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x30),
+			0xFFFFFFFF);
+		/* make sure distributor changes happen */
+		dsb();
+
+		mask->header = IRQ_MASK_HEADER;
+		mask->footer = IRQ_MASK_FOOTER;
+
+		return 0;
+	} else {
+		return -1;
 	}
-	/* make sure all cirq setting take effect before doing other things */
-	dmbsy();
 }
 
-/*
- * mt_cirq_enable: Enable SYS_CIRQ
- */
-void mt_cirq_enable(void)
+static uint32_t mt_irq_get_pol(uint32_t irq)
 {
-	uint32_t st;
+#ifdef CIRQ_WITH_POLARITY
+	uint32_t reg;
+	uint32_t base = INT_POL_CTL0;
 
-	mt_cirq_ack_all();
+	if (irq < 32U) {
+		return 0;
+	}
 
-	st = mt_cirq_read32(CIRQ_CON);
-	st |= (CIRQ_CON_EN << CIRQ_CON_EN_BITS) |
-			(CIRQ_CON_EDGE_ONLY << CIRQ_CON_EDGE_ONLY_BITS);
+	reg = ((irq - 32U) / 32U);
 
-	mt_cirq_write32((st & CIRQ_CON_BITS_MASK), CIRQ_CON);
+	return  mmio_read_32(base + reg * 4U);
+#else
+	return 0;
+#endif
 }
 
-/*
- * mt_cirq_disable: Disable SYS_CIRQ
- */
-void mt_cirq_disable(void)
+unsigned int mt_irq_get_sens(unsigned int irq)
 {
-	uint32_t st;
+	unsigned int config;
 
-	st = mt_cirq_read32(CIRQ_CON);
-	st &= ~(CIRQ_CON_EN << CIRQ_CON_EN_BITS);
+	/*
+	 * 2'b10 edge
+	 * 2'b01 level
+	 */
+	config = mmio_read_32(MT_GIC_BASE + GICD_ICFGR + (irq / 16U) * 4U);
+	config = (config >> (irq % 16U) * 2U) & 0x3;
 
-	mt_cirq_write32((st & CIRQ_CON_BITS_MASK), CIRQ_CON);
+	return config;
 }
 
-/*
- * mt_cirq_get_mask: Get the specified SYS_CIRQ mask
- * @cirq_num: the SYS_CIRQ number to get
- * @return:
- *    1: this cirq is masked
- *    0: this cirq is umasked
- *    2: cirq num is out of range
- */
-__attribute__((weak)) unsigned int mt_cirq_get_mask(uint32_t cirq_num)
+static void collect_all_wakeup_events(void)
 {
-	uint32_t st;
-	unsigned int val;
+	unsigned int i;
+	uint32_t gic_irq;
+	uint32_t cirq;
+	uint32_t cirq_reg;
+	uint32_t cirq_offset;
+	uint32_t mask;
+	uint32_t pol_mask;
+	uint32_t irq_offset;
+	uint32_t irq_mask;
 
-	if (cirq_num >= CIRQ_IRQ_NUM) {
-		ERROR("[CIRQ] %s: invalid cirq %u\n", __func__, cirq_num);
-		return 2;
+	if ((cirq_all_events.wakeup_events == NULL) ||
+			cirq_all_events.num_of_events == 0U) {
+		return;
 	}
 
-	st = mt_cirq_read32((cirq_num / 32U) * 4U + CIRQ_MASK_BASE);
-	val = (st >> (cirq_num % 32U)) & 1U;
-	return val;
-}
-
-/*
- * mt_cirq_mask_all: Mask all interrupts on SYS_CIRQ.
- */
-void mt_cirq_mask_all(void)
-{
-	unsigned int i;
+	for (i = 0U; i < cirq_all_events.num_of_events; i++) {
+		if (cirq_all_events.wakeup_events[i] > 0U) {
+			gic_irq = cirq_all_events.wakeup_events[i];
+			cirq = gic_irq - cirq_all_events.spi_start - 32U;
+			cirq_reg = cirq / 32U;
+			cirq_offset = cirq % 32U;
+			mask = 0x1 << cirq_offset;
+			irq_offset = gic_irq % 32U;
+			irq_mask = 0x1 << irq_offset;
+			/*
+			 * CIRQ default masks all
+			 */
+			cirq_all_events.table[cirq_reg].mask |= mask;
+			/*
+			 * CIRQ default pol is low
+			 */
+			pol_mask = mt_irq_get_pol(
+					cirq_all_events.wakeup_events[i])
+					& irq_mask;
+			/*
+			 * 0 means rising
+			 */
+			if (pol_mask == 0U) {
+				cirq_all_events.table[cirq_reg].pol |= mask;
+			}
+			/*
+			 * CIRQ could monitor edge/level trigger
+			 * cirq register (0: edge, 1: level)
+			 */
+			if (mt_irq_get_sens(cirq_all_events.wakeup_events[i])
+				== SENS_EDGE) {
+				cirq_all_events.table[cirq_reg].sen |= mask;
+			}
 
-	for (i = 0U; i < CIRQ_CTRL_REG_NUM; i++) {
-		mt_cirq_write32(0xFFFFFFFF, CIRQ_MASK_SET_BASE + (i * 4U));
+			cirq_all_events.table[cirq_reg].used = 1U;
+			cirq_all_events.table[cirq_reg].reg_num = cirq_reg;
+		}
 	}
-	/* make sure all cirq setting take effect before doing other things */
-	dmbsy();
 }
 
 /*
- * mt_cirq_unmask_all: Unmask all interrupts on SYS_CIRQ.
+ * mt_cirq_set_pol: Set the polarity for the specified SYS_CIRQ number.
+ * @cirq_num: the SYS_CIRQ number to set
+ * @pol: polarity to set
+ * @return:
+ *    0: set pol success
+ *   -1: cirq num is out of range
  */
-void mt_cirq_unmask_all(void)
+#ifdef CIRQ_WITH_POLARITY
+static int mt_cirq_set_pol(uint32_t cirq_num, uint32_t pol)
 {
-	unsigned int i;
+	uint32_t base;
+	uint32_t bit = 1U << (cirq_num % 32U);
 
-	for (i = 0U; i < CIRQ_CTRL_REG_NUM; i++) {
-		mt_cirq_write32(0xFFFFFFFF, CIRQ_MASK_CLR_BASE + (i * 4U));
+	if (cirq_num >= CIRQ_IRQ_NUM) {
+		return -1;
+	}
+
+	if (pol == MT_CIRQ_POL_NEG) {
+		base = (cirq_num / 32U) * 4U + CIRQ_POL_CLR_BASE;
+	} else if (pol == MT_CIRQ_POL_POS) {
+		base = (cirq_num / 32U) * 4U + CIRQ_POL_SET_BASE;
+	} else {
+		return -1;
 	}
-	/* make sure all cirq setting take effect before doing other things */
-	dmbsy();
+
+	mmio_write_32(base, bit);
+	return 0;
 }
+#endif
 
 /*
  * mt_cirq_mask: Mask the specified SYS_CIRQ.
@@ -151,11 +269,11 @@
 	uint32_t bit = 1U << (cirq_num % 32U);
 
 	if (cirq_num >= CIRQ_IRQ_NUM) {
-		ERROR("[CIRQ] %s: invalid cirq %u\n", __func__, cirq_num);
 		return -1;
 	}
 
-	mt_cirq_write32(bit, (cirq_num / 32U) * 4U + CIRQ_MASK_SET_BASE);
+	mmio_write_32((cirq_num / 32U) * 4U + CIRQ_MASK_SET_BASE, bit);
+
 	return 0;
 }
 
@@ -171,324 +289,264 @@
 	uint32_t bit = 1U << (cirq_num % 32U);
 
 	if (cirq_num >= CIRQ_IRQ_NUM) {
-		ERROR("[CIRQ] %s: invalid cirq %u\n", __func__, cirq_num);
 		return -1;
 	}
 
-	mt_cirq_write32(bit, (cirq_num / 32U) * 4U + CIRQ_MASK_CLR_BASE);
+	mmio_write_32((cirq_num / 32U) * 4U + CIRQ_MASK_CLR_BASE, bit);
+
 	return 0;
 }
 
-/*
- * mt_cirq_set_sens: Set the sensitivity for the specified SYS_CIRQ number.
- * @cirq_num: the SYS_CIRQ number to set
- * @sens: sensitivity to set
- * @return:
- *    0: set sens success
- *   -1: cirq num is out of range
- */
-static int mt_cirq_set_sens(uint32_t cirq_num, uint32_t sens)
+uint32_t mt_irq_get_en(uint32_t irq)
 {
-	uint32_t base;
-	uint32_t bit = 1U << (cirq_num % 32U);
+	uint32_t addr, st, val;
 
-	if (cirq_num >= CIRQ_IRQ_NUM) {
-		ERROR("[CIRQ] %s: invalid cirq %u\n", __func__, cirq_num);
-		return -1;
-	}
+	addr = BASE_GICD_BASE + GICD_ISENABLER + (irq / 32U) * 4U;
+	st = mmio_read_32(addr);
 
-	if (sens == MT_CIRQ_EDGE_SENSITIVE) {
-		base = (cirq_num / 32U) * 4U + CIRQ_SENS_CLR_BASE;
-	} else if (sens == MT_CIRQ_LEVEL_SENSITIVE) {
-		base = (cirq_num / 32U) * 4U + CIRQ_SENS_SET_BASE;
-	} else {
-		ERROR("[CIRQ] set_sens invalid sen value %u\n", sens);
-		return -1;
-	}
+	val = (st >> (irq % 32U)) & 1U;
 
-	mt_cirq_write32(bit, base);
-	return 0;
+	return val;
 }
 
-/*
- * mt_cirq_get_sens: Get the specified SYS_CIRQ sensitivity
- * @cirq_num: the SYS_CIRQ number to get
- * @return:
- *    1: this cirq is MT_LEVEL_SENSITIVE
- *    0: this cirq is MT_EDGE_SENSITIVE
- *    2: cirq num is out of range
- */
-__attribute__((weak)) unsigned int mt_cirq_get_sens(uint32_t cirq_num)
+static void __cirq_fast_clone(void)
 {
-	uint32_t st;
-	unsigned int val;
+	struct cirq_reg *reg;
+	unsigned int i;
 
-	if (cirq_num >= CIRQ_IRQ_NUM) {
-		ERROR("[CIRQ] %s: invalid cirq %u\n", __func__, cirq_num);
-		return 2;
-	}
+	for (i = 0U; i < CIRQ_REG_NUM ; ++i) {
+		uint32_t cirq_bit;
 
-	st = mt_cirq_read32((cirq_num / 32U) * 4U + CIRQ_SENS_BASE);
-	val = (st >> (cirq_num % 32U)) & 1U;
-	return val;
-}
+		reg = &cirq_all_events.table[i];
 
-/*
- * mt_cirq_set_pol: Set the polarity for the specified SYS_CIRQ number.
- * @cirq_num: the SYS_CIRQ number to set
- * @pol: polarity to set
- * @return:
- *    0: set pol success
- *   -1: cirq num is out of range
- */
-static int mt_cirq_set_pol(uint32_t cirq_num, uint32_t pol)
-{
-	uint32_t base;
-	uint32_t bit = 1U << (cirq_num % 32U);
+		if (reg->used == 0U) {
+			continue;
+		}
 
-	if (cirq_num >= CIRQ_IRQ_NUM) {
-		ERROR("[CIRQ] %s: invalid cirq %u\n", __func__, cirq_num);
-		return -1;
-	}
+		mmio_write_32(CIRQ_SENS_CLR_BASE + (reg->reg_num * 4U),
+				    reg->sen);
 
-	if (pol == MT_CIRQ_POL_NEG) {
-		base = (cirq_num / 32U) * 4U + CIRQ_POL_CLR_BASE;
-	} else if (pol == MT_CIRQ_POL_POS) {
-		base = (cirq_num / 32U) * 4U + CIRQ_POL_SET_BASE;
-	} else {
-		ERROR("[CIRQ] set_pol invalid polarity value %u\n", pol);
-		return -1;
-	}
+		for (cirq_bit = 0U; cirq_bit < 32U; ++cirq_bit) {
+			uint32_t val, cirq_id;
+			uint32_t gic_id;
+#ifdef CIRQ_WITH_POLARITY
+			uint32_t gic_bit, pol;
+#endif
+			uint32_t en;
 
-	mt_cirq_write32(bit, base);
-	return 0;
-}
+			val = ((1U << cirq_bit) & reg->mask);
 
-/*
- * mt_cirq_get_pol: Get the specified SYS_CIRQ polarity
- * @cirq_num: the SYS_CIRQ number to get
- * @return:
- *    1: this cirq is MT_CIRQ_POL_POS
- *    0: this cirq is MT_CIRQ_POL_NEG
- *    2: cirq num is out of range
- */
-__attribute__((weak)) unsigned int mt_cirq_get_pol(uint32_t cirq_num)
-{
-	uint32_t st;
-	unsigned int val;
+			if (val == 0U) {
+				continue;
+			}
 
-	if (cirq_num >= CIRQ_IRQ_NUM) {
-		ERROR("[CIRQ] %s: invalid cirq %u\n", __func__, cirq_num);
-		return 2;
+			cirq_id = (reg->reg_num << 5U) + cirq_bit;
+			gic_id = CIRQ_TO_IRQ_NUM(cirq_id);
+#ifdef CIRQ_WITH_POLARITY
+			gic_bit = (0x1U << ((gic_id - 32U) % 32U));
+			pol = mt_irq_get_pol(gic_id) & gic_bit;
+			if (pol != 0U) {
+				mt_cirq_set_pol(cirq_id, MT_CIRQ_POL_NEG);
+			} else {
+				mt_cirq_set_pol(cirq_id, MT_CIRQ_POL_POS);
+			}
+#endif
+			en = mt_irq_get_en(gic_id);
+			if (en == 1U) {
+				mt_cirq_unmask(cirq_id);
+			} else {
+				mt_cirq_mask(cirq_id);
+			}
+		}
 	}
+}
 
-	st = mt_cirq_read32((cirq_num / 32U) * 4U + CIRQ_POL_BASE);
-	val = (st >> (cirq_num % 32U)) & 1U;
-	return val;
+static void cirq_fast_clone(void)
+{
+	if (already_cloned == 0U) {
+		collect_all_wakeup_events();
+		already_cloned = 1U;
+	}
+	__cirq_fast_clone();
 }
 
+void set_wakeup_sources(uint32_t *list, uint32_t num_of_events)
+{
+	cirq_all_events.num_of_events = num_of_events;
+	cirq_all_events.wakeup_events = list;
+}
 /*
- * mt_cirq_get_pending: Get the specified SYS_CIRQ pending
- * @cirq_num: the SYS_CIRQ number to get
- * @return:
- *    1: this cirq is pending
- *    0: this cirq is not pending
- *    2: cirq num is out of range
+ * mt_cirq_clone_gic: Copy the setting from GIC to SYS_CIRQ
  */
-static unsigned int mt_cirq_get_pending(uint32_t cirq_num)
+void mt_cirq_clone_gic(void)
 {
-	uint32_t st;
-	unsigned int val;
+	cirq_fast_clone();
+}
 
-	if (cirq_num >= CIRQ_IRQ_NUM) {
-		ERROR("[CIRQ] %s: invalid cirq %u\n", __func__, cirq_num);
-		return 2;
+uint32_t mt_irq_get_pending_vec(uint32_t start_irq)
+{
+	uint32_t base = 0U;
+	uint32_t pending_vec = 0U;
+	uint32_t reg = start_irq / 32U;
+	uint32_t LSB_num, MSB_num;
+	uint32_t LSB_vec, MSB_vec;
+
+	base = BASE_GICD_BASE;
+
+	/* if start_irq is not aligned 32, do some assembling */
+	MSB_num = start_irq % 32U;
+	if (MSB_num != 0U) {
+		LSB_num = 32U - MSB_num;
+		LSB_vec = mmio_read_32(base + GICD_ISPENDR +
+			reg * 4U) >> MSB_num;
+		MSB_vec = mmio_read_32(base + GICD_ISPENDR +
+			(reg + 1U) * 4U) << LSB_num;
+		pending_vec = MSB_vec | LSB_vec;
+	} else {
+		pending_vec = mmio_read_32(base + GICD_ISPENDR + reg * 4);
 	}
 
-	st = mt_cirq_read32((cirq_num / 32U) * 4U + CIRQ_STA_BASE);
-	val = (st >> (cirq_num % 32U)) & 1U;
-	return val;
+	return pending_vec;
 }
 
+static int mt_cirq_get_mask_vec(unsigned int i)
+{
+	return mmio_read_32((i * 4U) + CIRQ_MASK_BASE);
+}
+
 /*
- * mt_cirq_clone_pol: Copy the polarity setting from GIC to SYS_CIRQ
+ * mt_cirq_ack_all: Ack all the interrupt on SYS_CIRQ
  */
-void mt_cirq_clone_pol(void)
+void mt_cirq_ack_all(void)
 {
-	uint32_t cirq_num;
+	uint32_t ack_vec, pend_vec, mask_vec;
+	unsigned int i;
 
-	for (cirq_num = 0U; cirq_num < CIRQ_IRQ_NUM; cirq_num++) {
-		mt_cirq_set_pol(cirq_num, MT_CIRQ_POL_POS);
+	for (i = 0; i < CIRQ_CTRL_REG_NUM; i++) {
+		/*
+		 * if a irq is pending & not masked, don't ack it
+		 * , since cirq start irq might not be 32 aligned with gic,
+		 * need an exotic API to get proper vector of pending irq
+		 */
+		pend_vec = mt_irq_get_pending_vec(CIRQ_SPI_START
+			+ (i + 1U) * 32U);
+		mask_vec = mt_cirq_get_mask_vec(i);
+		/* those should be acked are: "not (pending & not masked)",
+		 */
+		ack_vec = (~pend_vec) | mask_vec;
+		mmio_write_32(CIRQ_ACK_BASE + (i * 4U), ack_vec);
 	}
-}
 
+	/*
+	 * make sure all cirq setting take effect
+	 * before doing other things
+	 */
+	dsb();
+}
 /*
- * mt_cirq_clone_sens: Copy the sensitivity setting from GIC to SYS_CIRQ
+ * mt_cirq_enable: Enable SYS_CIRQ
  */
-void mt_cirq_clone_sens(void)
+void mt_cirq_enable(void)
 {
-	uint32_t cirq_num, irq_num;
-	uint32_t st, val;
-
-	for (cirq_num = 0U; cirq_num < CIRQ_IRQ_NUM; cirq_num++) {
-		irq_num = CIRQ_TO_IRQ_NUM(cirq_num);
+	uint32_t st;
 
-		if ((cirq_num == 0U) || (irq_num % 16U == 0U)) {
-			st = mmio_read_32(BASE_GICD_BASE + GICD_ICFGR +
-				(irq_num / 16U * 4U));
-		}
+	/* level only */
+	mt_cirq_ack_all();
 
-		val = (st >> ((irq_num % 16U) * 2U)) & 0x2U;
+	st = mmio_read_32(CIRQ_CON);
+	/*
+	 * CIRQ could monitor edge/level trigger
+	 */
+	st |= (CIRQ_CON_EN << CIRQ_CON_EN_BITS);
 
-		if (val) {
-			mt_cirq_set_sens(cirq_num, MT_CIRQ_EDGE_SENSITIVE);
-		} else {
-			mt_cirq_set_sens(cirq_num, MT_CIRQ_LEVEL_SENSITIVE);
-		}
-	}
+	mmio_write_32(CIRQ_CON, (st & CIRQ_CON_BITS_MASK));
 }
 
 /*
- * mt_cirq_clone_mask: Copy the mask setting from GIC to SYS_CIRQ
+ * mt_cirq_disable: Disable SYS_CIRQ
  */
-void mt_cirq_clone_mask(void)
+void mt_cirq_disable(void)
 {
-	uint32_t cirq_num, irq_num;
-	uint32_t st, val;
+	uint32_t st;
 
-	for (cirq_num = 0U; cirq_num < CIRQ_IRQ_NUM; cirq_num++) {
-		irq_num = CIRQ_TO_IRQ_NUM(cirq_num);
+	st = mmio_read_32(CIRQ_CON);
+	st &= ~(CIRQ_CON_EN << CIRQ_CON_EN_BITS);
+	mmio_write_32(CIRQ_CON, (st & CIRQ_CON_BITS_MASK));
+}
 
-		if ((cirq_num == 0U) || (irq_num % 32U == 0U)) {
-			st = mmio_read_32(BASE_GICD_BASE +
-				GICD_ISENABLER + (irq_num / 32U * 4U));
-		}
+void mt_irq_unmask_for_sleep_ex(uint32_t irq)
+{
+	uint32_t mask;
 
-		val = (st >> (irq_num % 32)) & 1U;
+	mask = 1U << (irq % 32U);
 
-		if (val) {
-			mt_cirq_unmask(cirq_num);
-		} else {
-			mt_cirq_mask(cirq_num);
-		}
-	}
+	mmio_write_32(BASE_GICD_BASE + GICD_ISENABLER +
+		((irq / 32U) * 4U), mask);
 }
 
-/*
- * mt_cirq_clone_gic: Copy the setting from GIC to SYS_CIRQ
- */
-void mt_cirq_clone_gic(void)
+void mt_cirq_mask_all(void)
 {
-	mt_cirq_clone_sens();
-	mt_cirq_clone_mask();
+	unsigned int i;
+
+	for (i = 0U; i < CIRQ_CTRL_REG_NUM; i++) {
+		mmio_write_32(CIRQ_MASK_SET_BASE + (i * 4U), 0xFFFFFFFF);
+	}
+	dsb();
 }
 
-/*
- * mt_cirq_disable: Flush interrupt from SYS_CIRQ to GIC
- */
-void mt_cirq_flush(void)
+static void cirq_fast_sw_flush(void)
 {
+	struct cirq_reg *reg;
 	unsigned int i;
-	unsigned char cirq_p_val = 0U;
-	unsigned char irq_p_val = 0U;
-	uint32_t irq_p = 0U;
-	unsigned char pass = 1U;
-	uint32_t first_cirq_found = 0U;
-	uint32_t first_flushed_cirq;
-	uint32_t first_irq_flushedto;
-	uint32_t last_fluashed_cirq;
-	uint32_t last_irq_flushedto;
 
-	if (cirq_pattern_clone_flush_check_val == 1U) {
-		if (cirq_pattern_list < CIRQ_IRQ_NUM) {
-			mt_cirq_unmask(cirq_pattern_list);
-			mt_cirq_set_sens(cirq_pattern_list,
-				MT_CIRQ_EDGE_SENSITIVE);
-			mt_cirq_set_pol(cirq_pattern_list, MT_CIRQ_POL_NEG);
-			mt_cirq_set_pol(cirq_pattern_list, MT_CIRQ_POL_POS);
-			mt_cirq_set_pol(cirq_pattern_list, MT_CIRQ_POL_NEG);
-		} else {
-			ERROR("[CIRQ] no pattern to test,");
-			ERROR("input pattern first\n");
-		}
-		ERROR("[CIRQ] cirq_pattern %u, cirq_p %u,",
-				cirq_pattern_list,
-				mt_cirq_get_pending(cirq_pattern_list));
-		ERROR("cirq_s %u, cirq_con 0x%x\n",
-				mt_cirq_get_sens(cirq_pattern_list),
-				mt_cirq_read32(CIRQ_CON));
-	}
+	for (i = 0U; i < CIRQ_REG_NUM ; ++i) {
+		uint32_t cirq_bit;
 
-	mt_cirq_unmask_all();
+		reg = &cirq_all_events.table[i];
 
-	for (i = 0U; i < CIRQ_IRQ_NUM; i++) {
-		cirq_p_val = mt_cirq_get_pending(i);
-		if (cirq_p_val) {
-			mt_irq_set_pending(CIRQ_TO_IRQ_NUM(i));
+		if (reg->used == 0U) {
+			continue;
 		}
 
+		reg->pending = mmio_read_32(CIRQ_STA_BASE +
+			(reg->reg_num << 2U));
+		reg->pending &= reg->mask;
+
-		if (cirq_clone_flush_check_val == 1U) {
-			if (cirq_p_val == 0U) {
+		for (cirq_bit = 0U; cirq_bit < 32U; ++cirq_bit) {
+			uint32_t val, cirq_id;
+
+			val = (1U << cirq_bit) & reg->pending;
+			if (val == 0U) {
 				continue;
-		}
-			irq_p = CIRQ_TO_IRQ_NUM(i);
-			irq_p_val = mt_irq_get_pending(irq_p);
-			if (cirq_p_val != irq_p_val) {
-				ERROR("[CIRQ] CIRQ Flush Failed ");
-				ERROR("%u(cirq %d)!= %u(gic %d)\n",
-					cirq_p_val, i, irq_p_val,
-					CIRQ_TO_IRQ_NUM(i));
-				pass = 0;
-			} else {
-				ERROR("[CIRQ] CIRQ Flush Pass ");
-				ERROR("%u(cirq %d) = %u(gic %d)\n",
-					cirq_p_val, i, irq_p_val,
-					CIRQ_TO_IRQ_NUM(i));
 			}
-			if (!first_cirq_found) {
-				first_flushed_cirq = i;
-				first_irq_flushedto = irq_p;
-				first_cirq_found = 1U;
+
+			cirq_id = (reg->reg_num << 5U) + cirq_bit;
+			mt_irq_set_pending(CIRQ_TO_IRQ_NUM(cirq_id));
+			if (CIRQ_TO_IRQ_NUM(cirq_id) == MD_WDT_IRQ_BIT_ID) {
+				INFO("Set MD_WDT_IRQ pending in %s\n",
+					__func__);
 			}
-			last_fluashed_cirq = i;
-			last_irq_flushedto = irq_p;
 		}
 	}
+}
 
-	if (cirq_clone_flush_check_val == 1U) {
-		if (first_cirq_found) {
-			ERROR("[CIRQ] The first flush : CIRQ%u to IRQ%u\n",
-				first_flushed_cirq, first_irq_flushedto);
-			ERROR("[CIRQ] The last flush : CIRQ%u to IRQ%u\n",
-				last_fluashed_cirq, last_irq_flushedto);
-		} else {
-			ERROR("[CIRQ] There are no pending ");
-			ERROR("interrupt in CIRQ\n");
-			ERROR("[CIRQ] so no flush operation happened\n");
-		}
-		ERROR("[CIRQ] The Flush Max Range : CIRQ");
-		ERROR("%d to IRQ%d ~ CIRQ%d to IRQ%d\n", 0U,
-			CIRQ_TO_IRQ_NUM(0U), CIRQ_IRQ_NUM - 1U,
-			CIRQ_TO_IRQ_NUM(CIRQ_IRQ_NUM - 1U));
-		ERROR("[CIRQ] Flush Check %s, Confirm:SPI_START_OFFSET:%d\n",
-			pass == 1 ? "Pass" : "Failed", CIRQ_SPI_START);
-	}
+/*
+ * mt_cirq_disable: Flush interrupt from SYS_CIRQ to GIC
+ */
+void mt_cirq_flush(void)
+{
+	cirq_fast_sw_flush();
 	mt_cirq_mask_all();
 	mt_cirq_ack_all();
 }
 
 void mt_cirq_sw_reset(void)
 {
+#ifdef CIRQ_NEED_SW_RESET
 	uint32_t st;
 
-	st = mt_cirq_read32(CIRQ_CON);
+	st = mmio_read_32(CIRQ_CON);
 	st |= (CIRQ_SW_RESET << CIRQ_CON_SW_RST_BITS);
-
-	mt_cirq_write32(st, CIRQ_CON);
-}
-
-void set_wakeup_sources(uint32_t *list, uint32_t num_of_events)
-{
-	cirq_all_events.num_of_events = num_of_events;
-	cirq_all_events.wakeup_events = list;
+	mmio_write_32(CIRQ_CON, st);
+#endif
 }
diff --git a/plat/mediatek/mt8192/plat_pm.c b/plat/mediatek/mt8192/plat_pm.c
index becf5d3..6a74c02 100644
--- a/plat/mediatek/mt8192/plat_pm.c
+++ b/plat/mediatek/mt8192/plat_pm.c
@@ -5,17 +5,351 @@
  */
 
 /* common headers */
+#include <assert.h>
+
 #include <arch_helpers.h>
 #include <common/debug.h>
 #include <drivers/gpio.h>
 #include <lib/psci/psci.h>
 
-/* mediatek platform specific headers */
+/* platform specific headers */
+#include <mt_gic_v3.h>
+#include <mtk_ptp3_common.h>
+#include <mtspmc.h>
+#include <plat/common/platform.h>
+#include <plat_mtk_lpm.h>
 #include <plat_params.h>
+#include <plat_pm.h>
+#include <pmic.h>
+#include <rtc.h>
+
+/*
+ * Cluster state request:
+ * [0] : The CPU requires cluster power down
+ * [1] : The CPU requires cluster power on
+ */
+#define coordinate_cluster(onoff)	write_clusterpwrdn_el1(onoff)
+#define coordinate_cluster_pwron()	coordinate_cluster(1)
+#define coordinate_cluster_pwroff()	coordinate_cluster(0)
+
+/* platform secure entry point */
+static uintptr_t secure_entrypoint;
+/* per-CPU power state */
+static unsigned int plat_power_state[PLATFORM_CORE_COUNT];
+
+/* platform CPU power domain - ops */
+static const struct mt_lpm_tz *plat_mt_pm;
+
+#define plat_mt_pm_invoke(_name, _cpu, _state) ({ \
+	int ret = -1; \
+	if (plat_mt_pm != NULL && plat_mt_pm->_name != NULL) { \
+		ret = plat_mt_pm->_name(_cpu, _state); \
+	} \
+	ret; })
+
+#define plat_mt_pm_invoke_no_check(_name, _cpu, _state) ({ \
+	if (plat_mt_pm != NULL && plat_mt_pm->_name != NULL) { \
+		(void) plat_mt_pm->_name(_cpu, _state); \
+	} \
+	})
+
+/*
+ * Common MTK_platform operations to power on/off a
+ * CPU in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request.
+ */
+
+static void plat_cpu_pwrdwn_common(unsigned int cpu,
+		const psci_power_state_t *state, unsigned int req_pstate)
+{
+	assert(cpu == plat_my_core_pos());
+
+	plat_mt_pm_invoke_no_check(pwr_cpu_dwn, cpu, state);
+
+	if ((psci_get_pstate_pwrlvl(req_pstate) >= MTK_AFFLVL_CLUSTER) ||
+			(req_pstate == 0U)) { /* hotplug off */
+		coordinate_cluster_pwroff();
+	}
+
+	/* Prevent interrupts from spuriously waking up this CPU */
+	mt_gic_rdistif_save();
+	gicv3_cpuif_disable(cpu);
+	gicv3_rdistif_off(cpu);
+	/* PTP3 config */
+	ptp3_deinit(cpu);
+}
+
+static void plat_cpu_pwron_common(unsigned int cpu,
+		const psci_power_state_t *state, unsigned int req_pstate)
+{
+	assert(cpu == plat_my_core_pos());
+
+	plat_mt_pm_invoke_no_check(pwr_cpu_on, cpu, state);
+
+	coordinate_cluster_pwron();
+
+	/* Enable the GIC CPU interface */
+	gicv3_rdistif_on(cpu);
+	gicv3_cpuif_enable(cpu);
+	mt_gic_rdistif_init();
+
+	/*
+	 * If mcusys does power down before then restore
+	 * all CPUs' GIC Redistributors
+	 */
+	if (IS_MCUSYS_OFF_STATE(state)) {
+		mt_gic_rdistif_restore_all();
+	} else {
+		mt_gic_rdistif_restore();
+	}
+
+	/* PTP3 config */
+	ptp3_init(cpu);
+}
+
+/*
+ * Common MTK_platform operations to power on/off a
+ * cluster in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request.
+ */
+
+static void plat_cluster_pwrdwn_common(unsigned int cpu,
+		const psci_power_state_t *state, unsigned int req_pstate)
+{
+	assert(cpu == plat_my_core_pos());
+
+	if (plat_mt_pm_invoke(pwr_cluster_dwn, cpu, state) != 0) {
+		coordinate_cluster_pwron();
+
+		/* TODO: return on fail.
+		 *       Add a 'return' here before adding any code following
+		 *       the if-block.
+		 */
+	}
+}
+
+static void plat_cluster_pwron_common(unsigned int cpu,
+		const psci_power_state_t *state, unsigned int req_pstate)
+{
+	assert(cpu == plat_my_core_pos());
+
+	if (plat_mt_pm_invoke(pwr_cluster_on, cpu, state) != 0) {
+		/* TODO: return on fail.
+		 *       Add a 'return' here before adding any code following
+		 *       the if-block.
+		 */
+	}
+}
+
+/*
+ * Common MTK_platform operations to power on/off a
+ * mcusys in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request.
+ */
+
+static void plat_mcusys_pwrdwn_common(unsigned int cpu,
+		const psci_power_state_t *state, unsigned int req_pstate)
+{
+	assert(cpu == plat_my_core_pos());
+
+	if (plat_mt_pm_invoke(pwr_mcusys_dwn, cpu, state) != 0) {
+		return;		/* return on fail */
+	}
+
+	mt_gic_distif_save();
+	gic_sgi_save_all();
+}
+
+static void plat_mcusys_pwron_common(unsigned int cpu,
+		const psci_power_state_t *state, unsigned int req_pstate)
+{
+	assert(cpu == plat_my_core_pos());
+
+	if (plat_mt_pm_invoke(pwr_mcusys_on, cpu, state) != 0) {
+		return;		/* return on fail */
+	}
+
+	mt_gic_init();
+	mt_gic_distif_restore();
+	gic_sgi_restore_all();
+
+	plat_mt_pm_invoke_no_check(pwr_mcusys_on_finished, cpu, state);
+}
+
+/*
+ * plat_psci_ops implementation
+ */
+
+static void plat_cpu_standby(plat_local_state_t cpu_state)
+{
+	uint64_t scr;
+
+	scr = read_scr_el3();
+	write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT);
+
+	isb();
+	dsb();
+	wfi();
+
+	write_scr_el3(scr);
+}
+
+static int plat_power_domain_on(u_register_t mpidr)
+{
+	unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr);
+	unsigned int cluster = 0U;
+
+	if (cpu >= PLATFORM_CORE_COUNT) {
+		return PSCI_E_INVALID_PARAMS;
+	}
+
+	if (!spm_get_cluster_powerstate(cluster)) {
+		spm_poweron_cluster(cluster);
+	}
 
-/*******************************************************************************
- * MTK handlers to shutdown/reboot the system
- ******************************************************************************/
+	/* init CPU reset arch as AARCH64 */
+	mcucfg_init_archstate(cluster, cpu, true);
+	mcucfg_set_bootaddr(cluster, cpu, secure_entrypoint);
+	spm_poweron_cpu(cluster, cpu);
+
+	return PSCI_E_SUCCESS;
+}
+
+static void plat_power_domain_on_finish(const psci_power_state_t *state)
+{
+	unsigned long mpidr = read_mpidr_el1();
+	unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr);
+
+	assert(cpu < PLATFORM_CORE_COUNT);
+
+	/* Allow IRQs to wakeup this core in IDLE flow */
+	mcucfg_enable_gic_wakeup(0U, cpu);
+
+	if (IS_CLUSTER_OFF_STATE(state)) {
+		plat_cluster_pwron_common(cpu, state, 0U);
+	}
+
+	plat_cpu_pwron_common(cpu, state, 0U);
+}
+
+static void plat_power_domain_off(const psci_power_state_t *state)
+{
+	unsigned long mpidr = read_mpidr_el1();
+	unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr);
+
+	assert(cpu < PLATFORM_CORE_COUNT);
+
+	plat_cpu_pwrdwn_common(cpu, state, 0U);
+	spm_poweroff_cpu(0U, cpu);
+
+	/* prevent unintended IRQs from waking up the hot-unplugged core */
+	mcucfg_disable_gic_wakeup(0U, cpu);
+
+	if (IS_CLUSTER_OFF_STATE(state)) {
+		plat_cluster_pwrdwn_common(cpu, state, 0U);
+	}
+}
+
+static void plat_power_domain_suspend(const psci_power_state_t *state)
+{
+	unsigned int cpu = plat_my_core_pos();
+
+	assert(cpu < PLATFORM_CORE_COUNT);
+
+	plat_mt_pm_invoke_no_check(pwr_prompt, cpu, state);
+
+	/* Perform the common CPU specific operations */
+	plat_cpu_pwrdwn_common(cpu, state, plat_power_state[cpu]);
+
+	if (IS_CLUSTER_OFF_STATE(state)) {
+		/* Perform the common cluster specific operations */
+		plat_cluster_pwrdwn_common(cpu, state, plat_power_state[cpu]);
+	}
+
+	if (IS_MCUSYS_OFF_STATE(state)) {
+		/* Perform the common mcusys specific operations */
+		plat_mcusys_pwrdwn_common(cpu, state, plat_power_state[cpu]);
+	}
+}
+
+static void plat_power_domain_suspend_finish(const psci_power_state_t *state)
+{
+	unsigned int cpu = plat_my_core_pos();
+
+	assert(cpu < PLATFORM_CORE_COUNT);
+
+	if (IS_MCUSYS_OFF_STATE(state)) {
+		/* Perform the common mcusys specific operations */
+		plat_mcusys_pwron_common(cpu, state, plat_power_state[cpu]);
+	}
+
+	if (IS_CLUSTER_OFF_STATE(state)) {
+		/* Perform the common cluster specific operations */
+		plat_cluster_pwron_common(cpu, state, plat_power_state[cpu]);
+	}
+
+	/* Perform the common CPU specific operations */
+	plat_cpu_pwron_common(cpu, state, plat_power_state[cpu]);
+
+	plat_mt_pm_invoke_no_check(pwr_reflect, cpu, state);
+}
+
+static int plat_validate_power_state(unsigned int power_state,
+					psci_power_state_t *req_state)
+{
+	unsigned int pstate = psci_get_pstate_type(power_state);
+	unsigned int aff_lvl = psci_get_pstate_pwrlvl(power_state);
+	unsigned int cpu = plat_my_core_pos();
+
+	if (pstate == PSTATE_TYPE_STANDBY) {
+		req_state->pwr_domain_state[0] = PLAT_MAX_RET_STATE;
+	} else {
+		unsigned int i;
+		unsigned int pstate_id = psci_get_pstate_id(power_state);
+		plat_local_state_t s = MTK_LOCAL_STATE_OFF;
+
+		/* Use pstate_id to be power domain state */
+		if (pstate_id > s) {
+			s = (plat_local_state_t)pstate_id;
+		}
+
+		for (i = 0U; i <= aff_lvl; i++) {
+			req_state->pwr_domain_state[i] = s;
+		}
+	}
+
+	plat_power_state[cpu] = power_state;
+	return PSCI_E_SUCCESS;
+}
+
+static void plat_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+	unsigned int lv;
+	unsigned int cpu = plat_my_core_pos();
+
+	for (lv = PSCI_CPU_PWR_LVL; lv <= PLAT_MAX_PWR_LVL; lv++) {
+		req_state->pwr_domain_state[lv] = PLAT_MAX_OFF_STATE;
+	}
+
+	plat_power_state[cpu] =
+			psci_make_powerstate(
+				MT_PLAT_PWR_STATE_SYSTEM_SUSPEND,
+				PSTATE_TYPE_POWERDOWN, PLAT_MAX_PWR_LVL);
+
+	flush_dcache_range((uintptr_t)
+			&plat_power_state[cpu],
+			sizeof(plat_power_state[cpu]));
+}
+
+static void __dead2 plat_mtk_system_off(void)
+{
+	INFO("MTK System Off\n");
+
+	rtc_power_off_sequence();
+	pmic_power_off();
+
+	wfi();
+	ERROR("MTK System Off: operation not handled.\n");
+	panic();
+}
+
 static void __dead2 plat_mtk_system_reset(void)
 {
 	struct bl_aux_gpio_info *gpio_reset = plat_get_mtk_gpio_reset();
@@ -29,18 +363,35 @@
 	panic();
 }
 
-/*******************************************************************************
- * MTK_platform handler called when an affinity instance is about to be turned
- * on. The level and mpidr determine the affinity instance.
- ******************************************************************************/
-static const plat_psci_ops_t plat_plat_pm_ops = {
-	.system_reset         = plat_mtk_system_reset,
+static const plat_psci_ops_t plat_psci_ops = {
+	.system_reset			= plat_mtk_system_reset,
+	.cpu_standby			= plat_cpu_standby,
+	.pwr_domain_on			= plat_power_domain_on,
+	.pwr_domain_on_finish		= plat_power_domain_on_finish,
+	.pwr_domain_off			= plat_power_domain_off,
+	.pwr_domain_suspend		= plat_power_domain_suspend,
+	.pwr_domain_suspend_finish	= plat_power_domain_suspend_finish,
+	.system_off			= plat_mtk_system_off,
+	.validate_power_state		= plat_validate_power_state,
+	.get_sys_suspend_power_state	= plat_get_sys_suspend_power_state
 };
 
 int plat_setup_psci_ops(uintptr_t sec_entrypoint,
 			const plat_psci_ops_t **psci_ops)
 {
-	*psci_ops = &plat_plat_pm_ops;
+	*psci_ops = &plat_psci_ops;
+	secure_entrypoint = sec_entrypoint;
+
+	/*
+	 * init the warm reset config for boot CPU
+	 * reset arch as AARCH64
+	 * reset addr as function bl31_warm_entrypoint()
+	 */
+	mcucfg_init_archstate(0U, 0U, true);
+	mcucfg_set_bootaddr(0U, 0U, secure_entrypoint);
+
+	spmc_init();
+	plat_mt_pm = mt_plat_cpu_pm_init();
 
 	return 0;
 }
diff --git a/plat/mediatek/mt8192/plat_sip_calls.c b/plat/mediatek/mt8192/plat_sip_calls.c
new file mode 100644
index 0000000..f97684f
--- /dev/null
+++ b/plat/mediatek/mt8192/plat_sip_calls.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+
+uintptr_t mediatek_plat_sip_handler(uint32_t smc_fid,
+				u_register_t x1,
+				u_register_t x2,
+				u_register_t x3,
+				u_register_t x4,
+				void *cookie,
+				void *handle,
+				u_register_t flags)
+{
+
+	switch (smc_fid) {
+	default:
+		ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
+		break;
+	}
+
+	SMC_RET1(handle, SMC_UNK);
+}
diff --git a/plat/mediatek/mt8192/plat_topology.c b/plat/mediatek/mt8192/plat_topology.c
index aa4975e..8c1231a 100644
--- a/plat/mediatek/mt8192/plat_topology.c
+++ b/plat/mediatek/mt8192/plat_topology.c
@@ -17,6 +17,8 @@
 	/* Number of root nodes */
 	PLATFORM_SYSTEM_COUNT,
 	/* Number of children for the root node */
+	PLATFORM_MCUSYS_COUNT,
+	/* Number of children for the mcusys node */
 	PLATFORM_CLUSTER_COUNT,
 	/* Number of children for the first cluster node */
 	PLATFORM_CLUSTER0_CORE_COUNT,
diff --git a/plat/mediatek/mt8192/platform.mk b/plat/mediatek/mt8192/platform.mk
index 7544b26..a5e7ee2 100644
--- a/plat/mediatek/mt8192/platform.mk
+++ b/plat/mediatek/mt8192/platform.mk
@@ -10,8 +10,16 @@
 PLAT_INCLUDES := -I${MTK_PLAT}/common/                            \
                  -I${MTK_PLAT_SOC}/include/                       \
                  -I${MTK_PLAT_SOC}/drivers/                       \
+                 -I${MTK_PLAT_SOC}/drivers/dcm                    \
+                 -I${MTK_PLAT_SOC}/drivers/emi_mpu/               \
                  -I${MTK_PLAT_SOC}/drivers/gpio/                  \
-                 -I${MTK_PLAT_SOC}/drivers/timer/
+                 -I${MTK_PLAT_SOC}/drivers/mcdi/                  \
+                 -I${MTK_PLAT_SOC}/drivers/pmic/                  \
+                 -I${MTK_PLAT_SOC}/drivers/ptp3/                  \
+                 -I${MTK_PLAT_SOC}/drivers/rtc/                   \
+                 -I${MTK_PLAT_SOC}/drivers/spmc/                  \
+                 -I${MTK_PLAT_SOC}/drivers/timer/                 \
+                 -I${MTK_PLAT_SOC}/drivers/uart/
 
 GICV3_SUPPORT_GIC600        :=      1
 include drivers/arm/gic/v3/gicv3.mk
@@ -23,25 +31,41 @@
                           plat/common/plat_psci_common.c
 
 BL31_SOURCES    += common/desc_image_load.c                              \
+                   drivers/delay_timer/delay_timer.c                     \
+                   drivers/delay_timer/generic_delay_timer.c             \
                    drivers/ti/uart/aarch64/16550_console.S               \
                    drivers/gpio/gpio.c                                   \
                    lib/bl_aux_params/bl_aux_params.c                     \
                    lib/cpus/aarch64/cortex_a55.S                         \
                    lib/cpus/aarch64/cortex_a76.S                         \
                    plat/common/plat_gicv3.c                              \
+                   ${MTK_PLAT}/common/drivers/pmic_wrap/pmic_wrap_init_v2.c \
+                   ${MTK_PLAT}/common/drivers/rtc/rtc_common.c           \
+                   ${MTK_PLAT}/common/drivers/uart/uart.c                \
                    ${MTK_PLAT}/common/mtk_plat_common.c                  \
+                   ${MTK_PLAT}/common/mtk_sip_svc.c                      \
                    ${MTK_PLAT}/common/params_setup.c                     \
                    ${MTK_PLAT_SOC}/aarch64/platform_common.c             \
                    ${MTK_PLAT_SOC}/aarch64/plat_helpers.S                \
                    ${MTK_PLAT_SOC}/bl31_plat_setup.c                     \
+                   ${MTK_PLAT_SOC}/drivers/pmic/pmic.c                   \
+                   ${MTK_PLAT_SOC}/drivers/rtc/rtc.c                     \
                    ${MTK_PLAT_SOC}/plat_pm.c                             \
                    ${MTK_PLAT_SOC}/plat_topology.c                       \
                    ${MTK_PLAT_SOC}/plat_mt_gic.c                         \
                    ${MTK_PLAT_SOC}/plat_mt_cirq.c                        \
+                   ${MTK_PLAT_SOC}/plat_sip_calls.c                      \
+                   ${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm.c                 \
+                   ${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm_utils.c           \
+                   ${MTK_PLAT_SOC}/drivers/emi_mpu/emi_mpu.c             \
                    ${MTK_PLAT_SOC}/drivers/gpio/mtgpio.c                 \
+                   ${MTK_PLAT_SOC}/drivers/mcdi/mt_cpu_pm.c              \
+                   ${MTK_PLAT_SOC}/drivers/mcdi/mt_cpu_pm_cpc.c          \
+                   ${MTK_PLAT_SOC}/drivers/mcdi/mt_mcdi.c                \
+                   ${MTK_PLAT_SOC}/drivers/ptp3/mtk_ptp3_main.c          \
+                   ${MTK_PLAT_SOC}/drivers/spmc/mtspmc.c                 \
                    ${MTK_PLAT_SOC}/drivers/timer/mt_timer.c
 
-
 # Configs for A76 and A55
 HW_ASSISTED_COHERENCY := 1
 USE_COHERENT_MEM := 0
diff --git a/plat/nvidia/tegra/common/tegra_platform.c b/plat/nvidia/tegra/common/tegra_platform.c
index 7c73e8f..d45d988 100644
--- a/plat/nvidia/tegra/common/tegra_platform.c
+++ b/plat/nvidia/tegra/common/tegra_platform.c
@@ -297,14 +297,14 @@
 }
 
 /*****************************************************************************
- * plat_smccc_feature_available() - This function checks whether SMCCC feature
+ * plat_is_smccc_feature_available() - This function checks whether SMCCC feature
  *                                  is availabile for the platform or not.
  * @fid: SMCCC function id
  *
  * Return SMC_ARCH_CALL_SUCCESS if SMCCC feature is available and
  * SMC_ARCH_CALL_NOT_SUPPORTED otherwise.
  *****************************************************************************/
-int32_t plat_smccc_feature_available(u_register_t fid)
+int32_t plat_is_smccc_feature_available(u_register_t fid)
 {
 	switch (fid) {
 	case SMCCC_ARCH_SOC_ID:
diff --git a/plat/qemu/qemu_sbsa/include/platform_def.h b/plat/qemu/qemu_sbsa/include/platform_def.h
index 7634005..75851e3 100644
--- a/plat/qemu/qemu_sbsa/include/platform_def.h
+++ b/plat/qemu/qemu_sbsa/include/platform_def.h
@@ -85,7 +85,7 @@
  */
 
 #define SHARED_RAM_BASE			SEC_SRAM_BASE
-#define SHARED_RAM_SIZE			0x00001000
+#define SHARED_RAM_SIZE			0x00002000
 
 #define PLAT_QEMU_TRUSTED_MAILBOX_BASE	SHARED_RAM_BASE
 #define PLAT_QEMU_TRUSTED_MAILBOX_SIZE	(8 + PLAT_QEMU_HOLD_SIZE)
diff --git a/plat/qemu/qemu_sbsa/platform.mk b/plat/qemu/qemu_sbsa/platform.mk
index 9be56a3..acaa43f 100644
--- a/plat/qemu/qemu_sbsa/platform.mk
+++ b/plat/qemu/qemu_sbsa/platform.mk
@@ -47,7 +47,8 @@
 				${PLAT_QEMU_COMMON_PATH}/${ARCH}/plat_helpers.S	\
 				${PLAT_QEMU_COMMON_PATH}/qemu_bl1_setup.c
 
-BL1_SOURCES		+=	lib/cpus/aarch64/cortex_a57.S
+BL1_SOURCES		+=	lib/cpus/aarch64/cortex_a57.S			\
+				lib/cpus/aarch64/cortex_a72.S
 
 BL2_SOURCES		+=	drivers/io/io_semihosting.c			\
 				drivers/io/io_storage.c				\
@@ -74,6 +75,7 @@
 				${PLAT_QEMU_COMMON_PATH}/qemu_gicv3.c
 
 BL31_SOURCES		+=	lib/cpus/aarch64/cortex_a57.S			\
+				lib/cpus/aarch64/cortex_a72.S			\
 				lib/semihosting/semihosting.c			\
 				lib/semihosting/${ARCH}/semihosting_call.S	\
 				plat/common/plat_psci_common.c			\
diff --git a/plat/qti/common/src/qti_common.c b/plat/qti/common/src/qti_common.c
index 9355eb7..da0eaec 100644
--- a/plat/qti/common/src/qti_common.c
+++ b/plat/qti/common/src/qti_common.c
@@ -176,14 +176,14 @@
 }
 
 /*****************************************************************************
- * plat_smccc_feature_available() - This function checks whether SMCCC feature
+ * plat_is_smccc_feature_available() - This function checks whether SMCCC feature
  *                                  is availabile for the platform or not.
  * @fid: SMCCC function id
  *
  * Return SMC_ARCH_CALL_SUCCESS if SMCCC feature is available and
  * SMC_ARCH_CALL_NOT_SUPPORTED otherwise.
  *****************************************************************************/
-int32_t plat_smccc_feature_available(u_register_t fid)
+int32_t plat_is_smccc_feature_available(u_register_t fid)
 {
 	switch (fid) {
 	case SMCCC_ARCH_SOC_ID:
diff --git a/plat/rockchip/common/rockchip_stack_protector.c b/plat/rockchip/common/rockchip_stack_protector.c
new file mode 100644
index 0000000..1898977
--- /dev/null
+++ b/plat/rockchip/common/rockchip_stack_protector.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <arch_helpers.h>
+#include <plat/common/platform.h>
+
+#define RANDOM_CANARY_VALUE ((u_register_t) 3288484550995823360ULL)
+
+u_register_t plat_get_stack_protector_canary(void)
+{
+	/*
+	 * Ideally, a random number should be returned instead of the
+	 * combination of a timer's value and a compile-time constant.
+	 * As the virt platform does not have any random number generator,
+	 * this is better than nothing but not necessarily really secure.
+	 */
+	return RANDOM_CANARY_VALUE ^ read_cntpct_el0();
+}
+
diff --git a/plat/rockchip/px30/platform.mk b/plat/rockchip/px30/platform.mk
index 87cf187..b1bb807 100644
--- a/plat/rockchip/px30/platform.mk
+++ b/plat/rockchip/px30/platform.mk
@@ -36,6 +36,10 @@
 				lib/xlat_tables/aarch64/xlat_tables.c		\
 				plat/common/plat_psci_common.c
 
+ifneq (${ENABLE_STACK_PROTECTOR},0)
+PLAT_BL_COMMON_SOURCES	+=	${RK_PLAT_COMMON}/rockchip_stack_protector.c
+endif
+
 BL31_SOURCES		+=	${RK_GIC_SOURCES}				\
 				common/desc_image_load.c			\
 				drivers/arm/cci/cci.c				\
diff --git a/plat/rockchip/rk3328/platform.mk b/plat/rockchip/rk3328/platform.mk
index 0219422..5a307e4 100644
--- a/plat/rockchip/rk3328/platform.mk
+++ b/plat/rockchip/rk3328/platform.mk
@@ -35,6 +35,10 @@
 				plat/common/aarch64/crash_console_helpers.S	\
 				plat/common/plat_psci_common.c
 
+ifneq (${ENABLE_STACK_PROTECTOR},0)
+PLAT_BL_COMMON_SOURCES	+=	${RK_PLAT_COMMON}/rockchip_stack_protector.c
+endif
+
 BL31_SOURCES		+=	${RK_GIC_SOURCES}				\
 				drivers/arm/cci/cci.c				\
 				drivers/ti/uart/aarch64/16550_console.S		\
diff --git a/plat/rockchip/rk3368/platform.mk b/plat/rockchip/rk3368/platform.mk
index cb0cb89..e787293 100644
--- a/plat/rockchip/rk3368/platform.mk
+++ b/plat/rockchip/rk3368/platform.mk
@@ -33,6 +33,10 @@
 				plat/common/aarch64/crash_console_helpers.S	\
 				plat/common/plat_psci_common.c
 
+ifneq (${ENABLE_STACK_PROTECTOR},0)
+PLAT_BL_COMMON_SOURCES	+=	${RK_PLAT_COMMON}/rockchip_stack_protector.c
+endif
+
 BL31_SOURCES		+=	${RK_GIC_SOURCES}				\
 				drivers/arm/cci/cci.c				\
 				drivers/ti/uart/aarch64/16550_console.S		\
diff --git a/plat/rockchip/rk3399/platform.mk b/plat/rockchip/rk3399/platform.mk
index a658fb2..aba67c2 100644
--- a/plat/rockchip/rk3399/platform.mk
+++ b/plat/rockchip/rk3399/platform.mk
@@ -38,6 +38,10 @@
 				plat/common/aarch64/crash_console_helpers.S \
 				plat/common/plat_psci_common.c
 
+ifneq (${ENABLE_STACK_PROTECTOR},0)
+PLAT_BL_COMMON_SOURCES	+=	${RK_PLAT_COMMON}/rockchip_stack_protector.c
+endif
+
 BL31_SOURCES	+=	${RK_GIC_SOURCES}				\
 			drivers/arm/cci/cci.c				\
 			drivers/ti/uart/aarch64/16550_console.S		\
diff --git a/plat/ti/k3/board/generic/board.mk b/plat/ti/k3/board/generic/board.mk
index a342214..ef74cd6 100644
--- a/plat/ti/k3/board/generic/board.mk
+++ b/plat/ti/k3/board/generic/board.mk
@@ -13,5 +13,12 @@
 K3_HW_CONFIG_BASE ?= 0x82000000
 $(eval $(call add_define,K3_HW_CONFIG_BASE))
 
+# Define sec_proxy usage as the full prioritized communication scheme
+K3_SEC_PROXY_LITE	:=	0
+$(eval $(call add_define,K3_SEC_PROXY_LITE))
+
+# System coherency is managed in hardware
+USE_COHERENT_MEM	:=	1
+
 PLAT_INCLUDES		+=	\
 				-Iplat/ti/k3/board/generic/include	\
diff --git a/plat/ti/k3/board/lite/board.mk b/plat/ti/k3/board/lite/board.mk
new file mode 100644
index 0000000..76246be
--- /dev/null
+++ b/plat/ti/k3/board/lite/board.mk
@@ -0,0 +1,24 @@
+#
+# Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+BL32_BASE ?= 0x9e800000
+$(eval $(call add_define,BL32_BASE))
+
+PRELOADED_BL33_BASE ?= 0x80080000
+$(eval $(call add_define,PRELOADED_BL33_BASE))
+
+K3_HW_CONFIG_BASE ?= 0x82000000
+$(eval $(call add_define,K3_HW_CONFIG_BASE))
+
+# Define sec_proxy usage as the lite version
+K3_SEC_PROXY_LITE	:=	1
+$(eval $(call add_define,K3_SEC_PROXY_LITE))
+
+# We dont have system level coherency capability
+USE_COHERENT_MEM	:=	0
+
+PLAT_INCLUDES	+=			\
+	-Iplat/ti/k3/board/lite/include	\
diff --git a/plat/ti/k3/board/lite/include/board_def.h b/plat/ti/k3/board/lite/include/board_def.h
new file mode 100644
index 0000000..7c7ea62
--- /dev/null
+++ b/plat/ti/k3/board/lite/include/board_def.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BOARD_DEF_H
+#define BOARD_DEF_H
+
+#include <lib/utils_def.h>
+
+/* The ports must be in order and contiguous */
+#define K3_CLUSTER0_CORE_COUNT		U(4)
+#define K3_CLUSTER1_CORE_COUNT		U(0)
+#define K3_CLUSTER2_CORE_COUNT		U(0)
+#define K3_CLUSTER3_CORE_COUNT		U(0)
+
+/*
+ * This RAM will be used for the bootloader including code, bss, and stacks.
+ * It may need to be increased if BL31 grows in size.
+ * Current computation assumes data structures necessary for GIC and ARM for
+ * a single cluster of 4 processor.
+ */
+#define SEC_SRAM_BASE			0x70000000 /* Base of SRAM */
+#define SEC_SRAM_SIZE			0x0001a000 /* 104k */
+
+#define PLAT_MAX_OFF_STATE		U(2)
+#define PLAT_MAX_RET_STATE		U(1)
+
+#define PLAT_PROC_START_ID		32
+#define PLAT_PROC_DEVICE_START_ID	135
+#define PLAT_CLUSTER_DEVICE_START_ID	134
+
+#endif /* BOARD_DEF_H */
diff --git a/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.c b/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.c
index ee1eecf..a0bfdee 100644
--- a/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.c
+++ b/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.c
@@ -97,11 +97,16 @@
 		.data_end_offset = 0x3C,
 	},
 	.threads = {
+#if !K3_SEC_PROXY_LITE
 		SP_THREAD(SP_NOTIFY),
 		SP_THREAD(SP_RESPONSE),
 		SP_THREAD(SP_HIGH_PRIORITY),
 		SP_THREAD(SP_LOW_PRIORITY),
 		SP_THREAD(SP_NOTIFY_RESP),
+#else
+		SP_THREAD(SP_RESPONSE),
+		SP_THREAD(SP_HIGH_PRIORITY),
+#endif /* K3_SEC_PROXY_LITE */
 	},
 };
 
@@ -261,9 +266,14 @@
 	/*
 	 * 'data_reg' indicates next register to write. If we did not already
 	 * write on tx complete reg(last reg), we must do so for transmit
+	 * In addition, we also need to make sure all intermediate data
+	 * registers(if any required), are reset to 0 for TISCI backward
+	 * compatibility to be maintained.
 	 */
-	if (data_reg <= spm.desc.data_end_offset)
-		mmio_write_32(spt->data + spm.desc.data_end_offset, 0);
+	while (data_reg <= spm.desc.data_end_offset) {
+		mmio_write_32(spt->data + data_reg, 0);
+		data_reg += sizeof(uint32_t);
+	}
 
 	VERBOSE("Message successfully sent on thread %s\n", spt->name);
 
diff --git a/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.h b/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.h
index 6c4f5df..f4b0b4b 100644
--- a/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.h
+++ b/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.h
@@ -16,13 +16,28 @@
  * enum k3_sec_proxy_chan_id - Secure Proxy thread IDs
  *
  * These the available IDs used in k3_sec_proxy_{send,recv}()
+ * There are two schemes we use:
+ * * if K3_SEC_PROXY_LITE = 1, we just have two threads to talk
+ * * if K3_SEC_PROXY_LITE = 0, we have the full fledged
+ *   communication scheme available.
  */
 enum k3_sec_proxy_chan_id {
+#if !K3_SEC_PROXY_LITE
 	SP_NOTIFY = 0,
 	SP_RESPONSE,
 	SP_HIGH_PRIORITY,
 	SP_LOW_PRIORITY,
 	SP_NOTIFY_RESP,
+#else
+	SP_RESPONSE = 8,
+	/*
+	 * Note: TISCI documentation indicates "low priority", but in reality
+	 * with a single thread, there is no low or high priority.. This usage
+	 * is more appropriate for TF-A since we can reduce the churn as a
+	 * result.
+	 */
+	SP_HIGH_PRIORITY,
+#endif /* K3_SEC_PROXY_LITE */
 };
 
 /**
diff --git a/plat/ti/k3/common/drivers/ti_sci/ti_sci.c b/plat/ti/k3/common/drivers/ti_sci/ti_sci.c
index e390efe..2c3313c 100644
--- a/plat/ti/k3/common/drivers/ti_sci/ti_sci.c
+++ b/plat/ti/k3/common/drivers/ti_sci/ti_sci.c
@@ -1163,6 +1163,7 @@
 		ERROR("Message alloc failed (%d)\n", ret);
 		return ret;
 	}
+	req.domain = TI_SCI_DOMAIN_FULL_SOC_RESET;
 
 	ret = ti_sci_do_xfer(&xfer);
 	if (ret) {
diff --git a/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h b/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h
index 2d23f9a..310bf45 100644
--- a/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h
+++ b/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h
@@ -95,12 +95,15 @@
 /**
  * struct ti_sci_msg_req_reboot - Reboot the SoC
  * @hdr:	Generic Header
+ * @domain:	Domain to be reset, 0 for full SoC reboot
  *
  * Request type is TI_SCI_MSG_SYS_RESET, responded with a generic
  * ACK/NACK message.
  */
 struct ti_sci_msg_req_reboot {
 	struct ti_sci_msg_hdr hdr;
+#define TI_SCI_DOMAIN_FULL_SOC_RESET	0x0
+	uint8_t domain;
 } __packed;
 
 /**
diff --git a/plat/ti/k3/common/k3_bl31_setup.c b/plat/ti/k3/common/k3_bl31_setup.c
index 8bd7362..ac4e60e 100644
--- a/plat/ti/k3/common/k3_bl31_setup.c
+++ b/plat/ti/k3/common/k3_bl31_setup.c
@@ -13,6 +13,7 @@
 #include <arch_helpers.h>
 #include <common/bl_common.h>
 #include <common/debug.h>
+#include <lib/mmio.h>
 #include <lib/xlat_tables/xlat_tables_v2.h>
 
 #include <k3_console.h>
@@ -23,6 +24,7 @@
 const mmap_region_t plat_k3_mmap[] = {
 	MAP_REGION_FLAT(K3_USART_BASE,       K3_USART_SIZE,       MT_DEVICE | MT_RW | MT_SECURE),
 	MAP_REGION_FLAT(K3_GIC_BASE,         K3_GIC_SIZE,         MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(K3_GTC_BASE,         K3_GTC_SIZE,         MT_DEVICE | MT_RW | MT_SECURE),
 	MAP_REGION_FLAT(SEC_PROXY_RT_BASE,   SEC_PROXY_RT_SIZE,   MT_DEVICE | MT_RW | MT_SECURE),
 	MAP_REGION_FLAT(SEC_PROXY_SCFG_BASE, SEC_PROXY_SCFG_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
 	MAP_REGION_FLAT(SEC_PROXY_DATA_BASE, SEC_PROXY_DATA_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
@@ -127,6 +129,38 @@
 
 unsigned int plat_get_syscnt_freq2(void)
 {
+	uint32_t gtc_freq;
+	uint32_t gtc_ctrl;
+
+	/* Lets try and provide basic diagnostics - cost is low */
+	gtc_ctrl = mmio_read_32(K3_GTC_BASE + K3_GTC_CNTCR_OFFSET);
+	/* Did the bootloader fail to enable timer and OS guys are confused? */
+	if ((gtc_ctrl & K3_GTC_CNTCR_EN_MASK) == 0U) {
+		ERROR("GTC is disabled! Timekeeping broken. Fix Bootloader\n");
+	}
+	/*
+	 * If debug will not pause time, we will have issues like
+	 * drivers timing out while debugging, in cases of OS like Linux,
+	 * RCU stall errors, which can be hard to differentiate vs real issues.
+	 */
+	if ((gtc_ctrl & K3_GTC_CNTCR_HDBG_MASK) == 0U) {
+		WARN("GTC: Debug access doesn't stop time. Fix Bootloader\n");
+	}
+
+	gtc_freq = mmio_read_32(K3_GTC_BASE + K3_GTC_CNTFID0_OFFSET);
+	/* Many older bootloaders may have missed programming FID0 register */
+	if (gtc_freq != 0U) {
+		return gtc_freq;
+	}
+
+	/*
+	 * We could have just warned about this, but this can have serious
+	 * hard to debug side effects if we are NOT sure what the actual
+	 * frequency is. Lets make sure people don't miss this.
+	 */
+	ERROR("GTC_CNTFID0 is 0! Assuming %d Hz. Fix Bootloader\n",
+	      SYS_COUNTER_FREQ_IN_TICKS);
+
 	return SYS_COUNTER_FREQ_IN_TICKS;
 }
 
diff --git a/plat/ti/k3/common/plat_common.mk b/plat/ti/k3/common/plat_common.mk
index c00262b..ab7366b 100644
--- a/plat/ti/k3/common/plat_common.mk
+++ b/plat/ti/k3/common/plat_common.mk
@@ -11,9 +11,8 @@
 # We can choose where a core starts executing
 PROGRAMMABLE_RESET_ADDRESS:=	1
 
-# System coherency is managed in hardware
+# ARM coherency is managed in hardware
 WARMBOOT_ENABLE_DCACHE_EARLY :=	1
-USE_COHERENT_MEM	:=	1
 
 # A53 erratum for SoC. (enable them all)
 ERRATA_A53_826319	:=	1
@@ -21,9 +20,11 @@
 ERRATA_A53_836870	:=	1
 ERRATA_A53_843419	:=	1
 ERRATA_A53_855873	:=	1
+ERRATA_A53_1530924	:=	1
 
 # A72 Erratum for SoC
 ERRATA_A72_859971	:=	1
+ERRATA_A72_1319367	:=	1
 
 CRASH_REPORTING		:= 1
 HANDLE_EA_EL3_FIRST	:= 1
diff --git a/plat/ti/k3/include/platform_def.h b/plat/ti/k3/include/platform_def.h
index 98db626..f12fb0b 100644
--- a/plat/ti/k3/include/platform_def.h
+++ b/plat/ti/k3/include/platform_def.h
@@ -150,15 +150,33 @@
 	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, grp, \
 			GIC_INTR_CFG_EDGE)
 
+
+#define K3_GTC_BASE		0x00A90000
+/* We just need 20 byte offset, but simpler to just remap the 64K page in */
+#define K3_GTC_SIZE		0x10000
+#define K3_GTC_CNTCR_OFFSET	0x00
+#define K3_GTC_CNTCR_EN_MASK	0x01
+#define K3_GTC_CNTCR_HDBG_MASK	0x02
+#define K3_GTC_CNTFID0_OFFSET	0x20
+
 #define K3_GIC_BASE	0x01800000
 #define K3_GIC_SIZE	0x200000
 
+#if !K3_SEC_PROXY_LITE
 #define SEC_PROXY_DATA_BASE	0x32C00000
 #define SEC_PROXY_DATA_SIZE	0x80000
 #define SEC_PROXY_SCFG_BASE	0x32800000
 #define SEC_PROXY_SCFG_SIZE	0x80000
 #define SEC_PROXY_RT_BASE	0x32400000
 #define SEC_PROXY_RT_SIZE	0x80000
+#else
+#define SEC_PROXY_DATA_BASE	0x4D000000
+#define SEC_PROXY_DATA_SIZE	0x80000
+#define SEC_PROXY_SCFG_BASE	0x4A400000
+#define SEC_PROXY_SCFG_SIZE	0x80000
+#define SEC_PROXY_RT_BASE	0x4A600000
+#define SEC_PROXY_RT_SIZE	0x80000
+#endif /* K3_SEC_PROXY_LITE */
 
 #define SEC_PROXY_TIMEOUT_US		1000000
 #define SEC_PROXY_MAX_MESSAGE_SIZE	56
diff --git a/plat/xilinx/common/pm_service/pm_ipi.c b/plat/xilinx/common/pm_service/pm_ipi.c
index c83d25b..5dcceae 100644
--- a/plat/xilinx/common/pm_service/pm_ipi.c
+++ b/plat/xilinx/common/pm_service/pm_ipi.c
@@ -18,6 +18,8 @@
 #include "pm_ipi.h"
 
 
+#define ERROR_CODE_MASK		0xFFFFU
+
 DEFINE_BAKERY_LOCK(pm_secure_lock);
 
 /**
@@ -230,7 +232,7 @@
 	if (ret != PM_RET_SUCCESS)
 		goto unlock;
 
-	ret = pm_ipi_buff_read(proc, value, count);
+	ret = ERROR_CODE_MASK & (pm_ipi_buff_read(proc, value, count));
 
 unlock:
 	bakery_lock_release(&pm_secure_lock);
diff --git a/plat/xilinx/versal/bl31_versal_setup.c b/plat/xilinx/versal/bl31_versal_setup.c
index 03b7fbb..27991d3 100644
--- a/plat/xilinx/versal/bl31_versal_setup.c
+++ b/plat/xilinx/versal/bl31_versal_setup.c
@@ -97,7 +97,7 @@
 	enum fsbl_handoff ret = fsbl_atf_handover(&bl32_image_ep_info,
 						  &bl33_image_ep_info,
 						  atf_handoff_addr);
-	if (ret == FSBL_HANDOFF_NO_STRUCT) {
+	if (ret == FSBL_HANDOFF_NO_STRUCT || ret == FSBL_HANDOFF_INVAL_STRUCT) {
 		bl31_set_default_config();
 	} else if (ret != FSBL_HANDOFF_SUCCESS) {
 		panic();
diff --git a/plat/xilinx/versal/plat_psci.c b/plat/xilinx/versal/plat_psci.c
index 3955085..fda42df 100644
--- a/plat/xilinx/versal/plat_psci.c
+++ b/plat/xilinx/versal/plat_psci.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -59,7 +59,9 @@
 
 	plat_versal_gic_cpuif_disable();
 
-	plat_versal_gic_save();
+	if (target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE) {
+		plat_versal_gic_save();
+	}
 
 	state = target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE ?
 		PM_STATE_SUSPEND_TO_RAM : PM_STATE_CPU_IDLE;
@@ -99,11 +101,9 @@
 	/* APU was turned off, so restore GIC context */
 	if (target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE) {
 		plat_versal_gic_resume();
-		plat_versal_gic_cpuif_enable();
-	} else {
-		plat_versal_gic_cpuif_enable();
-		plat_versal_gic_pcpu_init();
 	}
+
+	plat_versal_gic_cpuif_enable();
 }
 
 void versal_pwr_domain_on_finish(const psci_power_state_t *target_state)
diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.c b/plat/xilinx/versal/pm_service/pm_api_sys.c
index dbe94e6..eae881e 100644
--- a/plat/xilinx/versal/pm_service/pm_api_sys.c
+++ b/plat/xilinx/versal/pm_service/pm_api_sys.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, Xilinx, Inc. All rights reserved.
+ * Copyright (c) 2019-2020, Xilinx, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -14,6 +14,7 @@
 #include <plat/common/platform.h>
 #include "pm_api_sys.h"
 #include "pm_client.h"
+#include "pm_defs.h"
 
 /*********************************************************************
  * Target module IDs macros
@@ -84,6 +85,22 @@
 }
 
 /**
+ * pm_init_finalize() - Call to notify PMC PM firmware that master has power
+ *			management enabled and that it has finished its
+ *			initialization
+ *
+ * @return	Status returned by the PMU firmware
+ */
+enum pm_ret_status pm_init_finalize(void)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	/* Send request to the PMU */
+	PM_PACK_PAYLOAD1(payload, LIBPM_MODULE_ID, PM_INIT_FINALIZE);
+	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+}
+
+/**
  * pm_self_suspend() - PM call for processor to suspend itself
  * @nid		Node id of the processor or subsystem
  * @latency	Requested maximum wakeup latency (not supported)
@@ -554,6 +571,22 @@
 
 	return pm_ipi_send_sync(primary_proc, payload, parent, 1);
 }
+/**
+ * pm_clock_get_rate() - Get the rate value for the clock
+ * @clk_id	Clock ID
+ * @rate:	Buffer to store clock rate value
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_clock_get_rate(uint32_t clk_id, uint32_t *clk_rate)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	/* Send request to the PMC */
+	PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, PM_CLOCK_GETRATE, clk_id);
+
+	return pm_ipi_send_sync(primary_proc, payload, clk_rate, 2);
+}
 
 /**
  * pm_pll_set_param() - Set PLL parameter
@@ -689,12 +722,31 @@
 enum pm_ret_status pm_query_data(uint32_t qid, uint32_t arg1, uint32_t arg2,
 				 uint32_t arg3, uint32_t *data)
 {
+	uint32_t ret;
+	uint32_t version;
 	uint32_t payload[PAYLOAD_ARG_CNT];
+	uint32_t fw_api_version;
 
 	/* Send request to the PMC */
 	PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, PM_QUERY_DATA, qid, arg1,
 			 arg2, arg3);
-	return pm_ipi_send_sync(primary_proc, payload, data, 4);
+
+	ret = pm_feature_check(PM_QUERY_DATA, &version);
+	if (PM_RET_SUCCESS == ret) {
+		fw_api_version = version & 0xFFFF ;
+		if ((2U == fw_api_version) &&
+		    ((XPM_QID_CLOCK_GET_NAME == qid) ||
+		     (XPM_QID_PINCTRL_GET_FUNCTION_NAME == qid))) {
+			ret = pm_ipi_send_sync(primary_proc, payload, data, 8);
+			ret = data[0];
+			data[0] = data[1];
+			data[1] = data[2];
+			data[2] = data[3];
+		} else {
+			ret = pm_ipi_send_sync(primary_proc, payload, data, 4);
+		}
+	}
+	return ret;
 }
 /**
  * pm_api_ioctl() -  PM IOCTL API for device control and configs
@@ -780,7 +832,6 @@
 	switch (api_id) {
 	case PM_GET_CALLBACK_DATA:
 	case PM_GET_TRUSTZONE_VERSION:
-	case PM_INIT_FINALIZE:
 		*version = (PM_API_BASE_VERSION << 16);
 		return PM_RET_SUCCESS;
 	case PM_GET_API_VERSION:
@@ -798,6 +849,7 @@
 	case PM_SET_REQUIREMENT:
 	case PM_RESET_ASSERT:
 	case PM_RESET_GET_STATUS:
+	case PM_GET_CHIPID:
 	case PM_PINCTRL_REQUEST:
 	case PM_PINCTRL_RELEASE:
 	case PM_PINCTRL_GET_FUNCTION:
@@ -805,7 +857,11 @@
 	case PM_PINCTRL_CONFIG_PARAM_GET:
 	case PM_PINCTRL_CONFIG_PARAM_SET:
 	case PM_IOCTL:
+		*version = (PM_API_BASE_VERSION << 16);
+		break;
 	case PM_QUERY_DATA:
+		*version = (PM_API_QUERY_DATA_VERSION << 16);
+		break;
 	case PM_CLOCK_ENABLE:
 	case PM_CLOCK_DISABLE:
 	case PM_CLOCK_GETSTATE:
@@ -813,11 +869,15 @@
 	case PM_CLOCK_GETDIVIDER:
 	case PM_CLOCK_SETPARENT:
 	case PM_CLOCK_GETPARENT:
+	case PM_CLOCK_GETRATE:
 	case PM_PLL_SET_PARAMETER:
 	case PM_PLL_GET_PARAMETER:
 	case PM_PLL_SET_MODE:
 	case PM_PLL_GET_MODE:
 	case PM_FEATURE_CHECK:
+	case PM_INIT_FINALIZE:
+	case PM_SET_MAX_LATENCY:
+	case PM_REGISTER_NOTIFIER:
 		*version = (PM_API_BASE_VERSION << 16);
 		break;
 	case PM_LOAD_PDI:
@@ -883,3 +943,45 @@
 			 device_id, type);
 	return pm_ipi_send_sync(primary_proc, payload, result, 1);
 }
+
+/**
+ * pm_set_max_latency() - PM call to change in the maximum wake-up latency
+ *			  requirements for a specific device currently
+ *			  used by that CPU.
+ * @device_id	Device ID
+ * @latency	Latency value
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_set_max_latency(uint32_t device_id, uint32_t latency)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	/* Send request to the PMC */
+	PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, PM_SET_MAX_LATENCY,
+			 device_id, latency);
+
+	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+}
+
+/**
+ * pm_register_notifier() - PM call to register a subsystem to be notified
+ * 			    about the device event
+ * @device_id	Device ID for the Node to which the event is related
+ * @event	Event in question
+ * @wake	Wake subsystem upon capturing the event if value 1
+ * @enable	Enable the registration for value 1, disable for value 0
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_register_notifier(uint32_t device_id, uint32_t event,
+					uint32_t wake, uint32_t enable)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	/* Send request to the PMC */
+	PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, PM_REGISTER_NOTIFIER,
+			 device_id, event, wake, enable);
+
+	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+}
diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.h b/plat/xilinx/versal/pm_service/pm_api_sys.h
index 4de592a..84867b6 100644
--- a/plat/xilinx/versal/pm_service/pm_api_sys.h
+++ b/plat/xilinx/versal/pm_service/pm_api_sys.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, Xilinx, Inc. All rights reserved.
+ * Copyright (c) 2019-2020, Xilinx, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -15,6 +15,7 @@
  **********************************************************/
 
 enum pm_ret_status pm_get_api_version(unsigned int *version);
+enum pm_ret_status pm_init_finalize(void);
 enum pm_ret_status pm_self_suspend(uint32_t nid,
 				   unsigned int latency,
 				   unsigned int state,
@@ -52,6 +53,7 @@
 enum pm_ret_status pm_clock_get_divider(uint32_t clk_id, uint32_t *divider);
 enum pm_ret_status pm_clock_set_parent(uint32_t clk_id, uint32_t parent);
 enum pm_ret_status pm_clock_get_parent(uint32_t clk_id, uint32_t *parent);
+enum pm_ret_status pm_clock_get_rate(uint32_t clk_id, uint32_t *clk_rate);
 enum pm_ret_status pm_pll_set_param(uint32_t clk_id, uint32_t param,
 				    uint32_t value);
 enum pm_ret_status pm_pll_get_param(uint32_t clk_id, uint32_t param,
@@ -72,4 +74,7 @@
 enum pm_ret_status pm_get_op_characteristic(uint32_t device_id,
 					    enum pm_opchar_type type,
 					    uint32_t *result);
+enum pm_ret_status pm_set_max_latency(uint32_t device_id, uint32_t latency);
+enum pm_ret_status pm_register_notifier(uint32_t device_id, uint32_t event,
+					uint32_t wake, uint32_t enable);
 #endif /* PM_API_SYS_H */
diff --git a/plat/xilinx/versal/pm_service/pm_client.c b/plat/xilinx/versal/pm_service/pm_client.c
index 5b47838..9ab921e 100644
--- a/plat/xilinx/versal/pm_service/pm_client.c
+++ b/plat/xilinx/versal/pm_service/pm_client.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, Xilinx, Inc. All rights reserved.
+ * Copyright (c) 2019-2020, Xilinx, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -113,8 +113,9 @@
 /**
  * pm_client_set_wakeup_sources - Set all devices with enabled interrupts as
  *				  wake sources in the LibPM.
+ * @node_id:	Node id of processor
  */
-static void pm_client_set_wakeup_sources(void)
+static void pm_client_set_wakeup_sources(uint32_t node_id)
 {
 	uint32_t reg_num;
 	uint32_t device_id;
@@ -147,7 +148,7 @@
 			    (!pm_wakeup_nodes_set[node_idx])) {
 				/* Get device ID from node index */
 				device_id = PERIPH_DEVID(node_idx);
-				ret = pm_set_wakeup_source(XPM_DEVID_ACPU_0,
+				ret = pm_set_wakeup_source(node_id,
 							   device_id, 1);
 				pm_wakeup_nodes_set[node_idx] = !ret;
 			}
@@ -167,7 +168,7 @@
 	bakery_lock_get(&pm_client_secure_lock);
 
 	if (state == PM_STATE_SUSPEND_TO_RAM)
-		pm_client_set_wakeup_sources();
+		pm_client_set_wakeup_sources(proc->node_id);
 
 	/* Set powerdown request */
 	mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) |
diff --git a/plat/xilinx/versal/pm_service/pm_defs.h b/plat/xilinx/versal/pm_service/pm_defs.h
index 966b00b..793f750 100644
--- a/plat/xilinx/versal/pm_service/pm_defs.h
+++ b/plat/xilinx/versal/pm_service/pm_defs.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, Xilinx, Inc. All rights reserved.
+ * Copyright (c) 2019-2020, Xilinx, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -39,10 +39,13 @@
 /* PM API Versions */
 #define PM_API_BASE_VERSION		1U
 
+#define PM_API_QUERY_DATA_VERSION	2U
+
 /* PM API ids */
 #define PM_GET_API_VERSION		1U
 #define PM_GET_DEVICE_STATUS		3U
 #define PM_GET_OP_CHARACTERISTIC	4U
+#define PM_REGISTER_NOTIFIER		5U
 #define PM_REQ_SUSPEND			6U
 #define PM_SELF_SUSPEND			7U
 #define PM_FORCE_POWERDOWN		8U
@@ -53,6 +56,7 @@
 #define PM_REQUEST_DEVICE		13U
 #define PM_RELEASE_DEVICE		14U
 #define PM_SET_REQUIREMENT		15U
+#define PM_SET_MAX_LATENCY		16U
 #define PM_RESET_ASSERT			17U
 #define PM_RESET_GET_STATUS		18U
 #define PM_INIT_FINALIZE		21U
@@ -163,4 +167,25 @@
 	PM_RET_ERROR_TIMEOUT = 2006,
 	PM_RET_ERROR_NODE_USED = 2007
 };
+
+/**
+ * Qids
+ */
+enum pm_query_id {
+	XPM_QID_INVALID,
+	XPM_QID_CLOCK_GET_NAME,
+	XPM_QID_CLOCK_GET_TOPOLOGY,
+	XPM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS,
+	XPM_QID_CLOCK_GET_MUXSOURCES,
+	XPM_QID_CLOCK_GET_ATTRIBUTES,
+	XPM_QID_PINCTRL_GET_NUM_PINS,
+	XPM_QID_PINCTRL_GET_NUM_FUNCTIONS,
+	XPM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS,
+	XPM_QID_PINCTRL_GET_FUNCTION_NAME,
+	XPM_QID_PINCTRL_GET_FUNCTION_GROUPS,
+	XPM_QID_PINCTRL_GET_PIN_GROUPS,
+	XPM_QID_CLOCK_GET_NUM_CLOCKS,
+	XPM_QID_CLOCK_GET_MAX_DIVISOR,
+	XPM_QID_PLD_GET_PARENT,
+};
 #endif /* PM_DEFS_H */
diff --git a/plat/xilinx/versal/pm_service/pm_svc_main.c b/plat/xilinx/versal/pm_service/pm_svc_main.c
index 45b2803..2ed6d27 100644
--- a/plat/xilinx/versal/pm_service/pm_svc_main.c
+++ b/plat/xilinx/versal/pm_service/pm_svc_main.c
@@ -159,7 +159,8 @@
 	}
 
 	case PM_INIT_FINALIZE:
-		SMC_RET1(handle, (uint64_t)PM_RET_SUCCESS);
+		ret = pm_init_finalize();
+		SMC_RET1(handle, (uint64_t)ret);
 
 	case PM_GET_CALLBACK_DATA:
 	{
@@ -214,14 +215,15 @@
 
 	case PM_QUERY_DATA:
 	{
-		uint32_t data[4] = { 0 };
+		uint32_t data[8] = { 0 };
 
 		ret = pm_query_data(pm_arg[0], pm_arg[1], pm_arg[2],
-			      pm_arg[3], data);
+				      pm_arg[3], data);
+
 		SMC_RET2(handle, (uint64_t)ret  | ((uint64_t)data[0] << 32),
-			 (uint64_t)data[1] | ((uint64_t)data[2] << 32));
-	}
+				 (uint64_t)data[1] | ((uint64_t)data[2] << 32));
 
+	}
 	case PM_CLOCK_ENABLE:
 		ret = pm_clock_enable(pm_arg[0]);
 		SMC_RET1(handle, (uint64_t)ret);
@@ -262,6 +264,15 @@
 		SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
 	}
 
+	case PM_CLOCK_GETRATE:
+	{
+		uint32_t rate[2] = { 0 };
+
+		ret = pm_clock_get_rate(pm_arg[0], rate);
+		SMC_RET2(handle, (uint64_t)ret | ((uint64_t)rate[0] << 32),
+			 rate[1]);
+	}
+
 	case PM_PLL_SET_PARAMETER:
 		ret = pm_pll_set_param(pm_arg[0], pm_arg[1], pm_arg[2]);
 		SMC_RET1(handle, (uint64_t)ret);
@@ -321,6 +332,18 @@
 		SMC_RET1(handle, (uint64_t)ret | ((uint64_t)result << 32));
 	}
 
+	case PM_SET_MAX_LATENCY:
+	{
+		ret = pm_set_max_latency(pm_arg[0], pm_arg[1]);
+		SMC_RET1(handle, (uint64_t)ret);
+	}
+
+	case PM_REGISTER_NOTIFIER:
+	{
+		ret = pm_register_notifier(pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3]);
+		SMC_RET1(handle, (uint64_t)ret);
+	}
+
 	default:
 		WARN("Unimplemented PM Service Call: 0x%x\n", smc_fid);
 		SMC_RET1(handle, SMC_UNK);
diff --git a/plat/xilinx/zynqmp/bl31_zynqmp_setup.c b/plat/xilinx/zynqmp/bl31_zynqmp_setup.c
index b6d8770..8272d62 100644
--- a/plat/xilinx/zynqmp/bl31_zynqmp_setup.c
+++ b/plat/xilinx/zynqmp/bl31_zynqmp_setup.c
@@ -104,9 +104,12 @@
 		else if (ret != FSBL_HANDOFF_SUCCESS)
 			panic();
 	}
-
-	NOTICE("BL31: Secure code at 0x%lx\n", bl32_image_ep_info.pc);
-	NOTICE("BL31: Non secure code at 0x%lx\n", bl33_image_ep_info.pc);
+	if (bl32_image_ep_info.pc) {
+		VERBOSE("BL31: Secure code at 0x%lx\n", bl32_image_ep_info.pc);
+	}
+	if (bl33_image_ep_info.pc) {
+		VERBOSE("BL31: Non secure code at 0x%lx\n", bl33_image_ep_info.pc);
+	}
 }
 
 /* Enable the test setup */
diff --git a/plat/xilinx/zynqmp/include/zynqmp_def.h b/plat/xilinx/zynqmp/include/zynqmp_def.h
index 5e7254e..b492210 100644
--- a/plat/xilinx/zynqmp/include/zynqmp_def.h
+++ b/plat/xilinx/zynqmp/include/zynqmp_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -341,12 +341,19 @@
 #define PGGS_BASEADDR		(0xFFD80050U)
 #define PGGS_NUM_REGS		U(4)
 
-/* Warm restart boot health status register and mask */
-#define PM_BOOT_HEALTH_STATUS_REG		(GGS_BASEADDR + U(0x10))
+/* PMU GGS4 register 4 is used for warm restart boot health status */
+#define PMU_GLOBAL_GEN_STORAGE4			(GGS_BASEADDR + 0x10)
+/* Warm restart boot health status mask */
 #define PM_BOOT_HEALTH_STATUS_MASK		U(0x01)
 
 /*AFI registers */
 #define  AFIFM6_WRCTRL		U(13)
 #define  FABRIC_WIDTH		U(3)
 
+/* CSUDMA Module Base Address*/
+#define CSUDMA_BASE		0xFFC80000
+
+/* RSA-CORE Module Base Address*/
+#define RSA_CORE_BASE		0xFFCE0000
+
 #endif /* ZYNQMP_DEF_H */
diff --git a/plat/xilinx/zynqmp/platform.mk b/plat/xilinx/zynqmp/platform.mk
index 44f20f6..1cd168f 100644
--- a/plat/xilinx/zynqmp/platform.mk
+++ b/plat/xilinx/zynqmp/platform.mk
@@ -59,13 +59,14 @@
 				-Iplat/xilinx/zynqmp/include/			\
 				-Iplat/xilinx/zynqmp/pm_service/		\
 
+# Include GICv2 driver files
+include drivers/arm/gic/v2/gicv2.mk
+
 PLAT_BL_COMMON_SOURCES	:=	lib/xlat_tables/xlat_tables_common.c		\
 				lib/xlat_tables/aarch64/xlat_tables.c		\
 				drivers/delay_timer/delay_timer.c		\
 				drivers/delay_timer/generic_delay_timer.c	\
-				drivers/arm/gic/common/gic_common.c		\
-				drivers/arm/gic/v2/gicv2_main.c			\
-				drivers/arm/gic/v2/gicv2_helpers.c		\
+				${GICV2_SOURCES}				\
 				drivers/cadence/uart/aarch64/cdns_console.S	\
 				plat/arm/common/arm_cci.c			\
 				plat/arm/common/arm_common.c			\
@@ -95,6 +96,8 @@
 				plat/xilinx/zynqmp/pm_service/pm_api_clock.c	\
 				plat/xilinx/zynqmp/pm_service/pm_client.c
 
+BL31_CPPFLAGS		+=	-fno-jump-tables
+
 ifneq (${RESET_TO_BL31},1)
   $(error "Using BL31 as the reset vector is only one option supported on ZynqMP. Please set RESET_TO_BL31 to 1.")
 endif
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_clock.c b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c
index 852f927..0cc517e 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_clock.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -129,12 +129,26 @@
 		.div = NA_DIV,				\
 	}
 
-#define GENERIC_DIV(id)						\
+#define GENERIC_DIV1						\
 	{							\
-		.type = TYPE_DIV##id,				\
-		.offset = PERIPH_DIV##id##_SHIFT,		\
-		.width = PERIPH_DIV##id##_WIDTH,		\
+		.type = TYPE_DIV1,				\
+		.offset = PERIPH_DIV1_SHIFT,			\
+		.width = PERIPH_DIV1_WIDTH,			\
+		.clkflags = CLK_SET_RATE_NO_REPARENT |		\
+			    CLK_IS_BASIC,			\
+		.typeflags = CLK_DIVIDER_ONE_BASED |		\
+			     CLK_DIVIDER_ALLOW_ZERO,		\
+		.mult = NA_MULT,				\
+		.div = NA_DIV,					\
+	}
+
+#define GENERIC_DIV2						\
+	{							\
+		.type = TYPE_DIV2,				\
+		.offset = PERIPH_DIV2_SHIFT,			\
+		.width = PERIPH_DIV2_WIDTH,			\
 		.clkflags = CLK_SET_RATE_NO_REPARENT |		\
+			    CLK_SET_RATE_PARENT |		\
 			    CLK_IS_BASIC,			\
 		.typeflags = CLK_DIVIDER_ONE_BASED |		\
 			     CLK_DIVIDER_ALLOW_ZERO,		\
@@ -340,25 +354,25 @@
 
 static struct pm_clock_node generic_mux_div_nodes[] = {
 	GENERIC_MUX,
-	GENERIC_DIV(1),
+	GENERIC_DIV1,
 };
 
 static struct pm_clock_node generic_mux_div_gate_nodes[] = {
 	GENERIC_MUX,
-	GENERIC_DIV(1),
+	GENERIC_DIV1,
 	GENERIC_GATE,
 };
 
 static struct pm_clock_node generic_mux_div_unused_gate_nodes[] = {
 	GENERIC_MUX,
-	GENERIC_DIV(1),
+	GENERIC_DIV1,
 	IGNORE_UNUSED_GATE,
 };
 
 static struct pm_clock_node generic_mux_div_div_gate_nodes[] = {
 	GENERIC_MUX,
-	GENERIC_DIV(1),
-	GENERIC_DIV(2),
+	GENERIC_DIV1,
+	GENERIC_DIV2,
 	GENERIC_GATE,
 };
 
@@ -410,8 +424,8 @@
 
 static struct pm_clock_node usb_nodes[] = {
 	GENERIC_MUX,
-	GENERIC_DIV(1),
-	GENERIC_DIV(2),
+	GENERIC_DIV1,
+	GENERIC_DIV2,
 	{
 		.type = TYPE_GATE,
 		.offset = USB_GATE_SHIFT,
@@ -2432,10 +2446,11 @@
  *
  * @return	Returns success. In case of error, name data is 0.
  */
-enum pm_ret_status pm_api_clock_get_name(unsigned int clock_id, char *name)
+void pm_api_clock_get_name(unsigned int clock_id, char *name)
 {
 	if (clock_id == CLK_MAX)
-		memcpy(name, END_OF_CLK, CLK_NAME_LEN);
+		memcpy(name, END_OF_CLK, sizeof(END_OF_CLK) > CLK_NAME_LEN ?
+					 CLK_NAME_LEN : sizeof(END_OF_CLK));
 	else if (!pm_clock_valid(clock_id))
 		memset(name, 0, CLK_NAME_LEN);
 	else if (clock_id < CLK_MAX_OUTPUT_CLK)
@@ -2443,8 +2458,6 @@
 	else
 		memcpy(name, ext_clocks[clock_id - CLK_MAX_OUTPUT_CLK].name,
 		       CLK_NAME_LEN);
-
-	return PM_RET_SUCCESS;
 }
 
 /**
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_clock.h b/plat/xilinx/zynqmp/pm_service/pm_api_clock.h
index 301ed24..5efd63f 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_clock.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_clock.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -294,7 +294,7 @@
 struct pm_pll *pm_clock_get_pll_by_related_clk(enum clock_id clock_id);
 uint8_t pm_clock_has_div(unsigned int clock_id, enum pm_clock_div_id div_id);
 
-enum pm_ret_status pm_api_clock_get_name(unsigned int clock_id, char *name);
+void pm_api_clock_get_name(unsigned int clock_id, char *name);
 enum pm_ret_status pm_api_clock_get_num_clocks(unsigned int *nclocks);
 enum pm_ret_status pm_api_clock_get_topology(unsigned int clock_id,
 					     unsigned int index,
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c
index 9f3acaa..f165fb0 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -595,7 +595,7 @@
  */
 static enum pm_ret_status pm_ioctl_set_boot_health_status(unsigned int value)
 {
-	return pm_mmio_write(PM_BOOT_HEALTH_STATUS_REG,
+	return pm_mmio_write(PMU_GLOBAL_GEN_STORAGE4,
 			     PM_BOOT_HEALTH_STATUS_MASK, value);
 }
 
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c b/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c
index 4b8dfb6..9a6b497 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c
@@ -19,39 +19,6 @@
 #include "pm_common.h"
 #include "pm_ipi.h"
 
-#define PINCTRL_FUNCTION_MASK			U(0xFE)
-#define PINCTRL_VOLTAGE_STATUS_MASK		U(0x01)
-#define NFUNCS_PER_PIN				U(13)
-#define PINCTRL_NUM_MIOS			U(78)
-#define MAX_PIN_PER_REG				U(26)
-#define PINCTRL_BANK_ADDR_STEP			U(28)
-
-#define PINCTRL_DRVSTRN0_REG_OFFSET		U(0)
-#define PINCTRL_DRVSTRN1_REG_OFFSET		U(4)
-#define PINCTRL_SCHCMOS_REG_OFFSET		U(8)
-#define PINCTRL_PULLCTRL_REG_OFFSET		U(12)
-#define PINCTRL_PULLSTAT_REG_OFFSET		U(16)
-#define PINCTRL_SLEWCTRL_REG_OFFSET		U(20)
-#define PINCTRL_VOLTAGE_STAT_REG_OFFSET		U(24)
-
-#define IOU_SLCR_BANK1_CTRL5			U(0XFF180164)
-
-#define PINCTRL_CFG_ADDR_OFFSET(addr, reg, miopin)			\
-	((addr) + 4 * PINCTRL_NUM_MIOS + PINCTRL_BANK_ADDR_STEP *	\
-	((miopin) / MAX_PIN_PER_REG) + (reg))
-
-#define PINCTRL_PIN_OFFSET(_miopin) \
-	((_miopin) - (MAX_PIN_PER_REG * ((_miopin) / MAX_PIN_PER_REG)))
-
-#define PINCTRL_REGVAL_TO_PIN_CONFIG(_pin, _val)			\
-	(((_val) >> PINCTRL_PIN_OFFSET(_pin)) & 0x1)
-
-static uint8_t pm_pinctrl_mux[NFUNCS_PER_PIN] = {
-	0x02, 0x04, 0x08, 0x10, 0x18,
-	0x00, 0x20, 0x40, 0x60, 0x80,
-	0xA0, 0xC0, 0xE0
-};
-
 struct pinctrl_function {
 	char name[FUNCTION_NAME_LEN];
 	uint16_t (*groups)[];
@@ -2604,18 +2571,13 @@
  *
  * This function is used by master to get name of function specified
  * by given function ID.
- *
- * @return	Returns success. In case of error, name data is 0.
  */
-enum pm_ret_status pm_api_pinctrl_get_function_name(unsigned int fid,
-						    char *name)
+void pm_api_pinctrl_get_function_name(unsigned int fid, char *name)
 {
 	if (fid >= MAX_FUNCTION)
 		memcpy(name, END_OF_FUNCTION, FUNCTION_NAME_LEN);
 	else
 		memcpy(name, pinctrl_functions[fid].name, FUNCTION_NAME_LEN);
-
-	return PM_RET_SUCCESS;
 }
 
 /**
@@ -2709,333 +2671,6 @@
 		groups[i] = grps[index + i];
 		if (groups[i] == (uint16_t)END_OF_GROUPS)
 			break;
-	}
-
-	return PM_RET_SUCCESS;
-}
-
-/**
- * pm_api_pinctrl_get_function() - Read function id set for the given pin
- * @pin		Pin number
- * @nid		Node ID of function currently set for given pin
- *
- * This function provides the function currently set for the given pin.
- *
- * @return	Returns status, either success or error+reason
- */
-enum pm_ret_status pm_api_pinctrl_get_function(unsigned int pin,
-					       unsigned int *id)
-{
-	unsigned int i = 0, j = 0;
-	enum pm_ret_status ret = PM_RET_SUCCESS;
-	unsigned int ctrlreg, val, gid;
-	uint16_t *grps;
-
-	ctrlreg = IOU_SLCR_BASEADDR + 4U * pin;
-	ret = pm_mmio_read(ctrlreg, &val);
-	if (ret != PM_RET_SUCCESS)
-		return ret;
-
-	val &= PINCTRL_FUNCTION_MASK;
-
-	for (i = 0; i < NFUNCS_PER_PIN; i++)
-		if (val == pm_pinctrl_mux[i])
-			break;
-
-	if (i == NFUNCS_PER_PIN)
-		return PM_RET_ERROR_NOTSUPPORTED;
-
-	gid = *(*zynqmp_pin_groups[pin].groups + i);
-
-	for (i = 0; i < MAX_FUNCTION; i++) {
-		grps = *pinctrl_functions[i].groups;
-		if (grps == NULL)
-			continue;
-		if (val != pinctrl_functions[i].regval)
-			continue;
-
-		for (j = 0; grps[j] != (uint16_t)END_OF_GROUPS; j++) {
-			if (gid == grps[j]) {
-				*id = i;
-				goto done;
-			}
-		}
-	}
-	if (i == MAX_FUNCTION)
-		ret = PM_RET_ERROR_ARGS;
-done:
-	return ret;
-}
-
-/**
- * pm_api_pinctrl_set_function() - Set function id set for the given pin
- * @pin		Pin number
- * @nid		Node ID of function to set for given pin
- *
- * This function provides the function currently set for the given pin.
- *
- * @return	Returns status, either success or error+reason
- */
-enum pm_ret_status pm_api_pinctrl_set_function(unsigned int pin,
-					       unsigned int fid)
-{
-	int i, j;
-	unsigned int ctrlreg, val;
-	uint16_t *pgrps, *fgrps;
-
-	ctrlreg = IOU_SLCR_BASEADDR + 4U * pin;
-	val = pinctrl_functions[fid].regval;
-
-	for (i = 0; i < NFUNCS_PER_PIN; i++)
-		if (val == pm_pinctrl_mux[i])
-			break;
-
-	if (i == NFUNCS_PER_PIN)
-		return PM_RET_ERROR_NOTSUPPORTED;
-
-	pgrps = *zynqmp_pin_groups[pin].groups;
-	if (!pgrps)
-		return PM_RET_ERROR_NOTSUPPORTED;
-
-	fgrps = *pinctrl_functions[fid].groups;
-	if (!fgrps)
-		return PM_RET_ERROR_NOTSUPPORTED;
-
-	for (i = 0; fgrps[i] != (uint16_t)END_OF_GROUPS; i++)
-		for (j = 0; pgrps[j] != (uint16_t)END_OF_GROUPS; j++)
-			if (fgrps[i] == pgrps[j])
-				goto match;
-
-	return PM_RET_ERROR_NOTSUPPORTED;
-
-match:
-	return pm_mmio_write(ctrlreg, PINCTRL_FUNCTION_MASK, val);
-}
-
-/**
- * pm_api_pinctrl_set_config() - Set configuration parameter for given pin
- * @pin: Pin for which configuration is to be set
- * @param: Configuration parameter to be set
- * @value: Value to be set for configuration parameter
- *
- * This function sets value of requested configuration parameter for given pin.
- *
- * @return	Returns status, either success or error+reason
- */
-enum pm_ret_status pm_api_pinctrl_set_config(unsigned int pin,
-					     unsigned int param,
-					     unsigned int value)
-{
-	enum pm_ret_status ret;
-	unsigned int ctrlreg, mask, val, offset;
-
-	if (param >= PINCTRL_CONFIG_MAX)
-		return PM_RET_ERROR_NOTSUPPORTED;
-
-	if (pin >=  PINCTRL_NUM_MIOS)
-		return PM_RET_ERROR_ARGS;
-
-	mask = 1 << PINCTRL_PIN_OFFSET(pin);
-
-	switch (param) {
-	case PINCTRL_CONFIG_SLEW_RATE:
-		if (value != PINCTRL_SLEW_RATE_FAST &&
-		    value != PINCTRL_SLEW_RATE_SLOW)
-			return PM_RET_ERROR_ARGS;
-
-		ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
-					      PINCTRL_SLEWCTRL_REG_OFFSET,
-					      pin);
-		val = value << PINCTRL_PIN_OFFSET(pin);
-		ret = pm_mmio_write(ctrlreg, mask, val);
-		break;
-	case PINCTRL_CONFIG_BIAS_STATUS:
-		if (value != PINCTRL_BIAS_ENABLE &&
-		    value != PINCTRL_BIAS_DISABLE)
-			return PM_RET_ERROR_ARGS;
-
-		ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
-					      PINCTRL_PULLSTAT_REG_OFFSET,
-					      pin);
-
-		offset = PINCTRL_PIN_OFFSET(pin);
-		if (ctrlreg == IOU_SLCR_BANK1_CTRL5)
-			offset = (offset < 12U) ?
-					(offset + 14U) : (offset - 12U);
-
-		val = value << offset;
-		mask = 1 << offset;
-		ret = pm_mmio_write(ctrlreg, mask, val);
-		break;
-	case PINCTRL_CONFIG_PULL_CTRL:
-
-		if (value != PINCTRL_BIAS_PULL_DOWN &&
-		    value != PINCTRL_BIAS_PULL_UP)
-			return PM_RET_ERROR_ARGS;
-
-		ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
-					      PINCTRL_PULLSTAT_REG_OFFSET,
-					      pin);
-
-		offset = PINCTRL_PIN_OFFSET(pin);
-		if (ctrlreg == IOU_SLCR_BANK1_CTRL5)
-			offset = (offset < 12U) ?
-					(offset + 14U) : (offset - 12U);
-
-		val = PINCTRL_BIAS_ENABLE << offset;
-		ret = pm_mmio_write(ctrlreg, 1 << offset, val);
-		if (ret != PM_RET_SUCCESS)
-			return ret;
-
-		ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
-					      PINCTRL_PULLCTRL_REG_OFFSET,
-					      pin);
-		val = value << PINCTRL_PIN_OFFSET(pin);
-		ret = pm_mmio_write(ctrlreg, mask, val);
-		break;
-	case PINCTRL_CONFIG_SCHMITT_CMOS:
-		if (value != PINCTRL_INPUT_TYPE_CMOS &&
-		    value != PINCTRL_INPUT_TYPE_SCHMITT)
-			return PM_RET_ERROR_ARGS;
-
-		ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
-					      PINCTRL_SCHCMOS_REG_OFFSET,
-					      pin);
-
-		val = value << PINCTRL_PIN_OFFSET(pin);
-		ret = pm_mmio_write(ctrlreg, mask, val);
-		break;
-	case PINCTRL_CONFIG_DRIVE_STRENGTH:
-		if (value > PINCTRL_DRIVE_STRENGTH_12MA)
-			return PM_RET_ERROR_ARGS;
-
-		ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
-					      PINCTRL_DRVSTRN0_REG_OFFSET,
-					      pin);
-		val = (value >> 1) << PINCTRL_PIN_OFFSET(pin);
-		ret = pm_mmio_write(ctrlreg, mask, val);
-		if (ret)
-			return ret;
-
-		ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
-					      PINCTRL_DRVSTRN1_REG_OFFSET,
-					      pin);
-		val = (value & 0x01U) << PINCTRL_PIN_OFFSET(pin);
-		ret = pm_mmio_write(ctrlreg, mask, val);
-		break;
-	default:
-		ERROR("Invalid parameter %u\n", param);
-		ret = PM_RET_ERROR_NOTSUPPORTED;
-		break;
-	}
-
-	return ret;
-}
-
-/**
- * pm_api_pinctrl_get_config() - Get configuration parameter value for given pin
- * @pin: Pin for which configuration is to be read
- * @param: Configuration parameter to be read
- * @value: buffer to store value of configuration parameter
- *
- * This function reads value of requested configuration parameter for given pin.
- *
- * @return	Returns status, either success or error+reason
- */
-enum pm_ret_status pm_api_pinctrl_get_config(unsigned int pin,
-					     unsigned int param,
-					     unsigned int *value)
-{
-	enum pm_ret_status ret;
-	unsigned int ctrlreg, val;
-
-	if (param >= PINCTRL_CONFIG_MAX)
-		return PM_RET_ERROR_NOTSUPPORTED;
-
-	if (pin >=  PINCTRL_NUM_MIOS)
-		return PM_RET_ERROR_ARGS;
-
-	switch (param) {
-	case PINCTRL_CONFIG_SLEW_RATE:
-		ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
-					      PINCTRL_SLEWCTRL_REG_OFFSET,
-					      pin);
-
-		ret = pm_mmio_read(ctrlreg, &val);
-		if (ret != PM_RET_SUCCESS)
-			return ret;
-
-		*value = PINCTRL_REGVAL_TO_PIN_CONFIG(pin, val);
-		break;
-	case PINCTRL_CONFIG_BIAS_STATUS:
-		ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
-					      PINCTRL_PULLSTAT_REG_OFFSET,
-					      pin);
-
-		ret = pm_mmio_read(ctrlreg, &val);
-		if (ret)
-			return ret;
-
-		if (ctrlreg == IOU_SLCR_BANK1_CTRL5)
-			val = ((val & 0x3FFF) << 12) | ((val >> 14) & 0xFFF);
-
-		*value = PINCTRL_REGVAL_TO_PIN_CONFIG(pin, val);
-		break;
-	case PINCTRL_CONFIG_PULL_CTRL:
-
-		ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
-					      PINCTRL_PULLCTRL_REG_OFFSET,
-					      pin);
-
-		ret = pm_mmio_read(ctrlreg, &val);
-		if (ret)
-			return ret;
-
-		*value = PINCTRL_REGVAL_TO_PIN_CONFIG(pin, val);
-		break;
-	case PINCTRL_CONFIG_SCHMITT_CMOS:
-		ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
-					      PINCTRL_SCHCMOS_REG_OFFSET,
-					      pin);
-
-		ret = pm_mmio_read(ctrlreg, &val);
-		if (ret)
-			return ret;
-
-		*value = PINCTRL_REGVAL_TO_PIN_CONFIG(pin, val);
-		break;
-	case PINCTRL_CONFIG_DRIVE_STRENGTH:
-		ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
-					      PINCTRL_DRVSTRN0_REG_OFFSET,
-					      pin);
-		ret = pm_mmio_read(ctrlreg, &val);
-		if (ret)
-			return ret;
-
-		*value = PINCTRL_REGVAL_TO_PIN_CONFIG(pin, val) << 1;
-
-		ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
-					      PINCTRL_DRVSTRN1_REG_OFFSET,
-					      pin);
-		ret = pm_mmio_read(ctrlreg, &val);
-		if (ret)
-			return ret;
-
-		*value |= PINCTRL_REGVAL_TO_PIN_CONFIG(pin, val);
-		break;
-	case PINCTRL_CONFIG_VOLTAGE_STATUS:
-		ctrlreg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
-					      PINCTRL_VOLTAGE_STAT_REG_OFFSET,
-					      pin);
-
-		ret = pm_mmio_read(ctrlreg, &val);
-		if (ret)
-			return ret;
-
-		*value = val & PINCTRL_VOLTAGE_STATUS_MASK;
-		break;
-	default:
-		return PM_RET_ERROR_NOTSUPPORTED;
 	}
 
 	return PM_RET_SUCCESS;
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.h b/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.h
index 9923c00..2b8fca3 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -709,18 +709,7 @@
 #define	PINCTRL_DRIVE_STRENGTH_8MA 2U
 #define	PINCTRL_DRIVE_STRENGTH_12MA 3U
 
-enum pm_ret_status pm_api_pinctrl_set_function(unsigned int pin,
-					       unsigned int fid);
-enum pm_ret_status pm_api_pinctrl_get_function(unsigned int pin,
-					       unsigned int *id);
-enum pm_ret_status pm_api_pinctrl_set_config(unsigned int pin,
-					     unsigned int param,
-					     unsigned int value);
-enum pm_ret_status pm_api_pinctrl_get_config(unsigned int pin,
-					     unsigned int param,
-					     unsigned int *value);
-enum pm_ret_status pm_api_pinctrl_get_function_name(unsigned int fid,
-						    char *name);
+void pm_api_pinctrl_get_function_name(unsigned int fid, char *name);
 enum pm_ret_status pm_api_pinctrl_get_function_groups(unsigned int fid,
 						      unsigned int index,
 						      uint16_t *groups);
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
index b1720d9..9a53408 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
@@ -65,6 +65,10 @@
 	PM_PACK_PAYLOAD5(pl, arg0, arg1, arg2, arg3, arg4);		\
 }
 
+#define EM_PACK_PAYLOAD1(pl, arg0) {	\
+	pl[0] = (uint16_t)(0xE) << 16 | (uint16_t)arg0;	\
+}
+
 /**
  * pm_self_suspend() - PM call for processor to suspend itself
  * @nid		Node id of the processor or subsystem
@@ -655,7 +659,11 @@
  */
 enum pm_ret_status pm_pinctrl_request(unsigned int pin)
 {
-	return PM_RET_SUCCESS;
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	/* Send request to the PMU */
+	PM_PACK_PAYLOAD2(payload, PM_PINCTRL_REQUEST, pin);
+	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
 }
 
 /**
@@ -668,37 +676,44 @@
  */
 enum pm_ret_status pm_pinctrl_release(unsigned int pin)
 {
-	return PM_RET_SUCCESS;
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	/* Send request to the PMU */
+	PM_PACK_PAYLOAD2(payload, PM_PINCTRL_RELEASE, pin);
+	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
 }
 
 /**
  * pm_pinctrl_get_function() - Read function id set for the given pin
  * @pin		Pin number
- * @nid		Node ID of function currently set for given pin
+ * @fid		ID of function currently set for given pin
  *
  * This function provides the function currently set for the given pin.
  *
  * @return	Returns status, either success or error+reason
  */
-enum pm_ret_status pm_pinctrl_get_function(unsigned int pin,
-					   enum pm_node_id *nid)
+enum pm_ret_status pm_pinctrl_get_function(unsigned int pin, unsigned int *fid)
 {
-	return pm_api_pinctrl_get_function(pin, nid);
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	PM_PACK_PAYLOAD2(payload, PM_PINCTRL_GET_FUNCTION, pin);
+	return pm_ipi_send_sync(primary_proc, payload, fid, 1);
 }
 
 /**
  * pm_pinctrl_set_function() - Set function id set for the given pin
  * @pin		Pin number
- * @nid		Node ID of function to set for given pin
- *
- * This function provides the function currently set for the given pin.
+ * @fid		ID of function to set for given pin
  *
  * @return	Returns status, either success or error+reason
  */
-enum pm_ret_status pm_pinctrl_set_function(unsigned int pin,
-					   enum pm_node_id nid)
+enum pm_ret_status pm_pinctrl_set_function(unsigned int pin, unsigned int fid)
 {
-	return pm_api_pinctrl_set_function(pin, (unsigned int)nid);
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	/* Send request to the PMU */
+	PM_PACK_PAYLOAD3(payload, PM_PINCTRL_SET_FUNCTION, pin, fid);
+	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
 }
 
 /**
@@ -715,24 +730,30 @@
 					 unsigned int param,
 					 unsigned int *value)
 {
-	return pm_api_pinctrl_get_config(pin, param, value);
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	PM_PACK_PAYLOAD3(payload, PM_PINCTRL_CONFIG_PARAM_GET, pin, param);
+	return pm_ipi_send_sync(primary_proc, payload, value, 1);
 }
 
 /**
- * pm_pinctrl_set_config() - Read value of requested config param for given pin
+ * pm_pinctrl_set_config() - Set value of requested config param for given pin
  * @pin		Pin number
  * @param	Parameter to set
  * @value	Parameter value to set
  *
- * This function provides the configuration parameter value for the given pin.
- *
  * @return	Returns status, either success or error+reason
  */
 enum pm_ret_status pm_pinctrl_set_config(unsigned int pin,
 					 unsigned int param,
 					 unsigned int value)
 {
-	return pm_api_pinctrl_set_config(pin, param, value);
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	/* Send request to the PMU */
+	PM_PACK_PAYLOAD4(payload, PM_PINCTRL_CONFIG_PARAM_SET, pin, param,
+			 value);
+	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
 }
 
 /**
@@ -793,12 +814,10 @@
  *
  * This function is used by master to get nmae of clock specified
  * by given clock ID.
- *
- * @return	Returns status, either success or error+reason
  */
-static enum pm_ret_status pm_clock_get_name(unsigned int clock_id, char *name)
+static void pm_clock_get_name(unsigned int clock_id, char *name)
 {
-	return pm_api_clock_get_name(clock_id, name);
+	pm_api_clock_get_name(clock_id, name);
 }
 
 /**
@@ -907,7 +926,13 @@
 
 	/* Send request to the PMU */
 	PM_PACK_PAYLOAD2(payload, api_id, clock_id);
-	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+	status = pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+
+	/* If action fails due to the lack of permissions filter the error */
+	if (status == PM_RET_ERROR_ACCESS)
+		status = PM_RET_SUCCESS;
+
+	return status;
 }
 
 /**
@@ -1229,13 +1254,10 @@
  *
  * This function is used by master to get name of function specified
  * by given function Id
- *
- * Return: Returns status, either success or error+reason.
  */
-static enum pm_ret_status pm_pinctrl_get_function_name(unsigned int fid,
-						       char *name)
+static void pm_pinctrl_get_function_name(unsigned int fid, char *name)
 {
-	return pm_api_pinctrl_get_function_name(fid, name);
+	pm_api_pinctrl_get_function_name(fid, name);
 }
 
 /**
@@ -1295,78 +1317,58 @@
  * @data	Returned output data
  *
  * This function returns requested data.
- *
- * @return	Returns status, either success or error+reason
  */
-enum pm_ret_status pm_query_data(enum pm_query_id qid,
-				 unsigned int arg1,
-				 unsigned int arg2,
-				 unsigned int arg3,
-				 unsigned int *data)
+void pm_query_data(enum pm_query_id qid, unsigned int arg1, unsigned int arg2,
+		   unsigned int arg3, unsigned int *data)
 {
-	enum pm_ret_status ret;
-
 	switch (qid) {
 	case PM_QID_CLOCK_GET_NAME:
-		ret = pm_clock_get_name(arg1, (char *)data);
+		pm_clock_get_name(arg1, (char *)data);
 		break;
 	case PM_QID_CLOCK_GET_TOPOLOGY:
-		ret = pm_clock_get_topology(arg1, arg2, &data[1]);
-		data[0] = (unsigned int)ret;
+		data[0] = pm_clock_get_topology(arg1, arg2, &data[1]);
 		break;
 	case PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS:
-		ret = pm_clock_get_fixedfactor_params(arg1, &data[1], &data[2]);
-		data[0] = (unsigned int)ret;
+		data[0] = pm_clock_get_fixedfactor_params(arg1, &data[1],
+							  &data[2]);
 		break;
 	case PM_QID_CLOCK_GET_PARENTS:
-		ret = pm_clock_get_parents(arg1, arg2, &data[1]);
-		data[0] = (unsigned int)ret;
+		data[0] = pm_clock_get_parents(arg1, arg2, &data[1]);
 		break;
 	case PM_QID_CLOCK_GET_ATTRIBUTES:
-		ret = pm_clock_get_attributes(arg1, &data[1]);
-		data[0] = (unsigned int)ret;
+		data[0] = pm_clock_get_attributes(arg1, &data[1]);
 		break;
 	case PM_QID_PINCTRL_GET_NUM_PINS:
-		ret = pm_pinctrl_get_num_pins(&data[1]);
-		data[0] = (unsigned int)ret;
+		data[0] = pm_pinctrl_get_num_pins(&data[1]);
 		break;
 	case PM_QID_PINCTRL_GET_NUM_FUNCTIONS:
-		ret = pm_pinctrl_get_num_functions(&data[1]);
-		data[0] = (unsigned int)ret;
+		data[0] = pm_pinctrl_get_num_functions(&data[1]);
 		break;
 	case PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS:
-		ret = pm_pinctrl_get_num_function_groups(arg1, &data[1]);
-		data[0] = (unsigned int)ret;
+		data[0] = pm_pinctrl_get_num_function_groups(arg1, &data[1]);
 		break;
 	case PM_QID_PINCTRL_GET_FUNCTION_NAME:
-		ret = pm_pinctrl_get_function_name(arg1, (char *)data);
+		pm_pinctrl_get_function_name(arg1, (char *)data);
 		break;
 	case PM_QID_PINCTRL_GET_FUNCTION_GROUPS:
-		ret = pm_pinctrl_get_function_groups(arg1, arg2,
-						     (uint16_t *)&data[1]);
-		data[0] = (unsigned int)ret;
+		data[0] = pm_pinctrl_get_function_groups(arg1, arg2,
+							 (uint16_t *)&data[1]);
 		break;
 	case PM_QID_PINCTRL_GET_PIN_GROUPS:
-		ret = pm_pinctrl_get_pin_groups(arg1, arg2,
-						(uint16_t *)&data[1]);
-		data[0] = (unsigned int)ret;
+		data[0] = pm_pinctrl_get_pin_groups(arg1, arg2,
+						    (uint16_t *)&data[1]);
 		break;
 	case PM_QID_CLOCK_GET_NUM_CLOCKS:
-		ret = pm_clock_get_num_clocks(&data[1]);
-		data[0] = (unsigned int)ret;
+		data[0] = pm_clock_get_num_clocks(&data[1]);
 		break;
 
 	case PM_QID_CLOCK_GET_MAX_DIVISOR:
-		ret = pm_clock_get_max_divisor(arg1, arg2, &data[1]);
-		data[0] = (unsigned int)ret;
+		data[0] = pm_clock_get_max_divisor(arg1, arg2, &data[1]);
 		break;
 	default:
-		ret = PM_RET_ERROR_ARGS;
+		data[0] = PM_RET_ERROR_ARGS;
 		WARN("Unimplemented query service call: 0x%x\n", qid);
-		break;
 	}
-
-	return ret;
 }
 
 enum pm_ret_status pm_sha_hash(uint32_t address_high,
@@ -1548,3 +1550,101 @@
 	PM_PACK_PAYLOAD2(payload, PM_PLL_GET_MODE, nid);
 	return pm_ipi_send_sync(primary_proc, payload, mode, 1);
 }
+
+/**
+ * pm_register_access() -  PM API for register read/write access data
+ *
+ * @register_access_id	Register_access_id which says register read/write
+ *
+ * @address		Address of the register to be accessed
+ *
+ * @mask		Mask value to be used while writing value
+ *
+ * @value		Value to be written to register
+ *
+ * @out			Returned output data
+ *
+ * This function returns requested data.
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_register_access(unsigned int register_access_id,
+				      unsigned int address,
+				      unsigned int mask,
+				      unsigned int value,
+				      unsigned int *out)
+{
+	enum pm_ret_status ret;
+
+	if (((ZYNQMP_CSU_BASEADDR & address) != ZYNQMP_CSU_BASEADDR) &&
+			((CSUDMA_BASE & address) != CSUDMA_BASE) &&
+			((RSA_CORE_BASE & address) != RSA_CORE_BASE) &&
+			((PMU_GLOBAL_BASE & address) != PMU_GLOBAL_BASE))
+		return PM_RET_ERROR_ACCESS;
+
+	switch (register_access_id) {
+	case CONFIG_REG_WRITE:
+		ret = pm_mmio_write(address, mask, value);
+		break;
+	case CONFIG_REG_READ:
+		ret = pm_mmio_read(address, out);
+		break;
+	default:
+		ret = PM_RET_ERROR_ARGS;
+		WARN("Unimplemented register_access call\n\r");
+	}
+	return ret;
+}
+
+/**
+ * pm_efuse_access() - To program or read efuse bits.
+ *
+ * This function provides access to the xilskey library to program/read
+ * efuse bits.
+ *
+ * address_low: lower 32-bit Linear memory space address
+ * address_high: higher 32-bit Linear memory space address
+ *
+ * value: Returned output value
+ *
+ * @return  Returns status, either success or error+reason
+ *
+ */
+enum pm_ret_status pm_efuse_access(uint32_t address_high,
+				   uint32_t address_low,
+				   uint32_t *value)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	/* Send request to the PMU */
+	PM_PACK_PAYLOAD3(payload, PM_EFUSE_ACCESS, address_high, address_low);
+
+	return pm_ipi_send_sync(primary_proc, payload, value, 1);
+}
+
+enum pm_ret_status em_set_action(unsigned int *value)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	/* Send request to the PMU */
+	EM_PACK_PAYLOAD1(payload, EM_SET_ACTION);
+	return pm_ipi_send_sync(primary_proc, payload, value, 1);
+}
+
+enum pm_ret_status em_remove_action(unsigned int *value)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	/* Send request to the PMU */
+	EM_PACK_PAYLOAD1(payload, EM_REMOVE_ACTION);
+	return pm_ipi_send_sync(primary_proc, payload, value, 1);
+}
+
+enum pm_ret_status em_send_errors(unsigned int *value)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	/* Send request to the PMU */
+	EM_PACK_PAYLOAD1(payload, EM_SEND_ERRORS);
+	return pm_ipi_send_sync(primary_proc, payload, value, 1);
+}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
index ff66d3f..b0c2652 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
@@ -28,6 +28,11 @@
 	PM_QID_CLOCK_GET_MAX_DIVISOR,
 };
 
+enum pm_register_access_id {
+	CONFIG_REG_WRITE,
+	CONFIG_REG_READ,
+};
+
 /**********************************************************
  * System-level API function declarations
  **********************************************************/
@@ -151,11 +156,8 @@
 				      unsigned int parent_id);
 enum pm_ret_status pm_clock_getparent(unsigned int clock_id,
 				      unsigned int *parent_id);
-enum pm_ret_status pm_query_data(enum pm_query_id qid,
-				 unsigned int arg1,
-				 unsigned int arg2,
-				 unsigned int arg3,
-				 unsigned int *data);
+void pm_query_data(enum pm_query_id qid, unsigned int arg1, unsigned int arg2,
+		   unsigned int arg3, unsigned int *data);
 enum pm_ret_status pm_sha_hash(uint32_t address_high,
 				    uint32_t address_low,
 				    uint32_t size,
@@ -178,6 +180,11 @@
 enum pm_ret_status pm_aes_engine(uint32_t address_high,
 				 uint32_t address_low,
 				 uint32_t  *value);
+enum pm_ret_status pm_register_access(unsigned int register_access_id,
+				      unsigned int address,
+				      unsigned int mask,
+				      unsigned int value,
+				      unsigned int *out);
 
 enum pm_ret_status pm_pll_set_parameter(enum pm_node_id nid,
 				enum pm_pll_param param_id,
@@ -189,5 +196,10 @@
 
 enum pm_ret_status pm_pll_set_mode(enum pm_node_id nid, enum pm_pll_mode mode);
 enum pm_ret_status pm_pll_get_mode(enum pm_node_id nid, enum pm_pll_mode *mode);
+enum pm_ret_status pm_efuse_access(uint32_t address_high,
+				   uint32_t address_low, uint32_t *value);
+enum pm_ret_status em_set_action(unsigned int *value);
+enum pm_ret_status em_remove_action(unsigned int *value);
+enum pm_ret_status em_send_errors(unsigned int *value);
 
 #endif /* PM_API_SYS_H */
diff --git a/plat/xilinx/zynqmp/pm_service/pm_defs.h b/plat/xilinx/zynqmp/pm_service/pm_defs.h
index cae36c9..ee31c92 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_defs.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_defs.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -33,6 +33,7 @@
 #define PM_STATE_CPU_IDLE		0x0U
 #define PM_STATE_SUSPEND_TO_RAM		0xFU
 
+#define EM_FUNID_NUM_MASK    0xF0000U
 /*********************************************************************
  * Enum definitions
  ********************************************************************/
@@ -97,6 +98,9 @@
 	PM_PLL_GET_PARAMETER,
 	PM_PLL_SET_MODE,
 	PM_PLL_GET_MODE,
+	/* PM Register Access API */
+	PM_REGISTER_ACCESS,
+	PM_EFUSE_ACCESS,
 	PM_API_MAX
 };
 
@@ -215,26 +219,29 @@
 
 /**
  * @PM_RET_SUCCESS:		success
- * @PM_RET_ERROR_ARGS:		illegal arguments provided
+ * @PM_RET_ERROR_ARGS:		illegal arguments provided (deprecated)
+ * @PM_RET_ERROR_NOTSUPPORTED:	feature not supported  (deprecated)
+ * @PM_RET_ERROR_INTERNAL:	internal error
+ * @PM_RET_ERROR_CONFLICT:	conflict
  * @PM_RET_ERROR_ACCESS:	access rights violation
+ * @PM_RET_ERROR_INVALID_NODE:	invalid node
+ * @PM_RET_ERROR_DOUBLE_REQ:	duplicate request for same node
+ * @PM_RET_ERROR_ABORT_SUSPEND:	suspend procedure has been aborted
  * @PM_RET_ERROR_TIMEOUT:	timeout in communication with PMU
- * @PM_RET_ERROR_NOTSUPPORTED:	feature not supported
- * @PM_RET_ERROR_PROC:		node is not a processor node
- * @PM_RET_ERROR_API_ID:	illegal API ID
- * @PM_RET_ERROR_OTHER:		other error
+ * @PM_RET_ERROR_NODE_USED:	node is already in use
  */
 enum pm_ret_status {
 	PM_RET_SUCCESS,
-	PM_RET_ERROR_ARGS,
-	PM_RET_ERROR_ACCESS,
-	PM_RET_ERROR_TIMEOUT,
-	PM_RET_ERROR_NOTSUPPORTED,
-	PM_RET_ERROR_PROC,
-	PM_RET_ERROR_API_ID,
-	PM_RET_ERROR_FAILURE,
-	PM_RET_ERROR_COMMUNIC,
-	PM_RET_ERROR_DOUBLEREQ,
-	PM_RET_ERROR_OTHER,
+	PM_RET_ERROR_ARGS = 1,
+	PM_RET_ERROR_NOTSUPPORTED = 4,
+	PM_RET_ERROR_INTERNAL = 2000,
+	PM_RET_ERROR_CONFLICT = 2001,
+	PM_RET_ERROR_ACCESS = 2002,
+	PM_RET_ERROR_INVALID_NODE = 2003,
+	PM_RET_ERROR_DOUBLE_REQ = 2004,
+	PM_RET_ERROR_ABORT_SUSPEND = 2005,
+	PM_RET_ERROR_TIMEOUT = 2006,
+	PM_RET_ERROR_NODE_USED = 2007
 };
 
 /**
@@ -317,4 +324,13 @@
 	PM_CLOCK_DIV1_ID,
 };
 
+/**
+ * EM API IDs
+ */
+enum em_api_id {
+	EM_SET_ACTION = 1,
+	EM_REMOVE_ACTION,
+	EM_SEND_ERRORS,
+};
+
 #endif /* PM_DEFS_H */
diff --git a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c
index 3f4f069..a4bc1ac 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c
@@ -474,8 +474,8 @@
 	{
 		uint32_t data[4] = { 0 };
 
-		ret = pm_query_data(pm_arg[0], pm_arg[1], pm_arg[2],
-				    pm_arg[3], data);
+		pm_query_data(pm_arg[0], pm_arg[1], pm_arg[2],
+			      pm_arg[3], data);
 		SMC_RET2(handle, (uint64_t)data[0]  | ((uint64_t)data[1] << 32),
 			 (uint64_t)data[2] | ((uint64_t)data[3] << 32));
 	}
@@ -606,8 +606,78 @@
 		SMC_RET1(handle, (uint64_t)ret | ((uint64_t)mode << 32));
 	}
 
+	case PM_REGISTER_ACCESS:
+	{
+		uint32_t value;
+
+		ret = pm_register_access(pm_arg[0], pm_arg[1], pm_arg[2],
+					 pm_arg[3], &value);
+		SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+	}
+
+	case PM_EFUSE_ACCESS:
+	{
+		uint32_t value;
+
+		ret = pm_efuse_access(pm_arg[0], pm_arg[1], &value);
+		SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+	}
+
 	default:
 		WARN("Unimplemented PM Service Call: 0x%x\n", smc_fid);
 		SMC_RET1(handle, SMC_UNK);
 	}
 }
+
+/**
+ * em_smc_handler() - SMC handler for EM-API calls coming from EL1/EL2.
+ * @smc_fid - Function Identifier
+ * @x1 - x4 - Arguments
+ * @cookie  - Unused
+ * @handler - Pointer to caller's context structure
+ *
+ * @return  - Unused
+ *
+ * Determines that smc_fid is valid and supported EM SMC Function ID from the
+ * list of em_api_ids, otherwise completes the request with
+ * the unknown SMC Function ID
+ *
+ * The SMC calls for EM service are forwarded from SIP Service SMC handler
+ * function with rt_svc_handle signature
+ */
+uint64_t em_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
+			uint64_t x4, void *cookie, void *handle, uint64_t flags)
+{
+	enum pm_ret_status ret;
+
+	switch (smc_fid & FUNCID_NUM_MASK) {
+	/* EM API Functions */
+	case EM_SET_ACTION:
+	{
+		uint32_t value;
+
+		ret = em_set_action(&value);
+		SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+	}
+
+	case EM_REMOVE_ACTION:
+	{
+		uint32_t value;
+
+		ret = em_remove_action(&value);
+		SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+	}
+
+	case EM_SEND_ERRORS:
+	{
+		uint32_t value;
+
+		ret = em_send_errors(&value);
+		SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+	}
+
+	default:
+		WARN("Unimplemented EM Service Call: 0x%x\n", smc_fid);
+		SMC_RET1(handle, SMC_UNK);
+	}
+}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_svc_main.h b/plat/xilinx/zynqmp/pm_service/pm_svc_main.h
index 0968f64..abadd40 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_svc_main.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_svc_main.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -14,4 +14,7 @@
 			uint64_t x4, void *cookie, void *handle,
 			uint64_t flags);
 
+uint64_t em_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
+			uint64_t x4, void *cookie, void *handle,
+			uint64_t flags);
 #endif /* PM_SVC_MAIN_H */
diff --git a/plat/xilinx/zynqmp/sip_svc_setup.c b/plat/xilinx/zynqmp/sip_svc_setup.c
index 9b18274..4c29da2 100644
--- a/plat/xilinx/zynqmp/sip_svc_setup.c
+++ b/plat/xilinx/zynqmp/sip_svc_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -25,6 +25,9 @@
 #define PM_FID_MASK	0xf000u
 #define PM_FID_VALUE	0u
 #define IPI_FID_VALUE	0x1000u
+#define EM_FID_MASK     0xf0000u
+#define EM_FID_VALUE    0xE0000u
+#define is_em_fid(_fid) (((_fid) & EM_FID_MASK) == EM_FID_VALUE)
 #define is_pm_fid(_fid) (((_fid) & PM_FID_MASK) == PM_FID_VALUE)
 #define is_ipi_fid(_fid) (((_fid) & PM_FID_MASK) == IPI_FID_VALUE)
 
@@ -61,8 +64,12 @@
 			      void *handle,
 			      u_register_t flags)
 {
+	/* Let EM SMC handler deal with EM-related requests */
+	if (is_em_fid(smc_fid)) {
+		return em_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle,
+					flags);
+	} else if (is_pm_fid(smc_fid)) {
 	/* Let PM SMC handler deal with PM-related requests */
-	if (is_pm_fid(smc_fid)) {
 		return pm_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle,
 				      flags);
 	}
diff --git a/services/std_svc/spm_mm/spm_mm_setup.c b/services/std_svc/spm_mm/spm_mm_setup.c
index 468e5b3..32562c3 100644
--- a/services/std_svc/spm_mm/spm_mm_setup.c
+++ b/services/std_svc/spm_mm/spm_mm_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -142,6 +142,8 @@
 		SCTLR_DZE_BIT							|
 		/* Enable SP Alignment check for EL0 */
 		SCTLR_SA0_BIT							|
+		/* Don't change PSTATE.PAN on taking an exception to EL1 */
+		SCTLR_SPAN_BIT							|
 		/* Allow cacheable data and instr. accesses to normal memory. */
 		SCTLR_C_BIT | SCTLR_I_BIT					|
 		/* Enable MMU. */