Merge "fix(trp): Distinguish between cold and warm boot" into integration
diff --git a/.commitlintrc.js b/.commitlintrc.js
index 3bd68bb..f970481 100644
--- a/.commitlintrc.js
+++ b/.commitlintrc.js
@@ -46,7 +46,7 @@
         "change-id-exists": [1, "always", "Change-Id:"], /* Warning */
         "signed-off-by-exists": [1, "always", "Signed-off-by:"], /* Warning */
 
-        "scope-case": [2, "always", "kebab-case"], /* Error */
+        "scope-case": [2, "always", "lower-case"], /* Error */
         "scope-enum": [1, "always", scopes] /* Warning */
     },
 };
diff --git a/.cz.json b/.cz.json
index 5447f17..3c28d3c 100644
--- a/.cz.json
+++ b/.cz.json
@@ -93,12 +93,16 @@
                     "scopes": ["sve"]
                 },
                 {
+                    "title": "System Register Trace Extensions (FEAT_ETMv4, FEAT_ETE and FEAT_ETEv1.1)",
+                    "scopes": ["sys-reg-trace", "sys_reg_trace"]
+                },
+                {
                     "title": "Trace Buffer Extension (FEAT_TRBE)",
                     "scopes": ["trbe"]
                 },
                 {
-                    "title": "Self-hosted Trace Extensions (FEAT_TRF)",
-                    "scopes": ["trf", "sys_reg_trace"]
+                    "title": "Self-hosted Trace Extension (FEAT_TRF)",
+                    "scopes": ["trf"]
                 }
             ]
         },
@@ -194,6 +198,10 @@
                         {
                             "title": "MT8195",
                             "scopes": ["mt8195", "plat/mediatek/me8195", "plat/mediatek/mt8195", "plat/mdeiatek/mt8195"]
+                        },
+                        {
+                            "title": "MT8186",
+                            "scopes": ["mt8186", "plat/mediatek/mt8186"]
                         }
                     ]
                 },
@@ -801,6 +809,10 @@
                 {
                     "title": "STM32 Image",
                     "scopes": ["stm32image", "tools/stm32image"]
+                },
+                {
+                    "title": "fiptool",
+                    "scopes": ["fiptool"]
                 }
             ]
         },
diff --git a/Makefile b/Makefile
index 73007b4..32eb501 100644
--- a/Makefile
+++ b/Makefile
@@ -267,6 +267,16 @@
 ENABLE_FEAT_SB		= 	1
 endif
 
+# Determine and enable FEAT_FGT to access HDFGRTR_EL2 register for v8.6 and higher versions.
+ifeq "8.6" "$(word 1, $(sort 8.6 $(ARM_ARCH_MAJOR).$(ARM_ARCH_MINOR)))"
+ENABLE_FEAT_FGT		=	1
+endif
+
+# Determine and enable FEAT_ECV to access CNTPOFF_EL2 register for v8.6 and higher versions.
+ifeq "8.6" "$(word 1, $(sort 8.6 $(ARM_ARCH_MAJOR).$(ARM_ARCH_MINOR)))"
+ENABLE_FEAT_ECV		=	1
+endif
+
 ifneq ($(findstring armclang,$(notdir $(CC))),)
 TF_CFLAGS_aarch32	=	-target arm-arm-none-eabi $(march32-directive)
 TF_CFLAGS_aarch64	=	-target aarch64-arm-none-eabi $(march64-directive)
@@ -1041,6 +1051,9 @@
         ENABLE_FEAT_HCX \
         ENABLE_MPMM \
         ENABLE_MPMM_FCONF \
+        ENABLE_FEAT_FGT \
+        ENABLE_FEAT_AMUv1 \
+        ENABLE_FEAT_ECV \
 )))
 
 $(eval $(call assert_numerics,\
@@ -1153,6 +1166,9 @@
         ENABLE_FEAT_HCX \
         ENABLE_MPMM \
         ENABLE_MPMM_FCONF \
+        ENABLE_FEAT_FGT \
+        ENABLE_FEAT_AMUv1 \
+        ENABLE_FEAT_ECV \
 )))
 
 ifeq (${SANITIZE_UB},trap)
diff --git a/docs/about/release-information.rst b/docs/about/release-information.rst
index b65571d..b3553ae 100644
--- a/docs/about/release-information.rst
+++ b/docs/about/release-information.rst
@@ -48,6 +48,8 @@
 +-----------------+---------------------------+------------------------------+
 | v2.6            | 4th week of Nov '21       | 2nd week of Nov '21          |
 +-----------------+---------------------------+------------------------------+
+| v2.7            | 2nd week of May '22       | 4th week of Apr '22          |
++-----------------+---------------------------+------------------------------+
 
 Removal of Deprecated Interfaces
 --------------------------------
@@ -61,7 +63,7 @@
 |                                | Date        | after   |                                                         |
 |                                |             | Release |                                                         |
 +================================+=============+=========+=========================================================+
-|                                |             |         |                                                         |
+| STM32MP_USE_STM32IMAGE macro   |   Dec '21   |   2.7   | FIP is the recommended boot method for STM32MP          |
 +--------------------------------+-------------+---------+---------------------------------------------------------+
 
 --------------
diff --git a/docs/change-log.md b/docs/change-log.md
index f0cb352..7f36d01 100644
--- a/docs/change-log.md
+++ b/docs/change-log.md
@@ -63,15 +63,18 @@
 
     - enable SVE for the secure world ([0c5e7d1](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/0c5e7d1ce376cabcebebc43dbf238fe4482ab2dc))
 
+  - **System Register Trace Extensions (FEAT_ETMv4, FEAT_ETE and FEAT_ETEv1.1)**
+
+    - enable trace system registers access from lower NS ELs ([d4582d3](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d4582d30885673987240cf01fd4f5d2e6780e84c))
+    - initialize trap settings of trace system registers access ([2031d61](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/2031d6166a58623ae59034bc2353fcd2fabe9c30))
+
   - **Trace Buffer Extension (FEAT_TRBE)**
 
     - enable access to trace buffer control registers from lower NS EL ([813524e](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/813524ea9d2e4138246b8f77a772299e52fb33bc))
     - initialize trap settings of trace buffer control registers access ([40ff907](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/40ff90747098ed9d2a09894d1a886c10ca76cee6))
 
-  - **Self-hosted Trace Extensions (FEAT_TRF)**
+  - **Self-hosted Trace Extension (FEAT_TRF)**
 
-    - enable trace system registers access from lower NS ELs ([d4582d3](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d4582d30885673987240cf01fd4f5d2e6780e84c))
-    - initialize trap settings of trace system registers access ([2031d61](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/2031d6166a58623ae59034bc2353fcd2fabe9c30))
     - enable trace filter control register access from lower NS EL ([8fcd3d9](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/8fcd3d9600bb2cb6809c6fc68f945ce3ad89633d))
     - initialize trap settings of trace filter control registers access ([5de20ec](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/5de20ece38f782c8459f546a08c6a97b9e0f5bc5))
 
@@ -324,6 +327,7 @@
 
     - add support for Hayes CPU ([7bd8dfb](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/7bd8dfb85a8bf5c22d6a39f4538b89cc748090d1))
     - add support for Hunter CPU ([fb9e5f7](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/fb9e5f7bb76e9764b3ecd7973668c851015fa1b4))
+    - add support for Demeter CPU ([f4616ef](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/f4616efafbc1004f1330f515b898e7617e338875))
     - workaround for Cortex A78 AE erratum 1941500 ([47d6f5f](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/47d6f5ff16d1f2ad009d630a381054b10fa0a06f))
     - workaround for Cortex A78 AE erratum 1951502 ([8913047](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/8913047a52e646877812617a2d98cff99494487b))
 
diff --git a/docs/components/secure-partition-manager.rst b/docs/components/secure-partition-manager.rst
index 4faabf9..a598e5f 100644
--- a/docs/components/secure-partition-manager.rst
+++ b/docs/components/secure-partition-manager.rst
@@ -533,7 +533,10 @@
 
 SP manifests provide an optional boot order attribute meant to resolve
 dependencies such as an SP providing a service required to properly boot
-another SP.
+another SP. SPMC boots the SPs in accordance to the boot order attribute,
+lowest to the highest value. If the boot order attribute is absent from the FF-A
+manifest, the SP is treated as if it had the highest boot order value
+(i.e. lowest booting priority).
 
 It is possible for an SP to call into another SP through a direct request
 provided the latter SP has already been booted.
diff --git a/docs/design/cpu-specific-build-macros.rst b/docs/design/cpu-specific-build-macros.rst
index 9d0dd5e..7075ca6 100644
--- a/docs/design/cpu-specific-build-macros.rst
+++ b/docs/design/cpu-specific-build-macros.rst
@@ -441,6 +441,19 @@
 -  ``ERRATA_N2_2280757``: This applies errata 2280757 workaround to Neoverse-N2
    CPU. This needs to be enabled for revision r0p0 of the CPU and is still open.
 
+For Cortex-X2, the following errata build flags are defined :
+
+-  ``ERRATA_X2_2002765``: This applies errata 2002765 workaround to Cortex-X2
+   CPU. This needs to be enabled for revisions r0p0, r1p0, and r2p0 of the CPU,
+   it is still open.
+
+-  ``ERRATA_X2_2058056``: This applies errata 2058056 workaround to Cortex-X2
+   CPU. This needs to be enabled for revisions r0p0, r1p0, and r2p0 of the CPU,
+   it is still open.
+
+-  ``ERRATA_X2_2083908``: This applies errata 2083908 workaround to Cortex-X2
+   CPU. This needs to be enabled for revision r2p0 of the CPU, it is still open.
+
 DSU Errata Workarounds
 ----------------------
 
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index 7662a14..d77875e 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -246,6 +246,24 @@
    builds, but this behaviour can be overridden in each platform's Makefile or
    in the build command line.
 
+-  ``ENABLE_FEAT_AMUv1``: Boolean option to enable access to the HAFGRTR_EL2
+   (Hypervisor Activity Monitors Fine-Grained Read Trap Register) during EL2
+   to EL3 context save/restore operations. It is an optional feature available
+   on v8.4 and onwards and must be set to 1 alongside ``ENABLE_FEAT_FGT``, to
+   access the HAFGRTR_EL2 register. Defaults to ``0``.
+
+-  ``ENABLE_FEAT_ECV``: Boolean option to enable support for the Enhanced Counter
+   Virtualization feature, allowing for access to the CNTPOFF_EL2 (Counter-timer
+   Physical Offset register) during EL2 to EL3 context save/restore operations.
+   Its a mandatory architectural feature in Armv8.6 and defaults to ``1`` for
+   v8.6 or later CPUs.
+
+-  ``ENABLE_FEAT_FGT``: Boolean option to enable support for FGT (Fine Grain Traps)
+   feature allowing for access to the HDFGRTR_EL2 (Hypervisor Debug Fine-Grained
+   Read Trap Register)  during EL2 to EL3 context save/restore operations.
+   Its a mandatory architectural feature in Armv8.6 and defaults to ``1`` for
+   v8.6 or later CPUs.
+
 -  ``ENABLE_FEAT_HCX``: This option sets the bit SCR_EL3.HXEn in EL3 to allow
    access to HCRX_EL2 (extended hypervisor control register) from EL2 as well as
    adding HCRX_EL2 to the EL2 context save/restore operations.
diff --git a/docs/getting_started/porting-guide.rst b/docs/getting_started/porting-guide.rst
index 92ff39f..24af13e 100644
--- a/docs/getting_started/porting-guide.rst
+++ b/docs/getting_started/porting-guide.rst
@@ -1195,7 +1195,7 @@
 ::
 
     Argument : unsigned int, image_info_t *
-    Return   : void
+    Return   : int
 
 When the MEASURED_BOOT flag is enabled:
 
@@ -1204,7 +1204,25 @@
 -  On the Arm FVP port, this function measures the given image using its
    passed id and information and then records that measurement in the
    Event Log buffer.
--  This function must return 0 on success, a negative error code otherwise.
+-  This function must return 0 on success, a signed integer error code
+   otherwise.
+
+When the MEASURED_BOOT flag is disabled, this function doesn't do anything.
+
+Function : plat_mboot_measure_critical_data()
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+    Argument : unsigned int, const void *, size_t
+    Return   : int
+
+When the MEASURED_BOOT flag is enabled:
+
+-  This function measures the given critical data structure and records its
+   measurement using the measured boot backend driver.
+-  This function must return 0 on success, a signed integer error code
+   otherwise.
 
 When the MEASURED_BOOT flag is disabled, this function doesn't do anything.
 
diff --git a/docs/plat/index.rst b/docs/plat/index.rst
index 5848005..eadd946 100644
--- a/docs/plat/index.rst
+++ b/docs/plat/index.rst
@@ -20,6 +20,7 @@
    intel-stratix10
    marvell/index
    mt8183
+   mt8186
    mt8192
    mt8195
    nvidia-tegra
diff --git a/docs/plat/mt8186.rst b/docs/plat/mt8186.rst
new file mode 100644
index 0000000..16b833a
--- /dev/null
+++ b/docs/plat/mt8186.rst
@@ -0,0 +1,21 @@
+MediaTek 8186
+=============
+
+MediaTek 8186 (MT8186) is a 64-bit ARM SoC introduced by MediaTek in 2021.
+The chip incorporates eight cores - six Cortex-A55 little cores and two Cortex-A76.
+Cortex-A76 can operate at up to 2.05 GHz.
+Cortex-A55 can operate at up to 2.0 GHz.
+
+Boot Sequence
+-------------
+
+::
+
+    Boot Rom --> Coreboot --> TF-A BL31 --> Depthcharge --> Linux Kernel
+
+How to Build
+------------
+
+.. code:: shell
+
+    make CROSS_COMPILE=aarch64-linux-gnu- PLAT=mt8186 DEBUG=1 COREBOOT=1
diff --git a/docs/threat_model/index.rst b/docs/threat_model/index.rst
index b5ede69..335937e 100644
--- a/docs/threat_model/index.rst
+++ b/docs/threat_model/index.rst
@@ -15,6 +15,7 @@
 
    threat_model
    threat_model_spm
+   threat_model_fvp_r
 
 --------------
 
diff --git a/docs/threat_model/threat_model.rst b/docs/threat_model/threat_model.rst
index 4a31e79..072babc 100644
--- a/docs/threat_model/threat_model.rst
+++ b/docs/threat_model/threat_model.rst
@@ -1,4 +1,4 @@
-Generic threat model
+Generic Threat Model
 ********************
 
 ************************
diff --git a/docs/threat_model/threat_model_fvp_r.rst b/docs/threat_model/threat_model_fvp_r.rst
new file mode 100644
index 0000000..c1462bb
--- /dev/null
+++ b/docs/threat_model/threat_model_fvp_r.rst
@@ -0,0 +1,97 @@
+fvp_r-Platform Threat Model
+***************************
+
+************************
+Introduction
+************************
+This document provides a threat model for TF-A fvp_r platform.
+
+************************
+Target of Evaluation
+************************
+In this threat model, the target of evaluation is the fvp_r platform of Trusted
+Firmware for A-class Processors (TF-A).  The fvp_r platform provides limited
+support of AArch64 R-class Processors (v8-R64).
+
+This is a delta document, only pointing out differences from the general TF-A
+threat-model document, :ref:`Generic Threat Model`
+
+BL1 Only
+========
+The most fundamental difference between the threat model for the current fvp_r
+implementation compared to the general TF-A threat model, is that fvp_r is
+currently limited to BL1 only.  Any threats from the general TF-A threat model
+unrelated to BL1 are therefore not relevant to the fvp_r implementation.
+
+The fvp_r BL1 implementation directly loads a customer/partner-defined runtime
+system.  The threat model for that runtime system, being partner-defined, is
+out-of-scope for this threat-model.
+
+Relatedly, all exceptions, synchronous and asynchronous, are disabled during BL1
+execution.  So, any references to exceptions are not relevant.
+
+EL3 is Unsupported and All Secure
+=================================
+v8-R64 cores do not support EL3, and (essentially) all operation is defined as
+Secure-mode.  Therefore:
+
+    - Any threats regarding NS operation are not relevant.
+
+    - Any mentions of SMCs are also not relevant.
+
+    - Anything otherwise-relevant code running in EL3 is instead run in EL2.
+
+MPU instead of MMU
+==================
+v8-R64 cores, running in EL2, use an MPU for memory management, rather than an
+MMU.  The MPU in the fvp_r implementation is configured to function effectively
+identically with the MMU for the usual BL1 implementation.  There are
+memory-map differences, but the MPU configuration is functionally equivalent.
+
+No AArch32 Support
+==================
+Another substantial difference between v8-A and v8-R64 cores is that v8-R64 does
+not support AArch32.  However, this is not believed to have any threat-modeling
+ramifications.
+
+
+Threat Assessment
+=================
+For this section, please reference the Threat Assessment under the general TF-A
+threat-model document, :ref:`Generic Threat Model`
+
+The following threats from that document are still relevant to the fvp_r
+implementation:
+
+    - ID 01:  An attacker can mangle firmware images to execute arbitrary code.
+
+    - ID 03:  An attacker can use Time-of-Check-Time-of-Use (TOCTOU) attack to
+      bypass image authentication during the boot process.
+
+    - ID 04:  An attacker with physical access can execute arbitrary image by
+      bypassing the signature verification stage using clock- or power-glitching
+      techniques.
+
+    - ID 05:  Information leak via UART logs such as crashes
+
+    - ID 06:  An attacker can read sensitive data and execute arbitrary code
+      through the external debug and trace interface.
+
+    - ID 08:  Memory corruption due to memory overflows and lack of boundary
+      checking when accessing resources could allow an attacker to execute 
+      arbitrary code, modify some state variable to change the normal flow of
+      the program, or leak sensitive.
+
+    - ID 11:  Misconfiguration of the Memory Protection Unit (MPU) may allow
+      normal world software to access sensitive data or execute arbitrary code.
+      Arguably, MPUs having fewer memory regions, there may be a temptation to
+      share memory regions, making this a greater threat.  However, since the
+      fvp_r implementation is limited to BL1, since BL1's regions are fixed,
+      and since the MPU configuration is equivalent with that for the fvp
+      platform and others, this is not expected to be a concern.
+
+
+
+--------------
+
+*Copyright (c) 2021, Arm Limited. All rights reserved.*
diff --git a/docs/threat_model/threat_model_spm.rst b/docs/threat_model/threat_model_spm.rst
index 4db4c66..a7bc2a9 100644
--- a/docs/threat_model/threat_model_spm.rst
+++ b/docs/threat_model/threat_model_spm.rst
@@ -1,4 +1,4 @@
-SPMC threat model
+SPMC Threat Model
 *****************
 
 ************************
diff --git a/drivers/arm/css/scmi/scmi_private.h b/drivers/arm/css/scmi/scmi_private.h
index 61437f6..a684ca5 100644
--- a/drivers/arm/css/scmi/scmi_private.h
+++ b/drivers/arm/css/scmi/scmi_private.h
@@ -136,7 +136,7 @@
 	uint64_t res_b; /* Reserved */
 	uint32_t flags;
 	volatile uint32_t len;
-	uint32_t msg_header;
+	volatile uint32_t msg_header;
 	uint32_t payload[];
 } mailbox_mem_t;
 
diff --git a/drivers/arm/gic/v3/gicv3_private.h b/drivers/arm/gic/v3/gicv3_private.h
index 93ee1a1..3af0500 100644
--- a/drivers/arm/gic/v3/gicv3_private.h
+++ b/drivers/arm/gic/v3/gicv3_private.h
@@ -171,7 +171,7 @@
 static inline u_register_t gicd_irouter_val_from_mpidr(u_register_t mpidr,
 						       unsigned int irm)
 {
-	return (mpidr & ~(U(0xff) << 24)) |
+	return (mpidr & MPIDR_AFFINITY_MASK) |
 		((irm & IROUTER_IRM_MASK) << IROUTER_IRM_SHIFT);
 }
 
diff --git a/drivers/auth/crypto_mod.c b/drivers/auth/crypto_mod.c
index c63ff08..127eb0d 100644
--- a/drivers/auth/crypto_mod.c
+++ b/drivers/auth/crypto_mod.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2021, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -114,8 +114,9 @@
  *   data_ptr, data_len: data to be hashed
  *   output: resulting hash
  */
-int crypto_mod_calc_hash(unsigned int alg, void *data_ptr,
-			 unsigned int data_len, unsigned char *output)
+int crypto_mod_calc_hash(enum crypto_md_algo alg, void *data_ptr,
+			 unsigned int data_len,
+			 unsigned char output[CRYPTO_MD_MAX_SIZE])
 {
 	assert(data_ptr != NULL);
 	assert(data_len != 0);
diff --git a/drivers/auth/mbedtls/mbedtls_common.mk b/drivers/auth/mbedtls/mbedtls_common.mk
index 53ebe30..54c819c 100644
--- a/drivers/auth/mbedtls/mbedtls_common.mk
+++ b/drivers/auth/mbedtls/mbedtls_common.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2015-2020, Arm Limited. All rights reserved.
+# Copyright (c) 2015-2021, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -96,6 +96,18 @@
     TF_MBEDTLS_USE_AES_GCM	:=	0
 endif
 
+ifeq ($(MEASURED_BOOT),1)
+    ifeq (${TPM_HASH_ALG}, sha256)
+        TF_MBEDTLS_TPM_HASH_ALG_ID	:=	TF_MBEDTLS_SHA256
+    else ifeq (${TPM_HASH_ALG}, sha384)
+        TF_MBEDTLS_TPM_HASH_ALG_ID	:=	TF_MBEDTLS_SHA384
+    else ifeq (${TPM_HASH_ALG}, sha512)
+        TF_MBEDTLS_TPM_HASH_ALG_ID	:=	TF_MBEDTLS_SHA512
+    else
+        $(error "TPM_HASH_ALG not defined.")
+    endif
+endif
+
 # Needs to be set to drive mbed TLS configuration correctly
 $(eval $(call add_defines,\
     $(sort \
@@ -105,6 +117,10 @@
         TF_MBEDTLS_USE_AES_GCM \
 )))
 
+ifeq ($(MEASURED_BOOT),1)
+  $(eval $(call add_define,TF_MBEDTLS_TPM_HASH_ALG_ID))
+endif
+
 $(eval $(call MAKE_LIB,mbedtls))
 
 endif
diff --git a/drivers/auth/mbedtls/mbedtls_crypto.c b/drivers/auth/mbedtls/mbedtls_crypto.c
index 6d6efb5..114e6ad 100644
--- a/drivers/auth/mbedtls/mbedtls_crypto.c
+++ b/drivers/auth/mbedtls/mbedtls_crypto.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2021, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -24,6 +24,16 @@
 
 #define LIB_NAME		"mbed TLS"
 
+#if MEASURED_BOOT
+/*
+ * CRYPTO_MD_MAX_SIZE value is as per current stronger algorithm available
+ * so make sure that mbed TLS MD maximum size must be lesser than this.
+ */
+CASSERT(CRYPTO_MD_MAX_SIZE >= MBEDTLS_MD_MAX_SIZE,
+	assert_mbedtls_md_size_overflow);
+
+#endif /* MEASURED_BOOT */
+
 /*
  * AlgorithmIdentifier  ::=  SEQUENCE  {
  *     algorithm               OBJECT IDENTIFIER,
@@ -211,21 +221,45 @@
 
 #if MEASURED_BOOT
 /*
+ * Map a generic crypto message digest algorithm to the corresponding macro used
+ * by Mbed TLS.
+ */
+static inline mbedtls_md_type_t md_type(enum crypto_md_algo algo)
+{
+	switch (algo) {
+	case CRYPTO_MD_SHA512:
+		return MBEDTLS_MD_SHA512;
+	case CRYPTO_MD_SHA384:
+		return MBEDTLS_MD_SHA384;
+	case CRYPTO_MD_SHA256:
+		return MBEDTLS_MD_SHA256;
+	default:
+		/* Invalid hash algorithm. */
+		return MBEDTLS_MD_NONE;
+	}
+}
+
+/*
  * Calculate a hash
  *
  * output points to the computed hash
  */
-int calc_hash(unsigned int alg, void *data_ptr,
-	      unsigned int data_len, unsigned char *output)
+static int calc_hash(enum crypto_md_algo md_algo, void *data_ptr,
+		     unsigned int data_len,
+		     unsigned char output[CRYPTO_MD_MAX_SIZE])
 {
 	const mbedtls_md_info_t *md_info;
 
-	md_info = mbedtls_md_info_from_type((mbedtls_md_type_t)alg);
+	md_info = mbedtls_md_info_from_type(md_type(md_algo));
 	if (md_info == NULL) {
 		return CRYPTO_ERR_HASH;
 	}
 
-	/* Calculate the hash of the data */
+	/*
+	 * Calculate the hash of the data, it is safe to pass the
+	 * 'output' hash buffer pointer considering its size is always
+	 * bigger than or equal to MBEDTLS_MD_MAX_SIZE.
+	 */
 	return mbedtls_md(md_info, data_ptr, data_len, output);
 }
 #endif /* MEASURED_BOOT */
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
new file mode 100644
index 0000000..4cbc0f7
--- /dev/null
+++ b/drivers/clk/clk.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
+ * Author(s): Ludovic Barre, <ludovic.barre@st.com> for STMicroelectronics.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdbool.h>
+
+#include <drivers/clk.h>
+
+static const struct clk_ops *ops;
+
+int clk_enable(unsigned long id)
+{
+	assert((ops != NULL) && (ops->enable != NULL));
+
+	return ops->enable(id);
+}
+
+void clk_disable(unsigned long id)
+{
+	assert((ops != NULL) && (ops->disable != NULL));
+
+	ops->disable(id);
+}
+
+unsigned long clk_get_rate(unsigned long id)
+{
+	assert((ops != NULL) && (ops->get_rate != NULL));
+
+	return ops->get_rate(id);
+}
+
+int clk_get_parent(unsigned long id)
+{
+	assert((ops != NULL) && (ops->get_parent != NULL));
+
+	return ops->get_parent(id);
+}
+
+bool clk_is_enabled(unsigned long id)
+{
+	assert((ops != NULL) && (ops->is_enabled != NULL));
+
+	return ops->is_enabled(id);
+}
+
+/*
+ * Initialize the clk. The fields in the provided clk
+ * ops pointer must be valid.
+ */
+void clk_register(const struct clk_ops *ops_ptr)
+{
+	assert((ops_ptr != NULL) &&
+	       (ops_ptr->enable != NULL) &&
+	       (ops_ptr->disable != NULL) &&
+	       (ops_ptr->get_rate != NULL) &&
+	       (ops_ptr->get_parent != NULL) &&
+	       (ops_ptr->is_enabled != NULL));
+
+	ops = ops_ptr;
+}
diff --git a/drivers/marvell/comphy/phy-comphy-3700.c b/drivers/marvell/comphy/phy-comphy-3700.c
index a3e414c..1a97753 100644
--- a/drivers/marvell/comphy/phy-comphy-3700.c
+++ b/drivers/marvell/comphy/phy-comphy-3700.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 Marvell International Ltd.
+ * Copyright (C) 2018-2021 Marvell International Ltd.
  *
  * SPDX-License-Identifier:     BSD-3-Clause
  * https://spdx.org/licenses
@@ -301,7 +301,7 @@
 	}
 
 	/* Clear phy isolation mode to make it work in normal mode */
-	offset =  COMPHY_ISOLATION_CTRL_REG + SATAPHY_LANE2_REG_BASE_OFFSET;
+	offset =  COMPHY_ISOLATION_CTRL + SATAPHY_LANE2_REG_BASE_OFFSET;
 	comphy_sata_set_indirect(comphy_indir_regs, offset, 0, PHY_ISOLATE_MODE);
 
 	/* 0. Check the Polarity invert bits */
@@ -310,21 +310,21 @@
 	if (invert & COMPHY_POLARITY_RXD_INVERT)
 		data |= RXD_INVERT_BIT;
 
-	offset = COMPHY_SYNC_PATTERN_REG + SATAPHY_LANE2_REG_BASE_OFFSET;
+	offset = COMPHY_SYNC_PATTERN + SATAPHY_LANE2_REG_BASE_OFFSET;
 	comphy_sata_set_indirect(comphy_indir_regs, offset, data, TXD_INVERT_BIT |
 				 RXD_INVERT_BIT);
 
 	/* 1. Select 40-bit data width width */
-	offset = COMPHY_LOOPBACK_REG0 + SATAPHY_LANE2_REG_BASE_OFFSET;
+	offset = COMPHY_DIG_LOOPBACK_EN + SATAPHY_LANE2_REG_BASE_OFFSET;
 	comphy_sata_set_indirect(comphy_indir_regs, offset, DATA_WIDTH_40BIT,
 				 SEL_DATA_WIDTH_MASK);
 
 	/* 2. Select reference clock(25M) and PHY mode (SATA) */
 	offset = COMPHY_POWER_PLL_CTRL + SATAPHY_LANE2_REG_BASE_OFFSET;
 	if (get_ref_clk() == 40)
-		ref_clk = REF_CLOCK_SPEED_40M;
+		ref_clk = REF_FREF_SEL_SERDES_40MHZ;
 	else
-		ref_clk = REF_CLOCK_SPEED_25M;
+		ref_clk = REF_FREF_SEL_SERDES_25MHZ;
 
 	comphy_sata_set_indirect(comphy_indir_regs, offset, ref_clk | PHY_MODE_SATA,
 				 REF_FREF_SEL_MASK | PHY_MODE_MASK);
@@ -352,7 +352,7 @@
 
 	/* Polling status */
 	mmio_write_32(comphy_indir_regs + COMPHY_LANE2_INDIR_ADDR_OFFSET,
-		      COMPHY_LOOPBACK_REG0 + SATAPHY_LANE2_REG_BASE_OFFSET);
+		      COMPHY_DIG_LOOPBACK_EN + SATAPHY_LANE2_REG_BASE_OFFSET);
 
 	ret = polling_with_timeout(comphy_indir_regs +
 				   COMPHY_LANE2_INDIR_DATA_OFFSET,
@@ -401,8 +401,8 @@
 	 *    PHY TXP/TXN output to idle state during PHY initialization
 	 * 3. Set PHY input port PIN_PU_PLL=0, PIN_PU_RX=0, PIN_PU_TX=0.
 	 */
-	data = PIN_PU_IVEREF_BIT | PIN_TX_IDLE_BIT | PIN_RESET_COMPHY_BIT;
-	mask = PIN_RESET_CORE_BIT | PIN_PU_PLL_BIT | PIN_PU_RX_BIT |
+	data = PIN_PU_IVREF_BIT | PIN_TX_IDLE_BIT | PIN_RESET_COMPHY_BIT;
+	mask = data | PIN_RESET_CORE_BIT | PIN_PU_PLL_BIT | PIN_PU_RX_BIT |
 		PIN_PU_TX_BIT;
 	offset = MVEBU_COMPHY_REG_BASE + COMPHY_PHY_CFG1_OFFSET(comphy_index);
 	reg_set(offset, data, mask);
@@ -422,8 +422,8 @@
 		data |= SD_SPEED_1_25_G << GEN_TX_SEL_OFFSET;
 	} else if (mode == COMPHY_2500BASEX_MODE) {
 		/* 2500Base-X, SerDes speed 3.125G */
-		data |= SD_SPEED_2_5_G << GEN_RX_SEL_OFFSET;
-		data |= SD_SPEED_2_5_G << GEN_TX_SEL_OFFSET;
+		data |= SD_SPEED_3_125_G << GEN_RX_SEL_OFFSET;
+		data |= SD_SPEED_3_125_G << GEN_TX_SEL_OFFSET;
 	} else {
 		/* Other rates are not supported */
 		ERROR("unsupported SGMII speed on comphy lane%d\n",
@@ -450,16 +450,16 @@
 	 */
 	data = 0;
 	mask = PHY_REF_CLK_SEL;
-	reg_set16(SGMIIPHY_ADDR(COMPHY_MISC_REG0_ADDR, sd_ip_addr), data, mask);
+	reg_set16(SGMIIPHY_ADDR(COMPHY_MISC_CTRL0, sd_ip_addr), data, mask);
 
 	/*
 	 * 9. Set correct reference clock frequency in COMPHY register
 	 * REF_FREF_SEL.
 	 */
 	if (get_ref_clk() == 40)
-		data = REF_CLOCK_SPEED_50M;
+		data = REF_FREF_SEL_SERDES_50MHZ;
 	else
-		data = REF_CLOCK_SPEED_25M;
+		data = REF_FREF_SEL_SERDES_25MHZ;
 
 	mask = REF_FREF_SEL_MASK;
 	reg_set16(SGMIIPHY_ADDR(COMPHY_POWER_PLL_CTRL, sd_ip_addr), data, mask);
@@ -477,7 +477,8 @@
 	 */
 	data = DATA_WIDTH_10BIT;
 	mask = SEL_DATA_WIDTH_MASK;
-	reg_set16(SGMIIPHY_ADDR(COMPHY_LOOPBACK_REG0, sd_ip_addr), data, mask);
+	reg_set16(SGMIIPHY_ADDR(COMPHY_DIG_LOOPBACK_EN, sd_ip_addr),
+		  data, mask);
 
 	/*
 	 * 12. As long as DFE function needs to be enabled in any mode,
@@ -523,7 +524,7 @@
 	if (invert & COMPHY_POLARITY_RXD_INVERT)
 		data |= RXD_INVERT_BIT;
 	mask = TXD_INVERT_BIT | RXD_INVERT_BIT;
-	reg_set16(SGMIIPHY_ADDR(COMPHY_SYNC_PATTERN_REG, sd_ip_addr), data, mask);
+	reg_set16(SGMIIPHY_ADDR(COMPHY_SYNC_PATTERN, sd_ip_addr), data, mask);
 
 	/*
 	 * 17. Set PHY input ports PIN_PU_PLL, PIN_PU_TX and PIN_PU_RX to 1 to
@@ -645,68 +646,68 @@
 	 */
 	mask = PRD_TXDEEMPH0_MASK | PRD_TXMARGIN_MASK | PRD_TXSWING_MASK |
 		CFG_TX_ALIGN_POS_MASK;
-	usb3_reg_set(reg_base, COMPHY_REG_LANE_CFG0_ADDR, PRD_TXDEEMPH0_MASK,
-		     mask);
+	usb3_reg_set(reg_base, COMPHY_LANE_CFG0, PRD_TXDEEMPH0_MASK, mask);
 
 	/*
 	 * 2. Set BIT0: enable transmitter in high impedance mode
 	 *    Set BIT[3:4]: delay 2 clock cycles for HiZ off latency
 	 *    Set BIT6: Tx detect Rx at HiZ mode
 	 *    Unset BIT15: set to 0 to set USB3 De-emphasize level to -3.5db
-	 *            together with bit 0 of COMPHY_REG_LANE_CFG0_ADDR register
+	 *            together with bit 0 of COMPHY_LANE_CFG0 register
 	 */
 	mask = PRD_TXDEEMPH1_MASK | TX_DET_RX_MODE | GEN2_TX_DATA_DLY_MASK |
 		TX_ELEC_IDLE_MODE_EN;
 	data = TX_DET_RX_MODE | GEN2_TX_DATA_DLY_DEFT | TX_ELEC_IDLE_MODE_EN;
-	usb3_reg_set(reg_base, COMPHY_REG_LANE_CFG1_ADDR, data, mask);
+	usb3_reg_set(reg_base, COMPHY_LANE_CFG1, data, mask);
 
 	/*
 	 * 3. Set Spread Spectrum Clock Enabled
 	 */
-	usb3_reg_set(reg_base, COMPHY_REG_LANE_CFG4_ADDR,
+	usb3_reg_set(reg_base, COMPHY_LANE_CFG4,
 		     SPREAD_SPECTRUM_CLK_EN, SPREAD_SPECTRUM_CLK_EN);
 
 	/*
 	 * 4. Set Override Margining Controls From the MAC:
 	 *    Use margining signals from lane configuration
 	 */
-	usb3_reg_set(reg_base, COMPHY_REG_TEST_MODE_CTRL_ADDR,
+	usb3_reg_set(reg_base, COMPHY_TEST_MODE_CTRL,
 		     MODE_MARGIN_OVERRIDE, REG_16_BIT_MASK);
 
 	/*
 	 * 5. Set Lane-to-Lane Bundle Clock Sampling Period = per PCLK cycles
 	 *    set Mode Clock Source = PCLK is generated from REFCLK
 	 */
-	usb3_reg_set(reg_base, COMPHY_REG_GLOB_CLK_SRC_LO_ADDR, 0x0,
-		     (MODE_CLK_SRC | BUNDLE_PERIOD_SEL | BUNDLE_PERIOD_SCALE |
-		      BUNDLE_SAMPLE_CTRL | PLL_READY_DLY));
+	usb3_reg_set(reg_base, COMPHY_CLK_SRC_LO, 0x0,
+		     (MODE_CLK_SRC | BUNDLE_PERIOD_SEL |
+		      BUNDLE_PERIOD_SCALE_MASK | BUNDLE_SAMPLE_CTRL |
+		      PLL_READY_DLY_MASK));
 
 	/*
 	 * 6. Set G2 Spread Spectrum Clock Amplitude at 4K
 	 */
-	usb3_reg_set(reg_base, COMPHY_REG_GEN2_SET_2,
-		     G2_TX_SSC_AMP_VALUE_20, G2_TX_SSC_AMP_MASK);
+	usb3_reg_set(reg_base, COMPHY_GEN2_SET2,
+		     GS2_TX_SSC_AMP_VALUE_20, GS2_TX_SSC_AMP_MASK);
 
 	/*
 	 * 7. Unset G3 Spread Spectrum Clock Amplitude
 	 *    set G3 TX and RX Register Master Current Select
 	 */
-	mask = G3_TX_SSC_AMP_MASK | G3_VREG_RXTX_MAS_ISET_MASK |
-		RSVD_PH03FH_6_0_MASK;
-	usb3_reg_set(reg_base, COMPHY_REG_GEN2_SET_3,
-		     G3_VREG_RXTX_MAS_ISET_60U, mask);
+	mask = GS2_TX_SSC_AMP_MASK | GS2_VREG_RXTX_MAS_ISET_MASK |
+		GS2_RSVD_6_0_MASK;
+	usb3_reg_set(reg_base, COMPHY_GEN3_SET2,
+		     GS2_VREG_RXTX_MAS_ISET_60U, mask);
 
 	/*
 	 * 8. Check crystal jumper setting and program the Power and PLL Control
 	 * accordingly Change RX wait
 	 */
 	if (get_ref_clk() == 40) {
-		ref_clk = REF_CLOCK_SPEED_40M;
+		ref_clk = REF_FREF_SEL_PCIE_USB3_40MHZ;
 		cfg = CFG_PM_RXDLOZ_WAIT_12_UNIT;
 
 	} else {
 		/* 25 MHz */
-		ref_clk = USB3_REF_CLOCK_SPEED_25M;
+		ref_clk = REF_FREF_SEL_PCIE_USB3_25MHZ;
 		cfg = CFG_PM_RXDLOZ_WAIT_7_UNIT;
 	}
 
@@ -720,24 +721,24 @@
 	mask = CFG_PM_OSCCLK_WAIT_MASK | CFG_PM_RXDEN_WAIT_MASK |
 		CFG_PM_RXDLOZ_WAIT_MASK;
 	data = CFG_PM_RXDEN_WAIT_1_UNIT  | cfg;
-	usb3_reg_set(reg_base, COMPHY_REG_PWR_MGM_TIM1_ADDR, data, mask);
+	usb3_reg_set(reg_base, COMPHY_PWR_MGM_TIM1, data, mask);
 
 	/*
 	 * 9. Enable idle sync
 	 */
-	data = UNIT_CTRL_DEFAULT_VALUE | IDLE_SYNC_EN;
-	usb3_reg_set(reg_base, COMPHY_REG_UNIT_CTRL_ADDR, data, REG_16_BIT_MASK);
+	data = IDLE_SYNC_EN_DEFAULT_VALUE | IDLE_SYNC_EN;
+	usb3_reg_set(reg_base, COMPHY_IDLE_SYNC_EN, data, REG_16_BIT_MASK);
 
 	/*
 	 * 10. Enable the output of 500M clock
 	 */
-	data = MISC_REG0_DEFAULT_VALUE | CLK500M_EN;
-	usb3_reg_set(reg_base, COMPHY_MISC_REG0_ADDR, data, REG_16_BIT_MASK);
+	data = MISC_CTRL0_DEFAULT_VALUE | CLK500M_EN;
+	usb3_reg_set(reg_base, COMPHY_MISC_CTRL0, data, REG_16_BIT_MASK);
 
 	/*
 	 * 11. Set 20-bit data width
 	 */
-	usb3_reg_set(reg_base, COMPHY_LOOPBACK_REG0, DATA_WIDTH_20BIT,
+	usb3_reg_set(reg_base, COMPHY_DIG_LOOPBACK_EN, DATA_WIDTH_20BIT,
 		     REG_16_BIT_MASK);
 
 	/*
@@ -758,32 +759,31 @@
 		data |= RXD_INVERT_BIT;
 	}
 	mask = TXD_INVERT_BIT | RXD_INVERT_BIT;
-	usb3_reg_set(reg_base, COMPHY_SYNC_PATTERN_REG, data, mask);
+	usb3_reg_set(reg_base, COMPHY_SYNC_PATTERN, data, mask);
 
 	/*
 	 * 14. Set max speed generation to USB3.0 5Gbps
 	 */
-	usb3_reg_set(reg_base, COMPHY_SYNC_MASK_GEN_REG, PHY_GEN_USB3_5G,
+	usb3_reg_set(reg_base, COMPHY_SYNC_MASK_GEN, PHY_GEN_MAX_USB3_5G,
 		     PHY_GEN_MAX_MASK);
 
 	/*
 	 * 15. Set capacitor value for FFE gain peaking to 0xF
 	 */
-	usb3_reg_set(reg_base, COMPHY_REG_GEN3_SETTINGS_3,
-		     COMPHY_GEN_FFE_CAP_SEL_VALUE, COMPHY_GEN_FFE_CAP_SEL_MASK);
+	usb3_reg_set(reg_base, COMPHY_GEN2_SET3,
+		     GS3_FFE_CAP_SEL_VALUE, GS3_FFE_CAP_SEL_MASK);
 
 	/*
 	 * 16. Release SW reset
 	 */
 	data = MODE_CORE_CLK_FREQ_SEL | MODE_PIPE_WIDTH_32 | MODE_REFDIV_BY_4;
-	usb3_reg_set(reg_base, COMPHY_REG_GLOB_PHY_CTRL0_ADDR, data,
-		     REG_16_BIT_MASK);
+	usb3_reg_set(reg_base, COMPHY_RST_CLK_CTRL, data, REG_16_BIT_MASK);
 
 	/* Wait for > 55 us to allow PCLK be enabled */
 	udelay(PLL_SET_DELAY_US);
 
 	if (comphy_index == COMPHY_LANE2) {
-		data = COMPHY_REG_LANE_STATUS1_ADDR + USB3PHY_LANE2_REG_BASE_OFFSET;
+		data = COMPHY_LANE_STAT1 + USB3PHY_LANE2_REG_BASE_OFFSET;
 		mmio_write_32(reg_base + COMPHY_LANE2_INDIR_ADDR_OFFSET,
 			      data);
 
@@ -791,7 +791,7 @@
 		ret = polling_with_timeout(addr, TXDCLK_PCLK_EN, TXDCLK_PCLK_EN,
 					   COMPHY_PLL_TIMEOUT, REG_32BIT);
 	} else {
-		ret = polling_with_timeout(LANE_STATUS1_ADDR(USB3) + reg_base,
+		ret = polling_with_timeout(LANE_STAT1_ADDR(USB3) + reg_base,
 					   TXDCLK_PCLK_EN, TXDCLK_PCLK_EN,
 					   COMPHY_PLL_TIMEOUT, REG_16BIT);
 	}
@@ -826,11 +826,11 @@
 		  USE_MAX_PLL_RATE_EN, USE_MAX_PLL_RATE_EN);
 
 	/* 2. Select 20 bit SERDES interface. */
-	reg_set16(GLOB_CLK_SRC_LO_ADDR(PCIE) + COMPHY_SD_ADDR,
+	reg_set16(CLK_SRC_LO_ADDR(PCIE) + COMPHY_SD_ADDR,
 		  CFG_SEL_20B, CFG_SEL_20B);
 
 	/* 3. Force to use reg setting for PCIe mode */
-	reg_set16(MISC_REG1_ADDR(PCIE) + COMPHY_SD_ADDR,
+	reg_set16(MISC_CTRL1_ADDR(PCIE) + COMPHY_SD_ADDR,
 		  SEL_BITS_PCIE_FORCE, SEL_BITS_PCIE_FORCE);
 
 	/* 4. Change RX wait */
@@ -840,12 +840,12 @@
 		   CFG_PM_RXDLOZ_WAIT_MASK));
 
 	/* 5. Enable idle sync */
-	reg_set16(UNIT_CTRL_ADDR(PCIE) + COMPHY_SD_ADDR,
-		  UNIT_CTRL_DEFAULT_VALUE | IDLE_SYNC_EN, REG_16_BIT_MASK);
+	reg_set16(IDLE_SYNC_EN_ADDR(PCIE) + COMPHY_SD_ADDR,
+		  IDLE_SYNC_EN_DEFAULT_VALUE | IDLE_SYNC_EN, REG_16_BIT_MASK);
 
 	/* 6. Enable the output of 100M/125M/500M clock */
-	reg_set16(MISC_REG0_ADDR(PCIE) + COMPHY_SD_ADDR,
-		  MISC_REG0_DEFAULT_VALUE | CLK500M_EN | TXDCLK_2X_SEL | CLK100M_125M_EN,
+	reg_set16(MISC_CTRL0_ADDR(PCIE) + COMPHY_SD_ADDR,
+		  MISC_CTRL0_DEFAULT_VALUE | CLK500M_EN | TXDCLK_2X_SEL | CLK100M_125M_EN,
 		  REG_16_BIT_MASK);
 
 	/*
@@ -859,9 +859,9 @@
 	 */
 
 	if (get_ref_clk() == 40)
-		ref_clk = REF_CLOCK_SPEED_40M;
+		ref_clk = REF_FREF_SEL_PCIE_USB3_40MHZ;
 	else
-		ref_clk = PCIE_REF_CLOCK_SPEED_25M;
+		ref_clk = REF_FREF_SEL_PCIE_USB3_25MHZ;
 
 	reg_set16(PWR_PLL_CTRL_ADDR(PCIE) + COMPHY_SD_ADDR,
 		  (PU_IVREF_BIT | PU_PLL_BIT | PU_RX_BIT | PU_TX_BIT |
@@ -881,17 +881,17 @@
 		data |= RXD_INVERT_BIT;
 	}
 	mask = TXD_INVERT_BIT | RXD_INVERT_BIT;
-	reg_set16(SYNC_PATTERN_REG_ADDR(PCIE) + COMPHY_SD_ADDR, data, mask);
+	reg_set16(SYNC_PATTERN_ADDR(PCIE) + COMPHY_SD_ADDR, data, mask);
 
 	/* 11. Release SW reset */
-	reg_set16(GLOB_PHY_CTRL0_ADDR(PCIE) + COMPHY_SD_ADDR,
-		  MODE_CORE_CLK_FREQ_SEL | MODE_PIPE_WIDTH_32,
-		  SOFT_RESET | MODE_REFDIV);
+	data = MODE_CORE_CLK_FREQ_SEL | MODE_PIPE_WIDTH_32;
+	mask = data | SOFT_RESET | MODE_REFDIV_MASK;
+	reg_set16(RST_CLK_CTRL_ADDR(PCIE) + COMPHY_SD_ADDR, data, mask);
 
 	/* Wait for > 55 us to allow PCLK be enabled */
 	udelay(PLL_SET_DELAY_US);
 
-	ret = polling_with_timeout(LANE_STATUS1_ADDR(PCIE) + COMPHY_SD_ADDR,
+	ret = polling_with_timeout(LANE_STAT1_ADDR(PCIE) + COMPHY_SD_ADDR,
 				   TXDCLK_PCLK_EN, TXDCLK_PCLK_EN,
 				   COMPHY_PLL_TIMEOUT, REG_16BIT);
 	if (ret) {
@@ -961,7 +961,7 @@
 	debug_enter();
 
 	/* Set phy isolation mode */
-	offset = COMPHY_ISOLATION_CTRL_REG + SATAPHY_LANE2_REG_BASE_OFFSET;
+	offset = COMPHY_ISOLATION_CTRL + SATAPHY_LANE2_REG_BASE_OFFSET;
 	comphy_sata_set_indirect(comphy_indir_regs, offset, PHY_ISOLATE_MODE,
 				 PHY_ISOLATE_MODE);
 
@@ -1025,7 +1025,7 @@
 
 	/* Polling status */
 	mmio_write_32(comphy_indir_regs + COMPHY_LANE2_INDIR_ADDR_OFFSET,
-	       COMPHY_LOOPBACK_REG0 + SATAPHY_LANE2_REG_BASE_OFFSET);
+	       COMPHY_DIG_LOOPBACK_EN + SATAPHY_LANE2_REG_BASE_OFFSET);
 	addr = comphy_indir_regs + COMPHY_LANE2_INDIR_DATA_OFFSET;
 	data = polling_with_timeout(addr, PLL_READY_TX_BIT, PLL_READY_TX_BIT,
 				    COMPHY_PLL_TIMEOUT, REG_32BIT);
diff --git a/drivers/marvell/comphy/phy-comphy-3700.h b/drivers/marvell/comphy/phy-comphy-3700.h
index 94056f1..ed07624 100644
--- a/drivers/marvell/comphy/phy-comphy-3700.h
+++ b/drivers/marvell/comphy/phy-comphy-3700.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 Marvell International Ltd.
+ * Copyright (C) 2018-2021 Marvell International Ltd.
  *
  * SPDX-License-Identifier:     BSD-3-Clause
  * https://spdx.org/licenses
@@ -13,11 +13,11 @@
 #define REG_16_BIT_MASK				0xFFFF
 
 #define COMPHY_SELECTOR_PHY_REG			0xFC
-/* bit0: 0: Lane0 is GBE0; 1: Lane1 is PCIE */
+/* bit0: 0: Lane1 is GbE0; 1: Lane1 is PCIE */
 #define COMPHY_SELECTOR_PCIE_GBE0_SEL_BIT	BIT(0)
-/* bit4: 0: Lane1 is GBE1; 1: Lane1 is USB3 */
+/* bit4: 0: Lane0 is GbE1; 1: Lane0 is USB3 */
 #define COMPHY_SELECTOR_USB3_GBE1_SEL_BIT	BIT(4)
-/* bit8: 0: Lane1 is USB, Lane2 is SATA; 1: Lane2 is USB3 */
+/* bit8: 0: Lane0 is USB3 instead of GbE1, Lane2 is SATA; 1: Lane2 is USB3 */
 #define COMPHY_SELECTOR_USB3_PHY_SEL_BIT	BIT(8)
 
 /* SATA PHY register offset */
@@ -53,12 +53,11 @@
 #define PLL_LOCK_BIT			BIT(8)
 #define REF_FREF_SEL_OFFSET		0
 #define REF_FREF_SEL_MASK		(0x1F << REF_FREF_SEL_OFFSET)
-#define REF_CLOCK_SPEED_25M		(0x1 << REF_FREF_SEL_OFFSET)
-#define REF_CLOCK_SPEED_30M		(0x2 << REF_FREF_SEL_OFFSET)
-#define PCIE_REF_CLOCK_SPEED_25M	REF_CLOCK_SPEED_30M
-#define USB3_REF_CLOCK_SPEED_25M	REF_CLOCK_SPEED_30M
-#define REF_CLOCK_SPEED_40M		(0x3 << REF_FREF_SEL_OFFSET)
-#define REF_CLOCK_SPEED_50M		(0x4 << REF_FREF_SEL_OFFSET)
+#define REF_FREF_SEL_SERDES_25MHZ	(0x1 << REF_FREF_SEL_OFFSET)
+#define REF_FREF_SEL_SERDES_40MHZ	(0x3 << REF_FREF_SEL_OFFSET)
+#define REF_FREF_SEL_SERDES_50MHZ	(0x4 << REF_FREF_SEL_OFFSET)
+#define REF_FREF_SEL_PCIE_USB3_25MHZ	(0x2 << REF_FREF_SEL_OFFSET)
+#define REF_FREF_SEL_PCIE_USB3_40MHZ	(0x3 << REF_FREF_SEL_OFFSET)
 #define PHY_MODE_OFFSET			5
 #define PHY_MODE_MASK			(7 << PHY_MODE_OFFSET)
 #define PHY_MODE_SATA			(0x0 << PHY_MODE_OFFSET)
@@ -73,11 +72,9 @@
 #define SPEED_PLL_MASK			(0x3F << SPEED_PLL_OFFSET)
 #define SPEED_PLL_VALUE_16		(0x10 << SPEED_PLL_OFFSET)
 
-#define COMPHY_RESERVED_REG		0x0E
-#define PHYCTRL_FRM_PIN_BIT		BIT(13)
-
-#define COMPHY_LOOPBACK_REG0		0x23
-#define DIG_LB_EN_ADDR(unit)		(COMPHY_LOOPBACK_REG0 * PHY_SHFT(unit))
+#define COMPHY_DIG_LOOPBACK_EN		0x23
+#define DIG_LOOPBACK_EN_ADDR(unit)	(COMPHY_DIG_LOOPBACK_EN * \
+					 PHY_SHFT(unit))
 #define SEL_DATA_WIDTH_OFFSET		10
 #define SEL_DATA_WIDTH_MASK		(0x3 << SEL_DATA_WIDTH_OFFSET)
 #define DATA_WIDTH_10BIT		(0x0 << SEL_DATA_WIDTH_OFFSET)
@@ -85,80 +82,71 @@
 #define DATA_WIDTH_40BIT		(0x2 << SEL_DATA_WIDTH_OFFSET)
 #define PLL_READY_TX_BIT		BIT(4)
 
-#define COMPHY_SYNC_PATTERN_REG		0x24
-#define SYNC_PATTERN_REG_ADDR(unit)	(COMPHY_SYNC_PATTERN_REG * \
-					 PHY_SHFT(unit))
+#define COMPHY_SYNC_PATTERN		0x24
+#define SYNC_PATTERN_ADDR(unit)		(COMPHY_SYNC_PATTERN * PHY_SHFT(unit))
 #define TXD_INVERT_BIT			BIT(10)
 #define RXD_INVERT_BIT			BIT(11)
 
-#define COMPHY_SYNC_MASK_GEN_REG	0x25
+#define COMPHY_SYNC_MASK_GEN		0x25
 #define PHY_GEN_MAX_OFFSET		10
 #define PHY_GEN_MAX_MASK		(3 << PHY_GEN_MAX_OFFSET)
-#define PHY_GEN_USB3_5G			(1 << PHY_GEN_MAX_OFFSET)
+#define PHY_GEN_MAX_USB3_5G		(1 << PHY_GEN_MAX_OFFSET)
 
-#define COMPHY_ISOLATION_CTRL_REG	0x26
-#define ISOLATION_CTRL_REG_ADDR(unit)	(COMPHY_ISOLATION_CTRL_REG * \
-					 PHY_SHFT(unit))
+#define COMPHY_ISOLATION_CTRL		0x26
+#define ISOLATION_CTRL_ADDR(unit)	(COMPHY_ISOLATION_REG * PHY_SHFT(unit))
 #define PHY_ISOLATE_MODE		BIT(15)
 
+#define COMPHY_GEN2_SET2		0x3e
+#define GEN2_SET2_ADDR(unit)		(COMPHY_GEN2_SET2 * PHY_SHFT(unit))
+#define GS2_TX_SSC_AMP_VALUE_20		BIT(14)
+#define GS2_TX_SSC_AMP_OFF		9
+#define GS2_TX_SSC_AMP_LEN		7
+#define GS2_TX_SSC_AMP_MASK		(((1 << GS2_TX_SSC_AMP_LEN) - 1) << \
+					 GS2_TX_SSC_AMP_OFF)
+#define GS2_VREG_RXTX_MAS_ISET_OFF	7
+#define GS2_VREG_RXTX_MAS_ISET_60U	(0 << GS2_VREG_RXTX_MAS_ISET_OFF)
+#define GS2_VREG_RXTX_MAS_ISET_80U	(1 << GS2_VREG_RXTX_MAS_ISET_OFF)
+#define GS2_VREG_RXTX_MAS_ISET_100U	(2 << GS2_VREG_RXTX_MAS_ISET_OFF)
+#define GS2_VREG_RXTX_MAS_ISET_120U	(3 << GS2_VREG_RXTX_MAS_ISET_OFF)
+#define GS2_VREG_RXTX_MAS_ISET_MASK	(BIT(7) | BIT(8))
+#define GS2_RSVD_6_0_OFF		0
+#define GS2_RSVD_6_0_LEN		7
+#define GS2_RSVD_6_0_MASK		(((1 << GS2_RSVD_6_0_LEN) - 1) << \
+					 GS2_RSVD_6_0_OFF)
+
-#define COMPHY_MISC_REG0_ADDR		0x4F
-#define MISC_REG0_ADDR(unit)		(COMPHY_MISC_REG0_ADDR * PHY_SHFT(unit))
+#define COMPHY_GEN3_SET2		0x3f
+#define GEN3_SET2_ADDR(unit)		(COMPHY_GEN3_SET2 * PHY_SHFT(unit))
+
+#define COMPHY_IDLE_SYNC_EN		0x48
+#define IDLE_SYNC_EN_ADDR(unit)		(COMPHY_IDLE_SYNC_EN * PHY_SHFT(unit))
+#define IDLE_SYNC_EN			BIT(12)
+#define IDLE_SYNC_EN_DEFAULT_VALUE	0x60
+
+#define COMPHY_MISC_CTRL0		0x4F
+#define MISC_CTRL0_ADDR(unit)		(COMPHY_MISC_CTRL0 * PHY_SHFT(unit))
 #define CLK100M_125M_EN			BIT(4)
 #define TXDCLK_2X_SEL			BIT(6)
 #define CLK500M_EN			BIT(7)
 #define PHY_REF_CLK_SEL			BIT(10)
-#define MISC_REG0_DEFAULT_VALUE		0xA00D
+#define MISC_CTRL0_DEFAULT_VALUE	0xA00D
 
-#define COMPHY_REG_GEN2_SET_2	0x3e
-#define GEN2_SETTING_2_ADDR(unit)	(COMPHY_REG_GEN2_SET_2 * PHY_SHFT(unit))
-#define G2_TX_SSC_AMP_VALUE_20		BIT(14)
-#define G2_TX_SSC_AMP_OFF		9
-#define G2_TX_SSC_AMP_LEN		7
-#define G2_TX_SSC_AMP_MASK		(((1 << G2_TX_SSC_AMP_LEN) - 1) << \
-					 G2_TX_SSC_AMP_OFF)
-
-#define COMPHY_REG_GEN2_SET_3	0x3f
-#define GEN2_SETTING_3_ADDR(unit)	(COMPHY_REG_GEN2_SET_3 * PHY_SHFT(unit))
-#define G3_TX_SSC_AMP_OFF		9
-#define G3_TX_SSC_AMP_LEN		7
-#define G3_TX_SSC_AMP_MASK		(((1 << G2_TX_SSC_AMP_LEN) - 1) << \
-					 G2_TX_SSC_AMP_OFF)
-#define G3_VREG_RXTX_MAS_ISET_OFF	7
-#define G3_VREG_RXTX_MAS_ISET_60U	(0 << G3_VREG_RXTX_MAS_ISET_OFF)
-#define G3_VREG_RXTX_MAS_ISET_80U	(1 << G3_VREG_RXTX_MAS_ISET_OFF)
-#define G3_VREG_RXTX_MAS_ISET_100U	(2 << G3_VREG_RXTX_MAS_ISET_OFF)
-#define G3_VREG_RXTX_MAS_ISET_120U	(3 << G3_VREG_RXTX_MAS_ISET_OFF)
-#define G3_VREG_RXTX_MAS_ISET_MASK	(BIT(7) | BIT(8))
-#define RSVD_PH03FH_6_0_OFF		0
-#define RSVD_PH03FH_6_0_LEN		7
-#define RSVD_PH03FH_6_0_MASK		(((1 << RSVD_PH03FH_6_0_LEN) - 1) << \
-					 RSVD_PH03FH_6_0_OFF)
-
-#define COMPHY_REG_UNIT_CTRL_ADDR	0x48
-#define UNIT_CTRL_ADDR(unit)		(COMPHY_REG_UNIT_CTRL_ADDR * \
-					 PHY_SHFT(unit))
-#define IDLE_SYNC_EN			BIT(12)
-#define UNIT_CTRL_DEFAULT_VALUE		0x60
-
-#define COMPHY_MISC_REG1_ADDR		0x73
-#define MISC_REG1_ADDR(unit)		(COMPHY_MISC_REG1_ADDR * PHY_SHFT(unit))
+#define COMPHY_MISC_CTRL1		0x73
+#define MISC_CTRL1_ADDR(unit)		(COMPHY_MISC_CTRL1 * PHY_SHFT(unit))
 #define SEL_BITS_PCIE_FORCE		BIT(15)
 
-#define COMPHY_REG_GEN3_SETTINGS_3	0x112
-#define COMPHY_GEN_FFE_CAP_SEL_MASK	0xF
-#define COMPHY_GEN_FFE_CAP_SEL_VALUE	0xF
+#define COMPHY_GEN2_SET3		0x112
+#define GS3_FFE_CAP_SEL_MASK		0xF
+#define GS3_FFE_CAP_SEL_VALUE		0xF
 
-#define COMPHY_REG_LANE_CFG0_ADDR	0x180
-#define LANE_CFG0_ADDR(unit)		(COMPHY_REG_LANE_CFG0_ADDR * \
-					 PHY_SHFT(unit))
+#define COMPHY_LANE_CFG0		0x180
+#define LANE_CFG0_ADDR(unit)		(COMPHY_LANE_CFG0 * PHY_SHFT(unit))
 #define PRD_TXDEEMPH0_MASK		BIT(0)
 #define PRD_TXMARGIN_MASK		(BIT(1) | BIT(2) | BIT(3))
 #define PRD_TXSWING_MASK		BIT(4)
 #define CFG_TX_ALIGN_POS_MASK		(BIT(5) | BIT(6) | BIT(7) | BIT(8))
 
-#define COMPHY_REG_LANE_CFG1_ADDR	0x181
-#define LANE_CFG1_ADDR(unit)		(COMPHY_REG_LANE_CFG1_ADDR * \
-					 PHY_SHFT(unit))
+#define COMPHY_LANE_CFG1		0x181
+#define LANE_CFG1_ADDR(unit)		(COMPHY_LANE_CFG1 * PHY_SHFT(unit))
 #define PRD_TXDEEMPH1_MASK		BIT(15)
 #define USE_MAX_PLL_RATE_EN		BIT(9)
 #define TX_DET_RX_MODE			BIT(6)
@@ -166,21 +154,17 @@
 #define GEN2_TX_DATA_DLY_DEFT		(2 << 3)
 #define TX_ELEC_IDLE_MODE_EN		BIT(0)
 
-#define COMPHY_REG_LANE_STATUS1_ADDR	0x183
-#define LANE_STATUS1_ADDR(unit)		(COMPHY_REG_LANE_STATUS1_ADDR * \
-					 PHY_SHFT(unit))
+#define COMPHY_LANE_STAT1		0x183
+#define LANE_STAT1_ADDR(unit)		(COMPHY_LANE_STAT1 * PHY_SHFT(unit))
 #define TXDCLK_PCLK_EN				BIT(0)
 
-#define COMPHY_REG_LANE_CFG4_ADDR	0x188
-#define LANE_CFG4_ADDR(unit)		(COMPHY_REG_LANE_CFG4_ADDR * \
-					 PHY_SHFT(unit))
+#define COMPHY_LANE_CFG4		0x188
+#define LANE_CFG4_ADDR(unit)		(COMPHY_LANE_CFG4 * PHY_SHFT(unit))
 #define SPREAD_SPECTRUM_CLK_EN		BIT(7)
 
-#define COMPHY_REG_GLOB_PHY_CTRL0_ADDR	0x1C1
-#define GLOB_PHY_CTRL0_ADDR(unit)	(COMPHY_REG_GLOB_PHY_CTRL0_ADDR * \
-					 PHY_SHFT(unit))
+#define COMPHY_RST_CLK_CTRL		0x1C1
+#define RST_CLK_CTRL_ADDR(unit)		(COMPHY_RST_CLK_CTRL * PHY_SHFT(unit))
 #define SOFT_RESET			BIT(0)
-#define MODE_REFDIV			0x30
 #define MODE_CORE_CLK_FREQ_SEL		BIT(9)
 #define MODE_PIPE_WIDTH_32		BIT(3)
 #define MODE_REFDIV_OFFSET		4
@@ -188,24 +172,21 @@
 #define MODE_REFDIV_MASK		(0x3 << MODE_REFDIV_OFFSET)
 #define MODE_REFDIV_BY_4		(0x2 << MODE_REFDIV_OFFSET)
 
-#define COMPHY_REG_TEST_MODE_CTRL_ADDR	0x1C2
-#define TEST_MODE_CTRL_ADDR(unit)	(COMPHY_REG_TEST_MODE_CTRL_ADDR * \
-					 PHY_SHFT(unit))
+#define COMPHY_TEST_MODE_CTRL		0x1C2
+#define TEST_MODE_CTRL_ADDR(unit)	(COMPHY_TEST_MODE_CTRL * PHY_SHFT(unit))
 #define MODE_MARGIN_OVERRIDE		BIT(2)
 
-#define COMPHY_REG_GLOB_CLK_SRC_LO_ADDR	0x1C3
-#define GLOB_CLK_SRC_LO_ADDR(unit)	(COMPHY_REG_GLOB_CLK_SRC_LO_ADDR * \
-					 PHY_SHFT(unit))
+#define COMPHY_CLK_SRC_LO		0x1C3
+#define CLK_SRC_LO_ADDR(unit)		(COMPHY_CLK_SRC_LO * PHY_SHFT(unit))
 #define MODE_CLK_SRC			BIT(0)
 #define BUNDLE_PERIOD_SEL		BIT(1)
-#define BUNDLE_PERIOD_SCALE		(BIT(2) | BIT(3))
+#define BUNDLE_PERIOD_SCALE_MASK	(BIT(2) | BIT(3))
 #define BUNDLE_SAMPLE_CTRL		BIT(4)
-#define PLL_READY_DLY			(BIT(5) | BIT(6) | BIT(7))
+#define PLL_READY_DLY_MASK		(BIT(5) | BIT(6) | BIT(7))
 #define CFG_SEL_20B			BIT(15)
 
-#define COMPHY_REG_PWR_MGM_TIM1_ADDR	0x1D0
-#define PWR_MGM_TIM1_ADDR(unit)		(COMPHY_REG_PWR_MGM_TIM1_ADDR * \
-					 PHY_SHFT(unit))
+#define COMPHY_PWR_MGM_TIM1		0x1D0
+#define PWR_MGM_TIM1_ADDR(unit)		(COMPHY_PWR_MGM_TIM1 * PHY_SHFT(unit))
 #define CFG_PM_OSCCLK_WAIT_OFF		12
 #define CFG_PM_OSCCLK_WAIT_LEN		4
 #define CFG_PM_OSCCLK_WAIT_MASK		(((1 << CFG_PM_OSCCLK_WAIT_LEN) - 1) \
@@ -222,9 +203,18 @@
 #define CFG_PM_RXDLOZ_WAIT_7_UNIT	(7 << CFG_PM_RXDLOZ_WAIT_OFF)
 #define CFG_PM_RXDLOZ_WAIT_12_UNIT	(0xC << CFG_PM_RXDLOZ_WAIT_OFF)
 
+/*
+ * This register is not from PHY lane register space. It only exists in the
+ * indirect register space, before the actual PHY lane 2 registers. So the
+ * offset is absolute, not relative to SATAPHY_LANE2_REG_BASE_OFFSET.
+ * It is used only for SATA PHY initialization.
+ */
+#define COMPHY_RESERVED_REG		0x0E
+#define PHYCTRL_FRM_PIN_BIT		BIT(13)
+
 /* SGMII */
 #define COMPHY_PHY_CFG1_OFFSET(lane)	((1 - (lane)) * 0x28)
-#define PIN_PU_IVEREF_BIT		BIT(1)
+#define PIN_PU_IVREF_BIT		BIT(1)
 #define PIN_RESET_CORE_BIT		BIT(11)
 #define PIN_RESET_COMPHY_BIT		BIT(12)
 #define PIN_PU_PLL_BIT			BIT(16)
@@ -237,11 +227,11 @@
 #define GEN_TX_SEL_MASK			(0xF << GEN_TX_SEL_OFFSET)
 #define PHY_RX_INIT_BIT			BIT(30)
 #define SD_SPEED_1_25_G			0x6
-#define SD_SPEED_2_5_G			0x8
+#define SD_SPEED_3_125_G		0x8
 
 /* COMPHY status reg:
- * lane0: PCIe/GbE0 PHY Status 1
- * lane1: USB3/GbE1 PHY Status 1
+ * lane0: USB3/GbE1 PHY Status 1
+ * lane1: PCIe/GbE0 PHY Status 1
  */
 #define COMPHY_PHY_STATUS_OFFSET(lane)	(0x18 + (1 - (lane)) * 0x28)
 #define PHY_RX_INIT_DONE_BIT		BIT(0)
diff --git a/drivers/marvell/comphy/phy-comphy-common.h b/drivers/marvell/comphy/phy-comphy-common.h
index c599437..ba5d255 100644
--- a/drivers/marvell/comphy/phy-comphy-common.h
+++ b/drivers/marvell/comphy/phy-comphy-common.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 Marvell International Ltd.
+ * Copyright (C) 2018-2021 Marvell International Ltd.
  *
  * SPDX-License-Identifier:     BSD-3-Clause
  * https://spdx.org/licenses
@@ -147,7 +147,7 @@
 	debug("<atf>: WR to addr = 0x%lx, data = 0x%x (mask = 0x%x) - ",
 	      addr, data, mask);
 	debug("old value = 0x%x ==> ", mmio_read_32(addr));
-	mmio_clrsetbits_32(addr, mask, data);
+	mmio_clrsetbits_32(addr, mask, data & mask);
 
 	debug("new val 0x%x\n", mmio_read_32(addr));
 }
@@ -159,7 +159,7 @@
 	debug("<atf>: WR to addr = 0x%lx, data = 0x%x (mask = 0x%x) - ",
 	      addr, data, mask);
 	debug("old value = 0x%x ==> ", mmio_read_16(addr));
-	mmio_clrsetbits_16(addr, mask, data);
+	mmio_clrsetbits_16(addr, mask, data & mask);
 
 	debug("new val 0x%x\n", mmio_read_16(addr));
 }
diff --git a/drivers/marvell/uart/a3700_console.S b/drivers/marvell/uart/a3700_console.S
index 218fd86..c7eb165 100644
--- a/drivers/marvell/uart/a3700_console.S
+++ b/drivers/marvell/uart/a3700_console.S
@@ -34,7 +34,7 @@
 	 *     w1 - Uart clock in Hz
 	 *     w2 - Baud rate
 	 * Out: return 1 on success
-	 * Clobber list : x1, x2, x3
+	 * Clobber list : x1, x2, x3, x4
 	 * -----------------------------------------------
 	 */
 func console_a3700_core_init
@@ -44,24 +44,11 @@
 	cbz	w1, init_fail
 	cbz	w2, init_fail
 
-	/* Program the baudrate */
-	/* Divisor = Round(Uartclock / (16 * baudrate)) */
-	lsl	w2, w2, #4
-	add	w1, w1, w2, lsr #1
-	udiv	w2, w1, w2
-	and	w2, w2, #0x3ff /* clear all other bits to use default clock */
-
-	str	w2, [x0, #UART_BAUD_REG]/* set baud rate divisor */
-
-	/* Set UART to default 16X scheme */
-	mov	w3, #0
-	str	w3, [x0, #UART_POSSR_REG]
-
 	/*
 	 * Wait for the TX (THR and TSR) to be empty. If wait for 3ms, the TX FIFO is
 	 * still not empty, TX FIFO will reset by all means.
 	 */
-	mov	w1, #30				/* max time out 30 * 100 us */
+	mov	w4, #30				/* max time out 30 * 100 us */
 2:
 	/* Check whether TX (THR and TSR) is empty */
 	ldr	w3, [x0, #UART_STATUS_REG]
@@ -70,30 +57,51 @@
 	b.ne	4f
 
 	/* Delay */
-	mov	w2, #60000	/* 60000 cycles of below 3 instructions on 1200 MHz CPU ~~ 100 us */
+	mov	w3, #60000	/* 60000 cycles of below 3 instructions on 1200 MHz CPU ~~ 100 us */
 3:
-	sub     w2, w2, #1
-	cmp	w2, #0
+	sub	w3, w3, #1
+	cmp	w3, #0
 	b.ne	3b
 
 	/* Check whether wait timeout expired */
-	sub     w1, w1, #1
-	cmp	w1, #0
+	sub	w4, w4, #1
+	cmp	w4, #0
 	b.ne	2b
 
 4:
+	/* Reset UART via North Bridge Peripheral */
+	mov_imm	x4, MVEBU_NB_RESET_REG
+	ldr	w3, [x4]
+	bic	w3, w3, #MVEBU_NB_RESET_UART_N
+	str	w3, [x4]
+	orr	w3, w3, #MVEBU_NB_RESET_UART_N
+	str	w3, [x4]
+
 	/* Reset FIFO */
 	mov	w3, #UART_CTRL_RXFIFO_RESET
 	orr	w3, w3, #UART_CTRL_TXFIFO_RESET
 	str	w3, [x0, #UART_CTRL_REG]
 
 	/* Delay */
-	mov	w2, #2000
+	mov	w3, #2000
 1:
-	sub     w2, w2, #1
-	cmp	w2, #0
+	sub	w3, w3, #1
+	cmp	w3, #0
 	b.ne	1b
 
+	/* Program the baudrate */
+	/* Divisor = Round(Uartclock / (16 * baudrate)) */
+	lsl	w2, w2, #4
+	add	w1, w1, w2, lsr #1
+	udiv	w2, w1, w2
+	and	w2, w2, #0x3ff /* clear all other bits to use default clock */
+
+	str	w2, [x0, #UART_BAUD_REG]/* set baud rate divisor */
+
+	/* Set UART to default 16X scheme */
+	mov	w3, #0
+	str	w3, [x0, #UART_POSSR_REG]
+
 	/* No Parity, 1 Stop */
 	mov	w3, #0
 	str	w3, [x0, #UART_CTRL_REG]
@@ -118,7 +126,7 @@
 	 *     w2 - Baud rate
 	 *     x3 - pointer to empty console_t struct
 	 * Out: return 1 on success, 0 on error
-	 * Clobber list : x0, x1, x2, x6, x7, x14
+	 * Clobber list : x0, x1, x2, x3, x4, x6, x7, x14
 	 * -----------------------------------------------
 	 */
 func console_a3700_register
diff --git a/drivers/measured_boot/event_log/event_log.c b/drivers/measured_boot/event_log/event_log.c
index 1755dd9..792f235 100644
--- a/drivers/measured_boot/event_log/event_log.c
+++ b/drivers/measured_boot/event_log/event_log.c
@@ -13,10 +13,19 @@
 #include <common/debug.h>
 #include <drivers/auth/crypto_mod.h>
 #include <drivers/measured_boot/event_log/event_log.h>
-#include <mbedtls/md.h>
 
 #include <plat/common/platform.h>
 
+#if TPM_ALG_ID == TPM_ALG_SHA512
+#define	CRYPTO_MD_ID	CRYPTO_MD_SHA512
+#elif TPM_ALG_ID == TPM_ALG_SHA384
+#define	CRYPTO_MD_ID	CRYPTO_MD_SHA384
+#elif TPM_ALG_ID == TPM_ALG_SHA256
+#define	CRYPTO_MD_ID	CRYPTO_MD_SHA256
+#else
+#  error Invalid TPM algorithm.
+#endif /* TPM_ALG_ID */
+
 /* Running Event Log Pointer */
 static uint8_t *log_ptr;
 
@@ -245,20 +254,20 @@
 int event_log_measure_and_record(uintptr_t data_base, uint32_t data_size,
 				 uint32_t data_id)
 {
-	unsigned char hash_data[MBEDTLS_MD_MAX_SIZE];
+	unsigned char hash_data[CRYPTO_MD_MAX_SIZE];
 	int rc;
 	const event_log_metadata_t *metadata_ptr = plat_metadata_ptr;
 
 	/* Get the metadata associated with this image. */
-	while ((metadata_ptr->id != INVALID_ID) &&
+	while ((metadata_ptr->id != EVLOG_INVALID_ID) &&
 		(metadata_ptr->id != data_id)) {
 		metadata_ptr++;
 	}
-	assert(metadata_ptr->id != INVALID_ID);
+	assert(metadata_ptr->id != EVLOG_INVALID_ID);
 
 	/* Calculate hash */
-	rc = crypto_mod_calc_hash((unsigned int)MBEDTLS_MD_ID,
-				(void *)data_base, data_size, hash_data);
+	rc = crypto_mod_calc_hash(CRYPTO_MD_ID,
+				  (void *)data_base, data_size, hash_data);
 	if (rc != 0) {
 		return rc;
 	}
diff --git a/drivers/measured_boot/event_log/event_log.mk b/drivers/measured_boot/event_log/event_log.mk
index 37e5e29..d3fbbb5 100644
--- a/drivers/measured_boot/event_log/event_log.mk
+++ b/drivers/measured_boot/event_log/event_log.mk
@@ -12,35 +12,24 @@
 TPM_HASH_ALG			:=	sha256
 
 ifeq (${TPM_HASH_ALG}, sha512)
-    MBEDTLS_MD_ID		:=	MBEDTLS_MD_SHA512
     TPM_ALG_ID			:=	TPM_ALG_SHA512
     TCG_DIGEST_SIZE		:=	64U
 else ifeq (${TPM_HASH_ALG}, sha384)
-    MBEDTLS_MD_ID		:=	MBEDTLS_MD_SHA384
     TPM_ALG_ID			:=	TPM_ALG_SHA384
     TCG_DIGEST_SIZE		:=	48U
 else
-    MBEDTLS_MD_ID		:=	MBEDTLS_MD_SHA256
     TPM_ALG_ID			:=	TPM_ALG_SHA256
     TCG_DIGEST_SIZE		:=	32U
-endif
+endif #TPM_HASH_ALG
 
-
-# Set definitions for mbed TLS library and Measured Boot driver
+# Set definitions for Measured Boot driver.
 $(eval $(call add_defines,\
     $(sort \
-        MBEDTLS_MD_ID \
         TPM_ALG_ID \
         TCG_DIGEST_SIZE \
         EVENT_LOG_LEVEL \
 )))
 
-ifeq (${HASH_ALG}, sha256)
-    ifneq (${TPM_HASH_ALG}, sha256)
-        $(eval $(call add_define,MBEDTLS_SHA512_C))
-    endif
-endif
-
 MEASURED_BOOT_SRC_DIR	:= drivers/measured_boot/event_log/
 
 MEASURED_BOOT_SOURCES	:= ${MEASURED_BOOT_SRC_DIR}event_log.c		\
diff --git a/drivers/st/clk/stm32mp1_clk.c b/drivers/st/clk/stm32mp1_clk.c
index 3ebc376..684ab1a 100644
--- a/drivers/st/clk/stm32mp1_clk.c
+++ b/drivers/st/clk/stm32mp1_clk.c
@@ -17,6 +17,7 @@
 #include <arch_helpers.h>
 #include <common/debug.h>
 #include <common/fdt_wrappers.h>
+#include <drivers/clk.h>
 #include <drivers/delay_timer.h>
 #include <drivers/generic_delay_timer.h>
 #include <drivers/st/stm32mp_clkfunc.h>
@@ -1157,17 +1158,19 @@
 	stm32mp1_clk_unlock(&refcount_lock);
 }
 
-void stm32mp_clk_enable(unsigned long id)
+static int stm32mp_clk_enable(unsigned long id)
 {
 	__stm32mp1_clk_enable(id, true);
+
+	return 0;
 }
 
-void stm32mp_clk_disable(unsigned long id)
+static void stm32mp_clk_disable(unsigned long id)
 {
 	__stm32mp1_clk_disable(id, true);
 }
 
-bool stm32mp_clk_is_enabled(unsigned long id)
+static bool stm32mp_clk_is_enabled(unsigned long id)
 {
 	int i;
 
@@ -1183,15 +1186,55 @@
 	return __clk_is_enabled(gate_ref(i));
 }
 
-unsigned long stm32mp_clk_get_rate(unsigned long id)
+static unsigned long stm32mp_clk_get_rate(unsigned long id)
 {
+	uintptr_t rcc_base = stm32mp_rcc_base();
 	int p = stm32mp1_clk_get_parent(id);
+	uint32_t prescaler, timpre;
+	unsigned long parent_rate;
 
 	if (p < 0) {
 		return 0;
 	}
 
+	parent_rate = get_clock_rate(p);
+
-	return get_clock_rate(p);
+	switch (id) {
+	case TIM2_K:
+	case TIM3_K:
+	case TIM4_K:
+	case TIM5_K:
+	case TIM6_K:
+	case TIM7_K:
+	case TIM12_K:
+	case TIM13_K:
+	case TIM14_K:
+		prescaler = mmio_read_32(rcc_base + RCC_APB1DIVR) &
+			    RCC_APBXDIV_MASK;
+		timpre = mmio_read_32(rcc_base + RCC_TIMG1PRER) &
+			 RCC_TIMGXPRER_TIMGXPRE;
+		break;
+
+	case TIM1_K:
+	case TIM8_K:
+	case TIM15_K:
+	case TIM16_K:
+	case TIM17_K:
+		prescaler = mmio_read_32(rcc_base + RCC_APB2DIVR) &
+			    RCC_APBXDIV_MASK;
+		timpre = mmio_read_32(rcc_base + RCC_TIMG2PRER) &
+			 RCC_TIMGXPRER_TIMGXPRE;
+		break;
+
+	default:
+		return parent_rate;
+	}
+
+	if (prescaler == 0U) {
+		return parent_rate;
+	}
+
+	return parent_rate * (timpre + 1U) * 2U;
 }
 
 static void stm32mp1_ls_osc_set(bool enable, uint32_t offset, uint32_t mask_on)
@@ -1744,6 +1787,8 @@
 	bool pll4_bootrom = false;
 	const fdt32_t *pkcs_cell;
 	void *fdt;
+	int stgen_p = stm32mp1_clk_get_parent(STGEN_K);
+	int usbphy_p = stm32mp1_clk_get_parent(USBPHY_K);
 
 	if (fdt_get_address(&fdt) == 0) {
 		return -FDT_ERR_NOTFOUND;
@@ -1843,6 +1888,13 @@
 							pllcfg[_PLL4],
 							plloff[_PLL4]);
 	}
+	/* Don't initialize PLL4, when used by BOOTROM */
+	if ((stm32mp_get_boot_itf_selected() ==
+	     BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB) &&
+	    ((stgen_p == (int)_PLL4_R) || (usbphy_p == (int)_PLL4_R))) {
+		pll4_bootrom = true;
+		pll4_preserve = true;
+	}
 
 	for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
 		if (((i == _PLL3) && pll3_preserve) ||
@@ -1994,6 +2046,11 @@
 	if (pkcs_cell != NULL) {
 		bool ckper_disabled = false;
 		uint32_t j;
+		uint32_t usbreg_bootrom = 0U;
+
+		if (pll4_bootrom) {
+			usbreg_bootrom = mmio_read_32(rcc_base + RCC_USBCKSELR);
+		}
 
 		for (j = 0; j < ((uint32_t)len / sizeof(uint32_t)); j++) {
 			uint32_t pkcs = fdt32_to_cpu(pkcs_cell[j]);
@@ -2014,6 +2071,25 @@
 		if (ckper_disabled) {
 			stm32mp1_pkcs_config(CLK_CKPER_DISABLED);
 		}
+
+		if (pll4_bootrom) {
+			uint32_t usbreg_value, usbreg_mask;
+			const struct stm32mp1_clk_sel *sel;
+
+			sel = clk_sel_ref(_USBPHY_SEL);
+			usbreg_mask = (uint32_t)sel->msk << sel->src;
+			sel = clk_sel_ref(_USBO_SEL);
+			usbreg_mask |= (uint32_t)sel->msk << sel->src;
+
+			usbreg_value = mmio_read_32(rcc_base + RCC_USBCKSELR) &
+				       usbreg_mask;
+			usbreg_bootrom &= usbreg_mask;
+			if (usbreg_bootrom != usbreg_value) {
+				VERBOSE("forbidden new USB clk path\n");
+				VERBOSE("vs bootrom on USB boot\n");
+				return -FDT_ERR_BADVALUE;
+			}
+		}
 	}
 
 	/* Switch OFF HSI if not found in device-tree */
@@ -2231,11 +2307,21 @@
 	}
 }
 
+static const struct clk_ops stm32mp_clk_ops = {
+	.enable		= stm32mp_clk_enable,
+	.disable	= stm32mp_clk_disable,
+	.is_enabled	= stm32mp_clk_is_enabled,
+	.get_rate	= stm32mp_clk_get_rate,
+	.get_parent	= stm32mp1_clk_get_parent,
+};
+
 int stm32mp1_clk_probe(void)
 {
 	stm32mp1_osc_init();
 
 	sync_earlyboot_clocks_state();
 
+	clk_register(&stm32mp_clk_ops);
+
 	return 0;
 }
diff --git a/drivers/st/clk/stm32mp_clkfunc.c b/drivers/st/clk/stm32mp_clkfunc.c
index d57f120..c83b8ad 100644
--- a/drivers/st/clk/stm32mp_clkfunc.c
+++ b/drivers/st/clk/stm32mp_clkfunc.c
@@ -11,9 +11,11 @@
 #include <platform_def.h>
 
 #include <common/fdt_wrappers.h>
+#include <drivers/clk.h>
 #include <drivers/st/stm32_gpio.h>
 #include <drivers/st/stm32mp_clkfunc.h>
 
+#define DT_UART_COMPAT		"st,stm32h7-uart"
 /*
  * Get the frequency of an oscillator from its name in device tree.
  * @param name: oscillator name
@@ -297,3 +299,32 @@
 	cuint++;
 	return (int)fdt32_to_cpu(*cuint);
 }
+
+/*
+ * Get the frequency of the specified UART instance.
+ * @param instance: UART interface registers base address.
+ * @return: clock frequency on success, 0 value on failure.
+ */
+unsigned long fdt_get_uart_clock_freq(uintptr_t instance)
+{
+	void *fdt;
+	int node;
+	int clk_id;
+
+	if (fdt_get_address(&fdt) == 0) {
+		return 0UL;
+	}
+
+	/* Check for UART nodes */
+	node = dt_match_instance_by_compatible(DT_UART_COMPAT, instance);
+	if (node < 0) {
+		return 0UL;
+	}
+
+	clk_id = fdt_get_clock_id(node);
+	if (clk_id < 0) {
+		return 0UL;
+	}
+
+	return clk_get_rate((unsigned long)clk_id);
+}
diff --git a/drivers/st/crypto/stm32_hash.c b/drivers/st/crypto/stm32_hash.c
index 317fd9e..6a1d476 100644
--- a/drivers/st/crypto/stm32_hash.c
+++ b/drivers/st/crypto/stm32_hash.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2020, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -14,6 +14,7 @@
 
 #include <arch_helpers.h>
 #include <common/debug.h>
+#include <drivers/clk.h>
 #include <drivers/delay_timer.h>
 #include <drivers/st/stm32_hash.h>
 #include <drivers/st/stm32mp_reset.h>
@@ -189,7 +190,7 @@
 		return 0;
 	}
 
-	stm32mp_clk_enable(stm32_hash.clock);
+	clk_enable(stm32_hash.clock);
 
 	if (stm32_remain.length != 0U) {
 		uint32_t copysize;
@@ -231,7 +232,7 @@
 	}
 
 exit:
-	stm32mp_clk_disable(stm32_hash.clock);
+	clk_disable(stm32_hash.clock);
 
 	return ret;
 }
@@ -240,12 +241,12 @@
 {
 	int ret;
 
-	stm32mp_clk_enable(stm32_hash.clock);
+	clk_enable(stm32_hash.clock);
 
 	if (stm32_remain.length != 0U) {
 		ret = hash_write_data(stm32_remain.buffer);
 		if (ret != 0) {
-			stm32mp_clk_disable(stm32_hash.clock);
+			clk_disable(stm32_hash.clock);
 			return ret;
 		}
 
@@ -260,7 +261,7 @@
 
 	ret = hash_get_digest(digest);
 
-	stm32mp_clk_disable(stm32_hash.clock);
+	clk_disable(stm32_hash.clock);
 
 	return ret;
 }
@@ -280,11 +281,11 @@
 
 void stm32_hash_init(enum stm32_hash_algo_mode mode)
 {
-	stm32mp_clk_enable(stm32_hash.clock);
+	clk_enable(stm32_hash.clock);
 
 	hash_hw_init(mode);
 
-	stm32mp_clk_disable(stm32_hash.clock);
+	clk_disable(stm32_hash.clock);
 
 	zeromem(&stm32_remain, sizeof(stm32_remain));
 }
@@ -321,7 +322,7 @@
 	stm32_hash.base = hash_info.base;
 	stm32_hash.clock = hash_info.clock;
 
-	stm32mp_clk_enable(stm32_hash.clock);
+	clk_enable(stm32_hash.clock);
 
 	if (hash_info.reset >= 0) {
 		uint32_t id = (uint32_t)hash_info.reset;
@@ -335,7 +336,7 @@
 		}
 	}
 
-	stm32mp_clk_disable(stm32_hash.clock);
+	clk_disable(stm32_hash.clock);
 
 	return 0;
 }
diff --git a/drivers/st/ddr/stm32mp1_ddr.c b/drivers/st/ddr/stm32mp1_ddr.c
index 7d89d02..3db47c4 100644
--- a/drivers/st/ddr/stm32mp1_ddr.c
+++ b/drivers/st/ddr/stm32mp1_ddr.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018-2019, STMicroelectronics - All Rights Reserved
+ * Copyright (C) 2018-2021, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
  */
@@ -12,6 +12,7 @@
 #include <arch.h>
 #include <arch_helpers.h>
 #include <common/debug.h>
+#include <drivers/clk.h>
 #include <drivers/delay_timer.h>
 #include <drivers/st/stm32mp_pmic.h>
 #include <drivers/st/stm32mp1_ddr.h>
@@ -627,7 +628,7 @@
 	 */
 
 	/* Change Bypass Mode Frequency Range */
-	if (stm32mp_clk_get_rate(DDRPHYC) < 100000000U) {
+	if (clk_get_rate(DDRPHYC) < 100000000U) {
 		mmio_clrbits_32((uintptr_t)&priv->phy->dllgcr,
 				DDRPHYC_DLLGCR_BPS200);
 	} else {
diff --git a/drivers/st/ddr/stm32mp1_ram.c b/drivers/st/ddr/stm32mp1_ram.c
index b21c894..064e318 100644
--- a/drivers/st/ddr/stm32mp1_ram.c
+++ b/drivers/st/ddr/stm32mp1_ram.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018-2020, STMicroelectronics - All Rights Reserved
+ * Copyright (C) 2018-2021, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
  */
@@ -13,6 +13,7 @@
 #include <arch_helpers.h>
 #include <common/debug.h>
 #include <common/fdt_wrappers.h>
+#include <drivers/clk.h>
 #include <drivers/st/stm32mp1_ddr.h>
 #include <drivers/st/stm32mp1_ddr_helpers.h>
 #include <drivers/st/stm32mp1_ram.h>
@@ -29,7 +30,7 @@
 
 	ddr_enable_clock();
 
-	ddrphy_clk = stm32mp_clk_get_rate(DDRPHYC);
+	ddrphy_clk = clk_get_rate(DDRPHYC);
 
 	VERBOSE("DDR: mem_speed (%d kHz), RCC %ld kHz\n",
 		mem_speed, ddrphy_clk / 1000U);
diff --git a/drivers/st/fmc/stm32_fmc2_nand.c b/drivers/st/fmc/stm32_fmc2_nand.c
index 453069b..e9ab6da 100644
--- a/drivers/st/fmc/stm32_fmc2_nand.c
+++ b/drivers/st/fmc/stm32_fmc2_nand.c
@@ -14,6 +14,7 @@
 #include <platform_def.h>
 
 #include <common/debug.h>
+#include <drivers/clk.h>
 #include <drivers/delay_timer.h>
 #include <drivers/raw_nand.h>
 #include <drivers/st/stm32_fmc2_nand.h>
@@ -162,7 +163,7 @@
 static void stm32_fmc2_nand_setup_timing(void)
 {
 	struct stm32_fmc2_nand_timings tims;
-	unsigned long hclk = stm32mp_clk_get_rate(stm32_fmc2.clock_id);
+	unsigned long hclk = clk_get_rate(stm32_fmc2.clock_id);
 	unsigned long hclkp = FMC2_PSEC_PER_MSEC / (hclk / 1000U);
 	unsigned long timing, tar, tclr, thiz, twait;
 	unsigned long tset_mem, tset_att, thold_mem, thold_att;
@@ -909,7 +910,7 @@
 	}
 
 	/* Enable Clock */
-	stm32mp_clk_enable(stm32_fmc2.clock_id);
+	clk_enable(stm32_fmc2.clock_id);
 
 	/* Reset IP */
 	ret = stm32mp_reset_assert(stm32_fmc2.reset_id, TIMEOUT_US_1_MS);
diff --git a/drivers/st/gpio/stm32_gpio.c b/drivers/st/gpio/stm32_gpio.c
index 7d63262..5c54762 100644
--- a/drivers/st/gpio/stm32_gpio.c
+++ b/drivers/st/gpio/stm32_gpio.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2020, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2016-2021, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -14,6 +14,7 @@
 
 #include <common/bl_common.h>
 #include <common/debug.h>
+#include <drivers/clk.h>
 #include <drivers/st/stm32_gpio.h>
 #include <drivers/st/stm32mp_clkfunc.h>
 #include <lib/mmio.h>
@@ -208,7 +209,7 @@
 
 	assert(pin <= GPIO_PIN_MAX);
 
-	stm32mp_clk_enable(clock);
+	clk_enable(clock);
 
 	mmio_clrbits_32(base + GPIO_MODE_OFFSET,
 			((uint32_t)GPIO_MODE_MASK << (pin << 1)));
@@ -254,7 +255,7 @@
 	VERBOSE("GPIO %u mode alternate high to 0x%x\n", bank,
 		mmio_read_32(base + GPIO_AFRH_OFFSET));
 
-	stm32mp_clk_disable(clock);
+	clk_disable(clock);
 
 	if (status == DT_SECURE) {
 		stm32mp_register_secure_gpio(bank, pin);
@@ -273,7 +274,7 @@
 
 	assert(pin <= GPIO_PIN_MAX);
 
-	stm32mp_clk_enable(clock);
+	clk_enable(clock);
 
 	if (secure) {
 		mmio_setbits_32(base + GPIO_SECR_OFFSET, BIT(pin));
@@ -281,5 +282,12 @@
 		mmio_clrbits_32(base + GPIO_SECR_OFFSET, BIT(pin));
 	}
 
-	stm32mp_clk_disable(clock);
+	clk_disable(clock);
+}
+
+void set_gpio_reset_cfg(uint32_t bank, uint32_t pin)
+{
+	set_gpio(bank, pin, GPIO_MODE_ANALOG, GPIO_SPEED_LOW,
+		 GPIO_NO_PULL, GPIO_ALTERNATE_(0), DT_DISABLED);
+	set_gpio_secure_cfg(bank, pin, stm32_gpio_is_secure_at_reset(bank));
 }
diff --git a/drivers/st/i2c/stm32_i2c.c b/drivers/st/i2c/stm32_i2c.c
index ed88052..bf6c3ee 100644
--- a/drivers/st/i2c/stm32_i2c.c
+++ b/drivers/st/i2c/stm32_i2c.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2016-2021, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -13,6 +13,7 @@
 #include <platform_def.h>
 
 #include <common/debug.h>
+#include <drivers/clk.h>
 #include <drivers/delay_timer.h>
 #include <drivers/st/stm32_gpio.h>
 #include <drivers/st/stm32_i2c.h>
@@ -158,7 +159,7 @@
 
 	hi2c->i2c_state = I2C_STATE_BUSY;
 
-	stm32mp_clk_enable(hi2c->clock);
+	clk_enable(hi2c->clock);
 
 	/* Disable the selected I2C peripheral */
 	mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE);
@@ -220,11 +221,11 @@
 						I2C_ANALOGFILTER_DISABLE);
 	if (rc != 0) {
 		ERROR("Cannot initialize I2C analog filter (%d)\n", rc);
-		stm32mp_clk_disable(hi2c->clock);
+		clk_disable(hi2c->clock);
 		return rc;
 	}
 
-	stm32mp_clk_disable(hi2c->clock);
+	clk_disable(hi2c->clock);
 
 	return rc;
 }
@@ -548,7 +549,7 @@
 		return -EINVAL;
 	}
 
-	stm32mp_clk_enable(hi2c->clock);
+	clk_enable(hi2c->clock);
 
 	hi2c->lock = 1;
 
@@ -648,7 +649,7 @@
 
 bail:
 	hi2c->lock = 0;
-	stm32mp_clk_disable(hi2c->clock);
+	clk_disable(hi2c->clock);
 
 	return rc;
 }
@@ -729,7 +730,7 @@
 		return  -EINVAL;
 	}
 
-	stm32mp_clk_enable(hi2c->clock);
+	clk_enable(hi2c->clock);
 
 	hi2c->lock = 1;
 
@@ -817,7 +818,7 @@
 
 bail:
 	hi2c->lock = 0;
-	stm32mp_clk_disable(hi2c->clock);
+	clk_disable(hi2c->clock);
 
 	return rc;
 }
@@ -882,7 +883,7 @@
 		return rc;
 	}
 
-	stm32mp_clk_enable(hi2c->clock);
+	clk_enable(hi2c->clock);
 
 	hi2c->lock = 1;
 	hi2c->i2c_mode = I2C_MODE_NONE;
@@ -974,7 +975,7 @@
 
 bail:
 	hi2c->lock = 0;
-	stm32mp_clk_disable(hi2c->clock);
+	clk_disable(hi2c->clock);
 
 	return rc;
 }
diff --git a/drivers/st/iwdg/stm32_iwdg.c b/drivers/st/iwdg/stm32_iwdg.c
index c052b4d..74451d7 100644
--- a/drivers/st/iwdg/stm32_iwdg.c
+++ b/drivers/st/iwdg/stm32_iwdg.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2017-2021, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -15,6 +15,7 @@
 #include <arch_helpers.h>
 #include <common/debug.h>
 #include <drivers/arm/gicv2.h>
+#include <drivers/clk.h>
 #include <drivers/delay_timer.h>
 #include <drivers/st/stm32_iwdg.h>
 #include <drivers/st/stm32mp_clkfunc.h>
@@ -61,12 +62,12 @@
 
 		/* 0x00000000 is not a valid address for IWDG peripherals */
 		if (iwdg->base != 0U) {
-			stm32mp_clk_enable(iwdg->clock);
+			clk_enable(iwdg->clock);
 
 			mmio_write_32(iwdg->base + IWDG_KR_OFFSET,
 				      IWDG_KR_RELOAD_KEY);
 
-			stm32mp_clk_disable(iwdg->clock);
+			clk_disable(iwdg->clock);
 		}
 	}
 }
diff --git a/drivers/st/mmc/stm32_sdmmc2.c b/drivers/st/mmc/stm32_sdmmc2.c
index d3adeab..9db97d4 100644
--- a/drivers/st/mmc/stm32_sdmmc2.c
+++ b/drivers/st/mmc/stm32_sdmmc2.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2020, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2018-2021, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -15,6 +15,7 @@
 #include <arch.h>
 #include <arch_helpers.h>
 #include <common/debug.h>
+#include <drivers/clk.h>
 #include <drivers/delay_timer.h>
 #include <drivers/mmc.h>
 #include <drivers/st/stm32_gpio.h>
@@ -714,7 +715,7 @@
 		return -ENOMEM;
 	}
 
-	stm32mp_clk_enable(sdmmc2_params.clock_id);
+	clk_enable(sdmmc2_params.clock_id);
 
 	rc = stm32mp_reset_assert(sdmmc2_params.reset_id, TIMEOUT_US_1_MS);
 	if (rc != 0) {
@@ -727,7 +728,7 @@
 	}
 	mdelay(1);
 
-	sdmmc2_params.clk_rate = stm32mp_clk_get_rate(sdmmc2_params.clock_id);
+	sdmmc2_params.clk_rate = clk_get_rate(sdmmc2_params.clock_id);
 	sdmmc2_params.device_info->ocr_voltage = OCR_3_2_3_3 | OCR_3_3_3_4;
 
 	return mmc_init(&stm32_sdmmc2_ops, sdmmc2_params.clk_rate,
diff --git a/drivers/st/spi/stm32_qspi.c b/drivers/st/spi/stm32_qspi.c
index 4b1a029..d3c26d9 100644
--- a/drivers/st/spi/stm32_qspi.c
+++ b/drivers/st/spi/stm32_qspi.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2020, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
  */
@@ -11,6 +11,7 @@
 
 #include <common/debug.h>
 #include <common/fdt_wrappers.h>
+#include <drivers/clk.h>
 #include <drivers/delay_timer.h>
 #include <drivers/spi_mem.h>
 #include <drivers/st/stm32_gpio.h>
@@ -364,7 +365,7 @@
 
 static int stm32_qspi_set_speed(unsigned int hz)
 {
-	unsigned long qspi_clk = stm32mp_clk_get_rate(stm32_qspi.clock_id);
+	unsigned long qspi_clk = clk_get_rate(stm32_qspi.clock_id);
 	uint32_t prescaler = UINT8_MAX;
 	uint32_t csht;
 	int ret;
@@ -494,7 +495,7 @@
 	stm32_qspi.clock_id = (unsigned long)info.clock;
 	stm32_qspi.reset_id = (unsigned int)info.reset;
 
-	stm32mp_clk_enable(stm32_qspi.clock_id);
+	clk_enable(stm32_qspi.clock_id);
 
 	ret = stm32mp_reset_assert(stm32_qspi.reset_id, TIMEOUT_US_1_MS);
 	if (ret != 0) {
diff --git a/drivers/st/uart/stm32_uart.c b/drivers/st/uart/stm32_uart.c
new file mode 100644
index 0000000..e2e5405
--- /dev/null
+++ b/drivers/st/uart/stm32_uart.c
@@ -0,0 +1,404 @@
+/*
+ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include <common/bl_common.h>
+#include <drivers/delay_timer.h>
+#include <drivers/st/stm32_uart.h>
+#include <drivers/st/stm32_uart_regs.h>
+#include <drivers/st/stm32mp_clkfunc.h>
+#include <lib/mmio.h>
+
+#include <platform_def.h>
+
+/* UART time-out value */
+#define STM32_UART_TIMEOUT_US	20000U
+
+/* Mask to clear ALL the configuration registers */
+
+#define STM32_UART_CR1_FIELDS \
+		(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | USART_CR1_TE | \
+		 USART_CR1_RE | USART_CR1_OVER8 | USART_CR1_FIFOEN)
+
+#define STM32_UART_CR2_FIELDS \
+		(USART_CR2_SLVEN | USART_CR2_DIS_NSS | USART_CR2_ADDM7 | \
+		 USART_CR2_LBDL | USART_CR2_LBDIE | USART_CR2_LBCL | \
+		 USART_CR2_CPHA | USART_CR2_CPOL | USART_CR2_CLKEN | \
+		 USART_CR2_STOP | USART_CR2_LINEN | USART_CR2_SWAP | \
+		 USART_CR2_RXINV | USART_CR2_TXINV | USART_CR2_DATAINV | \
+		 USART_CR2_MSBFIRST | USART_CR2_ABREN | USART_CR2_ABRMODE | \
+		 USART_CR2_RTOEN | USART_CR2_ADD)
+
+#define STM32_UART_CR3_FIELDS \
+		(USART_CR3_EIE | USART_CR3_IREN | USART_CR3_IRLP | \
+		 USART_CR3_HDSEL | USART_CR3_NACK | USART_CR3_SCEN | \
+		 USART_CR3_DMAR | USART_CR3_DMAT | USART_CR3_RTSE | \
+		 USART_CR3_CTSE | USART_CR3_CTSIE | USART_CR3_ONEBIT | \
+		 USART_CR3_OVRDIS | USART_CR3_DDRE | USART_CR3_DEM | \
+		 USART_CR3_DEP | USART_CR3_SCARCNT | USART_CR3_WUS | \
+		 USART_CR3_WUFIE | USART_CR3_TXFTIE | USART_CR3_TCBGTIE | \
+		 USART_CR3_RXFTCFG | USART_CR3_RXFTIE | USART_CR3_TXFTCFG)
+
+#define STM32_UART_ISR_ERRORS	 \
+		(USART_ISR_ORE | USART_ISR_NE |  USART_ISR_FE | USART_ISR_PE)
+
+static const uint16_t presc_table[STM32_UART_PRESCALER_NB] = {
+	1U, 2U, 4U, 6U, 8U, 10U, 12U, 16U, 32U, 64U, 128U, 256U
+};
+
+/* @brief  BRR division operation to set BRR register in 8-bit oversampling
+ * mode.
+ * @param  clockfreq: UART clock.
+ * @param  baud_rate: Baud rate set by the user.
+ * @param  prescaler: UART prescaler value.
+ * @retval Division result.
+ */
+static uint32_t uart_div_sampling8(unsigned long clockfreq,
+				   uint32_t baud_rate,
+				   uint32_t prescaler)
+{
+	uint32_t scaled_freq = clockfreq / presc_table[prescaler];
+
+	return ((scaled_freq * 2) + (baud_rate / 2)) / baud_rate;
+
+}
+
+/* @brief  BRR division operation to set BRR register in 16-bit oversampling
+ * mode.
+ * @param  clockfreq: UART clock.
+ * @param  baud_rate: Baud rate set by the user.
+ * @param  prescaler: UART prescaler value.
+ * @retval Division result.
+ */
+static uint32_t uart_div_sampling16(unsigned long clockfreq,
+				    uint32_t baud_rate,
+				    uint32_t prescaler)
+{
+	uint32_t scaled_freq = clockfreq / presc_table[prescaler];
+
+	return (scaled_freq + (baud_rate / 2)) / baud_rate;
+
+}
+
+/*
+ * @brief  Return the UART clock frequency.
+ * @param  huart: UART handle.
+ * @retval Frequency value in Hz.
+ */
+static unsigned long uart_get_clock_freq(struct stm32_uart_handle_s *huart)
+{
+	return fdt_get_uart_clock_freq((uintptr_t)huart->base);
+}
+
+/*
+ * @brief  Configure the UART peripheral.
+ * @param  huart: UART handle.
+ * @retval UART status.
+ */
+static int uart_set_config(struct stm32_uart_handle_s *huart,
+			   const struct stm32_uart_init_s *init)
+{
+	uint32_t tmpreg;
+	unsigned long clockfreq;
+	uint32_t brrtemp;
+
+	/*
+	 * ---------------------- USART CR1 Configuration --------------------
+	 * Clear M, PCE, PS, TE, RE and OVER8 bits and configure
+	 * the UART word length, parity, mode and oversampling:
+	 * - set the M bits according to init->word_length value,
+	 * - set PCE and PS bits according to init->parity value,
+	 * - set TE and RE bits according to init->mode value,
+	 * - set OVER8 bit according to init->over_sampling value.
+	 */
+	tmpreg = init->word_length |
+		 init->parity |
+		 init->mode |
+		 init->over_sampling |
+		 init->fifo_mode;
+	mmio_clrsetbits_32(huart->base + USART_CR1, STM32_UART_CR1_FIELDS, tmpreg);
+
+	/*
+	 * --------------------- USART CR2 Configuration ---------------------
+	 * Configure the UART Stop Bits: Set STOP[13:12] bits according
+	 * to init->stop_bits value.
+	 */
+	mmio_clrsetbits_32(huart->base + USART_CR2, STM32_UART_CR2_FIELDS,
+			   init->stop_bits);
+
+	/*
+	 * --------------------- USART CR3 Configuration ---------------------
+	 * Configure:
+	 * - UART HardWare Flow Control: set CTSE and RTSE bits according
+	 *   to init->hw_flow_control value,
+	 * - one-bit sampling method versus three samples' majority rule
+	 *   according to init->one_bit_sampling (not applicable to
+	 *   LPUART),
+	 * - set TXFTCFG bit according to init->tx_fifo_threshold value,
+	 * - set RXFTCFG bit according to init->rx_fifo_threshold value.
+	 */
+	tmpreg = init->hw_flow_control | init->one_bit_sampling;
+
+	if (init->fifo_mode == USART_CR1_FIFOEN) {
+		tmpreg |= init->tx_fifo_threshold |
+			  init->rx_fifo_threshold;
+	}
+
+	mmio_clrsetbits_32(huart->base + USART_CR3, STM32_UART_CR3_FIELDS, tmpreg);
+
+	/*
+	 * --------------------- USART PRESC Configuration -------------------
+	 * Configure UART Clock Prescaler : set PRESCALER according to
+	 * init->prescaler value.
+	 */
+	assert(init->prescaler < STM32_UART_PRESCALER_NB);
+	mmio_clrsetbits_32(huart->base + USART_PRESC, USART_PRESC_PRESCALER,
+			   init->prescaler);
+
+	/*---------------------- USART BRR configuration --------------------*/
+	clockfreq = uart_get_clock_freq(huart);
+	if (clockfreq == 0UL) {
+		return -ENODEV;
+	}
+
+	if (init->over_sampling == STM32_UART_OVERSAMPLING_8) {
+		uint32_t usartdiv = uart_div_sampling8(clockfreq,
+						       init->baud_rate,
+						       init->prescaler);
+
+		brrtemp = (usartdiv & USART_BRR_DIV_MANTISSA) |
+			  ((usartdiv & USART_BRR_DIV_FRACTION) >> 1);
+	} else {
+		brrtemp = uart_div_sampling16(clockfreq,
+					      init->baud_rate,
+					      init->prescaler) &
+			  (USART_BRR_DIV_FRACTION | USART_BRR_DIV_MANTISSA);
+	}
+	mmio_write_32(huart->base + USART_BRR, brrtemp);
+
+	return 0;
+}
+
+/*
+ * @brief  Handle UART communication timeout.
+ * @param  huart: UART handle.
+ * @param  flag: Specifies the UART flag to check.
+ * @retval UART status.
+ */
+static int stm32_uart_wait_flag(struct stm32_uart_handle_s *huart, uint32_t flag)
+{
+	uint64_t timeout_ref = timeout_init_us(STM32_UART_TIMEOUT_US);
+
+	while ((mmio_read_32(huart->base + USART_ISR) & flag) == 0U) {
+		if (timeout_elapsed(timeout_ref)) {
+			return -ETIMEDOUT;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * @brief  Check the UART idle State.
+ * @param  huart: UART handle.
+ * @retval UART status.
+ */
+static int stm32_uart_check_idle(struct stm32_uart_handle_s *huart)
+{
+	int ret;
+
+	/* Check if the transmitter is enabled */
+	if ((mmio_read_32(huart->base + USART_CR1) & USART_CR1_TE) == USART_CR1_TE) {
+		ret = stm32_uart_wait_flag(huart, USART_ISR_TEACK);
+		if (ret != 0) {
+			return ret;
+		}
+	}
+
+	/* Check if the receiver is enabled */
+	if ((mmio_read_32(huart->base + USART_CR1) & USART_CR1_RE) == USART_CR1_RE) {
+		ret = stm32_uart_wait_flag(huart, USART_ISR_REACK);
+		if (ret != 0) {
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * @brief  Compute RDR register mask depending on word length.
+ * @param  huart: UART handle.
+ * @retval Mask value.
+ */
+static unsigned int stm32_uart_rdr_mask(const struct stm32_uart_init_s *init)
+{
+	unsigned int mask = 0U;
+
+	switch (init->word_length) {
+	case STM32_UART_WORDLENGTH_9B:
+		mask = GENMASK(8, 0);
+		break;
+	case STM32_UART_WORDLENGTH_8B:
+		mask = GENMASK(7, 0);
+		break;
+	case STM32_UART_WORDLENGTH_7B:
+		mask = GENMASK(6, 0);
+		break;
+	default:
+		break; /* not reached */
+	}
+
+	if (init->parity != STM32_UART_PARITY_NONE) {
+		mask >>= 1;
+	}
+
+	return mask;
+}
+
+/*
+ * @brief  Check interrupt and status errors.
+ * @retval True if error detected, false otherwise.
+ */
+static bool stm32_uart_error_detected(struct stm32_uart_handle_s *huart)
+{
+	return (mmio_read_32(huart->base + USART_ISR) & STM32_UART_ISR_ERRORS) != 0U;
+}
+
+/*
+ * @brief  Clear status errors.
+ */
+static void stm32_uart_error_clear(struct stm32_uart_handle_s *huart)
+{
+	mmio_write_32(huart->base + USART_ICR, STM32_UART_ISR_ERRORS);
+}
+
+/*
+ * @brief  Stop the UART.
+ * @param  base: UART base address.
+ */
+void stm32_uart_stop(uintptr_t base)
+{
+	mmio_clrbits_32(base + USART_CR1, USART_CR1_UE);
+}
+
+/*
+ * @brief  Initialize UART.
+ * @param  huart: UART handle.
+ * @param  base_addr: base address of UART.
+ * @param  init: UART initialization parameter.
+ * @retval UART status.
+ */
+
+int stm32_uart_init(struct stm32_uart_handle_s *huart,
+		    uintptr_t base_addr,
+		    const struct stm32_uart_init_s *init)
+{
+	int ret;
+
+	if (huart == NULL || init == NULL || base_addr == 0U) {
+		return -EINVAL;
+	}
+
+	huart->base = base_addr;
+
+	/* Disable the peripheral */
+	stm32_uart_stop(huart->base);
+
+	/* Computation of UART mask to apply to RDR register */
+	huart->rdr_mask = stm32_uart_rdr_mask(init);
+
+	/* Init the peripheral */
+	ret = uart_set_config(huart, init);
+	if (ret != 0) {
+		return ret;
+	}
+
+	/* Enable the peripheral */
+	mmio_setbits_32(huart->base + USART_CR1, USART_CR1_UE);
+
+	/* TEACK and/or REACK to check */
+	return stm32_uart_check_idle(huart);
+}
+
+/*
+ * @brief  Transmit one data in no blocking mode.
+ * @param  huart: UART handle.
+ * @param  c: data to sent.
+ * @retval UART status.
+ */
+int stm32_uart_putc(struct stm32_uart_handle_s *huart, int c)
+{
+	int ret;
+
+	if (huart == NULL) {
+		return -EINVAL;
+	}
+
+	ret = stm32_uart_wait_flag(huart, USART_ISR_TXE);
+	if (ret != 0) {
+		return ret;
+	}
+
+	mmio_write_32(huart->base + USART_TDR, c);
+	if (stm32_uart_error_detected(huart)) {
+		stm32_uart_error_clear(huart);
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+/*
+ * @brief  Flush TX Transmit fifo
+ * @param  huart: UART handle.
+ * @retval UART status.
+ */
+int stm32_uart_flush(struct stm32_uart_handle_s *huart)
+{
+	int ret;
+
+	if (huart == NULL) {
+		return -EINVAL;
+	}
+
+	ret = stm32_uart_wait_flag(huart, USART_ISR_TXE);
+	if (ret != 0) {
+		return ret;
+	}
+
+	return stm32_uart_wait_flag(huart, USART_ISR_TC);
+}
+
+/*
+ * @brief  Receive a data in no blocking mode.
+ * @retval value if >0 or UART status.
+ */
+int stm32_uart_getc(struct stm32_uart_handle_s *huart)
+{
+	uint32_t data;
+
+	if (huart == NULL) {
+		return -EINVAL;
+	}
+
+	/* Check if data is available */
+	if ((mmio_read_32(huart->base + USART_ISR) & USART_ISR_RXNE) == 0U) {
+		return -EAGAIN;
+	}
+
+	data = mmio_read_32(huart->base + USART_RDR) & huart->rdr_mask;
+
+	if (stm32_uart_error_detected(huart)) {
+		stm32_uart_error_clear(huart);
+		return -EFAULT;
+	}
+
+	return (int)data;
+}
diff --git a/fdts/morello-soc.dts b/fdts/morello-soc.dts
new file mode 100644
index 0000000..8464634
--- /dev/null
+++ b/fdts/morello-soc.dts
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+#include "morello.dtsi"
+
+/ {
+
+	chosen {
+		stdout-path = "soc_uart0:115200n8";
+	};
+
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		secure-firmware@ff000000 {
+			reg = <0 0xff000000 0 0x01000000>;
+			no-map;
+		};
+	};
+
+	cpus {
+		#address-cells = <2>;
+		#size-cells = <0>;
+		cpu0@0 {
+			compatible = "arm,armv8";
+			reg = <0x0 0x0>;
+			device_type = "cpu";
+			enable-method = "psci";
+			clocks = <&scmi_dvfs 0>;
+		};
+		cpu1@100 {
+			compatible = "arm,armv8";
+			reg = <0x0 0x100>;
+			device_type = "cpu";
+			enable-method = "psci";
+			clocks = <&scmi_dvfs 0>;
+		};
+		cpu2@10000 {
+			compatible = "arm,armv8";
+			reg = <0x0 0x10000>;
+			device_type = "cpu";
+			enable-method = "psci";
+			clocks = <&scmi_dvfs 1>;
+		};
+		cpu3@10100 {
+			compatible = "arm,armv8";
+			reg = <0x0 0x10100>;
+			device_type = "cpu";
+			enable-method = "psci";
+			clocks = <&scmi_dvfs 1>;
+		};
+	};
+
+	/* The first bank of memory, memory map is actually provided by UEFI. */
+	memory@80000000 {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		device_type = "memory";
+		/* [0x80000000-0xffffffff] */
+		reg = <0x00000000 0x80000000 0x0 0x7F000000>;
+	};
+
+	memory@8080000000 {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		device_type = "memory";
+		/* [0x8080000000-0x83f7ffffff] */
+		reg = <0x00000080 0x80000000 0x3 0x78000000>;
+	};
+
+	smmu_pcie: iommu@4f400000 {
+		compatible = "arm,smmu-v3";
+		reg = <0 0x4f400000 0 0x40000>;
+		interrupts = <GIC_SPI 235 IRQ_TYPE_EDGE_RISING>,
+				<GIC_SPI 40 IRQ_TYPE_EDGE_RISING>,
+				<GIC_SPI 236 IRQ_TYPE_EDGE_RISING>,
+				<GIC_SPI 237 IRQ_TYPE_EDGE_RISING>;
+		interrupt-names = "eventq", "priq", "cmdq-sync", "gerror";
+		msi-parent = <&its2 0>;
+		#iommu-cells = <1>;
+		dma-coherent;
+	};
+
+	pcie_ctlr: pcie@28c0000000 {
+		compatible = "pci-host-ecam-generic";
+		device_type = "pci";
+		reg = <0x28 0xC0000000 0 0x10000000>;
+		bus-range = <0 255>;
+		linux,pci-domain = <0>;
+		#address-cells = <3>;
+		#size-cells = <2>;
+		dma-coherent;
+		ranges = <0x01000000 0x00 0x00000000 0x00 0x6F000000 0x00 0x00800000>,
+		     <0x02000000 0x00 0x60000000 0x00 0x60000000 0x00 0x0F000000>,
+			 <0x42000000 0x09 0x00000000 0x09 0x00000000 0x1F 0xC0000000>;
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 0 0 7>;
+		interrupt-map = <0 0 0 1 &gic 0 0 0 169 IRQ_TYPE_LEVEL_HIGH>,
+			<0 0 0 2 &gic 0 0 0 170 IRQ_TYPE_LEVEL_HIGH>,
+			<0 0 0 3 &gic 0 0 0 171 IRQ_TYPE_LEVEL_HIGH>,
+			<0 0 0 4 &gic 0 0 0 172 IRQ_TYPE_LEVEL_HIGH>;
+		msi-map = <0 &its_pcie 0 0x10000>;
+		iommu-map = <0 &smmu_pcie 0 0x10000>;
+		status = "okay";
+	};
+
+	smmu_ccix: iommu@4f000000 {
+		compatible = "arm,smmu-v3";
+		reg = <0 0x4f000000 0 0x40000>;
+		interrupts = <GIC_SPI 228 IRQ_TYPE_EDGE_RISING>,
+				<GIC_SPI 41 IRQ_TYPE_EDGE_RISING>,
+				<GIC_SPI 229 IRQ_TYPE_EDGE_RISING>,
+				<GIC_SPI 230 IRQ_TYPE_EDGE_RISING>;
+		interrupt-names = "eventq", "priq", "cmdq-sync", "gerror";
+		msi-parent = <&its1 0>;
+		#iommu-cells = <1>;
+		dma-coherent;
+	};
+
+	ccix_pcie_ctlr: pcie@4fc0000000 {
+		compatible = "pci-host-ecam-generic";
+		device_type = "pci";
+		reg = <0x4F 0xC0000000 0 0x10000000>;
+		bus-range = <0 255>;
+		linux,pci-domain = <1>;
+		#address-cells = <3>;
+		#size-cells = <2>;
+		dma-coherent;
+		ranges = <0x01000000 0x00 0x00000000 0x00 0x7F000000 0x00 0x00800000>,
+		     <0x02000000 0x00 0x70000000 0x00 0x70000000 0x00 0x0F000000>,
+			 <0x42000000 0x30 0x00000000 0x30 0x00000000 0x1F 0xC0000000>;
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 0 0 7>;
+		interrupt-map = <0 0 0 1 &gic 0 0 0 201 IRQ_TYPE_LEVEL_HIGH>,
+			<0 0 0 2 &gic 0 0 0 202 IRQ_TYPE_LEVEL_HIGH>,
+			<0 0 0 3 &gic 0 0 0 203 IRQ_TYPE_LEVEL_HIGH>,
+			<0 0 0 4 &gic 0 0 0 204 IRQ_TYPE_LEVEL_HIGH>;
+		msi-map = <0 &its_ccix 0 0x10000>;
+		iommu-map = <0 &smmu_ccix 0 0x10000>;
+		status = "okay";
+	};
+
+	smmu_dp: iommu@2ce00000 {
+		compatible = "arm,smmu-v3";
+		reg = <0 0x2ce00000 0 0x40000>;
+		interrupts = <GIC_SPI 76 IRQ_TYPE_EDGE_RISING>,
+				<GIC_SPI 78 IRQ_TYPE_EDGE_RISING>,
+				<GIC_SPI 80 IRQ_TYPE_EDGE_RISING>;
+		interrupt-names = "eventq", "cmdq-sync", "gerror";
+		#iommu-cells = <1>;
+	};
+
+	dp0: display@2cc00000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "arm,mali-d32";
+		reg = <0 0x2cc00000 0 0x20000>;
+		interrupts = <0 69 4>;
+		interrupt-names = "DPU";
+		clocks = <&dpu_aclk>;
+		clock-names = "aclk";
+		iommus = <&smmu_dp 0>, <&smmu_dp 1>, <&smmu_dp 2>, <&smmu_dp 3>,
+			<&smmu_dp 8>;
+
+		pl0: pipeline@0 {
+			reg = <0>;
+			clocks = <&scmi_clk 1>;
+			clock-names = "pxclk";
+			pl_id = <0>;
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				port@0 {
+					reg = <0>;
+					dp_pl0_out0: endpoint {
+						remote-endpoint = <&tda998x_0_input>;
+					};
+				};
+			};
+		};
+	};
+
+	i2c@1c0f0000 {
+		compatible = "cdns,i2c-r1p14";
+		reg = <0x0 0x1c0f0000 0x0 0x1000>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-frequency = <100000>;
+		i2c-sda-hold-time-ns = <500>;
+		interrupts = <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&dpu_aclk>;
+
+		hdmi-transmitter@70 {
+			compatible = "nxp,tda998x";
+			reg = <0x70>;
+			video-ports = <0x234501>;
+			port {
+				tda998x_0_input: endpoint {
+					remote-endpoint = <&dp_pl0_out0>;
+				};
+			};
+		};
+	};
+
+	dpu_aclk: dpu_aclk {
+		/* 77.1 MHz derived from 24 MHz reference clock */
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <350000000>;
+		clock-output-names = "aclk";
+	};
+
+	firmware {
+		scmi {
+			compatible = "arm,scmi";
+			mbox-names = "tx", "rx";
+			mboxes = <&mailbox 1 0 &mailbox 1 1>;
+			shmem = <&cpu_scp_hpri0 &cpu_scp_hpri1>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			scmi_dvfs: protocol@13 {
+				reg = <0x13>;
+				#clock-cells = <1>;
+			};
+			scmi_clk: protocol@14 {
+				reg = <0x14>;
+				#clock-cells = <1>;
+			};
+		};
+	};
+};
+
+&gic {
+	reg = <0x0 0x30000000 0 0x10000>,	/* GICD */
+	      <0x0 0x300c0000 0 0x80000>;	/* GICR */
+	interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+
+	its1: its@30040000 {
+		compatible = "arm,gic-v3-its";
+		msi-controller;
+		#msi-cells = <1>;
+		reg = <0x0 0x30040000 0x0 0x20000>;
+	};
+
+	its2: its@30060000 {
+		compatible = "arm,gic-v3-its";
+		msi-controller;
+		#msi-cells = <1>;
+		reg = <0x0 0x30060000 0x0 0x20000>;
+	};
+
+	its_ccix: its@30080000 {
+		compatible = "arm,gic-v3-its";
+		msi-controller;
+		#msi-cells = <1>;
+		reg = <0x0 0x30080000 0x0 0x20000>;
+	};
+
+	its_pcie: its@300a0000 {
+		compatible = "arm,gic-v3-its";
+		msi-controller;
+		#msi-cells = <1>;
+		reg = <0x0 0x300a0000 0x0 0x20000>;
+	};
+};
diff --git a/fdts/morello.dtsi b/fdts/morello.dtsi
index 52c04cd..f119820 100644
--- a/fdts/morello.dtsi
+++ b/fdts/morello.dtsi
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -58,17 +58,17 @@
 				  "mhu_hpri_rx";
 		#mbox-cells = <2>;
 		mbox-name = "ARM-MHU";
-		clocks = <&soc_refclk100mhz>;
+		clocks = <&soc_refclk50mhz>;
 		clock-names = "apb_pclk";
 	};
 
 	sram: sram@45200000 {
 		compatible = "mmio-sram";
-		reg = <0x0 0x45200000 0x0 0x8000>;
+		reg = <0x0 0x06000000 0x0 0x8000>;
 
 		#address-cells = <1>;
 		#size-cells = <1>;
-		ranges = <0 0x0 0x45200000 0x8000>;
+		ranges = <0 0x0 0x06000000 0x8000>;
 
 		cpu_scp_hpri0: scp-shmem@0 {
 			compatible = "arm,scmi-shmem";
@@ -81,10 +81,10 @@
 		};
 	};
 
-	soc_refclk100mhz: refclk100mhz {
+	soc_refclk50mhz: refclk50mhz {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
-		clock-frequency = <100000000>;
+		clock-frequency = <50000000>;
 		clock-output-names = "apb_pclk";
 	};
 
@@ -99,7 +99,7 @@
 		compatible = "arm,pl011", "arm,primecell";
 		reg = <0x0 0x2a400000 0x0 0x1000>;
 		interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&soc_uartclk>, <&soc_refclk100mhz>;
+		clocks = <&soc_uartclk>, <&soc_refclk50mhz>;
 		clock-names = "uartclk", "apb_pclk";
 		status = "okay";
 	};
diff --git a/include/drivers/auth/crypto_mod.h b/include/drivers/auth/crypto_mod.h
index 71cf673..cdcf504 100644
--- a/include/drivers/auth/crypto_mod.h
+++ b/include/drivers/auth/crypto_mod.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2021, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -25,6 +25,16 @@
 	CRYPTO_GCM_DECRYPT = 0
 };
 
+/* Message digest algorithm */
+enum crypto_md_algo {
+	CRYPTO_MD_SHA256,
+	CRYPTO_MD_SHA384,
+	CRYPTO_MD_SHA512,
+};
+
+/* Maximum size as per the known stronger hash algorithm i.e.SHA512 */
+#define CRYPTO_MD_MAX_SIZE		64U
+
 /*
  * Cryptographic library descriptor
  */
@@ -49,8 +59,9 @@
 
 #if MEASURED_BOOT
 	/* Calculate a hash. Return hash value */
-	int (*calc_hash)(unsigned int alg, void *data_ptr,
-			 unsigned int data_len, unsigned char *output);
+	int (*calc_hash)(enum crypto_md_algo md_alg, void *data_ptr,
+			 unsigned int data_len,
+			 unsigned char output[CRYPTO_MD_MAX_SIZE]);
 #endif /* MEASURED_BOOT */
 
 	/*
@@ -79,8 +90,9 @@
 			    unsigned int tag_len);
 
 #if MEASURED_BOOT
-int crypto_mod_calc_hash(unsigned int alg, void *data_ptr,
-			 unsigned int data_len, unsigned char *output);
+int crypto_mod_calc_hash(enum crypto_md_algo alg, void *data_ptr,
+			 unsigned int data_len,
+			 unsigned char output[CRYPTO_MD_MAX_SIZE]);
 
 /* Macro to register a cryptographic library */
 #define REGISTER_CRYPTO_LIB(_name, _init, _verify_signature, _verify_hash, \
diff --git a/include/drivers/auth/mbedtls/mbedtls_config.h b/include/drivers/auth/mbedtls/mbedtls_config.h
index ad39fa9..8ad6d7a 100644
--- a/include/drivers/auth/mbedtls/mbedtls_config.h
+++ b/include/drivers/auth/mbedtls/mbedtls_config.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2015-2021, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -71,9 +71,20 @@
 #endif
 
 #define MBEDTLS_SHA256_C
-#if (TF_MBEDTLS_HASH_ALG_ID != TF_MBEDTLS_SHA256)
+
+/*
+ * If either Trusted Boot or Measured Boot require a stronger algorithm than
+ * SHA-256, pull in SHA-512 support.
+ */
+#if (TF_MBEDTLS_HASH_ALG_ID != TF_MBEDTLS_SHA256) /* TBB hash algo */
+#define	MBEDTLS_SHA512_C
+#else
+   /* TBB uses SHA-256, what about measured boot? */
+#if defined(TF_MBEDTLS_TPM_HASH_ALG_ID) && \
+	(TF_MBEDTLS_TPM_HASH_ALG_ID != TF_MBEDTLS_SHA256)
 #define MBEDTLS_SHA512_C
 #endif
+#endif
 
 #define MBEDTLS_VERSION_C
 
diff --git a/include/drivers/clk.h b/include/drivers/clk.h
new file mode 100644
index 0000000..a18f41f
--- /dev/null
+++ b/include/drivers/clk.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CLK_H
+#define CLK_H
+
+#include <stdbool.h>
+
+struct clk_ops {
+	int (*enable)(unsigned long id);
+	void (*disable)(unsigned long id);
+	unsigned long (*get_rate)(unsigned long id);
+	int (*get_parent)(unsigned long id);
+	bool (*is_enabled)(unsigned long id);
+};
+
+int clk_enable(unsigned long id);
+void clk_disable(unsigned long id);
+unsigned long clk_get_rate(unsigned long id);
+bool clk_is_enabled(unsigned long id);
+int clk_get_parent(unsigned long id);
+
+void clk_register(const struct clk_ops *ops);
+
+#endif /* CLK_H */
diff --git a/include/drivers/marvell/uart/a3700_console.h b/include/drivers/marvell/uart/a3700_console.h
index 12d2cdc..ce673a1 100644
--- a/include/drivers/marvell/uart/a3700_console.h
+++ b/include/drivers/marvell/uart/a3700_console.h
@@ -9,6 +9,7 @@
 #define A3700_CONSOLE_H
 
 #include <drivers/console.h>
+#include <platform_def.h>
 
 /* MVEBU UART Registers */
 #define UART_RX_REG		0x00
diff --git a/include/drivers/measured_boot/event_log/event_log.h b/include/drivers/measured_boot/event_log/event_log.h
index c6eb29c..a687d41 100644
--- a/include/drivers/measured_boot/event_log/event_log.h
+++ b/include/drivers/measured_boot/event_log/event_log.h
@@ -36,9 +36,9 @@
 #endif
 
 /* Number of hashing algorithms supported */
-#define HASH_ALG_COUNT	1U
+#define HASH_ALG_COUNT		1U
 
-#define	INVALID_ID	MAX_NUMBER_IDS
+#define EVLOG_INVALID_ID	UINT32_MAX
 
 #define MEMBER_SIZE(type, member) sizeof(((type *)0)->member)
 
diff --git a/include/drivers/st/stm32_gpio.h b/include/drivers/st/stm32_gpio.h
index e241f58..b072345 100644
--- a/include/drivers/st/stm32_gpio.h
+++ b/include/drivers/st/stm32_gpio.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2015-2021, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -52,6 +52,7 @@
 void set_gpio(uint32_t bank, uint32_t pin, uint32_t mode, uint32_t speed,
 	      uint32_t pull, uint32_t alternate, uint8_t status);
 void set_gpio_secure_cfg(uint32_t bank, uint32_t pin, bool secure);
+void set_gpio_reset_cfg(uint32_t bank, uint32_t pin);
 #endif /*__ASSEMBLER__*/
 
 #endif /* STM32_GPIO_H */
diff --git a/include/drivers/st/stm32_uart.h b/include/drivers/st/stm32_uart.h
new file mode 100644
index 0000000..212968f
--- /dev/null
+++ b/include/drivers/st/stm32_uart.h
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32_UART_H
+#define STM32_UART_H
+
+/* UART word length */
+#define STM32_UART_WORDLENGTH_7B		USART_CR1_M1
+#define STM32_UART_WORDLENGTH_8B		0x00000000U
+#define STM32_UART_WORDLENGTH_9B		USART_CR1_M0
+
+/* UART number of stop bits */
+#define STM32_UART_STOPBITS_0_5			USART_CR2_STOP_0
+#define STM32_UART_STOPBITS_1			0x00000000U
+#define STM32_UART_STOPBITS_1_5			(USART_CR2_STOP_0 | USART_CR2_STOP_1)
+#define STM32_UART_STOPBITS_2			USART_CR2_STOP_1
+
+/* UART parity */
+#define STM32_UART_PARITY_NONE			0x00000000U
+#define STM32_UART_PARITY_EVEN			USART_CR1_PCE
+#define STM32_UART_PARITY_ODD			(USART_CR1_PCE | USART_CR1_PS)
+
+/* UART transfer mode */
+#define STM32_UART_MODE_RX			USART_CR1_RE
+#define STM32_UART_MODE_TX			USART_CR1_TE
+#define STM32_UART_MODE_TX_RX			(USART_CR1_TE | USART_CR1_RE)
+
+/* UART hardware flow control */
+#define STM32_UART_HWCONTROL_NONE		0x00000000U
+#define STM32_UART_HWCONTROL_RTS		USART_CR3_RTSE
+#define STM32_UART_HWCONTROL_CTS		USART_CR3_CTSE
+#define STM32_UART_HWCONTROL_RTS_CTS		(USART_CR3_RTSE | USART_CR3_CTSE)
+
+/* UART over sampling */
+#define STM32_UART_OVERSAMPLING_16		0x00000000U
+#define STM32_UART_OVERSAMPLING_8		USART_CR1_OVER8
+
+/* UART prescaler */
+#define STM32_UART_PRESCALER_DIV1		0x00000000U
+#define STM32_UART_PRESCALER_DIV2		0x00000001U
+#define STM32_UART_PRESCALER_DIV4		0x00000002U
+#define STM32_UART_PRESCALER_DIV6		0x00000003U
+#define STM32_UART_PRESCALER_DIV8		0x00000004U
+#define STM32_UART_PRESCALER_DIV10		0x00000005U
+#define STM32_UART_PRESCALER_DIV12		0x00000006U
+#define STM32_UART_PRESCALER_DIV16		0x00000007U
+#define STM32_UART_PRESCALER_DIV32		0x00000008U
+#define STM32_UART_PRESCALER_DIV64		0x00000009U
+#define STM32_UART_PRESCALER_DIV128		0x0000000AU
+#define STM32_UART_PRESCALER_DIV256		0x0000000BU
+#define STM32_UART_PRESCALER_NB			0x0000000CU
+
+/* UART fifo mode */
+#define STM32_UART_FIFOMODE_EN			USART_CR1_FIFOEN
+#define STM32_UART_FIFOMODE_DIS			0x00000000U
+
+/* UART TXFIFO threshold level */
+#define STM32_UART_TXFIFO_THRESHOLD_1EIGHTHFULL		0x00000000U
+#define STM32_UART_TXFIFO_THRESHOLD_1QUARTERFUL		USART_CR3_TXFTCFG_0
+#define STM32_UART_TXFIFO_THRESHOLD_HALFFULL		USART_CR3_TXFTCFG_1
+#define STM32_UART_TXFIFO_THRESHOLD_3QUARTERSFULL	(USART_CR3_TXFTCFG_0 | USART_CR3_TXFTCFG_1)
+#define STM32_UART_TXFIFO_THRESHOLD_7EIGHTHFULL		USART_CR3_TXFTCFG_2
+#define STM32_UART_TXFIFO_THRESHOLD_EMPTY		(USART_CR3_TXFTCFG_2 | USART_CR3_TXFTCFG_0)
+
+/* UART RXFIFO threshold level */
+#define STM32_UART_RXFIFO_THRESHOLD_1EIGHTHFULL		0x00000000U
+#define STM32_UART_RXFIFO_THRESHOLD_1QUARTERFULL	USART_CR3_RXFTCFG_0
+#define STM32_UART_RXFIFO_THRESHOLD_HALFFULL		USART_CR3_RXFTCFG_1
+#define STM32_UART_RXFIFO_THRESHOLD_3QUARTERSFULL	(USART_CR3_RXFTCFG_0 | USART_CR3_RXFTCFG_1)
+#define STM32_UART_RXFIFO_THRESHOLD_7EIGHTHFULL		USART_CR3_RXFTCFG_2
+#define STM32_UART_RXFIFO_THRESHOLD_FULL		(USART_CR3_RXFTCFG_2 | USART_CR3_RXFTCFG_0)
+
+struct stm32_uart_init_s {
+	uint32_t baud_rate;		/*
+					 * Configures the UART communication
+					 * baud rate.
+					 */
+
+	uint32_t word_length;		/*
+					 * Specifies the number of data bits
+					 * transmitted or received in a frame.
+					 * This parameter can be a value of
+					 * @ref STM32_UART_WORDLENGTH_*.
+					 */
+
+	uint32_t stop_bits;		/*
+					 * Specifies the number of stop bits
+					 * transmitted. This parameter can be
+					 * a value of @ref STM32_UART_STOPBITS_*.
+					 */
+
+	uint32_t parity;		/*
+					 * Specifies the parity mode.
+					 * This parameter can be a value of
+					 * @ref STM32_UART_PARITY_*.
+					 */
+
+	uint32_t mode;			/*
+					 * Specifies whether the receive or
+					 * transmit mode is enabled or
+					 * disabled. This parameter can be a
+					 * value of @ref @ref STM32_UART_MODE_*.
+					 */
+
+	uint32_t hw_flow_control;	/*
+					 * Specifies whether the hardware flow
+					 * control mode is enabled or
+					 * disabled. This parameter can be a
+					 * value of @ref STM32_UARTHWCONTROL_*.
+					 */
+
+	uint32_t over_sampling;		/*
+					 * Specifies whether the over sampling
+					 * 8 is enabled or disabled.
+					 * This parameter can be a value of
+					 * @ref STM32_UART_OVERSAMPLING_*.
+					 */
+
+	uint32_t one_bit_sampling;	/*
+					 * Specifies whether a single sample
+					 * or three samples' majority vote is
+					 * selected. This parameter can be 0
+					 * or USART_CR3_ONEBIT.
+					 */
+
+	uint32_t prescaler;		/*
+					 * Specifies the prescaler value used
+					 * to divide the UART clock source.
+					 * This parameter can be a value of
+					 * @ref STM32_UART_PRESCALER_*.
+					 */
+
+	uint32_t fifo_mode;		/*
+					 * Specifies if the FIFO mode will be
+					 * used. This parameter can be a value
+					 * of @ref STM32_UART_FIFOMODE_*.
+					 */
+
+	uint32_t tx_fifo_threshold;	/*
+					 * Specifies the TXFIFO threshold
+					 * level. This parameter can be a
+					 * value of @ref
+					 * STM32_UART_TXFIFO_THRESHOLD_*.
+					 */
+
+	uint32_t rx_fifo_threshold;	/*
+					 * Specifies the RXFIFO threshold
+					 * level. This parameter can be a
+					 * value of @ref
+					 * STM32_UART_RXFIFO_THRESHOLD_*.
+					 */
+};
+
+struct stm32_uart_handle_s {
+	uint32_t base;
+	uint32_t rdr_mask;
+};
+
+int stm32_uart_init(struct stm32_uart_handle_s *huart,
+		    uintptr_t base_addr,
+		    const struct stm32_uart_init_s *init);
+void stm32_uart_stop(uintptr_t base_addr);
+int stm32_uart_putc(struct stm32_uart_handle_s *huart, int c);
+int stm32_uart_flush(struct stm32_uart_handle_s *huart);
+int stm32_uart_getc(struct stm32_uart_handle_s *huart);
+
+#endif /* STM32_UART_H */
diff --git a/include/drivers/st/stm32mp_clkfunc.h b/include/drivers/st/stm32mp_clkfunc.h
index c3329cc..a282035 100644
--- a/include/drivers/st/stm32mp_clkfunc.h
+++ b/include/drivers/st/stm32mp_clkfunc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2017-2021, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -26,5 +26,6 @@
 bool fdt_get_rcc_secure_status(void);
 
 int fdt_get_clock_id(int node);
+unsigned long fdt_get_uart_clock_freq(uintptr_t instance);
 
 #endif /* STM32MP_CLKFUNC_H */
diff --git a/include/lib/cpus/aarch64/cortex_x2.h b/include/lib/cpus/aarch64/cortex_x2.h
index 9ce1223..bf1b460 100644
--- a/include/lib/cpus/aarch64/cortex_x2.h
+++ b/include/lib/cpus/aarch64/cortex_x2.h
@@ -15,9 +15,23 @@
 #define CORTEX_X2_CPUECTLR_EL1					S3_0_C15_C1_4
 
 /*******************************************************************************
+ * CPU Extended Control register 2 specific definitions
+ ******************************************************************************/
+#define CORTEX_X2_CPUECTLR2_EL1					S3_0_C15_C1_5
+
+#define CORTEX_X2_CPUECTLR2_EL1_PF_MODE_SHIFT			U(11)
+#define CORTEX_X2_CPUECTLR2_EL1_PF_MODE_WIDTH			U(4)
+#define CORTEX_X2_CPUECTLR2_EL1_PF_MODE_CNSRV			ULL(0x9)
+
+/*******************************************************************************
  * CPU Power Control register specific definitions
  ******************************************************************************/
 #define CORTEX_X2_CPUPWRCTLR_EL1				S3_0_C15_C2_7
 #define CORTEX_X2_CPUPWRCTLR_EL1_CORE_PWRDN_BIT			U(1)
 
+/*******************************************************************************
+ * CPU Auxiliary Control Register 5 definitions
+ ******************************************************************************/
+#define CORTEX_X2_CPUACTLR5_EL1					S3_0_C15_C8_0
+
 #endif /* CORTEX_X2_H */
diff --git a/include/lib/el3_runtime/aarch64/context.h b/include/lib/el3_runtime/aarch64/context.h
index 698e208..512d196 100644
--- a/include/lib/el3_runtime/aarch64/context.h
+++ b/include/lib/el3_runtime/aarch64/context.h
@@ -207,8 +207,8 @@
 #define CTX_MPAMVPMV_EL2	U(0x158)
 
 // Starting with Armv8.6
-#define CTX_HAFGRTR_EL2		U(0x160)
-#define CTX_HDFGRTR_EL2		U(0x168)
+#define CTX_HDFGRTR_EL2		U(0x160)
+#define CTX_HAFGRTR_EL2		U(0x168)
 #define CTX_HDFGWTR_EL2		U(0x170)
 #define CTX_HFGITR_EL2		U(0x178)
 #define CTX_HFGRTR_EL2		U(0x180)
diff --git a/include/lib/fconf/fconf_dyn_cfg_getter.h b/include/lib/fconf/fconf_dyn_cfg_getter.h
index 6f8da0d..ff51c6c 100644
--- a/include/lib/fconf/fconf_dyn_cfg_getter.h
+++ b/include/lib/fconf/fconf_dyn_cfg_getter.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2021, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,6 +9,8 @@
 
 #include <lib/fconf/fconf.h>
 
+#define FCONF_INVALID_IDX	0xFFFFFFFFU
+
 /* Dynamic configuration related getter */
 #define dyn_cfg__dtb_getter(id)	dyn_cfg_dtb_info_getter(id)
 
@@ -18,6 +20,7 @@
 	unsigned int config_id;
 };
 
+unsigned int dyn_cfg_dtb_info_get_index(unsigned int config_id);
 struct dyn_cfg_dtb_info_t *dyn_cfg_dtb_info_getter(unsigned int config_id);
 int fconf_populate_dtb_registry(uintptr_t config);
 
diff --git a/include/plat/common/common_def.h b/include/plat/common/common_def.h
index 14ae603..632f122 100644
--- a/include/plat/common/common_def.h
+++ b/include/plat/common/common_def.h
@@ -85,4 +85,12 @@
 #endif /* BL2_IN_XIP_MEM */
 #endif /* SEPARATE_CODE_AND_RODATA */
 
+#if MEASURED_BOOT
+/*
+ * Start critical data Ids from 2^32/2 reserving Ids from 0 to (2^32/2 - 1)
+ * for Images, It is a critical data Id base for all platforms.
+ */
+#define CRITICAL_DATA_ID_BASE	U(0x80000000)
+#endif /* MEASURED_BOOT */
+
 #endif /* COMMON_DEF_H */
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index 3fa63f5..9a61b50 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -124,12 +124,22 @@
 
 #if MEASURED_BOOT
 int plat_mboot_measure_image(unsigned int image_id, image_info_t *image_data);
+int plat_mboot_measure_critical_data(unsigned int critical_data_id,
+				     const void *base,
+				     size_t size);
 #else
 static inline int plat_mboot_measure_image(unsigned int image_id __unused,
 					   image_info_t *image_data __unused)
 {
 	return 0;
 }
+static inline int plat_mboot_measure_critical_data(
+					unsigned int critical_data_id __unused,
+					const void *base __unused,
+					size_t size __unused)
+{
+	return 0;
+}
 #endif /* MEASURED_BOOT */
 
 /*******************************************************************************
diff --git a/include/services/gtsi_svc.h b/include/services/gtsi_svc.h
index cb942ed..ef4289f 100644
--- a/include/services/gtsi_svc.h
+++ b/include/services/gtsi_svc.h
@@ -14,12 +14,16 @@
 #define GTSI_ERROR_INVALID_PAS		-3
 
 /* The macros below are used to identify GTSI calls from the SMC function ID */
-#define GTSI_FNUM_MIN_VALUE	U(0x100)
-#define GTSI_FNUM_MAX_VALUE	U(0x101)
+#define GTSI_FNUM_MIN_VALUE	U(0x1B0)
+#define GTSI_FNUM_MAX_VALUE	U(0x1B1)
 #define is_gtsi_fid(fid) __extension__ ({		\
 	__typeof__(fid) _fid = (fid);			\
 	((GET_SMC_NUM(_fid) >= GTSI_FNUM_MIN_VALUE) &&	\
-	 (GET_SMC_NUM(_fid) <= GTSI_FNUM_MAX_VALUE)); })
+	(GET_SMC_NUM(_fid) <= GTSI_FNUM_MAX_VALUE)  &&	\
+	(GET_SMC_TYPE(_fid) == SMC_TYPE_FAST)	    &&	\
+	(GET_SMC_CC(_fid) == SMC_64)                &&	\
+	(GET_SMC_OEN(_fid) == OEN_STD_START)        &&	\
+	((_fid & 0x00FE0000) == 0U)); })
 
 /* Get GTSI fastcall std FID from function number */
 #define GTSI_FID(smc_cc, func_num)			\
@@ -28,8 +32,8 @@
 	 (OEN_STD_START << FUNCID_OEN_SHIFT)	|	\
 	 ((func_num) << FUNCID_NUM_SHIFT))
 
-#define GRAN_TRANS_TO_REALM_FNUM	U(0x100)
-#define GRAN_TRANS_TO_NS_FNUM		U(0x101)
+#define GRAN_TRANS_TO_REALM_FNUM	U(0x1B0)
+#define GRAN_TRANS_TO_NS_FNUM		U(0x1B1)
 
 #define SMC_ASC_MARK_REALM	GTSI_FID(SMC_64, GRAN_TRANS_TO_REALM_FNUM)
 #define SMC_ASC_MARK_NONSECURE	GTSI_FID(SMC_64, GRAN_TRANS_TO_NS_FNUM)
diff --git a/include/services/rmi_svc.h b/include/services/rmi_svc.h
index 22f635b..46fd510 100644
--- a/include/services/rmi_svc.h
+++ b/include/services/rmi_svc.h
@@ -17,22 +17,22 @@
 #define RMI_ERROR_INVALID_PAS		-3
 
 /* The macros below are used to identify RMI calls from the SMC function ID */
-#define RMI_FNUM_MIN_VALUE	U(0x00)
-#define RMI_FNUM_MAX_VALUE	U(0x20)
+#define RMI_FNUM_MIN_VALUE	U(0x150)
+#define RMI_FNUM_MAX_VALUE	U(0x18F)
 #define is_rmi_fid(fid) __extension__ ({		\
 	__typeof__(fid) _fid = (fid);			\
 	((GET_SMC_NUM(_fid) >= RMI_FNUM_MIN_VALUE) &&	\
 	 (GET_SMC_NUM(_fid) <= RMI_FNUM_MAX_VALUE) &&	\
 	 (GET_SMC_TYPE(_fid) == SMC_TYPE_FAST)	   &&	\
 	 (GET_SMC_CC(_fid) == SMC_64)              &&	\
-	 (GET_SMC_OEN(_fid) == OEN_ARM_START)      &&	\
+	 (GET_SMC_OEN(_fid) == OEN_STD_START)      &&	\
 	 ((_fid & 0x00FE0000) == 0U)); })
 
 /* Get RMI fastcall std FID from function number */
 #define RMI_FID(smc_cc, func_num)			\
 	((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT)	|	\
 	((smc_cc) << FUNCID_CC_SHIFT)		|	\
-	(OEN_ARM_START << FUNCID_OEN_SHIFT)	|	\
+	(OEN_STD_START << FUNCID_OEN_SHIFT)	|	\
 	((func_num) << FUNCID_NUM_SHIFT))
 
 /*
@@ -41,19 +41,20 @@
  * always invoked by the Normal world, forwarded by RMMD and handled by the
  * RMM
  */
-#define RMI_FNUM_REQ_COMPLETE		U(0x10)
-#define RMI_FNUM_VERSION_REQ		U(0x00)
+#define RMI_FNUM_REQ_COMPLETE		U(0x18F)
+#define RMI_FNUM_VERSION_REQ		U(0x150)
 
-#define RMI_FNUM_GRAN_NS_REALM		U(0x01)
-#define RMI_FNUM_GRAN_REALM_NS		U(0x02)
+#define RMI_FNUM_GRANULE_DELEGATE	U(0x151)
+#define RMI_FNUM_GRANULE_UNDELEGATE	U(0x152)
 
 /* RMI SMC64 FIDs handled by the RMMD */
 #define RMI_RMM_REQ_COMPLETE		RMI_FID(SMC_64, RMI_FNUM_REQ_COMPLETE)
 #define RMI_RMM_REQ_VERSION		RMI_FID(SMC_64, RMI_FNUM_VERSION_REQ)
 
-#define RMI_RMM_GRANULE_DELEGATE	RMI_FID(SMC_64, RMI_FNUM_GRAN_NS_REALM)
-#define RMI_RMM_GRANULE_UNDELEGATE	RMI_FID(SMC_64, RMI_FNUM_GRAN_REALM_NS)
-
+#define RMI_RMM_GRANULE_DELEGATE	RMI_FID(SMC_64, \
+						RMI_FNUM_GRANULE_DELEGATE)
+#define RMI_RMM_GRANULE_UNDELEGATE	RMI_FID(SMC_64, \
+						RMI_FNUM_GRANULE_UNDELEGATE)
 
 #define RMI_ABI_VERSION_GET_MAJOR(_version) ((_version) >> 16)
 #define RMI_ABI_VERSION_GET_MINOR(_version) ((_version) & 0xFFFF)
diff --git a/lib/aarch32/misc_helpers.S b/lib/aarch32/misc_helpers.S
index 8b16f93..59e15bd 100644
--- a/lib/aarch32/misc_helpers.S
+++ b/lib/aarch32/misc_helpers.S
@@ -301,9 +301,9 @@
 	cmp	r4, r6
 	blo	2f
 
-	/* Skip adding offset if address is >= upper limit */
+	/* Skip adding offset if address is > upper limit */
 	cmp	r4, r7
-	bhs	2f
+	bhi	2f
 
 	add 	r4, r0, r4
 	str	r4, [r3]
diff --git a/lib/aarch64/misc_helpers.S b/lib/aarch64/misc_helpers.S
index 6e4d1fc..01531ca 100644
--- a/lib/aarch64/misc_helpers.S
+++ b/lib/aarch64/misc_helpers.S
@@ -532,9 +532,9 @@
 	cmp	x3, x6
 	b.lo	2f
 
-	/* Skip adding offset if address is >= upper limit */
+	/* Skip adding offset if address is > upper limit */
 	cmp	x3, x7
-	b.hs	2f
+	b.hi	2f
 	add	x3, x3, x0
 	str	x3, [x1]
 
@@ -582,9 +582,9 @@
 	cmp	x4, x6
 	b.lo	2f
 
-	/* Skip adding offset if r_addend entry is >= upper limit */
+	/* Skip adding offset if r_addend entry is > upper limit */
 	cmp	x4, x7
-	b.hs	2f
+	b.hi	2f
 
 	add	x4, x0, x4	/* Diff(S) + r_addend */
 	str	x4, [x3]
diff --git a/lib/cpus/aarch64/cortex_x2.S b/lib/cpus/aarch64/cortex_x2.S
index 87a9bdf..88116c3 100644
--- a/lib/cpus/aarch64/cortex_x2.S
+++ b/lib/cpus/aarch64/cortex_x2.S
@@ -21,6 +21,98 @@
 #error "Cortex X2 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
 #endif
 
+	/* --------------------------------------------------
+	 * Errata Workaround for Cortex X2 Errata #2002765.
+	 * This applies to revisions r0p0, r1p0, and r2p0 and
+	 * is open.
+	 * x0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber: x0, x1, x17
+	 * --------------------------------------------------
+	 */
+func errata_cortex_x2_2002765_wa
+	/* Check workaround compatibility. */
+	mov	x17, x30
+	bl	check_errata_2002765
+	cbz	x0, 1f
+
+	ldr	x0, =0x6
+	msr	S3_6_C15_C8_0, x0 /* CPUPSELR_EL3 */
+	ldr	x0, =0xF3A08002
+	msr	S3_6_C15_C8_2, x0 /* CPUPOR_EL3 */
+	ldr	x0, =0xFFF0F7FE
+	msr	S3_6_C15_C8_3, x0 /* CPUPMR_EL3 */
+	ldr	x0, =0x40000001003ff
+	msr	S3_6_C15_C8_1, x0 /* CPUPCR_EL3 */
+	isb
+
+1:
+	ret	x17
+endfunc errata_cortex_x2_2002765_wa
+
+func check_errata_2002765
+	/* Applies to r0p0 - r2p0 */
+	mov	x1, #0x20
+	b	cpu_rev_var_ls
+endfunc check_errata_2002765
+
+	/* --------------------------------------------------
+	 * Errata Workaround for Cortex X2 Errata #2058056.
+	 * This applies to revisions r0p0, r1p0, and r2p0 and
+	 * is open.
+	 * x0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber: x0, x1, x17
+	 * --------------------------------------------------
+	 */
+func errata_cortex_x2_2058056_wa
+	/* Check workaround compatibility. */
+	mov	x17, x30
+	bl	check_errata_2058056
+	cbz	x0, 1f
+
+	mrs	x1, CORTEX_X2_CPUECTLR2_EL1
+	mov	x0, #CORTEX_X2_CPUECTLR2_EL1_PF_MODE_CNSRV
+	bfi	x1, x0, #CORTEX_X2_CPUECTLR2_EL1_PF_MODE_SHIFT, #CORTEX_X2_CPUECTLR2_EL1_PF_MODE_WIDTH
+	msr	CORTEX_X2_CPUECTLR2_EL1, x1
+
+1:
+	ret	x17
+endfunc errata_cortex_x2_2058056_wa
+
+func check_errata_2058056
+	/* Applies to r0p0 - r2p0 */
+	mov	x1, #0x20
+	b	cpu_rev_var_ls
+endfunc check_errata_2058056
+
+	/* --------------------------------------------------
+	 * Errata Workaround for Cortex X2 Errata #2083908.
+	 * This applies to revision r2p0 and is open.
+	 * x0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber: x0-x2, x17
+	 * --------------------------------------------------
+	 */
+func errata_cortex_x2_2083908_wa
+	/* Check workaround compatibility. */
+	mov	x17, x30
+	bl	check_errata_2083908
+	cbz	x0, 1f
+
+	/* Apply the workaround by setting bit 13 in CPUACTLR5_EL1. */
+	mrs	x1, CORTEX_X2_CPUACTLR5_EL1
+	orr	x1, x1, #BIT(13)
+	msr	CORTEX_X2_CPUACTLR5_EL1, x1
+
+1:
+	ret	x17
+endfunc errata_cortex_x2_2083908_wa
+
+func check_errata_2083908
+	/* Applies to r2p0 */
+	mov	x1, #0x20
+	mov	x2, #0x20
+	b	cpu_rev_var_range
+endfunc check_errata_2083908
+
 	/* ----------------------------------------------------
 	 * HW will do the cache maintenance while powering down
 	 * ----------------------------------------------------
@@ -42,15 +134,51 @@
 	 */
 #if REPORT_ERRATA
 func cortex_x2_errata_report
+	stp	x8, x30, [sp, #-16]!
+
+	bl	cpu_get_rev_var
+	mov	x8, x0
+
+	/*
+	 * Report all errata. The revision-variant information is passed to
+	 * checking functions of each errata.
+	 */
+	report_errata ERRATA_X2_2002765, cortex_x2, 2002765
+	report_errata ERRATA_X2_2058056, cortex_x2, 2058056
+	report_errata ERRATA_X2_2083908, cortex_x2, 2083908
+
+	ldp	x8, x30, [sp], #16
 	ret
 endfunc cortex_x2_errata_report
 #endif
 
 func cortex_x2_reset_func
+	mov	x19, x30
+
 	/* Disable speculative loads */
 	msr	SSBS, xzr
 	isb
-	ret
+
+	/* Get the CPU revision and stash it in x18. */
+	bl	cpu_get_rev_var
+	mov	x18, x0
+
+#if ERRATA_X2_2002765
+	mov	x0, x18
+	bl	errata_cortex_x2_2002765_wa
+#endif
+
+#if ERRATA_X2_2058056
+	mov	x0, x18
+	bl	errata_cortex_x2_2058056_wa
+#endif
+
+#if ERRATA_X2_2083908
+	mov	x0, x18
+	bl	errata_cortex_x2_2083908_wa
+#endif
+
+	ret x19
 endfunc cortex_x2_reset_func
 
 	/* ---------------------------------------------
diff --git a/lib/cpus/cpu-ops.mk b/lib/cpus/cpu-ops.mk
index a5b8aae..dd06cb8 100644
--- a/lib/cpus/cpu-ops.mk
+++ b/lib/cpus/cpu-ops.mk
@@ -495,6 +495,18 @@
 # to revision r0p0, r1p0 and r2p0 of the Cortex-A710 cpu and is still open.
 ERRATA_A710_2017096	?=0
 
+# Flag to apply erratum 2002765 workaround during reset. This erratum applies
+# to revisions r0p0, r1p0, and r2p0 of the Cortex-X2 cpu and is still open.
+ERRATA_X2_2002765   ?=0
+
+# Flag to apply erratum 2058056 workaround during reset. This erratum applies
+# to revisions r0p0, r1p0, and r2p0 of the Cortex-X2 cpu and is still open.
+ERRATA_X2_2058056   ?=0
+
+# Flag to apply erratum 2083908 workaround during reset. This erratum applies
+# to revision r2p0 of the Cortex-X2 cpu and is still open.
+ERRATA_X2_2083908   ?=0
+
 # Flag to apply DSU erratum 798953. This erratum applies to DSUs revision r0p0.
 # Applying the workaround results in higher DSU power consumption on idle.
 ERRATA_DSU_798953	?=0
@@ -920,6 +932,18 @@
 $(eval $(call assert_boolean,ERRATA_A710_2017096))
 $(eval $(call add_define,ERRATA_A710_2017096))
 
+# Process ERRATA_X2_2002765 flag
+$(eval $(call assert_boolean,ERRATA_X2_2002765))
+$(eval $(call add_define,ERRATA_X2_2002765))
+
+# Process ERRATA_X2_2058056 flag
+$(eval $(call assert_boolean,ERRATA_X2_2058056))
+$(eval $(call add_define,ERRATA_X2_2058056))
+
+# Process ERRATA_X2_2083908 flag
+$(eval $(call assert_boolean,ERRATA_X2_2083908))
+$(eval $(call add_define,ERRATA_X2_2083908))
+
 # Process ERRATA_DSU_798953 flag
 $(eval $(call assert_boolean,ERRATA_DSU_798953))
 $(eval $(call add_define,ERRATA_DSU_798953))
diff --git a/lib/el3_runtime/aarch64/context.S b/lib/el3_runtime/aarch64/context.S
index e270ad0..c9035e8 100644
--- a/lib/el3_runtime/aarch64/context.S
+++ b/lib/el3_runtime/aarch64/context.S
@@ -145,11 +145,14 @@
 	stp	x11, x12, [x0, #CTX_MPAMVPM7_EL2]
 #endif
 
-#if ARM_ARCH_AT_LEAST(8, 6)
-	mrs	x13, HAFGRTR_EL2
-	mrs	x14, HDFGRTR_EL2
-	stp	x13, x14, [x0, #CTX_HAFGRTR_EL2]
-
+#if ENABLE_FEAT_FGT
+	mrs	x13, HDFGRTR_EL2
+#if ENABLE_FEAT_AMUv1
+   	mrs	x14, HAFGRTR_EL2
+   	stp	x13, x14, [x0, #CTX_HDFGRTR_EL2]
+#else
+   	str	x13, [x0, #CTX_HDFGRTR_EL2]
+#endif
 	mrs	x15, HDFGWTR_EL2
 	mrs	x16, HFGITR_EL2
 	stp	x15, x16, [x0, #CTX_HDFGWTR_EL2]
@@ -157,7 +160,9 @@
 	mrs	x9, HFGRTR_EL2
 	mrs	x10, HFGWTR_EL2
 	stp	x9, x10, [x0, #CTX_HFGRTR_EL2]
+#endif
 
+#if ENABLE_FEAT_ECV
 	mrs	x11, CNTPOFF_EL2
 	str	x11, [x0, #CTX_CNTPOFF_EL2]
 #endif
@@ -319,10 +324,14 @@
 	msr	MPAMVPMV_EL2, x12
 #endif
 
-#if ARM_ARCH_AT_LEAST(8, 6)
-	ldp	x13, x14, [x0, #CTX_HAFGRTR_EL2]
-	msr	HAFGRTR_EL2, x13
-	msr	HDFGRTR_EL2, x14
+#if ENABLE_FEAT_FGT
+#if ENABLE_FEAT_AMUv1
+	ldp	x13, x14, [x0, #CTX_HDFGRTR_EL2]
+	msr	HAFGRTR_EL2, x14
+#else
+	ldr	x13, [x0, #CTX_HDFGRTR_EL2]
+#endif
+	msr	HDFGRTR_EL2, x13
 
 	ldp	x15, x16, [x0, #CTX_HDFGWTR_EL2]
 	msr	HDFGWTR_EL2, x15
@@ -331,7 +340,9 @@
 	ldp	x9, x10, [x0, #CTX_HFGRTR_EL2]
 	msr	HFGRTR_EL2, x9
 	msr	HFGWTR_EL2, x10
+#endif
 
+#if ENABLE_FEAT_ECV
 	ldr	x11, [x0, #CTX_CNTPOFF_EL2]
 	msr	CNTPOFF_EL2, x11
 #endif
diff --git a/lib/fconf/fconf_dyn_cfg_getter.c b/lib/fconf/fconf_dyn_cfg_getter.c
index 25dd7f9..34623fb 100644
--- a/lib/fconf/fconf_dyn_cfg_getter.c
+++ b/lib/fconf/fconf_dyn_cfg_getter.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2021, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -40,17 +40,30 @@
 	dtb_info->config_id = config_id;
 }
 
-struct dyn_cfg_dtb_info_t *dyn_cfg_dtb_info_getter(unsigned int config_id)
+/* Get index of the config_id image */
+unsigned int dyn_cfg_dtb_info_get_index(unsigned int config_id)
 {
 	unsigned int index;
 
 	/* Positions index to the proper config-id */
 	for (index = 0U; index < MAX_DTB_INFO; index++) {
 		if (dtb_infos[index].config_id == config_id) {
-			return &dtb_infos[index];
+			return index;
 		}
 	}
 
+	return FCONF_INVALID_IDX;
+}
+
+struct dyn_cfg_dtb_info_t *dyn_cfg_dtb_info_getter(unsigned int config_id)
+{
+	/* Positions index to the proper config-id */
+	unsigned int index = dyn_cfg_dtb_info_get_index(config_id);
+
+	if (index < MAX_DTB_INFO) {
+		return &dtb_infos[index];
+	}
+
 	WARN("FCONF: Invalid config id %u\n", config_id);
 
 	return NULL;
diff --git a/lib/xlat_tables_v2/xlat_tables_utils.c b/lib/xlat_tables_v2/xlat_tables_utils.c
index df17386..38a375e 100644
--- a/lib/xlat_tables_v2/xlat_tables_utils.c
+++ b/lib/xlat_tables_v2/xlat_tables_utils.c
@@ -6,6 +6,7 @@
 
 #include <assert.h>
 #include <errno.h>
+#include <inttypes.h>
 #include <stdbool.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -199,7 +200,7 @@
 					(uint64_t *)addr_inner,
 					XLAT_TABLE_ENTRIES, level + 1U);
 			} else {
-				printf("%sVA:0x%lx PA:0x%llx size:0x%zx ",
+				printf("%sVA:0x%lx PA:0x%" PRIx64 " size:0x%zx ",
 				       level_spacers[level], table_idx_va,
 				       (uint64_t)(desc & TABLE_ADDR_MASK),
 				       level_size);
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index e88148f..72f5e33 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -136,6 +136,15 @@
 # Flag to enable access to the HCRX_EL2 register by setting SCR_EL3.HXEn.
 ENABLE_FEAT_HCX			:= 0
 
+# Flag to enable access to the HAFGRTR_EL2 register
+ENABLE_FEAT_AMUv1		:= 0
+
+# Flag to enable access to the HDFGRTR_EL2 register
+ENABLE_FEAT_FGT			:= 0
+
+# Flag to enable access to the CNTPOFF_EL2 register
+ENABLE_FEAT_ECV			:= 0
+
 # By default BL31 encryption disabled
 ENCRYPT_BL31			:= 0
 
diff --git a/plat/arm/board/fvp/fvp_bl1_measured_boot.c b/plat/arm/board/fvp/fvp_bl1_measured_boot.c
index 47af1f5..5468555 100644
--- a/plat/arm/board/fvp/fvp_bl1_measured_boot.c
+++ b/plat/arm/board/fvp/fvp_bl1_measured_boot.c
@@ -17,7 +17,8 @@
 	{ FW_CONFIG_ID, EVLOG_FW_CONFIG_STRING, PCR_0 },
 	{ TB_FW_CONFIG_ID, EVLOG_TB_FW_CONFIG_STRING, PCR_0 },
 	{ BL2_IMAGE_ID, EVLOG_BL2_STRING, PCR_0 },
-	{ INVALID_ID, NULL, (unsigned int)(-1) }	/* Terminator */
+
+	{ EVLOG_INVALID_ID, NULL, (unsigned int)(-1) }	/* Terminator */
 };
 
 void bl1_plat_mboot_init(void)
diff --git a/plat/arm/board/fvp/fvp_bl2_measured_boot.c b/plat/arm/board/fvp/fvp_bl2_measured_boot.c
index 5ebfede..4943e58 100644
--- a/plat/arm/board/fvp/fvp_bl2_measured_boot.c
+++ b/plat/arm/board/fvp/fvp_bl2_measured_boot.c
@@ -7,7 +7,11 @@
 #include <stdint.h>
 
 #include <drivers/measured_boot/event_log/event_log.h>
+#include <tools_share/tbbr_oid.h>
+#include <fvp_critical_data.h>
+
 #include <plat/arm/common/plat_arm.h>
+#include <plat/common/common_def.h>
 
 /* Event Log data */
 static uint64_t event_log_base;
@@ -24,7 +28,10 @@
 	{ SCP_BL2_IMAGE_ID, EVLOG_SCP_BL2_STRING, PCR_0 },
 	{ SOC_FW_CONFIG_ID, EVLOG_SOC_FW_CONFIG_STRING, PCR_0 },
 	{ TOS_FW_CONFIG_ID, EVLOG_TOS_FW_CONFIG_STRING, PCR_0 },
-	{ INVALID_ID, NULL, (unsigned int)(-1) }	/* Terminator */
+
+	{ CRITICAL_DATA_ID, EVLOG_CRITICAL_DATA_STRING, PCR_1 },
+
+	{ EVLOG_INVALID_ID, NULL, (unsigned int)(-1) }	/* Terminator */
 };
 
 void bl2_plat_mboot_init(void)
@@ -58,6 +65,60 @@
 	event_log_init((uint8_t *)event_log_start, event_log_finish);
 }
 
+int plat_mboot_measure_critical_data(unsigned int critical_data_id,
+				     const void *base, size_t size)
+{
+	/*
+	 * It is very unlikely that the critical data size would be
+	 * bigger than 2^32 bytes
+	 */
+	assert(size < UINT32_MAX);
+	assert(base != NULL);
+
+	/* Calculate image hash and record data in Event Log */
+	int err = event_log_measure_and_record((uintptr_t)base, (uint32_t)size,
+					       critical_data_id);
+	if (err != 0) {
+		ERROR("%s%s critical data (%i)\n",
+		      "Failed to ", "record",  err);
+		return err;
+	}
+
+	return 0;
+}
+
+static int fvp_populate_critical_data(struct fvp_critical_data *critical_data)
+{
+	char *nv_ctr_oids[MAX_NV_CTR_IDS] = {
+		[TRUSTED_NV_CTR_ID] = TRUSTED_FW_NVCOUNTER_OID,
+		[NON_TRUSTED_NV_CTR_ID] = NON_TRUSTED_FW_NVCOUNTER_OID,
+	};
+
+	for (int i = 0; i < MAX_NV_CTR_IDS; i++) {
+		int rc = plat_get_nv_ctr(nv_ctr_oids[i],
+					 &critical_data->nv_ctr[i]);
+		if (rc != 0) {
+			return rc;
+		}
+	}
+
+	return 0;
+}
+
+static int fvp_populate_and_measure_critical_data(void)
+{
+	struct fvp_critical_data populate_critical_data;
+
+	int rc = fvp_populate_critical_data(&populate_critical_data);
+	if (rc == 0) {
+		rc = plat_mboot_measure_critical_data(CRITICAL_DATA_ID,
+						&populate_critical_data,
+						sizeof(populate_critical_data));
+	}
+
+	return rc;
+}
+
 void bl2_plat_mboot_finish(void)
 {
 	int rc;
@@ -68,6 +129,11 @@
 	/* Event Log filled size */
 	size_t event_log_cur_size;
 
+	rc = fvp_populate_and_measure_critical_data();
+	if (rc != 0) {
+		panic();
+	}
+
 	event_log_cur_size = event_log_get_cur_size((uint8_t *)event_log_base);
 
 	rc = arm_set_nt_fw_info(
diff --git a/plat/arm/board/fvp/include/fvp_critical_data.h b/plat/arm/board/fvp/include/fvp_critical_data.h
new file mode 100644
index 0000000..3010d21
--- /dev/null
+++ b/plat/arm/board/fvp/include/fvp_critical_data.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/nv_cntr_ids.h>
+#include <lib/utils_def.h>
+#include <plat/common/platform.h>
+
+#define EVLOG_CRITICAL_DATA_STRING	"CRITICAL DATA"
+
+#define CRITICAL_DATA_ID		CRITICAL_DATA_ID_BASE
+
+struct fvp_critical_data {
+
+	/* platform NV counters */
+	unsigned int nv_ctr[MAX_NV_CTR_IDS];
+};
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 0d2c319..b7f9c61 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -142,7 +142,8 @@
 					lib/cpus/aarch64/cortex_a65ae.S		\
 					lib/cpus/aarch64/cortex_a78c.S		\
 					lib/cpus/aarch64/cortex_hayes.S		\
-					lib/cpus/aarch64/cortex_hunter.S
+					lib/cpus/aarch64/cortex_hunter.S	\
+					lib/cpus/aarch64/cortex_x2.S
 	endif
 	# AArch64/AArch32 cores
 	FVP_CPU_LIBS	+=	lib/cpus/aarch64/cortex_a55.S		\
diff --git a/plat/arm/board/morello/fdts/morello_fw_config.dts b/plat/arm/board/morello/fdts/morello_fw_config.dts
new file mode 100644
index 0000000..c47bae5
--- /dev/null
+++ b/plat/arm/board/morello/fdts/morello_fw_config.dts
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2021, Arm Limited. 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/morello/fdts/morello_nt_fw_config.dts b/plat/arm/board/morello/fdts/morello_nt_fw_config.dts
new file mode 100644
index 0000000..e730d34
--- /dev/null
+++ b/plat/arm/board/morello/fdts/morello_nt_fw_config.dts
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+/ {
+	/* compatible string */
+	compatible = "arm,morello";
+
+	/*
+	 * Place holder for platform-info node with default values.
+	 * The values will be set to the correct values during
+	 * the BL2 stage of boot.
+	 */
+	platform-info {
+		local-ddr-size = <0x0 0x0>;
+#ifdef TARGET_PLATFORM_SOC
+		remote-ddr-size = <0x0 0x0>;
+		remote-chip-count = <0x0>;
+		multichip-mode = <0x0>;
+		scc-config = <0x0>;
+#endif
+	};
+};
diff --git a/plat/arm/board/morello/fdts/morello_tb_fw_config.dts b/plat/arm/board/morello/fdts/morello_tb_fw_config.dts
new file mode 100644
index 0000000..305a818
--- /dev/null
+++ b/plat/arm/board/morello/fdts/morello_tb_fw_config.dts
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021, Arm Limited. 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/morello/include/platform_def.h b/plat/arm/board/morello/include/platform_def.h
index 9ca75ff..08e2d60 100644
--- a/plat/arm/board/morello/include/platform_def.h
+++ b/plat/arm/board/morello/include/platform_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -15,8 +15,9 @@
 #define PLAT_ARM_BOOT_UART_BASE 		ULL(0x2A400000)
 #define PLAT_ARM_BOOT_UART_CLK_IN_HZ		U(50000000)
 
-#define PLAT_ARM_RUN_UART_BASE			ULL(0x2A410000)
-#define PLAT_ARM_RUN_UART_CLK_IN_HZ		U(50000000)
+/* IOFPGA UART0 */
+#define PLAT_ARM_RUN_UART_BASE			ULL(0x1C090000)
+#define PLAT_ARM_RUN_UART_CLK_IN_HZ		U(24000000)
 
 #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
@@ -24,6 +25,30 @@
 #define PLAT_ARM_DRAM2_BASE			ULL(0x8080000000)
 #define PLAT_ARM_DRAM2_SIZE			ULL(0xF80000000)
 
+#define MAX_IO_DEVICES				U(3)
+#define MAX_IO_HANDLES				U(4)
+
+#define PLAT_ARM_FLASH_IMAGE_BASE		ULL(0x1A000000)
+#define PLAT_ARM_FLASH_IMAGE_MAX_SIZE		ULL(0x01000000)
+
+#define PLAT_ARM_NVM_BASE			ULL(0x1A000000)
+#define PLAT_ARM_NVM_SIZE			ULL(0x01000000)
+
+#if defined NS_BL1U_BASE
+#undef NS_BL1U_BASE
+#define NS_BL1U_BASE			(PLAT_ARM_NVM_BASE + UL(0x00800000))
+#endif
+
+/*
+ * There are no non-volatile counters in morello, these macros points
+ * to unused addresses.
+ */
+#define SOC_TRUSTED_NVCTR_BASE		ULL(0x7FE70000)
+#define TFW_NVCTR_BASE			(SOC_TRUSTED_NVCTR_BASE + U(0x0000))
+#define TFW_NVCTR_SIZE			U(4)
+#define NTFW_CTR_BASE			(SOC_TRUSTED_NVCTR_BASE + U(0x0004))
+#define NTFW_CTR_SIZE			U(4)
+
 /*
  * To access the complete DDR memory along with remote chip's DDR memory,
  * which is at 4 TB offset, physical and virtual address space limits are
@@ -39,7 +64,36 @@
 #endif
 
 #define PLAT_ARM_TRUSTED_SRAM_SIZE		UL(0x00080000)
-#define PLAT_ARM_MAX_BL31_SIZE			UL(0x20000)
+
+/*
+ * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size
+ * plus a little space for growth.
+ */
+#define PLAT_ARM_MAX_BL1_RW_SIZE		UL(0xC000)
+
+/*
+ * PLAT_ARM_MAX_ROMLIB_RW_SIZE is define to use a full page
+ */
+
+#if USE_ROMLIB
+#define PLAT_ARM_MAX_ROMLIB_RW_SIZE		UL(0x1000)
+#define PLAT_ARM_MAX_ROMLIB_RO_SIZE		UL(0xE000)
+#else
+#define PLAT_ARM_MAX_ROMLIB_RW_SIZE		U(0)
+#define PLAT_ARM_MAX_ROMLIB_RO_SIZE		U(0)
+#endif
+
+/*
+ * PLAT_ARM_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a
+ * little space for growth.
+ */
+#if TRUSTED_BOARD_BOOT
+# define PLAT_ARM_MAX_BL2_SIZE			UL(0x1D000)
+#else
+# define PLAT_ARM_MAX_BL2_SIZE			UL(0x14000)
+#endif
+
+#define PLAT_ARM_MAX_BL31_SIZE			UL(0x3B000)
 
 /*******************************************************************************
  * MORELLO topology related constants
@@ -62,12 +116,49 @@
  * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the
  * plat_arm_mmap array defined for each BL stage.
  */
-#define PLAT_ARM_MMAP_ENTRIES			U(9)
-#define MAX_XLAT_TABLES				U(10)
+#if IMAGE_BL1 || IMAGE_BL31
+# define PLAT_ARM_MMAP_ENTRIES			U(6)
+# define MAX_XLAT_TABLES			U(7)
+#else
+# define PLAT_ARM_MMAP_ENTRIES			U(5)
+# define MAX_XLAT_TABLES			U(6)
+#endif
 
-#define PLATFORM_STACK_SIZE			U(0x400)
+/*
+ * Size of cacheable stacks
+ */
+#if defined(IMAGE_BL1)
+# if TRUSTED_BOARD_BOOT
+#  define PLATFORM_STACK_SIZE			UL(0x1000)
+# else
+#  define PLATFORM_STACK_SIZE			UL(0x440)
+# endif
+#elif defined(IMAGE_BL2)
+# if TRUSTED_BOARD_BOOT
+#  define PLATFORM_STACK_SIZE			UL(0x1000)
+# else
+#  define PLATFORM_STACK_SIZE			UL(0x400)
+# endif
+#elif defined(IMAGE_BL2U)
+# define PLATFORM_STACK_SIZE			UL(0x400)
+#elif defined(IMAGE_BL31)
+# if SPM_MM
+#  define PLATFORM_STACK_SIZE			UL(0x500)
+# else
+#  define PLATFORM_STACK_SIZE			UL(0x400)
+# endif
+#elif defined(IMAGE_BL32)
+# define PLATFORM_STACK_SIZE			UL(0x440)
+#endif
 
 #define PLAT_ARM_NSTIMER_FRAME_ID		U(0)
+
+#define PLAT_ARM_TRUSTED_ROM_BASE		U(0x0)
+#define PLAT_ARM_TRUSTED_ROM_SIZE		UL(0x00020000)	/* 128KB */
+
+#define PLAT_ARM_NSRAM_BASE			ULL(0x06000000)
+#define PLAT_ARM_NSRAM_SIZE			UL(0x00010000)	/* 64KB */
+
 #define PLAT_CSS_MHU_BASE			UL(0x45000000)
 #define PLAT_MHUV2_BASE				PLAT_CSS_MHU_BASE
 #define PLAT_MAX_PWR_LVL			U(2)
@@ -78,6 +169,10 @@
 #define MORELLO_DEVICE_BASE			ULL(0x08000000)
 #define MORELLO_DEVICE_SIZE			ULL(0x48000000)
 
+/*Secure Watchdog Constants */
+#define SBSA_SECURE_WDOG_BASE			UL(0x2A480000)
+#define SBSA_SECURE_WDOG_TIMEOUT		UL(1000)
+
 #define MORELLO_MAP_DEVICE			MAP_REGION_FLAT(	\
 						MORELLO_DEVICE_BASE,	\
 						MORELLO_DEVICE_SIZE,	\
diff --git a/plat/arm/board/morello/morello_bl1_setup.c b/plat/arm/board/morello/morello_bl1_setup.c
new file mode 100644
index 0000000..9155542
--- /dev/null
+++ b/plat/arm/board/morello/morello_bl1_setup.c
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*******************************************************************************
+ * Perform any BL1 specific platform actions.
+ ******************************************************************************/
+
+void soc_css_init_nic400(void)
+{
+}
+
+void soc_css_init_pcie(void)
+{
+}
diff --git a/plat/arm/board/morello/morello_bl2_setup.c b/plat/arm/board/morello/morello_bl2_setup.c
new file mode 100644
index 0000000..0d4b6d0
--- /dev/null
+++ b/plat/arm/board/morello/morello_bl2_setup.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <lib/utils.h>
+#include <plat/arm/common/plat_arm.h>
+
+void bl2_platform_setup(void)
+{
+#ifdef TARGET_PLATFORM_SOC
+	/*
+	 * Morello platform supports RDIMMs with ECC capability. To use the ECC
+	 * capability, the entire DDR memory space has to be zeroed out before
+	 * enabling the ECC bits in DMC-Bing.
+	 * Zeroing DDR memory range 0x80000000 - 0xFFFFFFFF during BL2 stage,
+	 * as BL33 binary cannot be copied to DDR memory before enabling ECC.
+	 * Rest of the DDR memory space is zeroed out during BL31 stage.
+	 */
+	INFO("Zeroing DDR memory range 0x80000000 - 0xFFFFFFFF\n");
+	zero_normalmem((void *)ARM_DRAM1_BASE, ARM_DRAM1_SIZE);
+	flush_dcache_range(ARM_DRAM1_BASE, ARM_DRAM1_SIZE);
+#endif
+	arm_bl2_platform_setup();
+}
diff --git a/plat/arm/board/morello/morello_bl31_setup.c b/plat/arm/board/morello/morello_bl31_setup.c
index 59dd37b..e418518 100644
--- a/plat/arm/board/morello/morello_bl31_setup.c
+++ b/plat/arm/board/morello/morello_bl31_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,40 +9,45 @@
 #include <drivers/arm/css/scmi.h>
 #include <drivers/arm/css/sds.h>
 #include <lib/cassert.h>
+#include <lib/utils.h>
 #include <plat/arm/common/plat_arm.h>
 
 #include "morello_def.h"
 #include <platform_def.h>
 
+#ifdef TARGET_PLATFORM_FVP
 /*
  * Platform information structure stored in SDS.
  * This structure holds information about platform's DDR
+ * size
+ *	- Local DDR size in bytes, DDR memory in main board
+ */
+struct morello_plat_info {
+	uint64_t local_ddr_size;
+} __packed;
+#else
+/*
+ * Platform information structure stored in SDS.
+ * This structure holds information about platform's DDR
  * size which is an information about multichip setup
- *	- Local DDR size in bytes, DDR memory in master board
- *	- Remote DDR size in bytes, DDR memory in slave board
- *	- slave_count
+ *	- Local DDR size in bytes, DDR memory in main board
+ *	- Remote DDR size in bytes, DDR memory in remote board
+ *	- remote_chip_count
  *	- multichip mode
+ *	- scc configuration
  */
 struct morello_plat_info {
 	uint64_t local_ddr_size;
 	uint64_t remote_ddr_size;
-	uint8_t slave_count;
+	uint8_t remote_chip_count;
 	bool multichip_mode;
+	uint32_t scc_config;
 } __packed;
+#endif
 
 /* Compile time assertion to ensure the size of structure is 18 bytes */
 CASSERT(sizeof(struct morello_plat_info) == MORELLO_SDS_PLATFORM_INFO_SIZE,
 		assert_invalid_plat_info_size);
-/*
- * BL33 image information structure stored in SDS.
- * This structure holds the source & destination addresses and
- * the size of the BL33 image which will be loaded by BL31.
- */
-struct morello_bl33_info {
-	uint32_t bl33_src_addr;
-	uint32_t bl33_dst_addr;
-	uint32_t bl33_size;
-};
 
 static scmi_channel_plat_info_t morello_scmi_plat_info = {
 	.scmi_mbx_mem = MORELLO_SCMI_PAYLOAD_BASE,
@@ -62,29 +67,143 @@
 	return css_scmi_override_pm_ops(ops);
 }
 
-static void copy_bl33(uint32_t src, uint32_t dst, uint32_t size)
+#ifdef TARGET_PLATFORM_SOC
+/*
+ * Morello platform supports RDIMMs with ECC capability. To use the ECC
+ * capability, the entire DDR memory space has to be zeroed out before
+ * enabling the ECC bits in DMC-Bing. Zeroing out several gigabytes of
+ * memory from SCP is quite time consuming so the following function
+ * is added to zero out the DDR memory from application processor which is
+ * much faster compared to SCP.
+ */
+
+static void dmc_ecc_setup(struct morello_plat_info *plat_info)
 {
-	unsigned int i;
+	uint64_t dram2_size;
+	uint32_t val;
+	uint64_t tag_mem_base;
+	uint64_t usable_mem_size;
+
+	INFO("Total DIMM size: %uGB\n",
+			(uint32_t)(plat_info->local_ddr_size / 0x40000000));
+
+	assert(plat_info->local_ddr_size > ARM_DRAM1_SIZE);
+	dram2_size = plat_info->local_ddr_size - ARM_DRAM1_SIZE;
+
+	INFO("Zeroing DDR memory range 0x%llx - 0x%llx\n",
+		ARM_DRAM2_BASE, ARM_DRAM2_BASE + dram2_size);
+	zero_normalmem((void *)ARM_DRAM2_BASE, dram2_size);
+	flush_dcache_range(ARM_DRAM2_BASE, dram2_size);
+
+	/* Clear previous ECC errors while zeroing out the memory */
+	val = mmio_read_32(MORELLO_DMC0_ERR2STATUS_REG);
+	mmio_write_32(MORELLO_DMC0_ERR2STATUS_REG, val);
+
+	val = mmio_read_32(MORELLO_DMC1_ERR2STATUS_REG);
+	mmio_write_32(MORELLO_DMC1_ERR2STATUS_REG, val);
+
+	/* Set DMCs to CONFIG state before writing ERR0CTLR0 register */
+	mmio_write_32(MORELLO_DMC0_MEMC_CMD_REG, MORELLO_DMC_MEMC_CMD_CONFIG);
+	mmio_write_32(MORELLO_DMC1_MEMC_CMD_REG, MORELLO_DMC_MEMC_CMD_CONFIG);
+
+	while ((mmio_read_32(MORELLO_DMC0_MEMC_STATUS_REG) &
+			MORELLO_DMC_MEMC_STATUS_MASK) !=
+			MORELLO_DMC_MEMC_CMD_CONFIG) {
+		continue;
+	}
 
-	INFO("Copying BL33 to DDR memory...\n");
-	for (i = 0U; i < size; (i = i + 8U))
-		mmio_write_64((dst + i), mmio_read_64(src + i));
+	while ((mmio_read_32(MORELLO_DMC1_MEMC_STATUS_REG) &
+			MORELLO_DMC_MEMC_STATUS_MASK) !=
+			MORELLO_DMC_MEMC_CMD_CONFIG) {
+		continue;
+	}
+
+	/* Configure Bing client/server mode based on SCC configuration */
+	if (plat_info->scc_config & MORELLO_SCC_CLIENT_MODE_MASK) {
+		INFO("Configuring DMC Bing in client mode\n");
+		usable_mem_size = plat_info->local_ddr_size -
+			(plat_info->local_ddr_size / 128ULL);
+
+		/* Linear DDR address */
+		tag_mem_base = usable_mem_size;
+		tag_mem_base = tag_mem_base / 4;
+
+		/* Reverse translation */
+		if (tag_mem_base < ARM_DRAM1_BASE) {
+			tag_mem_base += ARM_DRAM1_BASE;
+		} else {
+			tag_mem_base = tag_mem_base - ARM_DRAM1_BASE +
+				ARM_DRAM2_BASE;
+		}
+
+		mmio_write_32(MORELLO_DMC0_CAP_CTRL_REG, 0x1);
+		mmio_write_32(MORELLO_DMC1_CAP_CTRL_REG, 0x1);
+		mmio_write_32(MORELLO_DMC0_TAG_CACHE_CFG, 0x1);
+		mmio_write_32(MORELLO_DMC1_TAG_CACHE_CFG, 0x1);
 
-	for (i = 0U; i < size; (i = i + 8U)) {
-		if (mmio_read_64(src + i) != mmio_read_64(dst + i)) {
-			ERROR("Copy failed!\n");
-			panic();
+		if (plat_info->scc_config & MORELLO_SCC_C1_TAG_CACHE_EN_MASK) {
+			mmio_setbits_32(MORELLO_DMC0_TAG_CACHE_CFG, 0x2);
+			mmio_setbits_32(MORELLO_DMC1_TAG_CACHE_CFG, 0x2);
+			INFO("C1 Tag Cache Enabled\n");
 		}
+
+		if (plat_info->scc_config & MORELLO_SCC_C2_TAG_CACHE_EN_MASK) {
+			mmio_setbits_32(MORELLO_DMC0_TAG_CACHE_CFG, 0x4);
+			mmio_setbits_32(MORELLO_DMC1_TAG_CACHE_CFG, 0x4);
+			INFO("C2 Tag Cache Enabled\n");
+		}
+
+		mmio_write_32(MORELLO_DMC0_MEM_ADDR_CTL,
+				(uint32_t)tag_mem_base);
+		mmio_write_32(MORELLO_DMC1_MEM_ADDR_CTL,
+				(uint32_t)tag_mem_base);
+		mmio_write_32(MORELLO_DMC0_MEM_ADDR_CTL2,
+				(uint32_t)(tag_mem_base >> 32));
+		mmio_write_32(MORELLO_DMC1_MEM_ADDR_CTL2,
+				(uint32_t)(tag_mem_base >> 32));
+
+		mmio_setbits_32(MORELLO_DMC0_MEM_ACCESS_CTL,
+				MORELLO_DMC_MEM_ACCESS_DIS);
+		mmio_setbits_32(MORELLO_DMC1_MEM_ACCESS_CTL,
+				MORELLO_DMC_MEM_ACCESS_DIS);
+
+		INFO("Tag base set to 0x%lx\n", tag_mem_base);
+		plat_info->local_ddr_size = usable_mem_size;
+	} else {
+		INFO("Configuring DMC Bing in server mode\n");
+		mmio_write_32(MORELLO_DMC0_CAP_CTRL_REG, 0x0);
+		mmio_write_32(MORELLO_DMC1_CAP_CTRL_REG, 0x0);
 	}
-	INFO("done\n");
+
+	INFO("Enabling ECC on DMCs\n");
+	/* Enable ECC in DMCs */
+	mmio_setbits_32(MORELLO_DMC0_ERR0CTLR0_REG,
+		MORELLO_DMC_ERR0CTLR0_ECC_EN);
+	mmio_setbits_32(MORELLO_DMC1_ERR0CTLR0_REG,
+		MORELLO_DMC_ERR0CTLR0_ECC_EN);
+
+	/* Set DMCs to READY state */
+	mmio_write_32(MORELLO_DMC0_MEMC_CMD_REG, MORELLO_DMC_MEMC_CMD_READY);
+	mmio_write_32(MORELLO_DMC1_MEMC_CMD_REG, MORELLO_DMC_MEMC_CMD_READY);
+
+	while ((mmio_read_32(MORELLO_DMC0_MEMC_STATUS_REG) &
+			MORELLO_DMC_MEMC_STATUS_MASK) !=
+			MORELLO_DMC_MEMC_CMD_READY) {
+		continue;
+	}
+
+	while ((mmio_read_32(MORELLO_DMC1_MEMC_STATUS_REG) &
+			MORELLO_DMC_MEMC_STATUS_MASK) !=
+			MORELLO_DMC_MEMC_CMD_READY) {
+		continue;
+	}
 }
+#endif
 
 void bl31_platform_setup(void)
 {
 	int ret;
 	struct morello_plat_info plat_info;
-	struct morello_bl33_info bl33_info;
-	struct morello_plat_info *copy_dest;
 
 	ret = sds_init();
 	if (ret != SDS_OK) {
@@ -103,35 +222,22 @@
 	}
 
 	/* Validate plat_info SDS */
+#ifdef TARGET_PLATFORM_FVP
+	if (plat_info.local_ddr_size == 0U) {
+#else
 	if ((plat_info.local_ddr_size == 0U)
 		|| (plat_info.local_ddr_size > MORELLO_MAX_DDR_CAPACITY)
 		|| (plat_info.remote_ddr_size > MORELLO_MAX_DDR_CAPACITY)
-		|| (plat_info.slave_count > MORELLO_MAX_SLAVE_COUNT)) {
+		|| (plat_info.remote_chip_count > MORELLO_MAX_REMOTE_CHIP_COUNT)
+		) {
+#endif
 		ERROR("platform info SDS is corrupted\n");
 		panic();
 	}
 
 	arm_bl31_platform_setup();
 
-	ret = sds_struct_read(MORELLO_SDS_BL33_INFO_STRUCT_ID,
-				MORELLO_SDS_BL33_INFO_OFFSET,
-				&bl33_info,
-				MORELLO_SDS_BL33_INFO_SIZE,
-				SDS_ACCESS_MODE_NON_CACHED);
-	if (ret != SDS_OK) {
-		ERROR("Error getting BL33 info from SDS. ret:%d\n", ret);
-		panic();
-	}
-	copy_bl33(bl33_info.bl33_src_addr,
-			bl33_info.bl33_dst_addr,
-			bl33_info.bl33_size);
-	/*
-	 * Pass platform information to BL33. This method is followed as
-	 * currently there is no BL1/BL2 involved in boot flow of MORELLO.
-	 * When TBBR is implemented for MORELLO, this method should be removed
-	 * and platform information should be passed to BL33 using NT_FW_CONFIG
-	 * passing mechanism.
-	 */
-	copy_dest = (struct morello_plat_info *)MORELLO_PLATFORM_INFO_BASE;
-	*copy_dest = plat_info;
+#ifdef TARGET_PLATFORM_SOC
+	dmc_ecc_setup(&plat_info);
+#endif
 }
diff --git a/plat/arm/board/morello/morello_def.h b/plat/arm/board/morello/morello_def.h
index 793729b..f154924 100644
--- a/plat/arm/board/morello/morello_def.h
+++ b/plat/arm/board/morello/morello_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -18,16 +18,75 @@
 /* SDS Platform information defines */
 #define MORELLO_SDS_PLATFORM_INFO_STRUCT_ID	U(8)
 #define MORELLO_SDS_PLATFORM_INFO_OFFSET	U(0)
-#define MORELLO_SDS_PLATFORM_INFO_SIZE		U(18)
+#ifdef TARGET_PLATFORM_FVP
+# define MORELLO_SDS_PLATFORM_INFO_SIZE		U(8)
+#else
+# define MORELLO_SDS_PLATFORM_INFO_SIZE		U(22)
+#endif
 #define MORELLO_MAX_DDR_CAPACITY		U(0x1000000000)
-#define MORELLO_MAX_SLAVE_COUNT			U(16)
+#define MORELLO_MAX_REMOTE_CHIP_COUNT		U(16)
 
-/* SDS BL33 image information defines */
-#define MORELLO_SDS_BL33_INFO_STRUCT_ID		U(9)
-#define MORELLO_SDS_BL33_INFO_OFFSET		U(0)
-#define MORELLO_SDS_BL33_INFO_SIZE		U(12)
+#define MORELLO_SCC_SERVER_MODE			U(0)
+#define MORELLO_SCC_CLIENT_MODE_MASK		U(1)
+#define MORELLO_SCC_C1_TAG_CACHE_EN_MASK	U(4)
+#define MORELLO_SCC_C2_TAG_CACHE_EN_MASK	U(8)
 
 /* Base address of non-secure SRAM where Platform information will be filled */
 #define MORELLO_PLATFORM_INFO_BASE		UL(0x06000000)
 
+/* DMC memory status registers */
+#define MORELLO_DMC0_MEMC_STATUS_REG		UL(0x4E000000)
+#define MORELLO_DMC1_MEMC_STATUS_REG		UL(0x4E100000)
+
+#define MORELLO_DMC_MEMC_STATUS_MASK		U(7)
+
+/* DMC memory command registers */
+#define MORELLO_DMC0_MEMC_CMD_REG		UL(0x4E000008)
+#define MORELLO_DMC1_MEMC_CMD_REG		UL(0x4E100008)
+
+/* DMC capability control register */
+#define MORELLO_DMC0_CAP_CTRL_REG		UL(0x4E000D00)
+#define MORELLO_DMC1_CAP_CTRL_REG		UL(0x4E100D00)
+
+/* DMC tag cache control register */
+#define MORELLO_DMC0_TAG_CACHE_CTL		UL(0x4E000D04)
+#define MORELLO_DMC1_TAG_CACHE_CTL		UL(0x4E100D04)
+
+/* DMC tag cache config register */
+#define MORELLO_DMC0_TAG_CACHE_CFG		UL(0x4E000D08)
+#define MORELLO_DMC1_TAG_CACHE_CFG		UL(0x4E100D08)
+
+/* DMC memory access control register */
+#define MORELLO_DMC0_MEM_ACCESS_CTL		UL(0x4E000D0C)
+#define MORELLO_DMC1_MEM_ACCESS_CTL		UL(0x4E100D0C)
+
+#define MORELLO_DMC_MEM_ACCESS_DIS		(1UL << 16)
+
+/* DMC memory address control register */
+#define MORELLO_DMC0_MEM_ADDR_CTL		UL(0x4E000D10)
+#define MORELLO_DMC1_MEM_ADDR_CTL		UL(0x4E100D10)
+
+/* DMC memory address control 2 register */
+#define MORELLO_DMC0_MEM_ADDR_CTL2		UL(0x4E000D14)
+#define MORELLO_DMC1_MEM_ADDR_CTL2		UL(0x4E100D14)
+
+/* DMC special control register */
+#define MORELLO_DMC0_SPL_CTL_REG		UL(0x4E000D18)
+#define MORELLO_DMC1_SPL_CTL_REG		UL(0x4E100D18)
+
+/* DMC ERR0CTLR0 registers */
+#define MORELLO_DMC0_ERR0CTLR0_REG		UL(0x4E000708)
+#define MORELLO_DMC1_ERR0CTLR0_REG		UL(0x4E100708)
+
+/* DMC ECC in ERR0CTLR0 register */
+#define MORELLO_DMC_ERR0CTLR0_ECC_EN		U(9)
+
+/* DMC ERR2STATUS register */
+#define MORELLO_DMC0_ERR2STATUS_REG		UL(0x4E000790)
+#define MORELLO_DMC1_ERR2STATUS_REG		UL(0x4E100790)
+
+/* DMC memory commands */
+#define MORELLO_DMC_MEMC_CMD_CONFIG		U(0)
+#define MORELLO_DMC_MEMC_CMD_READY		U(3)
+
 #endif /* MORELLO_DEF_H */
diff --git a/plat/arm/board/morello/morello_err.c b/plat/arm/board/morello/morello_err.c
new file mode 100644
index 0000000..4d20a09
--- /dev/null
+++ b/plat/arm/board/morello/morello_err.c
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * morello error handler
+ */
+void __dead2 plat_arm_error_handler(int err)
+{
+	while (true) {
+		wfi();
+	}
+}
diff --git a/plat/arm/board/morello/morello_image_load.c b/plat/arm/board/morello/morello_image_load.c
new file mode 100644
index 0000000..52d46f3
--- /dev/null
+++ b/plat/arm/board/morello/morello_image_load.c
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <drivers/arm/css/sds.h>
+#include <libfdt.h>
+
+#include "morello_def.h"
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+
+#ifdef TARGET_PLATFORM_FVP
+/*
+ * Platform information structure stored in SDS.
+ * This structure holds information about platform's DDR
+ * size which is an information about multichip setup
+ *	- Local DDR size in bytes, DDR memory in main board
+ */
+struct morello_plat_info {
+	uint64_t local_ddr_size;
+} __packed;
+#else
+/*
+ * Platform information structure stored in SDS.
+ * This structure holds information about platform's DDR
+ * size which is an information about multichip setup
+ *	- Local DDR size in bytes, DDR memory in main board
+ *	- Remote DDR size in bytes, DDR memory in remote board
+ *	- remote_chip_count
+ *	- multichip mode
+ *	- scc configuration
+ */
+struct morello_plat_info {
+	uint64_t local_ddr_size;
+	uint64_t remote_ddr_size;
+	uint8_t remote_chip_count;
+	bool multichip_mode;
+	uint32_t scc_config;
+} __packed;
+#endif
+
+/* In client mode, a part of the DDR memory is reserved for Tag bits.
+ * Calculate the usable memory size after subtracting the Tag memory.
+ */
+static inline uint64_t get_mem_client_mode(uint64_t size)
+{
+	return (size - (size / 128ULL));
+}
+
+/*******************************************************************************
+ * This function inserts Platform information via device tree nodes as,
+ *	platform-info {
+ *		local-ddr-size = <0x0 0x0>;
+ *#ifdef TARGET_PLATFORM_SOC
+ *		remote-ddr-size = <0x0 0x0>;
+ *		remote-chip-count = <0x0>;
+ *		multichip-mode = <0x0>;
+ *		scc-config = <0x0>;
+ *#endif
+ *	};
+ ******************************************************************************/
+static int plat_morello_append_config_node(struct morello_plat_info *plat_info)
+{
+	bl_mem_params_node_t *mem_params;
+	void *fdt;
+	int nodeoffset, err;
+	uint64_t usable_mem_size;
+
+	usable_mem_size = plat_info->local_ddr_size;
+
+	mem_params = get_bl_mem_params_node(NT_FW_CONFIG_ID);
+	if (mem_params == NULL) {
+		ERROR("NT_FW CONFIG base address is NULL\n");
+		return -1;
+	}
+
+	fdt = (void *)(mem_params->image_info.image_base);
+
+	/* Check the validity of the fdt */
+	if (fdt_check_header(fdt) != 0) {
+		ERROR("Invalid NT_FW_CONFIG DTB passed\n");
+		return -1;
+	}
+
+	nodeoffset = fdt_subnode_offset(fdt, 0, "platform-info");
+	if (nodeoffset < 0) {
+		ERROR("NT_FW_CONFIG: Failed to get platform-info node offset\n");
+		return -1;
+	}
+
+#ifdef TARGET_PLATFORM_SOC
+	err = fdt_setprop_u64(fdt, nodeoffset, "remote-ddr-size",
+			plat_info->remote_ddr_size);
+	if (err < 0) {
+		ERROR("NT_FW_CONFIG: Failed to set remote-ddr-size\n");
+		return -1;
+	}
+
+	err = fdt_setprop_u32(fdt, nodeoffset, "remote-chip-count",
+			plat_info->remote_chip_count);
+	if (err < 0) {
+		ERROR("NT_FW_CONFIG: Failed to set remote-chip-count\n");
+		return -1;
+	}
+
+	err = fdt_setprop_u32(fdt, nodeoffset, "multichip-mode",
+			plat_info->multichip_mode);
+	if (err < 0) {
+		ERROR("NT_FW_CONFIG: Failed to set multichip-mode\n");
+		return -1;
+	}
+
+	err = fdt_setprop_u32(fdt, nodeoffset, "scc-config",
+			plat_info->scc_config);
+	if (err < 0) {
+		ERROR("NT_FW_CONFIG: Failed to set scc-config\n");
+		return -1;
+	}
+
+	if (plat_info->scc_config & MORELLO_SCC_CLIENT_MODE_MASK) {
+		usable_mem_size = get_mem_client_mode(plat_info->local_ddr_size);
+	}
+#endif
+	err = fdt_setprop_u64(fdt, nodeoffset, "local-ddr-size",
+			usable_mem_size);
+	if (err < 0) {
+		ERROR("NT_FW_CONFIG: Failed to set local-ddr-size\n");
+		return -1;
+	}
+
+	flush_dcache_range((uintptr_t)fdt, mem_params->image_info.image_size);
+
+	return 0;
+}
+
+/*******************************************************************************
+ * This function returns the list of executable images.
+ ******************************************************************************/
+bl_params_t *plat_get_next_bl_params(void)
+{
+	int ret;
+	struct morello_plat_info plat_info;
+
+	ret = sds_init();
+	if (ret != SDS_OK) {
+		ERROR("SDS initialization failed. ret:%d\n", ret);
+		panic();
+	}
+
+	ret = sds_struct_read(MORELLO_SDS_PLATFORM_INFO_STRUCT_ID,
+				MORELLO_SDS_PLATFORM_INFO_OFFSET,
+				&plat_info,
+				MORELLO_SDS_PLATFORM_INFO_SIZE,
+				SDS_ACCESS_MODE_NON_CACHED);
+	if (ret != SDS_OK) {
+		ERROR("Error getting platform info from SDS. ret:%d\n", ret);
+		panic();
+	}
+
+	/* Validate plat_info SDS */
+#ifdef TARGET_PLATFORM_FVP
+	if (plat_info.local_ddr_size == 0U) {
+#else
+	if ((plat_info.local_ddr_size == 0U)
+		|| (plat_info.local_ddr_size > MORELLO_MAX_DDR_CAPACITY)
+		|| (plat_info.remote_ddr_size > MORELLO_MAX_DDR_CAPACITY)
+		|| (plat_info.remote_chip_count > MORELLO_MAX_REMOTE_CHIP_COUNT)
+		){
+#endif
+		ERROR("platform info SDS is corrupted\n");
+		panic();
+	}
+
+	ret = plat_morello_append_config_node(&plat_info);
+	if (ret != 0) {
+		panic();
+	}
+
+	return arm_get_next_bl_params();
+}
diff --git a/plat/arm/board/morello/morello_plat.c b/plat/arm/board/morello/morello_plat.c
index 3830687..42e5171 100644
--- a/plat/arm/board/morello/morello_plat.c
+++ b/plat/arm/board/morello/morello_plat.c
@@ -1,9 +1,12 @@
 /*
- * Copyright (c) 2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <assert.h>
+
+#include <drivers/arm/sbsa.h>
 #include <plat/arm/common/plat_arm.h>
 
 #include "morello_def.h"
@@ -12,11 +15,45 @@
  * Table of regions to map using the MMU.
  * Replace or extend the below regions as required
  */
-
+#if IMAGE_BL1 || IMAGE_BL31
 const mmap_region_t plat_arm_mmap[] = {
 	ARM_MAP_SHARED_RAM,
 	MORELLO_MAP_DEVICE,
 	MORELLO_MAP_NS_SRAM,
 	ARM_MAP_DRAM1,
+	ARM_MAP_DRAM2,
 	{0}
 };
+#endif
+#if IMAGE_BL2
+const mmap_region_t plat_arm_mmap[] = {
+	ARM_MAP_SHARED_RAM,
+	MORELLO_MAP_DEVICE,
+	MORELLO_MAP_NS_SRAM,
+	ARM_MAP_DRAM1,
+#if TRUSTED_BOARD_BOOT && !BL2_AT_EL3
+	ARM_MAP_BL1_RW,
+#endif
+	{0}
+};
+#endif
+
+#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/arm/board/morello/morello_trusted_boot.c b/plat/arm/board/morello/morello_trusted_boot.c
new file mode 100644
index 0000000..f9bc009
--- /dev/null
+++ b/plat/arm/board/morello/morello_trusted_boot.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * Return the non-volatile counter value stored in the platform. The cookie
+ * will contain the OID of the counter in the certificate.
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr)
+{
+	*nv_ctr = MORELLO_FW_NVCTR_VAL;
+
+	return 0;
+}
+
+/*
+ * Store a new non-volatile counter value. By default on ARM development
+ * platforms, the non-volatile counters are RO and cannot be modified. We expect
+ * the values in the certificates to always match the RO values so that this
+ * function is never called.
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
+{
+	return 1;
+}
+
+/*
+ * 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/morello/platform.mk b/plat/arm/board/morello/platform.mk
index fc7d4d3..26a1911 100644
--- a/plat/arm/board/morello/platform.mk
+++ b/plat/arm/board/morello/platform.mk
@@ -1,9 +1,14 @@
 #
-# Copyright (c) 2020, Arm Limited. All rights reserved.
+# Copyright (c) 2020-2021, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
+# Making sure the Morello platform type is specified
+ifeq ($(filter ${TARGET_PLATFORM}, fvp soc),)
+	$(error TARGET_PLATFORM must be fvp or soc)
+endif
+
 MORELLO_BASE		:=	plat/arm/board/morello
 
 INTERCONNECT_SOURCES	:=	${MORELLO_BASE}/morello_interconnect.c
@@ -25,6 +30,21 @@
 PLAT_BL_COMMON_SOURCES	:=	${MORELLO_BASE}/morello_plat.c		\
 				${MORELLO_BASE}/aarch64/morello_helper.S
 
+BL1_SOURCES		:=	${MORELLO_CPU_SOURCES}			\
+				${INTERCONNECT_SOURCES}			\
+				${MORELLO_BASE}/morello_err.c		\
+				${MORELLO_BASE}/morello_trusted_boot.c	\
+				${MORELLO_BASE}/morello_bl1_setup.c	\
+				drivers/arm/sbsa/sbsa.c
+
+BL2_SOURCES		:=	${MORELLO_BASE}/morello_security.c	\
+				${MORELLO_BASE}/morello_err.c		\
+				${MORELLO_BASE}/morello_trusted_boot.c	\
+				${MORELLO_BASE}/morello_bl2_setup.c	\
+				${MORELLO_BASE}/morello_image_load.c	\
+				lib/utils/mem_region.c			\
+				drivers/arm/css/sds/sds.c
+
 BL31_SOURCES		:=	${MORELLO_CPU_SOURCES}			\
 				${INTERCONNECT_SOURCES}			\
 				${MORELLO_GIC_SOURCES}			\
@@ -33,19 +53,31 @@
 				${MORELLO_BASE}/morello_security.c	\
 				drivers/arm/css/sds/sds.c
 
-FDT_SOURCES		+=	fdts/morello-fvp.dts
+FDT_SOURCES		+=	fdts/morello-${TARGET_PLATFORM}.dts		\
+				${MORELLO_BASE}/fdts/morello_fw_config.dts	\
+				${MORELLO_BASE}/fdts/morello_tb_fw_config.dts	\
+				${MORELLO_BASE}/fdts/morello_nt_fw_config.dts
+
+FW_CONFIG		:=	${BUILD_PLAT}/fdts/morello_fw_config.dtb
+TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/morello_tb_fw_config.dtb
+NT_FW_CONFIG		:=	${BUILD_PLAT}/fdts/morello_nt_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}))
+# Add the NT_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config,${NT_FW_CONFIG}))
+
+MORELLO_FW_NVCTR_VAL	:=	0
+TFW_NVCTR_VAL		:=	${MORELLO_FW_NVCTR_VAL}
+NTFW_NVCTR_VAL		:=	${MORELLO_FW_NVCTR_VAL}
 
 # TF-A not required to load the SCP Images
 override CSS_LOAD_SCP_IMAGES		:=	0
 
-# BL1/BL2 Image not a part of the capsule Image for morello
-override NEED_BL1			:=	no
-override NEED_BL2			:=	no
 override NEED_BL2U			:=	no
 
-#TF-A for morello starts from BL31
-override RESET_TO_BL31			:=	1
-
 # 32 bit mode not supported
 override CTX_INCLUDE_AARCH32_REGS	:=	0
 
@@ -62,6 +94,12 @@
 # use USE_COHERENT_MEM. Require that USE_COHERENT_MEM must be set to 0 too.
 USE_COHERENT_MEM			:=	0
 
+# Add TARGET_PLATFORM to differentiate between Morello FVP and Morello SoC platform
+$(eval $(call add_define,TARGET_PLATFORM_$(call uppercase,${TARGET_PLATFORM})))
+
+# Add MORELLO_FW_NVCTR_VAL
+$(eval $(call add_define,MORELLO_FW_NVCTR_VAL))
+
 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/common/arm_common.mk b/plat/arm/common/arm_common.mk
index 78efb0f..064ed57 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -282,7 +282,7 @@
 ifeq (${JUNO_AARCH32_EL3_RUNTIME},1)
 BL2_SOURCES		+=	plat/arm/common/aarch32/arm_bl2_mem_params_desc.c
 else
-ifeq ($(filter ${TARGET_PLATFORM}, fpga fvp),)
+ifneq (${PLAT}, diphda)
 BL2_SOURCES		+=	plat/arm/common/${ARCH}/arm_bl2_mem_params_desc.c
 endif
 endif
@@ -389,6 +389,15 @@
 
     $(eval $(call TOOL_ADD_IMG,ns_bl2u,--fwu,FWU_))
 
+# Include Measured Boot makefile before any Crypto library makefile.
+# Crypto library makefile may need default definitions of Measured Boot build
+# flags present in Measured Boot makefile.
+ifeq (${MEASURED_BOOT},1)
+    MEASURED_BOOT_MK := drivers/measured_boot/event_log/event_log.mk
+    $(info Including ${MEASURED_BOOT_MK})
+    include ${MEASURED_BOOT_MK}
+endif
+
     # We expect to locate the *.mk files under the directories specified below
 ifeq (${ARM_CRYPTOCELL_INTEG},0)
     CRYPTO_LIB_MK := drivers/auth/mbedtls/mbedtls_crypto.mk
@@ -411,8 +420,3 @@
     endif
 endif
 
-ifeq (${MEASURED_BOOT},1)
-    MEASURED_BOOT_MK := drivers/measured_boot/event_log/event_log.mk
-    $(info Including ${MEASURED_BOOT_MK})
-    include ${MEASURED_BOOT_MK}
-endif
diff --git a/plat/arm/css/sgi/sgi-common.mk b/plat/arm/css/sgi/sgi-common.mk
index 8baf4ee..f56fe35 100644
--- a/plat/arm/css/sgi/sgi-common.mk
+++ b/plat/arm/css/sgi/sgi-common.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -20,6 +20,9 @@
 
 CSS_SGI_PLATFORM_VARIANT	:=	0
 
+# Do not enable SVE
+ENABLE_SVE_FOR_NS		:=	0
+
 INTERCONNECT_SOURCES	:=	${CSS_ENT_BASE}/sgi_interconnect.c
 
 PLAT_INCLUDES		+=	-I${CSS_ENT_BASE}/include
diff --git a/plat/marvell/armada/a3k/common/include/a3700_plat_def.h b/plat/marvell/armada/a3k/common/include/a3700_plat_def.h
index 83d9561..4d45e15 100644
--- a/plat/marvell/armada/a3k/common/include/a3700_plat_def.h
+++ b/plat/marvell/armada/a3k/common/include/a3700_plat_def.h
@@ -51,6 +51,41 @@
 #define MVEBU_CCI_BASE			0xFE000000
 
 /*****************************************************************************
+ * North and south bridge reset registers
+ *****************************************************************************
+ */
+#define MVEBU_NB_RESET_REG		(MVEBU_REGS_BASE + 0x12400)
+#define   MVEBU_NB_RESET_I2C1_N		(1 << 0)
+#define   MVEBU_NB_RESET_1WIRE_N	(1 << 1)
+#define   MVEBU_NB_RESET_SPI_N		(1 << 2)
+#define   MVEBU_NB_RESET_UART_N		(1 << 3)
+#define   MVEBU_NB_RESET_XTL_N		(1 << 4)
+#define   MVEBU_NB_RESET_I2C2_N		(1 << 5)
+#define   MVEBU_NB_RESET_UART2_N	(1 << 6)
+#define   MVEBU_NB_RESET_AVS_N		(1 << 7)
+#define   MVEBU_NB_RESET_DDR_N		(1 << 10)
+#define   MVEBU_NB_RESET_SETM_N		(1 << 11)
+#define   MVEBU_NB_RESET_DMA_N		(1 << 12)
+#define   MVEBU_NB_RESET_TSECM_N	(1 << 13)
+#define   MVEBU_NB_RESET_SDIO_N		(1 << 14)
+#define   MVEBU_NB_RESET_SATA_N		(1 << 15)
+#define   MVEBU_NB_RESET_PWRMGT_N	(1 << 16)
+#define   MVEBU_NB_RESET_OTP_N		(1 << 17)
+#define   MVEBU_NB_RESET_EIP_N		(1 << 18)
+#define MVEBU_SB_RESET_REG		(MVEBU_REGS_BASE + 0x18600)
+#define   MVEBU_SB_RESET_MCIPHY		(1 << 1)
+#define   MVEBU_SB_RESET_SDIO_N		(1 << 2)
+#define   MVEBU_SB_RESET_PCIE_N		(1 << 3)
+#define   MVEBU_SB_RESET_GBE1_N		(1 << 4)
+#define   MVEBU_SB_RESET_GBE0_N		(1 << 5)
+#define   MVEBU_SB_RESET_USB2PHY	(1 << 6)
+#define   MVEBU_SB_RESET_USB2HPHY	(1 << 7)
+#define   MVEBU_SB_RESET_MCI_N		(1 << 8)
+#define   MVEBU_SB_RESET_PWRMGT_N	(1 << 9)
+#define   MVEBU_SB_RESET_EBM_N		(1 << 10)
+#define   MVEBU_SB_RESET_OTP_N		(1 << 11)
+
+/*****************************************************************************
  * North and south bridge register base
  *****************************************************************************
  */
diff --git a/plat/mediatek/mt8186/aarch64/plat_helpers.S b/plat/mediatek/mt8186/aarch64/plat_helpers.S
new file mode 100644
index 0000000..35b293f
--- /dev/null
+++ b/plat/mediatek/mt8186/aarch64/plat_helpers.S
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+
+	.globl plat_is_my_cpu_primary
+	.globl plat_my_core_pos
+	.globl plat_mediatek_calc_core_pos
+
+func plat_is_my_cpu_primary
+	mrs	x0, mpidr_el1
+	and	x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+	cmp	x0, #PLAT_PRIMARY_CPU
+	cset	x0, eq
+	ret
+endfunc plat_is_my_cpu_primary
+
+	/* -----------------------------------------------------
+	 *  unsigned int plat_my_core_pos(void)
+	 *  This function uses the plat_mediatek_calc_core_pos()
+	 *  definition to get the index of the calling CPU.
+	 * -----------------------------------------------------
+	 */
+func plat_my_core_pos
+	mrs	x0, mpidr_el1
+	b	plat_mediatek_calc_core_pos
+endfunc plat_my_core_pos
+
+	/* -----------------------------------------------------
+	 * unsigned int plat_mediatek_calc_core_pos(u_register_t mpidr);
+	 *
+	 * With this function: CorePos = CoreID (AFF1)
+	 * we do it with x0 = (x0 >> 8) & 0xff
+	 * -----------------------------------------------------
+	 */
+func plat_mediatek_calc_core_pos
+	mov	x1, #MPIDR_AFFLVL_MASK
+	and	x0, x1, x0, lsr #MPIDR_AFF1_SHIFT
+	ret
+endfunc plat_mediatek_calc_core_pos
diff --git a/plat/mediatek/mt8186/aarch64/platform_common.c b/plat/mediatek/mt8186/aarch64/platform_common.c
new file mode 100644
index 0000000..9b9697f
--- /dev/null
+++ b/plat/mediatek/mt8186/aarch64/platform_common.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/xlat_tables/xlat_tables_v2.h>
+
+#include <platform_def.h>
+
+/* Table of regions to map using the MMU.  */
+const mmap_region_t plat_mmap[] = {
+	/* for TF text, RO, RW */
+	MAP_REGION_FLAT(MTK_DEV_RNG0_BASE, MTK_DEV_RNG0_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(MTK_DEV_RNG2_BASE, MTK_DEV_RNG2_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE),
+	{ 0 }
+};
+
+/*******************************************************************************
+ * Macro generating the code for the function setting up the pagetables as per
+ * the platform memory map & initialize the mmu, for the given exception level
+ ******************************************************************************/
+void plat_configure_mmu_el3(uintptr_t total_base,
+			    uintptr_t total_size,
+			    uintptr_t ro_start,
+			    uintptr_t ro_limit)
+{
+	mmap_add_region(total_base, total_base, total_size,
+			MT_RW_DATA | MT_SECURE);
+	mmap_add_region(ro_start, ro_start, ro_limit - ro_start,
+			MT_CODE | MT_SECURE);
+	mmap_add(plat_mmap);
+	init_xlat_tables();
+	enable_mmu_el3(0);
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+	return SYS_COUNTER_FREQ_IN_TICKS;
+}
diff --git a/plat/mediatek/mt8186/bl31_plat_setup.c b/plat/mediatek/mt8186/bl31_plat_setup.c
new file mode 100644
index 0000000..b70245f
--- /dev/null
+++ b/plat/mediatek/mt8186/bl31_plat_setup.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* System Includes */
+#include <assert.h>
+
+/* Project Includes */
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <drivers/generic_delay_timer.h>
+#include <drivers/ti/uart/uart_16550.h>
+#include <lib/coreboot.h>
+
+/* Platform Includes */
+#include <emi_mpu.h>
+#include <mt_gic_v3.h>
+#include <mt_timer.h>
+#include <mtgpio.h>
+#include <mtk_dcm.h>
+#include <plat_params.h>
+#include <plat_private.h>
+
+static entry_point_info_t bl32_ep_info;
+static entry_point_info_t bl33_ep_info;
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image for
+ * the security state specified. BL33 corresponds to the non-secure image type
+ * while BL32 corresponds to the secure image type. A NULL pointer is returned
+ * if the image does not exist.
+ ******************************************************************************/
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+	entry_point_info_t *next_image_info;
+
+	next_image_info = (type == NON_SECURE) ? &bl33_ep_info : &bl32_ep_info;
+	assert(next_image_info->h.type == PARAM_EP);
+
+	/* None of the images on this platform can have 0x0 as the entrypoint */
+	if (next_image_info->pc) {
+		return next_image_info;
+	} else {
+		return NULL;
+	}
+}
+
+/*******************************************************************************
+ * Perform any BL31 early platform setup. Here is an opportunity to copy
+ * parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before they
+ * are lost (potentially). This needs to be done before the MMU is initialized
+ * so that the memory layout can be used while creating page tables.
+ * BL2 has flushed this information to memory, so we are guaranteed to pick up
+ * good data.
+ ******************************************************************************/
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+				u_register_t arg2, u_register_t arg3)
+{
+	static console_t console;
+
+	params_early_setup(arg1);
+
+#if COREBOOT
+	if (coreboot_serial.type) {
+		console_16550_register(coreboot_serial.baseaddr,
+				       coreboot_serial.input_hertz,
+				       coreboot_serial.baud,
+				       &console);
+	}
+#else
+	console_16550_register(UART0_BASE, UART_CLOCK, UART_BAUDRATE, &console);
+#endif
+
+	INFO("MT8186 bl31_setup\n");
+
+	bl31_params_parse_helper(arg0, &bl32_ep_info, &bl33_ep_info);
+}
+
+
+/*******************************************************************************
+ * Perform any BL31 platform setup code
+ ******************************************************************************/
+void bl31_platform_setup(void)
+{
+	dcm_set_default();
+
+	/* Initialize the GIC driver, CPU and distributor interfaces */
+	mt_gic_driver_init();
+	mt_gic_init();
+
+	mt_gpio_init();
+	mt_systimer_init();
+	generic_delay_timer_init();
+
+	emi_mpu_init();
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only intializes the mmu in a quick and dirty way.
+ ******************************************************************************/
+void bl31_plat_arch_setup(void)
+{
+	plat_configure_mmu_el3(BL31_START,
+			       BL31_END - BL31_START,
+			       BL_CODE_BASE,
+			       BL_CODE_END);
+}
diff --git a/plat/mediatek/mt8186/drivers/dcm/mtk_dcm.c b/plat/mediatek/mt8186/drivers/dcm/mtk_dcm.c
new file mode 100644
index 0000000..5dde5c5
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/dcm/mtk_dcm.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#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_cpubiu_dbg_cg(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_cpubiu_dbg_cg_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;
+}
+
+void dcm_set_default(void)
+{
+	dcm_armcore(true);
+	dcm_mcusys(true);
+	dcm_stall(true);
+
+	INFO("%s: %d", __func__, check_dcm_state());
+}
diff --git a/plat/mediatek/mt8186/drivers/dcm/mtk_dcm.h b/plat/mediatek/mt8186/drivers/dcm/mtk_dcm.h
new file mode 100644
index 0000000..6abcff4
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/dcm/mtk_dcm.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTK_DCM_H
+#define MTK_DCM_H
+
+#include <stdbool.h>
+
+void dcm_set_default(void);
+
+#endif /* #ifndef MTK_DCM_H */
diff --git a/plat/mediatek/mt8186/drivers/dcm/mtk_dcm_utils.c b/plat/mediatek/mt8186/drivers/dcm/mtk_dcm_utils.c
new file mode 100644
index 0000000..ae0e964
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/dcm/mtk_dcm_utils.c
@@ -0,0 +1,490 @@
+/*
+ * Copyright (c) 2021, 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(16) |	\
+					 BIT(17) |	\
+					 BIT(18) |	\
+					 BIT(21))
+#define MP_CPUSYS_TOP_ADB_DCM_REG1_MASK (BIT(16) |	\
+					 BIT(17) |	\
+					 BIT(18))
+#define MP_CPUSYS_TOP_ADB_DCM_REG0_ON (BIT(16) |	\
+				       BIT(17) |	\
+				       BIT(18) |	\
+				       BIT(21))
+#define MP_CPUSYS_TOP_ADB_DCM_REG1_ON (BIT(16) |	\
+				       BIT(17) |	\
+				       BIT(18))
+#define MP_CPUSYS_TOP_ADB_DCM_REG0_OFF ((0x0 << 16) |	\
+					(0x0 << 17) |	\
+					(0x0 << 18) |	\
+					(0x0 << 21))
+#define MP_CPUSYS_TOP_ADB_DCM_REG1_OFF ((0x0 << 16) |	\
+					(0x0 << 17) |	\
+					(0x0 << 18))
+
+bool dcm_mp_cpusys_top_adb_dcm_is_on(void)
+{
+	bool ret = true;
+
+	ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP_ADB_DCM_CFG4) &
+		MP_CPUSYS_TOP_ADB_DCM_REG0_MASK) ==
+		(unsigned int) MP_CPUSYS_TOP_ADB_DCM_REG0_ON);
+	ret &= ((mmio_read_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0) &
+		MP_CPUSYS_TOP_ADB_DCM_REG1_MASK) ==
+		(unsigned int) MP_CPUSYS_TOP_ADB_DCM_REG1_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_CPUSYS_TOP_MP_ADB_DCM_CFG4,
+			MP_CPUSYS_TOP_ADB_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_ADB_DCM_REG0_ON);
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0,
+			MP_CPUSYS_TOP_ADB_DCM_REG1_MASK,
+			MP_CPUSYS_TOP_ADB_DCM_REG1_ON);
+	} else {
+		/* TINFO = "Turn OFF DCM 'mp_cpusys_top_adb_dcm'" */
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_ADB_DCM_CFG4,
+			MP_CPUSYS_TOP_ADB_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_ADB_DCM_REG0_OFF);
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0,
+			MP_CPUSYS_TOP_ADB_DCM_REG1_MASK,
+			MP_CPUSYS_TOP_ADB_DCM_REG1_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_CPUSYS_TOP_MP_MISC_DCM_CFG0) &
+		MP_CPUSYS_TOP_APB_DCM_REG0_MASK) ==
+		(unsigned int) MP_CPUSYS_TOP_APB_DCM_REG0_ON);
+	ret &= ((mmio_read_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0) &
+		MP_CPUSYS_TOP_APB_DCM_REG1_MASK) ==
+		(unsigned int) MP_CPUSYS_TOP_APB_DCM_REG1_ON);
+	ret &= ((mmio_read_32(MP_CPUSYS_TOP_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_CPUSYS_TOP_MP_MISC_DCM_CFG0,
+			MP_CPUSYS_TOP_APB_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_APB_DCM_REG0_ON);
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0,
+			MP_CPUSYS_TOP_APB_DCM_REG1_MASK,
+			MP_CPUSYS_TOP_APB_DCM_REG1_ON);
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_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_CPUSYS_TOP_MP_MISC_DCM_CFG0,
+			MP_CPUSYS_TOP_APB_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_APB_DCM_REG0_OFF);
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0,
+			MP_CPUSYS_TOP_APB_DCM_REG1_MASK,
+			MP_CPUSYS_TOP_APB_DCM_REG1_OFF);
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_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) |	\
+						 BIT(24) |	\
+						 BIT(25))
+#define MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_ON (BIT(11) |	\
+					       BIT(24) |	\
+					       BIT(25))
+#define MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_OFF ((0x0 << 11) |	\
+						(0x0 << 24) |	\
+						(0x0 << 25))
+
+bool dcm_mp_cpusys_top_bus_pll_div_dcm_is_on(void)
+{
+	bool ret = true;
+
+	ret &= ((mmio_read_32(MP_CPUSYS_TOP_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(MP_CPUSYS_TOP_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(MP_CPUSYS_TOP_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(MP_CPUSYS_TOP_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(MP_CPUSYS_TOP_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(MP_CPUSYS_TOP_MP0_DCM_CFG7,
+			MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_OFF);
+	}
+}
+
+#define MP_CPUSYS_TOP_CPUBIU_DBG_CG_REG0_MASK (BIT(0))
+#define MP_CPUSYS_TOP_CPUBIU_DBG_CG_REG0_ON ((0x0 << 0))
+#define MP_CPUSYS_TOP_CPUBIU_DBG_CG_REG0_OFF (BIT(0))
+
+bool dcm_mp_cpusys_top_cpubiu_dbg_cg_is_on(void)
+{
+	bool ret = true;
+
+	ret &= ((mmio_read_32(MP_CPUSYS_TOP_MCSI_CFG2) &
+		MP_CPUSYS_TOP_CPUBIU_DBG_CG_REG0_MASK) ==
+		(unsigned int) MP_CPUSYS_TOP_CPUBIU_DBG_CG_REG0_ON);
+
+	return ret;
+}
+
+void dcm_mp_cpusys_top_cpubiu_dbg_cg(bool on)
+{
+	if (on) {
+		/* TINFO = "Turn ON DCM 'mp_cpusys_top_cpubiu_dbg_cg'" */
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_MCSI_CFG2,
+			MP_CPUSYS_TOP_CPUBIU_DBG_CG_REG0_MASK,
+			MP_CPUSYS_TOP_CPUBIU_DBG_CG_REG0_ON);
+	} else {
+		/* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpubiu_dbg_cg'" */
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_MCSI_CFG2,
+			MP_CPUSYS_TOP_CPUBIU_DBG_CG_REG0_MASK,
+			MP_CPUSYS_TOP_CPUBIU_DBG_CG_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(MP_CPUSYS_TOP_MCSIC_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(MP_CPUSYS_TOP_MCSIC_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(MP_CPUSYS_TOP_MCSIC_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) |	\
+						   BIT(24) |	\
+						   BIT(25))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_ON (BIT(11) |	\
+						 BIT(24) |	\
+						 BIT(25))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_OFF ((0x0 << 11) |	\
+						  (0x0 << 24) |	\
+						  (0x0 << 25))
+
+bool dcm_mp_cpusys_top_cpu_pll_div_0_dcm_is_on(void)
+{
+	bool ret = true;
+
+	ret &= ((mmio_read_32(MP_CPUSYS_TOP_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(MP_CPUSYS_TOP_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(MP_CPUSYS_TOP_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) |	\
+						   BIT(24) |	\
+						   BIT(25))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_ON (BIT(11) |	\
+						 BIT(24) |	\
+						 BIT(25))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_OFF ((0x0 << 11) |	\
+						  (0x0 << 24) |	\
+						  (0x0 << 25))
+
+bool dcm_mp_cpusys_top_cpu_pll_div_1_dcm_is_on(void)
+{
+	bool ret = true;
+
+	ret &= ((mmio_read_32(MP_CPUSYS_TOP_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(MP_CPUSYS_TOP_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(MP_CPUSYS_TOP_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_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(MP_CPUSYS_TOP_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(MP_CPUSYS_TOP_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(MP_CPUSYS_TOP_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 (BIT(31))
+#define MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_ON (BIT(31))
+#define MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_OFF ((0x0 << 31))
+
+bool dcm_mp_cpusys_top_last_cor_idle_dcm_is_on(void)
+{
+	bool ret = true;
+
+	ret &= ((mmio_read_32(MP_CPUSYS_TOP_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(MP_CPUSYS_TOP_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(MP_CPUSYS_TOP_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(0) |	\
+					  BIT(1) |	\
+					  BIT(2) |	\
+					  BIT(3) |	\
+					  BIT(4))
+#define MP_CPUSYS_TOP_MISC_DCM_REG0_ON (BIT(0) |	\
+					BIT(1) |	\
+					BIT(2) |	\
+					BIT(3) |	\
+					BIT(4))
+#define MP_CPUSYS_TOP_MISC_DCM_REG0_OFF ((0x0 << 0) |	\
+					 (0x0 << 1) |	\
+					 (0x0 << 2) |	\
+					 (0x0 << 3) |	\
+					 (0x0 << 4))
+
+bool dcm_mp_cpusys_top_misc_dcm_is_on(void)
+{
+	bool ret = true;
+
+	ret &= ((mmio_read_32(MP_CPUSYS_TOP_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_CPUSYS_TOP_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_CPUSYS_TOP_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(0) |	\
+			BIT(1) |			\
+			BIT(2) |			\
+			BIT(3))
+#define MP_CPUSYS_TOP_MP0_QDCM_REG0_ON (BIT(0) |	\
+			BIT(1) |			\
+			BIT(2) |			\
+			BIT(3))
+#define MP_CPUSYS_TOP_MP0_QDCM_REG0_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_CPUSYS_TOP_MP0_DCM_CFG0) &
+		MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK) ==
+		(unsigned int) MP_CPUSYS_TOP_MP0_QDCM_REG0_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_CPUSYS_TOP_MP0_DCM_CFG0,
+			MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK,
+			MP_CPUSYS_TOP_MP0_QDCM_REG0_ON);
+	} else {
+		/* TINFO = "Turn OFF DCM 'mp_cpusys_top_mp0_qdcm'" */
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG0,
+			MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK,
+			MP_CPUSYS_TOP_MP0_QDCM_REG0_OFF);
+	}
+}
+
+#define CPCCFG_REG_EMI_WFIFO_REG0_MASK (BIT(0) | BIT(2))
+#define CPCCFG_REG_EMI_WFIFO_REG0_ON (BIT(0) | BIT(2))
+#define CPCCFG_REG_EMI_WFIFO_REG0_OFF ((0x0 << 0) | (0x0 << 2))
+
+bool dcm_cpccfg_reg_emi_wfifo_is_on(void)
+{
+	bool ret = true;
+
+	ret &= ((mmio_read_32(CPCCFG_REG_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(CPCCFG_REG_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(CPCCFG_REG_EMI_WFIFO,
+			CPCCFG_REG_EMI_WFIFO_REG0_MASK,
+			CPCCFG_REG_EMI_WFIFO_REG0_OFF);
+	}
+}
+
diff --git a/plat/mediatek/mt8186/drivers/dcm/mtk_dcm_utils.h b/plat/mediatek/mt8186/drivers/dcm/mtk_dcm_utils.h
new file mode 100644
index 0000000..ba76594
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/dcm/mtk_dcm_utils.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2021, 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	0xc538000
+#define CPCCFG_REG_BASE		0xc53a800
+
+/* Register Definition */
+#define CPCCFG_REG_EMI_WFIFO		(CPCCFG_REG_BASE + 0x100)
+#define MP_CPUSYS_TOP_BUS_PLLDIV_CFG	(MP_CPUSYS_TOP_BASE + 0x22e0)
+#define MP_CPUSYS_TOP_CPU_PLLDIV_CFG0	(MP_CPUSYS_TOP_BASE + 0x22a0)
+#define MP_CPUSYS_TOP_CPU_PLLDIV_CFG1	(MP_CPUSYS_TOP_BASE + 0x22a4)
+#define MP_CPUSYS_TOP_MCSIC_DCM0	(MP_CPUSYS_TOP_BASE + 0x2440)
+#define MP_CPUSYS_TOP_MCSI_CFG2		(MP_CPUSYS_TOP_BASE + 0x2418)
+#define MP_CPUSYS_TOP_MCUSYS_DCM_CFG0	(MP_CPUSYS_TOP_BASE + 0x25c0)
+#define MP_CPUSYS_TOP_MP0_DCM_CFG0	(MP_CPUSYS_TOP_BASE + 0x4880)
+#define MP_CPUSYS_TOP_MP0_DCM_CFG7	(MP_CPUSYS_TOP_BASE + 0x489c)
+#define MP_CPUSYS_TOP_MP_ADB_DCM_CFG4	(MP_CPUSYS_TOP_BASE + 0x2510)
+#define MP_CPUSYS_TOP_MP_MISC_DCM_CFG0	(MP_CPUSYS_TOP_BASE + 0x2518)
+
+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_dbg_cg_is_on(void);
+void dcm_mp_cpusys_top_cpubiu_dbg_cg(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_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);
+bool dcm_cpccfg_reg_emi_wfifo_is_on(void);
+void dcm_cpccfg_reg_emi_wfifo(bool on);
+#endif
diff --git a/plat/mediatek/mt8186/drivers/emi_mpu/emi_mpu.c b/plat/mediatek/mt8186/drivers/emi_mpu/emi_mpu.c
new file mode 100644
index 0000000..989ecf1
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/emi_mpu/emi_mpu.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <emi_mpu.h>
+
+#if ENABLE_EMI_MPU_SW_LOCK
+static unsigned char region_lock_state[EMI_MPU_REGION_NUM];
+#endif
+
+#define EMI_MPU_START_MASK		(0x00FFFFFF)
+#define EMI_MPU_END_MASK		(0x00FFFFFF)
+#define EMI_MPU_APC_SW_LOCK_MASK	(0x00FFFFFF)
+#define EMI_MPU_APC_HW_LOCK_MASK	(0x80FFFFFF)
+
+static int _emi_mpu_set_protection(unsigned int start, unsigned int end,
+				   unsigned int apc)
+{
+	unsigned int dgroup;
+	unsigned int region;
+
+	region = (start >> 24) & 0xFF;
+	start &= EMI_MPU_START_MASK;
+	dgroup = (end >> 24) & 0xFF;
+	end &= EMI_MPU_END_MASK;
+
+	if  ((region >= EMI_MPU_REGION_NUM) || (dgroup > EMI_MPU_DGROUP_NUM)) {
+		WARN("invalid region, domain\n");
+		return -1;
+	}
+
+#if ENABLE_EMI_MPU_SW_LOCK
+	if (region_lock_state[region] == 1) {
+		WARN("invalid region\n");
+		return -1;
+	}
+
+	if ((dgroup == 0U) && ((apc >> 31) & 0x1)) {
+		region_lock_state[region] = 1;
+	}
+
+	apc &= EMI_MPU_APC_SW_LOCK_MASK;
+#else
+	apc &= EMI_MPU_APC_HW_LOCK_MASK;
+#endif
+
+	if ((start >= DRAM_OFFSET) && (end >= start)) {
+		start -= DRAM_OFFSET;
+		end -= DRAM_OFFSET;
+	} else {
+		WARN("invalid range\n");
+		return -1;
+	}
+
+	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);
+
+#if defined(SUB_EMI_MPU_BASE)
+	mmio_write_32(SUB_EMI_MPU_SA(region), start);
+	mmio_write_32(SUB_EMI_MPU_EA(region), end);
+	mmio_write_32(SUB_EMI_MPU_APC(region, dgroup), apc);
+#endif
+	return 0;
+}
+
+int emi_mpu_set_protection(struct emi_region_info_t *region_info)
+{
+	unsigned int start, end;
+	int i;
+
+	if (region_info->region >= EMI_MPU_REGION_NUM) {
+		WARN("invalid region\n");
+		return -1;
+	}
+
+	start = (unsigned int)(region_info->start >> EMI_MPU_ALIGN_BITS) |
+		(region_info->region << 24);
+
+	for (i = EMI_MPU_DGROUP_NUM - 1; i >= 0; i--) {
+		end = (unsigned int)(region_info->end >> EMI_MPU_ALIGN_BITS) | (i << 24);
+
+		if (_emi_mpu_set_protection(start, end, region_info->apc[i]) < 0) {
+			WARN("failed to set emi mpu protection(%d, %d, %d)\n",
+			     start, end, region_info->apc[i]);
+		}
+	}
+
+	return 0;
+}
+
+void emi_mpu_init(void)
+{
+	/* TODO: more setting for EMI MPU. */
+}
diff --git a/plat/mediatek/mt8186/drivers/emi_mpu/emi_mpu.h b/plat/mediatek/mt8186/drivers/emi_mpu/emi_mpu.h
new file mode 100644
index 0000000..415146e
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/emi_mpu/emi_mpu.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2021, 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 ENABLE_EMI_MPU_SW_LOCK		1
+
+#define EMI_MPU_CTRL			(EMI_MPU_BASE + 0x000)
+#define EMI_MPU_DBG			(EMI_MPU_BASE + 0x004)
+#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_START			(0x000)
+#define EMI_MPU_END			(0x93C)
+
+#define SUB_EMI_MPU_CTRL		(SUB_EMI_MPU_BASE + 0x000)
+#define SUB_EMI_MPU_DBG			(SUB_EMI_MPU_BASE + 0x004)
+#define SUB_EMI_MPU_SA0			(SUB_EMI_MPU_BASE + 0x100)
+#define SUB_EMI_MPU_EA0			(SUB_EMI_MPU_BASE + 0x200)
+#define SUB_EMI_MPU_SA(region)		(SUB_EMI_MPU_SA0 + (region * 4))
+#define SUB_EMI_MPU_EA(region)		(SUB_EMI_MPU_EA0 + (region * 4))
+#define SUB_EMI_MPU_APC0		(SUB_EMI_MPU_BASE + 0x300)
+#define SUB_EMI_MPU_APC(region, dgroup)	(SUB_EMI_MPU_APC0 + (region * 4) + (dgroup * 0x100))
+#define SUB_EMI_MPU_CTRL_D0		(SUB_EMI_MPU_BASE + 0x800)
+#define SUB_EMI_MPU_CTRL_D(domain)	(SUB_EMI_MPU_CTRL_D0 + (domain * 4))
+#define SUB_EMI_RG_MASK_D0		(SUB_EMI_MPU_BASE + 0x900)
+#define SUB_EMI_RG_MASK_D(domain)	(SUB_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 NO_PROTECTION			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 LOCK				1
+#define UNLOCK				0
+
+#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[1] = 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 int apc[EMI_MPU_DGROUP_NUM];
+};
+
+void emi_mpu_init(void);
+
+#endif
diff --git a/plat/mediatek/mt8186/drivers/gpio/mtgpio.c b/plat/mediatek/mt8186/drivers/gpio/mtgpio.c
new file mode 100644
index 0000000..134476a
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/gpio/mtgpio.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <mtgpio.h>
+#include <platform_def.h>
+
+uintptr_t mt_gpio_find_reg_addr(uint32_t pin)
+{
+	uintptr_t reg_addr = 0U;
+	struct mt_pin_info gpio_info;
+
+	assert(pin < MAX_GPIO_PIN);
+
+	gpio_info = mt_pin_infos[pin];
+
+	switch (gpio_info.base & 0x0f) {
+	case 0:
+		reg_addr = IOCFG_LT_BASE;
+		break;
+	case 1:
+		reg_addr = IOCFG_LM_BASE;
+		break;
+	case 2:
+		reg_addr = IOCFG_LB_BASE;
+		break;
+	case 3:
+		reg_addr = IOCFG_BL_BASE;
+		break;
+	case 4:
+		reg_addr = IOCFG_RB_BASE;
+		break;
+	case 5:
+		reg_addr = IOCFG_RT_BASE;
+		break;
+	default:
+		break;
+	}
+
+	return reg_addr;
+}
diff --git a/plat/mediatek/mt8186/drivers/gpio/mtgpio.h b/plat/mediatek/mt8186/drivers/gpio/mtgpio.h
new file mode 100644
index 0000000..4430a58
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/gpio/mtgpio.h
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_GPIO_H
+#define MT_GPIO_H
+
+#include <mtgpio_common.h>
+
+/* Enumeration for GPIO pin */
+typedef enum GPIO_PIN {
+	GPIO_UNSUPPORTED = -1,
+	GPIO0, GPIO1, GPIO2, GPIO3, GPIO4, GPIO5, GPIO6,
+	GPIO7, GPIO8, GPIO9, GPIO10, GPIO11, GPIO12, GPIO13, GPIO14,
+	GPIO15, GPIO16, GPIO17, GPIO18, GPIO19, GPIO20, GPIO21, GPIO22,
+	GPIO23, GPIO24, GPIO25, GPIO26, GPIO27, GPIO28, GPIO29, GPIO30,
+	GPIO31, GPIO32, GPIO33, GPIO34, GPIO35, GPIO36, GPIO37, GPIO38,
+	GPIO39, GPIO40, GPIO41, GPIO42, GPIO43, GPIO44, GPIO45, GPIO46,
+	GPIO47, GPIO48, GPIO49, GPIO50, GPIO51, GPIO52, GPIO53, GPIO54,
+	GPIO55, GPIO56, GPIO57, GPIO58, GPIO59, GPIO60, GPIO61, GPIO62,
+	GPIO63, GPIO64, GPIO65, GPIO66, GPIO67, GPIO68, GPIO69, GPIO70,
+	GPIO71, GPIO72, GPIO73, GPIO74, GPIO75, GPIO76, GPIO77, GPIO78,
+	GPIO79, GPIO80, GPIO81, GPIO82, GPIO83, GPIO84, GPIO85, GPIO86,
+	GPIO87, GPIO88, GPIO89, GPIO90, GPIO91, GPIO92, GPIO93, GPIO94,
+	GPIO95, GPIO96, GPIO97, GPIO98, GPIO99, GPIO100, GPIO101, GPIO102,
+	GPIO103, GPIO104, GPIO105, GPIO106, GPIO107, GPIO108, GPIO109, GPIO110,
+	GPIO111, GPIO112, GPIO113, GPIO114, GPIO115, GPIO116, GPIO117, GPIO118,
+	GPIO119, GPIO120, GPIO121, GPIO122, GPIO123, GPIO124, GPIO125, GPIO126,
+	GPIO127, GPIO128, GPIO129, GPIO130, GPIO131, GPIO132, GPIO133, GPIO134,
+	GPIO135, GPIO136, GPIO137, GPIO138, GPIO139, GPIO140, GPIO141, GPIO142,
+	GPIO143, GPIO144, GPIO145, GPIO146, GPIO147, GPIO148, GPIO149, GPIO150,
+	GPIO151, GPIO152, GPIO153, GPIO154, GPIO155, GPIO156, GPIO157, GPIO158,
+	GPIO159, GPIO160, GPIO161, GPIO162, GPIO163, GPIO164, GPIO165, GPIO166,
+	GPIO167, GPIO168, GPIO169, GPIO170, GPIO171, GPIO172, GPIO173, GPIO174,
+	GPIO175, GPIO176, GPIO177, GPIO178, GPIO179, GPIO180, GPIO181, GPIO182,
+	GPIO183, GPIO184,
+	MT_GPIO_BASE_MAX
+} GPIO_PIN;
+
+static const struct mt_pin_info mt_pin_infos[] = {
+	PIN(0, 0, 13, 0x16, 0x40),
+	PIN(1, 0, 14, 0x16, 0x40),
+	PIN(2, 0, 17, 0x16, 0x40),
+	PIN(3, 0, 18, 0x16, 0x40),
+	PIN(4, 0, 19, 0x16, 0x40),
+	PIN(5, 0, 20, 0x16, 0x40),
+	PIN(6, 0, 19, 0x24, 0x40),
+	PIN(7, 0, 20, 0x24, 0x40),
+	PIN(8, 0, 21, 0x24, 0x40),
+	PIN(9, 0, 22, 0x24, 0x40),
+	PIN(10, 0, 16, 0x24, 0x40),
+	PIN(11, 0, 17, 0x24, 0x40),
+	PIN(12, 0, 18, 0x24, 0x40),
+	PIN(13, 0, 0, 0x23, 0x60),
+	PIN(14, 0, 1, 0x23, 0x60),
+	PIN(15, 0, 15, 0x16, 0x40),
+	PIN(16, 0, 16, 0x16, 0x40),
+	PIN(17, 0, 9, 0x25, 0x70),
+	PIN(18, 0, 10, 0x25, 0x70),
+	PIN(19, 0, 3, 0x25, 0x70),
+	PIN(20, 0, 6, 0x25, 0x70),
+	PIN(21, 0, 4, 0x25, 0x70),
+	PIN(22, 0, 7, 0x25, 0x70),
+	PIN(23, 0, 5, 0x25, 0x70),
+	PIN(24, 0, 8, 0x25, 0x70),
+	PIN(25, 0, 18, 0x25, 0x70),
+	PIN(26, 0, 15, 0x25, 0x70),
+	PIN(27, 0, 17, 0x25, 0x70),
+	PIN(28, 0, 16, 0x25, 0x70),
+	PIN(29, 0, 0, 0x16, 0x40),
+	PIN(30, 0, 1, 0x16, 0x40),
+	PIN(31, 0, 2, 0x16, 0x40),
+	PIN(32, 0, 25, 0x12, 0x50),
+	PIN(33, 0, 27, 0x12, 0x50),
+	PIN(34, 0, 26, 0x12, 0x50),
+	PIN(35, 0, 28, 0x12, 0x50),
+	PIN(36, 0, 9, 0x12, 0x50),
+	PIN(37, 0, 10, 0x12, 0x50),
+	PIN(38, 0, 12, 0x12, 0x50),
+	PIN(39, 0, 11, 0x12, 0x50),
+	PIN(40, 0, 13, 0x12, 0x50),
+	PIN(41, 0, 14, 0x12, 0x50),
+	PIN(42, 0, 16, 0x12, 0x50),
+	PIN(43, 0, 15, 0x12, 0x50),
+	PIN(44, 0, 28, 0x25, 0x70),
+	PIN(45, 0, 29, 0x25, 0x70),
+	PIN(46, 0, 31, 0x25, 0x70),
+	PIN(47, 0, 30, 0x25, 0x70),
+	PIN(48, 0, 17, 0x12, 0x50),
+	PIN(49, 0, 18, 0x12, 0x50),
+	PIN(50, 0, 20, 0x12, 0x50),
+	PIN(51, 0, 19, 0x12, 0x50),
+	PIN(52, 0, 12, 0x23, 0x60),
+	PIN(53, 0, 13, 0x23, 0x60),
+	PIN(54, 0, 15, 0x23, 0x60),
+	PIN(55, 0, 14, 0x23, 0x60),
+	PIN(56, 0, 12, 0x25, 0x70),
+	PIN(57, 0, 11, 0x25, 0x70),
+	PIN(58, 0, 13, 0x25, 0x70),
+	PIN(59, 0, 14, 0x25, 0x70),
+	PIN(60, 0, 21, 0x23, 0x60),
+	PIN(61, 0, 16, 0x23, 0x60),
+	PIN(62, 0, 22, 0x23, 0x60),
+	PIN(63, 0, 17, 0x23, 0x60),
+	PIN(64, 0, 18, 0x23, 0x60),
+	PIN(65, 0, 19, 0x23, 0x60),
+	PIN(66, 0, 20, 0x23, 0x60),
+	PIN(67, 1, 10, 0x21, 0x70),
+	PIN(68, 1, 0, 0x21, 0x70),
+	PIN(69, 1, 1, 0x21, 0x70),
+	PIN(70, 1, 11, 0x21, 0x70),
+	PIN(71, 1, 2, 0x21, 0x70),
+	PIN(72, 1, 3, 0x21, 0x70),
+	PIN(73, 1, 4, 0x21, 0x70),
+	PIN(74, 1, 5, 0x21, 0x70),
+	PIN(75, 1, 6, 0x21, 0x70),
+	PIN(76, 1, 7, 0x21, 0x70),
+	PIN(77, 1, 8, 0x21, 0x70),
+	PIN(78, 1, 9, 0x21, 0x70),
+	PIN(79, 1, 0, 0x25, 0x80),
+	PIN(80, 1, 1, 0x25, 0x80),
+	PIN(81, 1, 2, 0x25, 0x80),
+	PIN(82, 1, 3, 0x25, 0x80),
+	PIN(83, 0, 3, 0x16, 0x40),
+	PIN(84, 1, 0, 0x23, 0x70),
+	PIN(85, 1, 1, 0x23, 0x70),
+	PIN(86, 1, 2, 0x23, 0x70),
+	PIN(87, 1, 3, 0x23, 0x70),
+	PIN(88, 1, 4, 0x23, 0x70),
+	PIN(89, 1, 5, 0x23, 0x70),
+	PIN(90, 0, 2, 0x23, 0x60),
+	PIN(91, 0, 23, 0x23, 0x60),
+	PIN(92, 0, 25, 0x23, 0x60),
+	PIN(93, 0, 3, 0x23, 0x60),
+	PIN(94, 0, 24, 0x23, 0x60),
+	PIN(95, 0, 26, 0x23, 0x60),
+	PIN(96, 0, 1, 0x12, 0x50),
+	PIN(97, 0, 0, 0x12, 0x50),
+	PIN(98, 0, 2, 0x12, 0x50),
+	PIN(99, 0, 14, 0x24, 0x40),
+	PIN(100, 0, 15, 0x24, 0x40),
+	PIN(101, 0, 13, 0x24, 0x40),
+	PIN(102, 0, 12, 0x24, 0x40),
+	PIN(103, 0, 0, 0x24, 0x40),
+	PIN(104, 0, 1, 0x24, 0x40),
+	PIN(105, 0, 4, 0x24, 0x40),
+	PIN(106, 0, 5, 0x24, 0x40),
+	PIN(107, 0, 6, 0x24, 0x40),
+	PIN(108, 0, 7, 0x24, 0x40),
+	PIN(109, 0, 8, 0x24, 0x40),
+	PIN(110, 0, 9, 0x24, 0x40),
+	PIN(111, 0, 10, 0x24, 0x40),
+	PIN(112, 0, 11, 0x24, 0x40),
+	PIN(113, 0, 2, 0x24, 0x40),
+	PIN(114, 0, 3, 0x24, 0x40),
+	PIN(115, 0, 4, 0x23, 0x60),
+	PIN(116, 0, 7, 0x23, 0x60),
+	PIN(117, 0, 5, 0x23, 0x60),
+	PIN(118, 0, 6, 0x23, 0x60),
+	PIN(119, 0, 22, 0x25, 0x70),
+	PIN(120, 0, 19, 0x25, 0x70),
+	PIN(121, 0, 20, 0x25, 0x70),
+	PIN(122, 0, 21, 0x25, 0x70),
+	PIN(123, 0, 23, 0x25, 0x70),
+	PIN(124, 0, 0, 0x25, 0x70),
+	PIN(125, 0, 1, 0x25, 0x70),
+	PIN(126, 0, 2, 0x25, 0x70),
+	PIN(127, 0, 8, 0x23, 0x60),
+	PIN(128, 0, 10, 0x23, 0x60),
+	PIN(129, 0, 24, 0x25, 0x70),
+	PIN(130, 0, 26, 0x25, 0x70),
+	PIN(131, 0, 25, 0x25, 0x70),
+	PIN(132, 0, 27, 0x25, 0x70),
+	PIN(133, 0, 9, 0x21, 0x60),
+	PIN(134, 0, 12, 0x21, 0x60),
+	PIN(135, 0, 21, 0x16, 0x40),
+	PIN(136, 0, 24, 0x16, 0x40),
+	PIN(137, 0, 10, 0x21, 0x60),
+	PIN(138, 0, 13, 0x21, 0x60),
+	PIN(139, 0, 7, 0x12, 0x50),
+	PIN(140, 0, 8, 0x12, 0x50),
+	PIN(141, 0, 9, 0x23, 0x60),
+	PIN(142, 0, 11, 0x23, 0x60),
+	PIN(143, 0, 22, 0x16, 0x40),
+	PIN(144, 0, 25, 0x16, 0x40),
+	PIN(145, 0, 23, 0x16, 0x40),
+	PIN(146, 0, 26, 0x16, 0x40),
+	PIN(147, 0, 23, 0x24, 0x40),
+	PIN(148, 0, 24, 0x24, 0x40),
+	PIN(149, 0, 25, 0x24, 0x40),
+	PIN(150, 0, 26, 0x24, 0x40),
+	PIN(151, 0, 27, 0x24, 0x40),
+	PIN(152, 0, 28, 0x24, 0x40),
+	PIN(153, 0, 29, 0x24, 0x40),
+	PIN(154, 0, 30, 0x24, 0x40),
+	PIN(155, 0, 31, 0x24, 0x40),
+	PIN(156, 0, 0, 0x24, 0x50),
+	PIN(157, 0, 4, 0x12, 0x50),
+	PIN(158, 0, 3, 0x12, 0x50),
+	PIN(159, 0, 6, 0x12, 0x50),
+	PIN(160, 0, 5, 0x12, 0x50),
+	PIN(161, 0, 23, 0x12, 0x50),
+	PIN(162, 0, 24, 0x12, 0x50),
+	PIN(163, 0, 11, 0x21, 0x60),
+	PIN(164, 0, 8, 0x21, 0x60),
+	PIN(165, 0, 16, 0x21, 0x60),
+	PIN(166, 0, 1, 0x21, 0x60),
+	PIN(167, 0, 7, 0x21, 0x60),
+	PIN(168, 0, 4, 0x21, 0x60),
+	PIN(169, 0, 5, 0x21, 0x60),
+	PIN(170, 0, 0, 0x21, 0x60),
+	PIN(171, 0, 6, 0x21, 0x60),
+	PIN(172, 0, 2, 0x21, 0x60),
+	PIN(173, 0, 3, 0x21, 0x60),
+	PIN(174, 0, 7, 0x16, 0x40),
+	PIN(175, 0, 8, 0x16, 0x40),
+	PIN(176, 0, 4, 0x16, 0x40),
+	PIN(177, 0, 5, 0x16, 0x40),
+	PIN(178, 0, 6, 0x16, 0x40),
+	PIN(179, 0, 9, 0x16, 0x40),
+	PIN(180, 0, 10, 0x16, 0x40),
+	PIN(181, 0, 11, 0x16, 0x40),
+	PIN(182, 0, 12, 0x16, 0x40),
+	PIN(183, 0, 21, 0x12, 0x50),
+	PIN(184, 0, 22, 0x12, 0x50),
+};
+
+#endif /* MT_GPIO_H */
diff --git a/plat/mediatek/mt8186/drivers/mcdi/build.mk b/plat/mediatek/mt8186/drivers/mcdi/build.mk
new file mode 100644
index 0000000..45acb5d
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/mcdi/build.mk
@@ -0,0 +1,31 @@
+#
+# Copyright (c) 2021, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+MCDI_TINYSYS_TYPE = sspm
+MCDI_TINYSYS_MBOX_TYPE = share_sram
+
+CUR_MCDI_FOLDER = ${MTK_PLAT_SOC}/drivers/mcdi
+
+BL31_MT_LPM_PLAT_CFLAGS += -I${CUR_MCDI_FOLDER}/
+
+BL31_MT_LPM_PLAT_SOURCE += \
+	${CUR_MCDI_FOLDER}/mt_cpu_pm.c	\
+	${CUR_MCDI_FOLDER}/mt_cpu_pm_cpc.c \
+	${CUR_MCDI_FOLDER}/mt_mcdi.c	\
+	${CUR_MCDI_FOLDER}/mt_lp_irqremain.c
+
+
+ifeq ($(MCDI_TINYSYS_TYPE), sspm)
+BL31_MT_LPM_PLAT_CFLAGS += -DMCDI_TINYSYS_SSPM
+BL31_MT_LPM_PLAT_SOURCE += ${CUR_MCDI_FOLDER}/mt_cpu_pm_mbox_sspm.c
+else
+BL31_MT_LPM_PLAT_CFLAGS += -DMCDI_TINYSYS_MCUPM
+BL31_MT_LPM_PLAT_SOURCE += ${CUR_MCDI_FOLDER}/mt_cpu_pm_mbox.c
+endif
+
+ifeq ($(MCDI_TINYSYS_MBOX_TYPE), share_sram)
+BL31_MT_LPM_PLAT_CFLAGS += -DMCDI_TINYSYS_MBOX_SHARE_SRAM
+endif
diff --git a/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm.c b/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm.c
new file mode 100644
index 0000000..c6c2e38
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2021, 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/mt8186/drivers/mcdi/mt_cpu_pm.h b/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm.h
new file mode 100644
index 0000000..83a7a53
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __MT_CPU_PM_H__
+#define __MT_CPU_PM_H__
+
+#define MCUSYS_STATUS_PDN		(1 << 0UL)
+#define MCUSYS_STATUS_CPUSYS_PROTECT	(1 << 8UL)
+#define MCUSYS_STATUS_MCUSYS_PROTECT	(1 << 9UL)
+
+/* cpu_pm function ID*/
+enum mt_cpu_pm_user_id {
+	MCUSYS_STATUS,
+	CPC_COMMAND,
+	IRQ_REMAIN_LIST_ALLOC,
+	IRQ_REMAIN_IRQ_ADD,
+	IRQ_REMAIN_IRQ_SUBMIT,
+	MBOX_INFO,
+};
+
+/* cpu_pm lp function ID */
+enum mt_cpu_pm_lp_smc_id {
+	LP_CPC_COMMAND,
+	IRQS_REMAIN_ALLOC,
+	IRQS_REMAIN_CTRL,
+	IRQS_REMAIN_IRQ,
+	IRQS_REMAIN_WAKEUP_CAT,
+	IRQS_REMAIN_WAKEUP_SRC,
+};
+
+#endif
diff --git a/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm_cpc.c b/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm_cpc.c
new file mode 100644
index 0000000..2b0f071
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm_cpc.c
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2021, 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/mt8186/drivers/mcdi/mt_cpu_pm_cpc.h b/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm_cpc.h
new file mode 100644
index 0000000..488b1d1
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm_cpc.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2021, 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)	(0x11B000 + (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 = 0U,
+	CPC_ERR_FAIL = 1U,
+	CPC_ERR_TIMEOUT = 2U,
+	NF_CPC_ERR = 3U,
+};
+
+enum {
+	CPC_SMC_EVENT_DUMP_TRACE_DATA = 0U,
+	CPC_SMC_EVENT_GIC_DPG_SET = 1U,
+	CPC_SMC_EVENT_CPC_CONFIG = 2U,
+	CPC_SMC_EVENT_READ_CONFIG = 3U,
+	NF_CPC_SMC_EVENT = 4U,
+};
+
+enum {
+	CPC_SMC_CONFIG_PROF = 0U,
+	CPC_SMC_CONFIG_AUTO_OFF = 1U,
+	CPC_SMC_CONFIG_AUTO_OFF_THRES = 2U,
+	CPC_SMC_CONFIG_CNT_CLR = 3U,
+	CPC_SMC_CONFIG_TIME_SYNC = 4U,
+	NF_CPC_SMC_CONFIG = 5U,
+};
+
+#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/mt8186/drivers/mcdi/mt_cpu_pm_mbox.c b/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm_mbox.c
new file mode 100644
index 0000000..789fafb
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm_mbox.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <mmio.h>
+#include <mt_cpu_pm_mbox.h>
+#include <platform_def.h>
+#include <sspm_reg.h>
+
+#define MCUPM_MBOX_3_BASE	(MTK_MCUPM_SRAM_BASE + 0xFCE0)
+
+#define _sspm_mbox_write(id, val) \
+		mmio_write_32(SSPM_MBOX_3_BASE + 4 * (id), val)
+#define _sspm_mbox_read(id) \
+		mmio_read_32(SSPM_MBOX_3_BASE + 4 * (id))
+
+#define _mcupm_mbox_write(id, val) \
+		mmio_write_32(MCUPM_MBOX_3_BASE + 4 * (id), val)
+#define _mcupm_mbox_read(id) \
+		mmio_read_32(MCUPM_MBOX_3_BASE + 4 * (id))
+
+
+#define MCUPM_MBOX_OFFSET_PDN		(0x0C55FDA8)
+#define MCUPM_POWER_DOWN		(0x4D50444E)
+
+void mtk_set_sspm_lp_cmd(void *buf, unsigned int size)
+{
+	unsigned int *p = (unsigned int *)buf;
+	int i;
+
+	for (i = 0; i < size; i++) {
+		_sspm_mbox_write(SSPM_MBOX_SPM_CMD + i, p[i]);
+	}
+}
+
+void mtk_clr_sspm_lp_cmd(unsigned int size)
+{
+	int i;
+
+	for (i = 0; i < size; i++) {
+		_sspm_mbox_write(SSPM_MBOX_SPM_CMD + i, 0);
+	}
+}
+
+void mtk_set_cpu_pm_pll_mode(unsigned int mode)
+{
+	if (mode < NF_MCUPM_ARMPLL_MODE) {
+		_mcupm_mbox_write(MCUPM_MBOX_ARMPLL_MODE, mode);
+	}
+}
+
+int mtk_get_cpu_pm_pll_mode(void)
+{
+	return _mcupm_mbox_read(MCUPM_MBOX_ARMPLL_MODE);
+}
+
+void mtk_set_cpu_pm_buck_mode(unsigned int mode)
+{
+	if (mode < NF_MCUPM_BUCK_MODE) {
+		_mcupm_mbox_write(MCUPM_MBOX_BUCK_MODE, mode);
+	}
+}
+
+int mtk_get_cpu_pm_buck_mode(void)
+{
+	return _mcupm_mbox_read(MCUPM_MBOX_BUCK_MODE);
+}
+
+void mtk_set_cpu_pm_preffered_cpu(unsigned int cpuid)
+{
+	return _mcupm_mbox_read(MCUPM_MBOX_WAKEUP_CPU);
+}
+
+int mtk_set_cpu_pm_mbox_addr(uint64_t phy_addr)
+{
+	return 0;
+}
diff --git a/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm_mbox.h b/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm_mbox.h
new file mode 100644
index 0000000..63a43af
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm_mbox.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __MT_CPU_PM_MBOX_H__
+#define __MT_CPU_PM_MBOX_H__
+
+/* SSPM Mbox */
+/* AP Write */
+#define SSPM_MBOX_SPM_CMD	(0U)
+#define SSPM_MBOX_SPM_ARGS1	(1U)
+#define SSPM_MBOX_SPM_ARGS2	(2U)
+#define SSPM_MBOX_SPM_ARGS3	(3U)
+#define SSPM_MBOX_SPM_ARGS4	(4U)
+#define SSPM_MBOX_SPM_ARGS5	(5U)
+#define SSPM_MBOX_SPM_ARGS6	(6U)
+#define SSPM_MBOX_SPM_ARGS7	(7U)
+#define SSPM_MBOX_AP_READY	(17U)
+
+#define SSPM_MBOX_SPM_CMD_SIZE	(8U)
+
+void mtk_set_sspm_lp_cmd(void *buf, unsigned int size);
+void mtk_clr_sspm_lp_cmd(unsigned int size);
+
+/* MCUPM Mbox */
+/* AP Write */
+#define MCUPM_MBOX_AP_READY		(0U)
+#define MCUPM_MBOX_RESERVED_1		(1U)
+#define MCUPM_MBOX_RESERVED_2		(2U)
+#define MCUPM_MBOX_RESERVED_3		(3U)
+#define MCUPM_MBOX_PWR_CTRL_EN		(4U)
+#define MCUPM_MBOX_L3_CACHE_MODE	(5U)
+#define MCUPM_MBOX_BUCK_MODE		(6U)
+#define MCUPM_MBOX_ARMPLL_MODE		(7U)
+/* AP Read */
+#define MCUPM_MBOX_TASK_STA		(8U)
+#define MCUPM_MBOX_RESERVED_9		(9U)
+#define MCUPM_MBOX_RESERVED_10		(10U)
+#define MCUPM_MBOX_RESERVED_11		(11U)
+/* CPC mode - Read/Write */
+#define MCUPM_MBOX_WAKEUP_CPU		(12U)
+
+/* Mbox Slot: APMCU_MCUPM_MBOX_PWR_CTRL_EN (4) */
+#define MCUPM_MCUSYS_CTRL		(1U << 0)
+#define MCUPM_BUCK_CTRL			(1U << 1)
+#define MCUPM_ARMPLL_CTRL		(1U << 2)
+#define MCUPM_PWR_CTRL_MASK		((1U << 3) - 1U)
+
+/* Mbox Slot: APMCU_MCUPM_MBOX_L3_CACHE_MODE (5) */
+#define MCUPM_L3_OFF_MODE		(0U) /* default */
+#define MCUPM_L3_DORMANT_MODE		(1U)
+#define NF_MCUPM_L3_MODE		(2U)
+
+/* Mbox Slot: APMCU_MCUPM_MBOX_BUCK_MODE (6) */
+#define MCUPM_BUCK_NORMAL_MODE		(0U) /* default */
+#define MCUPM_BUCK_LP_MODE		(1U)
+#define MCUPM_BUCK_OFF_MODE		(2U)
+#define NF_MCUPM_BUCK_MODE		(3U)
+
+/* Mbox Slot: APMCU_MCUPM_MBOX_ARMPLL_MODE (7) */
+#define MCUPM_ARMPLL_ON			(0U) /* default */
+#define MCUPM_ARMPLL_GATING		(1U)
+#define MCUPM_ARMPLL_OFF		(2U)
+#define NF_MCUPM_ARMPLL_MODE		(3U)
+
+/* Mbox Slot: APMCU_MCUPM_MBOX_TASK_STA (9) */
+#define MCUPM_TASK_UNINIT		(0U)
+#define MCUPM_TASK_INIT			(1U)
+#define MCUPM_TASK_INIT_FINISH		(2U)
+#define MCUPM_TASK_WAIT			(3U)
+#define MCUPM_TASK_RUN			(4U)
+#define MCUPM_TASK_PAUSE		(5U)
+
+void mtk_set_cpu_pm_pll_mode(unsigned int mode);
+int mtk_get_cpu_pm_pll_mode(void);
+void mtk_set_cpu_pm_buck_mode(unsigned int mode);
+int mtk_get_cpu_pm_buck_mode(void);
+void mtk_set_cpu_pm_preffered_cpu(unsigned int cpuid);
+int mtk_set_cpu_pm_mbox_addr(uint64_t phy_addr);
+
+#endif
diff --git a/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm_mbox_sspm.c b/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm_mbox_sspm.c
new file mode 100644
index 0000000..34c281d
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm_mbox_sspm.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <mmio.h>
+#include <mt_cpu_pm.h>
+#include <mt_cpu_pm_mbox.h>
+#include <platform_def.h>
+#include <sspm_reg.h>
+
+#ifdef MCDI_TINYSYS_MBOX_SHARE_SRAM
+struct cpu_pm_mbox {
+	unsigned int ap_ready;
+	unsigned int reserved1;
+	unsigned int reserved2;
+	unsigned int reserved3;
+	unsigned int pwr_ctrl_en;
+	unsigned int l3_cache_mode;
+	unsigned int buck_mode;
+	unsigned int armpll_mode;
+	unsigned int task_sta;
+	unsigned int reserved9;
+	unsigned int reserved10;
+	unsigned int reserved11;
+	unsigned int wakeup_cpu;
+};
+
+struct cpu_pm_mbox *_cpu_pm_box = (struct cpu_pm_mbox *)SSPM_MBOX_3_BASE;
+#endif
+
+void mtk_set_cpu_pm_pll_mode(unsigned int mode)
+{
+#ifdef MCDI_TINYSYS_MBOX_SHARE_SRAM
+	if (_cpu_pm_box) {
+		_cpu_pm_box->armpll_mode = mode;
+	}
+#endif
+}
+
+int mtk_get_cpu_pm_pll_mode(void)
+{
+#ifdef MCDI_TINYSYS_MBOX_SHARE_SRAM
+	if (!_cpu_pm_box) {
+		return 0;
+	}
+	return _cpu_pm_box->armpll_mode;
+#endif
+}
+
+void mtk_set_cpu_pm_buck_mode(unsigned int mode)
+{
+#ifdef MCDI_TINYSYS_MBOX_SHARE_SRAM
+	if (_cpu_pm_box) {
+		_cpu_pm_box->buck_mode = mode;
+	}
+#endif
+}
+
+int mtk_get_cpu_pm_buck_mode(void)
+{
+#ifdef MCDI_TINYSYS_MBOX_SHARE_SRAM
+	if (!_cpu_pm_box) {
+		return 0;
+	}
+	return _cpu_pm_box->buck_mode;
+#endif
+}
+
+void mtk_set_cpu_pm_preffered_cpu(unsigned int cpuid)
+{
+#ifdef MCDI_TINYSYS_MBOX_SHARE_SRAM
+	if (_cpu_pm_box) {
+		_cpu_pm_box->wakeup_cpu = cpuid;
+	}
+#endif
+}
+
+int mtk_set_cpu_pm_mbox_addr(uint64_t phy_addr)
+{
+#ifdef MCDI_TINYSYS_MBOX_SHARE_SRAM
+	if (_cpu_pm_box || (phy_addr == 0)) {
+		return -1;
+	}
+
+	_cpu_pm_box = (struct cpu_pm_mbox *)(MTK_SSPM_BASE + phy_addr);
+#endif
+	return 0;
+}
diff --git a/plat/mediatek/mt8186/drivers/mcdi/mt_mcdi.c b/plat/mediatek/mt8186/drivers/mcdi/mt_mcdi.c
new file mode 100644
index 0000000..0103612
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/mcdi/mt_mcdi.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <cdefs.h>
+#include <common/debug.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(0x10420000)
+
+#define MCDI_NOT_INIT			U(0)
+#define MCDI_INIT_1			U(1)
+#define MCDI_INIT_2			U(2)
+#define MCDI_INIT_DONE			U(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;
+	}
+
+	INFO("mcdi ready for mcusys-off-idle and system suspend\n");
+
+	return (mcdi_init_status == MCDI_INIT_DONE) ? 0 : mcdi_init_status;
+}
diff --git a/plat/mediatek/mt8186/drivers/mcdi/mt_mcdi.h b/plat/mediatek/mt8186/drivers/mcdi/mt_mcdi.h
new file mode 100644
index 0000000..0e6444a
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/mcdi/mt_mcdi.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2021, 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/mt8186/drivers/pmic/pmic.c b/plat/mediatek/mt8186/drivers/pmic/pmic.c
new file mode 100644
index 0000000..4f7ab13
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/pmic/pmic.c
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <pmic.h>
+#include <pmic_wrap_init.h>
+
+uint32_t pmic_get_hwcid(void)
+{
+	uint32_t val = 0;
+
+	pwrap_read(PMIC_RG_HWCID_ADDR, &val);
+
+	return val;
+}
+
+void pmic_power_off(void)
+{
+	pwrap_write(PMIC_PWRHOLD, 0x0);
+}
diff --git a/plat/mediatek/mt8186/drivers/pmic/pmic.h b/plat/mediatek/mt8186/drivers/pmic/pmic.h
new file mode 100644
index 0000000..91ccb19
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/pmic/pmic.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PMIC_H
+#define PMIC_H
+
+#include <stdint.h>
+
+#define PMIC_RG_HWCID_ADDR 0x8
+#define PMIC_PWRHOLD 0xa08
+
+/* external API */
+uint32_t pmic_get_hwcid(void);
+void pmic_power_off(void);
+
+#endif /* PMIC_H */
diff --git a/plat/mediatek/mt8186/drivers/pmic/pmic_wrap_init.h b/plat/mediatek/mt8186/drivers/pmic/pmic_wrap_init.h
new file mode 100644
index 0000000..e837456
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/pmic/pmic_wrap_init.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2021, 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 mt8186_pmic_wrap_regs *const mtk_pwrap = (void *)PMIC_WRAP_BASE;
+
+/* timeout setting */
+enum {
+	TIMEOUT_RESET       = 50,	/* us */
+	TIMEOUT_READ        = 50,	/* us */
+	TIMEOUT_WAIT_IDLE   = 50	/* us */
+};
+
+/* PMIC_WRAP registers */
+struct mt8186_pmic_wrap_regs {
+	uint32_t unused[776];
+	uint32_t wacs2_cmd;
+	uint32_t wacs2_rdata;
+	uint32_t wacs2_vldclr;
+};
+
+enum {
+	RDATA_WACS_RDATA_SHIFT = 0,
+	RDATA_WACS_FSM_SHIFT = 16,
+	RDATA_WACS_REQ_SHIFT = 19,
+	RDATA_SYNC_IDLE_SHIFT = 20,
+	RDATA_INIT_DONE_SHIFT = 22,
+	RDATA_SYS_IDLE_SHIFT = 23,
+};
+
+enum {
+	RDATA_WACS_RDATA_MASK = 0xffff,
+	RDATA_WACS_FSM_MASK = 0x7,
+	RDATA_WACS_REQ_MASK = 0x1,
+	RDATA_SYNC_IDLE_MASK = 0x1,
+	RDATA_INIT_DONE_MASK = 0x1,
+	RDATA_SYS_IDLE_MASK = 0x1,
+};
+
+/* WACS_FSM */
+enum {
+	WACS_FSM_IDLE            = 0x00,
+	WACS_FSM_REQ             = 0x02,
+	WACS_FSM_WFDLE           = 0x04,
+	WACS_FSM_WFVLDCLR        = 0x06,
+	WACS_INIT_DONE           = 0x01,
+	WACS_SYNC_IDLE           = 0x01,
+	WACS_SYNC_BUSY           = 0x00
+};
+
+/* error information flag */
+enum {
+	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/mt8186/drivers/rtc/rtc.c b/plat/mediatek/mt8186/drivers/rtc/rtc.c
new file mode 100644
index 0000000..4fcf58e
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/rtc/rtc.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2021, 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 = 0;
+
+	pmic_reg = RTC_Read(addr);
+
+	pmic_reg &= ~(MASK << SHIFT);
+	pmic_reg |= (data << SHIFT);
+
+	RTC_Write(addr, pmic_reg);
+}
+
+static void 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);
+	RTC_Write_Trigger();
+}
+
+static void rtc_xosc_write(uint16_t val, bool reload)
+{
+	uint16_t bbpu;
+
+	RTC_Write(RTC_OSC32CON, RTC_OSC32CON_UNLOCK1);
+	rtc_busy_wait();
+	RTC_Write(RTC_OSC32CON, RTC_OSC32CON_UNLOCK2);
+	rtc_busy_wait();
+
+	RTC_Write(RTC_OSC32CON, val);
+	rtc_busy_wait();
+
+	if (reload) {
+		bbpu = RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD;
+		RTC_Write(RTC_BBPU, bbpu);
+		RTC_Write_Trigger();
+	}
+}
+
+static void rtc_enable_k_eosc(void)
+{
+	uint16_t osc32;
+	uint16_t rtc_eosc_cali_td = 8; /* eosc cali period time */
+
+	/* Truning on eosc cali mode clock */
+	RTC_Config_Interface(PMIC_RG_TOP_CON, 1,
+			PMIC_RG_SRCLKEN_IN0_HW_MODE_MASK,
+			PMIC_RG_SRCLKEN_IN0_HW_MODE_SHIFT);
+	RTC_Config_Interface(PMIC_RG_TOP_CON, 1,
+			PMIC_RG_SRCLKEN_IN1_HW_MODE_MASK,
+			PMIC_RG_SRCLKEN_IN1_HW_MODE_SHIFT);
+	RTC_Config_Interface(PMIC_RG_SCK_TOP_CKPDN_CON0, 0,
+			PMIC_RG_RTC_EOSC32_CK_PDN_MASK,
+			PMIC_RG_RTC_EOSC32_CK_PDN_SHIFT);
+
+	switch (rtc_eosc_cali_td) {
+	case 1:
+		RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x3,
+			PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT);
+		break;
+	case 2:
+		RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x4,
+			PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT);
+		break;
+	case 4:
+		RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x5,
+			PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT);
+		break;
+	case 16:
+		RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x7,
+			PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT);
+		break;
+	default:
+		RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x6,
+			PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT);
+		break;
+	}
+	/* Switch the DCXO from 32k-less mode to RTC mode,
+	 * otherwise, EOSC cali will fail
+	 */
+	/* RTC mode will have only OFF mode and FPM */
+	RTC_Config_Interface(PMIC_RG_DCXO_CW02, 0, PMIC_RG_XO_EN32K_MAN_MASK,
+		PMIC_RG_XO_EN32K_MAN_SHIFT);
+	RTC_Write(RTC_BBPU,
+		  RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD);
+	RTC_Write_Trigger();
+	/* Enable K EOSC mode for normal power off and then plug out battery */
+	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);
+	RTC_Write_Trigger();
+
+	osc32 = RTC_Read(RTC_OSC32CON);
+	rtc_xosc_write(osc32 | RTC_EMBCK_SRC_SEL, true);
+	INFO("[RTC] RTC_enable_k_eosc\n");
+}
+
+void rtc_power_off_sequence(void)
+{
+	uint16_t bbpu;
+
+	rtc_disable_2sec_reboot();
+	rtc_enable_k_eosc();
+
+	/* clear alarm */
+	bbpu = RTC_BBPU_KEY | RTC_BBPU_CLR | RTC_BBPU_PWREN;
+	if (Writeif_unlock()) {
+		RTC_Write(RTC_BBPU, bbpu);
+
+		RTC_Write(RTC_AL_MASK, RTC_AL_MASK_DOW);
+		RTC_Write_Trigger();
+		mdelay(1);
+
+		bbpu = RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD;
+		RTC_Write(RTC_BBPU, bbpu);
+		RTC_Write_Trigger();
+		INFO("[RTC] BBPU=0x%x, IRQ_EN=0x%x, AL_MSK=0x%x, AL_SEC=0x%x\n",
+		     RTC_Read(RTC_BBPU), RTC_Read(RTC_IRQ_EN),
+		     RTC_Read(RTC_AL_MASK), RTC_Read(RTC_AL_SEC));
+	}
+}
diff --git a/plat/mediatek/mt8186/drivers/rtc/rtc.h b/plat/mediatek/mt8186/drivers/rtc/rtc.h
new file mode 100644
index 0000000..b48dbb9
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/rtc/rtc.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RTC_H
+#define RTC_H
+
+#define PMIC_RG_SRCLKEN_IN0_HW_MODE_MASK	(1U)
+#define PMIC_RG_SRCLKEN_IN0_HW_MODE_SHIFT	(1U)
+#define PMIC_RG_SRCLKEN_IN1_HW_MODE_MASK	(1U)
+#define PMIC_RG_SRCLKEN_IN1_HW_MODE_SHIFT	(3U)
+#define PMIC_RG_RTC_EOSC32_CK_PDN_MASK		(1U)
+#define PMIC_RG_RTC_EOSC32_CK_PDN_SHIFT		(2U)
+#define PMIC_RG_EOSC_CALI_TD_MASK		(7U)
+#define PMIC_RG_EOSC_CALI_TD_SHIFT		(5U)
+#define PMIC_RG_XO_EN32K_MAN_MASK		(1U)
+#define PMIC_RG_XO_EN32K_MAN_SHIFT		(0U)
+
+/* 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_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_PROT_UNLOCK1 = 0x586A,
+	RTC_PROT_UNLOCK2 = 0x9136
+};
+
+enum {
+	RTC_BBPU_PWREN	= 1U << 0,
+	RTC_BBPU_CLR	= 1U << 1,
+	RTC_BBPU_INIT	= 1U << 2,
+	RTC_BBPU_AUTO	= 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
+};
+
+/* PMIC TOP Register Definition */
+enum {
+	PMIC_RG_TOP_CON = 0x001E,
+	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 = 0x051A,
+	PMIC_RG_SCK_TOP_CKPDN_CON0_SET = 0x051C,
+	PMIC_RG_SCK_TOP_CKPDN_CON0_CLR = 0x051E,
+	PMIC_RG_EOSC_CALI_CON0 = 0x540
+};
+
+/* PMIC DCXO Register Definition */
+enum {
+	PMIC_RG_DCXO_CW00 = 0x0788,
+	PMIC_RG_DCXO_CW02 = 0x0790
+};
+
+/* 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/mt8186/drivers/spmc/mtspmc.c b/plat/mediatek/mt8186/drivers/spmc/mtspmc.c
new file mode 100644
index 0000000..91ef096
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/spmc/mtspmc.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2021, 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>
+#include <plat/common/platform.h>
+
+void mcucfg_disable_gic_wakeup(unsigned int cluster, unsigned int cpu)
+{
+	mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(cpu));
+}
+
+void mcucfg_enable_gic_wakeup(unsigned int cluster, unsigned int cpu)
+{
+	mmio_clrbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(cpu));
+	/* Clear cpu's cpc sw hint */
+	mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_CLR, BIT(cpu));
+}
+
+void mcucfg_set_bootaddr(unsigned int cluster, unsigned int cpu, uintptr_t bootaddr)
+{
+	assert(cluster == 0U);
+
+	mmio_write_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR), bootaddr);
+}
+
+uintptr_t mcucfg_get_bootaddr(unsigned int cluster, unsigned int cpu)
+{
+	assert(cluster == 0U);
+
+	return (uintptr_t)mmio_read_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR));
+}
+
+void mcucfg_init_archstate(unsigned int cluster, unsigned int cpu, bool arm64)
+{
+	uint32_t reg;
+
+	assert(cluster == 0U);
+
+	reg = per_cluster(cluster, MCUCFG_INITARCH);
+
+	if (arm64) {
+		mmio_setbits_32(reg, MCUCFG_INITARCH_CPU_BIT(cpu));
+	} else {
+		mmio_clrbits_32(reg, MCUCFG_INITARCH_CPU_BIT(cpu));
+	}
+}
+
+/*
+ * Return subsystem's power state.
+ *
+ * @mask: mask to 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);
+}
+
+bool spm_get_cluster_powerstate(unsigned int cluster)
+{
+	assert(cluster == 0U);
+
+	return spm_get_powerstate(MP0_CPUTOP);
+}
+
+bool spm_get_cpu_powerstate(unsigned int cluster, unsigned int cpu)
+{
+	uint32_t mask = BIT(cpu);
+
+	assert(cluster == 0U);
+
+	return spm_get_powerstate(mask);
+}
+
+int spmc_init(void)
+{
+	unsigned int cpu = plat_my_core_pos();
+
+
+	INFO("SPM: enable CPC mode\n");
+
+	mmio_write_32(SPM_POWERON_CONFIG_EN, PROJECT_CODE | BCLK_CG_EN);
+
+	mmio_setbits_32(per_cpu(0, 1, SPM_CPU_PWR), PWR_RST_B);
+	mmio_setbits_32(per_cpu(0, 2, SPM_CPU_PWR), PWR_RST_B);
+	mmio_setbits_32(per_cpu(0, 3, SPM_CPU_PWR), PWR_RST_B);
+	mmio_setbits_32(per_cpu(0, 4, SPM_CPU_PWR), PWR_RST_B);
+	mmio_setbits_32(per_cpu(0, 5, SPM_CPU_PWR), PWR_RST_B);
+	mmio_setbits_32(per_cpu(0, 6, SPM_CPU_PWR), PWR_RST_B);
+	mmio_setbits_32(per_cpu(0, 7, SPM_CPU_PWR), PWR_RST_B);
+
+	mmio_clrbits_32(SPM_MCUSYS_PWR_CON, RESETPWRON_CONFIG);
+	mmio_clrbits_32(SPM_MP0_CPUTOP_PWR_CON, RESETPWRON_CONFIG);
+	mmio_clrbits_32(per_cpu(0, 0, SPM_CPU_PWR), RESETPWRON_CONFIG);
+
+	mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, CPC_CTRL_ENABLE);
+
+	/* Clear bootup cpu's cpc sw hint */
+	mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_CLR, BIT(cpu));
+
+	return 0;
+}
+
+/*
+ * Power on a core with specified cluster and core index
+ *
+ * @cluster: the cluster ID of the CPU which to be powered on
+ * @cpu: the CPU ID of the CPU which to be powered on
+ */
+void spm_poweron_cpu(unsigned int cluster, unsigned int cpu)
+{
+	/* info CPC that CPU hotplug on */
+	mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, SSPM_ALL_PWR_CTRL_EN);
+
+	/* Set mp0_spmc_pwr_on_cpuX = 1 */
+	mmio_setbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWR_ON);
+
+	/* wait for power on ack */
+	while (!spm_get_cpu_powerstate(cluster, cpu))
+		;
+
+	/* info CPC that CPU hotplug off */
+	mmio_clrbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, SSPM_ALL_PWR_CTRL_EN);
+}
+
+/*
+ * Power off a core with specified cluster and core index
+ *
+ * @cluster: the cluster ID of the CPU which to be powered off
+ * @cpu: the CPU ID of the CPU which to be powered off
+ */
+void spm_poweroff_cpu(unsigned int cluster, unsigned int cpu)
+{
+	/* Set mp0_spmc_pwr_on_cpuX = 0 */
+	mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWR_ON);
+}
+
+/*
+ * Power off a cluster with specified index
+ *
+ * @cluster: the cluster index which to be powered off
+ */
+void spm_poweroff_cluster(unsigned int cluster)
+{
+	/* No need to power on/off cluster on single cluster platform */
+	assert(false);
+}
+
+/*
+ * Power on a cluster with specified index
+ *
+ * @cluster: the cluster index which to be powered on
+ */
+void spm_poweron_cluster(unsigned int cluster)
+{
+	/* No need to power on/off cluster on single cluster platform */
+	assert(false);
+}
diff --git a/plat/mediatek/mt8186/drivers/spmc/mtspmc.h b/plat/mediatek/mt8186/drivers/spmc/mtspmc.h
new file mode 100644
index 0000000..768599b
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/spmc/mtspmc.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTSPMC_H
+#define MTSPMC_H
+
+#include <stdint.h>
+
+int spmc_init(void);
+
+void spm_poweron_cpu(unsigned int cluster, unsigned int cpu);
+void spm_poweroff_cpu(unsigned int cluster, unsigned int cpu);
+
+void spm_poweroff_cluster(unsigned int cluster);
+void spm_poweron_cluster(unsigned int cluster);
+
+bool spm_get_cpu_powerstate(unsigned int cluster, unsigned int cpu);
+bool spm_get_cluster_powerstate(unsigned int cluster);
+bool spm_get_powerstate(uint32_t mask);
+
+void mcucfg_init_archstate(unsigned int cluster, unsigned int cpu, bool arm64);
+void mcucfg_set_bootaddr(unsigned int cluster, unsigned int cpu, uintptr_t bootaddr);
+uintptr_t mcucfg_get_bootaddr(unsigned int cluster, unsigned int cpu);
+
+void mcucfg_disable_gic_wakeup(unsigned int cluster, unsigned int cpu);
+void mcucfg_enable_gic_wakeup(unsigned int cluster, unsigned int cpu);
+
+#endif /* MTSPMC_H */
diff --git a/plat/mediatek/mt8186/drivers/spmc/mtspmc_private.h b/plat/mediatek/mt8186/drivers/spmc/mtspmc_private.h
new file mode 100644
index 0000000..472b54c
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/spmc/mtspmc_private.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2021, 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		SPM_REG(0x200)
+#define SPM_MP0_CPUTOP_PWR_CON		SPM_REG(0x204)
+#define SPM_MP0_CPU0_PWR_CON		SPM_REG(0x208)
+#define SPM_MP0_CPU1_PWR_CON		SPM_REG(0x20c)
+#define SPM_MP0_CPU2_PWR_CON		SPM_REG(0x210)
+#define SPM_MP0_CPU3_PWR_CON		SPM_REG(0x214)
+#define SPM_MP0_CPU4_PWR_CON		SPM_REG(0x218)
+#define SPM_MP0_CPU5_PWR_CON		SPM_REG(0x21c)
+#define SPM_MP0_CPU6_PWR_CON		SPM_REG(0x220)
+#define SPM_MP0_CPU7_PWR_CON		SPM_REG(0x224)
+
+/* 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 */
+#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)
+
+/* per_cpu registers for MCUCFG_MP0_CLUSTER_CFG */
+static const struct per_cpu_reg MCUCFG_BOOTADDR[] = {
+	{ .cluster_addr = MCUCFG_MP0_CLUSTER_CFG8, .cpu_stride = 3U }
+};
+
+/* per_cpu registers for MCUCFG_MP0_CLUSTER_CFG5 */
+static const struct per_cpu_reg MCUCFG_INITARCH[] = {
+	{ .cluster_addr = MCUCFG_MP0_CLUSTER_CFG5, .cpu_stride = 0U }
+};
+
+#define MCUCFG_INITARCH_CPU_BIT(cpu)	BIT(16U + cpu)
+/* CPC control */
+#define MCUCFG_CPC_FLOW_CTRL_CFG	MCUCFG_REG(0xa814)
+#define MCUCFG_CPC_SPMC_PWR_STATUS	MCUCFG_REG(0xa840)
+
+/* bit-fields of CPC_FLOW_CTRL_CFG */
+#define CPC_CTRL_ENABLE			BIT(16)
+#define SSPM_ALL_PWR_CTRL_EN		BIT(13) /* for cpu-hotplug */
+#define GIC_WAKEUP_IGNORE(cpu)		BIT(21 + cpu)
+
+/* bit-fields of CPC_SPMC_PWR_STATUS */
+#define CORE_SPMC_PWR_ON_ACK		GENMASK(11, 0)
+
+/* APB module infracfg_ao */
+#define INFRA_TOPAXI_PROTECTEN		INFRACFG_AO_REG(0x0220)
+#define INFRA_TOPAXI_PROTECTEN_STA0	INFRACFG_AO_REG(0x0224)
+#define INFRA_TOPAXI_PROTECTEN_STA1	INFRACFG_AO_REG(0x0228)
+#define INFRA_TOPAXI_PROTECTEN_SET	INFRACFG_AO_REG(0x02a0)
+#define INFRA_TOPAXI_PROTECTEN_CLR	INFRACFG_AO_REG(0x02a4)
+#define INFRA_TOPAXI_PROTECTEN_1	INFRACFG_AO_REG(0x0250)
+#define INFRA_TOPAXI_PROTECTEN_STA0_1	INFRACFG_AO_REG(0x0254)
+#define INFRA_TOPAXI_PROTECTEN_STA1_1	INFRACFG_AO_REG(0x0258)
+#define INFRA_TOPAXI_PROTECTEN_1_SET	INFRACFG_AO_REG(0x02a8)
+#define INFRA_TOPAXI_PROTECTEN_1_CLR	INFRACFG_AO_REG(0x02ac)
+
+/* bit-fields of INFRA_TOPAXI_PROTECTEN */
+#define MP0_SPMC_PROT_STEP1_0_MASK	BIT(12)
+#define MP0_SPMC_PROT_STEP1_1_MASK	(BIT(26) | BIT(12))
+
+/* SPARK */
+#define VOLTAGE_04			U(0x40)
+#define VOLTAGE_05			U(0x60)
+
+#define PTP3_CPU0_SPMC_SW_CFG		MCUCFG_REG(0x200)
+#define CPU0_ILDO_CONTROL5		MCUCFG_REG(0x334)
+#define CPU0_ILDO_CONTROL8		MCUCFG_REG(0x340)
+
+/* bit-fields of CPU0_ILDO_CONTROL5 */
+#define ILDO_RET_VOSEL			GENMASK(7, 0)
+
+/* bit-fields of PTP3_CPU_SPMC_SW_CFG */
+#define SW_SPARK_EN			BIT(0)
+
+/* bit-fields of CPU0_ILDO_CONTROL8 */
+#define ILDO_BYPASS_B			BIT(0)
+
+static const struct per_cpu_reg MCUCFG_SPARK[] = {
+	{ .cluster_addr = PTP3_CPU0_SPMC_SW_CFG, .cpu_stride = 11U }
+};
+
+static const struct per_cpu_reg ILDO_CONTROL5[] = {
+	{ .cluster_addr = CPU0_ILDO_CONTROL5, .cpu_stride = 11U }
+};
+
+static const struct per_cpu_reg ILDO_CONTROL8[] = {
+	{ .cluster_addr = CPU0_ILDO_CONTROL8, .cpu_stride = 11U }
+};
+
+#endif /* MTSPMC_PRIVATE_H */
diff --git a/plat/mediatek/mt8186/include/mcucfg.h b/plat/mediatek/mt8186/include/mcucfg.h
new file mode 100644
index 0000000..78a01a8
--- /dev/null
+++ b/plat/mediatek/mt8186/include/mcucfg.h
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2021, 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/mt8186/include/plat_helpers.h b/plat/mediatek/mt8186/include/plat_helpers.h
new file mode 100644
index 0000000..ebc9fa0
--- /dev/null
+++ b/plat/mediatek/mt8186/include/plat_helpers.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLAT_HELPERS_H__
+#define __PLAT_HELPERS_H__
+
+unsigned int plat_mediatek_calc_core_pos(u_register_t mpidr);
+
+#endif /* __PLAT_HELPERS_H__ */
diff --git a/plat/mediatek/mt8186/include/plat_macros.S b/plat/mediatek/mt8186/include/plat_macros.S
new file mode 100644
index 0000000..39727ea
--- /dev/null
+++ b/plat/mediatek/mt8186/include/plat_macros.S
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+#include <platform_def.h>
+
+.section .rodata.gic_reg_name, "aS"
+gicc_regs:
+	.asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", ""
+gicd_pend_reg:
+	.asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n"	\
+		" Offset:\t\t\tvalue\n"
+newline:
+	.asciz "\n"
+spacer:
+	.asciz ":\t\t0x"
+
+.section .rodata.cci_reg_name, "aS"
+cci_iface_regs:
+	.asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , ""
+
+	/* ---------------------------------------------
+	 * The below macro prints out relevant GIC
+	 * registers whenever an unhandled exception
+	 * is taken in BL31.
+	 * Clobbers: x0 - x10, x26, x27, sp
+	 * ---------------------------------------------
+	 */
+	.macro plat_crash_print_regs
+	/* TODO: leave implementation to GIC owner */
+	.endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/mediatek/mt8186/include/plat_mtk_lpm.h b/plat/mediatek/mt8186/include/plat_mtk_lpm.h
new file mode 100644
index 0000000..347f358
--- /dev/null
+++ b/plat/mediatek/mt8186/include/plat_mtk_lpm.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2021, 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(32)
+#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/mt8186/include/plat_pm.h b/plat/mediatek/mt8186/include/plat_pm.h
new file mode 100644
index 0000000..436db34
--- /dev/null
+++ b/plat/mediatek/mt8186/include/plat_pm.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2021, 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/mt8186/include/plat_private.h b/plat/mediatek/mt8186/include/plat_private.h
new file mode 100644
index 0000000..7ef2b85
--- /dev/null
+++ b/plat/mediatek/mt8186/include/plat_private.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_PRIVATE_H
+#define PLAT_PRIVATE_H
+
+/*******************************************************************************
+ * Function and variable prototypes
+ ******************************************************************************/
+void plat_configure_mmu_el3(uintptr_t total_base,
+			    uintptr_t total_size,
+			    uintptr_t ro_start,
+			    uintptr_t ro_limit);
+
+#endif /* PLAT_PRIVATE_H */
diff --git a/plat/mediatek/mt8186/include/plat_sip_calls.h b/plat/mediatek/mt8186/include/plat_sip_calls.h
new file mode 100644
index 0000000..598a5b8
--- /dev/null
+++ b/plat/mediatek/mt8186/include/plat_sip_calls.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2021, 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/mt8186/include/platform_def.h b/plat/mediatek/mt8186/include/platform_def.h
new file mode 100644
index 0000000..479a8d4
--- /dev/null
+++ b/plat/mediatek/mt8186/include/platform_def.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#define PLAT_PRIMARY_CPU	0x0
+
+#define MT_GIC_BASE		(0x0C000000)
+#define MCUCFG_BASE		(0x0C530000)
+#define IO_PHYS			(0x10000000)
+
+/* Aggregate of all devices for MMU mapping */
+#define MTK_DEV_RNG0_BASE	IO_PHYS
+#define MTK_DEV_RNG0_SIZE	0x10000000
+#define MTK_DEV_RNG2_BASE	MT_GIC_BASE
+#define MTK_DEV_RNG2_SIZE	0x600000
+
+#define SPM_BASE		(IO_PHYS + 0x00006000)
+
+/*******************************************************************************
+ * GPIO related constants
+ ******************************************************************************/
+#define GPIO_BASE		(IO_PHYS + 0x00005000)
+#define IOCFG_LT_BASE		(IO_PHYS + 0x00002000)
+#define IOCFG_LM_BASE		(IO_PHYS + 0x00002200)
+#define IOCFG_LB_BASE		(IO_PHYS + 0x00002400)
+#define IOCFG_BL_BASE		(IO_PHYS + 0x00002600)
+#define IOCFG_RB_BASE		(IO_PHYS + 0x00002A00)
+#define IOCFG_RT_BASE		(IO_PHYS + 0x00002C00)
+
+/*******************************************************************************
+ * UART related constants
+ ******************************************************************************/
+#define UART0_BASE			(IO_PHYS + 0x01002000)
+
+#define UART_BAUDRATE			115200
+
+/*******************************************************************************
+ * PWRAP related constants
+ ******************************************************************************/
+#define PMIC_WRAP_BASE			(IO_PHYS + 0x0000D000)
+
+/*******************************************************************************
+ * EMI MPU related constants
+ ******************************************************************************/
+#define EMI_MPU_BASE		(IO_PHYS + 0x0021B000)
+
+/*******************************************************************************
+ * GIC-600 & interrupt handling related constants
+ ******************************************************************************/
+/* Base MTK_platform compatible GIC memory map */
+#define BASE_GICD_BASE			MT_GIC_BASE
+#define MT_GIC_RDIST_BASE		(MT_GIC_BASE + 0x40000)
+
+#define SYS_CIRQ_BASE			(IO_PHYS + 0x204000)
+#define CIRQ_REG_NUM			11
+#define CIRQ_IRQ_NUM			326
+#define CIRQ_SPI_START			64
+#define MD_WDT_IRQ_BIT_ID		107
+/*******************************************************************************
+ * System counter frequency related constants
+ ******************************************************************************/
+#define SYS_COUNTER_FREQ_IN_TICKS	13000000
+#define SYS_COUNTER_FREQ_IN_MHZ		13
+
+/*******************************************************************************
+ * Platform binary types for linking
+ ******************************************************************************/
+#define PLATFORM_LINKER_FORMAT		"elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH		aarch64
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+#define PLATFORM_STACK_SIZE		0x800
+
+#define FIRMWARE_WELCOME_STR		"Booting Trusted Firmware\n"
+
+#define PLAT_MAX_PWR_LVL		U(3)
+#define PLAT_MAX_RET_STATE		U(1)
+#define PLAT_MAX_OFF_STATE		U(9)
+
+#define PLATFORM_SYSTEM_COUNT		U(1)
+#define PLATFORM_MCUSYS_COUNT		U(1)
+#define PLATFORM_CLUSTER_COUNT		U(1)
+#define PLATFORM_CLUSTER0_CORE_COUNT	U(8)
+#define PLATFORM_CLUSTER1_CORE_COUNT	U(0)
+
+#define PLATFORM_CORE_COUNT		(PLATFORM_CLUSTER0_CORE_COUNT)
+#define PLATFORM_MAX_CPUS_PER_CLUSTER	U(8)
+
+#define SOC_CHIP_ID			U(0x8186)
+
+/*******************************************************************************
+ * Platform memory map related constants
+ ******************************************************************************/
+#define TZRAM_BASE			0x54600000
+#define TZRAM_SIZE			0x00030000
+
+/*******************************************************************************
+ * BL31 specific defines.
+ ******************************************************************************/
+/*
+ * Put BL3-1 at the top of the Trusted SRAM (just below the shared memory, if
+ * present). BL31_BASE is calculated using the current BL3-1 debug size plus a
+ * little space for growth.
+ */
+#define BL31_BASE			(TZRAM_BASE + 0x1000)
+#define BL31_LIMIT			(TZRAM_BASE + TZRAM_SIZE)
+
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+#define PLAT_PHY_ADDR_SPACE_SIZE	(1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 32)
+#define MAX_XLAT_TABLES			16
+#define MAX_MMAP_REGIONS		16
+
+/*******************************************************************************
+ * Declarations and constants to access the mailboxes safely. Each mailbox is
+ * aligned on the biggest cache line size in the platform. This is known only
+ * to the platform as it might have a combination of integrated and external
+ * caches. Such alignment ensures that two maiboxes do not sit on the same cache
+ * line at any cache level. They could belong to different cpus/clusters &
+ * get written while being protected by different locks causing corruption of
+ * a valid mailbox address.
+ ******************************************************************************/
+#define CACHE_WRITEBACK_SHIFT		6
+#define CACHE_WRITEBACK_GRANULE		(1 << CACHE_WRITEBACK_SHIFT)
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/mediatek/mt8186/plat_pm.c b/plat/mediatek/mt8186/plat_pm.c
new file mode 100644
index 0000000..e8d834d
--- /dev/null
+++ b/plat/mediatek/mt8186/plat_pm.c
@@ -0,0 +1,400 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* common headers */
+#include <assert.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/gpio.h>
+#include <lib/psci/psci.h>
+
+/* platform specific headers */
+#include <mt_gic_v3.h>
+#include <mtspmc.h>
+#include <plat/common/platform.h>
+#include <plat_mtk_lpm.h>
+#include <plat_params.h>
+#include <plat_pm.h>
+#include <pmic.h>
+#include <rtc.h>
+
+/*
+ * Cluster state request:
+ * [0] : The CPU requires cluster power down
+ * [1] : The CPU requires cluster power on
+ */
+#define coordinate_cluster(onoff)	write_clusterpwrdn_el1(onoff)
+#define coordinate_cluster_pwron()	coordinate_cluster(1)
+#define coordinate_cluster_pwroff()	coordinate_cluster(0)
+
+/* platform secure entry point */
+static uintptr_t secure_entrypoint;
+/* per-CPU power state */
+static unsigned int plat_power_state[PLATFORM_CORE_COUNT];
+
+/* platform CPU power domain - ops */
+static const struct mt_lpm_tz *plat_mt_pm;
+
+static inline int plat_mt_pm_invoke(int (*func)(unsigned int cpu,
+						const psci_power_state_t *state),
+				    int cpu, const psci_power_state_t *state)
+{
+	int ret = -1;
+
+	if (func != NULL) {
+		ret = func(cpu, state);
+	}
+	return ret;
+}
+
+/*
+ * 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());
+	assert(plat_mt_pm != NULL);
+
+	(void)plat_mt_pm_invoke(plat_mt_pm->pwr_cpu_dwn, cpu, state);
+
+	if ((psci_get_pstate_pwrlvl(req_pstate) >= MTK_AFFLVL_CLUSTER) ||
+			(req_pstate == 0U)) { /* hotplug off */
+		coordinate_cluster_pwroff();
+	}
+
+	/* Prevent interrupts from spuriously waking up this CPU */
+	mt_gic_rdistif_save();
+	gicv3_cpuif_disable(cpu);
+	gicv3_rdistif_off(cpu);
+}
+
+static void plat_cpu_pwron_common(unsigned int cpu,
+		const psci_power_state_t *state, unsigned int req_pstate)
+{
+	assert(cpu == plat_my_core_pos());
+	assert(plat_mt_pm != NULL);
+
+	(void)plat_mt_pm_invoke(plat_mt_pm->pwr_cpu_on, cpu, state);
+
+	coordinate_cluster_pwron();
+
+	/*
+	 * If mcusys does power down before then restore
+	 * all CPUs' GIC Redistributors
+	 */
+	if (IS_MCUSYS_OFF_STATE(state)) {
+		mt_gic_rdistif_restore_all();
+	} else {
+		gicv3_rdistif_on(cpu);
+		gicv3_cpuif_enable(cpu);
+		mt_gic_rdistif_init();
+		mt_gic_rdistif_restore();
+	}
+}
+
+/*
+ * Common MTK_platform operations to power on/off a
+ * cluster in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request.
+ */
+static void plat_cluster_pwrdwn_common(unsigned int cpu,
+		const psci_power_state_t *state, unsigned int req_pstate)
+{
+	assert(cpu == plat_my_core_pos());
+	assert(plat_mt_pm != NULL);
+
+	if (plat_mt_pm_invoke(plat_mt_pm->pwr_cluster_dwn, cpu, state) != 0) {
+		coordinate_cluster_pwron();
+
+		/*
+		 * TODO:
+		 * Return on fail and 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());
+	assert(plat_mt_pm != NULL);
+
+	if (plat_mt_pm_invoke(plat_mt_pm->pwr_cluster_on, cpu, state) != 0) {
+		/*
+		 * TODO:
+		 * return on fail and 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());
+	assert(plat_mt_pm != NULL);
+
+	if (plat_mt_pm_invoke(plat_mt_pm->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());
+	assert(plat_mt_pm != NULL);
+
+	if (plat_mt_pm_invoke(plat_mt_pm->pwr_mcusys_on, cpu, state) != 0) {
+		/* return on fail */
+		return;
+	}
+
+	mt_gic_init();
+	mt_gic_distif_restore();
+	gic_sgi_restore_all();
+
+	(void)plat_mt_pm_invoke(plat_mt_pm->pwr_mcusys_on_finished, cpu, state);
+}
+
+/* plat_psci_ops implementation */
+static void plat_cpu_standby(plat_local_state_t cpu_state)
+{
+	uint64_t scr;
+
+	scr = read_scr_el3();
+	write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT);
+
+	isb();
+	dsb();
+	wfi();
+
+	write_scr_el3(scr);
+}
+
+static int plat_power_domain_on(u_register_t mpidr)
+{
+	unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr);
+	unsigned int cluster = 0U;
+
+	if (cpu >= PLATFORM_CORE_COUNT) {
+		return PSCI_E_INVALID_PARAMS;
+	}
+
+	if (!spm_get_cluster_powerstate(cluster)) {
+		spm_poweron_cluster(cluster);
+	}
+
+	/* init CPU reset arch as AARCH64 */
+	mcucfg_init_archstate(cluster, cpu, true);
+	mcucfg_set_bootaddr(cluster, cpu, secure_entrypoint);
+	spm_poweron_cpu(cluster, cpu);
+
+	return PSCI_E_SUCCESS;
+}
+
+static void plat_power_domain_on_finish(const psci_power_state_t *state)
+{
+	unsigned long mpidr = read_mpidr_el1();
+	unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr);
+
+	assert(cpu < PLATFORM_CORE_COUNT);
+
+	/* Allow IRQs to wakeup this core in IDLE flow */
+	mcucfg_enable_gic_wakeup(0U, cpu);
+
+	if (IS_CLUSTER_OFF_STATE(state)) {
+		plat_cluster_pwron_common(cpu, state, 0U);
+	}
+
+	plat_cpu_pwron_common(cpu, state, 0U);
+}
+
+static void plat_power_domain_off(const psci_power_state_t *state)
+{
+	unsigned long mpidr = read_mpidr_el1();
+	unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr);
+
+	assert(cpu < PLATFORM_CORE_COUNT);
+
+	plat_cpu_pwrdwn_common(cpu, state, 0U);
+	spm_poweroff_cpu(0U, cpu);
+
+	/* prevent unintended IRQs from waking up the hot-unplugged core */
+	mcucfg_disable_gic_wakeup(0U, cpu);
+
+	if (IS_CLUSTER_OFF_STATE(state)) {
+		plat_cluster_pwrdwn_common(cpu, state, 0U);
+	}
+}
+
+static void plat_power_domain_suspend(const psci_power_state_t *state)
+{
+	unsigned int cpu = plat_my_core_pos();
+
+	assert(cpu < PLATFORM_CORE_COUNT);
+	assert(plat_mt_pm != NULL);
+
+	(void)plat_mt_pm_invoke(plat_mt_pm->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);
+	assert(plat_mt_pm != NULL);
+
+	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]);
+
+	(void)plat_mt_pm_invoke(plat_mt_pm->pwr_reflect, cpu, state);
+}
+
+static int plat_validate_power_state(unsigned int power_state,
+					psci_power_state_t *req_state)
+{
+	unsigned int pstate = psci_get_pstate_type(power_state);
+	unsigned int aff_lvl = psci_get_pstate_pwrlvl(power_state);
+	unsigned int cpu = plat_my_core_pos();
+
+	if (aff_lvl > PLAT_MAX_PWR_LVL) {
+		return PSCI_E_INVALID_PARAMS;
+	}
+
+	if (pstate == PSTATE_TYPE_STANDBY) {
+		req_state->pwr_domain_state[0] = PLAT_MAX_RET_STATE;
+	} else {
+		unsigned int i;
+		unsigned int pstate_id = psci_get_pstate_id(power_state);
+		plat_local_state_t s = MTK_LOCAL_STATE_OFF;
+
+		/* Use pstate_id to be power domain state */
+		if (pstate_id > s) {
+			s = (plat_local_state_t)pstate_id;
+		}
+
+		for (i = 0U; i <= aff_lvl; i++) {
+			req_state->pwr_domain_state[i] = s;
+		}
+	}
+
+	plat_power_state[cpu] = power_state;
+	return PSCI_E_SUCCESS;
+}
+
+static void plat_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+	unsigned int lv;
+	unsigned int cpu = plat_my_core_pos();
+
+	for (lv = PSCI_CPU_PWR_LVL; lv <= PLAT_MAX_PWR_LVL; lv++) {
+		req_state->pwr_domain_state[lv] = PLAT_MAX_OFF_STATE;
+	}
+
+	plat_power_state[cpu] =
+			psci_make_powerstate(
+				MT_PLAT_PWR_STATE_SYSTEM_SUSPEND,
+				PSTATE_TYPE_POWERDOWN, PLAT_MAX_PWR_LVL);
+
+	flush_dcache_range((uintptr_t)
+			&plat_power_state[cpu],
+			sizeof(plat_power_state[cpu]));
+}
+
+/*******************************************************************************
+ * MTK handlers to shutdown/reboot the system
+ ******************************************************************************/
+static void __dead2 plat_mtk_system_reset(void)
+{
+	struct bl_aux_gpio_info *gpio_reset = plat_get_mtk_gpio_reset();
+
+	INFO("MTK System Reset\n");
+
+	gpio_set_value(gpio_reset->index, gpio_reset->polarity);
+
+	wfi();
+	ERROR("MTK System Reset: operation not handled.\n");
+	panic();
+}
+
+static void __dead2 plat_mtk_system_off(void)
+{
+	INFO("MTK System Off\n");
+
+	rtc_power_off_sequence();
+	pmic_power_off();
+
+	wfi();
+	ERROR("MTK System Off: operation not handled.\n");
+	panic();
+}
+
+static const plat_psci_ops_t plat_psci_ops = {
+	.cpu_standby			= plat_cpu_standby,
+	.pwr_domain_on			= plat_power_domain_on,
+	.pwr_domain_on_finish		= plat_power_domain_on_finish,
+	.pwr_domain_off			= plat_power_domain_off,
+	.pwr_domain_suspend		= plat_power_domain_suspend,
+	.pwr_domain_suspend_finish	= plat_power_domain_suspend_finish,
+	.validate_power_state		= plat_validate_power_state,
+	.get_sys_suspend_power_state	= plat_get_sys_suspend_power_state,
+	.system_off			= plat_mtk_system_off,
+	.system_reset			= plat_mtk_system_reset,
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+			const plat_psci_ops_t **psci_ops)
+{
+	*psci_ops = &plat_psci_ops;
+	secure_entrypoint = sec_entrypoint;
+
+	/*
+	 * init the warm reset config for boot CPU
+	 * reset arch as AARCH64
+	 * reset addr as function bl31_warm_entrypoint()
+	 */
+	mcucfg_init_archstate(0U, 0U, true);
+	mcucfg_set_bootaddr(0U, 0U, secure_entrypoint);
+
+	spmc_init();
+	plat_mt_pm = mt_plat_cpu_pm_init();
+
+	return 0;
+}
diff --git a/plat/mediatek/mt8186/plat_sip_calls.c b/plat/mediatek/mt8186/plat_sip_calls.c
new file mode 100644
index 0000000..716f3d9
--- /dev/null
+++ b/plat/mediatek/mt8186/plat_sip_calls.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2021, 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/mt8186/plat_topology.c b/plat/mediatek/mt8186/plat_topology.c
new file mode 100644
index 0000000..bc95c64
--- /dev/null
+++ b/plat/mediatek/mt8186/plat_topology.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <lib/psci/psci.h>
+
+#include <plat_helpers.h>
+#include <platform_def.h>
+
+const unsigned char mtk_power_domain_tree_desc[] = {
+	/* Number of root nodes */
+	PLATFORM_SYSTEM_COUNT,
+	/* Number of children for the root node */
+	PLATFORM_MCUSYS_COUNT,
+	/* Number of children for the mcusys node */
+	PLATFORM_CLUSTER_COUNT,
+	/* Number of children for the first cluster node */
+	PLATFORM_CLUSTER0_CORE_COUNT,
+};
+
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+	return mtk_power_domain_tree_desc;
+}
+
+/*******************************************************************************
+ * This function implements a part of the critical interface between the psci
+ * generic layer and the platform that allows the former to query the platform
+ * to convert an MPIDR to a unique linear index. An error code (-1) is returned
+ * in case the MPIDR is invalid.
+ ******************************************************************************/
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+	unsigned int cluster_id, cpu_id;
+
+	if ((read_mpidr() & MPIDR_MT_MASK) != 0) {
+		/* ARMv8.2 arch */
+		if ((mpidr & (MPIDR_AFFLVL_MASK << MPIDR_AFF0_SHIFT)) != 0) {
+			return -1;
+		}
+		return plat_mediatek_calc_core_pos(mpidr);
+	}
+
+	mpidr &= MPIDR_AFFINITY_MASK;
+
+	if ((mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) != 0) {
+		return -1;
+	}
+
+	cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
+	cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
+
+	if (cluster_id >= PLATFORM_CLUSTER_COUNT) {
+		return -1;
+	}
+
+	/*
+	 * Validate cpu_id by checking whether it represents a CPU in
+	 * one of the two clusters present on the platform.
+	 */
+	if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER) {
+		return -1;
+	}
+
+	return (cpu_id + (cluster_id * 8));
+}
diff --git a/plat/mediatek/mt8186/platform.mk b/plat/mediatek/mt8186/platform.mk
new file mode 100644
index 0000000..79c6834
--- /dev/null
+++ b/plat/mediatek/mt8186/platform.mk
@@ -0,0 +1,93 @@
+#
+# Copyright (c) 2021, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+MTK_PLAT     := plat/mediatek
+MTK_PLAT_SOC := ${MTK_PLAT}/${PLAT}
+
+PLAT_INCLUDES := -I${MTK_PLAT}/common/                            \
+                 -I${MTK_PLAT}/common/drivers/gic600/             \
+                 -I${MTK_PLAT}/common/drivers/gpio/             \
+                 -I${MTK_PLAT}/common/drivers/timer/              \
+                 -I${MTK_PLAT_SOC}/drivers/dcm/                   \
+                 -I${MTK_PLAT_SOC}/drivers/emi_mpu/               \
+                 -I${MTK_PLAT_SOC}/drivers/gpio/               \
+                 -I${MTK_PLAT_SOC}/drivers/mcdi/                  \
+                 -I${MTK_PLAT_SOC}/drivers/pmic/                  \
+                 -I${MTK_PLAT_SOC}/drivers/rtc/                   \
+                 -I${MTK_PLAT_SOC}/drivers/spmc/                  \
+                 -I${MTK_PLAT_SOC}/include/
+
+GICV3_SUPPORT_GIC600        :=      1
+include drivers/arm/gic/v3/gicv3.mk
+include lib/xlat_tables_v2/xlat_tables.mk
+
+PLAT_BL_COMMON_SOURCES := ${GICV3_SOURCES}                              \
+                          ${XLAT_TABLES_LIB_SRCS}                       \
+                          plat/common/aarch64/crash_console_helpers.S   \
+                          plat/common/plat_psci_common.c
+
+
+BL31_SOURCES += common/desc_image_load.c                              \
+                drivers/delay_timer/delay_timer.c                     \
+                drivers/gpio/gpio.c                                   \
+                drivers/delay_timer/generic_delay_timer.c             \
+                drivers/ti/uart/aarch64/16550_console.S               \
+                lib/bl_aux_params/bl_aux_params.c                     \
+                lib/cpus/aarch64/cortex_a55.S                         \
+                lib/cpus/aarch64/cortex_a76.S                         \
+                plat/common/plat_gicv3.c                              \
+                ${MTK_PLAT}/common/drivers/gic600/mt_gic_v3.c         \
+                ${MTK_PLAT}/common/drivers/gpio/mtgpio_common.c       \
+                ${MTK_PLAT}/common/drivers/pmic_wrap/pmic_wrap_init.c \
+                ${MTK_PLAT}/common/drivers/rtc/rtc_common.c           \
+                ${MTK_PLAT}/common/mtk_plat_common.c                  \
+                ${MTK_PLAT}/common/mtk_sip_svc.c                      \
+                ${MTK_PLAT}/common/params_setup.c                     \
+                ${MTK_PLAT}/common/drivers/timer/mt_timer.c           \
+                ${MTK_PLAT}/common/mtk_cirq.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/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/pmic/pmic.c                   \
+                ${MTK_PLAT_SOC}/drivers/rtc/rtc.c                     \
+                ${MTK_PLAT_SOC}/drivers/spmc/mtspmc.c                 \
+                ${MTK_PLAT_SOC}/plat_pm.c                             \
+                ${MTK_PLAT_SOC}/plat_sip_calls.c                      \
+                ${MTK_PLAT_SOC}/plat_topology.c
+
+# Configs for A76 and A55
+HW_ASSISTED_COHERENCY := 1
+USE_COHERENT_MEM := 0
+CTX_INCLUDE_AARCH32_REGS := 0
+ERRATA_A55_1530923 := 1
+ERRATA_A55_1221012 := 1
+
+ERRATA_A76_1257314 := 1
+ERRATA_A76_1262606 := 1
+ERRATA_A76_1262888 := 1
+ERRATA_A76_1275112 := 1
+ERRATA_A76_1286807 := 1
+ERRATA_A76_1791580 := 1
+ERRATA_A76_1165522 := 1
+ERRATA_A76_1868343 := 1
+ERRATA_A76_1946160 := 1
+
+# indicate the reset vector address can be programmed
+PROGRAMMABLE_RESET_ADDRESS := 1
+
+COLD_BOOT_SINGLE_CPU := 1
+
+MACH_MT8186 := 1
+$(eval $(call add_define,MACH_MT8186))
+
+include lib/coreboot/coreboot.mk
diff --git a/plat/mediatek/mt8195/aarch64/platform_common.c b/plat/mediatek/mt8195/aarch64/platform_common.c
index 4792746..2b95171 100644
--- a/plat/mediatek/mt8195/aarch64/platform_common.c
+++ b/plat/mediatek/mt8195/aarch64/platform_common.c
@@ -21,6 +21,14 @@
 			MT_DEVICE | MT_RW | MT_SECURE),
 	MAP_REGION_FLAT(eDP_SEC_BASE, eDP_SEC_SIZE,
 			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(APUSYS_SCTRL_REVISER_BASE, APUSYS_SCTRL_REVISER_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(APUSYS_APU_S_S_4_BASE, APUSYS_APU_S_S_4_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(APUSYS_APU_PLL_BASE, APUSYS_APU_PLL_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(APUSYS_APU_ACC_BASE, APUSYS_APU_ACC_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE),
 	{ 0 }
 };
 
diff --git a/plat/mediatek/mt8195/drivers/apusys/apupll.c b/plat/mediatek/mt8195/drivers/apusys/apupll.c
new file mode 100644
index 0000000..0eb8d4a
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/apusys/apupll.c
@@ -0,0 +1,581 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/spinlock.h>
+
+#include <apupwr_clkctl.h>
+#include <apupwr_clkctl_def.h>
+#include <mtk_plat_common.h>
+#include <platform_def.h>
+
+uint32_t mixed_con0_addr[APUPLL_MAX] = {
+	APU_PLL4H_PLL1_CON0,
+	APU_PLL4H_PLL2_CON0,
+	APU_PLL4H_PLL3_CON0,
+	APU_PLL4H_PLL4_CON0,
+};
+
+uint32_t mixed_con1_addr[APUPLL_MAX] = {
+	APU_PLL4H_PLL1_CON1,
+	APU_PLL4H_PLL2_CON1,
+	APU_PLL4H_PLL3_CON1,
+	APU_PLL4H_PLL4_CON1,
+};
+
+uint32_t mixed_con3_addr[APUPLL_MAX] = {
+	APU_PLL4H_PLL1_CON3,
+	APU_PLL4H_PLL2_CON3,
+	APU_PLL4H_PLL3_CON3,
+	APU_PLL4H_PLL4_CON3,
+};
+
+uint32_t fhctl_dds_addr[APUPLL_MAX] = {
+	APU_PLL4H_FHCTL0_DDS,
+	APU_PLL4H_FHCTL1_DDS,
+	APU_PLL4H_FHCTL2_DDS,
+	APU_PLL4H_FHCTL3_DDS,
+};
+
+uint32_t fhctl_dvfs_addr[APUPLL_MAX] = {
+	APU_PLL4H_FHCTL0_DVFS,
+	APU_PLL4H_FHCTL1_DVFS,
+	APU_PLL4H_FHCTL2_DVFS,
+	APU_PLL4H_FHCTL3_DVFS,
+};
+
+uint32_t fhctl_mon_addr[APUPLL_MAX] = {
+	APU_PLL4H_FHCTL0_MON,
+	APU_PLL4H_FHCTL1_MON,
+	APU_PLL4H_FHCTL2_MON,
+	APU_PLL4H_FHCTL3_MON,
+};
+
+uint32_t fhctl_cfg_addr[APUPLL_MAX] = {
+	APU_PLL4H_FHCTL0_CFG,
+	APU_PLL4H_FHCTL1_CFG,
+	APU_PLL4H_FHCTL2_CFG,
+	APU_PLL4H_FHCTL3_CFG,
+};
+
+static spinlock_t apupll_lock;
+static spinlock_t npupll_lock;
+static spinlock_t apupll_1_lock;
+static spinlock_t apupll_2_lock;
+static uint32_t pll_cnt[APUPLL_MAX];
+/**
+ * vd2pllidx() - voltage domain to pll idx.
+ * @domain: the voltage domain for getting pll index.
+ *
+ * Caller will get correspond pll index by different voltage domain.
+ * pll_idx[0] --> APUPLL (MDLA0/1)
+ * pll_idx[1] --> NPUPLL (VPU0/1)
+ * pll_idx[2] --> APUPLL1(CONN)
+ * pll_idx[3] --> APUPLL2(IOMMU)
+ * The longer description may have multiple paragraphs.
+ *
+ * Context: Any context.
+ * Return:
+ * * 0 ~ 3	- return the corresponding pll index
+ * * -EEXIST	- cannot find pll idex of the specific voltage domain
+ *
+ */
+static int32_t vd2pllidx(enum dvfs_voltage_domain domain)
+{
+	int32_t ret;
+
+	switch (domain) {
+	case V_VPU0:
+	case V_VPU1:
+		ret = NPUPLL;
+		break;
+	case V_MDLA0:
+	case V_MDLA1:
+		ret = APUPLL;
+		break;
+	case V_TOP_IOMMU:
+		ret = APUPLL2;
+		break;
+	case V_APU_CONN:
+		ret = APUPLL1;
+		break;
+	default:
+		ERROR("%s wrong voltage domain: %d\n", __func__, domain);
+		ret = -EEXIST; /* non-exist */
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * pllidx2name() - return names of specific pll index.
+ * @pll_idx: input for specific pll index.
+ *
+ * Given pll index, this function will return name of it.
+ *
+ * Context: Any context.
+ * Return: Names of pll_idx, if found, otherwise will return "NULL"
+ */
+static const char *pllidx2name(int32_t pll_idx)
+{
+	static const char *const names[] = {
+		[APUPLL] = "PLL4H_PLL1",
+		[NPUPLL] = "PLL4H_PLL2",
+		[APUPLL1] = "PLL4H_PLL3",
+		[APUPLL2] = "PLL4H_PLL4",
+		[APUPLL_MAX] = "NULL",
+	};
+
+	if (pll_idx >= APUPLL_MAX) {
+		pll_idx = APUPLL_MAX;
+	}
+
+	return names[pll_idx];
+}
+
+/**
+ * _fhctl_mon_done() - poll whether fhctl HW mode is done.
+ * @pll_idx: input for specific pll index.
+ * @tar_dds: target dds for fhctl_mon to be.
+ *
+ * Given pll index, this function will continue to poll whether fhctl_mon
+ * has reached the expected value within 80us.
+ *
+ * Context: Any context.
+ * Return:
+ * * 0 - OK for fhctl_mon == tar_dds
+ * * -ETIMEDOUT - fhctl_mon not reach tar_dds
+ */
+static int32_t _fhctl_mon_done(uint32_t pll_idx, unsigned long tar_dds)
+{
+	unsigned long mon_dds;
+	uint64_t timeout = timeout_init_us(PLL_READY_TIME_20US);
+	int32_t ret = 0;
+
+	tar_dds &= DDS_MASK;
+	do {
+		mon_dds = apupwr_readl(fhctl_mon_addr[pll_idx]) & DDS_MASK;
+		if (mon_dds == tar_dds) {
+			break;
+		}
+
+		if (timeout_elapsed(timeout)) {
+			ERROR("%s monitor DDS 0x%08lx != expect 0x%08lx\n",
+				  pllidx2name(pll_idx), mon_dds, tar_dds);
+			ret = -ETIMEDOUT;
+			break;
+		}
+	} while (mon_dds != tar_dds);
+
+	return ret;
+}
+
+/**
+ * _pll_get_postdiv_reg() - return current post dividor of pll_idx
+ * @pll_idx: input for specific pll index.
+ *
+ * Given pll index, this function will return its current post dividor.
+ *
+ * Context: Any context.
+ * Return: post dividor of current pll_idx.
+ *
+ */
+static uint32_t _pll_get_postdiv_reg(uint32_t pll_idx)
+{
+	int32_t pll_postdiv_reg = 0;
+	uint32_t val;
+
+	val = apupwr_readl(mixed_con1_addr[pll_idx]);
+	pll_postdiv_reg = (val >> POSDIV_SHIFT) & POSDIV_MASK;
+	return pll_postdiv_reg;
+}
+
+/**
+ * _set_postdiv_reg() - set pll_idx's post dividor.
+ * @pll_idx: Which PLL to enable/disable
+ * @post_div: the register value of post dividor to be wrtten.
+ *
+ * Below are lists of post dividor register value and its meaning:
+ * [31]     APUPLL_SDM_PCW_CHG
+ * [26:24]  APUPLL_POSDIV
+ * [21:0]   APUPLL_SDM_PCW (8bit integer + 14bit fraction)
+ * expected freq range ----- divider-------post divider in reg:
+ * >1500M   (1500/ 1)         -> 1        -> 0(2 to the zero power)
+ * > 750M   (1500/ 2)         -> 2        -> 1(2 to the 1st  power)
+ * > 375M   (1500/ 4)         -> 4        -> 2(2 to the 2nd  power)
+ * > 187.5M (1500/ 8)         -> 8        -> 3(2 to the 3rd  power)
+ * > 93.75M (1500/16)         -> 16       -> 4(2 to the 4th  power)
+ *
+ * Context: Any context.
+ */
+static void _set_postdiv_reg(uint32_t pll_idx, uint32_t post_div)
+{
+	apupwr_clrbits(POSDIV_MASK << POSDIV_SHIFT, mixed_con1_addr[pll_idx]);
+	apupwr_setbits((post_div & POSDIV_MASK) << POSDIV_SHIFT,
+			mixed_con1_addr[pll_idx]);
+}
+
+/**
+ * _cal_pll_data() - input freq, calculate correspond post dividor and dds.
+ * @pd: address of output post dividor.
+ * @dds: address of output dds.
+ * @freq: input frequency.
+ *
+ * Given freq, this function will calculate correspond post dividor and dds.
+ *
+ * Context: Any context.
+ * Return:
+ * * 0 - done for calculating post dividor and dds.
+ */
+static int32_t _cal_pll_data(uint32_t *pd, uint32_t *dds, uint32_t freq)
+{
+	uint32_t vco, postdiv_val = 1, postdiv_reg = 0;
+	uint32_t pcw_val;
+
+	vco = freq;
+	postdiv_val = 1;
+	postdiv_reg = 0;
+	while (vco <= FREQ_VCO_MIN) {
+		postdiv_val = postdiv_val << 1;
+		postdiv_reg = postdiv_reg + 1;
+		vco = vco << 1;
+	}
+
+	pcw_val = vco * (1 << PCW_FRACTIONAL_SHIFT);
+	pcw_val = pcw_val / FREQ_FIN;
+
+	if (postdiv_reg == 0) { /* Fvco * 2 with post_divider = 2 */
+		pcw_val = pcw_val * 2;
+		postdiv_val = postdiv_val << 1;
+		postdiv_reg = postdiv_reg + 1;
+	} /* Post divider is 1 is not available */
+	*pd = postdiv_reg;
+	*dds = pcw_val | RG_PLL_SDM_PCW_CHG;
+
+	return 0;
+}
+
+/**
+ * _pll_en() - enable/disable RG_PLL_EN of CON1 for pll[pll_idx]
+ * @pll_idx: Which PLL to enable/disable
+ * @on: 1 -> enable, 0 -> disable.
+ *
+ * This funciton will only change RG_PLL_EN of CON1 for pll[pll_idx].
+ *
+ * Context: Any context.
+ */
+static void _pll_en(uint32_t pll_idx, bool on)
+{
+	if (on) {
+		apupwr_setbits(RG_PLL_EN, mixed_con0_addr[pll_idx]);
+	} else {
+		apupwr_clrbits(RG_PLL_EN, mixed_con0_addr[pll_idx]);
+	}
+}
+
+/**
+ * _pll_pwr() - enable/disable PLL_SDM_PWR_ON of CON3 for pll[pll_idx]
+ * @pll_idx: Which PLL to enable/disable
+ * @on: 1 -> enable, 0 -> disable.
+ *
+ * This funciton will only change PLL_SDM_PWR_ON of CON3 for pll[pll_idx].
+ *
+ * Context: Any context.
+ */
+static void _pll_pwr(uint32_t pll_idx, bool on)
+{
+	if (on) {
+		apupwr_setbits(DA_PLL_SDM_PWR_ON, mixed_con3_addr[pll_idx]);
+	} else {
+		apupwr_clrbits(DA_PLL_SDM_PWR_ON, mixed_con3_addr[pll_idx]);
+	}
+}
+
+/**
+ * _pll_iso() - enable/disable PLL_SDM_ISO_EN of CON3 for pll[pll_idx]
+ * @pll_idx: Which PLL to enable/disable
+ * @enable: 1 -> turn on isolation, 0 -> turn off isolation.
+ *
+ * This funciton will turn on/off pll isolation by
+ * changing PLL_SDM_PWR_ON of CON3 for pll[pll_idx].
+ *
+ * Context: Any context.
+ */
+static void _pll_iso(uint32_t pll_idx, bool enable)
+{
+	if (enable) {
+		apupwr_setbits(DA_PLL_SDM_ISO_EN, mixed_con3_addr[pll_idx]);
+	} else {
+		apupwr_clrbits(DA_PLL_SDM_ISO_EN, mixed_con3_addr[pll_idx]);
+	}
+}
+
+/**
+ * _pll_switch() - entry point to turn whole PLL on/off
+ * @pll_idx: Which PLL to enable/disable
+ * @on: 1 -> enable, 0 -> disable.
+ * @fhctl_en: enable or disable fhctl function
+ *
+ * This is the entry poing for controlling pll and fhctl funciton on/off.
+ * Caller can chose only enable pll instead of fhctl function.
+ *
+ * Context: Any context.
+ * Return:
+ * * 0		- done for enable pll or fhctl as well.
+ */
+static int32_t _pll_switch(uint32_t pll_idx, bool on, bool fhctl_en)
+{
+	int32_t ret = 0;
+
+	if (pll_idx >= APUPLL_MAX) {
+		ERROR("%s wrong pll_idx: %d\n", __func__, pll_idx);
+		ret = -EINVAL;
+		goto err;
+	}
+
+	if (on) {
+		_pll_pwr(pll_idx, true);
+		udelay(PLL_CMD_READY_TIME_1US);
+		_pll_iso(pll_idx, false);
+		udelay(PLL_CMD_READY_TIME_1US);
+		_pll_en(pll_idx, true);
+		udelay(PLL_READY_TIME_20US);
+	} else {
+		_pll_en(pll_idx, false);
+		_pll_iso(pll_idx, true);
+		_pll_pwr(pll_idx, false);
+	}
+
+err:
+	return ret;
+}
+
+/**
+ * apu_pll_enable() - API for smc function to enable/disable pll
+ * @pll_idx: Which pll to enable/disable.
+ * @enable: 1 -> enable, 0 -> disable.
+ * @fhctl_en: enable or disable fhctl function
+ *
+ * pll_idx[0] --> APUPLL (MDLA0/1)
+ * pll_idx[1] --> NPUPLL (VPU0/1)
+ * pll_idx[2] --> APUPLL1(CONN)
+ * pll_idx[3] --> APUPLL2(IOMMU)
+ * The differences between _pll_switch are:
+ * 1. Atomic update pll reference cnt to protect double enable pll &
+ * close pll during user is not zero.
+ *
+ * Context: Any context.
+ * Return:
+ * * 0 - done for enable pll or fhctl as well.
+ */
+int32_t apu_pll_enable(int32_t pll_idx, bool enable, bool fhctl_en)
+{
+	int32_t ret = 0;
+
+	if (pll_idx >= APUPLL_MAX) {
+		ERROR("%s wrong pll_idx: %d\n", __func__, pll_idx);
+		ret = -EINVAL;
+		goto err;
+	}
+
+	if (enable) {
+		switch (pll_idx) {
+		case APUPLL:
+			spin_lock(&apupll_lock);
+			if (pll_cnt[APUPLL] == 0) {
+				_pll_switch(pll_idx, enable, fhctl_en);
+			}
+			pll_cnt[APUPLL]++;
+			spin_unlock(&apupll_lock);
+			break;
+		case NPUPLL:
+			spin_lock(&npupll_lock);
+			if (pll_cnt[NPUPLL] == 0) {
+				_pll_switch(pll_idx, enable, fhctl_en);
+			}
+			pll_cnt[NPUPLL]++;
+			spin_unlock(&npupll_lock);
+			break;
+		case APUPLL1:
+			spin_lock(&apupll_1_lock);
+			if (pll_cnt[APUPLL1] == 0) {
+				_pll_switch(pll_idx, enable, fhctl_en);
+			}
+			pll_cnt[APUPLL1]++;
+			spin_unlock(&apupll_1_lock);
+			break;
+		case APUPLL2:
+			spin_lock(&apupll_2_lock);
+			if (pll_cnt[APUPLL2] == 0) {
+				_pll_switch(pll_idx, enable, fhctl_en);
+			}
+			pll_cnt[APUPLL2]++;
+			spin_unlock(&apupll_2_lock);
+			break;
+		default:
+			ERROR("%s invalid pll_idx: %d\n", __func__, pll_idx);
+			ret = -EINVAL;
+			break;
+		}
+	} else {
+		switch (pll_idx) {
+		case APUPLL:
+			spin_lock(&apupll_lock);
+			if (pll_cnt[APUPLL]) {
+				pll_cnt[APUPLL]--;
+			}
+			if (pll_cnt[APUPLL] == 0) {
+				_pll_switch(pll_idx, enable, fhctl_en);
+			}
+			spin_unlock(&apupll_lock);
+			break;
+		case NPUPLL:
+			spin_lock(&npupll_lock);
+			if (pll_cnt[NPUPLL]) {
+				pll_cnt[NPUPLL]--;
+			}
+			if (pll_cnt[NPUPLL] == 0) {
+				_pll_switch(pll_idx, enable, fhctl_en);
+			}
+			spin_unlock(&npupll_lock);
+			break;
+		case APUPLL1:
+			spin_lock(&apupll_1_lock);
+			if (pll_cnt[APUPLL1]) {
+				pll_cnt[APUPLL1]--;
+			}
+			if (pll_cnt[APUPLL1] == 0) {
+				_pll_switch(pll_idx, enable, fhctl_en);
+			}
+			spin_unlock(&apupll_1_lock);
+			break;
+		case APUPLL2:
+			spin_lock(&apupll_2_lock);
+			if (pll_cnt[APUPLL2]) {
+				pll_cnt[APUPLL2]--;
+			}
+			if (pll_cnt[APUPLL2] == 0) {
+				_pll_switch(pll_idx, enable, fhctl_en);
+			}
+			spin_unlock(&apupll_2_lock);
+			break;
+		default:
+			ERROR("%s invalid pll_idx: %d\n", __func__, pll_idx);
+			ret = -EINVAL;
+			break;
+		}
+	}
+
+err:
+	return ret;
+}
+
+/**
+ * anpu_pll_set_rate() - API for smc function to set rate of voltage domain.
+ * @domain: Which pll of correspond voltage domain to change rate.
+ * @mode: which mode to use when set_rate
+ * @freq: which frequency to set.
+ *
+ * For V_VPU0/1, it will only allow 1 of them to modify NPUPLL
+ * such that there will be no race condition happen.
+ *
+ * For V_MDLA0/1, it will only allow 1 of them to modify APUPLL1
+ * such that there will be no race condition happen.
+ *
+ * There are 3 kinds of modes to set pll's rate.
+ * 1. pure sw mode: (CON0_PCW)
+ *        fhctl function is off and change rate by programming CON1_PCW.
+ * 2. fhctl sw mode: (FHCTL_SW)
+ *        fhctl function is on and change rate by programming fhctl_dds.
+ *        (post dividor is still need to program CON1_PCW)
+ * 3. fhctl hw mode: (FHCTL_HW)
+ *        fhctl function is on and change rate by programming fhctl_dvfs.
+ *        (post dividor is still need to program CON1_PCW)
+ *
+ * Context: Any context.
+ * Return:
+ * * 0 - done for set rate of voltage domain.
+ */
+int32_t anpu_pll_set_rate(enum dvfs_voltage_domain domain,
+		      enum pll_set_rate_mode mode, int32_t freq)
+{
+	uint32_t pd, old_pd, dds;
+	int32_t pll_idx, ret = 0;
+
+	pll_idx = vd2pllidx(domain);
+	if (pll_idx < 0) {
+		ret = pll_idx;
+		goto err;
+	}
+
+	_cal_pll_data(&pd, &dds, freq / 1000);
+
+	INFO("%s %s new post_div=%d, target dds=0x%08x(%dMhz) mode = %d\n",
+	     __func__, pllidx2name(pll_idx), pd, dds, freq / 1000, mode);
+
+	/* spin_lock for NPULL, since vpu0/1 share npupll */
+	if (domain == V_VPU0 || domain == V_VPU1) {
+		spin_lock(&npupll_lock);
+	}
+
+	/* spin_lock for APUPLL, since mdla0/1 shate apupll */
+	if (domain == V_MDLA0 || domain == V_MDLA1) {
+		spin_lock(&apupll_lock);
+	}
+
+	switch (mode) {
+	case CON0_PCW:
+		pd = RG_PLL_SDM_PCW_CHG |
+		     (pd & POSDIV_MASK) << POSDIV_SHIFT | dds;
+		apupwr_writel(pd, mixed_con1_addr[pll_idx]);
+		udelay(PLL_READY_TIME_20US);
+		break;
+	case FHCTL_SW:
+		/* pll con0 disable */
+		_pll_en(pll_idx, false);
+		apupwr_writel(dds, fhctl_dds_addr[pll_idx]);
+		_set_postdiv_reg(pll_idx, pd);
+		apupwr_setbits(PLL_TGL_ORG, fhctl_dds_addr[pll_idx]);
+		udelay(PLL_CMD_READY_TIME_1US);
+		/* pll con0 enable */
+		_pll_en(pll_idx, true);
+		udelay(PLL_READY_TIME_20US);
+		break;
+	case FHCTL_HW:
+		old_pd = _pll_get_postdiv_reg(pll_idx);
+		if (pd > old_pd) {
+			_set_postdiv_reg(pll_idx, pd);
+			apupwr_writel(dds, fhctl_dvfs_addr[pll_idx]);
+		} else {
+			apupwr_writel(dds, fhctl_dvfs_addr[pll_idx]);
+			_set_postdiv_reg(pll_idx, pd);
+		}
+		ret = _fhctl_mon_done(pll_idx, dds);
+		break;
+	default:
+		ERROR("%s input wrong mode: %d\n", __func__, mode);
+		ret = -EINVAL;
+		break;
+	}
+
+	/* spin_lock for NPULL, since vpu0/1 share npupll */
+	if (domain == V_VPU0 || domain == V_VPU1) {
+		spin_unlock(&npupll_lock);
+	}
+
+	/* spin_lock for APUPLL, since mdla0/1 share apupll */
+	if (domain == V_MDLA0 || domain == V_MDLA1) {
+		spin_unlock(&apupll_lock);
+	}
+
+err:
+	return ret;
+}
diff --git a/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl.c b/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl.c
new file mode 100644
index 0000000..465054d
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl.c
@@ -0,0 +1,341 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+
+#include <apupwr_clkctl.h>
+#include <apupwr_clkctl_def.h>
+#include <mtk_plat_common.h>
+#include <platform_def.h>
+
+/* 8195 use PCW mode to change freq directly */
+enum pll_set_rate_mode PLL_MODE = CON0_PCW;
+
+char *buck_domain_str[APUSYS_BUCK_DOMAIN_NUM] = {
+	"V_VPU0",
+	"V_VPU1",
+	"V_MDLA0",
+	"V_MDLA1",
+	"V_APU_CONN",
+	"V_TOP_IOMMU",
+	"V_VCORE",
+};
+
+uint32_t aacc_set[APUSYS_BUCK_DOMAIN_NUM] = {
+	APU_ACC_CONFG_SET1, APU_ACC_CONFG_SET2,
+	APU_ACC_CONFG_SET4, APU_ACC_CONFG_SET5,
+	APU_ACC_CONFG_SET0, APU_ACC_CONFG_SET7
+};
+
+uint32_t aacc_clr[APUSYS_BUCK_DOMAIN_NUM] = {
+	APU_ACC_CONFG_CLR1, APU_ACC_CONFG_CLR2,
+	APU_ACC_CONFG_CLR4, APU_ACC_CONFG_CLR5,
+	APU_ACC_CONFG_CLR0, APU_ACC_CONFG_CLR7
+};
+
+struct reg_seq {
+	uint32_t address;
+	uint32_t val;
+};
+
+static const struct reg_seq init_acc_cfg[] = {
+	{ APU_ACC_CONFG_SET0, BIT(BIT_SEL_APU) },
+	{ APU_ACC_CONFG_CLR0, BIT(BIT_CGEN_SOC) },
+	{ APU_ACC_CONFG_SET0, BIT(BIT_SEL_APU_DIV2) },
+	{ APU_ACC_CONFG_SET7, BIT(BIT_SEL_APU) },
+	{ APU_ACC_CONFG_CLR7, BIT(BIT_CGEN_SOC) },
+	{ APU_ACC_CONFG_SET7, BIT(BIT_SEL_APU_DIV2) },
+	{ APU_ACC_CONFG_SET1, BIT(BIT_SEL_APU) },
+	{ APU_ACC_CONFG_CLR1, BIT(BIT_CGEN_SOC) },
+	{ APU_ACC_CONFG_SET1, BIT(BIT_SEL_APU_DIV2) },
+	{ APU_ACC_CONFG_SET2, BIT(BIT_INVEN_OUT) },
+	{ APU_ACC_CONFG_SET2, BIT(BIT_SEL_APU) },
+	{ APU_ACC_CONFG_CLR2, BIT(BIT_CGEN_SOC) },
+	{ APU_ACC_CONFG_SET2, BIT(BIT_SEL_APU_DIV2) },
+	{ APU_ACC_CONFG_SET4, BIT(BIT_SEL_APU) },
+	{ APU_ACC_CONFG_CLR4, BIT(BIT_CGEN_SOC) },
+	{ APU_ACC_CONFG_SET4, BIT(BIT_SEL_APU_DIV2) },
+	{ APU_ACC_CONFG_SET5, BIT(BIT_INVEN_OUT) },
+	{ APU_ACC_CONFG_SET5, BIT(BIT_SEL_APU) },
+	{ APU_ACC_CONFG_CLR5, BIT(BIT_CGEN_SOC) },
+	{ APU_ACC_CONFG_SET5, BIT(BIT_SEL_APU_DIV2) },
+};
+
+int32_t apupwr_smc_acc_init_all(void)
+{
+	int32_t i;
+
+	for (i = 0; i < ARRAY_SIZE(init_acc_cfg); i++) {
+		apupwr_writel(init_acc_cfg[i].val,
+			      init_acc_cfg[i].address);
+	}
+
+	/* Deault ACC will raise APU_DIV_2 */
+	apupwr_smc_pll_set_rate(BUCK_VCONN_DOMAIN_DEFAULT_FREQ,
+				true, V_APU_CONN);
+
+	apupwr_smc_pll_set_rate(BUCK_VCONN_DOMAIN_DEFAULT_FREQ,
+				true, V_TOP_IOMMU);
+
+	apupwr_smc_pll_set_rate(BUCK_VVPU_DOMAIN_DEFAULT_FREQ,
+				true, V_VPU0);
+
+	apupwr_smc_pll_set_rate(BUCK_VMDLA_DOMAIN_DEFAULT_FREQ,
+				true, V_MDLA0);
+
+	return 0;
+}
+
+void apupwr_smc_acc_top(bool enable)
+{
+	if (enable) {
+		apupwr_writel(BIT(BIT_CGEN_APU), aacc_set[V_APU_CONN]);
+		apupwr_writel(BIT(BIT_CGEN_APU), aacc_set[V_TOP_IOMMU]);
+	} else {
+		apupwr_writel(BIT(BIT_CGEN_APU), aacc_clr[V_APU_CONN]);
+		apupwr_writel(BIT(BIT_CGEN_APU), aacc_clr[V_TOP_IOMMU]);
+	}
+}
+
+/*
+ * acc_clk_set_parent:ACC MUX select
+ * 0. freq parameters here, only ACC clksrc is valid
+ * 1. Switch between APUPLL <=> Parking (F26M, PARK)
+ * 2. Turn on/off CG_F26M, CG_PARK, CG_SOC, but no CG_APU
+ * 3. Clear APU Div2 while Parking
+ * 4. Only use clksrc of APUPLL while ACC CG_APU is on
+ */
+int32_t apupwr_smc_acc_set_parent(uint32_t freq, uint32_t domain)
+{
+	uint32_t acc_set = 0;
+	uint32_t acc_clr = 0;
+	int32_t ret = 0;
+
+	if (freq > DVFS_FREQ_ACC_APUPLL) {
+		ERROR("%s wrong clksrc: %d\n", __func__, freq);
+		ret = -EIO;
+		goto err;
+	}
+
+	switch (domain) {
+	case V_VPU1:
+	case V_VPU0:
+	case V_MDLA1:
+	case V_MDLA0:
+	case V_APU_CONN:
+	case V_TOP_IOMMU:
+		acc_set = aacc_set[domain];
+		acc_clr = aacc_clr[domain];
+		break;
+	default:
+		ret = -EIO;
+		break;
+	}
+
+	/* Select park source */
+	switch (freq) {
+	case DVFS_FREQ_ACC_PARKING:
+		/* Select park source */
+		apupwr_writel(BIT(BIT_SEL_PARK), acc_set);
+		apupwr_writel(BIT(BIT_SEL_F26M), acc_clr);
+		/* Enable park cg */
+		apupwr_writel(BIT(BIT_CGEN_PARK), acc_set);
+		apupwr_writel(BIT(BIT_CGEN_F26M) | BIT(BIT_CGEN_SOC), acc_clr);
+		/* Select park path */
+		apupwr_writel(BIT(BIT_SEL_APU), acc_clr);
+		/* clear apu div 2 */
+		apupwr_writel(BIT(BIT_SEL_APU_DIV2), acc_clr);
+		break;
+
+	case DVFS_FREQ_ACC_APUPLL:
+		/* Select park path */
+		apupwr_writel(BIT(BIT_SEL_APU), acc_set);
+		/* Clear park cg */
+		apupwr_writel(BIT(BIT_CGEN_PARK) | BIT(BIT_CGEN_F26M) |
+			      BIT(BIT_CGEN_SOC), acc_clr);
+		break;
+
+	case DVFS_FREQ_ACC_SOC:
+		/* Select park source */
+		apupwr_writel(BIT(BIT_SEL_PARK), acc_clr);
+		apupwr_writel(BIT(BIT_SEL_F26M), acc_clr);
+		/* Enable park cg */
+		apupwr_writel(BIT(BIT_CGEN_SOC), acc_set);
+		apupwr_writel(BIT(BIT_CGEN_F26M) | BIT(BIT_CGEN_PARK), acc_clr);
+		/* Select park path */
+		apupwr_writel(BIT(BIT_SEL_APU), acc_clr);
+		/* clear apu div 2 */
+		apupwr_writel(BIT(BIT_SEL_APU_DIV2), acc_clr);
+		break;
+
+	case DVFS_FREQ_ACC_26M:
+	case DVFS_FREQ_NOT_SUPPORT:
+	default:
+		/* Select park source */
+		apupwr_writel(BIT(BIT_SEL_F26M), acc_set);
+		apupwr_writel(BIT(BIT_SEL_PARK), acc_clr);
+		/* Enable park cg */
+		apupwr_writel(BIT(BIT_CGEN_F26M), acc_set);
+		apupwr_writel(BIT(BIT_CGEN_PARK) | BIT(BIT_CGEN_SOC), acc_clr);
+		/* Select park path */
+		apupwr_writel(BIT(BIT_SEL_APU), acc_clr);
+		/* clear apu div 2 */
+		apupwr_writel(BIT(BIT_SEL_APU_DIV2), acc_clr);
+		ERROR("[APUPWR] %s wrong ACC clksrc : %d, force assign 26M\n",
+		      __func__, freq);
+		break;
+	}
+
+err:
+	return ret;
+}
+
+int32_t apupwr_smc_pll_set_rate(uint32_t freq, bool div2, uint32_t domain)
+{
+	int32_t ret = 0;
+	uint32_t acc_set0 = 0, acc_set1 = 0;
+
+	if (freq > DVFS_FREQ_MAX) {
+		ERROR("%s wrong freq: %d\n", __func__, freq);
+		ret = -EIO;
+		goto err;
+	}
+
+	/*
+	 * Switch to Parking src
+	 * 1. Need to switch out all ACCs sharing the same apupll
+	 */
+	switch (domain) {
+	case V_MDLA0:
+	case V_MDLA1:
+		acc_set0 = APU_ACC_CONFG_SET4;
+		acc_set1 = APU_ACC_CONFG_SET5;
+		ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_PARKING,
+						V_MDLA0);
+		ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_PARKING,
+						V_MDLA1);
+		break;
+	case V_VPU0:
+	case V_VPU1:
+		acc_set0 = APU_ACC_CONFG_SET1;
+		acc_set1 = APU_ACC_CONFG_SET2;
+		ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_PARKING,
+						V_VPU0);
+		ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_PARKING,
+						V_VPU1);
+		break;
+	case V_APU_CONN:
+		acc_set0 = APU_ACC_CONFG_SET0;
+		ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_PARKING,
+						V_APU_CONN);
+		break;
+	case V_TOP_IOMMU:
+		acc_set0 = APU_ACC_CONFG_SET7;
+		ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_PARKING,
+						V_TOP_IOMMU);
+		break;
+	default:
+		ERROR("[APUPWR] %s %d invalid domain (%d)\n",
+		      __func__, __LINE__, domain);
+		ret = -EIO;
+		goto err;
+	}
+
+	anpu_pll_set_rate(domain, PLL_MODE, (div2) ? (freq * 2) : freq);
+
+	if (div2) {
+		apupwr_writel(BIT(BIT_SEL_APU_DIV2), acc_set0);
+		if (acc_set1) {
+			apupwr_writel(BIT(BIT_SEL_APU_DIV2), acc_set1);
+		}
+	}
+
+	/*
+	 * Switch back to APUPLL
+	 * Only switch back to APUPLL while CG_APU on
+	 * And clksrc is not APUPLL
+	 */
+	switch (domain) {
+	case V_VPU0:
+	case V_VPU1:
+		if ((apupwr_readl(acc_set0) & BIT(BIT_CGEN_APU)) &&
+		     !(apupwr_readl(acc_set0) & BIT(BIT_SEL_APU))) {
+			ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_APUPLL,
+							V_VPU0);
+		}
+		if ((apupwr_readl(acc_set1) & BIT(BIT_CGEN_APU)) &&
+		     !(apupwr_readl(acc_set1) & BIT(BIT_SEL_APU))) {
+			ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_APUPLL,
+							V_VPU1);
+		}
+		break;
+	case V_MDLA0:
+	case V_MDLA1:
+		if ((apupwr_readl(acc_set0) & BIT(BIT_CGEN_APU)) &&
+		     !(apupwr_readl(acc_set0) & BIT(BIT_SEL_APU))) {
+			ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_APUPLL,
+							V_MDLA0);
+		}
+		if ((apupwr_readl(acc_set1) & BIT(BIT_CGEN_APU)) &&
+		     !(apupwr_readl(acc_set1) & BIT(BIT_SEL_APU))) {
+			ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_APUPLL,
+							V_MDLA1);
+		}
+		break;
+	case V_APU_CONN:
+	case V_TOP_IOMMU:
+		if ((apupwr_readl(acc_set0) & BIT(BIT_CGEN_APU)) &&
+		    !(apupwr_readl(acc_set0) & BIT(BIT_SEL_APU))) {
+			ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_APUPLL,
+							domain);
+		}
+		break;
+	default:
+		ERROR("[APUPWR] %s %d invalid domain (%d)\n",
+		      __func__, __LINE__, domain);
+		ret = -EIO;
+		break;
+	}
+	INFO("[%s][%d] set domain %d to freq %d\n",
+	     __func__, __LINE__, domain, (div2) ? (freq * 2) : freq);
+
+err:
+	return ret;
+}
+
+int32_t apupwr_smc_bulk_pll(bool enable)
+{
+	int32_t ret = 0;
+	int32_t pll_idx;
+
+	if (enable) {
+		for (pll_idx = APUPLL; pll_idx < APUPLL_MAX; pll_idx++) {
+			ret = apu_pll_enable(pll_idx, enable, false);
+			if (ret != 0) {
+				goto err;
+			}
+		}
+	} else {
+		for (pll_idx = APUPLL2; pll_idx >= APUPLL; pll_idx--) {
+			ret = apu_pll_enable(pll_idx, enable, false);
+			if (ret != 0) {
+				goto err;
+			}
+		}
+	}
+
+err:
+	return ret;
+}
+
+void apupwr_smc_bus_prot_cg_on(void)
+{
+	apupwr_clrbits(AO_MD32_MNOC_MASK, APU_CSR_DUMMY_0);
+}
diff --git a/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl.h b/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl.h
new file mode 100644
index 0000000..3b27c1b
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef APUPWR_CLKCTL_H
+#define APUPWR_CLKCTL_H
+
+#include <arch_helpers.h>
+#include <apupwr_clkctl_def.h>
+
+int32_t apupwr_smc_acc_init_all(void);
+void apupwr_smc_acc_top(bool enable);
+int32_t apupwr_smc_acc_set_parent(uint32_t freq, uint32_t domain);
+int32_t apupwr_smc_pll_set_rate(uint32_t pll, bool div2, uint32_t domain);
+int32_t apupwr_smc_bulk_pll(bool enable);
+void apupwr_smc_bus_prot_cg_on(void);
+
+int32_t apu_pll_enable(int32_t pll_idx, bool enable, bool fhctl_en);
+int32_t anpu_pll_set_rate(enum dvfs_voltage_domain domain,
+			  enum pll_set_rate_mode mode, int32_t freq);
+#endif /* APUPWR_CLKCTL_H */
diff --git a/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl_def.h b/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl_def.h
new file mode 100644
index 0000000..6663ad9
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl_def.h
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef APUPWR_CLKCTL_DEF_H
+#define APUPWR_CLKCTL_DEF_H
+
+#include <lib/mmio.h>
+
+enum dvfs_voltage_domain {
+	V_VPU0			= 0,
+	V_VPU1			= 1,
+	V_MDLA0			= 2,
+	V_MDLA1			= 3,
+	V_APU_CONN		= 4,
+	V_TOP_IOMMU		= 5,
+	V_VCORE			= 6,
+	APUSYS_BUCK_DOMAIN_NUM	= 7,
+};
+
+enum dvfs_freq {
+	DVFS_FREQ_NOT_SUPPORT	= 0,
+	DVFS_FREQ_ACC_26M	= 1,
+	DVFS_FREQ_ACC_PARKING	= 2,
+	DVFS_FREQ_ACC_SOC	= 3,
+	DVFS_FREQ_ACC_APUPLL	= 4,
+	DVFS_FREQ_00_026000_F	= 26000,
+	DVFS_FREQ_00_208000_F	= 208000,
+	DVFS_FREQ_00_238000_F	= 238000,
+	DVFS_FREQ_00_273000_F	= 273000,
+	DVFS_FREQ_00_312000_F	= 312000,
+	DVFS_FREQ_00_358000_F	= 358000,
+	DVFS_FREQ_00_385000_F	= 385000,
+	DVFS_FREQ_00_499200_F	= 499200,
+	DVFS_FREQ_00_500000_F	= 500000,
+	DVFS_FREQ_00_525000_F	= 525000,
+	DVFS_FREQ_00_546000_F	= 546000,
+	DVFS_FREQ_00_594000_F	= 594000,
+	DVFS_FREQ_00_624000_F	= 624000,
+	DVFS_FREQ_00_688000_F	= 688000,
+	DVFS_FREQ_00_687500_F	= 687500,
+	DVFS_FREQ_00_728000_F	= 728000,
+	DVFS_FREQ_00_800000_F	= 800000,
+	DVFS_FREQ_00_832000_F	= 832000,
+	DVFS_FREQ_00_960000_F	= 960000,
+	DVFS_FREQ_00_1100000_F	= 1100000,
+};
+#define DVFS_FREQ_MAX (DVFS_FREQ_00_1100000_F)
+
+enum pll_set_rate_mode {
+	CON0_PCW		= 0,
+	FHCTL_SW		= 1,
+	FHCTL_HW		= 2,
+	PLL_SET_RATE_MODE_MAX	= 3,
+};
+
+enum apupll {
+	APUPLL		= 0,
+	NPUPLL		= 1,
+	APUPLL1		= 2,
+	APUPLL2		= 3,
+	APUPLL_MAX	= 4,
+};
+
+#define BUCK_VVPU_DOMAIN_DEFAULT_FREQ	(DVFS_FREQ_00_273000_F)
+#define BUCK_VMDLA_DOMAIN_DEFAULT_FREQ	(DVFS_FREQ_00_312000_F)
+#define BUCK_VCONN_DOMAIN_DEFAULT_FREQ	(DVFS_FREQ_00_208000_F)
+
+#define apupwr_writel(VAL, REG)		mmio_write_32((uintptr_t)REG, VAL)
+#define apupwr_writel_relax(VAL, REG)	mmio_write_32_relax((uintptr_t)REG, VAL)
+#define apupwr_readl(REG)		mmio_read_32((uintptr_t)REG)
+#define apupwr_clrbits(VAL, REG)	mmio_clrbits_32((uintptr_t)REG, VAL)
+#define apupwr_setbits(VAL, REG)	mmio_setbits_32((uintptr_t)REG, VAL)
+#define apupwr_clrsetbits(CLR_VAL, SET_VAL, REG)	\
+			  mmio_clrsetbits_32((uintptr_t)REG, CLR_VAL, SET_VAL)
+
+/* PLL and related register */
+#define APU_PLL_BASE		(APUSYS_APU_PLL_BASE)
+#define APU_PLL4H_PLL1_CON0	(APU_PLL_BASE + 0x008)
+#define APU_PLL4H_PLL1_CON1	(APU_PLL_BASE + 0x00C)
+#define APU_PLL4H_PLL1_CON3	(APU_PLL_BASE + 0x014)
+
+#define APU_PLL4H_PLL2_CON0	(APU_PLL_BASE + 0x018)
+#define APU_PLL4H_PLL2_CON1	(APU_PLL_BASE + 0x01C)
+#define APU_PLL4H_PLL2_CON3	(APU_PLL_BASE + 0x024)
+
+#define APU_PLL4H_PLL3_CON0	(APU_PLL_BASE + 0x028)
+#define APU_PLL4H_PLL3_CON1	(APU_PLL_BASE + 0x02C)
+#define APU_PLL4H_PLL3_CON3	(APU_PLL_BASE + 0x034)
+
+#define APU_PLL4H_PLL4_CON0	(APU_PLL_BASE + 0x038)
+#define APU_PLL4H_PLL4_CON1	(APU_PLL_BASE + 0x03C)
+#define APU_PLL4H_PLL4_CON3	(APU_PLL_BASE + 0x044)
+
+#define APU_PLL4H_FHCTL_HP_EN		(APU_PLL_BASE + 0x0E00)
+#define APU_PLL4H_FHCTL_UNITSLOPE_EN	(APU_PLL_BASE + 0x0E04)
+#define APU_PLL4H_FHCTL_CLK_CON		(APU_PLL_BASE + 0x0E08)
+#define APU_PLL4H_FHCTL_RST_CON		(APU_PLL_BASE + 0x0E0C)
+#define APU_PLL4H_FHCTL_SLOPE0		(APU_PLL_BASE + 0x0E10)
+#define APU_PLL4H_FHCTL_SLOPE1		(APU_PLL_BASE + 0x0E14)
+#define APU_PLL4H_FHCTL_DSSC_CFG	(APU_PLL_BASE + 0x0E18)
+#define APU_PLL4H_FHCTL_DSSC0_CON	(APU_PLL_BASE + 0x0E1C)
+#define APU_PLL4H_FHCTL_DSSC1_CON	(APU_PLL_BASE + 0x0E20)
+#define APU_PLL4H_FHCTL_DSSC2_CON	(APU_PLL_BASE + 0x0E24)
+#define APU_PLL4H_FHCTL_DSSC3_CON	(APU_PLL_BASE + 0x0E28)
+#define APU_PLL4H_FHCTL_DSSC4_CON	(APU_PLL_BASE + 0x0E2C)
+#define APU_PLL4H_FHCTL_DSSC5_CON	(APU_PLL_BASE + 0x0E30)
+#define APU_PLL4H_FHCTL_DSSC6_CON	(APU_PLL_BASE + 0x0E34)
+#define APU_PLL4H_FHCTL_DSSC7_CON	(APU_PLL_BASE + 0x0E38)
+#define APU_PLL4H_FHCTL0_CFG		(APU_PLL_BASE + 0x0E3C)
+#define APU_PLL4H_FHCTL0_UPDNLMT	(APU_PLL_BASE + 0x0E40)
+#define APU_PLL4H_FHCTL0_DDS		(APU_PLL_BASE + 0x0E44)
+#define APU_PLL4H_FHCTL0_DVFS		(APU_PLL_BASE + 0x0E48)
+#define APU_PLL4H_FHCTL0_MON		(APU_PLL_BASE + 0x0E4C)
+#define APU_PLL4H_FHCTL1_CFG		(APU_PLL_BASE + 0x0E50)
+#define APU_PLL4H_FHCTL1_UPDNLMT	(APU_PLL_BASE + 0x0E54)
+#define APU_PLL4H_FHCTL1_DDS		(APU_PLL_BASE + 0x0E58)
+#define APU_PLL4H_FHCTL1_DVFS		(APU_PLL_BASE + 0x0E5C)
+#define APU_PLL4H_FHCTL1_MON		(APU_PLL_BASE + 0x0E60)
+#define APU_PLL4H_FHCTL2_CFG		(APU_PLL_BASE + 0x0E64)
+#define APU_PLL4H_FHCTL2_UPDNLMT	(APU_PLL_BASE + 0x0E68)
+#define APU_PLL4H_FHCTL2_DDS		(APU_PLL_BASE + 0x0E6C)
+#define APU_PLL4H_FHCTL2_DVFS		(APU_PLL_BASE + 0x0E70)
+#define APU_PLL4H_FHCTL2_MON		(APU_PLL_BASE + 0x0E74)
+#define APU_PLL4H_FHCTL3_CFG		(APU_PLL_BASE + 0x0E78)
+#define APU_PLL4H_FHCTL3_UPDNLMT	(APU_PLL_BASE + 0x0E7C)
+#define APU_PLL4H_FHCTL3_DDS		(APU_PLL_BASE + 0x0E80)
+#define APU_PLL4H_FHCTL3_DVFS		(APU_PLL_BASE + 0x0E84)
+#define APU_PLL4H_FHCTL3_MON		(APU_PLL_BASE + 0x0E88)
+
+/* PLL4H_PLLx_CON0 */
+#define RG_PLL_EN		BIT(0)
+
+/* PLL4H_PLLx_CON1 */
+#define RG_PLL_SDM_PCW_CHG	BIT(31)
+#define POSDIV_SHIFT		(24U)
+#define POSDIV_MASK		(0x7)
+
+/* PLL4H_PLLx_CON3 */
+#define DA_PLL_SDM_PWR_ON	BIT(0)
+#define DA_PLL_SDM_ISO_EN	BIT(1)
+
+/* FHCTLx_DDS */
+#define DDS_MASK		GENMASK_32(21, 0)
+#define PCW_FRACTIONAL_SHIFT	14U
+#define PLL_TGL_ORG		BIT(31)
+
+#define PLL_READY_TIME_20US	(20U)
+#define PLL_CMD_READY_TIME_1US	(1U)
+
+#define FREQ_VCO_MIN		(1500U) /* 1500MHz*/
+#define FREQ_FIN		(26U)	/* 26M*/
+
+/* ACC and related register */
+#define APU_ACC_BASE		(APUSYS_APU_ACC_BASE)
+#define APU_ACC_CONFG_SET0	(APU_ACC_BASE + 0x000)
+#define APU_ACC_CONFG_SET1	(APU_ACC_BASE + 0x004)
+#define APU_ACC_CONFG_SET2	(APU_ACC_BASE + 0x008)
+#define APU_ACC_CONFG_SET4	(APU_ACC_BASE + 0x010)
+#define APU_ACC_CONFG_SET5	(APU_ACC_BASE + 0x014)
+#define APU_ACC_CONFG_SET7	(APU_ACC_BASE + 0x01C)
+
+#define APU_ACC_CONFG_CLR0	(APU_ACC_BASE + 0x040)
+#define APU_ACC_CONFG_CLR1	(APU_ACC_BASE + 0x044)
+#define APU_ACC_CONFG_CLR2	(APU_ACC_BASE + 0x048)
+#define APU_ACC_CONFG_CLR4	(APU_ACC_BASE + 0x050)
+#define APU_ACC_CONFG_CLR5	(APU_ACC_BASE + 0x054)
+#define APU_ACC_CONFG_CLR7	(APU_ACC_BASE + 0x05C)
+
+#define APU_ACC_FM_CONFG_SET	(APU_ACC_BASE + 0x0C0)
+#define APU_ACC_FM_CONFG_CLR	(APU_ACC_BASE + 0x0C4)
+#define APU_ACC_FM_SEL		(APU_ACC_BASE + 0x0C8)
+#define APU_ACC_FM_CNT		(APU_ACC_BASE + 0x0CC)
+
+/* APU AO control */
+#define APU_AO_CTRL_BASE	(APUSYS_APU_S_S_4_BASE)
+#define APU_CSR_DUMMY_0		(APU_AO_CTRL_BASE + 0x24)
+
+#define AO_MD32_MNOC_MASK	(BIT(1) | BIT(0))
+
+#define BIT_CGEN_F26M		(0)
+#define BIT_CGEN_PARK		(1)
+#define BIT_CGEN_SOC		(2)
+#define BIT_CGEN_APU		(3)
+#define BIT_CGEN_OUT		(4)
+#define BIT_SEL_PARK		(8)
+#define BIT_SEL_F26M		(9)
+#define BIT_SEL_APU_DIV2	(10)
+#define BIT_SEL_APU		(11)
+#define BIT_SEL_PARK_SRC_OUT	(12)
+#define BIT_INVEN_OUT		(15)
+
+#endif /* APUPWR_CLKCTL_DEF_H*/
diff --git a/plat/mediatek/mt8195/drivers/apusys/mtk_apusys.c b/plat/mediatek/mt8195/drivers/apusys/mtk_apusys.c
new file mode 100644
index 0000000..3ed26a1
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/apusys/mtk_apusys.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <lib/mmio.h>
+
+#include <apupwr_clkctl.h>
+#include <mtk_apusys.h>
+#include <plat/common/platform.h>
+
+int32_t apusys_kernel_ctrl(uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4,
+			    uint32_t *ret1)
+{
+	int32_t ret = 0L;
+	uint32_t request_ops;
+
+	request_ops = (uint32_t)x1;
+
+	switch (request_ops) {
+	case MTK_SIP_APU_START_MCU:
+		/* setup addr[33:32] in reviser */
+		mmio_write_32(REVISER_SECUREFW_CTXT, 0U);
+		mmio_write_32(REVISER_USDRFW_CTXT, 0U);
+
+		/* setup secure sideband */
+		mmio_write_32(AO_SEC_FW,
+			      (SEC_FW_NON_SECURE << SEC_FW_SHIFT_NS) |
+			      (0U << SEC_FW_DOMAIN_SHIFT));
+
+		/* setup boot address */
+		mmio_write_32(AO_MD32_BOOT_CTRL, 0U);
+
+		/* setup pre-define region */
+		mmio_write_32(AO_MD32_PRE_DEFINE,
+			      (PRE_DEFINE_CACHE_TCM << PRE_DEFINE_SHIFT_0G) |
+			      (PRE_DEFINE_CACHE << PRE_DEFINE_SHIFT_1G) |
+			      (PRE_DEFINE_CACHE << PRE_DEFINE_SHIFT_2G) |
+			      (PRE_DEFINE_CACHE << PRE_DEFINE_SHIFT_3G));
+
+		/* release runstall */
+		mmio_write_32(AO_MD32_SYS_CTRL, SYS_CTRL_RUN);
+
+		INFO("[APUSYS] rev(0x%08x,0x%08x)\n",
+		     mmio_read_32(REVISER_SECUREFW_CTXT),
+		     mmio_read_32(REVISER_USDRFW_CTXT));
+		INFO("[APUSYS] ao(0x%08x,0x%08x,0x%08x,0x%08x,0x%08x)\n",
+		     mmio_read_32(AO_SEC_FW),
+		     mmio_read_32(AO_SEC_USR_FW),
+		     mmio_read_32(AO_MD32_BOOT_CTRL),
+		     mmio_read_32(AO_MD32_PRE_DEFINE),
+		     mmio_read_32(AO_MD32_SYS_CTRL));
+		break;
+	case MTK_SIP_APU_STOP_MCU:
+		/* hold runstall */
+		mmio_write_32(AO_MD32_SYS_CTRL, SYS_CTRL_STALL);
+
+		INFO("[APUSYS] md32_boot_ctrl=0x%08x,runstall=0x%08x\n",
+		     mmio_read_32(AO_MD32_BOOT_CTRL),
+		     mmio_read_32(AO_MD32_SYS_CTRL));
+		break;
+	case MTK_SIP_APUPWR_BUS_PROT_CG_ON:
+		apupwr_smc_bus_prot_cg_on();
+		break;
+	case MTK_SIP_APUPWR_BULK_PLL:
+		ret = apupwr_smc_bulk_pll((bool)x2);
+		break;
+	case MTK_SIP_APUPWR_ACC_INIT_ALL:
+		ret = apupwr_smc_acc_init_all();
+		break;
+	case MTK_SIP_APUPWR_ACC_TOP:
+		apupwr_smc_acc_top((bool)x2);
+		break;
+	default:
+		ERROR("%s, unknown request_ops=0x%x\n", __func__, request_ops);
+		break;
+	}
+
+	return ret;
+}
diff --git a/plat/mediatek/mt8195/drivers/apusys/mtk_apusys.h b/plat/mediatek/mt8195/drivers/apusys/mtk_apusys.h
new file mode 100644
index 0000000..639abd3
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/apusys/mtk_apusys.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTK_APUSYS_H
+#define MTK_APUSYS_H
+
+#include <stdint.h>
+
+/* setup the SMC command ops */
+#define MTK_SIP_APU_START_MCU		(0x00U)
+#define MTK_SIP_APU_STOP_MCU		(0x01U)
+#define MTK_SIP_APUPWR_BUS_PROT_CG_ON	(0x02U)
+#define MTK_SIP_APUPWR_BULK_PLL		(0x03U)
+#define MTK_SIP_APUPWR_ACC_INIT_ALL	(0x04U)
+#define MTK_SIP_APUPWR_ACC_TOP		(0x05U)
+
+/* AO Register */
+#define AO_MD32_PRE_DEFINE	(APUSYS_APU_S_S_4_BASE + 0x00)
+#define AO_MD32_BOOT_CTRL	(APUSYS_APU_S_S_4_BASE + 0x04)
+#define AO_MD32_SYS_CTRL	(APUSYS_APU_S_S_4_BASE + 0x08)
+#define AO_SEC_FW		(APUSYS_APU_S_S_4_BASE + 0x10)
+#define AO_SEC_USR_FW		(APUSYS_APU_S_S_4_BASE + 0x14)
+
+#define PRE_DEFINE_CACHE_TCM	(0x3U)
+#define PRE_DEFINE_CACHE	(0x2U)
+#define PRE_DEFINE_SHIFT_0G	(0U)
+#define PRE_DEFINE_SHIFT_1G	(2U)
+#define PRE_DEFINE_SHIFT_2G	(4U)
+#define PRE_DEFINE_SHIFT_3G	(6U)
+
+#define SEC_FW_NON_SECURE	(1U)
+#define SEC_FW_SHIFT_NS		(4U)
+#define SEC_FW_DOMAIN_SHIFT	(0U)
+
+#define SEC_USR_FW_NON_SECURE	(1U)
+#define SEC_USR_FW_SHIFT_NS	(4U)
+#define SEC_USR_FW_DOMAIN_SHIFT	(0U)
+
+#define SYS_CTRL_RUN		(0U)
+#define SYS_CTRL_STALL		(1U)
+
+/* Reviser Register */
+#define REVISER_SECUREFW_CTXT	(APUSYS_SCTRL_REVISER_BASE + 0x100)
+#define REVISER_USDRFW_CTXT	(APUSYS_SCTRL_REVISER_BASE + 0x104)
+
+int32_t apusys_kernel_ctrl(uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4,
+			   uint32_t *ret1);
+#endif /* MTK_APUSYS_H */
diff --git a/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.c b/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.c
index 4330b77..794e21e 100644
--- a/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.c
+++ b/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.c
@@ -91,7 +91,61 @@
 	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));
+
+		INFO("region %d:\n", region);
+		INFO("\tsa:0x%lx, ea:0x%lx, apc0: 0x%lx apc1: 0x%lx\n",
+		     sa, ea, apc[0], apc[1]);
+	}
+}
+
 void emi_mpu_init(void)
 {
-	/* TODO: more setting for EMI MPU. */
+	struct emi_region_info_t region_info;
+
+	/* SCP DRAM */
+	region_info.start = 0x50000000ULL;
+	region_info.end = 0x51400000ULL;
+	region_info.region = 2;
+	SET_ACCESS_PERMISSION(region_info.apc, 1,
+			      FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+			      FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+			      FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+			      NO_PROTECTION, FORBIDDEN, FORBIDDEN, NO_PROTECTION);
+	emi_mpu_set_protection(&region_info);
+
+	/* DSP protect address */
+	region_info.start = 0x60000000ULL;	/* dram base addr */
+	region_info.end = 0x610FFFFFULL;
+	region_info.region = 3;
+	SET_ACCESS_PERMISSION(region_info.apc, 1,
+			      FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+			      FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+			      FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROTECTION,
+			      FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROTECTION);
+	emi_mpu_set_protection(&region_info);
+
+	/* Forbidden All */
+	region_info.start = 0x40000000ULL;	/* dram base addr */
+	region_info.end = 0x1FFFF0000ULL;
+	region_info.region = 4;
+	SET_ACCESS_PERMISSION(region_info.apc, 1,
+			      FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+			      FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+			      FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+			      FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROTECTION);
+	emi_mpu_set_protection(&region_info);
+
+	dump_emi_mpu_regions();
 }
diff --git a/plat/mediatek/mt8195/include/plat_sip_calls.h b/plat/mediatek/mt8195/include/plat_sip_calls.h
index ce25c6f..5562a67 100644
--- a/plat/mediatek/mt8195/include/plat_sip_calls.h
+++ b/plat/mediatek/mt8195/include/plat_sip_calls.h
@@ -10,7 +10,7 @@
 /*******************************************************************************
  * Plat SiP function constants
  ******************************************************************************/
-#define MTK_PLAT_SIP_NUM_CALLS    4
+#define MTK_PLAT_SIP_NUM_CALLS    6
 
 /* DFD */
 #define MTK_SIP_KERNEL_DFD_AARCH32	0x82000205
@@ -20,4 +20,8 @@
 #define MTK_SIP_DP_CONTROL_AARCH32	0x82000523
 #define MTK_SIP_DP_CONTROL_AARCH64	0xC2000523
 
+/* APUSYS SMC call */
+#define MTK_SIP_APUSYS_CONTROL_AARCH32	0x8200051E
+#define MTK_SIP_APUSYS_CONTROL_AARCH64	0xC200051E
+
 #endif /* PLAT_SIP_CALLS_H */
diff --git a/plat/mediatek/mt8195/include/platform_def.h b/plat/mediatek/mt8195/include/platform_def.h
index 68301d6..d4f2f83 100644
--- a/plat/mediatek/mt8195/include/platform_def.h
+++ b/plat/mediatek/mt8195/include/platform_def.h
@@ -21,6 +21,16 @@
 #define MTK_MCDI_SRAM_BASE	0x11B000
 #define MTK_MCDI_SRAM_MAP_SIZE	0x1000
 
+#define APUSYS_BASE			0x19000000
+#define APUSYS_SCTRL_REVISER_BASE	0x19021000
+#define APUSYS_SCTRL_REVISER_SIZE	0x1000
+#define APUSYS_APU_S_S_4_BASE		0x190F2000
+#define APUSYS_APU_S_S_4_SIZE		0x1000
+#define APUSYS_APU_PLL_BASE		0x190F3000
+#define APUSYS_APU_PLL_SIZE		0x1000
+#define APUSYS_APU_ACC_BASE		0x190F4000
+#define APUSYS_APU_ACC_SIZE		0x1000
+
 #define TOPCKGEN_BASE           (IO_PHYS + 0x00000000)
 #define INFRACFG_AO_BASE        (IO_PHYS + 0x00001000)
 #define SPM_BASE		(IO_PHYS + 0x00006000)
diff --git a/plat/mediatek/mt8195/plat_sip_calls.c b/plat/mediatek/mt8195/plat_sip_calls.c
index ddc7502..7d3c512 100644
--- a/plat/mediatek/mt8195/plat_sip_calls.c
+++ b/plat/mediatek/mt8195/plat_sip_calls.c
@@ -9,6 +9,7 @@
 #include <mt_dp.h>
 #include <mt_spm.h>
 #include <mt_spm_vcorefs.h>
+#include <mtk_apusys.h>
 #include <mtk_sip_svc.h>
 #include <plat_dfd.h>
 #include "plat_sip_calls.h"
@@ -41,6 +42,11 @@
 		ret = dfd_smc_dispatcher(x1, x2, x3, x4);
 		SMC_RET1(handle, ret);
 		break;
+	case MTK_SIP_APUSYS_CONTROL_AARCH32:
+	case MTK_SIP_APUSYS_CONTROL_AARCH64:
+		ret = apusys_kernel_ctrl(x1, x2, x3, x4, &ret_val);
+		SMC_RET2(handle, ret, ret_val);
+		break;
 	default:
 		ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
 		break;
diff --git a/plat/mediatek/mt8195/platform.mk b/plat/mediatek/mt8195/platform.mk
index ef7ff81..72c71fe 100644
--- a/plat/mediatek/mt8195/platform.mk
+++ b/plat/mediatek/mt8195/platform.mk
@@ -14,6 +14,7 @@
                  -I${MTK_PLAT}/common/drivers/timer/              \
                  -I${MTK_PLAT}/common/drivers/uart/               \
                  -I${MTK_PLAT}/common/lpm/                        \
+                 -I${MTK_PLAT_SOC}/drivers/apusys/                \
                  -I${MTK_PLAT_SOC}/drivers/dcm                    \
                  -I${MTK_PLAT_SOC}/drivers/dfd                    \
                  -I${MTK_PLAT_SOC}/drivers/dp/                    \
@@ -59,6 +60,9 @@
                 ${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/apusys/apupll.c               \
+                ${MTK_PLAT_SOC}/drivers/apusys/apupwr_clkctl.c        \
+		${MTK_PLAT_SOC}/drivers/apusys/mtk_apusys.c           \
                 ${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm.c                 \
                 ${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm_utils.c           \
                 ${MTK_PLAT_SOC}/drivers/dfd/plat_dfd.c                \
diff --git a/plat/socionext/synquacer/drivers/scp/sq_scmi.c b/plat/socionext/synquacer/drivers/scp/sq_scmi.c
index e2013cc..0e99256 100644
--- a/plat/socionext/synquacer/drivers/scp/sq_scmi.c
+++ b/plat/socionext/synquacer/drivers/scp/sq_scmi.c
@@ -189,6 +189,11 @@
 /*
  * Helper function to reset the system via SCMI.
  */
+void __dead2 sq_scmi_sys_shutdown(void)
+{
+	sq_scmi_system_off(SCMI_SYS_PWR_SHUTDOWN);
+}
+
 void __dead2 sq_scmi_sys_reboot(void)
 {
 	sq_scmi_system_off(SCMI_SYS_PWR_COLD_RESET);
diff --git a/plat/socionext/synquacer/include/platform_def.h b/plat/socionext/synquacer/include/platform_def.h
index 2f8613a..49ffbf9 100644
--- a/plat/socionext/synquacer/include/platform_def.h
+++ b/plat/socionext/synquacer/include/platform_def.h
@@ -76,6 +76,7 @@
 
 #define SQ_SYS_TIMCTL_BASE		0x2a810000
 #define PLAT_SQ_NSTIMER_FRAME_ID	0
+#define SQ_SYS_CNT_BASE_NS		0x2a830000
 
 #define DRAMINFO_BASE			0x2E00FFC0
 
diff --git a/plat/socionext/synquacer/include/sq_common.h b/plat/socionext/synquacer/include/sq_common.h
index a985822..b09d22a 100644
--- a/plat/socionext/synquacer/include/sq_common.h
+++ b/plat/socionext/synquacer/include/sq_common.h
@@ -45,6 +45,7 @@
 /* SCMI API for power management by SCP */
 void sq_scmi_off(const struct psci_power_state *target_state);
 void sq_scmi_on(u_register_t mpidr);
+void __dead2 sq_scmi_sys_shutdown(void);
 void __dead2 sq_scmi_sys_reboot(void);
 void __dead2 sq_scmi_system_off(int state);
 /* SCMI API for vendor specific protocol */
diff --git a/plat/socionext/synquacer/sq_bl31_setup.c b/plat/socionext/synquacer/sq_bl31_setup.c
index 9723ef9..a7a0ce0 100644
--- a/plat/socionext/synquacer/sq_bl31_setup.c
+++ b/plat/socionext/synquacer/sq_bl31_setup.c
@@ -24,6 +24,20 @@
 IMPORT_SYM(uintptr_t, __SPM_SHIM_EXCEPTIONS_END__,   SPM_SHIM_EXCEPTIONS_END);
 IMPORT_SYM(uintptr_t, __SPM_SHIM_EXCEPTIONS_LMA__,   SPM_SHIM_EXCEPTIONS_LMA);
 
+unsigned int plat_get_syscnt_freq2(void)
+{
+	unsigned int counter_base_frequency;
+
+	/* Read the frequency from Frequency modes table */
+	counter_base_frequency = mmio_read_32(SQ_SYS_CNTCTL_BASE + CNTFID_OFF);
+
+	/* The first entry of the frequency modes table must not be 0 */
+	if (counter_base_frequency == 0)
+		panic();
+
+	return counter_base_frequency;
+}
+
 entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
 {
 	assert(sec_state_is_valid(type));
@@ -119,6 +133,7 @@
 static void sq_configure_sys_timer(void)
 {
 	unsigned int reg_val;
+	unsigned int freq_val = plat_get_syscnt_freq2();
 
 	reg_val = (1 << CNTACR_RPCT_SHIFT) | (1 << CNTACR_RVCT_SHIFT);
 	reg_val |= (1 << CNTACR_RFRQ_SHIFT) | (1 << CNTACR_RVOFF_SHIFT);
@@ -128,6 +143,17 @@
 
 	reg_val = (1 << CNTNSAR_NS_SHIFT(PLAT_SQ_NSTIMER_FRAME_ID));
 	mmio_write_32(SQ_SYS_TIMCTL_BASE + CNTNSAR, reg_val);
+
+	/* Initialize CNTFRQ register in CNTCTLBase frame */
+	mmio_write_32(SQ_SYS_TIMCTL_BASE + CNTCTLBASE_CNTFRQ, freq_val);
+
+	/*
+	 * Initialize CNTFRQ register in Non-secure CNTBase frame.
+	 * This is required for SynQuacer, because it does not
+	 * follow ARM ARM in that the value updated in CNTFRQ is not
+	 * reflected in CNTBASEN_CNTFRQ. Hence update the value manually.
+	 */
+	mmio_write_32(SQ_SYS_CNT_BASE_NS + CNTBASEN_CNTFRQ, freq_val);
 }
 
 void bl31_platform_setup(void)
@@ -184,17 +210,3 @@
 {
 	enable_mmu_el3(flags | XLAT_TABLE_NC);
 }
-
-unsigned int plat_get_syscnt_freq2(void)
-{
-	unsigned int counter_base_frequency;
-
-	/* Read the frequency from Frequency modes table */
-	counter_base_frequency = mmio_read_32(SQ_SYS_CNTCTL_BASE + CNTFID_OFF);
-
-	/* The first entry of the frequency modes table must not be 0 */
-	if (counter_base_frequency == 0)
-		panic();
-
-	return counter_base_frequency;
-}
diff --git a/plat/socionext/synquacer/sq_psci.c b/plat/socionext/synquacer/sq_psci.c
index 4168df9..3062f63 100644
--- a/plat/socionext/synquacer/sq_psci.c
+++ b/plat/socionext/synquacer/sq_psci.c
@@ -113,6 +113,9 @@
 
 void __dead2 sq_system_off(void)
 {
+#if SQ_USE_SCMI_DRIVER
+	sq_scmi_sys_shutdown();
+#else
 	volatile uint32_t *gpio = (uint32_t *)PLAT_SQ_GPIO_BASE;
 
 	/* set PD[9] high to power off the system */
@@ -139,6 +142,7 @@
 	wfi();
 	ERROR("SQ System Off: operation not handled.\n");
 	panic();
+#endif
 }
 
 void __dead2 sq_system_reset(void)
diff --git a/plat/st/common/bl2_io_storage.c b/plat/st/common/bl2_io_storage.c
index b0314d2..6069e5f 100644
--- a/plat/st/common/bl2_io_storage.c
+++ b/plat/st/common/bl2_io_storage.c
@@ -99,7 +99,7 @@
 static const io_dev_connector_t *spi_dev_con;
 #endif
 
-#if STM32MP_USB_PROGRAMMER
+#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER
 static const io_dev_connector_t *memmap_dev_con;
 #endif
 
@@ -136,6 +136,9 @@
 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI:
 		INFO("Using SPI NAND\n");
 		break;
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART:
+		INFO("Using UART\n");
+		break;
 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB:
 		INFO("Using USB\n");
 		break;
@@ -257,7 +260,7 @@
 }
 #endif /* STM32MP_SPI_NAND */
 
-#if STM32MP_USB_PROGRAMMER
+#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER
 static void mmap_io_setup(void)
 {
 	int io_result __unused;
@@ -270,6 +273,21 @@
 	assert(io_result == 0);
 }
 
+#if STM32MP_UART_PROGRAMMER
+static void stm32cubeprogrammer_uart(void)
+{
+	int ret __unused;
+	boot_api_context_t *boot_context =
+		(boot_api_context_t *)stm32mp_get_boot_ctx_address();
+	uintptr_t uart_base;
+
+	uart_base = get_uart_address(boot_context->boot_interface_instance);
+	ret = stm32cubeprog_uart_load(uart_base, DWL_BUFFER_BASE, DWL_BUFFER_SIZE);
+	assert(ret == 0);
+}
+#endif
+
+#if STM32MP_USB_PROGRAMMER
 static void stm32cubeprogrammer_usb(void)
 {
 	int ret __unused;
@@ -282,6 +300,8 @@
 	assert(ret == 0);
 }
 #endif
+#endif /* STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER */
+
 
 void stm32mp_io_setup(void)
 {
@@ -334,8 +354,13 @@
 		boot_spi_nand(boot_context);
 		break;
 #endif
+#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER
+#if STM32MP_UART_PROGRAMMER
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART:
+#endif
 #if STM32MP_USB_PROGRAMMER
 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB:
+#endif
 		dmbsy();
 		mmap_io_setup();
 		break;
@@ -400,6 +425,16 @@
 		break;
 #endif
 
+#if STM32MP_UART_PROGRAMMER
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART:
+		if (image_id == FW_CONFIG_ID) {
+			stm32cubeprogrammer_uart();
+			/* FIP loaded at DWL address */
+			image_block_spec.offset = DWL_BUFFER_BASE;
+			image_block_spec.length = DWL_BUFFER_SIZE;
+		}
+		break;
+#endif
 #if STM32MP_USB_PROGRAMMER
 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB:
 		if (image_id == FW_CONFIG_ID) {
diff --git a/plat/st/common/include/stm32cubeprogrammer.h b/plat/st/common/include/stm32cubeprogrammer.h
index 503d919..0f5a64d 100644
--- a/plat/st/common/include/stm32cubeprogrammer.h
+++ b/plat/st/common/include/stm32cubeprogrammer.h
@@ -24,4 +24,6 @@
 			   uintptr_t ssbl_base,
 			   size_t ssbl_len);
 
+int stm32cubeprog_uart_load(uintptr_t instance, uintptr_t base, size_t len);
+
 #endif /* STM32CUBEPROGRAMMER_H */
diff --git a/plat/st/common/include/stm32mp_common.h b/plat/st/common/include/stm32mp_common.h
index 8a5fe48..9ca5d16 100644
--- a/plat/st/common/include/stm32mp_common.h
+++ b/plat/st/common/include/stm32mp_common.h
@@ -48,6 +48,14 @@
 uint32_t stm32_iwdg_shadow_update(uint32_t iwdg_inst, uint32_t flags);
 #endif
 
+#if STM32MP_UART_PROGRAMMER || !defined(IMAGE_BL2)
+/* Get the UART address from its instance number */
+uintptr_t get_uart_address(uint32_t instance_nb);
+#endif
+
+/* Setup the UART console */
+int stm32mp_uart_console_setup(void);
+
 /*
  * Platform util functions for the GPIO driver
  * @bank: Target GPIO bank ID as per DT bindings
@@ -64,6 +72,7 @@
 uintptr_t stm32_get_gpio_bank_base(unsigned int bank);
 unsigned long stm32_get_gpio_bank_clock(unsigned int bank);
 uint32_t stm32_get_gpio_bank_offset(unsigned int bank);
+bool stm32_gpio_is_secure_at_reset(unsigned int bank);
 
 /* Return node offset for target GPIO bank ID @bank or a FDT error code */
 int stm32_get_gpio_bank_pinctrl_node(void *fdt, unsigned int bank);
@@ -83,15 +92,6 @@
 /* Print board information */
 void stm32mp_print_boardinfo(void);
 
-/*
- * Util for clock gating and to get clock rate for stm32 and platform drivers
- * @id: Target clock ID, ID used in clock DT bindings
- */
-bool stm32mp_clk_is_enabled(unsigned long id);
-void stm32mp_clk_enable(unsigned long id);
-void stm32mp_clk_disable(unsigned long id);
-unsigned long stm32mp_clk_get_rate(unsigned long id);
-
 /* Initialise the IO layer and register platform IO devices */
 void stm32mp_io_setup(void);
 
@@ -109,4 +109,8 @@
 int stm32mp_map_ddr_non_cacheable(void);
 int stm32mp_unmap_ddr(void);
 
+/* Functions to save and get boot peripheral info */
+void stm32_save_boot_interface(uint32_t interface, uint32_t instance);
+void stm32_get_boot_interface(uint32_t *interface, uint32_t *instance);
+
 #endif /* STM32MP_COMMON_H */
diff --git a/plat/st/common/stm32cubeprogrammer_uart.c b/plat/st/common/stm32cubeprogrammer_uart.c
new file mode 100644
index 0000000..46ac9cf
--- /dev/null
+++ b/plat/st/common/stm32cubeprogrammer_uart.c
@@ -0,0 +1,521 @@
+/*
+ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <endian.h>
+#include <errno.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <drivers/st/stm32_iwdg.h>
+#include <drivers/st/stm32_uart.h>
+#include <drivers/st/stm32_uart_regs.h>
+#include <lib/mmio.h>
+#include <tools_share/firmware_image_package.h>
+
+#include <platform_def.h>
+#include <stm32cubeprogrammer.h>
+
+/* USART bootloader protocol version V4.0 */
+#define USART_BL_VERSION	0x40U
+
+/* Command definition */
+#define GET_CMD_COMMAND		0x00U
+#define GET_VER_COMMAND		0x01U
+#define GET_ID_COMMAND		0x02U
+#define PHASE_COMMAND		0x03U
+#define READ_PART_COMMAND	0x12U
+#define START_COMMAND		0x21U
+#define DOWNLOAD_COMMAND	0x31U
+
+/* Answer defines */
+#define INIT_BYTE		0x7FU
+#define ACK_BYTE		0x79U
+#define NACK_BYTE		0x1FU
+#define ABORT			0x5FU
+
+#define UNDEFINED_DOWN_ADDR	U(0xFFFFFFFF)
+#define PROGRAMMER_TIMEOUT_US	20000U
+
+static const uint8_t command_tab[] = {
+	GET_CMD_COMMAND,
+	GET_VER_COMMAND,
+	GET_ID_COMMAND,
+	PHASE_COMMAND,
+	START_COMMAND,
+	DOWNLOAD_COMMAND
+};
+
+/* STM32CubeProgrammer over UART handle */
+struct stm32prog_uart_handle_s {
+	struct stm32_uart_handle_s uart;
+	uint32_t packet;
+	uint8_t *addr;
+	uint32_t len;
+	uint8_t phase;
+	/* Error msg buffer: max 255 in UART protocol, reduced in TF-A */
+	uint8_t error[64];
+} handle;
+
+/* Trace and handle unrecoverable UART protocol error */
+#define STM32PROG_ERROR(...) \
+	{ \
+		ERROR(__VA_ARGS__); \
+		if (handle.phase != PHASE_RESET) { \
+			snprintf((char *)&handle.error, sizeof(handle.error), __VA_ARGS__); \
+			handle.phase = PHASE_RESET; \
+			handle.addr = (uint8_t *)UNDEFINED_DOWN_ADDR; \
+			handle.len = 0U; \
+			handle.packet = 0U; \
+		} \
+	}
+
+static int uart_write(const uint8_t *addr, uint16_t size)
+{
+	while (size != 0U) {
+		if (stm32_uart_putc(&handle.uart, *addr) != 0) {
+			return -EIO;
+		}
+		size--;
+		addr++;
+	}
+
+	return 0;
+}
+
+static int uart_write_8(uint8_t byte)
+{
+	return stm32_uart_putc(&handle.uart, byte);
+}
+
+static int uart_write_32(uint32_t value)
+{
+	return uart_write((uint8_t *)&value, 4U);
+}
+
+static int uart_read_8(uint8_t *byte)
+{
+	int ret;
+	uint64_t timeout_ref = timeout_init_us(PROGRAMMER_TIMEOUT_US);
+
+	do {
+		ret = stm32_uart_getc(&handle.uart);
+		if (ret == -EAGAIN) {
+			if (timeout_elapsed(timeout_ref)) {
+				return -ETIMEDOUT;
+			}
+		} else if (ret < 0) {
+			return ret;
+		}
+	} while (ret == -EAGAIN);
+
+	*byte = (uint8_t)ret;
+
+	return 0;
+}
+
+static int uart_send_result(uint8_t byte)
+{
+	int ret;
+
+	/* Always flush fifo before to send result = read all pending data */
+	do {
+		ret = stm32_uart_getc(&handle.uart);
+	} while (ret >= 0);
+
+	return uart_write_8(byte);
+}
+
+static bool is_valid_header(fip_toc_header_t *header)
+{
+	return (header->name == TOC_HEADER_NAME) &&
+	       (header->serial_number != 0U);
+}
+
+static int uart_receive_command(uint8_t *command)
+{
+	uint8_t byte = 0U;
+	uint8_t xor = 0U;
+	unsigned int count;
+	bool found = false;
+	int ret;
+
+	/* Repeat read until something is received */
+	do {
+		stm32_iwdg_refresh();
+		ret = uart_read_8(&byte);
+	} while (ret == -ETIMEDOUT);
+
+	if (ret != 0) {
+		return ret;
+	}
+
+	/* Handle reconnection request */
+	if (byte == INIT_BYTE) {
+		*command = byte;
+		return 0;
+	}
+
+	for (count = 0U; count < ARRAY_SIZE(command_tab); count++) {
+		if (command_tab[count] == byte) {
+			found = true;
+			break;
+		}
+	}
+	if (!found) {
+		VERBOSE("UART: Command unknown (byte=0x%x)\n", byte);
+		return -EPROTO;
+	}
+
+	ret = uart_read_8(&xor);
+	if (ret != 0) {
+		return ret;
+	}
+	if ((byte ^ xor) != 0xFF) {
+		VERBOSE("UART: Command XOR check fail (byte=0x%x, xor=0x%x)\n",
+			byte, xor);
+		return -EPROTO;
+	}
+
+	*command = byte;
+
+	return 0;
+}
+
+static int get_cmd_command(void)
+{
+	const uint8_t msg[2] = {
+		sizeof(command_tab), /* Length of data - 1 */
+		USART_BL_VERSION
+	};
+	int ret;
+
+	ret = uart_write(msg, sizeof(msg));
+	if (ret != 0) {
+		return ret;
+	}
+
+	return uart_write(command_tab, sizeof(command_tab));
+}
+
+static int get_version_command(void)
+{
+	return uart_write_8(STM32_TF_VERSION);
+}
+
+static int get_id_command(void)
+{
+	uint8_t msg[3] = {
+		sizeof(msg) - 1 /* Length of data - 1 */
+	};
+	uint32_t chip_id = stm32mp_get_chip_dev_id();
+
+	be16enc(&msg[1], chip_id);
+
+	return uart_write(msg, sizeof(msg));
+}
+
+static int uart_send_phase(uint32_t address)
+{
+	int ret;
+	uint8_t msg_size = 5U; /* Length of data - 1 */
+	uint8_t error_size = 0U;
+
+	/* Additional information only for RESET phase */
+	if (handle.phase == PHASE_RESET) {
+		error_size = strnlen((char *)&handle.error, sizeof(handle.error));
+	}
+	ret = uart_write_8(msg_size + error_size);
+	if (ret != 0) {
+		return ret;
+	}
+
+	/* Send the ID of next partition */
+	ret = uart_write_8(handle.phase);
+	if (ret != 0) {
+		return ret;
+	}
+
+	/* Destination address */
+	ret = uart_write_32(address);
+	if (ret != 0) {
+		return ret;
+	}
+
+	ret = uart_write_8(error_size);
+	if (ret != 0) {
+		return ret;
+	}
+
+	/* Additional information: message error */
+	if (error_size > 0U) {
+		ret = uart_write(handle.error, error_size);
+	}
+
+	return ret;
+}
+
+static int uart_download_part(void)
+{
+	uint8_t operation = 0U;
+	uint8_t xor;
+	uint8_t byte = 0U;
+	uint32_t packet_number = 0U;
+	uint32_t packet_size = 0U;
+	uint32_t i = 0U;
+	int ret;
+
+	/* Get operation number */
+	ret = uart_read_8(&operation);
+	if (ret != 0) {
+		return ret;
+	}
+
+	xor = operation;
+
+	/* Get packet number */
+	for (i = 3U; i != 0U; i--) {
+		ret = uart_read_8(&byte);
+		if (ret != 0) {
+			return ret;
+		}
+
+		xor ^= byte;
+		packet_number = (packet_number << 8) | byte;
+	}
+
+	if (packet_number != handle.packet) {
+		WARN("UART: Bad packet number receive: %u, expected %u\n",
+		     packet_number, handle.packet);
+		return -EPROTO;
+	}
+
+	/* Checksum */
+	ret = uart_read_8(&byte);
+	if (ret != 0) {
+		return ret;
+	}
+	if (xor != byte) {
+		VERBOSE("UART: Download Command checksum xor: %x, received %x\n",
+			xor, byte);
+		return -EPROTO;
+	}
+
+	ret = uart_send_result(ACK_BYTE);
+	if (ret != 0) {
+		return ret;
+	}
+
+	ret = uart_read_8(&byte);
+	if (ret != 0) {
+		return ret;
+	}
+	xor = byte;
+	packet_size = byte + 1U;
+	if (handle.len < packet_size) {
+		STM32PROG_ERROR("Download overflow at %p\n", handle.addr + packet_size);
+		return 0;
+	}
+
+	for (i = 0U; i < packet_size; i++) {
+		ret = uart_read_8(&byte);
+		if (ret != 0) {
+			return ret;
+		}
+
+		*(handle.addr + i) = byte;
+		xor ^= byte;
+	}
+
+	/* Checksum */
+	ret = uart_read_8(&byte) != 0;
+	if (ret != 0) {
+		return ret;
+	}
+	if (xor != byte) {
+		VERBOSE("UART: Download Data checksum xor: %x, received %x\n",
+			xor, byte);
+		return -EPROTO;
+	}
+
+	/* Packet treated */
+	handle.packet++;
+	handle.addr += packet_size;
+	handle.len -= packet_size;
+
+	return 0;
+}
+
+static int uart_start_cmd(uintptr_t buffer)
+{
+	uint8_t byte = 0U;
+	uint8_t xor = 0U;
+	uint32_t i;
+	uint32_t start_address = 0U;
+	int ret;
+
+	/* Get address */
+	for (i = 4U; i != 0U; i--) {
+		ret = uart_read_8(&byte);
+		if (ret != 0U) {
+			return ret;
+		}
+
+		xor ^= byte;
+		start_address = (start_address << 8) | byte;
+	}
+
+	/* Checksum */
+	ret = uart_read_8(&byte);
+	if (ret != 0) {
+		return ret;
+	}
+
+	if (xor != byte) {
+		VERBOSE("UART: Start Command checksum xor: %x, received %x\n",
+			xor, byte);
+		return -EPROTO;
+	}
+
+	if (start_address != UNDEFINED_DOWN_ADDR) {
+		STM32PROG_ERROR("Invalid start at %x, for phase %u\n",
+				start_address, handle.phase);
+		return 0;
+	}
+
+	if (!is_valid_header((fip_toc_header_t *)buffer)) {
+		STM32PROG_ERROR("FIP Header check failed %lx, for phase %u\n",
+				buffer, handle.phase);
+		return -EIO;
+	}
+	VERBOSE("FIP header looks OK.\n");
+
+	return 0;
+}
+
+static int uart_read(uint8_t id, uintptr_t buffer, size_t length)
+{
+	bool start_done = false;
+	int ret;
+	uint8_t command = 0U;
+
+	handle.phase = id;
+	handle.packet = 0U;
+	handle.addr = (uint8_t *)buffer;
+	handle.len = length;
+
+	INFO("UART: read phase %u at 0x%lx size 0x%x\n",
+	     id, buffer, length);
+	while (!start_done) {
+		ret = uart_receive_command(&command);
+		if (ret != 0) {
+			/* Delay to wait STM32CubeProgrammer end of transmission */
+			mdelay(3);
+
+			ret = uart_send_result(NACK_BYTE);
+			if (ret != 0U) {
+				return ret;
+			}
+
+			continue;
+		}
+
+		uart_send_result(ACK_BYTE);
+
+		switch (command) {
+		case INIT_BYTE:
+			INFO("UART: Connected\n");
+			/* Nothing to do */
+			continue;
+
+		case GET_CMD_COMMAND:
+			ret = get_cmd_command();
+			break;
+
+		case GET_VER_COMMAND:
+			ret = get_version_command();
+			break;
+
+		case GET_ID_COMMAND:
+			ret = get_id_command();
+			break;
+
+		case PHASE_COMMAND:
+			ret = uart_send_phase((uint32_t)buffer);
+			if ((ret == 0) && (handle.phase == PHASE_RESET)) {
+				start_done = true;
+				INFO("UART: Reset\n");
+			}
+			break;
+
+		case DOWNLOAD_COMMAND:
+			ret = uart_download_part();
+			break;
+
+		case START_COMMAND:
+			ret = uart_start_cmd(buffer);
+			if ((ret == 0) && (handle.phase == id)) {
+				INFO("UART: Start phase %u\n", handle.phase);
+				start_done = true;
+			}
+			break;
+
+		default:
+			WARN("UART: Unknown command\n");
+			ret = -EINVAL;
+			break;
+		}
+
+		if (ret == 0) {
+			ret = uart_send_result(ACK_BYTE);
+		} else {
+			ret = uart_send_result(NACK_BYTE);
+		}
+		if (ret != 0) {
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+/* Init UART: 115200, 8bit 1stop parity even and enable FIFO mode */
+const struct stm32_uart_init_s init = {
+	.baud_rate = U(115200),
+	.word_length = STM32_UART_WORDLENGTH_9B,
+	.stop_bits = STM32_UART_STOPBITS_1,
+	.parity = STM32_UART_PARITY_EVEN,
+	.hw_flow_control = STM32_UART_HWCONTROL_NONE,
+	.mode = STM32_UART_MODE_TX_RX,
+	.over_sampling = STM32_UART_OVERSAMPLING_16,
+	.fifo_mode = STM32_UART_FIFOMODE_EN,
+};
+
+int stm32cubeprog_uart_load(uintptr_t instance, uintptr_t base, size_t len)
+{
+	int ret;
+
+	if (stm32_uart_init(&handle.uart, instance, &init) != 0) {
+		return -EIO;
+	}
+
+	/*
+	 * The following NACK_BYTE is written because STM32CubeProgrammer has
+	 * already sent its command before TF-A has reached this point, and
+	 * because FIFO was not configured by BootROM.
+	 * The byte in the UART_RX register is then the checksum and not the
+	 * command. NACK_BYTE has to be written, so that the programmer will
+	 * re-send the good command.
+	 */
+	ret = uart_send_result(NACK_BYTE);
+	if (ret != 0) {
+		return ret;
+	}
+
+	return uart_read(PHASE_SSBL, base, len);
+}
diff --git a/plat/st/common/stm32mp_common.c b/plat/st/common/stm32mp_common.c
index 9120408..918c289 100644
--- a/plat/st/common/stm32mp_common.c
+++ b/plat/st/common/stm32mp_common.c
@@ -7,17 +7,24 @@
 #include <assert.h>
 #include <errno.h>
 
-#include <platform_def.h>
-
 #include <arch_helpers.h>
 #include <common/debug.h>
+#include <drivers/clk.h>
+#include <drivers/delay_timer.h>
+#include <drivers/st/stm32_console.h>
 #include <drivers/st/stm32mp_clkfunc.h>
+#include <drivers/st/stm32mp_reset.h>
 #include <lib/smccc.h>
 #include <lib/xlat_tables/xlat_tables_v2.h>
 #include <plat/common/platform.h>
 #include <services/arm_arch_svc.h>
 
+#include <platform_def.h>
+
 #define HEADER_VERSION_MAJOR_MASK	GENMASK(23, 16)
+#define RESET_TIMEOUT_US_1MS		1000U
+
+static console_t console;
 
 uintptr_t plat_get_ns_image_entrypoint(void)
 {
@@ -128,6 +135,83 @@
 					   STM32MP_DDR_MAX_SIZE);
 }
 
+#if  defined(IMAGE_BL2)
+static void reset_uart(uint32_t reset)
+{
+	int ret;
+
+	ret = stm32mp_reset_assert(reset, RESET_TIMEOUT_US_1MS);
+	if (ret != 0) {
+		panic();
+	}
+
+	udelay(2);
+
+	ret = stm32mp_reset_deassert(reset, RESET_TIMEOUT_US_1MS);
+	if (ret != 0) {
+		panic();
+	}
+
+	mdelay(1);
+}
+#endif
+
+int stm32mp_uart_console_setup(void)
+{
+	struct dt_node_info dt_uart_info;
+	unsigned int console_flags;
+	uint32_t clk_rate;
+	int result;
+	uint32_t boot_itf __unused;
+	uint32_t boot_instance __unused;
+
+	result = dt_get_stdout_uart_info(&dt_uart_info);
+
+	if ((result <= 0) ||
+	    (dt_uart_info.status == DT_DISABLED) ||
+	    (dt_uart_info.clock < 0) ||
+	    (dt_uart_info.reset < 0)) {
+		return -ENODEV;
+	}
+
+#if STM32MP_UART_PROGRAMMER || !defined(IMAGE_BL2)
+	stm32_get_boot_interface(&boot_itf, &boot_instance);
+
+	if ((boot_itf == BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART) &&
+	    (get_uart_address(boot_instance) == dt_uart_info.base)) {
+		return -EACCES;
+	}
+#endif
+
+#if defined(IMAGE_BL2)
+	if (dt_set_stdout_pinctrl() != 0) {
+		return -ENODEV;
+	}
+#endif
+
+	clk_enable((unsigned long)dt_uart_info.clock);
+
+#if defined(IMAGE_BL2)
+	reset_uart((uint32_t)dt_uart_info.reset);
+#endif
+
+	clk_rate = clk_get_rate((unsigned long)dt_uart_info.clock);
+
+	if (console_stm32_register(dt_uart_info.base, clk_rate,
+				   STM32MP_UART_BAUDRATE, &console) == 0) {
+		panic();
+	}
+
+	console_flags = CONSOLE_FLAG_BOOT | CONSOLE_FLAG_CRASH |
+			CONSOLE_FLAG_TRANSLATE_CRLF;
+#if !defined(IMAGE_BL2) && defined(DEBUG)
+	console_flags |= CONSOLE_FLAG_RUNTIME;
+#endif
+	console_set_scope(&console, console_flags);
+
+	return 0;
+}
+
 /*****************************************************************************
  * plat_is_smccc_feature_available() - This function checks whether SMCCC
  *                                     feature is availabile for platform.
diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c
index 7eaf0ed..512afa8 100644
--- a/plat/st/stm32mp1/bl2_plat_setup.c
+++ b/plat/st/stm32mp1/bl2_plat_setup.c
@@ -8,23 +8,19 @@
 #include <errno.h>
 #include <string.h>
 
-#include <platform_def.h>
-
 #include <arch_helpers.h>
 #include <common/bl_common.h>
 #include <common/debug.h>
 #include <common/desc_image_load.h>
-#include <drivers/delay_timer.h>
 #include <drivers/generic_delay_timer.h>
 #include <drivers/mmc.h>
 #include <drivers/st/bsec.h>
-#include <drivers/st/stm32_console.h>
 #include <drivers/st/stm32_iwdg.h>
-#include <drivers/st/stm32mp_pmic.h>
-#include <drivers/st/stm32mp_reset.h>
+#include <drivers/st/stm32_uart.h>
 #include <drivers/st/stm32mp1_clk.h>
 #include <drivers/st/stm32mp1_pwr.h>
 #include <drivers/st/stm32mp1_ram.h>
+#include <drivers/st/stm32mp_pmic.h>
 #include <lib/fconf/fconf.h>
 #include <lib/fconf/fconf_dyn_cfg_getter.h>
 #include <lib/mmio.h>
@@ -32,12 +28,9 @@
 #include <lib/xlat_tables/xlat_tables_v2.h>
 #include <plat/common/platform.h>
 
-#include <stm32mp1_context.h>
+#include <platform_def.h>
 #include <stm32mp1_dbgmcu.h>
 
-#define RESET_TIMEOUT_US_1MS		1000U
-
-static console_t console;
 static struct stm32mp_auth_ops stm32mp1_auth_ops;
 
 static void print_reset_reason(void)
@@ -167,11 +160,9 @@
 void bl2_el3_plat_arch_setup(void)
 {
 	int32_t result;
-	struct dt_node_info dt_uart_info;
 	const char *board_model;
 	boot_api_context_t *boot_context =
 		(boot_api_context_t *)stm32mp_get_boot_ctx_address();
-	uint32_t clk_rate;
 	uintptr_t pwr_base;
 	uintptr_t rcc_base;
 
@@ -238,6 +229,16 @@
 
 	generic_delay_timer_init();
 
+#if STM32MP_UART_PROGRAMMER
+	/* Disable programmer UART before changing clock tree */
+	if (boot_context->boot_interface_selected ==
+	    BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART) {
+		uintptr_t uart_prog_addr =
+			get_uart_address(boot_context->boot_interface_instance);
+
+		stm32_uart_stop(uart_prog_addr);
+	}
+#endif
 	if (stm32mp1_clk_probe() < 0) {
 		panic();
 	}
@@ -248,45 +249,18 @@
 
 	stm32mp1_syscfg_init();
 
-	result = dt_get_stdout_uart_info(&dt_uart_info);
+	stm32_save_boot_interface(boot_context->boot_interface_selected,
+				  boot_context->boot_interface_instance);
 
-	if ((result <= 0) ||
-	    (dt_uart_info.status == 0U) ||
-	    (dt_uart_info.clock < 0) ||
-	    (dt_uart_info.reset < 0)) {
-		goto skip_console_init;
-	}
+#if STM32MP_USB_PROGRAMMER
+	/* Deconfigure all UART RX pins configured by ROM code */
+	stm32mp1_deconfigure_uart_pins();
+#endif
 
-	if (dt_set_stdout_pinctrl() != 0) {
+	if (stm32mp_uart_console_setup() != 0) {
 		goto skip_console_init;
 	}
 
-	stm32mp_clk_enable((unsigned long)dt_uart_info.clock);
-
-	if (stm32mp_reset_assert((uint32_t)dt_uart_info.reset,
-				 RESET_TIMEOUT_US_1MS) != 0) {
-		panic();
-	}
-
-	udelay(2);
-
-	if (stm32mp_reset_deassert((uint32_t)dt_uart_info.reset,
-				   RESET_TIMEOUT_US_1MS) != 0) {
-		panic();
-	}
-
-	mdelay(1);
-
-	clk_rate = stm32mp_clk_get_rate((unsigned long)dt_uart_info.clock);
-
-	if (console_stm32_register(dt_uart_info.base, clk_rate,
-				   STM32MP_UART_BAUDRATE, &console) == 0) {
-		panic();
-	}
-
-	console_set_scope(&console, CONSOLE_FLAG_BOOT |
-			  CONSOLE_FLAG_CRASH | CONSOLE_FLAG_TRANSLATE_CRLF);
-
 	stm32mp_print_cpuinfo();
 
 	board_model = dt_get_board_model();
@@ -314,12 +288,6 @@
 		INFO("IWDG2 freeze error : %i\n", result);
 	}
 
-	if (stm32_save_boot_interface(boot_context->boot_interface_selected,
-				      boot_context->boot_interface_instance) !=
-	    0) {
-		ERROR("Cannot save boot interface\n");
-	}
-
 	stm32mp1_auth_ops.check_key = boot_context->bootrom_ecdsa_check_key;
 	stm32mp1_auth_ops.verify_signature =
 		boot_context->bootrom_ecdsa_verify_signature;
@@ -352,6 +320,7 @@
 	const struct dyn_cfg_dtb_info_t *config_info;
 	bl_mem_params_node_t *tos_fw_mem_params;
 	unsigned int i;
+	unsigned int idx;
 	unsigned long long ddr_top __unused;
 	const unsigned int image_ids[] = {
 		BL32_IMAGE_ID,
@@ -370,8 +339,14 @@
 		set_config_info(STM32MP_FW_CONFIG_BASE, STM32MP_FW_CONFIG_MAX_SIZE, FW_CONFIG_ID);
 		fconf_populate("FW_CONFIG", STM32MP_FW_CONFIG_BASE);
 
+		idx = dyn_cfg_dtb_info_get_index(TOS_FW_CONFIG_ID);
+
 		/* Iterate through all the fw config IDs */
 		for (i = 0U; i < ARRAY_SIZE(image_ids); i++) {
+			if ((image_ids[i] == TOS_FW_CONFIG_ID) && (idx == FCONF_INVALID_IDX)) {
+				continue;
+			}
+
 			bl_mem_params = get_bl_mem_params_node(image_ids[i]);
 			assert(bl_mem_params != NULL);
 
@@ -493,12 +468,13 @@
 	uint16_t boot_itf = stm32mp_get_boot_itf_selected();
 
 	switch (boot_itf) {
-#if STM32MP_USB_PROGRAMMER
+#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART:
 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB:
 		/* Invalidate the downloaded buffer used with io_memmap */
 		inv_dcache_range(DWL_BUFFER_BASE, DWL_BUFFER_SIZE);
 		break;
-#endif
+#endif /* STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER */
 	default:
 		/* Do nothing in default case */
 		break;
diff --git a/plat/st/stm32mp1/include/boot_api.h b/plat/st/stm32mp1/include/boot_api.h
index 52b1d1a..198ffa9 100644
--- a/plat/st/stm32mp1/include/boot_api.h
+++ b/plat/st/stm32mp1/include/boot_api.h
@@ -39,6 +39,9 @@
 /* Boot occurred on QSPI NOR */
 #define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI		0x4U
 
+/* Boot occurred on UART */
+#define BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART		0x5U
+
 /* Boot occurred on USB */
 #define BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB		0x6U
 
diff --git a/plat/st/stm32mp1/include/stm32mp1_context.h b/plat/st/stm32mp1/include/stm32mp1_context.h
deleted file mode 100644
index 698415a..0000000
--- a/plat/st/stm32mp1/include/stm32mp1_context.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef STM32MP1_CONTEXT_H
-#define STM32MP1_CONTEXT_H
-
-#include <stdint.h>
-
-int stm32_save_boot_interface(uint32_t interface, uint32_t instance);
-
-#endif /* STM32MP1_CONTEXT_H */
diff --git a/plat/st/stm32mp1/include/stm32mp1_private.h b/plat/st/stm32mp1/include/stm32mp1_private.h
index 729d233..2eec16f 100644
--- a/plat/st/stm32mp1/include/stm32mp1_private.h
+++ b/plat/st/stm32mp1/include/stm32mp1_private.h
@@ -21,6 +21,8 @@
 void stm32mp1_syscfg_enable_io_compensation(void);
 void stm32mp1_syscfg_disable_io_compensation(void);
 
+void stm32mp1_deconfigure_uart_pins(void);
+
 #if STM32MP_USE_STM32IMAGE
 uint32_t stm32mp_get_ddr_ns_size(void);
 #endif /* STM32MP_USE_STM32IMAGE */
diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk
index badc926..aa91646 100644
--- a/plat/st/stm32mp1/platform.mk
+++ b/plat/st/stm32mp1/platform.mk
@@ -28,6 +28,8 @@
 TF_CFLAGS		+=	-mfloat-abi=soft
 endif
 
+TF_CFLAGS		+=	-Wsign-compare
+
 # Not needed for Cortex-A7
 WORKAROUND_CVE_2017_5715:=	0
 
@@ -55,6 +57,7 @@
 
 # Serial boot devices
 STM32MP_USB_PROGRAMMER	?=	0
+STM32MP_UART_PROGRAMMER	?=	0
 
 # Device tree
 DTB_FILE_NAME		?=	stm32mp157c-ev1.dtb
@@ -123,34 +126,38 @@
 # Enable flags for C files
 $(eval $(call assert_booleans,\
 	$(sort \
+		PLAT_XLAT_TABLES_DYNAMIC \
 		STM32MP_EMMC \
-		STM32MP_SDMMC \
+		STM32MP_EMMC_BOOT \
 		STM32MP_RAW_NAND \
+		STM32MP_SDMMC \
 		STM32MP_SPI_NAND \
 		STM32MP_SPI_NOR \
-		STM32MP_EMMC_BOOT \
-		PLAT_XLAT_TABLES_DYNAMIC \
+		STM32MP_UART_PROGRAMMER \
 		STM32MP_USB_PROGRAMMER \
 		STM32MP_USE_STM32IMAGE \
 )))
 
 $(eval $(call assert_numerics,\
 	$(sort \
-		STM32_TF_A_COPIES \
 		PLAT_PARTITION_MAX_ENTRIES \
+		STM32_TF_A_COPIES \
+		STM32_TF_VERSION \
 )))
 
 $(eval $(call add_defines,\
 	$(sort \
+		PLAT_PARTITION_MAX_ENTRIES \
+		PLAT_XLAT_TABLES_DYNAMIC \
+		STM32_TF_A_COPIES \
+		STM32_TF_VERSION \
 		STM32MP_EMMC \
-		STM32MP_SDMMC \
+		STM32MP_EMMC_BOOT \
 		STM32MP_RAW_NAND \
+		STM32MP_SDMMC \
 		STM32MP_SPI_NAND \
 		STM32MP_SPI_NOR \
-		STM32MP_EMMC_BOOT \
-		PLAT_XLAT_TABLES_DYNAMIC \
-		STM32_TF_A_COPIES \
-		PLAT_PARTITION_MAX_ENTRIES \
+		STM32MP_UART_PROGRAMMER \
 		STM32MP_USB_PROGRAMMER \
 		STM32MP_USE_STM32IMAGE \
 )))
@@ -182,6 +189,7 @@
 PLAT_BL_COMMON_SOURCES	+=	lib/cpus/aarch32/cortex_a7.S
 
 PLAT_BL_COMMON_SOURCES	+=	drivers/arm/tzc/tzc400.c				\
+				drivers/clk/clk.c					\
 				drivers/delay_timer/delay_timer.c			\
 				drivers/delay_timer/generic_delay_timer.c		\
 				drivers/st/bsec/bsec.c					\
@@ -195,7 +203,6 @@
 				drivers/st/pmic/stpmic1.c				\
 				drivers/st/reset/stm32mp1_reset.c			\
 				plat/st/common/stm32mp_dt.c				\
-				plat/st/stm32mp1/stm32mp1_context.c			\
 				plat/st/stm32mp1/stm32mp1_dbgmcu.c			\
 				plat/st/stm32mp1/stm32mp1_helper.S			\
 				plat/st/stm32mp1/stm32mp1_syscfg.c
@@ -260,11 +267,19 @@
 BL2_SOURCES		+=	plat/st/stm32mp1/stm32mp1_boot_device.c
 endif
 
+ifneq ($(filter 1,${STM32MP_UART_PROGRAMMER} ${STM32MP_USB_PROGRAMMER}),)
+BL2_SOURCES		+=	drivers/io/io_memmap.c
+endif
+
+ifeq (${STM32MP_UART_PROGRAMMER},1)
+BL2_SOURCES		+=	drivers/st/uart/stm32_uart.c				\
+				plat/st/common/stm32cubeprogrammer_uart.c
+endif
+
 ifeq (${STM32MP_USB_PROGRAMMER},1)
 #The DFU stack uses only one end point, reduce the USB stack footprint
 $(eval $(call add_define_val,CONFIG_USBD_EP_NB,1U))
-BL2_SOURCES		+=	drivers/io/io_memmap.c					\
-				drivers/st/usb/stm32mp1_usb.c				\
+BL2_SOURCES		+=	drivers/st/usb/stm32mp1_usb.c				\
 				drivers/usb/usb_device.c				\
 				plat/st/common/stm32cubeprogrammer_usb.c		\
 				plat/st/common/usb_dfu.c					\
@@ -295,6 +310,7 @@
 	    [ ${STM32MP_RAW_NAND} != 1 ] && \
 	    [ ${STM32MP_SPI_NAND} != 1 ] && \
 	    [ ${STM32MP_SPI_NOR} != 1 ] && \
+	    [ ${STM32MP_UART_PROGRAMMER} != 1 ] && \
 	    [ ${STM32MP_USB_PROGRAMMER} != 1 ]; then \
 		echo "No boot device driver is enabled"; \
 		false; \
diff --git a/plat/st/stm32mp1/sp_min/sp_min_setup.c b/plat/st/stm32mp1/sp_min/sp_min_setup.c
index 1495e02..8106795 100644
--- a/plat/st/stm32mp1/sp_min/sp_min_setup.c
+++ b/plat/st/stm32mp1/sp_min/sp_min_setup.c
@@ -18,7 +18,6 @@
 #include <drivers/generic_delay_timer.h>
 #include <drivers/st/bsec.h>
 #include <drivers/st/etzpc.h>
-#include <drivers/st/stm32_console.h>
 #include <drivers/st/stm32_gpio.h>
 #include <drivers/st/stm32_iwdg.h>
 #include <drivers/st/stm32mp1_clk.h>
@@ -36,8 +35,6 @@
  ******************************************************************************/
 static entry_point_info_t bl33_image_ep_info;
 
-static console_t console;
-
 /*******************************************************************************
  * Interrupt handler for FIQ (secure IRQ)
  ******************************************************************************/
@@ -115,8 +112,6 @@
 void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1,
 				  u_register_t arg2, u_register_t arg3)
 {
-	struct dt_node_info dt_uart_info;
-	int result;
 	bl_params_t *params_from_bl2 = (bl_params_t *)arg0;
 #if STM32MP_USE_STM32IMAGE
 	uintptr_t dt_addr = STM32MP_DTB_BASE;
@@ -174,24 +169,7 @@
 		panic();
 	}
 
-	result = dt_get_stdout_uart_info(&dt_uart_info);
-
-	if ((result > 0) && (dt_uart_info.status != 0U)) {
-		unsigned int console_flags;
-
-		if (console_stm32_register(dt_uart_info.base, 0,
-					   STM32MP_UART_BAUDRATE, &console) ==
-		    0) {
-			panic();
-		}
-
-		console_flags = CONSOLE_FLAG_BOOT | CONSOLE_FLAG_CRASH |
-			CONSOLE_FLAG_TRANSLATE_CRLF;
-#ifdef DEBUG
-		console_flags |= CONSOLE_FLAG_RUNTIME;
-#endif
-		console_set_scope(&console, console_flags);
-	}
+	(void)stm32mp_uart_console_setup();
 
 	stm32mp1_etzpc_early_setup();
 }
diff --git a/plat/st/stm32mp1/stm32mp1_context.c b/plat/st/stm32mp1/stm32mp1_context.c
deleted file mode 100644
index cf8a91e..0000000
--- a/plat/st/stm32mp1/stm32mp1_context.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <errno.h>
-
-#include <platform_def.h>
-
-#include <drivers/st/stm32mp1_clk.h>
-#include <dt-bindings/clock/stm32mp1-clks.h>
-#include <lib/mmio.h>
-
-#include <stm32mp1_context.h>
-
-#define TAMP_BOOT_ITF_BACKUP_REG_ID	U(20)
-#define TAMP_BOOT_ITF_MASK		U(0x0000FF00)
-#define TAMP_BOOT_ITF_SHIFT		8
-
-int stm32_save_boot_interface(uint32_t interface, uint32_t instance)
-{
-	uint32_t bkpr_itf_idx = tamp_bkpr(TAMP_BOOT_ITF_BACKUP_REG_ID);
-
-	stm32mp_clk_enable(RTCAPB);
-
-	mmio_clrsetbits_32(bkpr_itf_idx,
-			   TAMP_BOOT_ITF_MASK,
-			   ((interface << 4) | (instance & 0xFU)) <<
-			   TAMP_BOOT_ITF_SHIFT);
-
-	stm32mp_clk_disable(RTCAPB);
-
-	return 0;
-}
diff --git a/plat/st/stm32mp1/stm32mp1_fconf_firewall.c b/plat/st/stm32mp1/stm32mp1_fconf_firewall.c
index caf9ff1..a1969eb 100644
--- a/plat/st/stm32mp1/stm32mp1_fconf_firewall.c
+++ b/plat/st/stm32mp1/stm32mp1_fconf_firewall.c
@@ -9,7 +9,7 @@
 #include <common/debug.h>
 #include <common/fdt_wrappers.h>
 #include <drivers/arm/tzc400.h>
-#include <drivers/st/stm32mp1_clk.h>
+#include <drivers/clk.h>
 #include <dt-bindings/clock/stm32mp1-clks.h>
 #include <lib/fconf/fconf.h>
 #include <lib/object_pool.h>
@@ -31,8 +31,8 @@
 
 void stm32mp1_arch_security_setup(void)
 {
-	stm32mp_clk_enable(TZC1);
-	stm32mp_clk_enable(TZC2);
+	clk_enable(TZC1);
+	clk_enable(TZC2);
 
 	tzc400_init(STM32MP1_TZC_BASE);
 	tzc400_disable_filters();
diff --git a/plat/st/stm32mp1/stm32mp1_pm.c b/plat/st/stm32mp1/stm32mp1_pm.c
index 31a9ae7..ed4d5e5 100644
--- a/plat/st/stm32mp1/stm32mp1_pm.c
+++ b/plat/st/stm32mp1/stm32mp1_pm.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -14,7 +14,7 @@
 #include <common/debug.h>
 #include <drivers/arm/gic_common.h>
 #include <drivers/arm/gicv2.h>
-#include <drivers/st/stm32mp1_clk.h>
+#include <drivers/clk.h>
 #include <dt-bindings/clock/stm32mp1-clks.h>
 #include <lib/mmio.h>
 #include <lib/psci/psci.h>
@@ -74,7 +74,7 @@
 		return PSCI_E_INVALID_ADDRESS;
 	}
 
-	stm32mp_clk_enable(RTCAPB);
+	clk_enable(RTCAPB);
 
 	cntfrq_core0 = read_cntfrq_el0();
 
@@ -84,7 +84,7 @@
 	/* Write magic number in backup register */
 	mmio_write_32(bkpr_core1_magic, BOOT_API_A7_CORE1_MAGIC_NUMBER);
 
-	stm32mp_clk_disable(RTCAPB);
+	clk_disable(RTCAPB);
 
 	/* Generate an IT to core 1 */
 	gicv2_raise_sgi(ARM_IRQ_SEC_SGI_0, STM32MP_SECONDARY_CPU);
diff --git a/plat/st/stm32mp1/stm32mp1_private.c b/plat/st/stm32mp1/stm32mp1_private.c
index e4065c1..e58528e 100644
--- a/plat/st/stm32mp1/stm32mp1_private.c
+++ b/plat/st/stm32mp1/stm32mp1_private.c
@@ -6,13 +6,15 @@
 
 #include <assert.h>
 
+#include <drivers/clk.h>
+#include <drivers/st/stm32_gpio.h>
+#include <drivers/st/stm32_iwdg.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
 #include <libfdt.h>
 
 #include <platform_def.h>
 
-#include <drivers/st/stm32_iwdg.h>
-#include <lib/xlat_tables/xlat_tables_v2.h>
-
 /* Internal layout of the 32bit OTP word board_id */
 #define BOARD_ID_BOARD_NB_MASK		GENMASK(31, 16)
 #define BOARD_ID_BOARD_NB_SHIFT		16
@@ -34,6 +36,10 @@
 					 BOARD_ID_VARFG_SHIFT)
 #define BOARD_ID2BOM(_id)		((_id) & BOARD_ID_BOM_MASK)
 
+#define TAMP_BOOT_MODE_BACKUP_REG_ID	U(20)
+#define TAMP_BOOT_MODE_ITF_MASK		U(0x0000FF00)
+#define TAMP_BOOT_MODE_ITF_SHIFT	8
+
 #if defined(IMAGE_BL2)
 #define MAP_SEC_SYSRAM	MAP_REGION_FLAT(STM32MP_SYSRAM_BASE, \
 					STM32MP_SYSRAM_SIZE, \
@@ -120,6 +126,15 @@
 	return bank * GPIO_BANK_OFFSET;
 }
 
+bool stm32_gpio_is_secure_at_reset(unsigned int bank)
+{
+	if (bank == GPIO_BANK_Z) {
+		return true;
+	}
+
+	return false;
+}
+
 unsigned long stm32_get_gpio_bank_clock(unsigned int bank)
 {
 	if (bank == GPIO_BANK_Z) {
@@ -151,7 +166,80 @@
 	default:
 		panic();
 	}
+}
+
+#if STM32MP_UART_PROGRAMMER || !defined(IMAGE_BL2)
+/*
+ * UART Management
+ */
+static const uintptr_t stm32mp1_uart_addresses[8] = {
+	USART1_BASE,
+	USART2_BASE,
+	USART3_BASE,
+	UART4_BASE,
+	UART5_BASE,
+	USART6_BASE,
+	UART7_BASE,
+	UART8_BASE,
+};
+
+uintptr_t get_uart_address(uint32_t instance_nb)
+{
+	if ((instance_nb == 0U) ||
+	    (instance_nb > ARRAY_SIZE(stm32mp1_uart_addresses))) {
+		return 0U;
+	}
+
+	return stm32mp1_uart_addresses[instance_nb - 1U];
 }
+#endif
+
+#if STM32MP_USB_PROGRAMMER
+struct gpio_bank_pin_list {
+	uint32_t bank;
+	uint32_t pin;
+};
+
+static const struct gpio_bank_pin_list gpio_list[] = {
+	{	/* USART2_RX: GPIOA3 */
+		.bank = 0U,
+		.pin = 3U,
+	},
+	{	/* USART3_RX: GPIOB12 */
+		.bank = 1U,
+		.pin = 12U,
+	},
+	{	/* UART4_RX: GPIOB2 */
+		.bank = 1U,
+		.pin = 2U,
+	},
+	{	/* UART5_RX: GPIOB4 */
+		.bank = 1U,
+		.pin = 5U,
+	},
+	{	/* USART6_RX: GPIOC7 */
+		.bank = 2U,
+		.pin = 7U,
+	},
+	{	/* UART7_RX: GPIOF6 */
+		.bank = 5U,
+		.pin = 6U,
+	},
+	{	/* UART8_RX: GPIOE0 */
+		.bank = 4U,
+		.pin = 0U,
+	},
+};
+
+void stm32mp1_deconfigure_uart_pins(void)
+{
+	size_t i;
+
+	for (i = 0U; i < ARRAY_SIZE(gpio_list); i++) {
+		set_gpio_reset_cfg(gpio_list[i].bank, gpio_list[i].pin);
+	}
+}
+#endif
 
 uint32_t stm32mp_get_chip_version(void)
 {
@@ -474,3 +562,36 @@
 	return ddr_ns_size;
 }
 #endif /* STM32MP_USE_STM32IMAGE */
+
+void stm32_save_boot_interface(uint32_t interface, uint32_t instance)
+{
+	uint32_t bkpr_itf_idx = tamp_bkpr(TAMP_BOOT_MODE_BACKUP_REG_ID);
+
+	clk_enable(RTCAPB);
+
+	mmio_clrsetbits_32(bkpr_itf_idx,
+			   TAMP_BOOT_MODE_ITF_MASK,
+			   ((interface << 4) | (instance & 0xFU)) <<
+			   TAMP_BOOT_MODE_ITF_SHIFT);
+
+	clk_disable(RTCAPB);
+}
+
+void stm32_get_boot_interface(uint32_t *interface, uint32_t *instance)
+{
+	static uint32_t itf;
+
+	if (itf == 0U) {
+		uint32_t bkpr = tamp_bkpr(TAMP_BOOT_MODE_BACKUP_REG_ID);
+
+		clk_enable(RTCAPB);
+
+		itf = (mmio_read_32(bkpr) & TAMP_BOOT_MODE_ITF_MASK) >>
+			TAMP_BOOT_MODE_ITF_SHIFT;
+
+		clk_disable(RTCAPB);
+	}
+
+	*interface = itf >> 4;
+	*instance = itf & 0xFU;
+}
diff --git a/plat/st/stm32mp1/stm32mp1_scmi.c b/plat/st/stm32mp1/stm32mp1_scmi.c
index 6d60bd4..98585dc 100644
--- a/plat/st/stm32mp1/stm32mp1_scmi.c
+++ b/plat/st/stm32mp1/stm32mp1_scmi.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2020, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -8,6 +8,7 @@
 
 #include <platform_def.h>
 
+#include <drivers/clk.h>
 #include <drivers/scmi-msg.h>
 #include <drivers/scmi.h>
 #include <drivers/st/stm32mp1_clk.h>
@@ -274,7 +275,7 @@
 	if (array == NULL) {
 		*nb_elts = 1U;
 	} else if (*nb_elts == 1U) {
-		*array = stm32mp_clk_get_rate(clock->clock_id);
+		*array = clk_get_rate(clock->clock_id);
 	} else {
 		return SCMI_GENERIC_ERROR;
 	}
@@ -292,7 +293,7 @@
 		return 0U;
 	}
 
-	return stm32mp_clk_get_rate(clock->clock_id);
+	return clk_get_rate(clock->clock_id);
 }
 
 int32_t plat_scmi_clock_get_state(unsigned int agent_id, unsigned int scmi_id)
@@ -323,13 +324,13 @@
 	if (enable_not_disable) {
 		if (!clock->enabled) {
 			VERBOSE("SCMI clock %u enable\n", scmi_id);
-			stm32mp_clk_enable(clock->clock_id);
+			clk_enable(clock->clock_id);
 			clock->enabled = true;
 		}
 	} else {
 		if (clock->enabled) {
 			VERBOSE("SCMI clock %u disable\n", scmi_id);
-			stm32mp_clk_disable(clock->clock_id);
+			clk_disable(clock->clock_id);
 			clock->enabled = false;
 		}
 	}
@@ -461,7 +462,7 @@
 			/* Sync SCMI clocks with their targeted initial state */
 			if (clk->enabled &&
 			    stm32mp_nsec_can_access_clock(clk->clock_id)) {
-				stm32mp_clk_enable(clk->clock_id);
+				clk_enable(clk->clock_id);
 			}
 		}
 
diff --git a/plat/st/stm32mp1/stm32mp1_security.c b/plat/st/stm32mp1/stm32mp1_security.c
index 19ef4f0..c84bffc 100644
--- a/plat/st/stm32mp1/stm32mp1_security.c
+++ b/plat/st/stm32mp1/stm32mp1_security.c
@@ -10,6 +10,7 @@
 
 #include <common/debug.h>
 #include <drivers/arm/tzc400.h>
+#include <drivers/clk.h>
 #include <drivers/st/stm32mp1_clk.h>
 #include <dt-bindings/clock/stm32mp1-clks.h>
 #include <dt-bindings/soc/stm32mp15-tzc400.h>
@@ -106,8 +107,8 @@
  ******************************************************************************/
 static void early_init_tzc400(void)
 {
-	stm32mp_clk_enable(TZC1);
-	stm32mp_clk_enable(TZC2);
+	clk_enable(TZC1);
+	clk_enable(TZC2);
 
 	/* Region 0 set to cover all DRAM secure at 0xC000_0000 */
 	init_tzc400_begin(TZC_REGION_S_RDWR);
diff --git a/plat/xilinx/versal/bl31_versal_setup.c b/plat/xilinx/versal/bl31_versal_setup.c
index 8b8714c..60f7449 100644
--- a/plat/xilinx/versal/bl31_versal_setup.c
+++ b/plat/xilinx/versal/bl31_versal_setup.c
@@ -46,11 +46,11 @@
  */
 static inline void bl31_set_default_config(void)
 {
-	bl32_image_ep_info.pc = BL32_BASE;
-	bl32_image_ep_info.spsr = arm_get_spsr_for_bl32_entry();
-	bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
-	bl33_image_ep_info.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX,
-					DISABLE_ALL_EXCEPTIONS);
+	bl32_image_ep_info.pc = (uintptr_t)BL32_BASE;
+	bl32_image_ep_info.spsr = (uint32_t)arm_get_spsr_for_bl32_entry();
+	bl33_image_ep_info.pc = (uintptr_t)plat_get_ns_image_entrypoint();
+	bl33_image_ep_info.spsr = (uint32_t)SPSR_64(MODE_EL2, MODE_SP_ELX,
+						    DISABLE_ALL_EXCEPTIONS);
 }
 
 /*
@@ -64,26 +64,29 @@
 {
 	uint64_t atf_handoff_addr;
 
-	if (VERSAL_CONSOLE_IS(pl011)) {
+	if (VERSAL_CONSOLE_IS(pl011) || (VERSAL_CONSOLE_IS(pl011_1))) {
 		static console_t versal_runtime_console;
 		/* Initialize the console to provide early debug support */
-		int rc = console_pl011_register(VERSAL_UART_BASE,
-						VERSAL_UART_CLOCK,
-						VERSAL_UART_BAUDRATE,
+		int rc = console_pl011_register((unsigned long)VERSAL_UART_BASE,
+						(unsigned int)VERSAL_UART_CLOCK,
+						(unsigned int)VERSAL_UART_BAUDRATE,
 						&versal_runtime_console);
 		if (rc == 0) {
 			panic();
 		}
 
-		console_set_scope(&versal_runtime_console, CONSOLE_FLAG_BOOT |
-				  CONSOLE_FLAG_RUNTIME);
+		console_set_scope(&versal_runtime_console, (unsigned int)(CONSOLE_FLAG_BOOT |
+				  CONSOLE_FLAG_RUNTIME));
 	} else if (VERSAL_CONSOLE_IS(dcc)) {
 		/* Initialize the dcc console for debug */
 		int rc = console_dcc_register();
 		if (rc == 0) {
 			panic();
 		}
+	} else {
+		NOTICE("BL31: Did not register for any console.\n");
 	}
+
 	/* Initialize the platform config for future decision making */
 	versal_config_setup();
 	/* There are no parameters from BL2 if BL31 is a reset vector */
@@ -111,6 +114,8 @@
 		bl31_set_default_config();
 	} else if (ret != FSBL_HANDOFF_SUCCESS) {
 		panic();
+	} else {
+		ERROR("BL31: Error during fsbl-atf handover %d.\n", ret);
 	}
 
 	NOTICE("BL31: Secure code at 0x%lx\n", bl32_image_ep_info.pc);
@@ -122,7 +127,7 @@
 int request_intr_type_el3(uint32_t id, interrupt_type_handler_t handler)
 {
 	/* Validate 'handler'*/
-	if (!handler) {
+	if (handler == NULL) {
 		return -EINVAL;
 	}
 
@@ -145,7 +150,7 @@
 	}
 
 	handler = type_el3_interrupt_handler;
-	if (handler) {
+	if (handler != NULL) {
 		return handler(intr_id, flags, handle, cookie);
 	}
 
@@ -161,12 +166,12 @@
 void bl31_plat_runtime_setup(void)
 {
 	uint64_t flags = 0;
-	uint64_t rc;
+	int32_t rc;
 
 	set_interrupt_rm_flag(flags, NON_SECURE);
 	rc = register_interrupt_type_handler(INTR_TYPE_EL3,
 					     rdo_el3_interrupt_handler, flags);
-	if (rc) {
+	if (rc != 0) {
 		panic();
 	}
 }
diff --git a/plat/xilinx/versal/include/platform_def.h b/plat/xilinx/versal/include/platform_def.h
index 8b513ef..83e5083 100644
--- a/plat/xilinx/versal/include/platform_def.h
+++ b/plat/xilinx/versal/include/platform_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -18,9 +18,9 @@
 #define PLATFORM_STACK_SIZE	0x440
 
 #define PLATFORM_CORE_COUNT		U(2)
-#define PLAT_MAX_PWR_LVL		1
-#define PLAT_MAX_RET_STATE		1
-#define PLAT_MAX_OFF_STATE		2
+#define PLAT_MAX_PWR_LVL		U(1)
+#define PLAT_MAX_RET_STATE		U(1)
+#define PLAT_MAX_OFF_STATE		U(2)
 
 /*******************************************************************************
  * BL31 specific defines.
@@ -31,8 +31,8 @@
  * little space for growth.
  */
 #ifndef VERSAL_ATF_MEM_BASE
-# define BL31_BASE			0xfffe0000
-# define BL31_LIMIT			0xffffffff
+# define BL31_BASE			U(0xfffe0000)
+# define BL31_LIMIT			U(0xffffffff)
 #else
 # define BL31_BASE			(VERSAL_ATF_MEM_BASE)
 # define BL31_LIMIT			(VERSAL_ATF_MEM_BASE + VERSAL_ATF_MEM_SIZE - 1)
@@ -45,8 +45,8 @@
  * BL32 specific defines.
  ******************************************************************************/
 #ifndef VERSAL_BL32_MEM_BASE
-# define BL32_BASE			0x60000000
-# define BL32_LIMIT			0x7fffffff
+# define BL32_BASE			U(0x60000000)
+# define BL32_LIMIT			U(0x7fffffff)
 #else
 # define BL32_BASE			(VERSAL_BL32_MEM_BASE)
 # define BL32_LIMIT			(VERSAL_BL32_MEM_BASE + VERSAL_BL32_MEM_SIZE - 1)
@@ -56,7 +56,7 @@
  * BL33 specific defines.
  ******************************************************************************/
 #ifndef PRELOADED_BL33_BASE
-# define PLAT_ARM_NS_IMAGE_BASE		0x8000000
+# define PLAT_ARM_NS_IMAGE_BASE		U(0x8000000)
 #else
 # define PLAT_ARM_NS_IMAGE_BASE		PRELOADED_BL33_BASE
 #endif
@@ -81,8 +81,8 @@
 #define CACHE_WRITEBACK_SHIFT	6
 #define CACHE_WRITEBACK_GRANULE	(1 << CACHE_WRITEBACK_SHIFT)
 
-#define PLAT_VERSAL_GICD_BASE	0xF9000000
-#define PLAT_VERSAL_GICR_BASE	0xF9080000
+#define PLAT_VERSAL_GICD_BASE	U(0xF9000000)
+#define PLAT_VERSAL_GICR_BASE	U(0xF9080000)
 
 /*
  * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
@@ -91,7 +91,7 @@
  */
 #define PLAT_VERSAL_G1S_IRQS	VERSAL_IRQ_SEC_PHY_TIMER
 #define PLAT_VERSAL_G0_IRQS	VERSAL_IRQ_SEC_PHY_TIMER
-#define PLAT_VERSAL_IPI_IRQ	62
+#define PLAT_VERSAL_IPI_IRQ	U(62)
 
 #define PLAT_VERSAL_G1S_IRQ_PROPS(grp) \
 	INTR_PROP_DESC(VERSAL_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \
diff --git a/plat/xilinx/versal/include/versal_def.h b/plat/xilinx/versal/include/versal_def.h
index 001fb04..9372954 100644
--- a/plat/xilinx/versal/include/versal_def.h
+++ b/plat/xilinx/versal/include/versal_def.h
@@ -52,7 +52,7 @@
 /*******************************************************************************
  * IRQ constants
  ******************************************************************************/
-#define VERSAL_IRQ_SEC_PHY_TIMER		29
+#define VERSAL_IRQ_SEC_PHY_TIMER		U(29)
 
 /*******************************************************************************
  * CCI-400 related constants
@@ -112,33 +112,33 @@
 #define FPD_MAINCCI_SIZE	0x00100000
 
 /* APU registers and bitfields */
-#define FPD_APU_BASE		0xFD5C0000
-#define FPD_APU_CONFIG_0	(FPD_APU_BASE + 0x20)
-#define FPD_APU_RVBAR_L_0	(FPD_APU_BASE + 0x40)
-#define FPD_APU_RVBAR_H_0	(FPD_APU_BASE + 0x44)
-#define FPD_APU_PWRCTL		(FPD_APU_BASE + 0x90)
+#define FPD_APU_BASE		0xFD5C0000U
+#define FPD_APU_CONFIG_0	(FPD_APU_BASE + 0x20U)
+#define FPD_APU_RVBAR_L_0	(FPD_APU_BASE + 0x40U)
+#define FPD_APU_RVBAR_H_0	(FPD_APU_BASE + 0x44U)
+#define FPD_APU_PWRCTL		(FPD_APU_BASE + 0x90U)
 
-#define FPD_APU_CONFIG_0_VINITHI_SHIFT	8
-#define APU_0_PWRCTL_CPUPWRDWNREQ_MASK	1
-#define APU_1_PWRCTL_CPUPWRDWNREQ_MASK	2
+#define FPD_APU_CONFIG_0_VINITHI_SHIFT	8U
+#define APU_0_PWRCTL_CPUPWRDWNREQ_MASK	1U
+#define APU_1_PWRCTL_CPUPWRDWNREQ_MASK	2U
 
 /* PMC registers and bitfields */
-#define PMC_GLOBAL_BASE			0xF1110000
-#define PMC_GLOBAL_GLOB_GEN_STORAGE4	(PMC_GLOBAL_BASE + 0x40)
+#define PMC_GLOBAL_BASE			0xF1110000U
+#define PMC_GLOBAL_GLOB_GEN_STORAGE4	(PMC_GLOBAL_BASE + 0x40U)
 
 /* IPI registers and bitfields */
-#define IPI0_REG_BASE		0xFF330000
-#define IPI0_TRIG_BIT		(1 << 2)
-#define PMC_IPI_TRIG_BIT	(1 << 1)
-#define IPI1_REG_BASE		0xFF340000
-#define IPI1_TRIG_BIT		(1 << 3)
-#define IPI2_REG_BASE		0xFF350000
-#define IPI2_TRIG_BIT		(1 << 4)
-#define IPI3_REG_BASE		0xFF360000
-#define IPI3_TRIG_BIT		(1 << 5)
-#define IPI4_REG_BASE		0xFF370000
-#define IPI4_TRIG_BIT		(1 << 5)
-#define IPI5_REG_BASE		0xFF380000
-#define IPI5_TRIG_BIT		(1 << 6)
+#define IPI0_REG_BASE		U(0xFF330000)
+#define IPI0_TRIG_BIT		(1U << 2U)
+#define PMC_IPI_TRIG_BIT	(1U << 1U)
+#define IPI1_REG_BASE		U(0xFF340000)
+#define IPI1_TRIG_BIT		(1U << 3U)
+#define IPI2_REG_BASE		U(0xFF350000)
+#define IPI2_TRIG_BIT		(1U << 4U)
+#define IPI3_REG_BASE		U(0xFF360000)
+#define IPI3_TRIG_BIT		(1U << 5U)
+#define IPI4_REG_BASE		U(0xFF370000)
+#define IPI4_TRIG_BIT		(1U << 5U)
+#define IPI5_REG_BASE		U(0xFF380000)
+#define IPI5_TRIG_BIT		(1U << 6U)
 
 #endif /* VERSAL_DEF_H */
diff --git a/plat/xilinx/versal/plat_psci.c b/plat/xilinx/versal/plat_psci.c
index fa0284c..eb05e58 100644
--- a/plat/xilinx/versal/plat_psci.c
+++ b/plat/xilinx/versal/plat_psci.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -21,19 +21,20 @@
 
 static int versal_pwr_domain_on(u_register_t mpidr)
 {
-	unsigned int cpu_id = plat_core_pos_by_mpidr(mpidr);
+	int cpu_id = plat_core_pos_by_mpidr(mpidr);
 	const struct pm_proc *proc;
 
 	VERBOSE("%s: mpidr: 0x%lx\n", __func__, mpidr);
 
-	if (cpu_id == -1)
+	if (cpu_id == -1) {
 		return PSCI_E_INTERN_FAIL;
+	}
 
-	proc = pm_get_proc(cpu_id);
+	proc = pm_get_proc((unsigned int)cpu_id);
 
 	/* Send request to PMC to wake up selected ACPU core */
-	pm_req_wakeup(proc->node_id, (versal_sec_entry & 0xFFFFFFFF) | 0x1,
-		      versal_sec_entry >> 32, 0, SECURE_FLAG);
+	(void)pm_req_wakeup(proc->node_id, (versal_sec_entry & 0xFFFFFFFFU) | 0x1U,
+			    versal_sec_entry >> 32, 0, SECURE_FLAG);
 
 	/* Clear power down request */
 	pm_client_wakeup(proc);
@@ -53,9 +54,10 @@
 	unsigned int cpu_id = plat_my_core_pos();
 	const struct pm_proc *proc = pm_get_proc(cpu_id);
 
-	for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++)
+	for (size_t i = 0U; i <= PLAT_MAX_PWR_LVL; i++) {
 		VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
 			__func__, i, target_state->pwr_domain_state[i]);
+	}
 
 	plat_versal_gic_cpuif_disable();
 
@@ -67,8 +69,8 @@
 		PM_STATE_SUSPEND_TO_RAM : PM_STATE_CPU_IDLE;
 
 	/* Send request to PMC to suspend this core */
-	pm_self_suspend(proc->node_id, MAX_LATENCY, state, versal_sec_entry,
-			SECURE_FLAG);
+	(void)pm_self_suspend(proc->node_id, MAX_LATENCY, state, versal_sec_entry,
+			      SECURE_FLAG);
 
 	/* APU is to be turned off */
 	if (target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE) {
@@ -89,9 +91,10 @@
 	unsigned int cpu_id = plat_my_core_pos();
 	const struct pm_proc *proc = pm_get_proc(cpu_id);
 
-	for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++)
+	for (size_t i = 0U; i <= PLAT_MAX_PWR_LVL; i++) {
 		VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
 			__func__, i, target_state->pwr_domain_state[i]);
+	}
 
 	/* Clear the APU power control register for this cpu */
 	pm_client_wakeup(proc);
@@ -123,11 +126,12 @@
 static void __dead2 versal_system_off(void)
 {
 	/* Send the power down request to the PMC */
-	pm_system_shutdown(XPM_SHUTDOWN_TYPE_SHUTDOWN,
-			  pm_get_shutdown_scope(), SECURE_FLAG);
+	(void)pm_system_shutdown(XPM_SHUTDOWN_TYPE_SHUTDOWN,
+				 pm_get_shutdown_scope(), SECURE_FLAG);
 
-	while (1)
+	while (1) {
 		wfi();
+	}
 }
 
 /**
@@ -137,11 +141,12 @@
 static void __dead2 versal_system_reset(void)
 {
 	/* Send the system reset request to the PMC */
-	pm_system_shutdown(XPM_SHUTDOWN_TYPE_RESET,
-			  pm_get_shutdown_scope(), SECURE_FLAG);
+	(void)pm_system_shutdown(XPM_SHUTDOWN_TYPE_RESET,
+				 pm_get_shutdown_scope(), SECURE_FLAG);
 
-	while (1)
+	while (1) {
 		wfi();
+	}
 }
 
 /**
@@ -154,9 +159,10 @@
 	unsigned int cpu_id = plat_my_core_pos();
 	const struct pm_proc *proc = pm_get_proc(cpu_id);
 
-	for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++)
+	for (size_t i = 0U; i <= PLAT_MAX_PWR_LVL; i++) {
 		VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
 			__func__, i, target_state->pwr_domain_state[i]);
+	}
 
 	/* Prevent interrupts from spuriously waking up this cpu */
 	plat_versal_gic_cpuif_disable();
@@ -169,8 +175,8 @@
 	 * invoking CPU_on function, during which resume address will
 	 * be set.
 	 */
-	pm_self_suspend(proc->node_id, MAX_LATENCY, PM_STATE_CPU_IDLE, 0,
-			SECURE_FLAG);
+	(void)pm_self_suspend(proc->node_id, MAX_LATENCY, PM_STATE_CPU_IDLE, 0,
+			      SECURE_FLAG);
 }
 
 /**
@@ -187,19 +193,21 @@
 {
 	VERBOSE("%s: power_state: 0x%x\n", __func__, power_state);
 
-	int pstate = psci_get_pstate_type(power_state);
+	unsigned int pstate = psci_get_pstate_type(power_state);
 
 	assert(req_state);
 
 	/* Sanity check the requested state */
-	if (pstate == PSTATE_TYPE_STANDBY)
+	if (pstate == PSTATE_TYPE_STANDBY) {
 		req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_RET_STATE;
-	else
+	} else {
 		req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_OFF_STATE;
+	}
 
 	/* We expect the 'state id' to be zero */
-	if (psci_get_pstate_id(power_state))
+	if (psci_get_pstate_id(power_state) != 0U) {
 		return PSCI_E_INVALID_PARAMS;
+	}
 
 	return PSCI_E_SUCCESS;
 }
diff --git a/plat/xilinx/versal/plat_versal.c b/plat/xilinx/versal/plat_versal.c
index 107eae6..54c35b6 100644
--- a/plat/xilinx/versal/plat_versal.c
+++ b/plat/xilinx/versal/plat_versal.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,7 +9,7 @@
 
 int plat_core_pos_by_mpidr(u_register_t mpidr)
 {
-	if (mpidr & MPIDR_CLUSTER_MASK) {
+	if ((mpidr & MPIDR_CLUSTER_MASK) != 0U) {
 		return -1;
 	}
 
@@ -17,5 +17,5 @@
 		return -1;
 	}
 
-	return versal_calc_core_pos(mpidr);
+	return (int)versal_calc_core_pos(mpidr);
 }
diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.c b/plat/xilinx/versal/pm_service/pm_api_sys.c
index 912835a..534d910 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-2020, Xilinx, Inc. All rights reserved.
+ * Copyright (c) 2019-2021, Xilinx, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -21,10 +21,10 @@
 /*********************************************************************
  * Target module IDs macros
  ********************************************************************/
-#define LIBPM_MODULE_ID		0x2
-#define LOADER_MODULE_ID	0x7
+#define LIBPM_MODULE_ID		0x2U
+#define LOADER_MODULE_ID	0x7U
 
-#define  MODE	0x80000000
+#define  MODE	0x80000000U
 /* default shutdown/reboot scope is system(2) */
 static unsigned int pm_shutdown_scope = XPM_SHUTDOWN_SUBTYPE_RST_SYSTEM;
 
@@ -42,32 +42,32 @@
  * Assigning of argument values into array elements.
  */
 #define PM_PACK_PAYLOAD1(pl, mid, flag, arg0) {	\
-	pl[0] = (uint32_t)((uint32_t)((arg0) & 0xFF) | (mid << 8) | ((flag) << 24)); \
+	pl[0] = (uint32_t)(((uint32_t)(arg0) & 0xFFU) | ((mid) << 8U) | ((flag) << 24U)); \
 }
 
 #define PM_PACK_PAYLOAD2(pl, mid, flag, arg0, arg1) {		\
 	pl[1] = (uint32_t)(arg1);				\
-	PM_PACK_PAYLOAD1(pl, mid, flag, arg0);			\
+	PM_PACK_PAYLOAD1(pl, (mid), (flag), (arg0));			\
 }
 
 #define PM_PACK_PAYLOAD3(pl, mid, flag, arg0, arg1, arg2) {	\
 	pl[2] = (uint32_t)(arg2);				\
-	PM_PACK_PAYLOAD2(pl, mid, flag, arg0, arg1);		\
+	PM_PACK_PAYLOAD2(pl, (mid), (flag), (arg0), (arg1));		\
 }
 
 #define PM_PACK_PAYLOAD4(pl, mid, flag, arg0, arg1, arg2, arg3) {	\
 	pl[3] = (uint32_t)(arg3);					\
-	PM_PACK_PAYLOAD3(pl, mid, flag, arg0, arg1, arg2);		\
+	PM_PACK_PAYLOAD3(pl, (mid), (flag), (arg0), (arg1), (arg2));		\
 }
 
 #define PM_PACK_PAYLOAD5(pl, mid, flag, arg0, arg1, arg2, arg3, arg4) {	\
 	pl[4] = (uint32_t)(arg4);					\
-	PM_PACK_PAYLOAD4(pl, mid, flag, arg0, arg1, arg2, arg3);	\
+	PM_PACK_PAYLOAD4(pl, (mid), (flag), (arg0), (arg1), (arg2), (arg3));	\
 }
 
 #define PM_PACK_PAYLOAD6(pl, mid, flag, arg0, arg1, arg2, arg3, arg4, arg5) {	\
 	pl[5] = (uint32_t)(arg5);						\
-	PM_PACK_PAYLOAD5(pl, mid, flag, arg0, arg1, arg2, arg3, arg4);		\
+	PM_PACK_PAYLOAD5(pl, (mid), (flag), (arg0), (arg1), (arg2), (arg3), (arg4));		\
 }
 
 /* PM API functions */
@@ -130,7 +130,7 @@
 	unsigned int cpuid = plat_my_core_pos();
 	const struct pm_proc *proc = pm_get_proc(cpuid);
 
-	if (!proc) {
+	if (proc == NULL) {
 		WARN("Failed to get proc %d\n", cpuid);
 		return PM_RET_ERROR_INTERNAL;
 	}
@@ -197,10 +197,11 @@
 	/* Send request to the PMU */
 	PM_PACK_PAYLOAD4(payload, LIBPM_MODULE_ID, flag, PM_REQ_SUSPEND, target,
 			 latency, state);
-	if (ack == IPI_BLOCKING)
+	if (ack == IPI_BLOCKING) {
 		return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
-	else
+	} else {
 		return pm_ipi_send(primary_proc, payload);
+	}
 }
 
 /**
@@ -372,8 +373,9 @@
 void pm_get_callbackdata(uint32_t *data, size_t count, uint32_t flag)
 {
 	/* Return if interrupt is not from PMU */
-	if (!pm_ipi_irq_status(primary_proc))
+	if (pm_ipi_irq_status(primary_proc) == 0) {
 		return;
+	}
 
 	pm_ipi_buff_read_callb(data, count);
 	pm_ipi_irq_clear(primary_proc);
@@ -771,10 +773,11 @@
 	PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_FORCE_POWERDOWN,
 			 target, ack);
 
-	if (ack == IPI_BLOCKING)
+	if (ack == IPI_BLOCKING) {
 		return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
-	else
+	} else {
 		return pm_ipi_send(primary_proc, payload);
+	}
 }
 
 /**
@@ -830,7 +833,7 @@
 
 	ret = pm_feature_check(PM_QUERY_DATA, &version, flag);
 	if (PM_RET_SUCCESS == ret) {
-		fw_api_version = version & 0xFFFF ;
+		fw_api_version = version & 0xFFFFU;
 		if ((2U == fw_api_version) &&
 		    ((XPM_QID_CLOCK_GET_NAME == qid) ||
 		     (XPM_QID_PINCTRL_GET_FUNCTION_NAME == qid))) {
@@ -864,32 +867,39 @@
 				uint32_t flag)
 {
 	uint32_t payload[PAYLOAD_ARG_CNT];
-	int ret;
+	enum pm_ret_status ret;
 
 	switch (ioctl_id) {
 	case IOCTL_SET_PLL_FRAC_MODE:
-		return pm_pll_set_mode(arg1, arg2, flag);
+		ret =  pm_pll_set_mode(arg1, arg2, flag);
+		break;
 	case IOCTL_GET_PLL_FRAC_MODE:
-		return pm_pll_get_mode(arg1, value, flag);
+		ret =  pm_pll_get_mode(arg1, value, flag);
+		break;
 	case IOCTL_SET_PLL_FRAC_DATA:
-		return pm_pll_set_param(arg1, PM_PLL_PARAM_DATA, arg2, flag);
+		ret =  pm_pll_set_param(arg1, PM_PLL_PARAM_DATA, arg2, flag);
+		break;
 	case IOCTL_GET_PLL_FRAC_DATA:
-		return pm_pll_get_param(arg1, PM_PLL_PARAM_DATA, value, flag);
+		ret =  pm_pll_get_param(arg1, PM_PLL_PARAM_DATA, value, flag);
+		break;
 	case IOCTL_SET_SGI:
 		/* Get the sgi number */
-		ret = pm_register_sgi(arg1);
-		if (ret) {
+		if (pm_register_sgi(arg1) != 0) {
 			return PM_RET_ERROR_ARGS;
 		}
 		gicd_write_irouter(gicv3_driver_data->gicd_base,
-				PLAT_VERSAL_IPI_IRQ, MODE);
-		return PM_RET_SUCCESS;
+				  (unsigned int)PLAT_VERSAL_IPI_IRQ, MODE);
+		ret =  PM_RET_SUCCESS;
+		break;
 	default:
 		/* Send request to the PMC */
 		PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, flag, PM_IOCTL,
 				 device_id, ioctl_id, arg1, arg2);
-		return pm_ipi_send_sync(primary_proc, payload, value, 1);
+		ret =  pm_ipi_send_sync(primary_proc, payload, value, 1);
+		break;
 	}
+
+	return ret;
 }
 
 /**
@@ -944,14 +954,15 @@
 				    uint32_t flag)
 {
 	uint32_t payload[PAYLOAD_ARG_CNT], fw_api_version;
-	uint32_t status;
+	enum pm_ret_status status = PM_RET_ERROR_NOFEATURE;
 
 	switch (api_id) {
 	case PM_GET_CALLBACK_DATA:
 	case PM_GET_TRUSTZONE_VERSION:
 	case PM_LOAD_PDI:
 		*version = (PM_API_BASE_VERSION << 16);
-		return PM_RET_SUCCESS;
+		status = PM_RET_SUCCESS;
+		break;
 	case PM_GET_API_VERSION:
 	case PM_GET_DEVICE_STATUS:
 	case PM_GET_OP_CHARACTERISTIC:
@@ -992,25 +1003,36 @@
 	case PM_SET_MAX_LATENCY:
 	case PM_REGISTER_NOTIFIER:
 		*version = (PM_API_BASE_VERSION << 16);
+		status = PM_RET_SUCCESS;
 		break;
 	case PM_QUERY_DATA:
 		*version = (PM_API_QUERY_DATA_VERSION << 16);
+		status = PM_RET_SUCCESS;
 		break;
 	default:
 		*version = 0U;
-		return PM_RET_ERROR_NOFEATURE;
+		status = PM_RET_ERROR_NOFEATURE;
+		break;
 	}
 
+	if (status != PM_RET_SUCCESS) {
+		goto done;
+	}
+
 	PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag,
 			 PM_FEATURE_CHECK, api_id);
 
 	status = pm_ipi_send_sync(primary_proc, payload, &fw_api_version, 1);
-	if (status != PM_RET_SUCCESS)
-		return status;
+	if (status != PM_RET_SUCCESS) {
+		goto done;
+	}
 
 	*version |= fw_api_version;
 
-	return PM_RET_SUCCESS;
+	status = PM_RET_SUCCESS;
+
+done:
+	return status;
 }
 
 /**
diff --git a/plat/xilinx/versal/pm_service/pm_client.c b/plat/xilinx/versal/pm_service/pm_client.c
index f6c3148..77ec20e 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-2020, Xilinx, Inc. All rights reserved.
+ * Copyright (c) 2019-2021, Xilinx, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -23,8 +23,8 @@
 #include "pm_client.h"
 
 #define UNDEFINED_CPUID		(~0)
-#define IRQ_MAX		142
-#define NUM_GICD_ISENABLER	((IRQ_MAX >> 5) + 1)
+#define IRQ_MAX		142U
+#define NUM_GICD_ISENABLER	((IRQ_MAX >> 5U) + 1U)
 
 DEFINE_BAKERY_LOCK(pm_client_secure_lock);
 
@@ -122,36 +122,38 @@
 	uint8_t pm_wakeup_nodes_set[XPM_NODEIDX_DEV_MAX];
 	uintptr_t isenabler1 = PLAT_VERSAL_GICD_BASE + GICD_ISENABLER + 4;
 
-	zeromem(&pm_wakeup_nodes_set, sizeof(pm_wakeup_nodes_set));
+	zeromem(&pm_wakeup_nodes_set, (u_register_t)sizeof(pm_wakeup_nodes_set));
 
-	for (reg_num = 0; reg_num < NUM_GICD_ISENABLER; reg_num++) {
+	for (reg_num = 0U; reg_num < NUM_GICD_ISENABLER; reg_num++) {
 		uint32_t base_irq = reg_num << ISENABLER_SHIFT;
 		uint32_t reg = mmio_read_32(isenabler1 + (reg_num << 2));
 
-		if (!reg)
+		if (reg == 0U) {
 			continue;
+		}
 
-		while (reg) {
+		while (reg != 0U) {
 			enum pm_device_node_idx node_idx;
-			uint32_t idx, ret, irq, lowest_set = reg & (-reg);
-
+			uint32_t idx, irq, lowest_set = reg & (-reg);
+			enum pm_ret_status ret;
 			idx = __builtin_ctz(lowest_set);
 			irq = base_irq + idx;
 
-			if (irq > IRQ_MAX)
+			if (irq > IRQ_MAX) {
 				break;
+			}
 
 			node_idx = irq_to_pm_node_idx(irq);
 			reg &= ~lowest_set;
 
 			if ((node_idx != XPM_NODEIDX_DEV_MIN) &&
-			    (!pm_wakeup_nodes_set[node_idx])) {
+			    (pm_wakeup_nodes_set[node_idx] == 0U)) {
 				/* Get device ID from node index */
 				device_id = PERIPH_DEVID(node_idx);
 				ret = pm_set_wakeup_source(node_id,
 							   device_id, 1,
 							   SECURE_FLAG);
-				pm_wakeup_nodes_set[node_idx] = !ret;
+				pm_wakeup_nodes_set[node_idx] = (uint8_t)(!ret);
 			}
 		}
 	}
@@ -168,12 +170,13 @@
 {
 	bakery_lock_get(&pm_client_secure_lock);
 
-	if (state == PM_STATE_SUSPEND_TO_RAM)
-		pm_client_set_wakeup_sources(proc->node_id);
+	if (state == PM_STATE_SUSPEND_TO_RAM) {
+		pm_client_set_wakeup_sources((uint32_t)proc->node_id);
+	}
 
 	/* Set powerdown request */
 	mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) |
-		      proc->pwrdn_mask);
+		      (uint32_t)proc->pwrdn_mask);
 
 	bakery_lock_release(&pm_client_secure_lock);
 }
@@ -193,7 +196,7 @@
 
 	/* Clear powerdown request */
 	mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) &
-		      ~primary_proc->pwrdn_mask);
+		      ~((uint32_t)primary_proc->pwrdn_mask));
 
 	bakery_lock_release(&pm_client_secure_lock);
 }
@@ -206,9 +209,10 @@
  */
 static unsigned int pm_get_cpuid(uint32_t nid)
 {
-	for (size_t i = 0; i < ARRAY_SIZE(pm_procs_all); i++) {
-		if (pm_procs_all[i].node_id == nid)
+	for (size_t i = 0U; i < ARRAY_SIZE(pm_procs_all); i++) {
+		if (pm_procs_all[i].node_id == nid) {
 			return i;
+		}
 	}
 	return UNDEFINED_CPUID;
 }
@@ -223,8 +227,9 @@
 {
 	unsigned int cpuid = pm_get_cpuid(proc->node_id);
 
-	if (cpuid == UNDEFINED_CPUID)
+	if (cpuid == UNDEFINED_CPUID) {
 		return;
+	}
 
 	bakery_lock_get(&pm_client_secure_lock);
 
@@ -244,8 +249,9 @@
  */
 const struct pm_proc *pm_get_proc(unsigned int cpuid)
 {
-	if (cpuid < ARRAY_SIZE(pm_procs_all))
+	if (cpuid < ARRAY_SIZE(pm_procs_all)) {
 		return &pm_procs_all[cpuid];
+	}
 
 	return NULL;
 }
diff --git a/plat/xilinx/versal/pm_service/pm_defs.h b/plat/xilinx/versal/pm_service/pm_defs.h
index ccb2617..08b46e2 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-2020, Xilinx, Inc. All rights reserved.
+ * Copyright (c) 2019-2021, Xilinx, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -33,8 +33,8 @@
 				       XPM_NODESUBCL_DEV_PERIPH, \
 				       XPM_NODETYPE_DEV_PERIPH, (IDX))
 
-#define PM_GET_CALLBACK_DATA		0xa01
-#define PM_GET_TRUSTZONE_VERSION	0xa03
+#define PM_GET_CALLBACK_DATA		0xa01U
+#define PM_GET_TRUSTZONE_VERSION	0xa03U
 
 /* PM API Versions */
 #define PM_API_BASE_VERSION		1U
@@ -88,11 +88,11 @@
 #define PM_LOAD_PDI			0x701U
 
 /* IOCTL IDs for clock driver */
-#define IOCTL_SET_PLL_FRAC_MODE		8
-#define	IOCTL_GET_PLL_FRAC_MODE		9
-#define	IOCTL_SET_PLL_FRAC_DATA		10
-#define	IOCTL_GET_PLL_FRAC_DATA		11
-#define	IOCTL_SET_SGI			25
+#define IOCTL_SET_PLL_FRAC_MODE		8U
+#define	IOCTL_GET_PLL_FRAC_MODE		9U
+#define	IOCTL_SET_PLL_FRAC_DATA		10U
+#define	IOCTL_GET_PLL_FRAC_DATA		11U
+#define	IOCTL_SET_SGI			25U
 
 /* Parameter ID for PLL IOCTLs */
 /* Fractional data portion for PLL */
diff --git a/plat/xilinx/versal/pm_service/pm_svc_main.c b/plat/xilinx/versal/pm_service/pm_svc_main.c
index 87ba732..b082acb 100644
--- a/plat/xilinx/versal/pm_service/pm_svc_main.c
+++ b/plat/xilinx/versal/pm_service/pm_svc_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2020, Xilinx, Inc. All rights reserved.
+ * Copyright (c) 2019-2021, Xilinx, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -20,24 +20,24 @@
 #include <drivers/arm/gicv3.h>
 
 #define XSCUGIC_SGIR_EL1_INITID_SHIFT    24U
-#define INVALID_SGI    0xFF
+#define INVALID_SGI    0xFFU
 DEFINE_RENAME_SYSREG_RW_FUNCS(icc_asgi1r_el1, S3_0_C12_C11_6)
 
 /* pm_up = true - UP, pm_up = false - DOWN */
 static bool pm_up;
-static unsigned int sgi = INVALID_SGI;
+static unsigned int sgi = (unsigned int)INVALID_SGI;
 
 static uint64_t ipi_fiq_handler(uint32_t id, uint32_t flags, void *handle,
 				void *cookie)
 {
-	int cpu;
+	unsigned int cpu;
 	unsigned int reg;
 
 	(void)plat_ic_acknowledge_interrupt();
-	cpu = plat_my_core_pos() + 1;
+	cpu = plat_my_core_pos() + 1U;
 
-	if (sgi != INVALID_SGI) {
-		reg = (cpu | (sgi << XSCUGIC_SGIR_EL1_INITID_SHIFT));
+	if ((unsigned int)sgi != (unsigned int)INVALID_SGI) {
+		reg = (cpu | ((unsigned int)sgi << (unsigned int)XSCUGIC_SGIR_EL1_INITID_SHIFT));
 		write_icc_asgi1r_el1(reg);
 	}
 
@@ -60,7 +60,7 @@
  */
 int pm_register_sgi(unsigned int sgi_num)
 {
-	if (sgi != INVALID_SGI) {
+	if ((unsigned int)sgi != (unsigned int)INVALID_SGI) {
 		return -EBUSY;
 	}
 
@@ -68,7 +68,7 @@
 		return -EINVAL;
 	}
 
-	sgi = sgi_num;
+	sgi = (unsigned int)sgi_num;
 	return 0;
 }
 
@@ -107,7 +107,7 @@
 	pm_ipi_irq_enable(primary_proc);
 
 	ret = request_intr_type_el3(PLAT_VERSAL_IPI_IRQ, ipi_fiq_handler);
-	if (ret) {
+	if (ret != 0) {
 		WARN("BL31: registering IPI interrupt failed\n");
 	}
 	return ret;
@@ -138,8 +138,9 @@
 	uint32_t security_flag = SECURE_FLAG;
 
 	/* Handle case where PM wasn't initialized properly */
-	if (!pm_up)
+	if (pm_up == false) {
 		SMC_RET1(handle, SMC_UNK);
+	}
 
 	pm_arg[0] = (uint32_t)x1;
 	pm_arg[1] = (uint32_t)(x1 >> 32);
@@ -150,7 +151,7 @@
 	 * Mark BIT24 payload (i.e 1st bit of pm_arg[3] ) as non-secure (1)
 	 * if smc called is non secure
 	 */
-	if (is_caller_non_secure(flags)) {
+	if (is_caller_non_secure(flags) != 0) {
 		security_flag = NON_SECURE_FLAG;
 	}
 
@@ -207,8 +208,8 @@
 		uint32_t api_version;
 
 		ret = pm_get_api_version(&api_version, security_flag);
-		SMC_RET1(handle, (uint64_t)PM_RET_SUCCESS |
-				 ((uint64_t)api_version << 32));
+		SMC_RET1(handle, (u_register_t)PM_RET_SUCCESS |
+				 ((u_register_t)api_version << 32));
 	}
 
 	case PM_GET_DEVICE_STATUS:
@@ -216,8 +217,8 @@
 		uint32_t buff[3];
 
 		ret = pm_get_device_status(pm_arg[0], buff, security_flag);
-		SMC_RET2(handle, (uint64_t)ret | ((uint64_t)buff[0] << 32),
-			 (uint64_t)buff[1] | ((uint64_t)buff[2] << 32));
+		SMC_RET2(handle, (u_register_t)ret | ((u_register_t)buff[0] << 32),
+			 (u_register_t)buff[1] | ((u_register_t)buff[2] << 32));
 	}
 
 	case PM_RESET_ASSERT:
@@ -230,8 +231,8 @@
 
 		ret = pm_reset_get_status(pm_arg[0], &reset_status,
 					  security_flag);
-		SMC_RET1(handle, (uint64_t)ret |
-			 ((uint64_t)reset_status << 32));
+		SMC_RET1(handle, (u_register_t)ret |
+			 ((u_register_t)reset_status << 32));
 	}
 
 	case PM_INIT_FINALIZE:
@@ -244,8 +245,8 @@
 
 		pm_get_callbackdata(result, ARRAY_SIZE(result), security_flag);
 		SMC_RET2(handle,
-			 (uint64_t)result[0] | ((uint64_t)result[1] << 32),
-			 (uint64_t)result[2] | ((uint64_t)result[3] << 32));
+			 (u_register_t)result[0] | ((u_register_t)result[1] << 32),
+			 (u_register_t)result[2] | ((u_register_t)result[3] << 32));
 	}
 
 	case PM_PINCTRL_REQUEST:
@@ -261,7 +262,7 @@
 		uint32_t value = 0;
 
 		ret = pm_pinctrl_get_function(pm_arg[0], &value, security_flag);
-		SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+		SMC_RET1(handle, (u_register_t)ret | ((u_register_t)value) << 32);
 	}
 
 	case PM_PINCTRL_SET_FUNCTION:
@@ -275,7 +276,7 @@
 
 		ret = pm_pinctrl_get_pin_param(pm_arg[0], pm_arg[1], &value,
 					       security_flag);
-		SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+		SMC_RET1(handle, (u_register_t)ret | ((u_register_t)value) << 32);
 	}
 
 	case PM_PINCTRL_CONFIG_PARAM_SET:
@@ -289,7 +290,7 @@
 
 		ret = pm_api_ioctl(pm_arg[0], pm_arg[1], pm_arg[2],
 				   pm_arg[3], &value, security_flag);
-		SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+		SMC_RET1(handle, (u_register_t)ret | ((u_register_t)value) << 32);
 	}
 
 	case PM_QUERY_DATA:
@@ -299,8 +300,8 @@
 		ret = pm_query_data(pm_arg[0], pm_arg[1], pm_arg[2],
 				      pm_arg[3], data, security_flag);
 
-		SMC_RET2(handle, (uint64_t)ret  | ((uint64_t)data[0] << 32),
-				 (uint64_t)data[1] | ((uint64_t)data[2] << 32));
+		SMC_RET2(handle, (u_register_t)ret  | ((u_register_t)data[0] << 32),
+				 (u_register_t)data[1] | ((u_register_t)data[2] << 32));
 
 	}
 	case PM_CLOCK_ENABLE:
@@ -316,7 +317,7 @@
 		uint32_t value;
 
 		ret = pm_clock_get_state(pm_arg[0], &value, security_flag);
-		SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+		SMC_RET1(handle, (u_register_t)ret | ((u_register_t)value) << 32);
 	}
 
 	case PM_CLOCK_SETDIVIDER:
@@ -328,7 +329,7 @@
 		uint32_t value;
 
 		ret = pm_clock_get_divider(pm_arg[0], &value, security_flag);
-		SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+		SMC_RET1(handle, (u_register_t)ret | ((u_register_t)value) << 32);
 	}
 
 	case PM_CLOCK_SETPARENT:
@@ -340,7 +341,7 @@
 		uint32_t value;
 
 		ret = pm_clock_get_parent(pm_arg[0], &value, security_flag);
-		SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+		SMC_RET1(handle, (u_register_t)ret | ((u_register_t)value) << 32);
 	}
 
 	case PM_CLOCK_GETRATE:
@@ -348,8 +349,8 @@
 		uint32_t rate[2] = { 0 };
 
 		ret = pm_clock_get_rate(pm_arg[0], rate, security_flag);
-		SMC_RET2(handle, (uint64_t)ret | ((uint64_t)rate[0] << 32),
-			 rate[1]);
+		SMC_RET2(handle, (u_register_t)ret | ((u_register_t)rate[0] << 32),
+			 (u_register_t)rate[1] | ((u_register_t)0U << 32));
 	}
 
 	case PM_PLL_SET_PARAMETER:
@@ -363,7 +364,7 @@
 
 		ret = pm_pll_get_param(pm_arg[0], pm_arg[1], &value,
 				       security_flag);
-		SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value << 32));
+		SMC_RET1(handle, (u_register_t)ret | ((u_register_t)value << 32));
 	}
 
 	case PM_PLL_SET_MODE:
@@ -375,7 +376,7 @@
 		uint32_t mode;
 
 		ret = pm_pll_get_mode(pm_arg[0], &mode, security_flag);
-		SMC_RET1(handle, (uint64_t)ret | ((uint64_t)mode << 32));
+		SMC_RET1(handle, (u_register_t)ret | ((u_register_t)mode << 32));
 	}
 
 	case PM_GET_TRUSTZONE_VERSION:
@@ -387,8 +388,8 @@
 		uint32_t result[2];
 
 		ret = pm_get_chipid(result, security_flag);
-		SMC_RET2(handle, (uint64_t)ret | ((uint64_t)result[0] << 32),
-			 result[1]);
+		SMC_RET2(handle, (u_register_t)ret | ((u_register_t)result[0] << 32),
+			 (u_register_t)result[1] | ((u_register_t)0U << 32));
 	}
 
 	case PM_FEATURE_CHECK:
@@ -396,14 +397,14 @@
 		uint32_t version;
 
 		ret = pm_feature_check(pm_arg[0], &version, security_flag);
-		SMC_RET1(handle, (uint64_t)ret | ((uint64_t)version << 32));
+		SMC_RET1(handle, (u_register_t)ret | ((u_register_t)version << 32));
 	}
 
 	case PM_LOAD_PDI:
 	{
 		ret = pm_load_pdi(pm_arg[0], pm_arg[1], pm_arg[2],
 				  security_flag);
-		SMC_RET1(handle, (uint64_t)ret);
+		SMC_RET1(handle, (u_register_t)ret);
 	}
 
 	case PM_GET_OP_CHARACTERISTIC:
@@ -412,20 +413,20 @@
 
 		ret = pm_get_op_characteristic(pm_arg[0], pm_arg[1], &result,
 					       security_flag);
-		SMC_RET1(handle, (uint64_t)ret | ((uint64_t)result << 32));
+		SMC_RET1(handle, (u_register_t)ret | ((u_register_t)result << 32));
 	}
 
 	case PM_SET_MAX_LATENCY:
 	{
 		ret = pm_set_max_latency(pm_arg[0], pm_arg[1], security_flag);
-		SMC_RET1(handle, (uint64_t)ret);
+		SMC_RET1(handle, (u_register_t)ret);
 	}
 
 	case PM_REGISTER_NOTIFIER:
 	{
 		ret = pm_register_notifier(pm_arg[0], pm_arg[1], pm_arg[2],
 					   pm_arg[3], security_flag);
-		SMC_RET1(handle, (uint64_t)ret);
+		SMC_RET1(handle, (u_register_t)ret);
 	}
 
 	default:
diff --git a/plat/xilinx/versal/sip_svc_setup.c b/plat/xilinx/versal/sip_svc_setup.c
index bc7d8b7..6f2ff94 100644
--- a/plat/xilinx/versal/sip_svc_setup.c
+++ b/plat/xilinx/versal/sip_svc_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -14,13 +14,13 @@
 #include "pm_svc_main.h"
 
 /* SMC function IDs for SiP Service queries */
-#define VERSAL_SIP_SVC_CALL_COUNT	0x8200ff00
-#define VERSAL_SIP_SVC_UID		0x8200ff01
-#define VERSAL_SIP_SVC_VERSION		0x8200ff03
+#define VERSAL_SIP_SVC_CALL_COUNT	U(0x8200ff00)
+#define VERSAL_SIP_SVC_UID		U(0x8200ff01)
+#define VERSAL_SIP_SVC_VERSION		U(0x8200ff03)
 
 /* SiP Service Calls version numbers */
-#define SIP_SVC_VERSION_MAJOR	0
-#define SIP_SVC_VERSION_MINOR	1
+#define SIP_SVC_VERSION_MAJOR	U(0)
+#define SIP_SVC_VERSION_MINOR	U(1)
 
 /* These macros are used to identify PM calls from the SMC function ID */
 #define PM_FID_MASK	0xf000u
@@ -31,8 +31,8 @@
 
 /* SiP Service UUID */
 DEFINE_SVC_UUID2(versal_sip_uuid,
-		0x2ab9e4ec, 0x93b9, 0x11e7, 0xa0, 0x19,
-		0xdf, 0xe0, 0xdb, 0xad, 0x0a, 0xe0);
+		0x2ab9e4ecU, 0x93b9U, 0x11e7U, 0xa0U, 0x19U,
+		0xdfU, 0xe0U, 0xdbU, 0xadU, 0x0aU, 0xe0U);
 
 /**
  * sip_svc_setup() - Setup SiP Service
@@ -42,7 +42,7 @@
 static int32_t sip_svc_setup(void)
 {
 	/* PM implementation as SiP Service */
-	pm_setup();
+	(void)pm_setup();
 
 	return 0;
 }
diff --git a/plat/xilinx/versal/versal_ipi.c b/plat/xilinx/versal/versal_ipi.c
index 27541ff..f99af82 100644
--- a/plat/xilinx/versal/versal_ipi.c
+++ b/plat/xilinx/versal/versal_ipi.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, Xilinx, Inc. All rights reserved.
+ * Copyright (c) 2019-2021, Xilinx, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -24,49 +24,49 @@
 	[IPI_ID_APU] = {
 		.ipi_bit_mask = IPI0_TRIG_BIT,
 		.ipi_reg_base = IPI0_REG_BASE,
-		.secure_only = 0,
+		.secure_only = 0U,
 	},
 
 	/* PMC IPI */
 	[IPI_ID_PMC] = {
 		.ipi_bit_mask = PMC_IPI_TRIG_BIT,
 		.ipi_reg_base = IPI0_REG_BASE,
-		.secure_only = 0,
+		.secure_only = 0U,
 	},
 
 	/* RPU0 IPI */
 	[IPI_ID_RPU0] = {
 		.ipi_bit_mask = IPI1_TRIG_BIT,
 		.ipi_reg_base = IPI1_REG_BASE,
-		.secure_only = 0,
+		.secure_only = 0U,
 	},
 
 	/* RPU1 IPI */
 	[IPI_ID_RPU1] = {
 		.ipi_bit_mask = IPI2_TRIG_BIT,
 		.ipi_reg_base = IPI2_REG_BASE,
-		.secure_only = 0,
+		.secure_only = 0U,
 	},
 
 	/* IPI3 IPI */
 	[IPI_ID_3] = {
 		.ipi_bit_mask = IPI3_TRIG_BIT,
 		.ipi_reg_base = IPI3_REG_BASE,
-		.secure_only = 0,
+		.secure_only = 0U,
 	},
 
 	/* IPI4 IPI */
 	[IPI_ID_4] = {
 		.ipi_bit_mask = IPI4_TRIG_BIT,
 		.ipi_reg_base = IPI4_REG_BASE,
-		.secure_only = 0,
+		.secure_only = 0U,
 	},
 
 	/* IPI5 IPI */
 	[IPI_ID_5] = {
 		.ipi_bit_mask = IPI5_TRIG_BIT,
 		.ipi_reg_base = IPI5_REG_BASE,
-		.secure_only = 0,
+		.secure_only = 0U,
 	},
 };
 
diff --git a/plat/xilinx/zynqmp/bl31_zynqmp_setup.c b/plat/xilinx/zynqmp/bl31_zynqmp_setup.c
index 47be4e1..58eee3a 100644
--- a/plat/xilinx/zynqmp/bl31_zynqmp_setup.c
+++ b/plat/xilinx/zynqmp/bl31_zynqmp_setup.c
@@ -68,7 +68,7 @@
 {
 	uint64_t atf_handoff_addr;
 
-	if (ZYNQMP_CONSOLE_IS(cadence)) {
+	if (ZYNQMP_CONSOLE_IS(cadence) || (ZYNQMP_CONSOLE_IS(cadence1))) {
 		/* Register the console to provide early debug support */
 		static console_t bl31_boot_console;
 		(void)console_cdns_register(ZYNQMP_UART_BASE,
diff --git a/plat/xilinx/zynqmp/platform.mk b/plat/xilinx/zynqmp/platform.mk
index d075a56..3d98584 100644
--- a/plat/xilinx/zynqmp/platform.mk
+++ b/plat/xilinx/zynqmp/platform.mk
@@ -118,6 +118,7 @@
 endif
 
 BL31_CPPFLAGS		+=	-fno-jump-tables
+TF_CFLAGS_aarch64	+=	-mbranch-protection=none
 
 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.")
diff --git a/services/arm_arch_svc/arm_arch_svc_setup.c b/services/arm_arch_svc/arm_arch_svc_setup.c
index 1d4423c..5523a1c 100644
--- a/services/arm_arch_svc/arm_arch_svc_setup.c
+++ b/services/arm_arch_svc/arm_arch_svc_setup.c
@@ -11,19 +11,9 @@
 #include <lib/cpus/wa_cve_2018_3639.h>
 #include <lib/smccc.h>
 #include <services/arm_arch_svc.h>
-#include <services/rmi_svc.h>
-#include <services/rmmd_svc.h>
 #include <smccc_helpers.h>
 #include <plat/common/platform.h>
 
-#if ENABLE_RME
-/* Setup Arm architecture Services */
-static int32_t arm_arch_svc_setup(void)
-{
-	return rmmd_setup();
-}
-#endif
-
 static int32_t smccc_version(void)
 {
 	return MAKE_SMCCC_VERSION(SMCCC_MAJOR_VERSION, SMCCC_MINOR_VERSION);
@@ -143,16 +133,6 @@
 		SMC_RET0(handle);
 #endif
 	default:
-#if ENABLE_RME
-		/*
-		 * RMI functions are allocated from the Arch service range. Call
-		 * the RMM dispatcher to handle RMI calls.
-		 */
-		if (is_rmi_fid(smc_fid)) {
-			return rmmd_rmi_handler(smc_fid, x1, x2, x3, x4, cookie,
-						handle, flags);
-		}
-#endif
 		WARN("Unimplemented Arm Architecture Service Call: 0x%x \n",
 			smc_fid);
 		SMC_RET1(handle, SMC_UNK);
@@ -165,10 +145,6 @@
 		OEN_ARM_START,
 		OEN_ARM_END,
 		SMC_TYPE_FAST,
-#if ENABLE_RME
-		arm_arch_svc_setup,
-#else
 		NULL,
-#endif
 		arm_arch_svc_smc_handler
 );
diff --git a/services/std_svc/rmmd/rmmd_main.c b/services/std_svc/rmmd/rmmd_main.c
index e9004c7..c4ea706 100644
--- a/services/std_svc/rmmd/rmmd_main.c
+++ b/services/std_svc/rmmd/rmmd_main.c
@@ -30,6 +30,7 @@
 #include <services/rmi_svc.h>
 #include <services/rmmd_svc.h>
 #include <smccc_helpers.h>
+#include <lib/extensions/sve.h>
 #include "rmmd_initial_context.h"
 #include "rmmd_private.h"
 
@@ -112,6 +113,26 @@
 }
 
 /*******************************************************************************
+ * Enable architecture extensions on first entry to Realm world.
+ ******************************************************************************/
+static void manage_extensions_realm(cpu_context_t *ctx)
+{
+#if ENABLE_SVE_FOR_NS
+	/*
+	 * Enable SVE and FPU in realm context when it is enabled for NS.
+	 * Realm manager must ensure that the SVE and FPU register
+	 * contexts are properly managed.
+	 */
+	sve_enable(ctx);
+#else
+	/*
+	 * Disable SVE and FPU in realm context when it is disabled for NS.
+	 */
+	sve_disable(ctx);
+#endif /* ENABLE_SVE_FOR_NS */
+}
+
+/*******************************************************************************
  * Jump to the RMM for the first time.
  ******************************************************************************/
 static int32_t rmm_init(void)
@@ -124,6 +145,9 @@
 	INFO("RMM init start.\n");
 	ctx->state = RMM_STATE_RESET;
 
+	/* Enable architecture extensions */
+	manage_extensions_realm(&ctx->cpu_ctx);
+
 	/* Initialize RMM EL2 context. */
 	rmm_el2_context_init(&ctx->cpu_ctx.el2_sysregs_ctx);
 
@@ -281,6 +305,9 @@
 	/* Initialise RMM context with this entry point information */
 	cm_setup_context(&ctx->cpu_ctx, rmm_ep_info);
 
+	/* Enable architecture extensions */
+	manage_extensions_realm(&ctx->cpu_ctx);
+
 	/* Initialize RMM EL2 context. */
 	rmm_el2_context_init(&ctx->cpu_ctx.el2_sysregs_ctx);
 
diff --git a/services/std_svc/std_svc_setup.c b/services/std_svc/std_svc_setup.c
index 39db429..eea7e14 100644
--- a/services/std_svc/std_svc_setup.c
+++ b/services/std_svc/std_svc_setup.c
@@ -15,6 +15,7 @@
 #include <lib/runtime_instr.h>
 #include <services/gtsi_svc.h>
 #include <services/pci_svc.h>
+#include <services/rmi_svc.h>
 #include <services/rmmd_svc.h>
 #include <services/sdei.h>
 #include <services/spm_mm_svc.h>
@@ -62,6 +63,12 @@
 	}
 #endif
 
+#if ENABLE_RME
+	if (rmmd_setup() != 0) {
+		ret = 1;
+	}
+#endif
+
 #if SDEI_SUPPORT
 	/* SDEI initialisation */
 	sdei_init();
@@ -169,6 +176,11 @@
 		return rmmd_gtsi_handler(smc_fid, x1, x2, x3, x4, cookie,
 						handle, flags);
 	}
+
+	if (is_rmi_fid(smc_fid)) {
+		return rmmd_rmi_handler(smc_fid, x1, x2, x3, x4, cookie,
+					handle, flags);
+	}
 #endif
 
 #if SMC_PCI_SUPPORT
diff --git a/tools/fiptool/fiptool.c b/tools/fiptool/fiptool.c
index d92c31d..5c240b5 100644
--- a/tools/fiptool/fiptool.c
+++ b/tools/fiptool/fiptool.c
@@ -537,7 +537,7 @@
 	for (desc = image_desc_head; desc != NULL; desc = desc->next) {
 		image_t *image = desc->image;
 
-		if (image == NULL)
+		if (image == NULL || (image->toc_e.size == 0ULL))
 			continue;
 		payload_size += image->toc_e.size;
 		entry_offset = (entry_offset + align - 1) & ~(align - 1);