Merge "fix(errata): workaround for Cortex-A710 erratum 2371105" into integration
diff --git a/changelog.yaml b/changelog.yaml
index 01e91b4..c4028c4 100644
--- a/changelog.yaml
+++ b/changelog.yaml
@@ -1051,6 +1051,13 @@
             deprecated:
               - fdts stm32mp1
 
+            subsections:
+              - title: STM32MP13
+                scope: stm32mp13-fdts
+
+              - title: STM32MP15
+                scope: stm32mp15-fdts
+
       - title: PIE
         scope: pie
 
diff --git a/common/fdt_fixup.c b/common/fdt_fixup.c
index b1d628c..1bad74f 100644
--- a/common/fdt_fixup.c
+++ b/common/fdt_fixup.c
@@ -583,3 +583,44 @@
 						   (ac + sc + ac) * 4,
 						   val, sc * 4);
 }
+/**
+ * fdt_set_mac_address () - store MAC address in device tree
+ * @dtb:	pointer to the device tree blob in memory
+ * @eth_idx:	number of Ethernet interface in /aliases node
+ * @mac_addr:	pointer to 6 byte MAC address to store
+ *
+ * Use the generic local-mac-address property in a network device DT node
+ * to define the MAC address this device should be using. Many platform
+ * network devices lack device-specific non-volatile storage to hold this
+ * address, and leave it up to firmware to find and store a unique MAC
+ * address in the DT.
+ * The MAC address could be read from some board or firmware defined storage,
+ * or could be derived from some other unique property like a serial number.
+ *
+ * Return: 0 on success, a negative libfdt error value otherwise.
+ */
+int fdt_set_mac_address(void *dtb, unsigned int ethernet_idx,
+			const uint8_t *mac_addr)
+{
+	char eth_alias[12];
+	const char *path;
+	int node;
+
+	if (ethernet_idx > 9U) {
+		return -FDT_ERR_BADVALUE;
+	}
+	snprintf(eth_alias, sizeof(eth_alias), "ethernet%d", ethernet_idx);
+
+	path = fdt_get_alias(dtb, eth_alias);
+	if (path == NULL) {
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	node = fdt_path_offset(dtb, path);
+	if (node < 0) {
+		ERROR("Path \"%s\" not found in DT: %d\n", path, node);
+		return node;
+	}
+
+	return fdt_setprop(dtb, node, "local-mac-address", mac_addr, 6);
+}
diff --git a/docs/about/maintainers.rst b/docs/about/maintainers.rst
index 52cf93a..d16b5dd 100644
--- a/docs/about/maintainers.rst
+++ b/docs/about/maintainers.rst
@@ -113,14 +113,22 @@
 :|G|: `ManishVB-Arm`_
 :|F|: bl31/ehf.c
 
+Realm Management Monitor Dispatcher (RMMD)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+:|M|: Javier Almansa Sobrino <javier.almansasobrino@arm.com>
+:|G|: `javieralso-arm`_
+:|F|: services/std_svc/rmmd/\*
+:|F|: include/services/rmmd_svc.h
+:|F|: include/services/rmm_core_manifest.h
+
 Realm Management Extension (RME)
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 :|M|: Bipin Ravi <bipin.ravi@arm.com>
 :|G|: `bipinravi-arm`_
 :|M|: Mark Dykes <mark.dykes@arm.com>
 :|G|: `mardyk01`_
-:|M|: Zelalem Aweke <Zelalem.Aweke@arm.com>
-:|G|: `zelalem-aweke`_
+:|M|: Javier Almansa Sobrino <javier.almansasobrino@arm.com>
+:|G|: `javieralso-arm`_
 
 Drivers, Libraries and Framework Code
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/docs/design/cpu-specific-build-macros.rst b/docs/design/cpu-specific-build-macros.rst
index e36ac1f..de3b9bc 100644
--- a/docs/design/cpu-specific-build-macros.rst
+++ b/docs/design/cpu-specific-build-macros.rst
@@ -325,6 +325,12 @@
   Cortex-A78 AE CPU. This needs to be enabled for revisions r0p0 and r0p1. This
   erratum is still open.
 
+For Cortex-A78C, the following errata build flags are defined :
+
+- ``ERRATA_A78C_2132064`` : This applies errata 2132064 workaround to
+  Cortex-A78C CPU. This needs to be enabled for revisions r0p1, r0p2 and
+  it is still open.
+
 For Cortex-X1 CPU, the following errata build flags are defined:
 
 - ``ERRATA_X1_1821534`` : This applies errata 1821534 workaround to Cortex-X1
@@ -502,6 +508,10 @@
 -  ``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.
 
+-  ``ERRATA_N2_2388450``: This applies errata 2388450 workaround to Neoverse-N2
+   CPU. This needs to be enabled for revision r0p0 of the CPU, it is fixed in
+   r0p1.
+
 For Cortex-X2, the following errata build flags are defined :
 
 -  ``ERRATA_X2_2002765``: This applies errata 2002765 workaround to Cortex-X2
diff --git a/docs/design/trusted-board-boot-build.rst b/docs/design/trusted-board-boot-build.rst
index dd61b61..c3f3a2f 100644
--- a/docs/design/trusted-board-boot-build.rst
+++ b/docs/design/trusted-board-boot-build.rst
@@ -35,6 +35,13 @@
    By default, this will use the Chain of Trust described in the TBBR-client
    document. To select a different one, use the ``COT`` build option.
 
+   If using a custom build of OpenSSL, set the ``OPENSSL_DIR`` variable
+   accordingly so it points at the OpenSSL installation path, as explained in
+   :ref:`Build Options`. In addition, set the ``LD_LIBRARY_PATH`` variable
+   when running to point at the custom OpenSSL path, so the OpenSSL libraries
+   are loaded from that path instead of the default OS path. Export this
+   variable if necessary.
+
    In the case of Arm platforms, the location of the ROTPK hash must also be
    specified at build time. The following locations are currently supported (see
    ``ARM_ROTPK_LOCATION`` build option):
@@ -63,7 +70,7 @@
        make PLAT=<platform> TRUSTED_BOARD_BOOT=1 GENERATE_COT=1        \
        ARM_ROTPK_LOCATION=devel_rsa                                    \
        ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem        \
-       BL33=<path-to>/<bl33_image>                                     \
+       BL33=<path-to>/<bl33_image> OPENSSL_DIR=<path-to>/<openssl>     \
        all fip
 
    The result of this build will be the bl1.bin and the fip.bin binaries. This
@@ -87,7 +94,7 @@
        make PLAT=juno TRUSTED_BOARD_BOOT=1 GENERATE_COT=1              \
        ARM_ROTPK_LOCATION=devel_rsa                                    \
        ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem        \
-       BL33=<path-to>/<bl33_image>                                     \
+       BL33=<path-to>/<bl33_image> OPENSSL_DIR=<path-to>/<openssl>     \
        SCP_BL2=<path-to>/<scp_bl2_image>                               \
        SCP_BL2U=<path-to>/<scp_bl2u_image>                             \
        NS_BL2U=<path-to>/<ns_bl2u_image>                               \
@@ -109,7 +116,7 @@
 
 --------------
 
-*Copyright (c) 2019-2020, Arm Limited. All rights reserved.*
+*Copyright (c) 2019-2022, Arm Limited. All rights reserved.*
 
 .. _mbed TLS Repository: https://github.com/ARMmbed/mbedtls.git
 .. _mbed TLS Security Center: https://tls.mbed.org/security
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index 26d5458..b291d62 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -974,9 +974,10 @@
   bit, to trap access to the RAS ERR and RAS ERX registers from lower ELs.
   This flag is disabled by default.
 
-- ``OPENSSL_DIR``: This flag is used to provide the installed openssl directory
-  path on the host machine which is used to build certificate generation and
-  firmware encryption tool.
+- ``OPENSSL_DIR``: This option is used to provide the path to a directory on the
+  host machine where a custom installation of OpenSSL is located, which is used
+  to build the certificate generation, firmware encryption and FIP tools. If
+  this option is not set, the default OS installation will be used.
 
 - ``USE_SP804_TIMER``: Use the SP804 timer instead of the Generic Timer for
   functions that wait for an arbitrary time length (udelay and mdelay). The
diff --git a/docs/getting_started/porting-guide.rst b/docs/getting_started/porting-guide.rst
index d49ddeb..77ee897 100644
--- a/docs/getting_started/porting-guide.rst
+++ b/docs/getting_started/porting-guide.rst
@@ -1665,6 +1665,42 @@
 must return 0, otherwise it must return 1. The default implementation
 of this always returns 0.
 
+Function : bl2_plat_mboot_init() [optional]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+    Argument : void
+    Return   : void
+
+When the MEASURED_BOOT flag is enabled:
+
+-  This function is used to initialize the backend driver(s) of measured boot.
+-  On the Arm FVP port, this function is used to initialize the Event Log
+   backend driver with the Event Log buffer information (base address and
+   size) received from BL1. It results in panic on error.
+
+When the MEASURED_BOOT flag is disabled, this function doesn't do anything.
+
+Function : bl2_plat_mboot_finish() [optional]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+    Argument : void
+    Return   : void
+
+When the MEASURED_BOOT flag is enabled:
+
+-  This function is used to finalize the measured boot backend driver(s),
+   and also, set the information for the next bootloader component to extend
+   the measurement if needed.
+-  On the Arm FVP port, this function is used to pass the Event Log buffer
+   information (base address and size) to non-secure(BL33) and trusted OS(BL32)
+   via nt_fw and tos_fw config respectively. It results in panic on error.
+
+When the MEASURED_BOOT flag is disabled, this function doesn't do anything.
+
 Boot Loader Stage 2 (BL2) at EL3
 --------------------------------
 
@@ -1822,42 +1858,6 @@
 This function returns 0 on success, a negative error code otherwise.
 This function is included if SCP_BL2U_BASE is defined.
 
-Function : bl2_plat_mboot_init() [optional]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-::
-
-    Argument : void
-    Return   : void
-
-When the MEASURED_BOOT flag is enabled:
-
--  This function is used to initialize the backend driver(s) of measured boot.
--  On the Arm FVP port, this function is used to initialize the Event Log
-   backend driver with the Event Log buffer information (base address and
-   size) received from BL1. It results in panic on error.
-
-When the MEASURED_BOOT flag is disabled, this function doesn't do anything.
-
-Function : bl2_plat_mboot_finish() [optional]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-::
-
-    Argument : void
-    Return   : void
-
-When the MEASURED_BOOT flag is enabled:
-
--  This function is used to finalize the measured boot backend driver(s),
-   and also, set the information for the next bootloader component to extend
-   the measurement if needed.
--  On the Arm FVP port, this function is used to pass the Event Log buffer
-   information (base address and size) to non-secure(BL33) and trusted OS(BL32)
-   via nt_fw and tos_fw config respectively. It results in panic on error.
-
-When the MEASURED_BOOT flag is disabled, this function doesn't do anything.
-
 Boot Loader Stage 3-1 (BL31)
 ----------------------------
 
diff --git a/docs/getting_started/prerequisites.rst b/docs/getting_started/prerequisites.rst
index 0b8a71c..81c55a5 100644
--- a/docs/getting_started/prerequisites.rst
+++ b/docs/getting_started/prerequisites.rst
@@ -7,6 +7,7 @@
 It may possible to build |TF-A| with combinations of software packages that are
 different from those listed below, however only the software described in this
 document can be officially supported.
+
 Build Host
 ----------
 
@@ -57,6 +58,12 @@
 
    Required to build the cert_create tool.
 
+   .. note::
+
+    OpenSSL 3.0 has to be built from source code, as it's not available in
+    the default package repositories in recent Ubuntu versions. Please refer
+    to the OpenSSL project documentation for more information.
+
 The following libraries are required for Trusted Board Boot and Measured Boot
 support:
 
@@ -89,7 +96,7 @@
 
 .. code:: shell
 
-    sudo apt install build-essential git libssl-dev
+    sudo apt install build-essential git
 
 The optional packages can be installed using:
 
diff --git a/docs/getting_started/tools-build.rst b/docs/getting_started/tools-build.rst
index c050f58..daf7e06 100644
--- a/docs/getting_started/tools-build.rst
+++ b/docs/getting_started/tools-build.rst
@@ -1,6 +1,16 @@
 Building Supporting Tools
 =========================
 
+.. note::
+
+    OpenSSL 3.0 is needed in order to build the tools. A custom installation
+    can be used if not updating the OpenSSL version on the OS. In order to do
+    this, use the ``OPENSSL_DIR`` variable after the ``make`` command to
+    indicate the location of the custom OpenSSL build. Then, to run the tools,
+    use the ``LD_LIBRARY_PATH`` to indicate the location of the built
+    libraries. More info about ``OPENSSL_DIR`` can be found at
+    :ref:`Build Options`.
+
 Building and using the FIP tool
 -------------------------------
 
@@ -164,4 +174,4 @@
 
 --------------
 
-*Copyright (c) 2019, Arm Limited. All rights reserved.*
+*Copyright (c) 2019-2022, Arm Limited. All rights reserved.*
diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c
index 7db6c0b..47ff26b 100644
--- a/drivers/ufs/ufs.c
+++ b/drivers/ufs/ufs.c
@@ -225,8 +225,7 @@
 			}
 			continue;
 		}
-		while ((mmio_read_32(base + HCS) & HCS_DP) == 0)
-			;
+		assert((mmio_read_32(base + HCS) & HCS_DP) == 0);
 		data = mmio_read_32(base + IS);
 		if (data & UFS_INT_ULSS)
 			mmio_write_32(base + IS, UFS_INT_ULSS);
@@ -482,9 +481,7 @@
 	mmio_write_32(ufs_params.reg_base + IS, ~0);
 
 	mmio_write_32(ufs_params.reg_base + UTRLRSR, 1);
-	do {
-		data = mmio_read_32(ufs_params.reg_base + UTRLRSR);
-	} while (data == 0);
+	assert(mmio_read_32(ufs_params.reg_base + UTRLRSR) == 1);
 
 	data = UTRIACR_IAEN | UTRIACR_CTR | UTRIACR_IACTH(0x1F) |
 	       UTRIACR_IATOVAL(0xFF);
diff --git a/fdts/stm32mp131.dtsi b/fdts/stm32mp131.dtsi
index decd812..e4d9d3b 100644
--- a/fdts/stm32mp131.dtsi
+++ b/fdts/stm32mp131.dtsi
@@ -383,7 +383,7 @@
 			status = "disabled";
 		};
 
-		ddr: ddr@5a003000{
+		ddr: ddr@5a003000 {
 			compatible = "st,stm32mp13-ddr";
 			reg = <0x5a003000 0x550>, <0x5a004000 0x234>;
 			clocks = <&rcc AXIDCG>,
diff --git a/fdts/stm32mp15-ddr3-dhsom-2x4Gb-1066-binG.dtsi b/fdts/stm32mp15-ddr3-dhsom-2x4Gb-1066-binG.dtsi
new file mode 100644
index 0000000..ff184c2
--- /dev/null
+++ b/fdts/stm32mp15-ddr3-dhsom-2x4Gb-1066-binG.dtsi
@@ -0,0 +1,108 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause
+/*
+ * Copyright (C) 2020, DH electronics - All Rights Reserved
+ *
+ * STM32MP15xx DHSOM configuration
+ * 2x DDR3L 4Gb each, 16-bit, 533MHz, Single Die Package in flyby topology.
+ * Reference used W634GU6NB15I from Winbond
+ *
+ * DDR type / Platform	DDR3/3L
+ * freq		533MHz
+ * width	32
+ * datasheet	0  = W634GU6NB15I / DDR3-1333
+ * DDR density	8
+ * timing mode	optimized
+ * address mapping : RBC
+ * Tc > + 85C : J
+ */
+
+#define DDR_MEM_NAME "DDR3L 32bits 2x4Gb 533MHz"
+#define DDR_MEM_SPEED 533000
+#define DDR_MEM_SIZE 0x40000000
+
+#define DDR_MSTR 0x00040401
+#define DDR_MRCTRL0 0x00000010
+#define DDR_MRCTRL1 0x00000000
+#define DDR_DERATEEN 0x00000000
+#define DDR_DERATEINT 0x00800000
+#define DDR_PWRCTL 0x00000000
+#define DDR_PWRTMG 0x00400010
+#define DDR_HWLPCTL 0x00000000
+#define DDR_RFSHCTL0 0x00210000
+#define DDR_RFSHCTL3 0x00000000
+#define DDR_RFSHTMG 0x0040008B
+#define DDR_CRCPARCTL0 0x00000000
+#define DDR_DRAMTMG0 0x121B1214
+#define DDR_DRAMTMG1 0x000A041C
+#define DDR_DRAMTMG2 0x0608090F
+#define DDR_DRAMTMG3 0x0050400C
+#define DDR_DRAMTMG4 0x08040608
+#define DDR_DRAMTMG5 0x06060403
+#define DDR_DRAMTMG6 0x02020002
+#define DDR_DRAMTMG7 0x00000202
+#define DDR_DRAMTMG8 0x00001005
+#define DDR_DRAMTMG14 0x000000A0
+#define DDR_ZQCTL0 0xC2000040
+#define DDR_DFITMG0 0x02060105
+#define DDR_DFITMG1 0x00000202
+#define DDR_DFILPCFG0 0x07000000
+#define DDR_DFIUPD0 0xC0400003
+#define DDR_DFIUPD1 0x00000000
+#define DDR_DFIUPD2 0x00000000
+#define DDR_DFIPHYMSTR 0x00000000
+#define DDR_ODTCFG 0x06000600
+#define DDR_ODTMAP 0x00000001
+#define DDR_SCHED 0x00000C01
+#define DDR_SCHED1 0x00000000
+#define DDR_PERFHPR1 0x01000001
+#define DDR_PERFLPR1 0x08000200
+#define DDR_PERFWR1 0x08000400
+#define DDR_DBG0 0x00000000
+#define DDR_DBG1 0x00000000
+#define DDR_DBGCMD 0x00000000
+#define DDR_POISONCFG 0x00000000
+#define DDR_PCCFG 0x00000010
+#define DDR_PCFGR_0 0x00010000
+#define DDR_PCFGW_0 0x00000000
+#define DDR_PCFGQOS0_0 0x02100C03
+#define DDR_PCFGQOS1_0 0x00800100
+#define DDR_PCFGWQOS0_0 0x01100C03
+#define DDR_PCFGWQOS1_0 0x01000200
+#define DDR_PCFGR_1 0x00010000
+#define DDR_PCFGW_1 0x00000000
+#define DDR_PCFGQOS0_1 0x02100C03
+#define DDR_PCFGQOS1_1 0x00800040
+#define DDR_PCFGWQOS0_1 0x01100C03
+#define DDR_PCFGWQOS1_1 0x01000200
+#define DDR_ADDRMAP1 0x00080808
+#define DDR_ADDRMAP2 0x00000000
+#define DDR_ADDRMAP3 0x00000000
+#define DDR_ADDRMAP4 0x00001F1F
+#define DDR_ADDRMAP5 0x07070707
+#define DDR_ADDRMAP6 0x0F070707
+#define DDR_ADDRMAP9 0x00000000
+#define DDR_ADDRMAP10 0x00000000
+#define DDR_ADDRMAP11 0x00000000
+#define DDR_PGCR 0x01442E02
+#define DDR_PTR0 0x0022AA5B
+#define DDR_PTR1 0x04841104
+#define DDR_PTR2 0x042DA068
+#define DDR_ACIOCR 0x10400812
+#define DDR_DXCCR 0x00000C40
+#define DDR_DSGCR 0xF200011F
+#define DDR_DCR 0x0000000B
+#define DDR_DTPR0 0x38D488D0
+#define DDR_DTPR1 0x098B00D8
+#define DDR_DTPR2 0x10023600
+#define DDR_MR0 0x00000840
+#define DDR_MR1 0x00000000
+#define DDR_MR2 0x00000248
+#define DDR_MR3 0x00000000
+#define DDR_ODTCR 0x00010000
+#define DDR_ZQ0CR1 0x00000038
+#define DDR_DX0GCR 0x0000CE81
+#define DDR_DX1GCR 0x0000CE81
+#define DDR_DX2GCR 0x0000CE81
+#define DDR_DX3GCR 0x0000CE81
+
+#include "stm32mp15-ddr.dtsi"
diff --git a/fdts/stm32mp15-pinctrl.dtsi b/fdts/stm32mp15-pinctrl.dtsi
index d74dc2b..1b5fbc6 100644
--- a/fdts/stm32mp15-pinctrl.dtsi
+++ b/fdts/stm32mp15-pinctrl.dtsi
@@ -114,7 +114,7 @@
 			drive-push-pull;
 			bias-pull-up;
 		};
-		pins2{
+		pins2 {
 			pinmux = <STM32_PINMUX('E', 4, AF8)>; /* SDMMC1_CKIN */
 			bias-pull-up;
 		};
diff --git a/fdts/stm32mp151.dtsi b/fdts/stm32mp151.dtsi
index 20071fe..575d61e 100644
--- a/fdts/stm32mp151.dtsi
+++ b/fdts/stm32mp151.dtsi
@@ -360,7 +360,7 @@
 			status = "disabled";
 		};
 
-		ddr: ddr@5a003000{
+		ddr: ddr@5a003000 {
 			compatible = "st,stm32mp1-ddr";
 			reg = <0x5A003000 0x550 0x5A004000 0x234>;
 			clocks = <&rcc AXIDCG>,
diff --git a/fdts/stm32mp157c-dhcom-pdk2-fw-config.dts b/fdts/stm32mp157c-dhcom-pdk2-fw-config.dts
new file mode 100644
index 0000000..6a5a192
--- /dev/null
+++ b/fdts/stm32mp157c-dhcom-pdk2-fw-config.dts
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause
+/*
+ * Copyright (c) 2022 DH electronics GmbH
+ */
+
+#define DDR_SIZE 0x40000000 /* 1GB */
+#include "stm32mp15-fw-config.dtsi"
diff --git a/fdts/stm32mp157c-dhcom-pdk2.dts b/fdts/stm32mp157c-dhcom-pdk2.dts
new file mode 100644
index 0000000..370a69a
--- /dev/null
+++ b/fdts/stm32mp157c-dhcom-pdk2.dts
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause
+/*
+ * Copyright (C) 2019-2020 Marek Vasut <marex@denx.de>
+ * Copyright (C) 2022 DH electronics GmbH
+ *
+ * DHCOM STM32MP1 variant:
+ * DHCM-STM32MP157C-C065-R102-F0819-SPI-E2-CAN2-SDR104-RTC-WBT-T-DSI-I-01D2
+ * DHCOM PCB number: 587-200 or newer
+ * PDK2 PCB number: 516-400 or newer
+ */
+/dts-v1/;
+
+#include "stm32mp157.dtsi"
+#include "stm32mp15xc.dtsi"
+#include "stm32mp15xx-dhcom-som.dtsi"
+#include "stm32mp15xx-dhcom-pdk2.dtsi"
+
+/ {
+	model = "DH electronics STM32MP157C DHCOM Premium Developer Kit (2)";
+	compatible = "dh,stm32mp157c-dhcom-pdk2", "dh,stm32mp157c-dhcom-som",
+		     "st,stm32mp157";
+};
+
+&cryp1 {
+	status = "okay";
+};
diff --git a/fdts/stm32mp15xx-dhcom-pdk2.dtsi b/fdts/stm32mp15xx-dhcom-pdk2.dtsi
new file mode 100644
index 0000000..1ffc60d
--- /dev/null
+++ b/fdts/stm32mp15xx-dhcom-pdk2.dtsi
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause
+/*
+ * Copyright (C) 2019-2020 Marek Vasut <marex@denx.de>
+ * Copyright (C) 2022 DH electronics GmbH
+ */
+
+/ {
+	aliases {
+		serial0 = &uart4;
+		serial1 = &usart3;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&usart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&usart3_pins_a>;
+	status = "okay";
+};
+
+&usbotg_hs {
+	dr_mode = "otg";
+	pinctrl-0 = <&usbotg_hs_pins_a>;
+	pinctrl-names = "default";
+	phy-names = "usb2-phy";
+	phys = <&usbphyc_port1 0>;
+	vbus-supply = <&vbus_otg>;
+	status = "okay";
+};
+
+&usbphyc {
+	status = "okay";
+};
+
+&usbphyc_port0 {
+	phy-supply = <&vdd_usb>;
+};
+
+&usbphyc_port1 {
+	phy-supply = <&vdd_usb>;
+};
diff --git a/fdts/stm32mp15xx-dhcom-som.dtsi b/fdts/stm32mp15xx-dhcom-som.dtsi
new file mode 100644
index 0000000..3021ef8
--- /dev/null
+++ b/fdts/stm32mp15xx-dhcom-som.dtsi
@@ -0,0 +1,338 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause
+/*
+ * Copyright (C) 2019-2020 Marek Vasut <marex@denx.de>
+ * Copyright (C) 2022 DH electronics GmbH
+ */
+
+#include "stm32mp15-pinctrl.dtsi"
+#include "stm32mp15xxaa-pinctrl.dtsi"
+#include <dt-bindings/clock/stm32mp1-clksrc.h>
+#include "stm32mp15-ddr3-dhsom-2x4Gb-1066-binG.dtsi"
+
+/ {
+	memory@c0000000 {
+		device_type = "memory";
+		reg = <0xC0000000 0x40000000>;
+	};
+};
+
+&bsec {
+	board_id: board_id@ec {
+		reg = <0xec 0x4>;
+		st,non-secure-otp;
+	};
+};
+
+&cpu0 {
+	cpu-supply = <&vddcore>;
+};
+
+&cpu1 {
+	cpu-supply = <&vddcore>;
+};
+
+&hash1 {
+	status = "okay";
+};
+
+&i2c4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c4_pins_a>;
+	i2c-scl-rising-time-ns = <185>;
+	i2c-scl-falling-time-ns = <20>;
+	status = "okay";
+
+	pmic: stpmic@33 {
+		compatible = "st,stpmic1";
+		reg = <0x33>;
+		interrupts-extended = <&gpioa 0 IRQ_TYPE_EDGE_FALLING>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		status = "okay";
+
+		regulators {
+			compatible = "st,stpmic1-regulators";
+			ldo1-supply = <&v3v3>;
+			ldo2-supply = <&v3v3>;
+			ldo3-supply = <&vdd_ddr>;
+			ldo5-supply = <&v3v3>;
+			ldo6-supply = <&v3v3>;
+			pwr_sw1-supply = <&bst_out>;
+			pwr_sw2-supply = <&bst_out>;
+
+			vddcore: buck1 {
+				regulator-name = "vddcore";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-always-on;
+				regulator-initial-mode = <0>;
+				regulator-over-current-protection;
+			};
+
+			vdd_ddr: buck2 {
+				regulator-name = "vdd_ddr";
+				regulator-min-microvolt = <1350000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-always-on;
+				regulator-initial-mode = <0>;
+				regulator-over-current-protection;
+			};
+
+			vdd: buck3 {
+				regulator-name = "vdd";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+				st,mask-reset;
+				regulator-initial-mode = <0>;
+				regulator-over-current-protection;
+			};
+
+			v3v3: buck4 {
+				regulator-name = "v3v3";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+				regulator-over-current-protection;
+				regulator-initial-mode = <0>;
+			};
+
+			vdda: ldo1 {
+				regulator-name = "vdda";
+				regulator-min-microvolt = <2900000>;
+				regulator-max-microvolt = <2900000>;
+				regulator-always-on;
+			};
+
+			v2v8: ldo2 {
+				regulator-name = "v2v8";
+				regulator-min-microvolt = <2800000>;
+				regulator-max-microvolt = <2800000>;
+			};
+
+			vtt_ddr: ldo3 {
+				regulator-name = "vtt_ddr";
+				regulator-always-on;
+				regulator-over-current-protection;
+				st,regulator-sink-source;
+			};
+
+			vdd_usb: ldo4 {
+				regulator-name = "vdd_usb";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			vdd_sd: ldo5 {
+				regulator-name = "vdd_sd";
+				regulator-min-microvolt = <2900000>;
+				regulator-max-microvolt = <2900000>;
+				regulator-boot-on;
+			};
+
+			v1v8: ldo6 {
+				regulator-name = "v1v8";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+			};
+
+			vref_ddr: vref_ddr {
+				regulator-name = "vref_ddr";
+				regulator-always-on;
+			};
+
+			bst_out: boost {
+				regulator-name = "bst_out";
+			};
+
+			vbus_otg: pwr_sw1 {
+				regulator-name = "vbus_otg";
+			};
+
+			vbus_sw: pwr_sw2 {
+				regulator-name = "vbus_sw";
+				regulator-active-discharge = <1>;
+			};
+		};
+	};
+};
+
+&iwdg2 {
+	timeout-sec = <32>;
+	status = "okay";
+	secure-status = "okay";
+};
+
+&pwr_regulators {
+	vdd-supply = <&vdd>;
+	vdd_3v3_usbfs-supply = <&vdd_usb>;
+};
+
+&qspi {
+	pinctrl-names = "default";
+	pinctrl-0 = <&qspi_clk_pins_a &qspi_bk1_pins_a>;
+	reg = <0x58003000 0x1000>, <0x70000000 0x4000000>;
+	#address-cells = <1>;
+	#size-cells = <0>;
+	status = "okay";
+
+	flash0: flash@0 {
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+		spi-rx-bus-width = <4>;
+		spi-max-frequency = <108000000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+	};
+};
+
+&rcc {
+	secure-status = "disabled";
+	st,clksrc = <
+		CLK_MPU_PLL1P
+		CLK_AXI_PLL2P
+		CLK_MCU_PLL3P
+		CLK_PLL12_HSE
+		CLK_PLL3_HSE
+		CLK_PLL4_HSE
+		CLK_RTC_LSE
+		CLK_MCO1_DISABLED
+		CLK_MCO2_PLL4P
+	>;
+
+	st,clkdiv = <
+		1 /*MPU*/
+		0 /*AXI*/
+		0 /*MCU*/
+		1 /*APB1*/
+		1 /*APB2*/
+		1 /*APB3*/
+		1 /*APB4*/
+		2 /*APB5*/
+		23 /*RTC*/
+		0 /*MCO1*/
+		1 /*MCO2*/
+	>;
+
+	st,pkcs = <
+		CLK_CKPER_HSE
+		CLK_FMC_ACLK
+		CLK_QSPI_ACLK
+		CLK_ETH_PLL4P
+		CLK_SDMMC12_PLL4P
+		CLK_DSI_DSIPLL
+		CLK_STGEN_HSE
+		CLK_USBPHY_HSE
+		CLK_SPI2S1_PLL3Q
+		CLK_SPI2S23_PLL3Q
+		CLK_SPI45_HSI
+		CLK_SPI6_HSI
+		CLK_I2C46_HSI
+		CLK_SDMMC3_PLL4P
+		CLK_USBO_USBPHY
+		CLK_ADC_CKPER
+		CLK_CEC_LSE
+		CLK_I2C12_HSI
+		CLK_I2C35_HSI
+		CLK_UART1_HSI
+		CLK_UART24_HSI
+		CLK_UART35_HSI
+		CLK_UART6_HSI
+		CLK_UART78_HSI
+		CLK_SPDIF_PLL4P
+		CLK_FDCAN_PLL4R
+		CLK_SAI1_PLL3Q
+		CLK_SAI2_PLL3Q
+		CLK_SAI3_PLL3Q
+		CLK_SAI4_PLL3Q
+		CLK_RNG1_LSI
+		CLK_RNG2_LSI
+		CLK_LPTIM1_PCLK1
+		CLK_LPTIM23_PCLK3
+		CLK_LPTIM45_LSE
+	>;
+
+	/* VCO = 1300.0 MHz => P = 650 (CPU) */
+	pll1: st,pll@0 {
+		compatible = "st,stm32mp1-pll";
+		reg = <0>;
+		cfg = <2 80 0 0 0 PQR(1,0,0)>;
+		frac = <0x800>;
+	};
+
+	/* VCO = 1066.0 MHz => P = 266 (AXI), Q = 533 (GPU), R = 533 (DDR) */
+	pll2: st,pll@1 {
+		compatible = "st,stm32mp1-pll";
+		reg = <1>;
+		cfg = <2 65 1 0 0 PQR(1,1,1)>;
+		frac = <0x1400>;
+	};
+
+	/* VCO = 417.8 MHz => P = 209, Q = 24, R = 11 */
+	pll3: st,pll@2 {
+		compatible = "st,stm32mp1-pll";
+		reg = <2>;
+		cfg = <1 33 1 16 36 PQR(1,1,1)>;
+		frac = <0x1a04>;
+	};
+
+	/* VCO = 600.0 MHz => P = 50, Q = 50, R = 50 */
+	pll4: st,pll@3 {
+		compatible = "st,stm32mp1-pll";
+		reg = <3>;
+		cfg = <1 49 5 11 11 PQR(1,1,1)>;
+	};
+};
+
+&rng1 {
+	status = "okay";
+};
+
+&rtc {
+	status = "okay";
+};
+
+&sdmmc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_a>;
+	disable-wp;
+	st,sig-dir;
+	st,neg-edge;
+	bus-width = <4>;
+	vmmc-supply = <&vdd_sd>;
+	status = "okay";
+};
+
+&sdmmc1_b4_pins_a {
+	/*
+	 * SD bus pull-up resistors:
+	 * - optional on SoMs with SD voltage translator
+	 * - mandatory on SoMs without SD voltage translator
+	 */
+	pins1 {
+		bias-pull-up;
+	};
+	pins2 {
+		bias-pull-up;
+	};
+};
+
+&sdmmc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_a>;
+	non-removable;
+	no-sd;
+	no-sdio;
+	st,neg-edge;
+	bus-width = <8>;
+	vmmc-supply = <&v3v3>;
+	vqmmc-supply = <&v3v3>;
+	mmc-ddr-3_3v;
+	status = "okay";
+};
+
+&uart4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart4_pins_a>;
+	status = "okay";
+};
diff --git a/fdts/stm32mp15xx-dkx.dtsi b/fdts/stm32mp15xx-dkx.dtsi
index 05eb46a..74e529d 100644
--- a/fdts/stm32mp15xx-dkx.dtsi
+++ b/fdts/stm32mp15xx-dkx.dtsi
@@ -33,11 +33,11 @@
 	st,digbypass;
 };
 
-&cpu0{
+&cpu0 {
 	cpu-supply = <&vddcore>;
 };
 
-&cpu1{
+&cpu1 {
 	cpu-supply = <&vddcore>;
 };
 
diff --git a/fdts/stm32mp15xx-osd32.dtsi b/fdts/stm32mp15xx-osd32.dtsi
index ca67235..c7ddc92 100644
--- a/fdts/stm32mp15xx-osd32.dtsi
+++ b/fdts/stm32mp15xx-osd32.dtsi
@@ -167,11 +167,11 @@
 	st,digbypass;
 };
 
-&cpu0{
+&cpu0 {
 	cpu-supply = <&vddcore>;
 };
 
-&cpu1{
+&cpu1 {
 	cpu-supply = <&vddcore>;
 };
 
diff --git a/include/common/fdt_fixup.h b/include/common/fdt_fixup.h
index c35e9be..9531bdb 100644
--- a/include/common/fdt_fixup.h
+++ b/include/common/fdt_fixup.h
@@ -32,5 +32,7 @@
 int fdt_add_cpu_idle_states(void *dtb, const struct psci_cpu_idle_state *state);
 int fdt_adjust_gic_redist(void *dtb, unsigned int nr_cores, uintptr_t gicr_base,
 			  unsigned int gicr_frame_size);
+int fdt_set_mac_address(void *dtb, unsigned int ethernet_idx,
+			const uint8_t *mac_addr);
 
 #endif /* FDT_FIXUP_H */
diff --git a/include/lib/cpus/aarch64/a64fx.h b/include/lib/cpus/aarch64/a64fx.h
new file mode 100644
index 0000000..b7342b0
--- /dev/null
+++ b/include/lib/cpus/aarch64/a64fx.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2022, Fujitsu Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef A64FX_H
+#define A64FX_H
+
+#include <lib/utils_def.h>
+
+/* A64FX midr for revision 0 */
+#define A64FX_MIDR					U(0x461f0010)
+
+#endif /* A64FX_H */
diff --git a/include/lib/cpus/aarch64/cortex_a78c.h b/include/lib/cpus/aarch64/cortex_a78c.h
index b1945ed..39e2adf 100644
--- a/include/lib/cpus/aarch64/cortex_a78c.h
+++ b/include/lib/cpus/aarch64/cortex_a78c.h
@@ -17,6 +17,8 @@
  * CPU Extended Control register specific definitions.
  ******************************************************************************/
 #define CORTEX_A78C_CPUECTLR_EL1		        S3_0_C15_C1_4
+#define CORTEX_A78C_CPUECTLR_EL1_BIT6		        (ULL(1) << 6)
+#define CORTEX_A78C_CPUECTLR_EL1_BIT7		        (ULL(1) << 7)
 
 /*******************************************************************************
  * CPU Power Control register specific definitions
diff --git a/include/lib/cpus/aarch64/neoverse_n2.h b/include/lib/cpus/aarch64/neoverse_n2.h
index 0452b39..5d41a13 100644
--- a/include/lib/cpus/aarch64/neoverse_n2.h
+++ b/include/lib/cpus/aarch64/neoverse_n2.h
@@ -38,6 +38,7 @@
  ******************************************************************************/
 #define NEOVERSE_N2_CPUACTLR2_EL1			S3_0_C15_C1_1
 #define NEOVERSE_N2_CPUACTLR2_EL1_BIT_2			(ULL(1) << 2)
+#define NEOVERSE_N2_CPUACTLR2_EL1_BIT_40		(ULL(1) << 40)
 
 /*******************************************************************************
  * CPU Auxiliary Control register 5 specific definitions.
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index 47fbe76..ab0e4ff 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -310,9 +310,14 @@
 					MT_MEMORY | MT_RW | MT_SECURE)
 
 #if ENABLE_RME
+/*
+ * We add the EL3_RMM_SHARED size to RMM mapping to map the region as a block.
+ * Else we end up requiring more pagetables in BL2 for ROMLIB build.
+ */
 #define ARM_MAP_RMM_DRAM	MAP_REGION_FLAT(			\
 					PLAT_ARM_RMM_BASE,		\
-					PLAT_ARM_RMM_SIZE,		\
+					(PLAT_ARM_RMM_SIZE + 		\
+					ARM_EL3_RMM_SHARED_SIZE),	\
 					MT_MEMORY | MT_RW | MT_REALM)
 
 
diff --git a/lib/cpus/aarch64/a64fx.S b/lib/cpus/aarch64/a64fx.S
new file mode 100644
index 0000000..54c20c3
--- /dev/null
+++ b/lib/cpus/aarch64/a64fx.S
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2022, Fujitsu Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <arch.h>
+#include <asm_macros.S>
+#include <assert_macros.S>
+#include <a64fx.h>
+#include <cpu_macros.S>
+#include <plat_macros.S>
+
+func a64fx_core_pwr_dwn
+endfunc a64fx_core_pwr_dwn
+
+func a64fx_cluster_pwr_dwn
+endfunc a64fx_cluster_pwr_dwn
+
+#if REPORT_ERRATA
+/*
+ * Errata printing function for A64FX. Must follow AAPCS.
+ */
+func a64fx_errata_report
+        ret
+endfunc a64fx_errata_report
+#endif
+
+        /* ---------------------------------------------
+         * This function provides cpu specific
+         * register information for crash reporting.
+         * It needs to return with x6 pointing to
+         * a list of register names in ascii and
+         * x8 - x15 having values of registers to be
+         * reported.
+         * ---------------------------------------------
+         */
+.section .rodata.a64fx_regs, "aS"
+a64fx_regs:  /* The ascii list of register names to be reported */
+        .asciz  ""
+
+func a64fx_cpu_reg_dump
+        adr     x6, a64fx_regs
+        ret
+endfunc a64fx_cpu_reg_dump
+
+declare_cpu_ops a64fx, A64FX_MIDR, CPU_NO_RESET_FUNC \
+                a64fx_core_pwr_dwn, \
+                a64fx_cluster_pwr_dwn
+
diff --git a/lib/cpus/aarch64/cortex_a78c.S b/lib/cpus/aarch64/cortex_a78c.S
index 0712109..f57ecaf 100644
--- a/lib/cpus/aarch64/cortex_a78c.S
+++ b/lib/cpus/aarch64/cortex_a78c.S
@@ -21,6 +21,43 @@
 	wa_cve_2022_23960_bhb_vector_table CORTEX_A78C_BHB_LOOP_COUNT, cortex_a78c
 #endif /* WORKAROUND_CVE_2022_23960 */
 
+/* --------------------------------------------------
+ * Errata Workaround for A78C Erratum 2132064.
+ * This applies to revisions r0p1 and r0p2 of A78C
+ * and is still open.
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x17
+ * --------------------------------------------------
+ */
+func errata_a78c_2132064_wa
+	/* Compare x0 against revisions r0p0 - r0p1 */
+	mov	x17, x30
+	bl	check_errata_2132064
+	cbz	x0, 1f
+
+	/* --------------------------------------------------------
+	 * Place the data prefetcher in the most conservative mode
+	 * to reduce prefetches by writing the following bits to
+	 * the value indicated: ecltr[7:6], PF_MODE = 2'b11
+	 * --------------------------------------------------------
+	 */
+	mrs	x0, CORTEX_A78C_CPUECTLR_EL1
+	orr	x0, x0, #CORTEX_A78C_CPUECTLR_EL1_BIT6
+	orr	x0, x0, #CORTEX_A78C_CPUECTLR_EL1_BIT7
+	msr	CORTEX_A78C_CPUECTLR_EL1, x0
+	isb
+1:
+	ret	x17
+endfunc errata_a78c_2132064_wa
+
+func check_errata_2132064
+	/* Applies to revisions r0p1 and r0p2. */
+	mov	x1, #CPU_REV(0, 1)
+	mov	x2, #CPU_REV(0, 2)
+	b	cpu_rev_var_range
+endfunc check_errata_2132064
+
 func check_errata_cve_2022_23960
 #if WORKAROUND_CVE_2022_23960
 	mov	x0, #ERRATA_APPLIES
@@ -35,6 +72,15 @@
 	 * -------------------------------------------------
 	 */
 func cortex_a78c_reset_func
+	mov	x19, x30
+	bl	cpu_get_rev_var
+	mov	x18, x0
+
+#if ERRATA_A78C_2132064
+	mov	x0, x18
+	bl	errata_a78c_2132064_wa
+#endif
+
 #if IMAGE_BL31 && WORKAROUND_CVE_2022_23960
 	/*
 	 * The Cortex-A78c generic vectors are overridden to apply errata
@@ -43,8 +89,9 @@
 	adr	x0, wa_cve_vbar_cortex_a78c
 	msr	vbar_el3, x0
 #endif /* IMAGE_BL31 && WORKAROUND_CVE_2022_23960 */
+
 	isb
-	ret
+	ret	x19
 endfunc cortex_a78c_reset_func
 
 	/* ----------------------------------------------------
@@ -77,6 +124,7 @@
 	 * Report all errata. The revision-variant information is passed to
 	 * checking functions of each errata.
 	 */
+	report_errata ERRATA_A78C_2132064, cortex_a78c, 2132064
 	report_errata WORKAROUND_CVE_2022_23960, cortex_a78c, cve_2022_23960
 
 	ldp	x8, x30, [sp], #16
diff --git a/lib/cpus/aarch64/neoverse_n2.S b/lib/cpus/aarch64/neoverse_n2.S
index 5b796dc..fae3be2 100644
--- a/lib/cpus/aarch64/neoverse_n2.S
+++ b/lib/cpus/aarch64/neoverse_n2.S
@@ -338,6 +338,36 @@
 	b	cpu_rev_var_ls
 endfunc check_errata_2280757
 
+/* --------------------------------------------------
+ * Errata Workaround for Neoverse N2 Erratum 2388450.
+ * This applies to revision r0p0 of Neoverse N2,
+ * fixed in r0p1.
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x1, x17
+ * --------------------------------------------------
+ */
+func errata_n2_2388450_wa
+	/* Check revision. */
+	mov	x17, x30
+	bl	check_errata_2388450
+	cbz	x0, 1f
+
+	/*Set bit 40 in ACTLR2_EL1 */
+	mrs	x1, NEOVERSE_N2_CPUACTLR2_EL1
+	orr	x1, x1, #NEOVERSE_N2_CPUACTLR2_EL1_BIT_40
+	msr	NEOVERSE_N2_CPUACTLR2_EL1, x1
+	isb
+1:
+	ret	x17
+endfunc errata_n2_2388450_wa
+
+func check_errata_2388450
+	/* Applies to r0p0, fixed in r0p1 */
+	mov	x1, #0x00
+	b	cpu_rev_var_ls
+endfunc check_errata_2388450
+
 func check_errata_cve_2022_23960
 #if WORKAROUND_CVE_2022_23960
 	mov	x0, #ERRATA_APPLIES
@@ -417,6 +447,11 @@
 	bl	errata_n2_2280757_wa
 #endif
 
+#if ERRATA_N2_2388450
+	mov	x0, x18
+	bl	errata_n2_2388450_wa
+#endif
+
 #if ENABLE_AMU
 	/* Make sure accesses from EL0/EL1 and EL2 are not trapped to EL3 */
 	mrs	x0, cptr_el3
@@ -496,6 +531,7 @@
 	report_errata ERRATA_N2_2138958, neoverse_n2, 2138958
 	report_errata ERRATA_N2_2242400, neoverse_n2, 2242400
 	report_errata ERRATA_N2_2280757, neoverse_n2, 2280757
+	report_errata ERRATA_N2_2388450, neoverse_n2, 2388450
 	report_errata WORKAROUND_CVE_2022_23960, neoverse_n2, cve_2022_23960
 	report_errata ERRATA_DSU_2313941, neoverse_n2, dsu_2313941
 
diff --git a/lib/cpus/cpu-ops.mk b/lib/cpus/cpu-ops.mk
index ec3f1e1..5be0a55 100644
--- a/lib/cpus/cpu-ops.mk
+++ b/lib/cpus/cpu-ops.mk
@@ -361,6 +361,10 @@
 # to revisions r0p0 and r0p1 of the A78 AE cpu. It is still open.
 ERRATA_A78_AE_2395408	?=0
 
+# Flag to apply erratum 2132064 workaround during reset. This erratum applies
+# to revisions r0p1 and r0p2 of the A78C cpu. It is still open.
+ERRATA_A78C_2132064	?=0
+
 # Flag to apply erratum 1821534 workaround during reset. This erratum applies
 # to revisions r0p0 - r1p0 of the X1 cpu and fixed in r1p1.
 ERRATA_X1_1821534	?=0
@@ -560,6 +564,10 @@
 # to revision r0p0 of the Neoverse N2 cpu and is still open.
 ERRATA_N2_2280757	?=0
 
+# Flag to apply erratum 2388450 workaround during reset. This erratum applies
+# to revision r0p0 of the Neoverse N2 cpu, it is fixed in r0p1.
+ERRATA_N2_2388450	?=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
@@ -915,6 +923,10 @@
 $(eval $(call assert_boolean,ERRATA_A78_AE_2395408))
 $(eval $(call add_define,ERRATA_A78_AE_2395408))
 
+# Process ERRATA_A78C_2132064 flag
+$(eval $(call assert_boolean,ERRATA_A78C_2132064))
+$(eval $(call add_define,ERRATA_A78C_2132064))
+
 # Process ERRATA_X1_1821534 flag
 $(eval $(call assert_boolean,ERRATA_X1_1821534))
 $(eval $(call add_define,ERRATA_X1_1821534))
@@ -1111,6 +1123,10 @@
 $(eval $(call assert_boolean,ERRATA_N2_2280757))
 $(eval $(call add_define,ERRATA_N2_2280757))
 
+# Process ERRATA_N2_2388450 flag
+$(eval $(call assert_boolean,ERRATA_N2_2388450))
+$(eval $(call add_define,ERRATA_N2_2388450))
+
 # Process ERRATA_X2_2002765 flag
 $(eval $(call assert_boolean,ERRATA_X2_2002765))
 $(eval $(call add_define,ERRATA_X2_2002765))
diff --git a/plat/arm/board/fvp/include/fvp_critical_data.h b/plat/arm/board/fvp/include/fvp_critical_data.h
index 3010d21..04bd5b2 100644
--- a/plat/arm/board/fvp/include/fvp_critical_data.h
+++ b/plat/arm/board/fvp/include/fvp_critical_data.h
@@ -1,8 +1,10 @@
 /*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
+#ifndef FVP_CRITICAL_DATA_H
+#define FVP_CRITICAL_DATA_H
 
 #include <common/nv_cntr_ids.h>
 #include <lib/utils_def.h>
@@ -17,3 +19,5 @@
 	/* platform NV counters */
 	unsigned int nv_ctr[MAX_NV_CTR_IDS];
 };
+
+#endif /* FVP_CRITICAL_DATA_H */
diff --git a/plat/arm/board/morello/morello_bl2_setup.c b/plat/arm/board/morello/morello_bl2_setup.c
index 0d4b6d0..da1f7ae 100644
--- a/plat/arm/board/morello/morello_bl2_setup.c
+++ b/plat/arm/board/morello/morello_bl2_setup.c
@@ -1,27 +1,226 @@
 /*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include <common/debug.h>
+#include <drivers/arm/css/sds.h>
+#include <lib/mmio.h>
 #include <lib/utils.h>
 #include <plat/arm/common/plat_arm.h>
 
-void bl2_platform_setup(void)
-{
+#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 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
+
+/* 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);
+
 #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.
-	 */
+/*
+ * 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)
+{
+	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 0x80000000 - 0xFFFFFFFF\n");
 	zero_normalmem((void *)ARM_DRAM1_BASE, ARM_DRAM1_SIZE);
 	flush_dcache_range(ARM_DRAM1_BASE, 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;
+	}
+
+	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);
+
+		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("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 bl2_platform_setup(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();
+	}
+
+#ifdef TARGET_PLATFORM_SOC
+	dmc_ecc_setup(&plat_info);
 #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 e418518..a044212 100644
--- a/plat/arm/board/morello/morello_bl31_setup.c
+++ b/plat/arm/board/morello/morello_bl31_setup.c
@@ -1,54 +1,16 @@
 /*
- * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2022, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#include <common/debug.h>
 #include <drivers/arm/css/css_mhu_doorbell.h>
 #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 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
-
-/* 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);
-
 static scmi_channel_plat_info_t morello_scmi_plat_info = {
 	.scmi_mbx_mem = MORELLO_SCMI_PAYLOAD_BASE,
 	.db_reg_addr = PLAT_CSS_MHU_BASE + CSS_SCMI_MHU_DB_REG_OFF,
@@ -67,177 +29,7 @@
 	return css_scmi_override_pm_ops(ops);
 }
 
-#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)
-{
-	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;
-	}
-
-	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);
-
-		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("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;
-
-	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();
-	}
-
 	arm_bl31_platform_setup();
-
-#ifdef TARGET_PLATFORM_SOC
-	dmc_ecc_setup(&plat_info);
-#endif
 }
diff --git a/plat/arm/board/morello/morello_plat.c b/plat/arm/board/morello/morello_plat.c
index 42e5171..1da0ff9 100644
--- a/plat/arm/board/morello/morello_plat.c
+++ b/plat/arm/board/morello/morello_plat.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2022, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -15,7 +15,7 @@
  * Table of regions to map using the MMU.
  * Replace or extend the below regions as required
  */
-#if IMAGE_BL1 || IMAGE_BL31
+#if IMAGE_BL1
 const mmap_region_t plat_arm_mmap[] = {
 	ARM_MAP_SHARED_RAM,
 	MORELLO_MAP_DEVICE,
@@ -25,12 +25,23 @@
 	{0}
 };
 #endif
+
+#if IMAGE_BL31
+const mmap_region_t plat_arm_mmap[] = {
+	ARM_MAP_SHARED_RAM,
+	MORELLO_MAP_DEVICE,
+	MORELLO_MAP_NS_SRAM,
+	{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,
+	ARM_MAP_DRAM2,
 #if TRUSTED_BOARD_BOOT && !BL2_AT_EL3
 	ARM_MAP_BL1_RW,
 #endif
diff --git a/plat/arm/board/morello/platform.mk b/plat/arm/board/morello/platform.mk
index 86047e3..156b7ea 100644
--- a/plat/arm/board/morello/platform.mk
+++ b/plat/arm/board/morello/platform.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2020-2021, Arm Limited. All rights reserved.
+# Copyright (c) 2020-2022, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -83,6 +83,8 @@
 
 override ARM_PLAT_MT			:=	1
 
+override ARM_BL31_IN_DRAM		:=	1
+
 # Errata workarounds:
 ERRATA_N1_1868343			:=	1
 
diff --git a/plat/arm/board/rde1edge/include/platform_def.h b/plat/arm/board/rde1edge/include/platform_def.h
index a9b30a4..69bfd7b 100644
--- a/plat/arm/board/rde1edge/include/platform_def.h
+++ b/plat/arm/board/rde1edge/include/platform_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2022, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -26,12 +26,15 @@
 
 #define CSS_SYSTEM_PWR_DMN_LVL		ARM_PWR_LVL3
 
+/* Maximum number of address bits used per chip */
+#define CSS_SGI_ADDR_BITS_PER_CHIP	U(36)
+
 /*
  * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes
  */
 #ifdef __aarch64__
-#define PLAT_PHY_ADDR_SPACE_SIZE	(1ULL << 36)
-#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 36)
+#define PLAT_PHY_ADDR_SPACE_SIZE	(1ULL << CSS_SGI_ADDR_BITS_PER_CHIP)
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << CSS_SGI_ADDR_BITS_PER_CHIP)
 #else
 #define PLAT_PHY_ADDR_SPACE_SIZE	(1ULL << 32)
 #define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 32)
diff --git a/plat/arm/board/rdn1edge/include/platform_def.h b/plat/arm/board/rdn1edge/include/platform_def.h
index a61b0d5..de01902 100644
--- a/plat/arm/board/rdn1edge/include/platform_def.h
+++ b/plat/arm/board/rdn1edge/include/platform_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -30,12 +30,17 @@
 /* Virtual address used by dynamic mem_protect for chunk_base */
 #define PLAT_ARM_MEM_PROTEC_VA_FRAME	UL(0xc0000000)
 
+/* Maximum number of address bits used per chip */
+#define CSS_SGI_ADDR_BITS_PER_CHIP	U(42)
+
 /*
  * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes
  */
 #ifdef __aarch64__
-#define PLAT_PHY_ADDR_SPACE_SIZE	(1ULL << 43)
-#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 43)
+#define PLAT_PHY_ADDR_SPACE_SIZE	CSS_SGI_REMOTE_CHIP_MEM_OFFSET( \
+						CSS_SGI_CHIP_COUNT)
+#define PLAT_VIRT_ADDR_SPACE_SIZE	CSS_SGI_REMOTE_CHIP_MEM_OFFSET( \
+						CSS_SGI_CHIP_COUNT)
 #else
 #define PLAT_PHY_ADDR_SPACE_SIZE	(1ULL << 32)
 #define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 32)
diff --git a/plat/arm/board/rdn2/include/platform_def.h b/plat/arm/board/rdn2/include/platform_def.h
index e4015f7..464a157 100644
--- a/plat/arm/board/rdn2/include/platform_def.h
+++ b/plat/arm/board/rdn2/include/platform_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -69,15 +69,16 @@
  */
 #ifdef __aarch64__
 #if (CSS_SGI_PLATFORM_VARIANT == 2)
+#define CSS_SGI_ADDR_BITS_PER_CHIP	U(46)	/* 64TB */
+#else
+#define CSS_SGI_ADDR_BITS_PER_CHIP	U(42)	/* 4TB */
+#endif
+
 #define PLAT_PHY_ADDR_SPACE_SIZE	CSS_SGI_REMOTE_CHIP_MEM_OFFSET( \
 						CSS_SGI_CHIP_COUNT)
 #define PLAT_VIRT_ADDR_SPACE_SIZE	CSS_SGI_REMOTE_CHIP_MEM_OFFSET( \
 						CSS_SGI_CHIP_COUNT)
 #else
-#define PLAT_PHY_ADDR_SPACE_SIZE	(1ULL << 42)
-#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 42)
-#endif
-#else
 #define PLAT_PHY_ADDR_SPACE_SIZE	(1ULL << 32)
 #define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 32)
 #endif
diff --git a/plat/arm/board/rdv1/include/platform_def.h b/plat/arm/board/rdv1/include/platform_def.h
index 5b98b4e..620fa3e 100644
--- a/plat/arm/board/rdv1/include/platform_def.h
+++ b/plat/arm/board/rdv1/include/platform_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -46,12 +46,15 @@
 		(TZC_REGION_ACCESS_RDWR(TZC_NSAID_CLCD))   | \
 		(TZC_REGION_ACCESS_RDWR(TZC_NSAID_VIRTIO))
 
+/* Maximum number of address bits used per chip */
+#define CSS_SGI_ADDR_BITS_PER_CHIP	U(42)
+
 /*
  * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes
  */
 #ifdef __aarch64__
-#define PLAT_PHY_ADDR_SPACE_SIZE	(1ULL << 42)
-#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 42)
+#define PLAT_PHY_ADDR_SPACE_SIZE	(1ULL << CSS_SGI_ADDR_BITS_PER_CHIP)
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << CSS_SGI_ADDR_BITS_PER_CHIP)
 #else
 #define PLAT_PHY_ADDR_SPACE_SIZE	(1ULL << 32)
 #define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 32)
diff --git a/plat/arm/board/rdv1mc/include/platform_def.h b/plat/arm/board/rdv1mc/include/platform_def.h
index 12ce806..3670904 100644
--- a/plat/arm/board/rdv1mc/include/platform_def.h
+++ b/plat/arm/board/rdv1mc/include/platform_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -46,6 +46,9 @@
 /* Virtual address used by dynamic mem_protect for chunk_base */
 #define PLAT_ARM_MEM_PROTEC_VA_FRAME	UL(0xC0000000)
 
+/* Remote chip address offset (4TB per chip) */
+#define CSS_SGI_ADDR_BITS_PER_CHIP	U(42)
+
 /* Physical and virtual address space limits for MMU in AARCH64 mode */
 #define PLAT_PHY_ADDR_SPACE_SIZE	CSS_SGI_REMOTE_CHIP_MEM_OFFSET( \
 						CSS_SGI_CHIP_COUNT)
diff --git a/plat/arm/board/sgi575/include/platform_def.h b/plat/arm/board/sgi575/include/platform_def.h
index 72d5f7c..82a38c5 100644
--- a/plat/arm/board/sgi575/include/platform_def.h
+++ b/plat/arm/board/sgi575/include/platform_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -27,12 +27,15 @@
 
 #define PLAT_MAX_PWR_LVL		ARM_PWR_LVL1
 
+/* Maximum number of address bits used per chip */
+#define CSS_SGI_ADDR_BITS_PER_CHIP	U(36)
+
 /*
  * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes
  */
 #ifdef __aarch64__
-#define PLAT_PHY_ADDR_SPACE_SIZE	(1ULL << 36)
-#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 36)
+#define PLAT_PHY_ADDR_SPACE_SIZE	(1ULL << CSS_SGI_ADDR_BITS_PER_CHIP)
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << CSS_SGI_ADDR_BITS_PER_CHIP)
 #else
 #define PLAT_PHY_ADDR_SPACE_SIZE	(1ULL << 32)
 #define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 32)
diff --git a/plat/arm/board/tc/include/platform_def.h b/plat/arm/board/tc/include/platform_def.h
index 745d91c..6ca3261 100644
--- a/plat/arm/board/tc/include/platform_def.h
+++ b/plat/arm/board/tc/include/platform_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2022, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -177,7 +177,7 @@
 
 #define PLAT_ARM_NSTIMER_FRAME_ID	0
 
-#define PLAT_ARM_TRUSTED_ROM_BASE	0x0
+#define PLAT_ARM_TRUSTED_ROM_BASE	0x1000
 #define PLAT_ARM_TRUSTED_ROM_SIZE	0x00080000	/* 512KB */
 
 #define PLAT_ARM_NSRAM_BASE		0x06000000
diff --git a/plat/arm/common/arm_dyn_cfg.c b/plat/arm/common/arm_dyn_cfg.c
index 83e3f9a..a62693c 100644
--- a/plat/arm/common/arm_dyn_cfg.c
+++ b/plat/arm/common/arm_dyn_cfg.c
@@ -131,6 +131,7 @@
 	bl_mem_params_node_t *cfg_mem_params = NULL;
 	uintptr_t image_base;
 	uint32_t image_size;
+	unsigned int error_config_id = MAX_IMAGE_IDS;
 	const unsigned int config_ids[] = {
 			HW_CONFIG_ID,
 			SOC_FW_CONFIG_ID,
@@ -142,17 +143,17 @@
 
 	/* Iterate through all the fw config IDs */
 	for (i = 0; i < ARRAY_SIZE(config_ids); i++) {
-		/* Get the config load address and size from TB_FW_CONFIG */
+		/* Get the config load address and size */
 		cfg_mem_params = get_bl_mem_params_node(config_ids[i]);
 		if (cfg_mem_params == NULL) {
-			VERBOSE("%sHW_CONFIG in bl_mem_params_node\n",
-				"Couldn't find ");
+			VERBOSE("%sconfig_id = %d in bl_mem_params_node\n",
+				"Couldn't find ", config_ids[i]);
 			continue;
 		}
 
 		dtb_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, config_ids[i]);
 		if (dtb_info == NULL) {
-			VERBOSE("%sconfig_id %d load info in TB_FW_CONFIG\n",
+			VERBOSE("%sconfig_id %d load info in FW_CONFIG\n",
 				"Couldn't find ", config_ids[i]);
 			continue;
 		}
@@ -168,17 +169,32 @@
 		if (config_ids[i] != HW_CONFIG_ID) {
 
 			if (check_uptr_overflow(image_base, image_size)) {
+				VERBOSE("%s=%d as its %s is overflowing uptr\n",
+					"skip loading of firmware config",
+					config_ids[i],
+					"load-address");
+				error_config_id = config_ids[i];
 				continue;
 			}
 #ifdef	BL31_BASE
 			/* Ensure the configs don't overlap with BL31 */
 			if ((image_base >= BL31_BASE) &&
 			    (image_base <= BL31_LIMIT)) {
+				VERBOSE("%s=%d as its %s is overlapping BL31\n",
+					"skip loading of firmware config",
+					config_ids[i],
+					"load-address");
+				error_config_id = config_ids[i];
 				continue;
 			}
 #endif
 			/* Ensure the configs are loaded in a valid address */
 			if (image_base < ARM_BL_RAM_BASE) {
+				VERBOSE("%s=%d as its %s is invalid\n",
+					"skip loading of firmware config",
+					config_ids[i],
+					"load-address");
+				error_config_id = config_ids[i];
 				continue;
 			}
 #ifdef BL32_BASE
@@ -188,6 +204,11 @@
 			 */
 			if ((image_base >= BL32_BASE) &&
 			    (image_base <= BL32_LIMIT)) {
+				VERBOSE("%s=%d as its %s is overlapping BL32\n",
+					"skip loading of firmware config",
+					config_ids[i],
+					"load-address");
+				error_config_id = config_ids[i];
 				continue;
 			}
 #endif
@@ -202,4 +223,9 @@
 		 */
 		cfg_mem_params->image_info.h.attr &= ~IMAGE_ATTRIB_SKIP_LOADING;
 	}
+
+	if (error_config_id != MAX_IMAGE_IDS) {
+		ERROR("Invalid config file %u\n", error_config_id);
+		panic();
+	}
 }
diff --git a/plat/arm/css/sgi/include/sgi_base_platform_def.h b/plat/arm/css/sgi/include/sgi_base_platform_def.h
index 58a153a..22870c4 100644
--- a/plat/arm/css/sgi/include/sgi_base_platform_def.h
+++ b/plat/arm/css/sgi/include/sgi_base_platform_def.h
@@ -21,8 +21,9 @@
 
 #define PLAT_ARM_TRUSTED_SRAM_SIZE	0x00040000	/* 256 KB */
 
-/* Remote chip address offset (4TB per chip) */
-#define CSS_SGI_REMOTE_CHIP_MEM_OFFSET(n)	((ULL(1) << 42) * (n))
+/* Remote chip address offset */
+#define CSS_SGI_REMOTE_CHIP_MEM_OFFSET(n)	\
+		((ULL(1) << CSS_SGI_ADDR_BITS_PER_CHIP) * (n))
 
 /*
  * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the
@@ -67,7 +68,7 @@
  * 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	0xC000
+#define PLAT_ARM_MAX_BL1_RW_SIZE	(64 * 1024)	/* 64 KB */
 
 /*
  * PLAT_ARM_MAX_ROMLIB_RW_SIZE is define to use a full page
diff --git a/plat/imx/common/imx_sip_svc.c b/plat/imx/common/imx_sip_svc.c
index fd54820..fae9750 100644
--- a/plat/imx/common/imx_sip_svc.c
+++ b/plat/imx/common/imx_sip_svc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -34,6 +34,13 @@
 		SMC_RET1(handle, imx_soc_info_handler(smc_fid, x1, x2, x3));
 		break;
 #endif
+#if defined(PLAT_imx8mm) || defined(PLAT_imx8mn) || defined(PLAT_imx8mp)
+	case IMX_SIP_DDR_DVFS:
+		return dram_dvfs_handler(smc_fid, handle, x1, x2, x3);
+	case IMX_SIP_GPC:
+		SMC_RET1(handle, imx_gpc_handler(smc_fid, x1, x2, x3));
+		break;
+#endif
 #if (defined(PLAT_imx8qm) || defined(PLAT_imx8qx))
 	case  IMX_SIP_SRTC:
 		return imx_srtc_handler(smc_fid, handle, x1, x2, x3, x4);
diff --git a/plat/imx/common/include/imx_sip_svc.h b/plat/imx/common/include/imx_sip_svc.h
index 6c7a760..c6e9879 100644
--- a/plat/imx/common/include/imx_sip_svc.h
+++ b/plat/imx/common/include/imx_sip_svc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -8,6 +8,8 @@
 #define __IMX_SIP_SVC_H__
 
 /* SMC function IDs for SiP Service queries */
+#define IMX_SIP_GPC			0xC2000000
+
 #define IMX_SIP_CPUFREQ			0xC2000001
 #define IMX_SIP_SET_CPUFREQ		0x00
 
@@ -17,6 +19,8 @@
 #define IMX_SIP_BUILDINFO			0xC2000003
 #define IMX_SIP_BUILDINFO_GET_COMMITHASH	0x00
 
+#define IMX_SIP_DDR_DVFS		0xc2000004
+
 #define IMX_SIP_SRC			0xC2000005
 #define IMX_SIP_SRC_SET_SECONDARY_BOOT	0x10
 #define IMX_SIP_SRC_IS_SECONDARY_BOOT	0x11
@@ -41,6 +45,13 @@
 int imx_soc_info_handler(uint32_t smc_fid, u_register_t x1,
 			 u_register_t x2, u_register_t x3);
 #endif
+#if defined(PLAT_imx8mm) || defined(PLAT_imx8mn) || defined(PLAT_imx8mp)
+int dram_dvfs_handler(uint32_t smc_fid, void *handle,
+	u_register_t x1, u_register_t x2, u_register_t x3);
+
+int imx_gpc_handler(uint32_t smc_fid, u_register_t x1,
+		    u_register_t x2, u_register_t x3);
+#endif
 
 #if defined(PLAT_imx8mm) || defined(PLAT_imx8mq)
 int imx_src_handler(uint32_t smc_fid, u_register_t x1,
diff --git a/plat/imx/imx8m/ddr/clock.c b/plat/imx/imx8m/ddr/clock.c
new file mode 100644
index 0000000..7fb5730
--- /dev/null
+++ b/plat/imx/imx8m/ddr/clock.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2018-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+
+#include <lib/mmio.h>
+#include <platform_def.h>
+
+#define IMX_CCM_IP_BASE				(IMX_CCM_BASE + 0xa000)
+#define DRAM_SEL_CFG				(IMX_CCM_BASE + 0x9800)
+#define CCM_IP_CLK_ROOT_GEN_TAGET(i)		(IMX_CCM_IP_BASE + 0x80 * (i) + 0x00)
+#define CCM_IP_CLK_ROOT_GEN_TAGET_SET(i)	(IMX_CCM_IP_BASE + 0x80 * (i) + 0x04)
+#define CCM_IP_CLK_ROOT_GEN_TAGET_CLR(i)	(IMX_CCM_IP_BASE + 0x80 * (i) + 0x08)
+#define PLL_FREQ_800M	U(0x00ece580)
+#define PLL_FREQ_400M	U(0x00ec6984)
+#define PLL_FREQ_167M	U(0x00f5a406)
+
+void ddr_pll_bypass_100mts(void)
+{
+	/* change the clock source of dram_alt_clk_root to source 2 --100MHz */
+	mmio_write_32(CCM_IP_CLK_ROOT_GEN_TAGET_CLR(0), (0x7 << 24) | (0x7 << 16));
+	mmio_write_32(CCM_IP_CLK_ROOT_GEN_TAGET_SET(0), (0x2 << 24));
+
+	/* change the clock source of dram_apb_clk_root to source 2 --40MHz/2 */
+	mmio_write_32(CCM_IP_CLK_ROOT_GEN_TAGET_CLR(1), (0x7 << 24) | (0x7 << 16));
+	mmio_write_32(CCM_IP_CLK_ROOT_GEN_TAGET_SET(1), (0x2 << 24) | (0x1 << 16));
+
+	/* configure pll bypass mode */
+	mmio_write_32(DRAM_SEL_CFG + 0x4, BIT(24));
+}
+
+void ddr_pll_bypass_400mts(void)
+{
+	/* change the clock source of dram_alt_clk_root to source 1 --400MHz */
+	mmio_write_32(CCM_IP_CLK_ROOT_GEN_TAGET_CLR(0), (0x7 << 24) | (0x7 << 16));
+	mmio_write_32(CCM_IP_CLK_ROOT_GEN_TAGET_SET(0), (0x1 << 24) | (0x1 << 16));
+
+	/* change the clock source of dram_apb_clk_root to source 3 --160MHz/2 */
+	mmio_write_32(CCM_IP_CLK_ROOT_GEN_TAGET_CLR(1), (0x7 << 24) | (0x7 << 16));
+	mmio_write_32(CCM_IP_CLK_ROOT_GEN_TAGET_SET(1), (0x3 << 24) | (0x1 << 16));
+
+	/* configure pll bypass mode */
+	mmio_write_32(DRAM_SEL_CFG + 0x4, BIT(24));
+}
+
+void ddr_pll_unbypass(void)
+{
+	mmio_write_32(DRAM_SEL_CFG + 0x8, BIT(24));
+	mmio_write_32(CCM_IP_CLK_ROOT_GEN_TAGET_CLR(1), (0x7 << 24) | (0x7 << 16));
+	/* to source 4 --800MHz/5 */
+	mmio_write_32(CCM_IP_CLK_ROOT_GEN_TAGET_SET(1), (0x4 << 24) | (0x4 << 16));
+}
+
+#if defined(PLAT_imx8mq)
+void dram_pll_init(unsigned int drate)
+{
+	/* bypass the PLL */
+	mmio_setbits_32(HW_DRAM_PLL_CFG0, 0x30);
+
+	switch (drate) {
+	case 3200:
+		mmio_write_32(HW_DRAM_PLL_CFG2, PLL_FREQ_800M);
+		break;
+	case 1600:
+		mmio_write_32(HW_DRAM_PLL_CFG2, PLL_FREQ_400M);
+		break;
+	case 667:
+		mmio_write_32(HW_DRAM_PLL_CFG2, PLL_FREQ_167M);
+		break;
+	default:
+		break;
+	}
+
+	/* unbypass the PLL */
+	mmio_clrbits_32(HW_DRAM_PLL_CFG0, 0x30);
+	while (!(mmio_read_32(HW_DRAM_PLL_CFG0) & (1 << 31))) {
+		;
+	}
+}
+#else
+void dram_pll_init(unsigned int drate)
+{
+	/* bypass the PLL */
+	mmio_setbits_32(DRAM_PLL_CTRL, (1 << 16));
+	mmio_clrbits_32(DRAM_PLL_CTRL, (1 << 9));
+
+	switch (drate) {
+	case 2400:
+		mmio_write_32(DRAM_PLL_CTRL + 0x4, (300 << 12) | (3 << 4) | 2);
+		break;
+	case 1600:
+		mmio_write_32(DRAM_PLL_CTRL + 0x4, (400 << 12) | (3 << 4) | 3);
+		break;
+	case 1066:
+		mmio_write_32(DRAM_PLL_CTRL + 0x4, (266 << 12) | (3 << 4) | 3);
+		break;
+	case 667:
+		mmio_write_32(DRAM_PLL_CTRL + 0x4, (334 << 12) | (3 << 4) | 4);
+		break;
+	default:
+		break;
+	}
+
+	mmio_setbits_32(DRAM_PLL_CTRL, BIT(9));
+	/* wait for PLL locked */
+	while (!(mmio_read_32(DRAM_PLL_CTRL) & BIT(31))) {
+		;
+	}
+
+	/* unbypass the PLL */
+	mmio_clrbits_32(DRAM_PLL_CTRL, BIT(16));
+}
+#endif
+
+/* change the dram clock frequency */
+void dram_clock_switch(unsigned int target_drate, bool bypass_mode)
+{
+	if (bypass_mode) {
+		switch (target_drate) {
+		case 400:
+			ddr_pll_bypass_400mts();
+			break;
+		case 100:
+			ddr_pll_bypass_100mts();
+			break;
+		default:
+			ddr_pll_unbypass();
+			break;
+		}
+	} else {
+		dram_pll_init(target_drate);
+	}
+}
diff --git a/plat/imx/imx8m/ddr/ddr4_dvfs.c b/plat/imx/imx8m/ddr/ddr4_dvfs.c
new file mode 100644
index 0000000..cdc7dc2
--- /dev/null
+++ b/plat/imx/imx8m/ddr/ddr4_dvfs.c
@@ -0,0 +1,241 @@
+/*
+ * Copyright 2018-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <dram.h>
+
+void ddr4_mr_write(uint32_t mr, uint32_t data, uint32_t mr_type, uint32_t rank)
+{
+	uint32_t val, mr_mirror, data_mirror;
+
+	/*
+	 * 1. Poll MRSTAT.mr_wr_busy until it is 0 to make sure
+	 * that there is no outstanding MR transAction.
+	 */
+	while (mmio_read_32(DDRC_MRSTAT(0)) & 0x1) {
+		;
+	}
+
+	/*
+	 * 2. Write the MRCTRL0.mr_type, MRCTRL0.mr_addr, MRCTRL0.mr_rank
+	 * and (for MRWs) MRCTRL1.mr_data to define the MR transaction.
+	 */
+	val = mmio_read_32(DDRC_DIMMCTL(0));
+	if ((val & 0x2) && (rank == 0x2)) {
+		mr_mirror = (mr & 0x4) | ((mr & 0x1) << 1) | ((mr & 0x2) >> 1); /* BA0, BA1 swap */
+		data_mirror = (data & 0x1607) | ((data & 0x8) << 1) | ((data & 0x10) >> 1) |
+				((data & 0x20) << 1) | ((data & 0x40) >> 1) | ((data & 0x80) << 1) |
+				 ((data & 0x100) >> 1) | ((data & 0x800) << 2) | ((data & 0x2000) >> 2) ;
+	} else {
+		mr_mirror = mr;
+		data_mirror = data;
+	}
+
+	mmio_write_32(DDRC_MRCTRL0(0), mr_type | (mr_mirror << 12) | (rank << 4));
+	mmio_write_32(DDRC_MRCTRL1(0), data_mirror);
+
+	/*
+	 * 3. In a separate APB transaction, write the MRCTRL0.mr_wr to 1.
+	 * This bit is self-clearing, and triggers the MR transaction.
+	 * The uMCTL2 then asserts the MRSTAT.mr_wr_busy while it performs
+	 * the MR transaction to SDRAM, and no further accesses can be
+	 * initiated until it is deasserted.
+	 */
+	mmio_setbits_32(DDRC_MRCTRL0(0), BIT(31));
+
+	while (mmio_read_32(DDRC_MRSTAT(0))) {
+		;
+	}
+}
+
+void dram_cfg_all_mr(struct dram_info *info, uint32_t pstate)
+{
+	uint32_t num_rank = info->num_rank;
+	/*
+	 * 15. Perform MRS commands as required to re-program
+	 * timing registers in the SDRAM for the new frequency
+	 * (in particular, CL, CWL and WR may need to be changed).
+	 */
+
+	for (int i = 1; i <= num_rank; i++) {
+		for (int j = 0; j < 6; j++) {
+			ddr4_mr_write(j, info->mr_table[pstate][j], 0, i);
+		}
+		ddr4_mr_write(6, info->mr_table[pstate][7], 0, i);
+	}
+}
+
+void sw_pstate(uint32_t pstate, uint32_t drate)
+{
+	uint32_t val;
+
+	mmio_write_32(DDRC_SWCTL(0), 0x0);
+
+	/*
+	 * Update any registers which may be required to
+	 * change for the new frequency.
+	 */
+	mmio_write_32(DDRC_MSTR2(0), pstate);
+	mmio_setbits_32(DDRC_MSTR(0), (0x1 << 29));
+
+	/*
+	 * Toggle RFSHCTL3.refresh_update_level to allow the
+	 * new refresh-related register values to propagate
+	 * to the refresh logic.
+	 */
+	val = mmio_read_32(DDRC_RFSHCTL3(0));
+	if (val & 0x2) {
+		mmio_write_32(DDRC_RFSHCTL3(0), val & 0xFFFFFFFD);
+	} else {
+		mmio_write_32(DDRC_RFSHCTL3(0), val | 0x2);
+	}
+
+	/*
+	 * 19. If required, trigger the initialization in the PHY.
+	 * If using the gen2 multiPHY, PLL initialization should
+	 * be triggered at this point. See the PHY databook for
+	 * details about the frequency change procedure.
+	 */
+	mmio_write_32(DDRC_DFIMISC(0), 0x00000000 | (pstate << 8));
+	mmio_write_32(DDRC_DFIMISC(0), 0x00000020 | (pstate << 8));
+
+	/* wait DFISTAT.dfi_init_complete to 0 */
+	while (mmio_read_32(DDRC_DFISTAT(0)) & 0x1) {
+		;
+	}
+
+	/* change the clock to the target frequency */
+	dram_clock_switch(drate, false);
+
+	mmio_write_32(DDRC_DFIMISC(0), 0x00000000 | (pstate << 8));
+
+	/* wait DFISTAT.dfi_init_complete to 1 */
+	while (!(mmio_read_32(DDRC_DFISTAT(0)) & 0x1)) {
+		;
+	}
+
+	/*
+	 * When changing frequencies the controller may violate the JEDEC
+	 * requirement that no more than 16 refreshes should be issued within
+	 * 2*tREFI. These extra refreshes are not expected to cause a problem
+	 * in the SDRAM. This issue can be avoided by waiting for at least 2*tREFI
+	 * before exiting self-refresh in step 19.
+	 */
+	udelay(14);
+
+	/* 14. Exit the self-refresh state by setting PWRCTL.selfref_sw = 0. */
+	mmio_clrbits_32(DDRC_PWRCTL(0), (1 << 5));
+
+	while ((mmio_read_32(DDRC_STAT(0)) & 0x3f) == 0x23) {
+		;
+	}
+}
+
+void ddr4_swffc(struct dram_info *info, unsigned int pstate)
+{
+	uint32_t drate = info->timing_info->fsp_table[pstate];
+
+	/*
+	 * 1. set SWCTL.sw_done to disable quasi-dynamic register
+	 * programming outside reset.
+	 */
+	mmio_write_32(DDRC_SWCTL(0), 0x0);
+
+	/*
+	 * 2. Write 0 to PCTRL_n.port_en. This blocks AXI port(s)
+	 * from taking any transaction (blocks traffic on AXI ports).
+	 */
+	mmio_write_32(DDRC_PCTRL_0(0), 0x0);
+
+	/*
+	 * 3. Poll PSTAT.rd_port_busy_n=0 and PSTAT.wr_port_busy_n=0.
+	 * Wait until all AXI ports are idle (the uMCTL2 core has to
+	 * be idle).
+	 */
+	while (mmio_read_32(DDRC_PSTAT(0)) & 0x10001) {
+		;
+	}
+
+	/*
+	 * 4. Write 0 to SBRCTL.scrub_en. Disable SBR, required only if
+	 * SBR instantiated.
+	 * 5. Poll SBRSTAT.scrub_busy=0.
+	 * 6. Set DERATEEN.derate_enable = 0, if DERATEEN.derate_eanble = 1
+	 * and the read latency (RL) value needs to change after the frequency
+	 * change (LPDDR2/3/4 only).
+	 * 7. Set DBG1.dis_hif=1 so that no new commands will be accepted by the uMCTL2.
+	 */
+	mmio_setbits_32(DDRC_DBG1(0), (0x1 << 1));
+
+	/*
+	 * 8. Poll DBGCAM.dbg_wr_q_empty and DBGCAM.dbg_rd_q_empty to ensure
+	 * that write and read data buffers are empty.
+	 */
+	while ((mmio_read_32(DDRC_DBGCAM(0)) & 0x06000000) != 0x06000000) {
+		;
+	}
+
+	/*
+	 * 9. For DDR4, update MR6 with the new tDLLK value via the Mode
+	 * Register Write signals
+	 * 10. Set DFILPCFG0.dfi_lp_en_sr = 0, if DFILPCFG0.dfi_lp_en_sr = 1,
+	 * and wait until DFISTAT.dfi_lp_ack
+	 * 11. If DFI PHY Master interface is active in uMCTL2, then disable it
+	 * 12. Wait until STAT.operating_mode[1:0]!=11 indicating that the
+	 * controller is not in self-refresh mode.
+	 */
+	while ((mmio_read_32(DDRC_STAT(0)) & 0x3) == 0x3) {
+		;
+	}
+
+	/*
+	 * 13. Assert PWRCTL.selfref_sw for the DWC_ddr_umctl2 core to enter
+	 * the self-refresh mode.
+	 */
+	mmio_setbits_32(DDRC_PWRCTL(0), (1 << 5));
+
+	/*
+	 * 14. Wait until STAT.operating_mode[1:0]==11 indicating that the
+	 * controller core is in self-refresh mode.
+	 */
+	while ((mmio_read_32(DDRC_STAT(0)) & 0x3f) != 0x23) {
+		;
+	}
+
+	sw_pstate(pstate, drate);
+	dram_cfg_all_mr(info, pstate);
+
+	/* 23. Enable HIF commands by setting DBG1.dis_hif=0. */
+	mmio_clrbits_32(DDRC_DBG1(0), (0x1 << 1));
+
+	/*
+	 * 24. Reset DERATEEN.derate_enable = 1 if DERATEEN.derate_enable
+	 * has been set to 0 in step 6.
+	 * 25. If DFI PHY Master interface was active before step 11 then
+	 * enable it back by programming DFIPHYMSTR.phymstr_en = 1'b1.
+	 * 26. Write 1 to PCTRL_n.port_en. AXI port(s) are no longer blocked
+	 * from taking transactions (Re-enable traffic on AXI ports)
+	 */
+	mmio_write_32(DDRC_PCTRL_0(0), 0x1);
+
+	/*
+	 * 27. Write 1 to SBRCTL.scrub_en. Enable SBR if desired, only
+	 * required if SBR instantiated.
+	 */
+
+	/*
+	 * set SWCTL.sw_done to enable quasi-dynamic register programming
+	 * outside reset.
+	 */
+	mmio_write_32(DDRC_SWCTL(0), 0x1);
+
+	/* wait SWSTAT.sw_done_ack to 1 */
+	while (!(mmio_read_32(DDRC_SWSTAT(0)) & 0x1)) {
+		;
+	}
+}
diff --git a/plat/imx/imx8m/ddr/dram.c b/plat/imx/imx8m/ddr/dram.c
new file mode 100644
index 0000000..6ccd6fd
--- /dev/null
+++ b/plat/imx/imx8m/ddr/dram.c
@@ -0,0 +1,261 @@
+/*
+ * Copyright 2019-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <bl31/interrupt_mgmt.h>
+#include <common/runtime_svc.h>
+#include <lib/mmio.h>
+#include <lib/spinlock.h>
+#include <plat/common/platform.h>
+
+#include <dram.h>
+
+#define IMX_SIP_DDR_DVFS_GET_FREQ_COUNT		0x10
+#define IMX_SIP_DDR_DVFS_GET_FREQ_INFO		0x11
+
+struct dram_info dram_info;
+
+/* lock used for DDR DVFS */
+spinlock_t dfs_lock;
+
+static volatile uint32_t wfe_done;
+static volatile bool wait_ddrc_hwffc_done = true;
+static unsigned int dev_fsp = 0x1;
+
+static uint32_t fsp_init_reg[3][4] = {
+	{ DDRC_INIT3(0), DDRC_INIT4(0), DDRC_INIT6(0), DDRC_INIT7(0) },
+	{ DDRC_FREQ1_INIT3(0), DDRC_FREQ1_INIT4(0), DDRC_FREQ1_INIT6(0), DDRC_FREQ1_INIT7(0) },
+	{ DDRC_FREQ2_INIT3(0), DDRC_FREQ2_INIT4(0), DDRC_FREQ2_INIT6(0), DDRC_FREQ2_INIT7(0) },
+};
+
+static void get_mr_values(uint32_t (*mr_value)[8])
+{
+	uint32_t init_val;
+	unsigned int i, fsp_index;
+
+	for (fsp_index = 0U; fsp_index < 3U; fsp_index++) {
+		for (i = 0U; i < 4U; i++) {
+			init_val = mmio_read_32(fsp_init_reg[fsp_index][i]);
+			mr_value[fsp_index][2*i] = init_val >> 16;
+			mr_value[fsp_index][2*i + 1] = init_val & 0xFFFF;
+		}
+	}
+}
+
+/* Restore the ddrc configs */
+void dram_umctl2_init(struct dram_timing_info *timing)
+{
+	struct dram_cfg_param *ddrc_cfg = timing->ddrc_cfg;
+	unsigned int i;
+
+	for (i = 0U; i < timing->ddrc_cfg_num; i++) {
+		mmio_write_32(ddrc_cfg->reg, ddrc_cfg->val);
+		ddrc_cfg++;
+	}
+
+	/* set the default fsp to P0 */
+	mmio_write_32(DDRC_MSTR2(0), 0x0);
+}
+
+/* Restore the dram PHY config */
+void dram_phy_init(struct dram_timing_info *timing)
+{
+	struct dram_cfg_param *cfg = timing->ddrphy_cfg;
+	unsigned int i;
+
+	/* Restore the PHY init config */
+	cfg = timing->ddrphy_cfg;
+	for (i = 0U; i < timing->ddrphy_cfg_num; i++) {
+		dwc_ddrphy_apb_wr(cfg->reg, cfg->val);
+		cfg++;
+	}
+
+	/* Restore the DDR PHY CSRs */
+	cfg = timing->ddrphy_trained_csr;
+	for (i = 0U; i < timing->ddrphy_trained_csr_num; i++) {
+		dwc_ddrphy_apb_wr(cfg->reg, cfg->val);
+		cfg++;
+	}
+
+	/* Load the PIE image */
+	cfg = timing->ddrphy_pie;
+	for (i = 0U; i < timing->ddrphy_pie_num; i++) {
+		dwc_ddrphy_apb_wr(cfg->reg, cfg->val);
+		cfg++;
+	}
+}
+
+/* EL3 SGI-8 IPI handler for DDR Dynamic frequency scaling */
+static uint64_t waiting_dvfs(uint32_t id, uint32_t flags,
+				void *handle, void *cookie)
+{
+	uint64_t mpidr = read_mpidr_el1();
+	unsigned int cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
+	uint32_t irq;
+
+	irq = plat_ic_acknowledge_interrupt();
+	if (irq < 1022U) {
+		plat_ic_end_of_interrupt(irq);
+	}
+
+	/* set the WFE done status */
+	spin_lock(&dfs_lock);
+	wfe_done |= (1 << cpu_id * 8);
+	dsb();
+	spin_unlock(&dfs_lock);
+
+	while (1) {
+		/* ddr frequency change done */
+		if (!wait_ddrc_hwffc_done)
+			break;
+
+		wfe();
+	}
+
+	return 0;
+}
+
+void dram_info_init(unsigned long dram_timing_base)
+{
+	uint32_t ddrc_mstr, current_fsp;
+	uint32_t flags = 0;
+	uint32_t rc;
+	unsigned int i;
+
+	/* Get the dram type & rank */
+	ddrc_mstr = mmio_read_32(DDRC_MSTR(0));
+
+	dram_info.dram_type = ddrc_mstr & DDR_TYPE_MASK;
+	dram_info.num_rank = (ddrc_mstr >> 24) & ACTIVE_RANK_MASK;
+
+	/* Get current fsp info */
+	current_fsp = mmio_read_32(DDRC_DFIMISC(0)) & 0xf;
+	dram_info.boot_fsp = current_fsp;
+	dram_info.current_fsp = current_fsp;
+
+	get_mr_values(dram_info.mr_table);
+
+	dram_info.timing_info = (struct dram_timing_info *)dram_timing_base;
+
+	/* get the num of supported fsp */
+	for (i = 0U; i < 4U; ++i) {
+		if (!dram_info.timing_info->fsp_table[i]) {
+			break;
+		}
+	}
+	dram_info.num_fsp = i;
+
+	/* check if has bypass mode support */
+	if (dram_info.timing_info->fsp_table[i-1] < 666) {
+		dram_info.bypass_mode = true;
+	} else {
+		dram_info.bypass_mode = false;
+	}
+
+	/* Register the EL3 handler for DDR DVFS */
+	set_interrupt_rm_flag(flags, NON_SECURE);
+	rc = register_interrupt_type_handler(INTR_TYPE_EL3, waiting_dvfs, flags);
+	if (rc != 0) {
+		panic();
+	}
+}
+
+
+/*
+ * For each freq return the following info:
+ *
+ * r1: data rate
+ * r2: 1 + dram_core parent
+ * r3: 1 + dram_alt parent index
+ * r4: 1 + dram_apb parent index
+ *
+ * The parent indices can be used by an OS who manages source clocks to enabled
+ * them ahead of the switch.
+ *
+ * A parent value of "0" means "don't care".
+ *
+ * Current implementation of freq switch is hardcoded in
+ * plat/imx/common/imx8m/clock.c but in theory this can be enhanced to support
+ * a wide variety of rates.
+ */
+int dram_dvfs_get_freq_info(void *handle, u_register_t index)
+{
+	switch (index) {
+	case 0:
+		 SMC_RET4(handle, dram_info.timing_info->fsp_table[0],
+			1, 0, 5);
+	case 1:
+		if (!dram_info.bypass_mode) {
+			SMC_RET4(handle, dram_info.timing_info->fsp_table[1],
+				1, 0, 0);
+		}
+		SMC_RET4(handle, dram_info.timing_info->fsp_table[1],
+			2, 2, 4);
+	case 2:
+		if (!dram_info.bypass_mode) {
+			SMC_RET4(handle, dram_info.timing_info->fsp_table[2],
+				1, 0, 0);
+		}
+		SMC_RET4(handle, dram_info.timing_info->fsp_table[2],
+			2, 3, 3);
+	case 3:
+		 SMC_RET4(handle, dram_info.timing_info->fsp_table[3],
+			1, 0, 0);
+	default:
+		SMC_RET1(handle, -3);
+	}
+}
+
+int dram_dvfs_handler(uint32_t smc_fid, void *handle,
+	u_register_t x1, u_register_t x2, u_register_t x3)
+{
+	uint64_t mpidr = read_mpidr_el1();
+	unsigned int cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
+	unsigned int fsp_index = x1;
+	uint32_t online_cores = x2;
+
+	if (x1 == IMX_SIP_DDR_DVFS_GET_FREQ_COUNT) {
+		SMC_RET1(handle, dram_info.num_fsp);
+	} else if (x1 == IMX_SIP_DDR_DVFS_GET_FREQ_INFO) {
+		return dram_dvfs_get_freq_info(handle, x2);
+	} else if (x1 < 4) {
+		wait_ddrc_hwffc_done = true;
+		dsb();
+
+		/* trigger the SGI IPI to info other cores */
+		for (int i = 0; i < PLATFORM_CORE_COUNT; i++) {
+			if (cpu_id != i && (online_cores & (0x1 << (i * 8)))) {
+				plat_ic_raise_el3_sgi(0x8, i);
+			}
+		}
+
+		/* make sure all the core in WFE */
+		online_cores &= ~(0x1 << (cpu_id * 8));
+		while (1) {
+			if (online_cores == wfe_done) {
+				break;
+			}
+		}
+
+		/* flush the L1/L2 cache */
+		dcsw_op_all(DCCSW);
+
+		if (dram_info.dram_type == DDRC_LPDDR4) {
+			lpddr4_swffc(&dram_info, dev_fsp, fsp_index);
+			dev_fsp = (~dev_fsp) & 0x1;
+		} else if (dram_info.dram_type == DDRC_DDR4) {
+			ddr4_swffc(&dram_info, fsp_index);
+		}
+
+		dram_info.current_fsp = fsp_index;
+		wait_ddrc_hwffc_done = false;
+		wfe_done = 0;
+		dsb();
+		sev();
+		isb();
+	}
+
+	SMC_RET1(handle, 0);
+}
diff --git a/plat/imx/imx8m/ddr/dram_retention.c b/plat/imx/imx8m/ddr/dram_retention.c
new file mode 100644
index 0000000..7d4f823
--- /dev/null
+++ b/plat/imx/imx8m/ddr/dram_retention.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright 2018-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+#include <lib/mmio.h>
+
+#include <dram.h>
+#include <platform_def.h>
+
+#define SRC_DDR1_RCR		(IMX_SRC_BASE + 0x1000)
+#define SRC_DDR2_RCR		(IMX_SRC_BASE + 0x1004)
+
+#define PU_PGC_UP_TRG		0xf8
+#define PU_PGC_DN_TRG		0x104
+#define GPC_PU_PWRHSK		(IMX_GPC_BASE + 0x01FC)
+#define CCM_SRC_CTRL_OFFSET     (IMX_CCM_BASE + 0x800)
+#define CCM_CCGR_OFFSET         (IMX_CCM_BASE + 0x4000)
+#define CCM_SRC_CTRL(n)		(CCM_SRC_CTRL_OFFSET + 0x10 * (n))
+#define CCM_CCGR(n)		(CCM_CCGR_OFFSET + 0x10 * (n))
+
+#define DRAM_PLL_CTRL		(IMX_ANAMIX_BASE + 0x50)
+
+#define DBGCAM_EMPTY		0x36000000
+
+void dram_enter_retention(void)
+{
+	/* Wait DBGCAM to be empty */
+	while (mmio_read_32(DDRC_DBGCAM(0)) != DBGCAM_EMPTY) {
+		;
+	}
+
+	/* Block AXI ports from taking anymore transactions */
+	mmio_write_32(DDRC_PCTRL_0(0), 0x0);
+	/* Wait until all AXI ports are idle */
+	while (mmio_read_32(DDRC_PSTAT(0)) & 0x10001) {
+		;
+	}
+
+	/* Enter self refresh */
+	mmio_write_32(DDRC_PWRCTL(0), 0xaa);
+
+	/* LPDDR4 & DDR4/DDR3L need to check different status */
+	if (dram_info.dram_type == DDRC_LPDDR4) {
+		while (0x223 != (mmio_read_32(DDRC_STAT(0)) & 0x33f)) {
+			;
+		}
+	} else {
+		while (0x23 != (mmio_read_32(DDRC_STAT(0)) & 0x3f)) {
+			;
+		}
+	}
+
+	mmio_write_32(DDRC_DFIMISC(0), 0x0);
+	mmio_write_32(DDRC_SWCTL(0), 0x0);
+	mmio_write_32(DDRC_DFIMISC(0), 0x1f00);
+	mmio_write_32(DDRC_DFIMISC(0), 0x1f20);
+
+	while (mmio_read_32(DDRC_DFISTAT(0)) & 0x1) {
+		;
+	}
+
+	mmio_write_32(DDRC_DFIMISC(0), 0x1f00);
+	/* wait DFISTAT.dfi_init_complete to 1 */
+	while (!(mmio_read_32(DDRC_DFISTAT(0)) & 0x1)) {
+		;
+	}
+
+	mmio_write_32(DDRC_SWCTL(0), 0x1);
+
+	/* should check PhyInLP3 pub reg */
+	dwc_ddrphy_apb_wr(0xd0000, 0x0);
+	if (!(dwc_ddrphy_apb_rd(0x90028) & 0x1)) {
+		INFO("PhyInLP3 = 1\n");
+	}
+	dwc_ddrphy_apb_wr(0xd0000, 0x1);
+
+#if defined(PLAT_imx8mq)
+	/* pwrdnreqn_async adbm/adbs of ddr */
+	mmio_clrbits_32(GPC_PU_PWRHSK, BIT(1));
+	while (mmio_read_32(GPC_PU_PWRHSK) & BIT(18)) {
+		;
+	}
+	mmio_setbits_32(GPC_PU_PWRHSK, BIT(1));
+#else
+	/* pwrdnreqn_async adbm/adbs of ddr */
+	mmio_clrbits_32(GPC_PU_PWRHSK, BIT(2));
+	while (mmio_read_32(GPC_PU_PWRHSK) & BIT(20)) {
+		;
+	}
+	mmio_setbits_32(GPC_PU_PWRHSK, BIT(2));
+#endif
+	/* remove PowerOk */
+	mmio_write_32(SRC_DDR1_RCR, 0x8F000008);
+
+	mmio_write_32(CCM_CCGR(5), 0);
+	mmio_write_32(CCM_SRC_CTRL(15), 2);
+
+	/* enable the phy iso */
+	mmio_setbits_32(IMX_GPC_BASE + 0xd40, 1);
+	mmio_setbits_32(IMX_GPC_BASE + PU_PGC_DN_TRG, BIT(5));
+
+	VERBOSE("dram enter retention\n");
+}
+
+void dram_exit_retention(void)
+{
+	VERBOSE("dram exit retention\n");
+	/* assert all reset */
+#if defined(PLAT_imx8mq)
+	mmio_write_32(SRC_DDR2_RCR, 0x8F000003);
+	mmio_write_32(SRC_DDR1_RCR, 0x8F00000F);
+	mmio_write_32(SRC_DDR2_RCR, 0x8F000000);
+#else
+	mmio_write_32(SRC_DDR1_RCR, 0x8F00001F);
+	mmio_write_32(SRC_DDR1_RCR, 0x8F00000F);
+#endif
+	mmio_write_32(CCM_CCGR(5), 2);
+	mmio_write_32(CCM_SRC_CTRL(15), 2);
+
+	/* disable iso */
+	mmio_setbits_32(IMX_GPC_BASE + PU_PGC_UP_TRG, BIT(5));
+	mmio_write_32(SRC_DDR1_RCR, 0x8F000006);
+
+	/* wait dram pll locked */
+	while (!(mmio_read_32(DRAM_PLL_CTRL) & BIT(31))) {
+		;
+	}
+
+	/* ddrc re-init */
+	dram_umctl2_init(dram_info.timing_info);
+
+	/*
+	 * Skips the DRAM init routine and starts up in selfrefresh mode
+	 * Program INIT0.skip_dram_init = 2'b11
+	 */
+	mmio_setbits_32(DDRC_INIT0(0), 0xc0000000);
+	/* Keeps the controller in self-refresh mode */
+	mmio_write_32(DDRC_PWRCTL(0), 0xaa);
+	mmio_write_32(DDRC_DBG1(0), 0x0);
+	mmio_write_32(SRC_DDR1_RCR, 0x8F000004);
+	mmio_write_32(SRC_DDR1_RCR, 0x8F000000);
+
+	/* before write Dynamic reg, sw_done should be 0 */
+	mmio_write_32(DDRC_SWCTL(0), 0x0);
+
+#if !PLAT_imx8mn
+	if (dram_info.dram_type == DDRC_LPDDR4) {
+		mmio_write_32(DDRC_DDR_SS_GPR0, 0x01); /*LPDDR4 mode */
+	}
+#endif /* !PLAT_imx8mn */
+
+	mmio_write_32(DDRC_DFIMISC(0), 0x0);
+
+	/* dram phy re-init */
+	dram_phy_init(dram_info.timing_info);
+
+	/* DWC_DDRPHYA_APBONLY0_MicroContMuxSel */
+	dwc_ddrphy_apb_wr(0xd0000, 0x0);
+	while (dwc_ddrphy_apb_rd(0x20097)) {
+		;
+	}
+	dwc_ddrphy_apb_wr(0xd0000, 0x1);
+
+	/* before write Dynamic reg, sw_done should be 0 */
+	mmio_write_32(DDRC_SWCTL(0), 0x0);
+	mmio_write_32(DDRC_DFIMISC(0), 0x20);
+	/* wait DFISTAT.dfi_init_complete to 1 */
+	while (!(mmio_read_32(DDRC_DFISTAT(0)) & 0x1)) {
+		;
+	}
+
+	/* clear DFIMISC.dfi_init_start */
+	mmio_write_32(DDRC_DFIMISC(0), 0x0);
+	/* set DFIMISC.dfi_init_complete_en */
+	mmio_write_32(DDRC_DFIMISC(0), 0x1);
+
+	/* set SWCTL.sw_done to enable quasi-dynamic register programming */
+	mmio_write_32(DDRC_SWCTL(0), 0x1);
+	/* wait SWSTAT.sw_done_ack to 1 */
+	while (!(mmio_read_32(DDRC_SWSTAT(0)) & 0x1)) {
+		;
+	}
+
+	mmio_write_32(DDRC_PWRCTL(0), 0x88);
+	/* wait STAT to normal state */
+	while (0x1 != (mmio_read_32(DDRC_STAT(0)) & 0x7)) {
+		;
+	}
+
+	mmio_write_32(DDRC_PCTRL_0(0), 0x1);
+	 /* dis_auto-refresh is set to 0 */
+	mmio_write_32(DDRC_RFSHCTL3(0), 0x0);
+
+	/* should check PhyInLP3 pub reg */
+	dwc_ddrphy_apb_wr(0xd0000, 0x0);
+	if (!(dwc_ddrphy_apb_rd(0x90028) & 0x1)) {
+		VERBOSE("PHYInLP3 = 0\n");
+	}
+	dwc_ddrphy_apb_wr(0xd0000, 0x1);
+}
diff --git a/plat/imx/imx8m/ddr/lpddr4_dvfs.c b/plat/imx/imx8m/ddr/lpddr4_dvfs.c
new file mode 100644
index 0000000..2b4f300
--- /dev/null
+++ b/plat/imx/imx8m/ddr/lpddr4_dvfs.c
@@ -0,0 +1,292 @@
+/*
+ * Copyright 2018-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/mmio.h>
+
+#include <dram.h>
+
+static void lpddr4_mr_write(uint32_t mr_rank, uint32_t mr_addr, uint32_t mr_data)
+{
+	/*
+	 * 1. Poll MRSTAT.mr_wr_busy until it is 0. This checks that there
+	 * is no outstanding MR transaction. No
+	 * writes should be performed to MRCTRL0 and MRCTRL1 if MRSTAT.mr_wr_busy = 1.
+	 */
+	while (mmio_read_32(DDRC_MRSTAT(0)) & 0x1)
+		;
+
+	/*
+	 * 2. Write the MRCTRL0.mr_type, MRCTRL0.mr_addr,
+	 * MRCTRL0.mr_rank and (for MRWs)
+	 * MRCTRL1.mr_data to define the MR transaction.
+	 */
+	mmio_write_32(DDRC_MRCTRL0(0), (mr_rank << 4));
+	mmio_write_32(DDRC_MRCTRL1(0), (mr_addr << 8) | mr_data);
+	mmio_setbits_32(DDRC_MRCTRL0(0), BIT(31));
+}
+
+void lpddr4_swffc(struct dram_info *info, unsigned int init_fsp,
+	 unsigned int fsp_index)
+
+{
+	uint32_t mr, emr, emr2, emr3;
+	uint32_t mr11, mr12, mr22, mr14;
+	uint32_t val;
+	uint32_t derate_backup[3];
+	uint32_t (*mr_data)[8];
+
+	/* 1. program targetd UMCTL2_REGS_FREQ1/2/3,already done, skip it. */
+
+	/* 2. MR13.FSP-WR=1, MRW to update MR registers */
+	mr_data = info->mr_table;
+	mr = mr_data[fsp_index][0];
+	emr  = mr_data[fsp_index][1];
+	emr2 = mr_data[fsp_index][2];
+	emr3 = mr_data[fsp_index][3];
+	mr11 = mr_data[fsp_index][4];
+	mr12 = mr_data[fsp_index][5];
+	mr22 = mr_data[fsp_index][6];
+	mr14 = mr_data[fsp_index][7];
+
+	val = (init_fsp == 1) ? 0x2 << 6 : 0x1 << 6;
+	emr3 = (emr3 & 0x003f) | val | 0x0d00;
+
+	/* 12. set PWRCTL.selfref_en=0 */
+	mmio_clrbits_32(DDRC_PWRCTL(0), 0xf);
+
+	/* It is more safe to config it here */
+	mmio_clrbits_32(DDRC_DFIPHYMSTR(0), 0x1);
+
+	lpddr4_mr_write(3, 13, emr3);
+	lpddr4_mr_write(3, 1, mr);
+	lpddr4_mr_write(3, 2, emr);
+	lpddr4_mr_write(3, 3, emr2);
+	lpddr4_mr_write(3, 11, mr11);
+	lpddr4_mr_write(3, 12, mr12);
+	lpddr4_mr_write(3, 14, mr14);
+	lpddr4_mr_write(3, 22, mr22);
+
+	do {
+		val = mmio_read_32(DDRC_MRSTAT(0));
+	} while (val & 0x1);
+
+	/* 3. disable AXI ports */
+	mmio_write_32(DDRC_PCTRL_0(0), 0x0);
+
+	/* 4.Poll PSTAT.rd_port_busy_n=0 and PSTAT.wr_port_busy_n=0. */
+	do {
+		val = mmio_read_32(DDRC_PSTAT(0));
+	} while (val != 0);
+
+	/* 6.disable SBRCTL.scrub_en, skip if never enable it */
+	/* 7.poll SBRSTAT.scrub_busy  Q2: should skip phy master if never enable it */
+	/* Disable phy master */
+#ifdef DFILP_SPT
+	/* 8. disable DFI LP */
+	/* DFILPCFG0.dfi_lp_en_sr */
+	val = mmio_read_32(DDRC_DFILPCFG0(0));
+	if (val & 0x100) {
+		mmio_write_32(DDRC_DFILPCFG0(0), 0x0);
+		do {
+			val = mmio_read_32(DDRC_DFISTAT(0)); // dfi_lp_ack
+			val2 = mmio_read_32(DDRC_STAT(0)); // operating_mode
+		} while (((val & 0x2) == 0x2) && ((val2 & 0x7) == 3));
+	}
+#endif
+	/* 9. wait until in normal or power down states */
+	do {
+		/* operating_mode */
+		val = mmio_read_32(DDRC_STAT(0));
+	} while (((val & 0x7) != 1) && ((val & 0x7) != 2));
+
+	/* 10. Disable automatic derating: derate_enable */
+	val = mmio_read_32(DDRC_DERATEEN(0));
+	derate_backup[0] = val;
+	mmio_clrbits_32(DDRC_DERATEEN(0), 0x1);
+
+	val = mmio_read_32(DDRC_FREQ1_DERATEEN(0));
+	derate_backup[1] = val;
+	mmio_clrbits_32(DDRC_FREQ1_DERATEEN(0), 0x1);
+
+	val = mmio_read_32(DDRC_FREQ2_DERATEEN(0));
+	derate_backup[2] = val;
+	mmio_clrbits_32(DDRC_FREQ2_DERATEEN(0), 0x1);
+
+	/* 11. disable automatic ZQ calibration */
+	mmio_setbits_32(DDRC_ZQCTL0(0), BIT(31));
+	mmio_setbits_32(DDRC_FREQ1_ZQCTL0(0), BIT(31));
+	mmio_setbits_32(DDRC_FREQ2_ZQCTL0(0), BIT(31));
+
+	/* 12. set PWRCTL.selfref_en=0 */
+	mmio_clrbits_32(DDRC_PWRCTL(0), 0x1);
+
+	/* 13.Poll STAT.operating_mode is in "Normal" (001) or "Power-down" (010) */
+	do {
+		val = mmio_read_32(DDRC_STAT(0));
+	} while (((val & 0x7) != 1) && ((val & 0x7) != 2));
+
+	/* 14-15. trigger SW SR */
+	/* bit 5: selfref_sw, bit 6: stay_in_selfref */
+	mmio_setbits_32(DDRC_PWRCTL(0), 0x60);
+
+	/* 16. Poll STAT.selfref_state in "Self Refresh 1" */
+	do {
+		val = mmio_read_32(DDRC_STAT(0));
+	} while ((val & 0x300) != 0x100);
+
+	/* 17. disable dq */
+	mmio_setbits_32(DDRC_DBG1(0), 0x1);
+
+	/* 18. Poll DBGCAM.wr_data_pipeline_empty and DBGCAM.rd_data_pipeline_empty */
+	do {
+		val = mmio_read_32(DDRC_DBGCAM(0));
+		val &= 0x30000000;
+	} while (val != 0x30000000);
+
+	/* 19. change MR13.FSP-OP to new FSP and MR13.VRCG to high current */
+	emr3 = (((~init_fsp) & 0x1) << 7) | (0x1 << 3) | (emr3 & 0x0077) | 0x0d00;
+	lpddr4_mr_write(3, 13, emr3);
+
+	/* 20. enter SR Power Down */
+	mmio_clrsetbits_32(DDRC_PWRCTL(0), 0x60, 0x20);
+
+	/* 21. Poll STAT.selfref_state is in "SR Power down" */
+	do {
+		val = mmio_read_32(DDRC_STAT(0));
+	} while ((val & 0x300) != 0x200);
+
+	/* 22. set dfi_init_complete_en = 0 */
+
+	/* 23. switch clock */
+	/* set SWCTL.dw_done to 0 */
+	mmio_write_32(DDRC_SWCTL(0), 0x0000);
+
+	/* 24. program frequency mode=1(bit 29), target_frequency=target_freq (bit 29) */
+	mmio_write_32(DDRC_MSTR2(0), fsp_index);
+
+	/* 25. DBICTL for FSP-OP[1], skip it if never enable it */
+
+	/* 26.trigger initialization in the PHY */
+
+	/* Q3: if refresh level is updated, then should program */
+	/* as updating refresh, need to toggle refresh_update_level signal */
+	val = mmio_read_32(DDRC_RFSHCTL3(0));
+	val = val ^ 0x2;
+	mmio_write_32(DDRC_RFSHCTL3(0), val);
+
+	/* Q4: only for legacy PHY, so here can skipped */
+
+	/* dfi_frequency -> 0x1x */
+	val = mmio_read_32(DDRC_DFIMISC(0));
+	val &= 0xFE;
+	val |= (fsp_index << 8);
+	mmio_write_32(DDRC_DFIMISC(0), val);
+	/* dfi_init_start */
+	val |= 0x20;
+	mmio_write_32(DDRC_DFIMISC(0), val);
+
+	/* polling dfi_init_complete de-assert */
+	do {
+		val = mmio_read_32(DDRC_DFISTAT(0));
+	} while ((val & 0x1) == 0x1);
+
+	/* change the clock frequency */
+	dram_clock_switch(info->timing_info->fsp_table[fsp_index], info->bypass_mode);
+
+	/* dfi_init_start de-assert */
+	mmio_clrbits_32(DDRC_DFIMISC(0), 0x20);
+
+	/* polling dfi_init_complete re-assert */
+	do {
+		val = mmio_read_32(DDRC_DFISTAT(0));
+	} while ((val & 0x1) == 0x0);
+
+	/* 27. set ZQCTL0.dis_srx_zqcl = 1 */
+	if (fsp_index == 0) {
+		mmio_setbits_32(DDRC_ZQCTL0(0), BIT(30));
+	} else  if (fsp_index == 1) {
+		mmio_setbits_32(DDRC_FREQ1_ZQCTL0(0), BIT(30));
+	} else {
+		mmio_setbits_32(DDRC_FREQ2_ZQCTL0(0), BIT(30));
+	}
+
+	/* 28,29. exit "self refresh power down" to stay "self refresh 2" */
+	/* exit SR power down */
+	mmio_clrsetbits_32(DDRC_PWRCTL(0), 0x60, 0x40);
+	/* 30. Poll STAT.selfref_state in "Self refresh 2" */
+	do {
+		val = mmio_read_32(DDRC_STAT(0));
+	} while ((val & 0x300) != 0x300);
+
+	/* 31. change MR13.VRCG to normal */
+	emr3 = (emr3 & 0x00f7) | 0x0d00;
+	lpddr4_mr_write(3, 13, emr3);
+
+	/* enable PHY master */
+	mmio_write_32(DDRC_DFIPHYMSTR(0), 0x1);
+
+	/* 32. issue ZQ if required: zq_calib_short, bit 4 */
+	/* polling zq_calib_short_busy */
+	mmio_setbits_32(DDRC_DBGCMD(0), 0x10);
+
+	do {
+		val = mmio_read_32(DDRC_DBGSTAT(0));
+	} while ((val & 0x10) != 0x0);
+
+	/* 33. Reset ZQCTL0.dis_srx_zqcl=0 */
+	if (fsp_index == 1)
+		mmio_clrbits_32(DDRC_FREQ1_ZQCTL0(0), BIT(30));
+	else if (fsp_index == 2)
+		mmio_clrbits_32(DDRC_FREQ2_ZQCTL0(0), BIT(30));
+	else
+		mmio_clrbits_32(DDRC_ZQCTL0(0), BIT(30));
+
+	/* set SWCTL.dw_done to 1 and poll SWSTAT.sw_done_ack=1 */
+	mmio_write_32(DDRC_SWCTL(0), 0x1);
+
+	/* wait SWSTAT.sw_done_ack to 1 */
+	do {
+		val = mmio_read_32(DDRC_SWSTAT(0));
+	} while ((val & 0x1) == 0x0);
+
+	/* 34. set PWRCTL.stay_in_selfreh=0, exit SR */
+	mmio_clrbits_32(DDRC_PWRCTL(0), 0x40);
+	/* wait tXSR */
+
+	/* 35. Poll STAT.selfref_state in "Idle" */
+	do {
+		val = mmio_read_32(DDRC_STAT(0));
+	} while ((val & 0x300) != 0x0);
+
+#ifdef DFILP_SPT
+	/* 36. restore dfi_lp.dfi_lp_en_sr */
+	mmio_setbits_32(DDRC_DFILPCFG0(0), BIT(8));
+#endif
+
+	/* 37. re-enable CAM: dis_dq */
+	mmio_clrbits_32(DDRC_DBG1(0), 0x1);
+
+	/* 38. re-enable automatic SR: selfref_en */
+	mmio_setbits_32(DDRC_PWRCTL(0), 0x1);
+
+	/* 39. re-enable automatic ZQ: dis_auto_zq=0 */
+	/* disable automatic ZQ calibration */
+	if (fsp_index == 1)
+		mmio_clrbits_32(DDRC_FREQ1_ZQCTL0(0), BIT(31));
+	else if (fsp_index == 2)
+		mmio_clrbits_32(DDRC_FREQ2_ZQCTL0(0), BIT(31));
+	else
+		mmio_clrbits_32(DDRC_ZQCTL0(0), BIT(31));
+	/* 40. re-emable automatic derating: derate_enable */
+	mmio_write_32(DDRC_DERATEEN(0), derate_backup[0]);
+	mmio_write_32(DDRC_FREQ1_DERATEEN(0), derate_backup[1]);
+	mmio_write_32(DDRC_FREQ2_DERATEEN(0), derate_backup[2]);
+
+	/* 41. write 1 to PCTRL.port_en */
+	mmio_write_32(DDRC_PCTRL_0(0), 0x1);
+
+	/* 42. enable SBRCTL.scrub_en, skip if never enable it */
+}
diff --git a/plat/imx/imx8m/gpc_common.c b/plat/imx/imx8m/gpc_common.c
index 1e55f05..e674d7a 100644
--- a/plat/imx/imx8m/gpc_common.c
+++ b/plat/imx/imx8m/gpc_common.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,6 +9,7 @@
 #include <arch.h>
 #include <arch_helpers.h>
 #include <common/debug.h>
+#include <common/runtime_svc.h>
 #include <lib/mmio.h>
 #include <lib/psci/psci.h>
 
@@ -16,10 +17,14 @@
 #include <imx8m_psci.h>
 #include <plat_imx8.h>
 
+#define MAX_PLL_NUM	U(10)
+
 static uint32_t gpc_imr_offset[] = { IMR1_CORE0_A53, IMR1_CORE1_A53, IMR1_CORE2_A53, IMR1_CORE3_A53, };
 
 DEFINE_BAKERY_LOCK(gpc_lock);
 
+#define FSL_SIP_CONFIG_GPC_PM_DOMAIN		0x03
+
 #pragma weak imx_set_cpu_pwr_off
 #pragma weak imx_set_cpu_pwr_on
 #pragma weak imx_set_cpu_lpm
@@ -250,3 +255,54 @@
 	mmio_clrbits_32(IMX_GPC_BASE + SLPCR, SLPCR_RBC_EN |
 		(0x3f << SLPCR_RBC_COUNT_SHIFT));
 }
+
+struct pll_override {
+	uint32_t reg;
+	uint32_t override_mask;
+};
+
+struct pll_override pll[MAX_PLL_NUM] = {
+	{.reg = 0x0, .override_mask = (1 << 12) | (1 << 8), },
+	{.reg = 0x14, .override_mask = (1 << 12) | (1 << 8), },
+	{.reg = 0x28, .override_mask = (1 << 12) | (1 << 8), },
+	{.reg = 0x50, .override_mask = (1 << 12) | (1 << 8), },
+	{.reg = 0x64, .override_mask = (1 << 10) | (1 << 8), },
+	{.reg = 0x74, .override_mask = (1 << 10) | (1 << 8), },
+	{.reg = 0x84, .override_mask = (1 << 10) | (1 << 8), },
+	{.reg = 0x94, .override_mask = 0x5555500, },
+	{.reg = 0x104, .override_mask = 0x5555500, },
+	{.reg = 0x114, .override_mask = 0x500, },
+};
+
+#define PLL_BYPASS	BIT(4)
+void imx_anamix_override(bool enter)
+{
+	unsigned int i;
+
+	/*
+	 * bypass all the plls & enable the override bit before
+	 * entering DSM mode.
+	 */
+	for (i = 0U; i < MAX_PLL_NUM; i++) {
+		if (enter) {
+			mmio_setbits_32(IMX_ANAMIX_BASE + pll[i].reg, PLL_BYPASS);
+			mmio_setbits_32(IMX_ANAMIX_BASE + pll[i].reg, pll[i].override_mask);
+		} else {
+			mmio_clrbits_32(IMX_ANAMIX_BASE + pll[i].reg, PLL_BYPASS);
+			mmio_clrbits_32(IMX_ANAMIX_BASE + pll[i].reg, pll[i].override_mask);
+		}
+	}
+}
+
+int imx_gpc_handler(uint32_t smc_fid, u_register_t x1, u_register_t x2, u_register_t x3)
+{
+	switch (x1) {
+	case FSL_SIP_CONFIG_GPC_PM_DOMAIN:
+		imx_gpc_pm_domain_enable(x2, x3);
+		break;
+	default:
+		return SMC_UNK;
+	}
+
+	return 0;
+}
diff --git a/plat/imx/imx8m/imx8m_psci_common.c b/plat/imx/imx8m/imx8m_psci_common.c
index 9dfd311..4df4f8e 100644
--- a/plat/imx/imx8m/imx8m_psci_common.c
+++ b/plat/imx/imx8m/imx8m_psci_common.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -13,6 +13,7 @@
 #include <lib/mmio.h>
 #include <lib/psci/psci.h>
 
+#include <dram.h>
 #include <gpc.h>
 #include <imx8m_psci.h>
 #include <plat_imx8.h>
@@ -118,8 +119,11 @@
 	if (!is_local_state_run(CLUSTER_PWR_STATE(target_state)))
 		imx_set_cluster_powerdown(core_id, CLUSTER_PWR_STATE(target_state));
 
-	if (is_local_state_off(SYSTEM_PWR_STATE(target_state)))
+	if (is_local_state_off(SYSTEM_PWR_STATE(target_state))) {
 		imx_set_sys_lpm(core_id, true);
+		dram_enter_retention();
+		imx_anamix_override(true);
+	}
 }
 
 void imx_domain_suspend_finish(const psci_power_state_t *target_state)
@@ -127,8 +131,11 @@
 	uint64_t mpidr = read_mpidr_el1();
 	unsigned int core_id = MPIDR_AFFLVL0_VAL(mpidr);
 
-	if (is_local_state_off(SYSTEM_PWR_STATE(target_state)))
+	if (is_local_state_off(SYSTEM_PWR_STATE(target_state))) {
+		imx_anamix_override(false);
+		dram_exit_retention();
 		imx_set_sys_lpm(core_id, false);
+	}
 
 	if (!is_local_state_run(CLUSTER_PWR_STATE(target_state))) {
 		imx_clear_rbc_count();
diff --git a/plat/imx/imx8m/imx8mm/gpc.c b/plat/imx/imx8m/imx8mm/gpc.c
index ab59292..cc1cb10 100644
--- a/plat/imx/imx8m/imx8mm/gpc.c
+++ b/plat/imx/imx8m/imx8mm/gpc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -19,6 +19,332 @@
 #include <gpc.h>
 #include <imx_sip_svc.h>
 
+#define MIPI_PWR_REQ		BIT(0)
+#define PCIE_PWR_REQ		BIT(1)
+#define OTG1_PWR_REQ		BIT(2)
+#define OTG2_PWR_REQ		BIT(3)
+#define HSIOMIX_PWR_REQ		BIT(4)
+#define GPU2D_PWR_REQ		BIT(6)
+#define GPUMIX_PWR_REQ		BIT(7)
+#define VPUMIX_PWR_REQ		BIT(8)
+#define GPU3D_PWR_REQ		BIT(9)
+#define DISPMIX_PWR_REQ		BIT(10)
+#define VPU_G1_PWR_REQ		BIT(11)
+#define VPU_G2_PWR_REQ		BIT(12)
+#define VPU_H1_PWR_REQ		BIT(13)
+
+#define HSIOMIX_ADB400_SYNC	(0x3 << 5)
+#define DISPMIX_ADB400_SYNC	BIT(7)
+#define VPUMIX_ADB400_SYNC	BIT(8)
+#define GPU3D_ADB400_SYNC	BIT(9)
+#define GPU2D_ADB400_SYNC	BIT(10)
+#define GPUMIX_ADB400_SYNC	BIT(11)
+#define HSIOMIX_ADB400_ACK	(0x3 << 23)
+#define DISPMIX_ADB400_ACK	BIT(25)
+#define VPUMIX_ADB400_ACK	BIT(26)
+#define GPU3D_ADB400_ACK	BIT(27)
+#define GPU2D_ADB400_ACK	BIT(28)
+#define GPUMIX_ADB400_ACK	BIT(29)
+
+#define MIPI_PGC		0xc00
+#define PCIE_PGC		0xc40
+#define OTG1_PGC		0xc80
+#define OTG2_PGC		0xcc0
+#define HSIOMIX_PGC	        0xd00
+#define GPU2D_PGC		0xd80
+#define GPUMIX_PGC		0xdc0
+#define VPUMIX_PGC		0xe00
+#define GPU3D_PGC		0xe40
+#define DISPMIX_PGC		0xe80
+#define VPU_G1_PGC		0xec0
+#define VPU_G2_PGC		0xf00
+#define VPU_H1_PGC		0xf40
+
+enum pu_domain_id {
+	HSIOMIX,
+	PCIE,
+	OTG1,
+	OTG2,
+	GPUMIX,
+	VPUMIX,
+	VPU_G1,
+	VPU_G2,
+	VPU_H1,
+	DISPMIX,
+	MIPI,
+	/* below two domain only for ATF internal use */
+	GPU2D,
+	GPU3D,
+	MAX_DOMAINS,
+};
+
+/* PU domain */
+static struct imx_pwr_domain pu_domains[] = {
+	IMX_MIX_DOMAIN(HSIOMIX, false),
+	IMX_PD_DOMAIN(PCIE, false),
+	IMX_PD_DOMAIN(OTG1, true),
+	IMX_PD_DOMAIN(OTG2, true),
+	IMX_MIX_DOMAIN(GPUMIX, false),
+	IMX_MIX_DOMAIN(VPUMIX, false),
+	IMX_PD_DOMAIN(VPU_G1, false),
+	IMX_PD_DOMAIN(VPU_G2, false),
+	IMX_PD_DOMAIN(VPU_H1, false),
+	IMX_MIX_DOMAIN(DISPMIX, false),
+	IMX_PD_DOMAIN(MIPI, false),
+	/* below two domain only for ATF internal use */
+	IMX_MIX_DOMAIN(GPU2D, false),
+	IMX_MIX_DOMAIN(GPU3D, false),
+};
+
+static unsigned int pu_domain_status;
+
+#define GPU_RCR		0x40
+#define VPU_RCR		0x44
+
+#define VPU_CTL_BASE		0x38330000
+#define BLK_SFT_RSTN_CSR	0x0
+#define H1_SFT_RSTN		BIT(2)
+#define G1_SFT_RSTN		BIT(1)
+#define G2_SFT_RSTN		BIT(0)
+
+#define DISP_CTL_BASE		0x32e28000
+
+void vpu_sft_reset_assert(uint32_t domain_id)
+{
+	uint32_t val;
+
+	val = mmio_read_32(VPU_CTL_BASE + BLK_SFT_RSTN_CSR);
+
+	switch (domain_id) {
+	case VPU_G1:
+		val &= ~G1_SFT_RSTN;
+		mmio_write_32(VPU_CTL_BASE + BLK_SFT_RSTN_CSR, val);
+		break;
+	case VPU_G2:
+		val &= ~G2_SFT_RSTN;
+		mmio_write_32(VPU_CTL_BASE + BLK_SFT_RSTN_CSR, val);
+		break;
+	case VPU_H1:
+		val &= ~H1_SFT_RSTN;
+		mmio_write_32(VPU_CTL_BASE + BLK_SFT_RSTN_CSR, val);
+		break;
+	default:
+		break;
+	}
+}
+
+void vpu_sft_reset_deassert(uint32_t domain_id)
+{
+	uint32_t val;
+
+	val = mmio_read_32(VPU_CTL_BASE + BLK_SFT_RSTN_CSR);
+
+	switch (domain_id) {
+	case VPU_G1:
+		val |= G1_SFT_RSTN;
+		mmio_write_32(VPU_CTL_BASE + BLK_SFT_RSTN_CSR, val);
+		break;
+	case VPU_G2:
+		val |= G2_SFT_RSTN;
+		mmio_write_32(VPU_CTL_BASE + BLK_SFT_RSTN_CSR, val);
+		break;
+	case VPU_H1:
+		val |= H1_SFT_RSTN;
+		mmio_write_32(VPU_CTL_BASE + BLK_SFT_RSTN_CSR, val);
+		break;
+	default:
+		break;
+	}
+}
+
+void imx_gpc_pm_domain_enable(uint32_t domain_id, bool on)
+{
+	if (domain_id >= MAX_DOMAINS) {
+		return;
+	}
+
+	struct imx_pwr_domain *pwr_domain = &pu_domains[domain_id];
+
+	if (on) {
+		pu_domain_status |= (1 << domain_id);
+
+		if (domain_id == VPU_G1 || domain_id == VPU_G2 ||
+		    domain_id == VPU_H1) {
+			vpu_sft_reset_assert(domain_id);
+		}
+
+		/* HSIOMIX has no PU bit, so skip for it */
+		if (domain_id != HSIOMIX) {
+			/* clear the PGC bit */
+			mmio_clrbits_32(IMX_GPC_BASE + pwr_domain->pgc_offset, 0x1);
+
+			/* power up the domain */
+			mmio_setbits_32(IMX_GPC_BASE + PU_PGC_UP_TRG, pwr_domain->pwr_req);
+
+			/* wait for power request done */
+			while (mmio_read_32(IMX_GPC_BASE + PU_PGC_UP_TRG) & pwr_domain->pwr_req) {
+				;
+			}
+		}
+
+		if (domain_id == VPU_G1 || domain_id == VPU_G2 ||
+		    domain_id == VPU_H1) {
+			vpu_sft_reset_deassert(domain_id);
+			/* dealy for a while to make sure reset done */
+			udelay(100);
+		}
+
+		if (domain_id == GPUMIX) {
+			/* assert reset */
+			mmio_write_32(IMX_SRC_BASE + GPU_RCR, 0x1);
+
+			/* power up GPU2D */
+			mmio_clrbits_32(IMX_GPC_BASE + GPU2D_PGC, 0x1);
+
+			mmio_setbits_32(IMX_GPC_BASE + PU_PGC_UP_TRG, GPU2D_PWR_REQ);
+
+			/* wait for power request done */
+			while (mmio_read_32(IMX_GPC_BASE + PU_PGC_UP_TRG) & GPU2D_PWR_REQ) {
+				;
+			}
+
+			udelay(1);
+
+			/* power up GPU3D */
+			mmio_clrbits_32(IMX_GPC_BASE + GPU3D_PGC, 0x1);
+
+			mmio_setbits_32(IMX_GPC_BASE + PU_PGC_UP_TRG, GPU3D_PWR_REQ);
+
+			/* wait for power request done */
+			while (mmio_read_32(IMX_GPC_BASE + PU_PGC_UP_TRG) & GPU3D_PWR_REQ) {
+				;
+			}
+
+			udelay(10);
+			/* release the gpumix reset */
+			mmio_write_32(IMX_SRC_BASE + GPU_RCR, 0x0);
+			udelay(10);
+		}
+
+		/* vpu sft clock enable */
+		if (domain_id == VPUMIX) {
+			mmio_write_32(IMX_SRC_BASE + VPU_RCR, 0x1);
+			udelay(5);
+			mmio_write_32(IMX_SRC_BASE + VPU_RCR, 0x0);
+			udelay(5);
+
+			/* enable all clock */
+			mmio_write_32(VPU_CTL_BASE + 0x4, 0x7);
+		}
+
+		if (domain_id == DISPMIX) {
+			/* special setting for DISPMIX */
+			mmio_write_32(DISP_CTL_BASE + 0x4, 0x1fff);
+			mmio_write_32(DISP_CTL_BASE, 0x7f);
+			mmio_write_32(DISP_CTL_BASE + 0x8, 0x30000);
+		}
+
+		/* handle the ADB400 sync */
+		if (pwr_domain->need_sync) {
+			/* clear adb power down request */
+			mmio_setbits_32(IMX_GPC_BASE + GPC_PU_PWRHSK, pwr_domain->adb400_sync);
+
+			/* wait for adb power request ack */
+			while (!(mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & pwr_domain->adb400_ack)) {
+				;
+			}
+		}
+
+		if (domain_id == GPUMIX) {
+			/* power up GPU2D ADB */
+			mmio_setbits_32(IMX_GPC_BASE + GPC_PU_PWRHSK, GPU2D_ADB400_SYNC);
+
+			/* wait for adb power request ack */
+			while (!(mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & GPU2D_ADB400_ACK)) {
+				;
+			}
+
+			/* power up GPU3D ADB */
+			mmio_setbits_32(IMX_GPC_BASE + GPC_PU_PWRHSK, GPU3D_ADB400_SYNC);
+
+			/* wait for adb power request ack */
+			while (!(mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & GPU3D_ADB400_ACK)) {
+				;
+			}
+		}
+	} else {
+		pu_domain_status &= ~(1 << domain_id);
+
+		if (domain_id == OTG1 || domain_id == OTG2) {
+			return;
+		}
+
+		/* GPU2D & GPU3D ADB power down */
+		if (domain_id == GPUMIX) {
+			mmio_clrbits_32(IMX_GPC_BASE + GPC_PU_PWRHSK, GPU2D_ADB400_SYNC);
+
+			/* wait for adb power request ack */
+			while ((mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & GPU2D_ADB400_ACK)) {
+				;
+			}
+
+			mmio_clrbits_32(IMX_GPC_BASE + GPC_PU_PWRHSK, GPU3D_ADB400_SYNC);
+
+				/* wait for adb power request ack */
+			while ((mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & GPU3D_ADB400_ACK)) {
+				;
+			}
+		}
+
+		/* handle the ADB400 sync */
+		if (pwr_domain->need_sync) {
+			/* set adb power down request */
+			mmio_clrbits_32(IMX_GPC_BASE + GPC_PU_PWRHSK, pwr_domain->adb400_sync);
+
+			/* wait for adb power request ack */
+			while ((mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & pwr_domain->adb400_ack)) {
+				;
+			}
+		}
+
+		if (domain_id == GPUMIX) {
+			/* power down GPU2D */
+			mmio_setbits_32(IMX_GPC_BASE + GPU2D_PGC, 0x1);
+
+			mmio_setbits_32(IMX_GPC_BASE + PU_PGC_DN_TRG, GPU2D_PWR_REQ);
+
+			/* wait for power request done */
+			while (mmio_read_32(IMX_GPC_BASE + PU_PGC_DN_TRG) & GPU2D_PWR_REQ) {
+				;
+			}
+
+			/* power down GPU3D */
+			mmio_setbits_32(IMX_GPC_BASE + GPU3D_PGC, 0x1);
+
+			mmio_setbits_32(IMX_GPC_BASE + PU_PGC_DN_TRG, GPU3D_PWR_REQ);
+
+			/* wait for power request done */
+			while (mmio_read_32(IMX_GPC_BASE + PU_PGC_DN_TRG) & GPU3D_PWR_REQ) {
+				;
+			}
+		}
+
+		/* HSIOMIX has no PU bit, so skip for it */
+		if (domain_id != HSIOMIX) {
+			/* set the PGC bit */
+			mmio_setbits_32(IMX_GPC_BASE + pwr_domain->pgc_offset, 0x1);
+
+			/* power down the domain */
+			mmio_setbits_32(IMX_GPC_BASE + PU_PGC_DN_TRG, pwr_domain->pwr_req);
+
+			/* wait for power request done */
+			while (mmio_read_32(IMX_GPC_BASE + PU_PGC_DN_TRG) & pwr_domain->pwr_req) {
+				;
+			}
+		}
+	}
+}
+
 void imx_gpc_init(void)
 {
 	unsigned int val;
@@ -85,7 +411,4 @@
 	 */
 	mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG1PHY_SCR, 0x1);
 	mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG2PHY_SCR, 0x1);
-
-	/* enable all the power domain by default */
-	mmio_write_32(IMX_GPC_BASE + PU_PGC_UP_TRG, 0x3fcf);
 }
diff --git a/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c b/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c
index debede1..ba0db0c 100644
--- a/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c
+++ b/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c
@@ -21,6 +21,7 @@
 #include <lib/xlat_tables/xlat_tables_v2.h>
 #include <plat/common/platform.h>
 
+#include <dram.h>
 #include <gpc.h>
 #include <imx_aipstz.h>
 #include <imx_uart.h>
@@ -34,6 +35,9 @@
 static const mmap_region_t imx_mmap[] = {
 	MAP_REGION_FLAT(IMX_GIC_BASE, IMX_GIC_SIZE, MT_DEVICE | MT_RW),
 	MAP_REGION_FLAT(IMX_AIPS_BASE, IMX_AIPS_SIZE, MT_DEVICE | MT_RW), /* AIPS map */
+	MAP_REGION_FLAT(OCRAM_S_BASE, OCRAM_S_SIZE, MT_DEVICE | MT_RW), /* OCRAM_S */
+	MAP_REGION_FLAT(IMX_DDRPHY_BASE, IMX_DDR_IPS_SIZE, MT_DEVICE | MT_RW), /* DDRMIX */
+	MAP_REGION_FLAT(IMX_VPUMIX_BASE, IMX_VPUMIX_SIZE, MT_DEVICE | MT_RW), /* VPUMIX */
 	{0},
 };
 
@@ -198,6 +202,9 @@
 	/* select the CKIL source to 32K OSC */
 	mmio_write_32(IMX_ANAMIX_BASE + ANAMIX_MISC_CTL, 0x1);
 
+	/* Init the dram info */
+	dram_info_init(SAVED_DRAM_TIMING_BASE);
+
 	plat_gic_driver_init();
 	plat_gic_init();
 
diff --git a/plat/imx/imx8m/imx8mm/include/platform_def.h b/plat/imx/imx8m/imx8mm/include/platform_def.h
index ed693b9..84d86b9 100644
--- a/plat/imx/imx8m/imx8mm/include/platform_def.h
+++ b/plat/imx/imx8m/imx8mm/include/platform_def.h
@@ -6,6 +6,7 @@
 
 #include <arch.h>
 #include <common/tbbr/tbbr_img_def.h>
+#include <lib/utils_def.h>
 
 #define PLATFORM_LINKER_FORMAT		"elf64-littleaarch64"
 #define PLATFORM_LINKER_ARCH		aarch64
@@ -85,7 +86,7 @@
 #define IMX_AIPSTZ4			U(0x32df0000)
 
 #define IMX_AIPS_BASE			U(0x30000000)
-#define IMX_AIPS_SIZE			U(0xC00000)
+#define IMX_AIPS_SIZE			U(0x3000000)
 #define IMX_GPV_BASE			U(0x32000000)
 #define IMX_GPV_SIZE			U(0x800000)
 #define IMX_AIPS1_BASE			U(0x30200000)
@@ -105,7 +106,10 @@
 #define IMX_DDRC_BASE			U(0x3d400000)
 #define IMX_DDRPHY_BASE			U(0x3c000000)
 #define IMX_DDR_IPS_BASE		U(0x3d000000)
+#define IMX_DDR_IPS_SIZE		U(0x1800000)
 #define IMX_ROM_BASE			U(0x0)
+#define IMX_VPUMIX_BASE                U(0x38330000)
+#define IMX_VPUMIX_SIZE                U(0x100000)
 
 #define GPV_BASE			U(0x32000000)
 #define GPV_SIZE			U(0x800000)
@@ -140,12 +144,14 @@
 #define GPR_TZASC_EN_LOCK		BIT(16)
 
 #define ANAMIX_MISC_CTL			U(0x124)
+#define DRAM_PLL_CTRL			(IMX_ANAMIX_BASE + 0x50)
 
 #define MAX_CSU_NUM			U(64)
 
 #define OCRAM_S_BASE			U(0x00180000)
 #define OCRAM_S_SIZE			U(0x8000)
 #define OCRAM_S_LIMIT			(OCRAM_S_BASE + OCRAM_S_SIZE)
+#define SAVED_DRAM_TIMING_BASE		OCRAM_S_BASE
 
 #define COUNTER_FREQUENCY		8000000 /* 8MHz */
 
diff --git a/plat/imx/imx8m/imx8mm/platform.mk b/plat/imx/imx8m/imx8mm/platform.mk
index 60fa325..1c6c9f8 100644
--- a/plat/imx/imx8m/imx8mm/platform.mk
+++ b/plat/imx/imx8m/imx8mm/platform.mk
@@ -19,6 +19,12 @@
 
 include lib/libfdt/libfdt.mk
 
+IMX_DRAM_SOURCES	:=	plat/imx/imx8m/ddr/dram.c		\
+				plat/imx/imx8m/ddr/clock.c		\
+				plat/imx/imx8m/ddr/dram_retention.c	\
+				plat/imx/imx8m/ddr/ddr4_dvfs.c		\
+				plat/imx/imx8m/ddr/lpddr4_dvfs.c
+
 IMX_GIC_SOURCES		:=	${GICV3_SOURCES}			\
 				plat/common/plat_gicv3.c		\
 				plat/common/plat_psci_common.c		\
@@ -43,6 +49,7 @@
 				drivers/delay_timer/delay_timer.c		\
 				drivers/delay_timer/generic_delay_timer.c	\
 				${XLAT_TABLES_LIB_SRCS}				\
+				${IMX_DRAM_SOURCES}				\
 				${IMX_GIC_SOURCES}
 
 ifeq (${NEED_BL2},yes)
diff --git a/plat/imx/imx8m/imx8mn/gpc.c b/plat/imx/imx8m/imx8mn/gpc.c
index 37d4226..4e05297 100644
--- a/plat/imx/imx8m/imx8mn/gpc.c
+++ b/plat/imx/imx8m/imx8mn/gpc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2019-2020 NXP
+ * Copyright 2019-2022 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -21,6 +21,124 @@
 
 #define CCGR(x)		(0x4000 + (x) * 0x10)
 
+#define MIPI_PWR_REQ		BIT(0)
+#define OTG1_PWR_REQ		BIT(2)
+#define HSIOMIX_PWR_REQ		BIT(4)
+#define GPUMIX_PWR_REQ		BIT(7)
+#define DISPMIX_PWR_REQ		BIT(10)
+
+#define HSIOMIX_ADB400_SYNC	BIT(5)
+#define DISPMIX_ADB400_SYNC	BIT(7)
+#define GPUMIX_ADB400_SYNC	(0x5 << 9)
+#define HSIOMIX_ADB400_ACK	BIT(23)
+#define DISPMIX_ADB400_ACK	BIT(25)
+#define GPUMIX_ADB400_ACK	(0x5 << 27)
+
+#define MIPI_PGC		0xc00
+#define OTG1_PGC		0xc80
+#define HSIOMIX_PGC	        0xd00
+#define GPUMIX_PGC		0xdc0
+#define DISPMIX_PGC		0xe80
+
+enum pu_domain_id {
+	HSIOMIX,
+	OTG1 = 2,
+	GPUMIX = 4,
+	DISPMIX = 9,
+	MIPI,
+};
+
+/* PU domain, add some hole to minimize the uboot change */
+static struct imx_pwr_domain pu_domains[11] = {
+	[HSIOMIX] = IMX_MIX_DOMAIN(HSIOMIX, false),
+	[OTG1] = IMX_PD_DOMAIN(OTG1, true),
+	[GPUMIX] = IMX_MIX_DOMAIN(GPUMIX, false),
+	[DISPMIX] = IMX_MIX_DOMAIN(DISPMIX, false),
+	[MIPI] = IMX_PD_DOMAIN(MIPI, true),
+};
+
+static unsigned int pu_domain_status;
+
+void imx_gpc_pm_domain_enable(uint32_t domain_id, bool on)
+{
+	if (domain_id > MIPI) {
+		return;
+	}
+
+	struct imx_pwr_domain *pwr_domain = &pu_domains[domain_id];
+
+	if (on) {
+		if (pwr_domain->need_sync) {
+			pu_domain_status |= (1 << domain_id);
+		}
+
+		/* HSIOMIX has no PU bit, so skip for it */
+		if (domain_id != HSIOMIX) {
+			/* clear the PGC bit */
+			mmio_clrbits_32(IMX_GPC_BASE + pwr_domain->pgc_offset, 0x1);
+
+			/* power up the domain */
+			mmio_setbits_32(IMX_GPC_BASE + PU_PGC_UP_TRG, pwr_domain->pwr_req);
+
+			/* wait for power request done */
+			while (mmio_read_32(IMX_GPC_BASE + PU_PGC_UP_TRG) & pwr_domain->pwr_req) {
+				;
+			}
+		}
+
+		if (domain_id == DISPMIX) {
+			/* de-reset bus_blk clk and
+			 * enable bus_blk clk
+			 */
+			mmio_write_32(0x32e28000, 0x100);
+			mmio_write_32(0x32e28004, 0x100);
+		}
+
+		/* handle the ADB400 sync */
+		if (pwr_domain->need_sync) {
+			/* clear adb power down request */
+			mmio_setbits_32(IMX_GPC_BASE + GPC_PU_PWRHSK, pwr_domain->adb400_sync);
+
+			/* wait for adb power request ack */
+			while (!(mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & pwr_domain->adb400_ack)) {
+				;
+			}
+		}
+	} else {
+		pu_domain_status &= ~(1 << domain_id);
+
+		if (domain_id == OTG1) {
+			return;
+		}
+
+		/* handle the ADB400 sync */
+		if (pwr_domain->need_sync) {
+
+			/* set adb power down request */
+			mmio_clrbits_32(IMX_GPC_BASE + GPC_PU_PWRHSK, pwr_domain->adb400_sync);
+
+			/* wait for adb power request ack */
+			while ((mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & pwr_domain->adb400_ack)) {
+				;
+			}
+		}
+
+		/* HSIOMIX has no PU bit, so skip for it */
+		if (domain_id != HSIOMIX) {
+			/* set the PGC bit */
+			mmio_setbits_32(IMX_GPC_BASE + pwr_domain->pgc_offset, 0x1);
+
+			/* power down the domain */
+			mmio_setbits_32(IMX_GPC_BASE + PU_PGC_DN_TRG, pwr_domain->pwr_req);
+
+			/* wait for power request done */
+			while (mmio_read_32(IMX_GPC_BASE + PU_PGC_DN_TRG) & pwr_domain->pwr_req) {
+				;
+			}
+		}
+	}
+}
+
 void imx_gpc_init(void)
 {
 	unsigned int val;
@@ -86,9 +204,4 @@
 	 * only need to do it once.
 	 */
 	mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG1PHY_SCR, 0x1);
-
-	/* enable all the power domain by default */
-	for (i = 0; i < 103; i++)
-		mmio_write_32(IMX_CCM_BASE + CCGR(i), 0x3);
-	mmio_write_32(IMX_GPC_BASE + PU_PGC_UP_TRG, 0x485);
 }
diff --git a/plat/imx/imx8m/imx8mn/imx8mn_bl31_setup.c b/plat/imx/imx8m/imx8mn/imx8mn_bl31_setup.c
index 8147792..5d2a64e 100644
--- a/plat/imx/imx8m/imx8mn/imx8mn_bl31_setup.c
+++ b/plat/imx/imx8m/imx8mn/imx8mn_bl31_setup.c
@@ -19,6 +19,7 @@
 #include <lib/xlat_tables/xlat_tables_v2.h>
 #include <plat/common/platform.h>
 
+#include <dram.h>
 #include <gpc.h>
 #include <imx_aipstz.h>
 #include <imx_uart.h>
@@ -207,6 +208,9 @@
 	/* select the CKIL source to 32K OSC */
 	mmio_write_32(IMX_ANAMIX_BASE + ANAMIX_MISC_CTL, 0x1);
 
+	/* Init the dram info */
+	dram_info_init(SAVED_DRAM_TIMING_BASE);
+
 	plat_gic_driver_init();
 	plat_gic_init();
 
diff --git a/plat/imx/imx8m/imx8mn/include/platform_def.h b/plat/imx/imx8m/imx8mn/include/platform_def.h
index 8d39ea6..dbb4416 100644
--- a/plat/imx/imx8m/imx8mn/include/platform_def.h
+++ b/plat/imx/imx8m/imx8mn/include/platform_def.h
@@ -9,6 +9,8 @@
 #include <lib/utils_def.h>
 #include <lib/xlat_tables/xlat_tables_v2.h>
 
+#include <lib/utils_def.h>
+
 #define PLATFORM_LINKER_FORMAT		"elf64-littleaarch64"
 #define PLATFORM_LINKER_ARCH		aarch64
 
@@ -70,7 +72,7 @@
 #define IMX_AIPSTZ4			U(0x32df0000)
 
 #define IMX_AIPS_BASE			U(0x30000000)
-#define IMX_AIPS_SIZE			U(0xC00000)
+#define IMX_AIPS_SIZE			U(0x3000000)
 #define IMX_GPV_BASE			U(0x32000000)
 #define IMX_GPV_SIZE			U(0x800000)
 #define IMX_AIPS1_BASE			U(0x30200000)
diff --git a/plat/imx/imx8m/imx8mn/platform.mk b/plat/imx/imx8m/imx8mn/platform.mk
index 54be41b..0f3ad1a 100644
--- a/plat/imx/imx8m/imx8mn/platform.mk
+++ b/plat/imx/imx8m/imx8mn/platform.mk
@@ -13,6 +13,13 @@
 # Include GICv3 driver files
 include drivers/arm/gic/v3/gicv3.mk
 
+IMX_DRAM_SOURCES	:=	plat/imx/imx8m/ddr/dram.c		\
+				plat/imx/imx8m/ddr/clock.c		\
+				plat/imx/imx8m/ddr/dram_retention.c	\
+				plat/imx/imx8m/ddr/ddr4_dvfs.c		\
+				plat/imx/imx8m/ddr/lpddr4_dvfs.c
+
+
 IMX_GIC_SOURCES		:=	${GICV3_SOURCES}			\
 				plat/common/plat_gicv3.c		\
 				plat/common/plat_psci_common.c		\
@@ -36,6 +43,7 @@
 				drivers/arm/tzc/tzc380.c			\
 				drivers/delay_timer/delay_timer.c		\
 				drivers/delay_timer/generic_delay_timer.c	\
+				${IMX_DRAM_SOURCES}				\
 				${IMX_GIC_SOURCES}				\
 				${XLAT_TABLES_LIB_SRCS}
 
diff --git a/plat/imx/imx8m/imx8mp/gpc.c b/plat/imx/imx8m/imx8mp/gpc.c
index 3d68b94..452e788 100644
--- a/plat/imx/imx8m/imx8mp/gpc.c
+++ b/plat/imx/imx8m/imx8mp/gpc.c
@@ -170,7 +170,7 @@
 	}
 }
 
-static void imx_gpc_pm_domain_enable(uint32_t domain_id, bool on)
+void imx_gpc_pm_domain_enable(uint32_t domain_id, bool on)
 {
 	struct imx_pwr_domain *pwr_domain = &pu_domains[domain_id];
 	unsigned int i;
diff --git a/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c b/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c
index 57e5c51..d443c3d 100644
--- a/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c
+++ b/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c
@@ -19,6 +19,7 @@
 #include <lib/xlat_tables/xlat_tables_v2.h>
 #include <plat/common/platform.h>
 
+#include <dram.h>
 #include <gpc.h>
 #include <imx_aipstz.h>
 #include <imx_uart.h>
@@ -203,6 +204,9 @@
 	/* select the CKIL source to 32K OSC */
 	mmio_write_32(IMX_ANAMIX_BASE + ANAMIX_MISC_CTL, 0x1);
 
+	/* Init the dram info */
+	dram_info_init(SAVED_DRAM_TIMING_BASE);
+
 	plat_gic_driver_init();
 	plat_gic_init();
 
diff --git a/plat/imx/imx8m/imx8mp/platform.mk b/plat/imx/imx8m/imx8mp/platform.mk
index 73fbd87..45f2972 100644
--- a/plat/imx/imx8m/imx8mp/platform.mk
+++ b/plat/imx/imx8m/imx8mp/platform.mk
@@ -15,6 +15,12 @@
 # Include GICv3 driver files
 include drivers/arm/gic/v3/gicv3.mk
 
+IMX_DRAM_SOURCES	:=	plat/imx/imx8m/ddr/dram.c		\
+				plat/imx/imx8m/ddr/clock.c		\
+				plat/imx/imx8m/ddr/dram_retention.c	\
+				plat/imx/imx8m/ddr/ddr4_dvfs.c		\
+				plat/imx/imx8m/ddr/lpddr4_dvfs.c
+
 IMX_GIC_SOURCES		:=	${GICV3_SOURCES}			\
 				plat/common/plat_gicv3.c		\
 				plat/common/plat_psci_common.c		\
@@ -38,6 +44,7 @@
 				drivers/arm/tzc/tzc380.c			\
 				drivers/delay_timer/delay_timer.c		\
 				drivers/delay_timer/generic_delay_timer.c	\
+				${IMX_DRAM_SOURCES}				\
 				${IMX_GIC_SOURCES}				\
 				${XLAT_TABLES_LIB_SRCS}
 
diff --git a/plat/imx/imx8m/include/ddrc.h b/plat/imx/imx8m/include/ddrc.h
new file mode 100644
index 0000000..55af3ff
--- /dev/null
+++ b/plat/imx/imx8m/include/ddrc.h
@@ -0,0 +1,336 @@
+/*
+ * Copyright 2019-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IMX_DDRC_H
+#define IMX_DDRC_H
+
+#define DDRC_IPS_BASE_ADDR(X)	(0x3d400000 + ((X) * 0x2000000))
+#define DDRC_DDR_SS_GPR0        0x3d000000
+
+/* DWC ddr umctl2 REGs offset*/
+/**********************/
+#define DDRC_MSTR(X)             (DDRC_IPS_BASE_ADDR(X) + 0x00)
+#define DDRC_STAT(X)             (DDRC_IPS_BASE_ADDR(X) + 0x04)
+#define DDRC_MSTR1(X)            (DDRC_IPS_BASE_ADDR(X) + 0x08)
+#define DDRC_MRCTRL0(X)          (DDRC_IPS_BASE_ADDR(X) + 0x10)
+#define DDRC_MRCTRL1(X)          (DDRC_IPS_BASE_ADDR(X) + 0x14)
+#define DDRC_MRSTAT(X)           (DDRC_IPS_BASE_ADDR(X) + 0x18)
+#define DDRC_MRCTRL2(X)          (DDRC_IPS_BASE_ADDR(X) + 0x1c)
+#define DDRC_DERATEEN(X)         (DDRC_IPS_BASE_ADDR(X) + 0x20)
+#define DDRC_DERATEINT(X)        (DDRC_IPS_BASE_ADDR(X) + 0x24)
+#define DDRC_MSTR2(X)            (DDRC_IPS_BASE_ADDR(X) + 0x28)
+#define DDRC_PWRCTL(X)           (DDRC_IPS_BASE_ADDR(X) + 0x30)
+#define DDRC_PWRTMG(X)           (DDRC_IPS_BASE_ADDR(X) + 0x34)
+#define DDRC_HWLPCTL(X)          (DDRC_IPS_BASE_ADDR(X) + 0x38)
+#define DDRC_HWFFCCTL(X)         (DDRC_IPS_BASE_ADDR(X) + 0x3c)
+#define DDRC_HWFFCSTAT(X)        (DDRC_IPS_BASE_ADDR(X) + 0x40)
+#define DDRC_RFSHCTL0(X)         (DDRC_IPS_BASE_ADDR(X) + 0x50)
+#define DDRC_RFSHCTL1(X)         (DDRC_IPS_BASE_ADDR(X) + 0x54)
+#define DDRC_RFSHCTL2(X)         (DDRC_IPS_BASE_ADDR(X) + 0x58)
+#define DDRC_RFSHCTL3(X)         (DDRC_IPS_BASE_ADDR(X) + 0x60)
+#define DDRC_RFSHTMG(X)          (DDRC_IPS_BASE_ADDR(X) + 0x64)
+#define DDRC_ECCCFG0(X)          (DDRC_IPS_BASE_ADDR(X) + 0x70)
+#define DDRC_ECCCFG1(X)          (DDRC_IPS_BASE_ADDR(X) + 0x74)
+#define DDRC_ECCSTAT(X)          (DDRC_IPS_BASE_ADDR(X) + 0x78)
+#define DDRC_ECCCLR(X)           (DDRC_IPS_BASE_ADDR(X) + 0x7c)
+#define DDRC_ECCERRCNT(X)        (DDRC_IPS_BASE_ADDR(X) + 0x80)
+#define DDRC_ECCCADDR0(X)        (DDRC_IPS_BASE_ADDR(X) + 0x84)
+#define DDRC_ECCCADDR1(X)        (DDRC_IPS_BASE_ADDR(X) + 0x88)
+#define DDRC_ECCCSYN0(X)         (DDRC_IPS_BASE_ADDR(X) + 0x8c)
+#define DDRC_ECCCSYN1(X)         (DDRC_IPS_BASE_ADDR(X) + 0x90)
+#define DDRC_ECCCSYN2(X)         (DDRC_IPS_BASE_ADDR(X) + 0x94)
+#define DDRC_ECCBITMASK0(X)      (DDRC_IPS_BASE_ADDR(X) + 0x98)
+#define DDRC_ECCBITMASK1(X)      (DDRC_IPS_BASE_ADDR(X) + 0x9c)
+#define DDRC_ECCBITMASK2(X)      (DDRC_IPS_BASE_ADDR(X) + 0xa0)
+#define DDRC_ECCUADDR0(X)        (DDRC_IPS_BASE_ADDR(X) + 0xa4)
+#define DDRC_ECCUADDR1(X)        (DDRC_IPS_BASE_ADDR(X) + 0xa8)
+#define DDRC_ECCUSYN0(X)         (DDRC_IPS_BASE_ADDR(X) + 0xac)
+#define DDRC_ECCUSYN1(X)         (DDRC_IPS_BASE_ADDR(X) + 0xb0)
+#define DDRC_ECCUSYN2(X)         (DDRC_IPS_BASE_ADDR(X) + 0xb4)
+#define DDRC_ECCPOISONADDR0(X)   (DDRC_IPS_BASE_ADDR(X) + 0xb8)
+#define DDRC_ECCPOISONADDR1(X)   (DDRC_IPS_BASE_ADDR(X) + 0xbc)
+#define DDRC_CRCPARCTL0(X)       (DDRC_IPS_BASE_ADDR(X) + 0xc0)
+#define DDRC_CRCPARCTL1(X)       (DDRC_IPS_BASE_ADDR(X) + 0xc4)
+#define DDRC_CRCPARCTL2(X)       (DDRC_IPS_BASE_ADDR(X) + 0xc8)
+#define DDRC_CRCPARSTAT(X)       (DDRC_IPS_BASE_ADDR(X) + 0xcc)
+#define DDRC_INIT0(X)            (DDRC_IPS_BASE_ADDR(X) + 0xd0)
+#define DDRC_INIT1(X)            (DDRC_IPS_BASE_ADDR(X) + 0xd4)
+#define DDRC_INIT2(X)            (DDRC_IPS_BASE_ADDR(X) + 0xd8)
+#define DDRC_INIT3(X)            (DDRC_IPS_BASE_ADDR(X) + 0xdc)
+#define DDRC_INIT4(X)            (DDRC_IPS_BASE_ADDR(X) + 0xe0)
+#define DDRC_INIT5(X)            (DDRC_IPS_BASE_ADDR(X) + 0xe4)
+#define DDRC_INIT6(X)            (DDRC_IPS_BASE_ADDR(X) + 0xe8)
+#define DDRC_INIT7(X)            (DDRC_IPS_BASE_ADDR(X) + 0xec)
+#define DDRC_DIMMCTL(X)          (DDRC_IPS_BASE_ADDR(X) + 0xf0)
+#define DDRC_RANKCTL(X)          (DDRC_IPS_BASE_ADDR(X) + 0xf4)
+#define DDRC_DRAMTMG0(X)         (DDRC_IPS_BASE_ADDR(X) + 0x100)
+#define DDRC_DRAMTMG1(X)         (DDRC_IPS_BASE_ADDR(X) + 0x104)
+#define DDRC_DRAMTMG2(X)         (DDRC_IPS_BASE_ADDR(X) + 0x108)
+#define DDRC_DRAMTMG3(X)         (DDRC_IPS_BASE_ADDR(X) + 0x10c)
+#define DDRC_DRAMTMG4(X)         (DDRC_IPS_BASE_ADDR(X) + 0x110)
+#define DDRC_DRAMTMG5(X)         (DDRC_IPS_BASE_ADDR(X) + 0x114)
+#define DDRC_DRAMTMG6(X)         (DDRC_IPS_BASE_ADDR(X) + 0x118)
+#define DDRC_DRAMTMG7(X)         (DDRC_IPS_BASE_ADDR(X) + 0x11c)
+#define DDRC_DRAMTMG8(X)         (DDRC_IPS_BASE_ADDR(X) + 0x120)
+#define DDRC_DRAMTMG9(X)         (DDRC_IPS_BASE_ADDR(X) + 0x124)
+#define DDRC_DRAMTMG10(X)        (DDRC_IPS_BASE_ADDR(X) + 0x128)
+#define DDRC_DRAMTMG11(X)        (DDRC_IPS_BASE_ADDR(X) + 0x12c)
+#define DDRC_DRAMTMG12(X)        (DDRC_IPS_BASE_ADDR(X) + 0x130)
+#define DDRC_DRAMTMG13(X)        (DDRC_IPS_BASE_ADDR(X) + 0x134)
+#define DDRC_DRAMTMG14(X)        (DDRC_IPS_BASE_ADDR(X) + 0x138)
+#define DDRC_DRAMTMG15(X)        (DDRC_IPS_BASE_ADDR(X) + 0x13C)
+#define DDRC_DRAMTMG16(X)        (DDRC_IPS_BASE_ADDR(X) + 0x140)
+#define DDRC_DRAMTMG17(X)        (DDRC_IPS_BASE_ADDR(X) + 0x144)
+
+#define DDRC_ZQCTL0(X)           (DDRC_IPS_BASE_ADDR(X) + 0x180)
+#define DDRC_ZQCTL1(X)           (DDRC_IPS_BASE_ADDR(X) + 0x184)
+#define DDRC_ZQCTL2(X)           (DDRC_IPS_BASE_ADDR(X) + 0x188)
+#define DDRC_ZQSTAT(X)           (DDRC_IPS_BASE_ADDR(X) + 0x18c)
+#define DDRC_DFITMG0(X)          (DDRC_IPS_BASE_ADDR(X) + 0x190)
+#define DDRC_DFITMG1(X)          (DDRC_IPS_BASE_ADDR(X) + 0x194)
+#define DDRC_DFILPCFG0(X)        (DDRC_IPS_BASE_ADDR(X) + 0x198)
+#define DDRC_DFILPCFG1(X)        (DDRC_IPS_BASE_ADDR(X) + 0x19c)
+#define DDRC_DFIUPD0(X)          (DDRC_IPS_BASE_ADDR(X) + 0x1a0)
+#define DDRC_DFIUPD1(X)          (DDRC_IPS_BASE_ADDR(X) + 0x1a4)
+#define DDRC_DFIUPD2(X)          (DDRC_IPS_BASE_ADDR(X) + 0x1a8)
+#define DDRC_DFIMISC(X)          (DDRC_IPS_BASE_ADDR(X) + 0x1b0)
+#define DDRC_DFITMG2(X)          (DDRC_IPS_BASE_ADDR(X) + 0x1b4)
+#define DDRC_DFITMG3(X)          (DDRC_IPS_BASE_ADDR(X) + 0x1b8)
+#define DDRC_DFISTAT(X)          (DDRC_IPS_BASE_ADDR(X) + 0x1bc)
+
+#define DDRC_DBICTL(X)           (DDRC_IPS_BASE_ADDR(X) + 0x1c0)
+#define DDRC_DFIPHYMSTR(X)       (DDRC_IPS_BASE_ADDR(X) + 0x1c4)
+#define DDRC_TRAINCTL0(X)        (DDRC_IPS_BASE_ADDR(X) + 0x1d0)
+#define DDRC_TRAINCTL1(X)        (DDRC_IPS_BASE_ADDR(X) + 0x1d4)
+#define DDRC_TRAINCTL2(X)        (DDRC_IPS_BASE_ADDR(X) + 0x1d8)
+#define DDRC_TRAINSTAT(X)        (DDRC_IPS_BASE_ADDR(X) + 0x1dc)
+#define DDRC_ADDRMAP0(X)         (DDRC_IPS_BASE_ADDR(X) + 0x200)
+#define DDRC_ADDRMAP1(X)         (DDRC_IPS_BASE_ADDR(X) + 0x204)
+#define DDRC_ADDRMAP2(X)         (DDRC_IPS_BASE_ADDR(X) + 0x208)
+#define DDRC_ADDRMAP3(X)         (DDRC_IPS_BASE_ADDR(X) + 0x20c)
+#define DDRC_ADDRMAP4(X)         (DDRC_IPS_BASE_ADDR(X) + 0x210)
+#define DDRC_ADDRMAP5(X)         (DDRC_IPS_BASE_ADDR(X) + 0x214)
+#define DDRC_ADDRMAP6(X)         (DDRC_IPS_BASE_ADDR(X) + 0x218)
+#define DDRC_ADDRMAP7(X)         (DDRC_IPS_BASE_ADDR(X) + 0x21c)
+#define DDRC_ADDRMAP8(X)         (DDRC_IPS_BASE_ADDR(X) + 0x220)
+#define DDRC_ADDRMAP9(X)         (DDRC_IPS_BASE_ADDR(X) + 0x224)
+#define DDRC_ADDRMAP10(X)        (DDRC_IPS_BASE_ADDR(X) + 0x228)
+#define DDRC_ADDRMAP11(X)        (DDRC_IPS_BASE_ADDR(X) + 0x22c)
+
+#define DDRC_ODTCFG(X)           (DDRC_IPS_BASE_ADDR(X) + 0x240)
+#define DDRC_ODTMAP(X)           (DDRC_IPS_BASE_ADDR(X) + 0x244)
+#define DDRC_SCHED(X)            (DDRC_IPS_BASE_ADDR(X) + 0x250)
+#define DDRC_SCHED1(X)           (DDRC_IPS_BASE_ADDR(X) + 0x254)
+#define DDRC_PERFHPR1(X)         (DDRC_IPS_BASE_ADDR(X) + 0x25c)
+#define DDRC_PERFLPR1(X)         (DDRC_IPS_BASE_ADDR(X) + 0x264)
+#define DDRC_PERFWR1(X)          (DDRC_IPS_BASE_ADDR(X) + 0x26c)
+#define DDRC_PERFVPR1(X)         (DDRC_IPS_BASE_ADDR(X) + 0x274)
+
+#define DDRC_PERFVPW1(X)         (DDRC_IPS_BASE_ADDR(X) + 0x278)
+
+#define DDRC_DQMAP0(X)           (DDRC_IPS_BASE_ADDR(X) + 0x280)
+#define DDRC_DQMAP1(X)           (DDRC_IPS_BASE_ADDR(X) + 0x284)
+#define DDRC_DQMAP2(X)           (DDRC_IPS_BASE_ADDR(X) + 0x288)
+#define DDRC_DQMAP3(X)           (DDRC_IPS_BASE_ADDR(X) + 0x28c)
+#define DDRC_DQMAP4(X)           (DDRC_IPS_BASE_ADDR(X) + 0x290)
+#define DDRC_DQMAP5(X)           (DDRC_IPS_BASE_ADDR(X) + 0x294)
+#define DDRC_DBG0(X)             (DDRC_IPS_BASE_ADDR(X) + 0x300)
+#define DDRC_DBG1(X)             (DDRC_IPS_BASE_ADDR(X) + 0x304)
+#define DDRC_DBGCAM(X)           (DDRC_IPS_BASE_ADDR(X) + 0x308)
+#define DDRC_DBGCMD(X)           (DDRC_IPS_BASE_ADDR(X) + 0x30c)
+#define DDRC_DBGSTAT(X)          (DDRC_IPS_BASE_ADDR(X) + 0x310)
+
+#define DDRC_SWCTL(X)            (DDRC_IPS_BASE_ADDR(X) + 0x320)
+#define DDRC_SWSTAT(X)           (DDRC_IPS_BASE_ADDR(X) + 0x324)
+#define DDRC_OCPARCFG0(X)        (DDRC_IPS_BASE_ADDR(X) + 0x330)
+#define DDRC_OCPARCFG1(X)        (DDRC_IPS_BASE_ADDR(X) + 0x334)
+#define DDRC_OCPARCFG2(X)        (DDRC_IPS_BASE_ADDR(X) + 0x338)
+#define DDRC_OCPARCFG3(X)        (DDRC_IPS_BASE_ADDR(X) + 0x33c)
+#define DDRC_OCPARSTAT0(X)       (DDRC_IPS_BASE_ADDR(X) + 0x340)
+#define DDRC_OCPARSTAT1(X)       (DDRC_IPS_BASE_ADDR(X) + 0x344)
+#define DDRC_OCPARWLOG0(X)       (DDRC_IPS_BASE_ADDR(X) + 0x348)
+#define DDRC_OCPARWLOG1(X)       (DDRC_IPS_BASE_ADDR(X) + 0x34c)
+#define DDRC_OCPARWLOG2(X)       (DDRC_IPS_BASE_ADDR(X) + 0x350)
+#define DDRC_OCPARAWLOG0(X)      (DDRC_IPS_BASE_ADDR(X) + 0x354)
+#define DDRC_OCPARAWLOG1(X)      (DDRC_IPS_BASE_ADDR(X) + 0x358)
+#define DDRC_OCPARRLOG0(X)       (DDRC_IPS_BASE_ADDR(X) + 0x35c)
+#define DDRC_OCPARRLOG1(X)       (DDRC_IPS_BASE_ADDR(X) + 0x360)
+#define DDRC_OCPARARLOG0(X)      (DDRC_IPS_BASE_ADDR(X) + 0x364)
+#define DDRC_OCPARARLOG1(X)      (DDRC_IPS_BASE_ADDR(X) + 0x368)
+#define DDRC_POISONCFG(X)        (DDRC_IPS_BASE_ADDR(X) + 0x36C)
+#define DDRC_POISONSTAT(X)       (DDRC_IPS_BASE_ADDR(X) + 0x370)
+#define DDRC_ADVECCINDEX(X)      (DDRC_IPS_BASE_ADDR(X) + 0x3)
+#define DDRC_ADVECCSTAT(X)       (DDRC_IPS_BASE_ADDR(X) + 0x3)
+#define DDRC_ECCPOISONPAT0(X)    (DDRC_IPS_BASE_ADDR(X) + 0x3)
+#define DDRC_ECCPOISONPAT1(X)    (DDRC_IPS_BASE_ADDR(X) + 0x3)
+#define DDRC_ECCPOISONPAT2(X)    (DDRC_IPS_BASE_ADDR(X) + 0x3)
+#define DDRC_HIFCTL(X)           (DDRC_IPS_BASE_ADDR(X) + 0x3)
+
+#define DDRC_PSTAT(X)            (DDRC_IPS_BASE_ADDR(X) + 0x3fc)
+#define DDRC_PCCFG(X)            (DDRC_IPS_BASE_ADDR(X) + 0x400)
+#define DDRC_PCFGR_0(X)          (DDRC_IPS_BASE_ADDR(X) + 0x404)
+#define DDRC_PCFGR_1(X)          (DDRC_IPS_BASE_ADDR(X) + 1 * 0xb0 + 0x404)
+#define DDRC_PCFGR_2(X)          (DDRC_IPS_BASE_ADDR(X) + 2 * 0xb0 + 0x404)
+#define DDRC_PCFGR_3(X)          (DDRC_IPS_BASE_ADDR(X) + 3 * 0xb0 + 0x404)
+#define DDRC_PCFGW_0(X)          (DDRC_IPS_BASE_ADDR(X) + 0x408)
+#define DDRC_PCFGW_1(X)          (DDRC_IPS_BASE_ADDR(X) + 1 * 0xb0 + 0x408)
+#define DDRC_PCFGW_2(X)          (DDRC_IPS_BASE_ADDR(X) + 2 * 0xb0 + 0x408)
+#define DDRC_PCFGW_3(X)          (DDRC_IPS_BASE_ADDR(X) + 3 * 0xb0 + 0x408)
+#define DDRC_PCFGC_0(X)          (DDRC_IPS_BASE_ADDR(X) + 0x40c)
+#define DDRC_PCFGIDMASKCH(X)     (DDRC_IPS_BASE_ADDR(X) + 0x410)
+#define DDRC_PCFGIDVALUECH(X)    (DDRC_IPS_BASE_ADDR(X) + 0x414)
+#define DDRC_PCTRL_0(X)          (DDRC_IPS_BASE_ADDR(X) + 0x490)
+#define DDRC_PCTRL_1(X)          (DDRC_IPS_BASE_ADDR(X) + 0x490 + 1 * 0xb0)
+#define DDRC_PCTRL_2(X)          (DDRC_IPS_BASE_ADDR(X) + 0x490 + 2 * 0xb0)
+#define DDRC_PCTRL_3(X)          (DDRC_IPS_BASE_ADDR(X) + 0x490 + 3 * 0xb0)
+#define DDRC_PCFGQOS0_0(X)       (DDRC_IPS_BASE_ADDR(X) + 0x494)
+#define DDRC_PCFGQOS1_0(X)       (DDRC_IPS_BASE_ADDR(X) + 0x498)
+#define DDRC_PCFGWQOS0_0(X)      (DDRC_IPS_BASE_ADDR(X) + 0x49c)
+#define DDRC_PCFGWQOS1_0(X)      (DDRC_IPS_BASE_ADDR(X) + 0x4a0)
+#define DDRC_SARBASE0(X)         (DDRC_IPS_BASE_ADDR(X) + 0xf04)
+#define DDRC_SARSIZE0(X)         (DDRC_IPS_BASE_ADDR(X) + 0xf08)
+#define DDRC_SBRCTL(X)           (DDRC_IPS_BASE_ADDR(X) + 0xf24)
+#define DDRC_SBRSTAT(X)          (DDRC_IPS_BASE_ADDR(X) + 0xf28)
+#define DDRC_SBRWDATA0(X)        (DDRC_IPS_BASE_ADDR(X) + 0xf2c)
+#define DDRC_SBRWDATA1(X)        (DDRC_IPS_BASE_ADDR(X) + 0xf30)
+#define DDRC_PDCH(X)             (DDRC_IPS_BASE_ADDR(X) + 0xf34)
+
+/* SHADOW registers */
+#define DDRC_FREQ1_DERATEEN(X)         (DDRC_IPS_BASE_ADDR(X) + 0x2020)
+#define DDRC_FREQ1_DERATEINT(X)        (DDRC_IPS_BASE_ADDR(X) + 0x2024)
+#define DDRC_FREQ1_RFSHCTL0(X)         (DDRC_IPS_BASE_ADDR(X) + 0x2050)
+#define DDRC_FREQ1_RFSHTMG(X)          (DDRC_IPS_BASE_ADDR(X) + 0x2064)
+#define DDRC_FREQ1_INIT3(X)            (DDRC_IPS_BASE_ADDR(X) + 0x20dc)
+#define DDRC_FREQ1_INIT4(X)            (DDRC_IPS_BASE_ADDR(X) + 0x20e0)
+#define DDRC_FREQ1_INIT6(X)            (DDRC_IPS_BASE_ADDR(X) + 0x20e8)
+#define DDRC_FREQ1_INIT7(X)            (DDRC_IPS_BASE_ADDR(X) + 0x20ec)
+#define DDRC_FREQ1_DRAMTMG0(X)         (DDRC_IPS_BASE_ADDR(X) + 0x2100)
+#define DDRC_FREQ1_DRAMTMG1(X)         (DDRC_IPS_BASE_ADDR(X) + 0x2104)
+#define DDRC_FREQ1_DRAMTMG2(X)         (DDRC_IPS_BASE_ADDR(X) + 0x2108)
+#define DDRC_FREQ1_DRAMTMG3(X)         (DDRC_IPS_BASE_ADDR(X) + 0x210c)
+#define DDRC_FREQ1_DRAMTMG4(X)         (DDRC_IPS_BASE_ADDR(X) + 0x2110)
+#define DDRC_FREQ1_DRAMTMG5(X)         (DDRC_IPS_BASE_ADDR(X) + 0x2114)
+#define DDRC_FREQ1_DRAMTMG6(X)         (DDRC_IPS_BASE_ADDR(X) + 0x2118)
+#define DDRC_FREQ1_DRAMTMG7(X)         (DDRC_IPS_BASE_ADDR(X) + 0x211c)
+#define DDRC_FREQ1_DRAMTMG8(X)         (DDRC_IPS_BASE_ADDR(X) + 0x2120)
+#define DDRC_FREQ1_DRAMTMG9(X)         (DDRC_IPS_BASE_ADDR(X) + 0x2124)
+#define DDRC_FREQ1_DRAMTMG10(X)        (DDRC_IPS_BASE_ADDR(X) + 0x2128)
+#define DDRC_FREQ1_DRAMTMG11(X)        (DDRC_IPS_BASE_ADDR(X) + 0x212c)
+#define DDRC_FREQ1_DRAMTMG12(X)        (DDRC_IPS_BASE_ADDR(X) + 0x2130)
+#define DDRC_FREQ1_DRAMTMG13(X)        (DDRC_IPS_BASE_ADDR(X) + 0x2134)
+#define DDRC_FREQ1_DRAMTMG14(X)        (DDRC_IPS_BASE_ADDR(X) + 0x2138)
+#define DDRC_FREQ1_DRAMTMG15(X)        (DDRC_IPS_BASE_ADDR(X) + 0x213C)
+#define DDRC_FREQ1_DRAMTMG16(X)        (DDRC_IPS_BASE_ADDR(X) + 0x2140)
+#define DDRC_FREQ1_DRAMTMG17(X)        (DDRC_IPS_BASE_ADDR(X) + 0x2144)
+#define DDRC_FREQ1_ZQCTL0(X)           (DDRC_IPS_BASE_ADDR(X) + 0x2180)
+#define DDRC_FREQ1_DFITMG0(X)          (DDRC_IPS_BASE_ADDR(X) + 0x2190)
+#define DDRC_FREQ1_DFITMG1(X)          (DDRC_IPS_BASE_ADDR(X) + 0x2194)
+#define DDRC_FREQ1_DFITMG2(X)          (DDRC_IPS_BASE_ADDR(X) + 0x21b4)
+#define DDRC_FREQ1_DFITMG3(X)          (DDRC_IPS_BASE_ADDR(X) + 0x21b8)
+#define DDRC_FREQ1_ODTCFG(X)           (DDRC_IPS_BASE_ADDR(X) + 0x2240)
+
+#define DDRC_FREQ2_DERATEEN(X)         (DDRC_IPS_BASE_ADDR(X) + 0x3020)
+#define DDRC_FREQ2_DERATEINT(X)        (DDRC_IPS_BASE_ADDR(X) + 0x3024)
+#define DDRC_FREQ2_RFSHCTL0(X)         (DDRC_IPS_BASE_ADDR(X) + 0x3050)
+#define DDRC_FREQ2_RFSHTMG(X)          (DDRC_IPS_BASE_ADDR(X) + 0x3064)
+#define DDRC_FREQ2_INIT3(X)            (DDRC_IPS_BASE_ADDR(X) + 0x30dc)
+#define DDRC_FREQ2_INIT4(X)            (DDRC_IPS_BASE_ADDR(X) + 0x30e0)
+#define DDRC_FREQ2_INIT6(X)            (DDRC_IPS_BASE_ADDR(X) + 0x30e8)
+#define DDRC_FREQ2_INIT7(X)            (DDRC_IPS_BASE_ADDR(X) + 0x30ec)
+#define DDRC_FREQ2_DRAMTMG0(X)         (DDRC_IPS_BASE_ADDR(X) + 0x3100)
+#define DDRC_FREQ2_DRAMTMG1(X)         (DDRC_IPS_BASE_ADDR(X) + 0x3104)
+#define DDRC_FREQ2_DRAMTMG2(X)         (DDRC_IPS_BASE_ADDR(X) + 0x3108)
+#define DDRC_FREQ2_DRAMTMG3(X)         (DDRC_IPS_BASE_ADDR(X) + 0x310c)
+#define DDRC_FREQ2_DRAMTMG4(X)         (DDRC_IPS_BASE_ADDR(X) + 0x3110)
+#define DDRC_FREQ2_DRAMTMG5(X)         (DDRC_IPS_BASE_ADDR(X) + 0x3114)
+#define DDRC_FREQ2_DRAMTMG6(X)         (DDRC_IPS_BASE_ADDR(X) + 0x3118)
+#define DDRC_FREQ2_DRAMTMG7(X)         (DDRC_IPS_BASE_ADDR(X) + 0x311c)
+#define DDRC_FREQ2_DRAMTMG8(X)         (DDRC_IPS_BASE_ADDR(X) + 0x3120)
+#define DDRC_FREQ2_DRAMTMG9(X)         (DDRC_IPS_BASE_ADDR(X) + 0x3124)
+#define DDRC_FREQ2_DRAMTMG10(X)        (DDRC_IPS_BASE_ADDR(X) + 0x3128)
+#define DDRC_FREQ2_DRAMTMG11(X)        (DDRC_IPS_BASE_ADDR(X) + 0x312c)
+#define DDRC_FREQ2_DRAMTMG12(X)        (DDRC_IPS_BASE_ADDR(X) + 0x3130)
+#define DDRC_FREQ2_DRAMTMG13(X)        (DDRC_IPS_BASE_ADDR(X) + 0x3134)
+#define DDRC_FREQ2_DRAMTMG14(X)        (DDRC_IPS_BASE_ADDR(X) + 0x3138)
+#define DDRC_FREQ2_DRAMTMG15(X)        (DDRC_IPS_BASE_ADDR(X) + 0x313C)
+#define DDRC_FREQ2_DRAMTMG16(X)        (DDRC_IPS_BASE_ADDR(X) + 0x3140)
+#define DDRC_FREQ2_DRAMTMG17(X)        (DDRC_IPS_BASE_ADDR(X) + 0x3144)
+#define DDRC_FREQ2_ZQCTL0(X)           (DDRC_IPS_BASE_ADDR(X) + 0x3180)
+#define DDRC_FREQ2_DFITMG0(X)          (DDRC_IPS_BASE_ADDR(X) + 0x3190)
+#define DDRC_FREQ2_DFITMG1(X)          (DDRC_IPS_BASE_ADDR(X) + 0x3194)
+#define DDRC_FREQ2_DFITMG2(X)          (DDRC_IPS_BASE_ADDR(X) + 0x31b4)
+#define DDRC_FREQ2_DFITMG3(X)          (DDRC_IPS_BASE_ADDR(X) + 0x31b8)
+#define DDRC_FREQ2_ODTCFG(X)           (DDRC_IPS_BASE_ADDR(X) + 0x3240)
+
+#define DDRC_FREQ3_DERATEEN(X)         (DDRC_IPS_BASE_ADDR(X) + 0x4020)
+#define DDRC_FREQ3_DERATEINT(X)        (DDRC_IPS_BASE_ADDR(X) + 0x4024)
+#define DDRC_FREQ3_RFSHCTL0(X)         (DDRC_IPS_BASE_ADDR(X) + 0x4050)
+#define DDRC_FREQ3_RFSHTMG(X)          (DDRC_IPS_BASE_ADDR(X) + 0x4064)
+#define DDRC_FREQ3_INIT3(X)            (DDRC_IPS_BASE_ADDR(X) + 0x40dc)
+#define DDRC_FREQ3_INIT4(X)            (DDRC_IPS_BASE_ADDR(X) + 0x40e0)
+#define DDRC_FREQ3_INIT6(X)            (DDRC_IPS_BASE_ADDR(X) + 0x40e8)
+#define DDRC_FREQ3_INIT7(X)            (DDRC_IPS_BASE_ADDR(X) + 0x40ec)
+#define DDRC_FREQ3_DRAMTMG0(X)         (DDRC_IPS_BASE_ADDR(X) + 0x4100)
+#define DDRC_FREQ3_DRAMTMG1(X)         (DDRC_IPS_BASE_ADDR(X) + 0x4104)
+#define DDRC_FREQ3_DRAMTMG2(X)         (DDRC_IPS_BASE_ADDR(X) + 0x4108)
+#define DDRC_FREQ3_DRAMTMG3(X)         (DDRC_IPS_BASE_ADDR(X) + 0x410c)
+#define DDRC_FREQ3_DRAMTMG4(X)         (DDRC_IPS_BASE_ADDR(X) + 0x4110)
+#define DDRC_FREQ3_DRAMTMG5(X)         (DDRC_IPS_BASE_ADDR(X) + 0x4114)
+#define DDRC_FREQ3_DRAMTMG6(X)         (DDRC_IPS_BASE_ADDR(X) + 0x4118)
+#define DDRC_FREQ3_DRAMTMG7(X)         (DDRC_IPS_BASE_ADDR(X) + 0x411c)
+#define DDRC_FREQ3_DRAMTMG8(X)         (DDRC_IPS_BASE_ADDR(X) + 0x4120)
+#define DDRC_FREQ3_DRAMTMG9(X)         (DDRC_IPS_BASE_ADDR(X) + 0x4124)
+#define DDRC_FREQ3_DRAMTMG10(X)        (DDRC_IPS_BASE_ADDR(X) + 0x4128)
+#define DDRC_FREQ3_DRAMTMG11(X)        (DDRC_IPS_BASE_ADDR(X) + 0x412c)
+#define DDRC_FREQ3_DRAMTMG12(X)        (DDRC_IPS_BASE_ADDR(X) + 0x4130)
+#define DDRC_FREQ3_DRAMTMG13(X)        (DDRC_IPS_BASE_ADDR(X) + 0x4134)
+#define DDRC_FREQ3_DRAMTMG14(X)        (DDRC_IPS_BASE_ADDR(X) + 0x4138)
+#define DDRC_FREQ3_DRAMTMG15(X)        (DDRC_IPS_BASE_ADDR(X) + 0x413C)
+#define DDRC_FREQ3_DRAMTMG16(X)        (DDRC_IPS_BASE_ADDR(X) + 0x4140)
+
+#define DDRC_FREQ3_ZQCTL0(X)           (DDRC_IPS_BASE_ADDR(X) + 0x4180)
+#define DDRC_FREQ3_DFITMG0(X)          (DDRC_IPS_BASE_ADDR(X) + 0x4190)
+#define DDRC_FREQ3_DFITMG1(X)          (DDRC_IPS_BASE_ADDR(X) + 0x4194)
+#define DDRC_FREQ3_DFITMG2(X)          (DDRC_IPS_BASE_ADDR(X) + 0x41b4)
+#define DDRC_FREQ3_DFITMG3(X)          (DDRC_IPS_BASE_ADDR(X) + 0x41b8)
+#define DDRC_FREQ3_ODTCFG(X)           (DDRC_IPS_BASE_ADDR(X) + 0x4240)
+#define DDRC_DFITMG0_SHADOW(X)         (DDRC_IPS_BASE_ADDR(X) + 0x2190)
+#define DDRC_DFITMG1_SHADOW(X)         (DDRC_IPS_BASE_ADDR(X) + 0x2194)
+#define DDRC_DFITMG2_SHADOW(X)         (DDRC_IPS_BASE_ADDR(X) + 0x21b4)
+#define DDRC_DFITMG3_SHADOW(X)         (DDRC_IPS_BASE_ADDR(X) + 0x21b8)
+#define DDRC_ODTCFG_SHADOW(X)          (DDRC_IPS_BASE_ADDR(X) + 0x2240)
+
+#define DRC_PERF_MON_BASE_ADDR(X)	(0x3d800000 + ((X) * 0x2000000))
+#define DRC_PERF_MON_CNT0_CTL(X)	(DRC_PERF_MON_BASE_ADDR(X) + 0x0)
+#define DRC_PERF_MON_CNT1_CTL(X)	(DRC_PERF_MON_BASE_ADDR(X) + 0x4)
+#define DRC_PERF_MON_CNT2_CTL(X)	(DRC_PERF_MON_BASE_ADDR(X) + 0x8)
+#define DRC_PERF_MON_CNT3_CTL(X)	(DRC_PERF_MON_BASE_ADDR(X) + 0xC)
+#define DRC_PERF_MON_CNT0_DAT(X)	(DRC_PERF_MON_BASE_ADDR(X) + 0x20)
+#define DRC_PERF_MON_CNT1_DAT(X)	(DRC_PERF_MON_BASE_ADDR(X) + 0x24)
+#define DRC_PERF_MON_CNT2_DAT(X)	(DRC_PERF_MON_BASE_ADDR(X) + 0x28)
+#define DRC_PERF_MON_CNT3_DAT(X)	(DRC_PERF_MON_BASE_ADDR(X) + 0x2C)
+#define DRC_PERF_MON_DPCR_DAT(X)	(DRC_PERF_MON_BASE_ADDR(X) + 0x30)
+#define DRC_PERF_MON_MRR0_DAT(X)	(DRC_PERF_MON_BASE_ADDR(X) + 0x40)
+#define DRC_PERF_MON_MRR1_DAT(X)	(DRC_PERF_MON_BASE_ADDR(X) + 0x44)
+#define DRC_PERF_MON_MRR2_DAT(X)	(DRC_PERF_MON_BASE_ADDR(X) + 0x48)
+#define DRC_PERF_MON_MRR3_DAT(X)	(DRC_PERF_MON_BASE_ADDR(X) + 0x4C)
+#define DRC_PERF_MON_MRR4_DAT(X)	(DRC_PERF_MON_BASE_ADDR(X) + 0x50)
+#define DRC_PERF_MON_MRR5_DAT(X)	(DRC_PERF_MON_BASE_ADDR(X) + 0x54)
+#define DRC_PERF_MON_MRR6_DAT(X)	(DRC_PERF_MON_BASE_ADDR(X) + 0x58)
+#define DRC_PERF_MON_MRR7_DAT(X)	(DRC_PERF_MON_BASE_ADDR(X) + 0x5C)
+#define DRC_PERF_MON_MRR8_DAT(X)	(DRC_PERF_MON_BASE_ADDR(X) + 0x60)
+#define DRC_PERF_MON_MRR9_DAT(X)	(DRC_PERF_MON_BASE_ADDR(X) + 0x64)
+#define DRC_PERF_MON_MRR10_DAT(X)	(DRC_PERF_MON_BASE_ADDR(X) + 0x68)
+#define DRC_PERF_MON_MRR11_DAT(X)	(DRC_PERF_MON_BASE_ADDR(X) + 0x6C)
+#define DRC_PERF_MON_MRR12_DAT(X)	(DRC_PERF_MON_BASE_ADDR(X) + 0x70)
+#define DRC_PERF_MON_MRR13_DAT(X)	(DRC_PERF_MON_BASE_ADDR(X) + 0x74)
+#define DRC_PERF_MON_MRR14_DAT(X)	(DRC_PERF_MON_BASE_ADDR(X) + 0x78)
+#define DRC_PERF_MON_MRR15_DAT(X)	(DRC_PERF_MON_BASE_ADDR(X) + 0x7C)
+
+#define dwc_ddrphy_apb_rd(addr)		mmio_read_32(IMX_DDRPHY_BASE + 4 * (addr))
+#define dwc_ddrphy_apb_wr(addr, val)	mmio_write_32(IMX_DDRPHY_BASE + 4 * (addr), val)
+
+#endif /*IMX_DDRC_H */
diff --git a/plat/imx/imx8m/include/dram.h b/plat/imx/imx8m/include/dram.h
new file mode 100644
index 0000000..ad11a27
--- /dev/null
+++ b/plat/imx/imx8m/include/dram.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2019-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef DRAM_H
+#define DRAM_H
+
+#include <assert.h>
+
+#include <arch_helpers.h>
+#include <lib/utils_def.h>
+
+#include <ddrc.h>
+#include <platform_def.h>
+
+#define DDRC_LPDDR4		BIT(5)
+#define DDRC_DDR4		BIT(4)
+#define DDRC_DDR3L		BIT(0)
+#define DDR_TYPE_MASK		U(0x3f)
+#define ACTIVE_RANK_MASK	U(0x3)
+
+/* reg & config param */
+struct dram_cfg_param {
+	unsigned int reg;
+	unsigned int val;
+};
+
+struct dram_timing_info {
+	/* umctl2 config */
+	struct dram_cfg_param *ddrc_cfg;
+	unsigned int ddrc_cfg_num;
+	/* ddrphy config */
+	struct dram_cfg_param *ddrphy_cfg;
+	unsigned int ddrphy_cfg_num;
+	/* ddr fsp train info */
+	struct dram_fsp_msg *fsp_msg;
+	unsigned int fsp_msg_num;
+	/* ddr phy trained CSR */
+	struct dram_cfg_param *ddrphy_trained_csr;
+	unsigned int ddrphy_trained_csr_num;
+	/* ddr phy PIE */
+	struct dram_cfg_param *ddrphy_pie;
+	unsigned int ddrphy_pie_num;
+	/* initialized fsp table */
+	unsigned int fsp_table[4];
+};
+
+struct dram_info {
+	int dram_type;
+	unsigned int num_rank;
+	uint32_t num_fsp;
+	int current_fsp;
+	int boot_fsp;
+	bool bypass_mode;
+	struct dram_timing_info *timing_info;
+	/* mr, emr, emr2, emr3, mr11, mr12, mr22, mr14 */
+	uint32_t mr_table[3][8];
+};
+
+extern struct dram_info dram_info;
+
+void dram_info_init(unsigned long dram_timing_base);
+void dram_umctl2_init(struct dram_timing_info *timing);
+void dram_phy_init(struct dram_timing_info *timing);
+
+/* dram retention */
+void dram_enter_retention(void);
+void dram_exit_retention(void);
+
+void dram_clock_switch(unsigned int target_drate, bool bypass_mode);
+
+/* dram frequency change */
+void lpddr4_swffc(struct dram_info *info, unsigned int init_fsp, unsigned int fsp_index);
+void ddr4_swffc(struct dram_info *dram_info, unsigned int pstate);
+
+#endif /* DRAM_H */
diff --git a/plat/imx/imx8m/include/gpc.h b/plat/imx/imx8m/include/gpc.h
index 29b8ecf..a41030e 100644
--- a/plat/imx/imx8m/include/gpc.h
+++ b/plat/imx/imx8m/include/gpc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -69,5 +69,7 @@
 void imx_set_sys_lpm(unsigned last_core, bool retention);
 void imx_set_rbc_count(void);
 void imx_clear_rbc_count(void);
+void imx_anamix_override(bool enter);
+void imx_gpc_pm_domain_enable(uint32_t domain_id, bool on);
 
 #endif /*IMX8M_GPC_H */
diff --git a/plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_sspm_notifier.c b/plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_sspm_notifier.c
index 198bac5..20ef011 100644
--- a/plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_sspm_notifier.c
+++ b/plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_sspm_notifier.c
@@ -11,7 +11,7 @@
 #include <mt_spm_sspm_intc.h>
 #include <sspm_reg.h>
 
-#define MT_SPM_SSPM_MBOX_OFF(x)		(SSPM_MBOX_3_BASE + x)
+#define MT_SPM_SSPM_MBOX_OFF(x)		(SSPM_MBOX_BASE + x)
 #define MT_SPM_MBOX(slot)		MT_SPM_SSPM_MBOX_OFF((slot << 2UL))
 
 #define SSPM_MBOX_SPM_LP_LOOKUP1	MT_SPM_MBOX(0)
diff --git a/plat/mediatek/mt8186/include/platform_def.h b/plat/mediatek/mt8186/include/platform_def.h
index b8b877a..f3d15f3 100644
--- a/plat/mediatek/mt8186/include/platform_def.h
+++ b/plat/mediatek/mt8186/include/platform_def.h
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
- * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ * Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2022, MediaTek Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -26,6 +26,8 @@
 #define INFRACFG_AO_BASE        (IO_PHYS + 0x00001000)
 #define SPM_BASE		(IO_PHYS + 0x00006000)
 #define APMIXEDSYS              (IO_PHYS + 0x0000C000)
+#define SSPM_MCDI_SHARE_SRAM    (IO_PHYS + 0x00420000)
+#define SSPM_CFGREG_BASE        (IO_PHYS + 0x00440000)  /* SSPM view: 0x30040000 */
 #define SSPM_MBOX_BASE          (IO_PHYS + 0x00480000)
 #define PERICFG_AO_BASE         (IO_PHYS + 0x01003000)
 #define VPPSYS0_BASE            (IO_PHYS + 0x04000000)
diff --git a/plat/mediatek/mt8186/include/sspm_reg.h b/plat/mediatek/mt8186/include/sspm_reg.h
index 3e8c3e2..40b71ac 100644
--- a/plat/mediatek/mt8186/include/sspm_reg.h
+++ b/plat/mediatek/mt8186/include/sspm_reg.h
@@ -9,12 +9,8 @@
 
 #include "platform_def.h"
 
-#define SSPM_CFGREG_BASE	(IO_PHYS + 0x440000)     /* SSPM view: 0x30040000 */
 #define SSPM_CFGREG_ADDR(ofs)	(SSPM_CFGREG_BASE + (ofs))
 
-#define SSPM_MCDI_SHARE_SRAM	(IO_PHYS + 0x420000)
-#define SSPM_MBOX_3_BASE	(IO_PHYS + 0x480000)
-
 #define SSPM_HW_SEM		SSPM_CFGREG_ADDR(0x0048)
 #define SSPM_ACAO_INT_SET	SSPM_CFGREG_ADDR(0x00D8)
 #define SSPM_ACAO_INT_CLR	SSPM_CFGREG_ADDR(0x00DC)
diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h
index 7e0745a..8ca6123 100644
--- a/plat/st/stm32mp1/stm32mp1_def.h
+++ b/plat/st/stm32mp1/stm32mp1_def.h
@@ -182,7 +182,12 @@
  #endif
 #endif
 
+#if STM32MP13
+#define STM32MP_BL33_BASE		STM32MP_DDR_BASE
+#endif
+#if STM32MP15
 #define STM32MP_BL33_BASE		(STM32MP_DDR_BASE + U(0x100000))
+#endif
 #define STM32MP_BL33_MAX_SIZE		U(0x400000)
 
 /* Define maximum page size for NAND devices */
@@ -247,8 +252,14 @@
 /*******************************************************************************
  * STM32MP1 UART
  ******************************************************************************/
+#if STM32MP13
+#define USART1_BASE			U(0x4C000000)
+#define USART2_BASE			U(0x4C001000)
+#endif
+#if STM32MP15
 #define USART1_BASE			U(0x5C000000)
 #define USART2_BASE			U(0x4000E000)
+#endif
 #define USART3_BASE			U(0x4000F000)
 #define UART4_BASE			U(0x40010000)
 #define UART5_BASE			U(0x40011000)
diff --git a/plat/xilinx/common/include/plat_startup.h b/plat/xilinx/common/include/plat_startup.h
index 6799e21..5ccb774 100644
--- a/plat/xilinx/common/include/plat_startup.h
+++ b/plat/xilinx/common/include/plat_startup.h
@@ -15,6 +15,23 @@
 	FSBL_HANDOFF_TOO_MANY_PARTS
 };
 
+#define FSBL_MAX_PARTITIONS		8U
+
+/* Structure corresponding to each partition entry */
+struct xfsbl_partition {
+	uint64_t entry_point;
+	uint64_t flags;
+};
+
+/* Structure for handoff parameters to ARM Trusted Firmware (ATF) */
+struct xfsbl_atf_handoff_params {
+	uint8_t magic[4];
+	uint32_t num_entries;
+	struct xfsbl_partition partition[FSBL_MAX_PARTITIONS];
+};
+
+#define ATF_HANDOFF_PARAMS_MAX_SIZE	sizeof(struct xfsbl_atf_handoff_params)
+
 enum fsbl_handoff fsbl_atf_handover(entry_point_info_t *bl32,
 					entry_point_info_t *bl33,
 					uint64_t atf_handoff_addr);
diff --git a/plat/xilinx/common/plat_startup.c b/plat/xilinx/common/plat_startup.c
index bf262c4..de9cf4d 100644
--- a/plat/xilinx/common/plat_startup.c
+++ b/plat/xilinx/common/plat_startup.c
@@ -24,49 +24,34 @@
  * CPU#			5:6		00 -> A53_0, 01 -> A53_1, 10 -> A53_2, 11 -> A53_3
  */
 
-#define FSBL_FLAGS_ESTATE_SHIFT		0
-#define FSBL_FLAGS_ESTATE_MASK		(1 << FSBL_FLAGS_ESTATE_SHIFT)
-#define FSBL_FLAGS_ESTATE_A64		0
-#define FSBL_FLAGS_ESTATE_A32		1
+#define FSBL_FLAGS_ESTATE_SHIFT		0U
+#define FSBL_FLAGS_ESTATE_MASK		(1U << FSBL_FLAGS_ESTATE_SHIFT)
+#define FSBL_FLAGS_ESTATE_A64		0U
+#define FSBL_FLAGS_ESTATE_A32		1U
 
-#define FSBL_FLAGS_ENDIAN_SHIFT		1
-#define FSBL_FLAGS_ENDIAN_MASK		(1 << FSBL_FLAGS_ENDIAN_SHIFT)
-#define FSBL_FLAGS_ENDIAN_LE		0
-#define FSBL_FLAGS_ENDIAN_BE		1
+#define FSBL_FLAGS_ENDIAN_SHIFT		1U
+#define FSBL_FLAGS_ENDIAN_MASK		(1U << FSBL_FLAGS_ENDIAN_SHIFT)
+#define FSBL_FLAGS_ENDIAN_LE		0U
+#define FSBL_FLAGS_ENDIAN_BE		1U
 
-#define FSBL_FLAGS_TZ_SHIFT		2
-#define FSBL_FLAGS_TZ_MASK		(1 << FSBL_FLAGS_TZ_SHIFT)
-#define FSBL_FLAGS_NON_SECURE		0
-#define FSBL_FLAGS_SECURE		1
+#define FSBL_FLAGS_TZ_SHIFT		2U
+#define FSBL_FLAGS_TZ_MASK		(1U << FSBL_FLAGS_TZ_SHIFT)
+#define FSBL_FLAGS_NON_SECURE		0U
+#define FSBL_FLAGS_SECURE		1U
 
-#define FSBL_FLAGS_EL_SHIFT		3
-#define FSBL_FLAGS_EL_MASK		(3 << FSBL_FLAGS_EL_SHIFT)
-#define FSBL_FLAGS_EL0			0
-#define FSBL_FLAGS_EL1			1
-#define FSBL_FLAGS_EL2			2
-#define FSBL_FLAGS_EL3			3
+#define FSBL_FLAGS_EL_SHIFT		3U
+#define FSBL_FLAGS_EL_MASK		(3U << FSBL_FLAGS_EL_SHIFT)
+#define FSBL_FLAGS_EL0			0U
+#define FSBL_FLAGS_EL1			1U
+#define FSBL_FLAGS_EL2			2U
+#define FSBL_FLAGS_EL3			3U
 
-#define FSBL_FLAGS_CPU_SHIFT		5
-#define FSBL_FLAGS_CPU_MASK		(3 << FSBL_FLAGS_CPU_SHIFT)
-#define FSBL_FLAGS_A53_0		0
-#define FSBL_FLAGS_A53_1		1
-#define FSBL_FLAGS_A53_2		2
-#define FSBL_FLAGS_A53_3		3
-
-#define FSBL_MAX_PARTITIONS		8
-
-/* Structure corresponding to each partition entry */
-struct xfsbl_partition {
-	uint64_t entry_point;
-	uint64_t flags;
-};
-
-/* Structure for handoff parameters to ARM Trusted Firmware (ATF) */
-struct xfsbl_atf_handoff_params {
-	uint8_t magic[4];
-	uint32_t num_entries;
-	struct xfsbl_partition partition[FSBL_MAX_PARTITIONS];
-};
+#define FSBL_FLAGS_CPU_SHIFT		5U
+#define FSBL_FLAGS_CPU_MASK		(3U << FSBL_FLAGS_CPU_SHIFT)
+#define FSBL_FLAGS_A53_0		0U
+#define FSBL_FLAGS_A53_1		1U
+#define FSBL_FLAGS_A53_2		2U
+#define FSBL_FLAGS_A53_3		3U
 
 /**
  * @partition: Pointer to partition struct
@@ -161,8 +146,6 @@
 					uint64_t atf_handoff_addr)
 {
 	const struct xfsbl_atf_handoff_params *ATFHandoffParams;
-	assert((atf_handoff_addr < BL31_BASE) ||
-	       (atf_handoff_addr > (uint64_t)&__BL31_END__));
 	if (!atf_handoff_addr) {
 		WARN("BL31: No ATF handoff structure passed\n");
 		return FSBL_HANDOFF_NO_STRUCT;
@@ -193,8 +176,8 @@
 	 */
 	for (size_t i = 0; i < ATFHandoffParams->num_entries; i++) {
 		entry_point_info_t *image;
-		int32_t target_estate, target_secure;
-		int32_t target_cpu, target_endianness, target_el;
+		int32_t target_estate, target_secure, target_cpu;
+		uint32_t target_endianness, target_el;
 
 		VERBOSE("BL31: %zd: entry:0x%" PRIx64 ", flags:0x%" PRIx64 "\n", i,
 			ATFHandoffParams->partition[i].entry_point,
diff --git a/plat/xilinx/versal/bl31_versal_setup.c b/plat/xilinx/versal/bl31_versal_setup.c
index 0d0d598..593cdc4 100644
--- a/plat/xilinx/versal/bl31_versal_setup.c
+++ b/plat/xilinx/versal/bl31_versal_setup.c
@@ -20,6 +20,9 @@
 #include <versal_def.h>
 #include <plat_private.h>
 #include <plat_startup.h>
+#include <pm_ipi.h>
+#include "pm_client.h"
+#include "pm_api_sys.h"
 
 static entry_point_info_t bl32_image_ep_info;
 static entry_point_info_t bl33_image_ep_info;
@@ -63,6 +66,9 @@
 				u_register_t arg2, u_register_t arg3)
 {
 	uint64_t atf_handoff_addr;
+	uint32_t payload[PAYLOAD_ARG_CNT], max_size = ATF_HANDOFF_PARAMS_MAX_SIZE;
+	enum pm_ret_status ret_status;
+	uint64_t addr[ATF_HANDOFF_PARAMS_MAX_SIZE];
 
 	if (VERSAL_CONSOLE_IS(pl011) || (VERSAL_CONSOLE_IS(pl011_1))) {
 		static console_t versal_runtime_console;
@@ -106,7 +112,17 @@
 	SET_PARAM_HEAD(&bl33_image_ep_info, PARAM_EP, VERSION_1, 0);
 	SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
 
-	atf_handoff_addr = mmio_read_32(PMC_GLOBAL_GLOB_GEN_STORAGE4);
+	PM_PACK_PAYLOAD4(payload, LOADER_MODULE_ID, 1, PM_LOAD_GET_HANDOFF_PARAMS,
+			(uintptr_t)addr >> 32U, (uintptr_t)addr, max_size);
+	ret_status = pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+	if (ret_status == PM_RET_SUCCESS) {
+		INFO("BL31: GET_HANDOFF_PARAMS call success=%d\n", ret_status);
+		atf_handoff_addr = (uintptr_t)&addr;
+	} else {
+		ERROR("BL31: GET_HANDOFF_PARAMS Failed, read atf_handoff_addr from reg\n");
+		atf_handoff_addr = mmio_read_32(PMC_GLOBAL_GLOB_GEN_STORAGE4);
+	}
+
 	enum fsbl_handoff ret = fsbl_atf_handover(&bl32_image_ep_info,
 						  &bl33_image_ep_info,
 						  atf_handoff_addr);
diff --git a/plat/xilinx/versal/include/plat_pm_common.h b/plat/xilinx/versal/include/plat_pm_common.h
index 22c9d11..fb4812d 100644
--- a/plat/xilinx/versal/include/plat_pm_common.h
+++ b/plat/xilinx/versal/include/plat_pm_common.h
@@ -19,8 +19,8 @@
 #define NON_SECURE_FLAG		1U
 #define SECURE_FLAG		0U
 
-#define VERSAL_TZ_VERSION_MAJOR		1
-#define VERSAL_TZ_VERSION_MINOR		0
-#define VERSAL_TZ_VERSION		((VERSAL_TZ_VERSION_MAJOR << 16) | \
+#define VERSAL_TZ_VERSION_MAJOR		1U
+#define VERSAL_TZ_VERSION_MINOR		0U
+#define VERSAL_TZ_VERSION		((VERSAL_TZ_VERSION_MAJOR << 16U) | \
 					VERSAL_TZ_VERSION_MINOR)
 #endif /* PLAT_PM_COMMON_H */
diff --git a/plat/xilinx/versal/include/platform_def.h b/plat/xilinx/versal/include/platform_def.h
index 83e5083..6d95fdc 100644
--- a/plat/xilinx/versal/include/platform_def.h
+++ b/plat/xilinx/versal/include/platform_def.h
@@ -15,7 +15,7 @@
  ******************************************************************************/
 
 /* Size of cacheable stacks */
-#define PLATFORM_STACK_SIZE	0x440
+#define PLATFORM_STACK_SIZE	U(0x440)
 
 #define PLATFORM_CORE_COUNT		U(2)
 #define PLAT_MAX_PWR_LVL		U(1)
diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.c b/plat/xilinx/versal/pm_service/pm_api_sys.c
index db78049..e464d32 100644
--- a/plat/xilinx/versal/pm_service/pm_api_sys.c
+++ b/plat/xilinx/versal/pm_service/pm_api_sys.c
@@ -18,15 +18,6 @@
 #include "pm_svc_main.h"
 #include "../drivers/arm/gic/v3/gicv3_private.h"
 
-/*********************************************************************
- * Target module IDs macros
- ********************************************************************/
-#define LIBPM_MODULE_ID		0x2U
-#define LOADER_MODULE_ID	0x7U
-
-#define  MODE	0x80000000U
-#define MODULE_ID_MASK		0x0000ff00
-
 /* default shutdown/reboot scope is system(2) */
 static uint32_t pm_shutdown_scope = XPM_SHUTDOWN_SUBTYPE_RST_SYSTEM;
 
@@ -40,38 +31,6 @@
 	return pm_shutdown_scope;
 }
 
-/**
- * Assigning of argument values into array elements.
- */
-#define PM_PACK_PAYLOAD1(pl, mid, flag, arg0) {	\
-	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));			\
-}
-
-#define PM_PACK_PAYLOAD3(pl, mid, flag, arg0, arg1, arg2) {	\
-	pl[2] = (uint32_t)(arg2);				\
-	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));		\
-}
-
-#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));	\
-}
-
-#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 API functions */
 
 /**
@@ -90,7 +49,7 @@
 	uint32_t payload[PAYLOAD_ARG_CNT] = {0};
 	uint32_t module_id;
 
-	module_id = (x0 & MODULE_ID_MASK) >> 8;
+	module_id = (x0 & MODULE_ID_MASK) >> 8U;
 
 	//default module id is for LIBPM
 	if (module_id == 0) {
@@ -438,7 +397,7 @@
 
 	ret = pm_feature_check(PM_QUERY_DATA, &version[0], flag);
 	if (ret == PM_RET_SUCCESS) {
-		fw_api_version = version[0] & 0xFFFF;
+		fw_api_version = version[0] & 0xFFFFU;
 		if ((fw_api_version == 2U) &&
 		    ((qid == XPM_QID_CLOCK_GET_NAME) ||
 		     (qid == XPM_QID_PINCTRL_GET_FUNCTION_NAME))) {
@@ -562,7 +521,7 @@
 		break;
 	}
 
-	module_id = (api_id & MODULE_ID_MASK) >> 8;
+	module_id = (api_id & MODULE_ID_MASK) >> 8U;
 
 	/*
 	 * feature check should be done only for LIBPM module
diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.h b/plat/xilinx/versal/pm_service/pm_api_sys.h
index 8343533..6fa65c2 100644
--- a/plat/xilinx/versal/pm_service/pm_api_sys.h
+++ b/plat/xilinx/versal/pm_service/pm_api_sys.h
@@ -10,6 +10,14 @@
 #include <stdint.h>
 #include "pm_defs.h"
 
+/*********************************************************************
+ * Target module IDs macros
+ ********************************************************************/
+#define LIBPM_MODULE_ID		0x2U
+#define LOADER_MODULE_ID	0x7U
+
+#define  MODE			0x80000000U
+#define  MODULE_ID_MASK		0x0000ff00
 /**********************************************************
  * PM API function declarations
  **********************************************************/
@@ -56,4 +64,37 @@
 enum pm_ret_status pm_register_notifier(uint32_t device_id, uint32_t event,
 					uint32_t wake, uint32_t enable,
 					uint32_t flag);
+
+/**
+ * Assigning of argument values into array elements.
+ */
+#define PM_PACK_PAYLOAD1(pl, mid, flag, arg0) {	\
+	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));			\
+}
+
+#define PM_PACK_PAYLOAD3(pl, mid, flag, arg0, arg1, arg2) {	\
+	pl[2] = (uint32_t)(arg2);				\
+	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));		\
+}
+
+#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));	\
+}
+
+#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));		\
+}
+
 #endif /* PM_API_SYS_H */
diff --git a/plat/xilinx/versal/pm_service/pm_defs.h b/plat/xilinx/versal/pm_service/pm_defs.h
index 9206120..5491555 100644
--- a/plat/xilinx/versal/pm_service/pm_defs.h
+++ b/plat/xilinx/versal/pm_service/pm_defs.h
@@ -62,6 +62,7 @@
 
 /* Loader API ids */
 #define PM_LOAD_PDI			0x701U
+#define PM_LOAD_GET_HANDOFF_PARAMS	0x70BU
 
 /* IOCTL IDs for clock driver */
 #define IOCTL_SET_PLL_FRAC_MODE		8U
diff --git a/plat/xilinx/versal/pm_service/pm_svc_main.c b/plat/xilinx/versal/pm_service/pm_svc_main.c
index f4d04b8..4b0f5e0 100644
--- a/plat/xilinx/versal/pm_service/pm_svc_main.c
+++ b/plat/xilinx/versal/pm_service/pm_svc_main.c
@@ -156,8 +156,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, (uint64_t)ret  | ((uint64_t)data[0] << 32U),
+				 (uint64_t)data[1] | ((uint64_t)data[2] << 32U));
 	}
 
 	case PM_FEATURE_CHECK:
@@ -165,8 +165,8 @@
 		uint32_t result[PAYLOAD_ARG_CNT] = {0U};
 
 		ret = pm_feature_check(pm_arg[0], result, security_flag);
-		SMC_RET2(handle, (uint64_t)ret | ((uint64_t)result[0] << 32),
-			 (uint64_t)result[1] | ((uint64_t)result[2] << 32));
+		SMC_RET2(handle, (uint64_t)ret | ((uint64_t)result[0] << 32U),
+			 (uint64_t)result[1] | ((uint64_t)result[2] << 32U));
 	}
 
 	case PM_LOAD_PDI:
@@ -255,13 +255,13 @@
 
 		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));
+			(uint64_t)result[0] | ((uint64_t)result[1] << 32U),
+			(uint64_t)result[2] | ((uint64_t)result[3] << 32U));
 	}
 
 	case PM_GET_TRUSTZONE_VERSION:
 		SMC_RET1(handle, (uint64_t)PM_RET_SUCCESS |
-			 ((uint64_t)VERSAL_TZ_VERSION << 32));
+			 ((uint64_t)VERSAL_TZ_VERSION << 32U));
 
 	default:
 		return (uintptr_t)0;
diff --git a/plat/xilinx/zynqmp/aarch64/zynqmp_common.c b/plat/xilinx/zynqmp/aarch64/zynqmp_common.c
index 5890311..3946e9b 100644
--- a/plat/xilinx/zynqmp/aarch64/zynqmp_common.c
+++ b/plat/xilinx/zynqmp/aarch64/zynqmp_common.c
@@ -215,8 +215,8 @@
 #define ZYNQMP_PL_STATUS_MASK	BIT(ZYNQMP_PL_STATUS_BIT)
 #define ZYNQMP_CSU_VERSION_MASK	~(ZYNQMP_PL_STATUS_MASK)
 
-#define SILICON_ID_XCK24	0x4714093
-#define SILICON_ID_XCK26	0x4724093
+#define SILICON_ID_XCK24	0x4714093U
+#define SILICON_ID_XCK26	0x4724093U
 
 static char *zynqmp_get_silicon_idcode_name(void)
 {
@@ -317,7 +317,7 @@
 	ver &= ZYNQMP_PS_VER_MASK;
 	ver >>= ZYNQMP_PS_VER_SHIFT;
 
-	return ver + 1;
+	return ver + 1U;
 }
 
 static void zynqmp_print_platform_name(void)
diff --git a/plat/xilinx/zynqmp/include/zynqmp_def.h b/plat/xilinx/zynqmp/include/zynqmp_def.h
index 19b6937..877127b 100644
--- a/plat/xilinx/zynqmp/include/zynqmp_def.h
+++ b/plat/xilinx/zynqmp/include/zynqmp_def.h
@@ -163,40 +163,40 @@
 #define ZYNQMP_CSU_VERSION_SILICON	0
 #define ZYNQMP_CSU_VERSION_QEMU		3
 
-#define ZYNQMP_RTL_VER_MASK		0xFF0
+#define ZYNQMP_RTL_VER_MASK		0xFF0U
 #define ZYNQMP_RTL_VER_SHIFT		4
 
-#define ZYNQMP_PS_VER_MASK		0xF
+#define ZYNQMP_PS_VER_MASK		0xFU
 #define ZYNQMP_PS_VER_SHIFT		0
 
 #define ZYNQMP_CSU_BASEADDR		U(0xFFCA0000)
-#define ZYNQMP_CSU_IDCODE_OFFSET	0x40
+#define ZYNQMP_CSU_IDCODE_OFFSET	0x40U
 
-#define ZYNQMP_CSU_IDCODE_XILINX_ID_SHIFT	0
-#define ZYNQMP_CSU_IDCODE_XILINX_ID_MASK	(0xFFF << \
+#define ZYNQMP_CSU_IDCODE_XILINX_ID_SHIFT	0U
+#define ZYNQMP_CSU_IDCODE_XILINX_ID_MASK	(0xFFFU << \
 					ZYNQMP_CSU_IDCODE_XILINX_ID_SHIFT)
 #define ZYNQMP_CSU_IDCODE_XILINX_ID		0x093
 
-#define ZYNQMP_CSU_IDCODE_SVD_SHIFT		12
-#define ZYNQMP_CSU_IDCODE_SVD_MASK		(0x7 << \
+#define ZYNQMP_CSU_IDCODE_SVD_SHIFT		12U
+#define ZYNQMP_CSU_IDCODE_SVD_MASK		(0x7U << \
 						 ZYNQMP_CSU_IDCODE_SVD_SHIFT)
-#define ZYNQMP_CSU_IDCODE_DEVICE_CODE_SHIFT	15
-#define ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK	(0xF << \
+#define ZYNQMP_CSU_IDCODE_DEVICE_CODE_SHIFT	15U
+#define ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK	(0xFU << \
 					ZYNQMP_CSU_IDCODE_DEVICE_CODE_SHIFT)
-#define ZYNQMP_CSU_IDCODE_SUB_FAMILY_SHIFT	19
-#define ZYNQMP_CSU_IDCODE_SUB_FAMILY_MASK	(0x3 << \
+#define ZYNQMP_CSU_IDCODE_SUB_FAMILY_SHIFT	19U
+#define ZYNQMP_CSU_IDCODE_SUB_FAMILY_MASK	(0x3U << \
 					ZYNQMP_CSU_IDCODE_SUB_FAMILY_SHIFT)
-#define ZYNQMP_CSU_IDCODE_FAMILY_SHIFT		21
-#define ZYNQMP_CSU_IDCODE_FAMILY_MASK		(0x7F << \
+#define ZYNQMP_CSU_IDCODE_FAMILY_SHIFT		21U
+#define ZYNQMP_CSU_IDCODE_FAMILY_MASK		(0x7FU << \
 					ZYNQMP_CSU_IDCODE_FAMILY_SHIFT)
 #define ZYNQMP_CSU_IDCODE_FAMILY		0x23
 
-#define ZYNQMP_CSU_IDCODE_REVISION_SHIFT	28
-#define ZYNQMP_CSU_IDCODE_REVISION_MASK		(0xF << \
+#define ZYNQMP_CSU_IDCODE_REVISION_SHIFT	28U
+#define ZYNQMP_CSU_IDCODE_REVISION_MASK		(0xFU << \
 					ZYNQMP_CSU_IDCODE_REVISION_SHIFT)
-#define ZYNQMP_CSU_IDCODE_REVISION		0
+#define ZYNQMP_CSU_IDCODE_REVISION		0U
 
-#define ZYNQMP_CSU_VERSION_OFFSET	0x44
+#define ZYNQMP_CSU_VERSION_OFFSET	0x44U
 
 /* Efuse */
 #define EFUSE_BASEADDR		U(0xFFCC0000)
diff --git a/plat/xilinx/zynqmp/plat_psci.c b/plat/xilinx/zynqmp/plat_psci.c
index 655a776..b7408b1 100644
--- a/plat/xilinx/zynqmp/plat_psci.c
+++ b/plat/xilinx/zynqmp/plat_psci.c
@@ -176,7 +176,7 @@
 {
 	VERBOSE("%s: power_state: 0x%x\n", __func__, power_state);
 
-	int32_t pstate = psci_get_pstate_type(power_state);
+	uint32_t pstate = psci_get_pstate_type(power_state);
 
 	assert(req_state);
 
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_clock.c b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c
index bfc6e44..c6bed7d 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_clock.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c
@@ -2610,7 +2610,7 @@
 		}
 	}
 
-	for (i = 0; i < 3; i++) {
+	for (i = 0; i < 3U; i++) {
 		parents[i] = clk_parents[index + i];
 		if (clk_parents[index + i] == CLK_NA_PARENT) {
 			break;
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c
index 1380895..8a5a25a 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c
@@ -35,7 +35,7 @@
 
 	val = mmio_read_32(ZYNQMP_RPU_GLBL_CNTL);
 	val &= ZYNQMP_SLSPLIT_MASK;
-	if (val == 0) {
+	if (val == 0U) {
 		*mode = PM_RPU_MODE_LOCKSTEP;
 	} else {
 		*mode = PM_RPU_MODE_SPLIT;
@@ -309,7 +309,7 @@
 		return ret;
 	}
 
-	if ((val & mask) == 0) {
+	if ((val & mask) == 0U) {
 		ret = pm_ioctl_sd_dll_reset(nid, PM_DLL_RESET_ASSERT);
 		if (ret != PM_RET_SUCCESS) {
 			return ret;
@@ -325,7 +325,7 @@
 			goto reset_release;
 		}
 
-		if (value == 0) {
+		if (value == 0U) {
 			ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY,
 					    (ZYNQMP_SD_ITAPDLYENA_MASK <<
 					     shift), 0);
diff --git a/plat/xilinx/zynqmp/pm_service/pm_defs.h b/plat/xilinx/zynqmp/pm_service/pm_defs.h
index 8eb197a..d48df55 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_defs.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_defs.h
@@ -17,10 +17,10 @@
  * Version number is a 32bit value, like:
  * (PM_VERSION_MAJOR << 16) | PM_VERSION_MINOR
  */
-#define PM_VERSION_MAJOR	1
-#define PM_VERSION_MINOR	1
+#define PM_VERSION_MAJOR	1U
+#define PM_VERSION_MINOR	1U
 
-#define PM_VERSION	((PM_VERSION_MAJOR << 16) | PM_VERSION_MINOR)
+#define PM_VERSION	((PM_VERSION_MAJOR << 16U) | PM_VERSION_MINOR)
 
 /**
  * PM API versions
diff --git a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c
index 0b366d7..a136ebc 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c
@@ -214,7 +214,7 @@
 		ERROR("BL31: Platform Management API version error. Expected: "
 		      "v%d.%d - Found: v%d.%d\n", PM_VERSION_MAJOR,
 		      PM_VERSION_MINOR, pm_ctx.api_version >> 16,
-		      pm_ctx.api_version & 0xFFFF);
+		      pm_ctx.api_version & 0xFFFFU);
 		return -EINVAL;
 	}