Merge "docs: Update contribution guidelines for binary components" into integration
diff --git a/bl32/sp_min/sp_min.ld.S b/bl32/sp_min/sp_min.ld.S
index 83b7860..4559903 100644
--- a/bl32/sp_min/sp_min.ld.S
+++ b/bl32/sp_min/sp_min.ld.S
@@ -16,6 +16,9 @@
     RAM (rwx): ORIGIN = BL32_BASE, LENGTH = BL32_LIMIT - BL32_BASE
 }
 
+#ifdef PLAT_SP_MIN_EXTRA_LD_SCRIPT
+#include <plat_sp_min.ld.S>
+#endif
 
 SECTIONS
 {
diff --git a/bl32/sp_min/sp_min_private.h b/bl32/sp_min/sp_min_private.h
index 6b5d792..628581a 100644
--- a/bl32/sp_min/sp_min_private.h
+++ b/bl32/sp_min/sp_min_private.h
@@ -7,7 +7,6 @@
 #ifndef SP_MIN_PRIVATE_H
 #define SP_MIN_PRIVATE_H
 
-void sp_min_warm_entrypoint(void);
 void sp_min_main(void);
 void sp_min_warm_boot(void);
 void sp_min_fiq(void);
diff --git a/docs/auth-framework.rst b/docs/auth-framework.rst
index 317ac18..0142fbd 100644
--- a/docs/auth-framework.rst
+++ b/docs/auth-framework.rst
@@ -80,7 +80,7 @@
 A CoT is basically a sequence of authentication images which usually starts with
 a root of trust and culminates in a single data image. The following diagram
 illustrates how this maps to a CoT for the BL31 image described in the
-TBBR-Client specification.
+`TBBR-Client specification`_.
 
 ::
 
@@ -969,3 +969,4 @@
 
 .. _Trusted Board Boot: ./trusted-board-boot.rst
 .. _Platform Porting Guide: ./porting-guide.rst
+.. _TBBR-Client specification: https://developer.arm.com/docs/den0006/latest/trusted-board-boot-requirements-client-tbbr-client-armv8-a
diff --git a/docs/cpu-specific-build-macros.rst b/docs/cpu-specific-build-macros.rst
index 7b7f4cd..493e07e 100644
--- a/docs/cpu-specific-build-macros.rst
+++ b/docs/cpu-specific-build-macros.rst
@@ -73,7 +73,7 @@
 
 For Cortex-A9, the following errata build flags are defined :
 
--  ``ERRATA_A9_794073``: This applies errata 794073 workaround to Cortex-A15
+-  ``ERRATA_A9_794073``: This applies errata 794073 workaround to Cortex-A9
    CPU. This needs to be enabled for all revisions of the CPU.
 
 For Cortex-A15, the following errata build flags are defined :
@@ -217,6 +217,18 @@
 -  ``ERRATA_A76_1220197``: This applies errata 1220197 workaround to Cortex-A76
    CPU. This needs to be enabled only for revision <= r2p0 of the CPU.
 
+-  ``ERRATA_A76_1257314``: This applies errata 1257314 workaround to Cortex-A76
+   CPU. This needs to be enabled only for revision <= r3p0 of the CPU.
+
+-  ``ERRATA_A76_1262606``: This applies errata 1262606 workaround to Cortex-A76
+   CPU. This needs to be enabled only for revision <= r3p0 of the CPU.
+
+-  ``ERRATA_A76_1262888``: This applies errata 1262888 workaround to Cortex-A76
+   CPU. This needs to be enabled only for revision <= r3p0 of the CPU.
+
+-  ``ERRATA_A76_1275112``: This applies errata 1275112 workaround to Cortex-A76
+   CPU. This needs to be enabled only for revision <= r3p0 of the CPU.
+
 DSU Errata Workarounds
 ----------------------
 
diff --git a/docs/firmware-design.rst b/docs/firmware-design.rst
index 66b16fa..8384c9c 100644
--- a/docs/firmware-design.rst
+++ b/docs/firmware-design.rst
@@ -2655,8 +2655,7 @@
 References
 ----------
 
-.. [#] Trusted Board Boot Requirements CLIENT PDD (Arm DEN0006C-1). Available
-       under NDA through your Arm account representative.
+.. [#] `Trusted Board Boot Requirements CLIENT (TBBR-CLIENT) Armv8-A (ARM DEN0006D)`_
 .. [#] `Power State Coordination Interface PDD`_
 .. [#] `SMC Calling Convention PDD`_
 .. [#] `TF-A Interrupt Management Design guide`_.
@@ -2684,5 +2683,6 @@
 .. _Xlat_tables design: xlat-tables-lib-v2-design.rst
 .. _Exception Handling Framework: exception-handling.rst
 .. _ROMLIB Design: romlib-design.rst
+.. _Trusted Board Boot Requirements CLIENT (TBBR-CLIENT) Armv8-A (ARM DEN0006D): https://developer.arm.com/docs/den0006/latest/trusted-board-boot-requirements-client-tbbr-client-armv8-a
 
 .. |Image 1| image:: diagrams/rt-svc-descs-layout.png?raw=true
diff --git a/docs/plat/rockchip.rst b/docs/plat/rockchip.rst
new file mode 100644
index 0000000..e88706b
--- /dev/null
+++ b/docs/plat/rockchip.rst
@@ -0,0 +1,54 @@
+Trusted Firmware-A for Rockchip SoCs
+====================================
+
+Trusted Firmware-A supports a number of Rockchip ARM SoCs from both
+AARCH32 and AARCH64 fields.
+
+This includes right now:
+-  rk3288: Quad-Core Cortex-A17 (past A12)
+-  rk3328: Quad-Core Cortex-A53
+-  rk3368: Octa-Core Cortex-A53
+-  rk3399: Hexa-Core Cortex-A53/A72
+
+
+Boot Sequence
+=============
+
+For AARCH32:
+    Bootrom --> BL1/BL2 --> BL32 --> BL33 --> Linux kernel
+
+For AARCH64:
+    Bootrom --> BL1/BL2 --> BL31 --> BL33 --> Linux kernel
+
+BL1/2 and BL33 can currently be supplied from either:
+-  Coreboot + Depthcharge
+-  U-Boot - either separately as TPL+SPL or only SPL
+
+
+How to build
+============
+
+Rockchip SoCs expect TF-A's BL31 (AARCH64) or BL32 (AARCH32) to get
+integrated with other boot software like U-Boot or Coreboot, so only
+these images need to get build from the TF-A repository.
+
+For AARCH64 architectures the build command looks like
+
+    make CROSS_COMPILE=aarch64-linux-gnu- PLAT=rk3399 bl32
+
+while AARCH32 needs a slightly different command
+
+    make ARCH=aarch32 CROSS_COMPILE=arm-linux-gnueabihf- PLAT=rk3288 AARCH32_SP=sp_min bl32
+
+Both need replacing the PLAT argument with the platform from above you
+want to build for and the CROSS_COMPILE argument with you cross-
+compilation toolchain.
+
+
+How to deploy
+=============
+
+Both upstream U-Boot and Coreboot projects contain instructions on where
+to put the built images during their respective build process.
+So after successfully building TF-A just follow their build instructions
+to continue.
diff --git a/docs/plat/stm32mp1.rst b/docs/plat/stm32mp1.rst
index bfae9cc..1cfdb84 100644
--- a/docs/plat/stm32mp1.rst
+++ b/docs/plat/stm32mp1.rst
@@ -69,20 +69,30 @@
 
 ROM code -> BL2 (compiled with BL2_AT_EL3) -> BL32 (SP_min) -> BL33 (U-Boot)
 
+or if Op-TEE is used:
+
+ROM code -> BL2 (compiled with BL2_AT_EL3) -> OP-TEE -> BL33 (U-Boot)
+
 
 Build Instructions
 ------------------
 
-To build:
+To build with SP_min:
 
 .. code:: bash
 
-    make CROSS_COMPILE=arm-linux-gnueabihf- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 AARCH32_SP=sp_min
+    make CROSS_COMPILE=arm-linux-gnueabihf- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 AARCH32_SP=sp_min DTB_FILE_NAME=stm32mp157c-ev1.dtb
     cd <u-boot_directory>
     make stm32mp15_basic_defconfig
     make DEVICE_TREE=stm32mp157c-ev1 all
     ./tools/mkimage -T stm32image -a 0xC0100000 -e 0xC0100000 -d u-boot.bin u-boot.stm32
 
+To build TF-A with with Op-TEE support:
+
+.. code:: bash
+
+    make CROSS_COMPILE=arm-linux-gnueabihf- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 AARCH32_SP=optee
+
 The following build options are supported:
 
 - ``ENABLE_STACK_PROTECTOR``: To enable the stack protection.
diff --git a/docs/trusted-board-boot.rst b/docs/trusted-board-boot.rst
index 1ca6fef..3ba9636 100644
--- a/docs/trusted-board-boot.rst
+++ b/docs/trusted-board-boot.rst
@@ -12,9 +12,9 @@
 normal world bootloader. It does this by establishing a Chain of Trust using
 Public-Key-Cryptography Standards (PKCS).
 
-This document describes the design of Trusted Firmware-A (TF-A) TBB, which is
-an implementation of the Trusted Board Boot Requirements (TBBR) specification,
-Arm DEN0006C-1. It should be used in conjunction with the `Firmware Update`_
+This document describes the design of Trusted Firmware-A (TF-A) TBB, which is an
+implementation of the `Trusted Board Boot Requirements (TBBR)`_ specification,
+Arm DEN0006D. It should be used in conjunction with the `Firmware Update`_
 design document, which implements a specific aspect of the TBBR.
 
 Chain of Trust
@@ -206,7 +206,7 @@
 
 The authentication framework included in TF-A provides support to implement
 the desired trusted boot sequence. Arm platforms use this framework to
-implement the boot requirements specified in the TBBR-client document.
+implement the boot requirements specified in the `TBBR-client`_ document.
 
 More information about the authentication framework can be found in the
 `Auth Framework`_ document.
@@ -230,9 +230,11 @@
 
 --------------
 
-*Copyright (c) 2015-2018, Arm Limited and Contributors. All rights reserved.*
+*Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved.*
 
 .. _Firmware Update: firmware-update.rst
 .. _X.509 v3: https://tools.ietf.org/rfc/rfc5280.txt
 .. _User Guide: user-guide.rst
 .. _Auth Framework: auth-framework.rst
+.. _TBBR-client: https://developer.arm.com/docs/den0006/latest/trusted-board-boot-requirements-client-tbbr-client-armv8-a
+.. _Trusted Board Boot Requirements (TBBR): `TBBR-client`_
diff --git a/docs/user-guide.rst b/docs/user-guide.rst
index b9f0871..b67a82d 100644
--- a/docs/user-guide.rst
+++ b/docs/user-guide.rst
@@ -359,16 +359,25 @@
    registers to be included when saving and restoring the CPU context. Default
    is 0.
 
--  ``CTX_INCLUDE_PAUTH_REGS``: Boolean option that, when set to 1, enables
-   Pointer Authentication for Secure world. This will cause the ARMv8.3-PAuth
-   registers to be included when saving and restoring the CPU context as
-   part of world switch. Default value is 0 and this is an experimental feature.
-   Note that Pointer Authentication is enabled for Non-secure world irrespective
-   of the value of this flag if the CPU supports it.
+-  ``CTX_INCLUDE_PAUTH_REGS``: Boolean option that, when set to 1, allows
+   Pointer Authentication for **Secure world**. This will cause the
+   Armv8.3-PAuth registers to be included when saving and restoring the CPU
+   context as part of a world switch. Default value is 0. Pointer Authentication
+   is an experimental feature.
+
+   Note that, if the CPU supports it, Pointer Authentication is allowed for
+   Non-secure world irrespectively of the value of this flag. "Allowed" means
+   that accesses to PAuth-related registers or execution of PAuth-related
+   instructions will not be trapped to EL3. As such, usage or not of PAuth in
+   Non-secure world images, depends on those images themselves.
 
 -  ``DEBUG``: Chooses between a debug and release build. It can take either 0
    (release) or 1 (debug) as values. 0 is the default.
 
+-  ``DISABLE_BIN_GENERATION``: Boolean option to disable the generation
+   of the binary image. If set to 1, then only the ELF image is built.
+   0 is the default.
+
 -  ``DYN_DISABLE_AUTH``: Provides the capability to dynamically disable Trusted
    Board Boot authentication at runtime. This option is meant to be enabled only
    for development platforms. ``TRUSTED_BOARD_BOOT`` flag must be set if this
@@ -413,12 +422,12 @@
    partitioning in EL3, however. Platform initialisation code should configure
    and use partitions in EL3 as required. This option defaults to ``0``.
 
--  ``ENABLE_PAUTH``: Boolean option to enable ARMv8.3 Pointer Authentication
-  support for TF-A BL images itself. If enabled, it is needed to use a compiler
-  that supports the option ``-msign-return-address``. This flag defaults to 0
-  and this is an experimental feature.
-  Note that Pointer Authentication is enabled for Non-secure world irrespective
-  of the value of this flag if the CPU supports it.
+-  ``ENABLE_PAUTH``: Boolean option to enable Armv8.3 Pointer Authentication
+   for **TF-A BL images themselves**. If enabled, the compiler must support the
+   ``-msign-return-address`` option. This flag defaults to 0. Pointer
+   Authentication is an experimental feature.
+
+   If this flag is enabled, ``CTX_INCLUDE_PAUTH_REGS`` must also be enabled.
 
 -  ``ENABLE_PIE``: Boolean option to enable Position Independent Executable(PIE)
    support within generic code in TF-A. This option is currently only supported
@@ -460,12 +469,12 @@
    architecture is AArch32.
 
 -  ``ENABLE_STACK_PROTECTOR``: String option to enable the stack protection
-   checks in GCC. Allowed values are "all", "strong" and "0" (default).
-   "strong" is the recommended stack protection level if this feature is
-   desired. 0 disables the stack protection. For all values other than 0, the
-   ``plat_get_stack_protector_canary()`` platform hook needs to be implemented.
-   The value is passed as the last component of the option
-   ``-fstack-protector-$ENABLE_STACK_PROTECTOR``.
+   checks in GCC. Allowed values are "all", "strong", "default" and "none". The
+   default value is set to "none". "strong" is the recommended stack protection
+   level if this feature is desired. "none" disables the stack protection. For
+   all values other than "none", the ``plat_get_stack_protector_canary()``
+   platform hook needs to be implemented. The value is passed as the last
+   component of the option ``-fstack-protector-$ENABLE_STACK_PROTECTOR``.
 
 -  ``ERROR_DEPRECATED``: This option decides whether to treat the usage of
    deprecated platform APIs, helper functions or drivers within Trusted
@@ -530,13 +539,21 @@
 
 -  ``HW_ASSISTED_COHERENCY``: On most Arm systems to-date, platform-specific
    software operations are required for CPUs to enter and exit coherency.
-   However, there exists newer systems where CPUs' entry to and exit from
-   coherency is managed in hardware. Such systems require software to only
-   initiate the operations, and the rest is managed in hardware, minimizing
-   active software management. In such systems, this boolean option enables
-   TF-A to carry out build and run-time optimizations during boot and power
-   management operations. This option defaults to 0 and if it is enabled,
-   then it implies ``WARMBOOT_ENABLE_DCACHE_EARLY`` is also enabled.
+   However, newer systems exist where CPUs' entry to and exit from coherency
+   is managed in hardware. Such systems require software to only initiate these
+   operations, and the rest is managed in hardware, minimizing active software
+   management. In such systems, this boolean option enables TF-A to carry out
+   build and run-time optimizations during boot and power management operations.
+   This option defaults to 0 and if it is enabled, then it implies
+   ``WARMBOOT_ENABLE_DCACHE_EARLY`` is also enabled.
+
+   If this flag is disabled while the platform which TF-A is compiled for
+   includes cores that manage coherency in hardware, then a compilation error is
+   generated. This is based on the fact that a system cannot have, at the same
+   time, cores that manage coherency in hardware and cores that don't. In other
+   words, a platform cannot have, at the same time, cores that require
+   ``HW_ASSISTED_COHERENCY=1`` and cores that require
+   ``HW_ASSISTED_COHERENCY=0``.
 
    Note that, when ``HW_ASSISTED_COHERENCY`` is enabled, version 2 of
    translation library (xlat tables v2) must be used; version 1 of translation
diff --git a/drivers/arm/sbsa/sbsa.c b/drivers/arm/sbsa/sbsa.c
new file mode 100644
index 0000000..6f00a60
--- /dev/null
+++ b/drivers/arm/sbsa/sbsa.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2019, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/common/platform.h>
+#include <drivers/arm/sbsa.h>
+#include <lib/mmio.h>
+#include <stdint_.h>
+#include <assert.h>
+
+void sbsa_watchdog_offset_reg_write(uintptr_t base, uint64_t value)
+{
+	assert((value >> SBSA_WDOG_WOR_WIDTH) == 0);
+	mmio_write_32(base + SBSA_WDOG_WOR_LOW_OFFSET,
+		 ((uint32_t)value & UINT32_MAX));
+	mmio_write_32(base + SBSA_WDOG_WOR_HIGH_OFFSET, (uint32_t)(value >> 32));
+}
+
+/*
+ * Start the watchdog timer at base address "base" for a
+ * period of "ms" milliseconds.The watchdog has to be
+ * refreshed within this time period.
+ */
+void sbsa_wdog_start(uintptr_t base, uint64_t ms)
+{
+	uint64_t counter_freq;
+	uint64_t offset_reg_value;
+
+	counter_freq = (uint64_t)plat_get_syscnt_freq2();
+	offset_reg_value = ms * counter_freq / 1000;
+
+	sbsa_watchdog_offset_reg_write(base, offset_reg_value);
+	mmio_write_32(base + SBSA_WDOG_WCS_OFFSET, SBSA_WDOG_WCS_EN);
+}
+
+/* Stop the watchdog */
+void sbsa_wdog_stop(uintptr_t base)
+{
+	mmio_write_32(base + SBSA_WDOG_WCS_OFFSET, (0x0));
+}
diff --git a/drivers/arm/smmu/smmu_v3.c b/drivers/arm/smmu/smmu_v3.c
index 004e81e..ab2eb2b 100644
--- a/drivers/arm/smmu/smmu_v3.c
+++ b/drivers/arm/smmu/smmu_v3.c
@@ -1,60 +1,55 @@
 /*
- * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <common/debug.h>
 #include <cdefs.h>
-#include <stdbool.h>
-
 #include <drivers/arm/smmu_v3.h>
 #include <lib/mmio.h>
 
-static inline uint32_t __init smmuv3_read_s_idr1(uintptr_t base)
-{
-	return mmio_read_32(base + SMMU_S_IDR1);
-}
+/* SMMU poll number of retries */
+#define SMMU_POLL_RETRY		1000000
 
-static inline uint32_t __init smmuv3_read_s_init(uintptr_t base)
+static int __init smmuv3_poll(uintptr_t smmu_reg, uint32_t mask,
+				uint32_t value)
 {
-	return mmio_read_32(base + SMMU_S_INIT);
-}
+	uint32_t reg_val, retries = SMMU_POLL_RETRY;
 
-static inline void __init smmuv3_write_s_init(uintptr_t base, uint32_t value)
-{
-	mmio_write_32(base + SMMU_S_INIT, value);
-}
+	do {
+		reg_val = mmio_read_32(smmu_reg);
+		if ((reg_val & mask) == value)
+			return 0;
+	} while (--retries != 0U);
 
-/* Test for pending invalidate */
-static inline bool smmuv3_inval_pending(uintptr_t base)
-{
-	return (smmuv3_read_s_init(base) & SMMU_S_INIT_INV_ALL_MASK) != 0U;
+	ERROR("Failed to poll SMMUv3 register @%p\n", (void *)smmu_reg);
+	ERROR("Read value 0x%x, expected 0x%x\n", reg_val,
+		value == 0U ? reg_val & ~mask : reg_val | mask);
+	return -1;
 }
 
 /*
  * Initialize the SMMU by invalidating all secure caches and TLBs.
- *
- * Returns 0 on success, and -1 on failure.
+ * Abort all incoming transactions in order to implement a default
+ * deny policy on reset
  */
 int __init smmuv3_init(uintptr_t smmu_base)
 {
-	uint32_t idr1_reg;
-
 	/*
 	 * Invalidation of secure caches and TLBs is required only if the SMMU
 	 * supports secure state. If not, it's implementation defined as to how
 	 * SMMU_S_INIT register is accessed.
 	 */
-	idr1_reg = smmuv3_read_s_idr1(smmu_base);
-	if (((idr1_reg >> SMMU_S_IDR1_SECURE_IMPL_SHIFT) &
-			SMMU_S_IDR1_SECURE_IMPL_MASK) == 0U) {
-		return -1;
-	}
+	if ((mmio_read_32(smmu_base + SMMU_S_IDR1) &
+			SMMU_S_IDR1_SECURE_IMPL) != 0U) {
 
-	/* Initiate invalidation, and wait for it to finish */
-	smmuv3_write_s_init(smmu_base, SMMU_S_INIT_INV_ALL_MASK);
-	while (smmuv3_inval_pending(smmu_base))
-		;
+		/* Initiate invalidation */
+		mmio_write_32(smmu_base + SMMU_S_INIT, SMMU_S_INIT_INV_ALL);
 
+		/* Wait for global invalidation operation to finish */
+		return smmuv3_poll(smmu_base + SMMU_S_INIT,
+					SMMU_S_INIT_INV_ALL, 0U);
+	}
 	return 0;
 }
diff --git a/drivers/console/multi_console.c b/drivers/console/multi_console.c
index b5ff88b..1ec81c3 100644
--- a/drivers/console/multi_console.c
+++ b/drivers/console/multi_console.c
@@ -20,8 +20,10 @@
 {
 	/* Assert that the struct is not on the stack (common mistake). */
 	assert((console < stacks_start) || (console >= stacks_end));
-	/* Assert that we won't make a circle in the list. */
-	assert(!console_is_registered(console));
+
+	/* Check that we won't make a circle in the list. */
+	if (console_is_registered(console) == 1)
+		return 1;
 
 	console->next = console_list;
 	console_list = console;
diff --git a/drivers/ti/uart/aarch32/16550_console.S b/drivers/ti/uart/aarch32/16550_console.S
new file mode 100644
index 0000000..6921884
--- /dev/null
+++ b/drivers/ti/uart/aarch32/16550_console.S
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <assert_macros.S>
+#include <console_macros.S>
+#include <drivers/ti/uart/uart_16550.h>
+
+	/*
+	 * "core" functions are low-level implementations that don't require
+	 * writable memory and are thus safe to call in BL1 crash context.
+	 */
+	.globl console_16550_core_init
+	.globl console_16550_core_putc
+	.globl console_16550_core_getc
+	.globl console_16550_core_flush
+
+	.globl console_16550_putc
+	.globl console_16550_getc
+	.globl console_16550_flush
+
+	/* -----------------------------------------------
+	 * int console_16550_core_init(uintptr_t base_addr,
+	 * unsigned int uart_clk, unsigned int baud_rate)
+	 * Function to initialize the console without a
+	 * C Runtime to print debug information. This
+	 * function will be accessed by console_init and
+	 * crash reporting.
+	 * In: r0 - console base address
+	 *     r1 - Uart clock in Hz
+	 *     r2 - Baud rate
+	 * Out: return 1 on success, 0 on error
+	 * Clobber list : r1, r2, r3
+	 * -----------------------------------------------
+	 */
+func console_16550_core_init
+	/* Check the input base address */
+	cmp	r0, #0
+	beq	init_fail
+	/* Check baud rate and uart clock for sanity */
+	cmp	r1, #0
+	beq	init_fail
+	cmp	r2, #0
+	beq	init_fail
+
+	/* Program the baudrate */
+	/* Divisor =  Uart clock / (16 * baudrate) */
+	lsl	r2, r2, #4
+	udiv	r2, r1, r2
+	and	r1, r2, #0xff		/* w1 = DLL */
+	lsr	r2, r2, #8
+	and	r2, r2, #0xff		/* w2 = DLLM */
+	ldr	r3, [r0, #UARTLCR]
+	orr	r3, r3, #UARTLCR_DLAB
+	str	r3, [r0, #UARTLCR]	/* enable DLL, DLLM programming */
+	str	r1, [r0, #UARTDLL]	/* program DLL */
+	str	r2, [r0, #UARTDLLM]	/* program DLLM */
+	mov	r2, #~UARTLCR_DLAB
+	and	r3, r3, r2
+	str	r3, [r0, #UARTLCR]	/* disable DLL, DLLM programming */
+
+	/* 8n1 */
+	mov	r3, #3
+	str	r3, [r0, #UARTLCR]
+	/* no interrupt */
+	mov	r3, #0
+	str	r3, [r0, #UARTIER]
+#ifdef TI_16550_MDR_QUIRK
+	/* UART must be enabled on some platforms via the MDR register */
+	str	r3, [r0, #UARTMDR1]
+#endif /* TI_16550_MDR_QUIRK */
+	/* enable fifo, DMA */
+	mov	r3, #(UARTFCR_FIFOEN | UARTFCR_DMAEN)
+	str	r3, [r0, #UARTFCR]
+	/* DTR + RTS */
+	mov	r3, #3
+	str	r3, [r0, #UARTMCR]
+	mov	r0, #1
+	bx	lr
+init_fail:
+	mov	r0, #0
+	bx	lr
+endfunc console_16550_core_init
+
+	.globl console_16550_register
+
+	/* -------------------------------------------------------
+	 * int console_stm32_register(uintptr_t baseaddr,
+	 *     uint32_t clock, uint32_t baud,
+	 *     struct console_stm32 *console);
+	 * Function to initialize and register a new STM32
+	 * console. Storage passed in for the console struct
+	 * *must* be persistent (i.e. not from the stack).
+	 * In: r0 - UART register base address
+	 *     r1 - UART clock in Hz
+	 *     r2 - Baud rate
+	 *     r3 - pointer to empty console_stm32 struct
+	 * Out: return 1 on success, 0 on error
+	 * Clobber list : r0, r1, r2
+	 * -------------------------------------------------------
+	 */
+func console_16550_register
+	push	{r4, lr}
+	mov	r4, r3
+	cmp	r4, #0
+	beq	register_fail
+	str	r0, [r4, #CONSOLE_T_16550_BASE]
+
+	bl	console_16550_core_init
+	cmp	r0, #0
+	beq	register_fail
+
+	mov	r0, r4
+	pop	{r4, lr}
+	finish_console_register 16550 putc=1, getc=1, flush=1
+
+register_fail:
+	pop	{r4, pc}
+endfunc console_16550_register
+
+	/* --------------------------------------------------------
+	 * int console_16550_core_putc(int c, uintptr_t base_addr)
+	 * Function to output a character over the console. It
+	 * returns the character printed on success or -1 on error.
+	 * In : r0 - character to be printed
+	 *      r1 - console base address
+	 * Out : return -1 on error else return character.
+	 * Clobber list : r2
+	 * --------------------------------------------------------
+	 */
+func console_16550_core_putc
+#if ENABLE_ASSERTIONS
+	cmp	r1, #0
+	ASM_ASSERT(ne)
+#endif /* ENABLE_ASSERTIONS */
+
+	/* Prepend '\r' to '\n' */
+	cmp	r0, #0xA
+	bne	2f
+	/* Check if the transmit FIFO is full */
+1:	ldr	r2, [r1, #UARTLSR]
+	and	r2, r2, #(UARTLSR_TEMT | UARTLSR_THRE)
+	cmp	r2, #(UARTLSR_TEMT | UARTLSR_THRE)
+	bne	1b
+	mov	r2, #0xD		/* '\r' */
+	str	r2, [r1, #UARTTX]
+
+	/* Check if the transmit FIFO is full */
+2:	ldr	r2, [r1, #UARTLSR]
+	and	r2, r2, #(UARTLSR_TEMT | UARTLSR_THRE)
+	cmp	r2, #(UARTLSR_TEMT | UARTLSR_THRE)
+	bne	2b
+	str	r0, [r1, #UARTTX]
+	bx	lr
+endfunc console_16550_core_putc
+
+	/* --------------------------------------------------------
+	 * int console_16550_putc(int c, console_16550_t *console)
+	 * Function to output a character over the console. It
+	 * returns the character printed on success or -1 on error.
+	 * In : r0 - character to be printed
+	 *      r1 - pointer to console_t structure
+	 * Out : return -1 on error else return character.
+	 * Clobber list : r2
+	 * --------------------------------------------------------
+	 */
+func console_16550_putc
+#if ENABLE_ASSERTIONS
+	cmp	r1, #0
+	ASM_ASSERT(ne)
+#endif /* ENABLE_ASSERTIONS */
+	ldr	r1, [r1, #CONSOLE_T_16550_BASE]
+	b	console_16550_core_putc
+endfunc console_16550_putc
+
+	/* ---------------------------------------------
+	 * int console_16550_core_getc(uintptr_t base_addr)
+	 * Function to get a character from the console.
+	 * It returns the character grabbed on success
+	 * or -1 on if no character is available.
+	 * In :  r0 - console base address
+	 * Clobber list : r0, r1
+	 * ---------------------------------------------
+	 */
+func console_16550_core_getc
+#if ENABLE_ASSERTIONS
+	cmp	r0, #0
+	ASM_ASSERT(ne)
+#endif /* ENABLE_ASSERTIONS */
+
+	/* Check if the receive FIFO is empty */
+1:	ldr	r1, [r0, #UARTLSR]
+	tst	r1, #UARTLSR_RDR_BIT
+	beq	no_char
+	ldr	r1, [r0, #UARTRX]
+	mov	r0, r1
+	bx	lr
+no_char:
+	mov	r0, #ERROR_NO_PENDING_CHAR
+	bx	lr
+endfunc console_16550_core_getc
+
+	/* ---------------------------------------------
+	 * int console_16550_getc(console_16550_t *console)
+	 * Function to get a character from the console.
+	 * It returns the character grabbed on success
+	 * or -1 on if no character is available.
+	 * In :  r0 - pointer to console_t stucture
+	 * Out : r0 - character if available, else -1
+	 * Clobber list : r0, r1
+	 * ---------------------------------------------
+	 */
+func console_16550_getc
+#if ENABLE_ASSERTIONS
+	cmp	r0, #0
+	ASM_ASSERT(ne)
+#endif /* ENABLE_ASSERTIONS */
+	ldr	r0, [r0, #CONSOLE_T_16550_BASE]
+	b	console_16550_core_getc
+endfunc console_16550_getc
+
+	/* ---------------------------------------------
+	 * int console_16550_core_flush(uintptr_t base_addr)
+	 * Function to force a write of all buffered
+	 * data that hasn't been output.
+	 * In : r0 - console base address
+	 * Out : return -1 on error else return 0.
+	 * Clobber list : r0, r1
+	 * ---------------------------------------------
+	 */
+func console_16550_core_flush
+#if ENABLE_ASSERTIONS
+	cmp	r0, #0
+	ASM_ASSERT(ne)
+#endif /* ENABLE_ASSERTIONS */
+
+	/* Loop until the transmit FIFO is empty */
+1:	ldr	r1, [r0, #UARTLSR]
+	and	r1, r1, #(UARTLSR_TEMT | UARTLSR_THRE)
+	cmp	r1, #(UARTLSR_TEMT | UARTLSR_THRE)
+	bne	1b
+
+	mov	r0, #0
+	bx	lr
+endfunc console_16550_core_flush
+
+	/* ---------------------------------------------
+	 * int console_16550_flush(console_pl011_t *console)
+	 * Function to force a write of all buffered
+	 * data that hasn't been output.
+	 * In : r0 - pointer to console_t structure
+	 * Out : return -1 on error else return 0.
+	 * Clobber list : r0, r1
+	 * ---------------------------------------------
+	 */
+func console_16550_flush
+#if ENABLE_ASSERTIONS
+	cmp	r0, #0
+	ASM_ASSERT(ne)
+#endif /* ENABLE_ASSERTIONS */
+	ldr	r0, [r0, #CONSOLE_T_16550_BASE]
+	b	console_16550_core_flush
+endfunc console_16550_flush
diff --git a/fdts/stm32mp15-ddr.dtsi b/fdts/stm32mp15-ddr.dtsi
index 1a5c51c..4825691 100644
--- a/fdts/stm32mp15-ddr.dtsi
+++ b/fdts/stm32mp15-ddr.dtsi
@@ -5,7 +5,7 @@
 
 / {
 	soc {
-		ddr: ddr@5A003000{
+		ddr: ddr@5a003000{
 
 			compatible = "st,stm32mp1-ddr";
 
diff --git a/fdts/stm32mp157-pinctrl.dtsi b/fdts/stm32mp157-pinctrl.dtsi
index 9dcd7b5..c7553ca 100644
--- a/fdts/stm32mp157-pinctrl.dtsi
+++ b/fdts/stm32mp157-pinctrl.dtsi
@@ -273,6 +273,19 @@
 				};
 			};
 
+			uart4_pins_b: uart4-1 {
+				pins1 {
+					pinmux = <STM32_PINMUX('D', 1, AF8)>; /* UART4_TX */
+					bias-disable;
+					drive-push-pull;
+					slew-rate = <0>;
+				};
+				pins2 {
+					pinmux = <STM32_PINMUX('B', 2, AF8)>; /* UART4_RX */
+					bias-disable;
+				};
+			};
+
 			usart3_pins_a: usart3-0 {
 				pins1 {
 					pinmux = <STM32_PINMUX('B', 10, AF7)>, /* USART3_TX */
diff --git a/fdts/stm32mp157a-avenger96.dts b/fdts/stm32mp157a-avenger96.dts
new file mode 100644
index 0000000..9df72b4
--- /dev/null
+++ b/fdts/stm32mp157a-avenger96.dts
@@ -0,0 +1,283 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (C) Arrow Electronics 2019 - All Rights Reserved
+ * Author: Botond Kardos <botond.kardos@arroweurope.com>
+ *
+ * Copyright (C) Linaro Ltd 2019 - All Rights Reserved
+ * Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+ */
+
+/dts-v1/;
+
+#include "stm32mp157c.dtsi"
+#include "stm32mp157cac-pinctrl.dtsi"
+
+/ {
+	model = "Arrow Electronics STM32MP157A Avenger96 board";
+	compatible = "st,stm32mp157a-avenger96", "st,stm32mp157";
+
+	aliases {
+		serial0 = &uart4;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+};
+
+&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 = <&exti_pwr 55 IRQ_TYPE_EDGE_FALLING>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		status = "okay";
+
+		st,main-control-register = <0x04>;
+		st,vin-control-register = <0xc0>;
+		st,usb-control-register = <0x20>;
+
+		regulators {
+			compatible = "st,stpmic1-regulators";
+
+			ldo1-supply = <&v3v3>;
+			ldo2-supply = <&v3v3>;
+			ldo3-supply = <&vdd_ddr>;
+			ldo5-supply = <&v3v3>;
+			ldo6-supply = <&v3v3>;
+
+			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>;
+			};
+
+			v2v8: ldo2 {
+				regulator-name = "v2v8";
+				regulator-min-microvolt = <2800000>;
+				regulator-max-microvolt = <2800000>;
+			};
+
+			vtt_ddr: ldo3 {
+				regulator-name = "vtt_ddr";
+				regulator-min-microvolt = <500000>;
+				regulator-max-microvolt = <750000>;
+				regulator-always-on;
+				regulator-over-current-protection;
+			};
+
+			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;
+				regulator-over-current-protection;
+			};
+		};
+	};
+};
+
+&iwdg2 {
+	timeout-sec = <32>;
+	status = "okay";
+};
+
+&rng1 {
+	status = "okay";
+};
+
+&rtc {
+	status = "okay";
+};
+
+&sdmmc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_a>;
+	broken-cd;
+	st,sig-dir;
+	st,neg-edge;
+	st,use-ckin;
+	bus-width = <4>;
+	vmmc-supply = <&vdda>;
+	status = "okay";
+};
+
+&uart4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart4_pins_b>;
+	status = "okay";
+};
+
+/* ATF Specific */
+#include <dt-bindings/clock/stm32mp1-clksrc.h>
+#include "stm32mp15-ddr3-2x4Gb-1066-binG.dtsi"
+#include "stm32mp157c-security.dtsi"
+
+/ {
+	aliases {
+		gpio0 = &gpioa;
+		gpio1 = &gpiob;
+		gpio2 = &gpioc;
+		gpio3 = &gpiod;
+		gpio4 = &gpioe;
+		gpio5 = &gpiof;
+		gpio6 = &gpiog;
+		gpio7 = &gpioh;
+		gpio8 = &gpioi;
+		gpio25 = &gpioz;
+		i2c3 = &i2c4;
+	};
+};
+
+/* CLOCK init */
+&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_DISABLED
+	>;
+
+	st,clkdiv = <
+		1 /*MPU*/
+		0 /*AXI*/
+		0 /*MCU*/
+		1 /*APB1*/
+		1 /*APB2*/
+		1 /*APB3*/
+		1 /*APB4*/
+		2 /*APB5*/
+		23 /*RTC*/
+		0 /*MCO1*/
+		0 /*MCO2*/
+	>;
+
+	st,pkcs = <
+		CLK_CKPER_HSE
+		CLK_FMC_ACLK
+		CLK_QSPI_ACLK
+		CLK_ETH_DISABLED
+		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_PLL4Q
+		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 {
+		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 {
+		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 {
+		cfg = < 1 33 1 16 36 PQR(1,1,1) >;
+		frac = < 0x1a04 >;
+	};
+
+	/* VCO = 480.0 MHz => P = 120, Q = 40, R = 96 */
+	pll4: st,pll@3 {
+		cfg = < 1 39 3 11 4 PQR(1,1,1) >;
+	};
+};
diff --git a/fdts/stm32mp157c-security.dtsi b/fdts/stm32mp157c-security.dtsi
index fb04e7d..59119c5 100644
--- a/fdts/stm32mp157c-security.dtsi
+++ b/fdts/stm32mp157c-security.dtsi
@@ -6,7 +6,7 @@
 
 / {
 	soc {
-		stgen: stgen@5C008000 {
+		stgen: stgen@5c008000 {
 			compatible = "st,stm32-stgen";
 			reg = <0x5C008000 0x1000>;
 			status = "okay";
diff --git a/include/arch/aarch64/arch_helpers.h b/include/arch/aarch64/arch_helpers.h
index c3ce1c4..c173706 100644
--- a/include/arch/aarch64/arch_helpers.h
+++ b/include/arch/aarch64/arch_helpers.h
@@ -87,12 +87,13 @@
  * TLB maintenance accessor prototypes
  ******************************************************************************/
 
-#if ERRATA_A57_813419
+#if ERRATA_A57_813419 || ERRATA_A76_1286807
 /*
  * Define function for TLBI instruction with type specifier that implements
- * the workaround for errata 813419 of Cortex-A57.
+ * the workaround for errata 813419 of Cortex-A57 or errata 1286807 of
+ * Cortex-A76.
  */
-#define DEFINE_TLBIOP_ERRATA_A57_813419_TYPE_FUNC(_type)\
+#define DEFINE_TLBIOP_ERRATA_TYPE_FUNC(_type)\
 static inline void tlbi ## _type(void)			\
 {							\
 	__asm__("tlbi " #_type "\n"			\
@@ -102,9 +103,10 @@
 
 /*
  * Define function for TLBI instruction with register parameter that implements
- * the workaround for errata 813419 of Cortex-A57.
+ * the workaround for errata 813419 of Cortex-A57 or errata 1286807 of
+ * Cortex-A76.
  */
-#define DEFINE_TLBIOP_ERRATA_A57_813419_TYPE_PARAM_FUNC(_type)	\
+#define DEFINE_TLBIOP_ERRATA_TYPE_PARAM_FUNC(_type)	\
 static inline void tlbi ## _type(uint64_t v)			\
 {								\
 	__asm__("tlbi " #_type ", %0\n"				\
@@ -125,27 +127,51 @@
 }
 #endif /* ERRATA_A53_819472 || ERRATA_A53_824069 || ERRATA_A53_827319 */
 
+#if ERRATA_A57_813419
 DEFINE_SYSOP_TYPE_FUNC(tlbi, alle1)
 DEFINE_SYSOP_TYPE_FUNC(tlbi, alle1is)
 DEFINE_SYSOP_TYPE_FUNC(tlbi, alle2)
 DEFINE_SYSOP_TYPE_FUNC(tlbi, alle2is)
-#if ERRATA_A57_813419
-DEFINE_TLBIOP_ERRATA_A57_813419_TYPE_FUNC(alle3)
-DEFINE_TLBIOP_ERRATA_A57_813419_TYPE_FUNC(alle3is)
+DEFINE_TLBIOP_ERRATA_TYPE_FUNC(alle3)
+DEFINE_TLBIOP_ERRATA_TYPE_FUNC(alle3is)
+DEFINE_SYSOP_TYPE_FUNC(tlbi, vmalle1)
+#elif ERRATA_A76_1286807
+DEFINE_TLBIOP_ERRATA_TYPE_FUNC(alle1)
+DEFINE_TLBIOP_ERRATA_TYPE_FUNC(alle1is)
+DEFINE_TLBIOP_ERRATA_TYPE_FUNC(alle2)
+DEFINE_TLBIOP_ERRATA_TYPE_FUNC(alle2is)
+DEFINE_TLBIOP_ERRATA_TYPE_FUNC(alle3)
+DEFINE_TLBIOP_ERRATA_TYPE_FUNC(alle3is)
+DEFINE_TLBIOP_ERRATA_TYPE_FUNC(vmalle1)
 #else
+DEFINE_SYSOP_TYPE_FUNC(tlbi, alle1)
+DEFINE_SYSOP_TYPE_FUNC(tlbi, alle1is)
+DEFINE_SYSOP_TYPE_FUNC(tlbi, alle2)
+DEFINE_SYSOP_TYPE_FUNC(tlbi, alle2is)
 DEFINE_SYSOP_TYPE_FUNC(tlbi, alle3)
 DEFINE_SYSOP_TYPE_FUNC(tlbi, alle3is)
-#endif
 DEFINE_SYSOP_TYPE_FUNC(tlbi, vmalle1)
+#endif
 
+#if ERRATA_A57_813419
 DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vaae1is)
 DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vaale1is)
 DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vae2is)
 DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vale2is)
-#if ERRATA_A57_813419
-DEFINE_TLBIOP_ERRATA_A57_813419_TYPE_PARAM_FUNC(vae3is)
-DEFINE_TLBIOP_ERRATA_A57_813419_TYPE_PARAM_FUNC(vale3is)
+DEFINE_TLBIOP_ERRATA_TYPE_PARAM_FUNC(vae3is)
+DEFINE_TLBIOP_ERRATA_TYPE_PARAM_FUNC(vale3is)
+#elif ERRATA_A76_1286807
+DEFINE_TLBIOP_ERRATA_TYPE_PARAM_FUNC(vaae1is)
+DEFINE_TLBIOP_ERRATA_TYPE_PARAM_FUNC(vaale1is)
+DEFINE_TLBIOP_ERRATA_TYPE_PARAM_FUNC(vae2is)
+DEFINE_TLBIOP_ERRATA_TYPE_PARAM_FUNC(vale2is)
+DEFINE_TLBIOP_ERRATA_TYPE_PARAM_FUNC(vae3is)
+DEFINE_TLBIOP_ERRATA_TYPE_PARAM_FUNC(vale3is)
 #else
+DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vaae1is)
+DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vaale1is)
+DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vae2is)
+DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vale2is)
 DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vae3is)
 DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vale3is)
 #endif
diff --git a/include/arch/aarch64/asm_macros.S b/include/arch/aarch64/asm_macros.S
index 387be4c..9b12185 100644
--- a/include/arch/aarch64/asm_macros.S
+++ b/include/arch/aarch64/asm_macros.S
@@ -12,9 +12,9 @@
 
 /*
  * TLBI instruction with type specifier that implements the workaround for
- * errata 813419 of Cortex-A57.
+ * errata 813419 of Cortex-A57 or errata 1286807 of Cortex-A76.
  */
-#if ERRATA_A57_813419
+#if ERRATA_A57_813419 || ERRATA_A76_1286807
 #define TLB_INVALIDATE(_type) \
 	tlbi	_type; \
 	dsb	ish; \
diff --git a/include/bl32/sp_min/platform_sp_min.h b/include/bl32/sp_min/platform_sp_min.h
index feb4ec3..971f661 100644
--- a/include/bl32/sp_min/platform_sp_min.h
+++ b/include/bl32/sp_min/platform_sp_min.h
@@ -18,6 +18,7 @@
 void sp_min_plat_runtime_setup(void);
 void sp_min_plat_arch_setup(void);
 entry_point_info_t *sp_min_plat_get_bl33_ep_info(void);
+void sp_min_warm_entrypoint(void);
 
 /* Platforms that enable SP_MIN_WITH_SECURE_FIQ shall implement this api */
 void sp_min_plat_fiq_handler(uint32_t id);
diff --git a/include/drivers/arm/sbsa.h b/include/drivers/arm/sbsa.h
new file mode 100644
index 0000000..9403634
--- /dev/null
+++ b/include/drivers/arm/sbsa.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2019, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SBSA_H
+#define SBSA_H
+
+#include <stdint.h>
+
+/* Register Offsets */
+#define SBSA_WDOG_WCS_OFFSET		UL(0x000)
+#define SBSA_WDOG_WOR_LOW_OFFSET	UL(0x008)
+#define SBSA_WDOG_WOR_HIGH_OFFSET	UL(0x00C)
+
+#define SBSA_WDOG_WCS_EN		U(0x1)
+
+#define SBSA_WDOG_WOR_WIDTH		UL(48)
+
+void sbsa_wdog_start(uintptr_t base, uint64_t ms);
+void sbsa_wdog_stop(uintptr_t base);
+
+#endif /* SBSA_H */
diff --git a/include/drivers/arm/smmu_v3.h b/include/drivers/arm/smmu_v3.h
index 33f3d6f..75c9465 100644
--- a/include/drivers/arm/smmu_v3.h
+++ b/include/drivers/arm/smmu_v3.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -8,20 +8,27 @@
 #define SMMU_V3_H
 
 #include <stdint.h>
-
 #include <lib/utils_def.h>
 
 /* SMMUv3 register offsets from device base */
+#define SMMU_GBPA	U(0x0044)
 #define SMMU_S_IDR1	U(0x8004)
 #define SMMU_S_INIT	U(0x803c)
+#define SMMU_S_GBPA	U(0x8044)
+
+/* SMMU_GBPA register fields */
+#define SMMU_GBPA_UPDATE		(1UL << 31)
+#define SMMU_GBPA_ABORT			(1UL << 20)
 
 /* SMMU_S_IDR1 register fields */
-#define SMMU_S_IDR1_SECURE_IMPL_SHIFT	31
-#define SMMU_S_IDR1_SECURE_IMPL_MASK	U(0x1)
+#define SMMU_S_IDR1_SECURE_IMPL		(1UL << 31)
 
 /* SMMU_S_INIT register fields */
-#define SMMU_S_INIT_INV_ALL_MASK	U(0x1)
+#define SMMU_S_INIT_INV_ALL		(1UL << 0)
 
+/* SMMU_S_GBPA register fields */
+#define SMMU_S_GBPA_UPDATE		(1UL << 31)
+#define SMMU_S_GBPA_ABORT		(1UL << 20)
 
 int smmuv3_init(uintptr_t smmu_base);
 
diff --git a/include/lib/cpus/aarch64/cortex_a76.h b/include/lib/cpus/aarch64/cortex_a76.h
index c2af8ca..7dc7e06 100644
--- a/include/lib/cpus/aarch64/cortex_a76.h
+++ b/include/lib/cpus/aarch64/cortex_a76.h
@@ -19,6 +19,7 @@
 #define CORTEX_A76_CPUECTLR_EL1		S3_0_C15_C1_4
 
 #define CORTEX_A76_CPUECTLR_EL1_WS_THR_L2	(ULL(3) << 24)
+#define CORTEX_A76_CPUECTLR_EL1_BIT_51		(ULL(1) << 51)
 
 /*******************************************************************************
  * CPU Auxiliary Control register specific definitions.
@@ -27,10 +28,17 @@
 
 #define CORTEX_A76_CPUACTLR_EL1_DISABLE_STATIC_PREDICTION	(ULL(1) << 6)
 
+#define CORTEX_A76_CPUACTLR_EL1_BIT_13	(ULL(1) << 13)
+
 #define CORTEX_A76_CPUACTLR2_EL1	S3_0_C15_C1_1
 
 #define CORTEX_A76_CPUACTLR2_EL1_DISABLE_LOAD_PASS_STORE	(ULL(1) << 16)
 
+#define CORTEX_A76_CPUACTLR3_EL1	S3_0_C15_C1_2
+
+#define CORTEX_A76_CPUACTLR3_EL1_BIT_10	(ULL(1) << 10)
+
+
 /* Definitions of register field mask in CORTEX_A76_CPUPWRCTLR_EL1 */
 #define CORTEX_A76_CORE_PWRDN_EN_MASK	U(0x1)
 
diff --git a/include/lib/cpus/aarch64/neoverse_n1.h b/include/lib/cpus/aarch64/neoverse_n1.h
index 908993e..ed5f136 100644
--- a/include/lib/cpus/aarch64/neoverse_n1.h
+++ b/include/lib/cpus/aarch64/neoverse_n1.h
@@ -13,10 +13,9 @@
 #define NEOVERSE_N1_MIDR		U(0x410fd0c0)
 
 /*******************************************************************************
- * CPU Extended Control register specific definitions.
+ * CPU Power Control register specific definitions.
  ******************************************************************************/
 #define NEOVERSE_N1_CPUPWRCTLR_EL1	S3_0_C15_C2_7
-#define NEOVERSE_N1_CPUECTLR_EL1	S3_0_C15_C1_4
 
 /* Definitions of register field mask in NEOVERSE_N1_CPUPWRCTLR_EL1 */
 #define NEOVERSE_N1_CORE_PWRDN_EN_MASK	U(0x1)
@@ -26,6 +25,18 @@
 #define NEOVERSE_N1_AMU_NR_COUNTERS	U(5)
 #define NEOVERSE_N1_AMU_GROUP0_MASK	U(0x1f)
 
+/*******************************************************************************
+ * CPU Extended Control register specific definitions.
+ ******************************************************************************/
+#define NEOVERSE_N1_CPUECTLR_EL1	S3_0_C15_C1_4
+
+/*******************************************************************************
+ * CPU Auxiliary Control register specific definitions.
+ ******************************************************************************/
+#define NEOVERSE_N1_CPUACTLR2_EL1	S3_0_C15_C1_1
+
+#define NEOVERSE_N1_CPUACTLR2_EL1_BIT_2	(ULL(1) << 2)
+
 /* Instruction patching registers */
 #define CPUPSELR_EL3	S3_6_C15_C8_0
 #define CPUPCR_EL3	S3_6_C15_C8_1
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index 527375f..97e6722 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -295,4 +295,8 @@
 extern const mmap_region_t plat_arm_mmap[];
 extern const unsigned int arm_pm_idle_states[];
 
+/* secure watchdog */
+void plat_arm_secure_wdt_start(void);
+void plat_arm_secure_wdt_stop(void);
+
 #endif /* PLAT_ARM_H */
diff --git a/lib/cpus/aarch64/cortex_a53.S b/lib/cpus/aarch64/cortex_a53.S
index f20082d..6fd3c53 100644
--- a/lib/cpus/aarch64/cortex_a53.S
+++ b/lib/cpus/aarch64/cortex_a53.S
@@ -45,31 +45,35 @@
 	/* ---------------------------------------------------
 	 * Errata Workaround for Cortex A53 Errata #819472.
 	 * This applies only to revision <= r0p1 of Cortex A53.
+	 * Due to the nature of the errata it is applied unconditionally
+	 * when built in, report it as applicable in this case
 	 * ---------------------------------------------------
 	 */
 func check_errata_819472
-	/*
-	 * Even though this is only needed for revision <= r0p1, it
-	 * is always applied due to limitations of the current
-	 * errata framework.
-	 */
-	mov	x0, #ERRATA_APPLIES
+#if ERRATA_A53_819472
+	mov x0, #ERRATA_APPLIES
 	ret
+#else
+	mov	x1, #0x01
+	b	cpu_rev_var_ls
+#endif
 endfunc check_errata_819472
 
 	/* ---------------------------------------------------
 	 * Errata Workaround for Cortex A53 Errata #824069.
 	 * This applies only to revision <= r0p2 of Cortex A53.
+	 * Due to the nature of the errata it is applied unconditionally
+	 * when built in, report it as applicable in this case
 	 * ---------------------------------------------------
 	 */
 func check_errata_824069
-	/*
-	 * Even though this is only needed for revision <= r0p2, it
-	 * is always applied due to limitations of the current
-	 * errata framework.
-	 */
-	mov	x0, #ERRATA_APPLIES
+#if ERRATA_A53_824069
+	mov x0, #ERRATA_APPLIES
 	ret
+#else
+	mov	x1, #0x02
+	b	cpu_rev_var_ls
+#endif
 endfunc check_errata_824069
 
 	/* --------------------------------------------------
@@ -103,16 +107,18 @@
 	/* ---------------------------------------------------
 	 * Errata Workaround for Cortex A53 Errata #827319.
 	 * This applies only to revision <= r0p2 of Cortex A53.
+	 * Due to the nature of the errata it is applied unconditionally
+	 * when built in, report it as applicable in this case
 	 * ---------------------------------------------------
 	 */
 func check_errata_827319
-	/*
-	 * Even though this is only needed for revision <= r0p2, it
-	 * is always applied due to limitations of the current
-	 * errata framework.
-	 */
-	mov	x0, #ERRATA_APPLIES
+#if ERRATA_A53_827319
+	mov x0, #ERRATA_APPLIES
 	ret
+#else
+	mov	x1, #0x02
+	b	cpu_rev_var_ls
+#endif
 endfunc check_errata_827319
 
 	/* ---------------------------------------------------------------------
diff --git a/lib/cpus/aarch64/cortex_a55.S b/lib/cpus/aarch64/cortex_a55.S
index b9a3f36..0ef373a 100644
--- a/lib/cpus/aarch64/cortex_a55.S
+++ b/lib/cpus/aarch64/cortex_a55.S
@@ -11,6 +11,11 @@
 #include <cpu_macros.S>
 #include <plat_macros.S>
 
+/* Hardware handled coherency */
+#if HW_ASSISTED_COHERENCY == 0
+#error "Cortex-A55 must be compiled with HW_ASSISTED_COHERENCY enabled"
+#endif
+
 	/* --------------------------------------------------
 	 * Errata Workaround for Cortex A55 Errata #768277.
 	 * This applies only to revision r0p0 of Cortex A55.
diff --git a/lib/cpus/aarch64/cortex_a75.S b/lib/cpus/aarch64/cortex_a75.S
index fda1aec..657457e 100644
--- a/lib/cpus/aarch64/cortex_a75.S
+++ b/lib/cpus/aarch64/cortex_a75.S
@@ -10,6 +10,11 @@
 #include <cpuamu.h>
 #include <cpu_macros.S>
 
+/* Hardware handled coherency */
+#if HW_ASSISTED_COHERENCY == 0
+#error "Cortex-A75 must be compiled with HW_ASSISTED_COHERENCY enabled"
+#endif
+
 	/* --------------------------------------------------
 	 * Errata Workaround for Cortex A75 Errata #764081.
 	 * This applies only to revision r0p0 of Cortex A75.
diff --git a/lib/cpus/aarch64/cortex_a76.S b/lib/cpus/aarch64/cortex_a76.S
index 4bf6e77..b48283c 100644
--- a/lib/cpus/aarch64/cortex_a76.S
+++ b/lib/cpus/aarch64/cortex_a76.S
@@ -13,6 +13,11 @@
 #include <plat_macros.S>
 #include <services/arm_arch_svc.h>
 
+/* Hardware handled coherency */
+#if HW_ASSISTED_COHERENCY == 0
+#error "Cortex-A76 must be compiled with HW_ASSISTED_COHERENCY enabled"
+#endif
+
 #define ESR_EL3_A64_SMC0	0x5e000000
 #define ESR_EL3_A32_SMC0	0x4e000000
 
@@ -208,7 +213,7 @@
 	isb
 1:
 	ret	x17
-	endfunc errata_a76_1073348_wa
+endfunc errata_a76_1073348_wa
 
 func check_errata_1073348
 	mov	x1, #0x10
@@ -271,6 +276,117 @@
 	b	cpu_rev_var_ls
 endfunc check_errata_1220197
 
+	/* --------------------------------------------------
+	 * Errata Workaround for Cortex A76 Errata #1257314.
+	 * This applies only to revision <= r3p0 of Cortex A76.
+	 * Inputs:
+	 * x0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber: x0-x17
+	 * --------------------------------------------------
+	 */
+func errata_a76_1257314_wa
+	/*
+	 * Compare x0 against revision r3p0
+	 */
+	mov	x17, x30
+	bl	check_errata_1257314
+	cbz	x0, 1f
+	mrs	x1, CORTEX_A76_CPUACTLR3_EL1
+	orr	x1, x1, CORTEX_A76_CPUACTLR3_EL1_BIT_10
+	msr	CORTEX_A76_CPUACTLR3_EL1, x1
+	isb
+1:
+	ret	x17
+endfunc errata_a76_1257314_wa
+
+func check_errata_1257314
+	mov	x1, #0x30
+	b	cpu_rev_var_ls
+endfunc check_errata_1257314
+
+	/* --------------------------------------------------
+	 * Errata Workaround for Cortex A76 Errata #1262888.
+	 * This applies only to revision <= r3p0 of Cortex A76.
+	 * Inputs:
+	 * x0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber: x0-x17
+	 * --------------------------------------------------
+	 */
+func errata_a76_1262888_wa
+	/*
+	 * Compare x0 against revision r3p0
+	 */
+	mov	x17, x30
+	bl	check_errata_1262888
+	cbz	x0, 1f
+	mrs	x1, CORTEX_A76_CPUECTLR_EL1
+	orr	x1, x1, CORTEX_A76_CPUECTLR_EL1_BIT_51
+	msr	CORTEX_A76_CPUECTLR_EL1, x1
+	isb
+1:
+	ret	x17
+endfunc errata_a76_1262888_wa
+
+func check_errata_1262888
+	mov	x1, #0x30
+	b	cpu_rev_var_ls
+endfunc check_errata_1262888
+
+	/* --------------------------------------------------
+	 * Errata Workaround for Cortex A76 Errata #1275112
+	 * and Errata #1262606.
+	 * This applies only to revision <= r3p0 of Cortex A76.
+	 * Inputs:
+	 * x0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber: x0-x17
+	 * --------------------------------------------------
+	 */
+func errata_a76_1275112_1262606_wa
+	/*
+	 * Compare x0 against revision r3p0
+	 */
+	mov	x17, x30
+	/*
+	 * Since both errata #1275112 and #1262606 have the same check, we can
+	 * invoke any one of them for the check here.
+	 */
+	bl	check_errata_1275112
+	cbz	x0, 1f
+	mrs	x1, CORTEX_A76_CPUACTLR_EL1
+	orr	x1, x1, CORTEX_A76_CPUACTLR_EL1_BIT_13
+	msr	CORTEX_A76_CPUACTLR_EL1, x1
+	isb
+1:
+	ret	x17
+endfunc errata_a76_1275112_1262606_wa
+
+func check_errata_1262606
+	mov	x1, #0x30
+	b	cpu_rev_var_ls
+endfunc check_errata_1262606
+
+func check_errata_1275112
+	mov	x1, #0x30
+	b	cpu_rev_var_ls
+endfunc check_errata_1275112
+
+	/* ---------------------------------------------------
+	 * Errata Workaround for Cortex A76 Errata #1286807.
+	 * This applies only to revision <= r3p0 of Cortex A76.
+	 * Due to the nature of the errata it is applied unconditionally
+	 * when built in, report it as applicable in this case
+	 * ---------------------------------------------------
+	 */
+func check_errata_1286807
+#if ERRATA_A76_1286807
+	mov x0, #ERRATA_APPLIES
+	ret
+#else
+	mov	x1, #0x30
+	b	cpu_rev_var_ls
+#endif
+endfunc check_errata_1286807
+
 func check_errata_cve_2018_3639
 #if WORKAROUND_CVE_2018_3639
 	mov	x0, #ERRATA_APPLIES
@@ -313,6 +429,21 @@
 	bl	errata_a76_1220197_wa
 #endif
 
+#if ERRATA_A76_1257314
+	mov	x0, x18
+	bl	errata_a76_1257314_wa
+#endif
+
+#if ERRATA_A76_1262606 || ERRATA_A76_1275112
+	mov	x0, x18
+	bl	errata_a76_1275112_1262606_wa
+#endif
+
+#if ERRATA_A76_1262888
+	mov	x0, x18
+	bl	errata_a76_1262888_wa
+#endif
+
 #if WORKAROUND_CVE_2018_3639
 	/* If the PE implements SSBS, we don't need the dynamic workaround */
 	mrs	x0, id_aa64pfr1_el1
@@ -388,6 +519,11 @@
 	report_errata ERRATA_A76_1073348, cortex_a76, 1073348
 	report_errata ERRATA_A76_1130799, cortex_a76, 1130799
 	report_errata ERRATA_A76_1220197, cortex_a76, 1220197
+	report_errata ERRATA_A76_1257314, cortex_a76, 1257314
+	report_errata ERRATA_A76_1262606, cortex_a76, 1262606
+	report_errata ERRATA_A76_1262888, cortex_a76, 1262888
+	report_errata ERRATA_A76_1275112, cortex_a76, 1275112
+	report_errata ERRATA_A76_1286807, cortex_a76, 1286807
 	report_errata WORKAROUND_CVE_2018_3639, cortex_a76, cve_2018_3639
 	report_errata ERRATA_DSU_798953, cortex_a76, dsu_798953
 	report_errata ERRATA_DSU_936184, cortex_a76, dsu_936184
diff --git a/lib/cpus/aarch64/cortex_a76ae.S b/lib/cpus/aarch64/cortex_a76ae.S
index 1ba8e9a..46e9450 100644
--- a/lib/cpus/aarch64/cortex_a76ae.S
+++ b/lib/cpus/aarch64/cortex_a76ae.S
@@ -8,6 +8,11 @@
 #include <cortex_a76ae.h>
 #include <cpu_macros.S>
 
+/* Hardware handled coherency */
+#if HW_ASSISTED_COHERENCY == 0
+#error "Cortex-A76AE must be compiled with HW_ASSISTED_COHERENCY enabled"
+#endif
+
 	/* ---------------------------------------------
 	 * HW will do the cache maintenance while powering down
 	 * ---------------------------------------------
diff --git a/lib/cpus/aarch64/cortex_deimos.S b/lib/cpus/aarch64/cortex_deimos.S
index 0e72fba..e73e89f 100644
--- a/lib/cpus/aarch64/cortex_deimos.S
+++ b/lib/cpus/aarch64/cortex_deimos.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -11,6 +11,11 @@
 #include <cpu_macros.S>
 #include <plat_macros.S>
 
+/* Hardware handled coherency */
+#if HW_ASSISTED_COHERENCY == 0
+#error "Deimos must be compiled with HW_ASSISTED_COHERENCY enabled"
+#endif
+
 	/* ---------------------------------------------
 	 * HW will do the cache maintenance while powering down
 	 * ---------------------------------------------
diff --git a/lib/cpus/aarch64/neoverse_e1.S b/lib/cpus/aarch64/neoverse_e1.S
index 8e40306..71e7b51 100644
--- a/lib/cpus/aarch64/neoverse_e1.S
+++ b/lib/cpus/aarch64/neoverse_e1.S
@@ -11,6 +11,11 @@
 #include <cpu_macros.S>
 #include <plat_macros.S>
 
+/* Hardware handled coherency */
+#if HW_ASSISTED_COHERENCY == 0
+#error "Neoverse E1 must be compiled with HW_ASSISTED_COHERENCY enabled"
+#endif
+
 func neoverse_e1_cpu_pwr_dwn
 	mrs	x0, NEOVERSE_E1_CPUPWRCTLR_EL1
 	orr	x0, x0, #NEOVERSE_E1_CPUPWRCTLR_EL1_CORE_PWRDN_BIT
diff --git a/lib/cpus/aarch64/neoverse_n1.S b/lib/cpus/aarch64/neoverse_n1.S
index 060c625..2038f31 100644
--- a/lib/cpus/aarch64/neoverse_n1.S
+++ b/lib/cpus/aarch64/neoverse_n1.S
@@ -10,6 +10,11 @@
 #include <cpuamu.h>
 #include <cpu_macros.S>
 
+/* Hardware handled coherency */
+#if HW_ASSISTED_COHERENCY == 0
+#error "Neoverse N1 must be compiled with HW_ASSISTED_COHERENCY enabled"
+#endif
+
 /* --------------------------------------------------
  * Errata Workaround for Neoverse N1 Errata
  * This applies to revision r0p0 and r1p0 of Neoverse N1.
@@ -50,6 +55,12 @@
 	/* Disables speculative loads */
 	msr	SSBS, xzr
 
+	/* Forces all cacheable atomic instructions to be near */
+	mrs	x0, NEOVERSE_N1_CPUACTLR2_EL1
+	orr	x0, x0, #NEOVERSE_N1_CPUACTLR2_EL1_BIT_2
+	msr	NEOVERSE_N1_CPUACTLR2_EL1, x0
+	isb
+
 	bl	cpu_get_rev_var
 	mov	x18, x0
 
diff --git a/lib/cpus/aarch64/neoverse_zeus.S b/lib/cpus/aarch64/neoverse_zeus.S
index 79c8b2f..c5241af 100644
--- a/lib/cpus/aarch64/neoverse_zeus.S
+++ b/lib/cpus/aarch64/neoverse_zeus.S
@@ -11,6 +11,11 @@
 #include <cpu_macros.S>
 #include <plat_macros.S>
 
+/* Hardware handled coherency */
+#if HW_ASSISTED_COHERENCY == 0
+#error "Neoverse Zeus must be compiled with HW_ASSISTED_COHERENCY enabled"
+#endif
+
 	/* ---------------------------------------------
 	 * HW will do the cache maintenance while powering down
 	 * ---------------------------------------------
diff --git a/lib/cpus/cpu-ops.mk b/lib/cpus/cpu-ops.mk
index 4deb262..e45d79d 100644
--- a/lib/cpus/cpu-ops.mk
+++ b/lib/cpus/cpu-ops.mk
@@ -210,6 +210,26 @@
 # only to revision <= r2p0 of the Cortex A76 cpu.
 ERRATA_A76_1220197	?=0
 
+# Flag to apply erratum 1257314 workaround during reset. This erratum applies
+# only to revision <= r3p0 of the Cortex A76 cpu.
+ERRATA_A76_1257314	?=0
+
+# Flag to apply erratum 1262606 workaround during reset. This erratum applies
+# only to revision <= r3p0 of the Cortex A76 cpu.
+ERRATA_A76_1262606	?=0
+
+# Flag to apply erratum 1262888 workaround during reset. This erratum applies
+# only to revision <= r3p0 of the Cortex A76 cpu.
+ERRATA_A76_1262888	?=0
+
+# Flag to apply erratum 1275112 workaround during reset. This erratum applies
+# only to revision <= r3p0 of the Cortex A76 cpu.
+ERRATA_A76_1275112	?=0
+
+# Flag to apply erratum 1286807 workaround during reset. This erratum applies
+# only to revision <= r3p0 of the Cortex A76 cpu.
+ERRATA_A76_1286807	?=0
+
 # Flag to apply T32 CLREX workaround during reset. This erratum applies
 # only to r0p0 and r1p0 of the Neoverse N1 cpu.
 ERRATA_N1_1043202	?=1
@@ -375,6 +395,26 @@
 $(eval $(call assert_boolean,ERRATA_A76_1220197))
 $(eval $(call add_define,ERRATA_A76_1220197))
 
+# Process ERRATA_A76_1257314 flag
+$(eval $(call assert_boolean,ERRATA_A76_1257314))
+$(eval $(call add_define,ERRATA_A76_1257314))
+
+# Process ERRATA_A76_1262606 flag
+$(eval $(call assert_boolean,ERRATA_A76_1262606))
+$(eval $(call add_define,ERRATA_A76_1262606))
+
+# Process ERRATA_A76_1262888 flag
+$(eval $(call assert_boolean,ERRATA_A76_1262888))
+$(eval $(call add_define,ERRATA_A76_1262888))
+
+# Process ERRATA_A76_1275112 flag
+$(eval $(call assert_boolean,ERRATA_A76_1275112))
+$(eval $(call add_define,ERRATA_A76_1275112))
+
+# Process ERRATA_A76_1286807 flag
+$(eval $(call assert_boolean,ERRATA_A76_1286807))
+$(eval $(call add_define,ERRATA_A76_1286807))
+
 # Process ERRATA_N1_1043202 flag
 $(eval $(call assert_boolean,ERRATA_N1_1043202))
 $(eval $(call add_define,ERRATA_N1_1043202))
diff --git a/lib/stack_protector/stack_protector.mk b/lib/stack_protector/stack_protector.mk
index 0f0d90f..94e804b 100644
--- a/lib/stack_protector/stack_protector.mk
+++ b/lib/stack_protector/stack_protector.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -7,13 +7,20 @@
 # Boolean macro to be used in C code
 STACK_PROTECTOR_ENABLED := 0
 
-ifneq (${ENABLE_STACK_PROTECTOR},0)
-STACK_PROTECTOR_ENABLED := 1
-BL_COMMON_SOURCES	+=	lib/stack_protector/stack_protector.c			\
+ifeq (${ENABLE_STACK_PROTECTOR},0)
+  ENABLE_STACK_PROTECTOR := none
+endif
+
+ifneq (${ENABLE_STACK_PROTECTOR},none)
+  STACK_PROTECTOR_ENABLED := 1
+  BL_COMMON_SOURCES	+=	lib/stack_protector/stack_protector.c	\
 				lib/stack_protector/${ARCH}/asm_stack_protector.S
 
-TF_CFLAGS		+=	-fstack-protector-${ENABLE_STACK_PROTECTOR}
+  ifeq (${ENABLE_STACK_PROTECTOR},default)
+    TF_CFLAGS		+=	-fstack-protector
+  else
+    TF_CFLAGS		+=	-fstack-protector-${ENABLE_STACK_PROTECTOR}
+  endif
 endif
 
 $(eval $(call add_define,STACK_PROTECTOR_ENABLED))
-
diff --git a/maintainers.rst b/maintainers.rst
index 52c3dac..4bee64c 100644
--- a/maintainers.rst
+++ b/maintainers.rst
@@ -208,6 +208,8 @@
 :M: Tony Xie <tony.xie@rock-chips.com>
 :G: `TonyXie06`_
 :G: `rockchip-linux`_
+:M: Heiko Stuebner <heiko@sntech.de>
+:G: `mmind`_
 :F: plat/rockchip/
 
 STM32MP1 platform port
@@ -277,6 +279,7 @@
 .. _niej: https://github.com/niej
 .. _kostapr: https://github.com/kostapr
 .. _masahir0y: https://github.com/masahir0y
+.. _mmind: https://github.com/mmind
 .. _mtk09422: https://github.com/mtk09422
 .. _npoushin: https://github.com/npoushin
 .. _qoriq-open-source: https://github.com/qoriq-open-source
diff --git a/make_helpers/build_macros.mk b/make_helpers/build_macros.mk
index 5d33954..2d41b2d 100644
--- a/make_helpers/build_macros.mk
+++ b/make_helpers/build_macros.mk
@@ -438,6 +438,11 @@
 		--script $(LINKERFILE) $(BUILD_DIR)/build_message.o \
 		$(OBJS) $(LDPATHS) $(LIBWRAPPER) $(LDLIBS) $(BL_LIBS)
 endif
+ifeq ($(DISABLE_BIN_GENERATION),1)
+	@${ECHO_BLANK_LINE}
+	@echo "Built $$@ successfully"
+	@${ECHO_BLANK_LINE}
+endif
 
 $(DUMP): $(ELF)
 	$${ECHO} "  OD      $$@"
@@ -451,7 +456,11 @@
 	@${ECHO_BLANK_LINE}
 
 .PHONY: bl$(1)
+ifeq ($(DISABLE_BIN_GENERATION),1)
+bl$(1): $(ELF) $(DUMP)
+else
 bl$(1): $(BIN) $(DUMP)
+endif
 
 all: bl$(1)
 
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index be84f77..dc797ed 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -62,6 +62,9 @@
 # Build platform
 DEFAULT_PLAT			:= fvp
 
+# Disable the generation of the binary image (ELF only).
+DISABLE_BIN_GENERATION		:= 0
+
 # Enable capability to disable authentication dynamically. Only meant for
 # development platforms.
 DYN_DISABLE_AUTH		:= 0
diff --git a/plat/allwinner/common/sunxi_pm.c b/plat/allwinner/common/sunxi_pm.c
index 1d2dc93..13e1353 100644
--- a/plat/allwinner/common/sunxi_pm.c
+++ b/plat/allwinner/common/sunxi_pm.c
@@ -20,9 +20,9 @@
 #include <sunxi_mmap.h>
 #include <sunxi_private.h>
 
-#define SUNXI_WDOG0_CTRL_REG		(SUNXI_WDOG_BASE + 0x0010)
-#define SUNXI_WDOG0_CFG_REG		(SUNXI_WDOG_BASE + 0x0014)
-#define SUNXI_WDOG0_MODE_REG		(SUNXI_WDOG_BASE + 0x0018)
+#define SUNXI_WDOG0_CTRL_REG		(SUNXI_R_WDOG_BASE + 0x0010)
+#define SUNXI_WDOG0_CFG_REG		(SUNXI_R_WDOG_BASE + 0x0014)
+#define SUNXI_WDOG0_MODE_REG		(SUNXI_R_WDOG_BASE + 0x0018)
 
 #define mpidr_is_valid(mpidr) ( \
 	MPIDR_AFFLVL3_VAL(mpidr) == 0 && \
diff --git a/plat/arm/board/fvp/fvp_bl1_setup.c b/plat/arm/board/fvp/fvp_bl1_setup.c
index 75090e8..aa56716 100644
--- a/plat/arm/board/fvp/fvp_bl1_setup.c
+++ b/plat/arm/board/fvp/fvp_bl1_setup.c
@@ -5,9 +5,10 @@
  */
 
 #include <common/tbbr/tbbr_img_def.h>
+#include <drivers/arm/sp805.h>
 #include <plat/arm/common/plat_arm.h>
+#include <plat/arm/common/arm_def.h>
 #include <plat/common/platform.h>
-
 #include "fvp_private.h"
 
 /*******************************************************************************
@@ -30,3 +31,13 @@
 	 */
 	fvp_interconnect_enable();
 }
+
+void plat_arm_secure_wdt_start(void)
+{
+	sp805_start(ARM_SP805_TWDG_BASE, ARM_TWDG_LOAD_VAL);
+}
+
+void plat_arm_secure_wdt_stop(void)
+{
+	sp805_stop(ARM_SP805_TWDG_BASE);
+}
diff --git a/plat/arm/board/fvp/fvp_bl31_setup.c b/plat/arm/board/fvp/fvp_bl31_setup.c
index 7f28b20..3f92d37 100644
--- a/plat/arm/board/fvp/fvp_bl31_setup.c
+++ b/plat/arm/board/fvp/fvp_bl31_setup.c
@@ -34,7 +34,7 @@
 	 */
 	fvp_interconnect_enable();
 
-	/* On FVP RevC, intialize SMMUv3 */
+	/* On FVP RevC, initialize SMMUv3 */
 	if ((arm_config.flags & ARM_CONFIG_FVP_HAS_SMMUV3) != 0U)
 		smmuv3_init(PLAT_FVP_SMMUV3_BASE);
 }
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 1a63e87..9b128a5 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -95,24 +95,32 @@
 FVP_CPU_LIBS		:=	lib/cpus/${ARCH}/aem_generic.S
 
 ifeq (${ARCH}, aarch64)
-FVP_CPU_LIBS		+=	lib/cpus/aarch64/cortex_a35.S			\
+
+# select a different set of CPU files, depending on whether we compile with
+# hardware assisted coherency configurations or not
+ifeq (${HW_ASSISTED_COHERENCY}, 0)
+	FVP_CPU_LIBS	+=	lib/cpus/aarch64/cortex_a35.S			\
 				lib/cpus/aarch64/cortex_a53.S			\
-				lib/cpus/aarch64/cortex_a55.S			\
 				lib/cpus/aarch64/cortex_a57.S			\
 				lib/cpus/aarch64/cortex_a72.S			\
-				lib/cpus/aarch64/cortex_a73.S			\
+				lib/cpus/aarch64/cortex_a73.S
+else
+	FVP_CPU_LIBS	+=	lib/cpus/aarch64/cortex_a55.S			\
 				lib/cpus/aarch64/cortex_a75.S			\
 				lib/cpus/aarch64/cortex_a76.S			\
 				lib/cpus/aarch64/cortex_a76ae.S			\
 				lib/cpus/aarch64/neoverse_n1.S			\
+				lib/cpus/aarch64/neoverse_e1.S			\
 				lib/cpus/aarch64/cortex_deimos.S		\
 				lib/cpus/aarch64/neoverse_zeus.S
+endif
 
 else
 FVP_CPU_LIBS		+=	lib/cpus/aarch32/cortex_a32.S
 endif
 
-BL1_SOURCES		+=	drivers/io/io_semihosting.c			\
+BL1_SOURCES		+=	drivers/arm/sp805/sp805.c			\
+				drivers/io/io_semihosting.c			\
 				lib/semihosting/semihosting.c			\
 				lib/semihosting/${ARCH}/semihosting_call.S	\
 				plat/arm/board/fvp/${ARCH}/fvp_helpers.S	\
@@ -216,10 +224,13 @@
 endif
 
 ifeq (${ENABLE_AMU},1)
-BL31_SOURCES		+=	lib/cpus/aarch64/cortex_a75_pubsub.c	\
-				lib/cpus/aarch64/neoverse_n1_pubsub.c	\
-				lib/cpus/aarch64/cpuamu.c		\
+BL31_SOURCES		+=	lib/cpus/aarch64/cpuamu.c		\
 				lib/cpus/aarch64/cpuamu_helpers.S
+
+ifeq (${HW_ASSISTED_COHERENCY}, 1)
+BL31_SOURCES		+=	lib/cpus/aarch64/cortex_a75_pubsub.c	\
+				lib/cpus/aarch64/neoverse_n1_pubsub.c
+endif
 endif
 
 ifeq (${RAS_EXTENSION},1)
diff --git a/plat/arm/board/fvp_ve/fvp_ve_bl1_setup.c b/plat/arm/board/fvp_ve/fvp_ve_bl1_setup.c
index 47cd876..4338f6f 100644
--- a/plat/arm/board/fvp_ve/fvp_ve_bl1_setup.c
+++ b/plat/arm/board/fvp_ve/fvp_ve_bl1_setup.c
@@ -4,8 +4,10 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <drivers/arm/sp805.h>
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
+#include <platform_def.h>
 
 /*******************************************************************************
  * Perform any BL1 specific platform actions.
@@ -14,3 +16,13 @@
 {
 	arm_bl1_early_platform_setup();
 }
+
+void plat_arm_secure_wdt_start(void)
+{
+	sp805_start(ARM_SP805_TWDG_BASE, ARM_TWDG_LOAD_VAL);
+}
+
+void plat_arm_secure_wdt_stop(void)
+{
+	sp805_stop(ARM_SP805_TWDG_BASE);
+}
diff --git a/plat/arm/board/juno/juno_bl1_setup.c b/plat/arm/board/juno/juno_bl1_setup.c
index 33f5c47..7a3d22d 100644
--- a/plat/arm/board/juno/juno_bl1_setup.c
+++ b/plat/arm/board/juno/juno_bl1_setup.c
@@ -12,6 +12,7 @@
 #include <drivers/arm/css/sds.h>
 #include <drivers/arm/sp805.h>
 #include <plat/arm/common/plat_arm.h>
+#include <plat/arm/common/arm_def.h>
 #include <plat/common/platform.h>
 #include <platform_def.h>
 
@@ -112,3 +113,13 @@
 	juno_reset_to_aarch32_state();
 }
 #endif /* JUNO_AARCH32_EL3_RUNTIME */
+
+void plat_arm_secure_wdt_start(void)
+{
+	sp805_start(ARM_SP805_TWDG_BASE, ARM_TWDG_LOAD_VAL);
+}
+
+void plat_arm_secure_wdt_stop(void)
+{
+	sp805_stop(ARM_SP805_TWDG_BASE);
+}
diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk
index e44791b..40e6264 100644
--- a/plat/arm/board/juno/platform.mk
+++ b/plat/arm/board/juno/platform.mk
@@ -62,6 +62,7 @@
 				lib/cpus/aarch64/cortex_a72.S		\
 				plat/arm/board/juno/juno_err.c		\
 				plat/arm/board/juno/juno_bl1_setup.c	\
+				drivers/arm/sp805/sp805.c		\
 				${JUNO_INTERCONNECT_SOURCES}		\
 				${JUNO_SECURITY_SOURCES}
 
diff --git a/plat/arm/board/juno/tsp/tsp-juno.mk b/plat/arm/board/juno/tsp/tsp-juno.mk
index 52461cf..be75c4d 100644
--- a/plat/arm/board/juno/tsp/tsp-juno.mk
+++ b/plat/arm/board/juno/tsp/tsp-juno.mk
@@ -1,11 +1,12 @@
 #
-# Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
 BL32_SOURCES		+=	plat/arm/board/juno/juno_topology.c	\
 				plat/arm/css/common/css_topology.c	\
-				${JUNO_GIC_SOURCES}
+				${JUNO_GIC_SOURCES}			\
+				${JUNO_SECURITY_SOURCES}
 
 include plat/arm/common/tsp/arm_tsp.mk
diff --git a/plat/arm/board/n1sdp/include/platform_def.h b/plat/arm/board/n1sdp/include/platform_def.h
index 03bd380..adb957e 100644
--- a/plat/arm/board/n1sdp/include/platform_def.h
+++ b/plat/arm/board/n1sdp/include/platform_def.h
@@ -87,4 +87,8 @@
 /* Platform ID address */
 #define SSC_VERSION				(SSC_REG_BASE + SSC_VERSION_OFFSET)
 
+/* Secure Watchdog Constants */
+#define SBSA_SECURE_WDOG_BASE			UL(0x2A480000)
+#define SBSA_SECURE_WDOG_TIMEOUT		UL(100)
+
 #endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/n1sdp/n1sdp_plat.c b/plat/arm/board/n1sdp/n1sdp_plat.c
index 6905896..f36f9e2 100644
--- a/plat/arm/board/n1sdp/n1sdp_plat.c
+++ b/plat/arm/board/n1sdp/n1sdp_plat.c
@@ -10,6 +10,7 @@
 #include <common/debug.h>
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
+#include <drivers/arm/sbsa.h>
 
 /*
  * Table of regions to map using the MMU.
@@ -22,3 +23,12 @@
 	{0}
 };
 
+void plat_arm_secure_wdt_start(void)
+{
+	sbsa_wdog_start(SBSA_SECURE_WDOG_BASE, SBSA_SECURE_WDOG_TIMEOUT);
+}
+
+void plat_arm_secure_wdt_stop(void)
+{
+	sbsa_wdog_stop(SBSA_SECURE_WDOG_BASE);
+}
diff --git a/plat/arm/board/n1sdp/platform.mk b/plat/arm/board/n1sdp/platform.mk
index 653d081..d0c34c8 100644
--- a/plat/arm/board/n1sdp/platform.mk
+++ b/plat/arm/board/n1sdp/platform.mk
@@ -25,6 +25,7 @@
 PLAT_BL_COMMON_SOURCES	:=	${N1SDP_BASE}/n1sdp_plat.c	        \
 				${N1SDP_BASE}/aarch64/n1sdp_helper.S
 
+BL1_SOURCES		+=	drivers/arm/sbsa/sbsa.c
 
 BL31_SOURCES		:=	${N1SDP_CPU_SOURCES}			\
 				${INTERCONNECT_SOURCES}			\
diff --git a/plat/arm/common/arm_bl1_setup.c b/plat/arm/common/arm_bl1_setup.c
index 1e9edef..8e0c046 100644
--- a/plat/arm/common/arm_bl1_setup.c
+++ b/plat/arm/common/arm_bl1_setup.c
@@ -11,7 +11,6 @@
 #include <arch.h>
 #include <bl1/bl1.h>
 #include <common/bl_common.h>
-#include <drivers/arm/sp805.h>
 #include <lib/utils.h>
 #include <lib/xlat_tables/xlat_tables_compat.h>
 #include <plat/arm/common/plat_arm.h>
@@ -67,7 +66,7 @@
 
 #if !ARM_DISABLE_TRUSTED_WDOG
 	/* Enable watchdog */
-	sp805_start(ARM_SP805_TWDG_BASE, ARM_TWDG_LOAD_VAL);
+	plat_arm_secure_wdt_start();
 #endif
 
 	/* Initialize the console to provide early debug support */
@@ -172,7 +171,7 @@
 {
 #if !ARM_DISABLE_TRUSTED_WDOG
 	/* Disable watchdog before leaving BL1 */
-	sp805_stop(ARM_SP805_TWDG_BASE);
+	plat_arm_secure_wdt_stop();
 #endif
 
 #ifdef EL3_PAYLOAD_BASE
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index 5e890ed..c3d9e03 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -158,8 +158,7 @@
 PLAT_BL_COMMON_SOURCES	+=	${XLAT_TABLES_LIB_SRCS}
 endif
 
-BL1_SOURCES		+=	drivers/arm/sp805/sp805.c			\
-				drivers/io/io_fip.c				\
+BL1_SOURCES		+=	drivers/io/io_fip.c				\
 				drivers/io/io_memmap.c				\
 				drivers/io/io_storage.c				\
 				plat/arm/common/arm_bl1_setup.c			\
diff --git a/plat/arm/common/arm_console.c b/plat/arm/common/arm_console.c
index 84886b4..580b2ee 100644
--- a/plat/arm/common/arm_console.c
+++ b/plat/arm/common/arm_console.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -80,9 +80,7 @@
 {
 	(void)console_flush();
 
-#if MULTI_CONSOLE_API
-	(void)console_unregister(&arm_runtime_console.console);
-#else
+#if !MULTI_CONSOLE_API
 	console_uninit();
-#endif /* MULTI_CONSOLE_API */
+#endif /* !MULTI_CONSOLE_API */
 }
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 c0e6555..032a1f4 100644
--- a/plat/arm/css/sgi/include/sgi_base_platform_def.h
+++ b/plat/arm/css/sgi/include/sgi_base_platform_def.h
@@ -208,5 +208,8 @@
 #define PLAT_ARM_MEM_PROT_ADDR		(V2M_FLASH0_BASE + \
 					 V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE)
 
+/*Secure Watchdog Constants */
+#define SBSA_SECURE_WDOG_BASE		UL(0x2A480000)
+#define SBSA_SECURE_WDOG_TIMEOUT	UL(100)
 
 #endif /* SGI_BASE_PLATFORM_DEF_H */
diff --git a/plat/arm/css/sgi/sgi-common.mk b/plat/arm/css/sgi/sgi-common.mk
index 613d3d5..b736b0b 100644
--- a/plat/arm/css/sgi/sgi-common.mk
+++ b/plat/arm/css/sgi/sgi-common.mk
@@ -33,7 +33,8 @@
 PLAT_BL_COMMON_SOURCES	+=	${CSS_ENT_BASE}/sgi_plat.c	\
 				${CSS_ENT_BASE}/aarch64/sgi_helper.S
 
-BL1_SOURCES		+=	${INTERCONNECT_SOURCES}
+BL1_SOURCES		+=	${INTERCONNECT_SOURCES}			\
+				drivers/arm/sbsa/sbsa.c
 
 BL2_SOURCES		+=	${CSS_ENT_BASE}/sgi_image_load.c
 
diff --git a/plat/arm/css/sgi/sgi_plat.c b/plat/arm/css/sgi/sgi_plat.c
index 42eff86..3e207ec 100644
--- a/plat/arm/css/sgi/sgi_plat.c
+++ b/plat/arm/css/sgi/sgi_plat.c
@@ -13,6 +13,8 @@
 #include <drivers/arm/ccn.h>
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
+#include <drivers/arm/sbsa.h>
+#include <sgi_base_platform_def.h>
 #include <services/secure_partition.h>
 
 #define SGI_MAP_FLASH0_RO	MAP_REGION_FLAT(V2M_FLASH0_BASE,\
@@ -139,3 +141,13 @@
 	return arm_get_mbedtls_heap(heap_addr, heap_size);
 }
 #endif
+
+void plat_arm_secure_wdt_start(void)
+{
+	sbsa_wdog_start(SBSA_SECURE_WDOG_BASE, SBSA_SECURE_WDOG_TIMEOUT);
+}
+
+void plat_arm_secure_wdt_stop(void)
+{
+	sbsa_wdog_stop(SBSA_SECURE_WDOG_BASE);
+}
diff --git a/plat/arm/css/sgm/sgm-common.mk b/plat/arm/css/sgm/sgm-common.mk
index 0a136e6..34e78b2 100644
--- a/plat/arm/css/sgm/sgm-common.mk
+++ b/plat/arm/css/sgm/sgm-common.mk
@@ -31,7 +31,8 @@
 BL1_SOURCES		+=	$(SGM_CPU_SOURCES)			\
 				${INTERCONNECT_SOURCES}			\
 				${CSS_SGM_BASE}/sgm_bl1_setup.c		\
-				${CSS_SGM_BASE}/sgm_plat_config.c
+				${CSS_SGM_BASE}/sgm_plat_config.c	\
+				drivers/arm/sp805/sp805.c
 
 BL2_SOURCES		+=	${SECURITY_SOURCES}			\
 				${CSS_SGM_BASE}/sgm_plat_config.c
diff --git a/plat/arm/css/sgm/sgm_bl1_setup.c b/plat/arm/css/sgm/sgm_bl1_setup.c
index 2036515..5fd9655 100644
--- a/plat/arm/css/sgm/sgm_bl1_setup.c
+++ b/plat/arm/css/sgm/sgm_bl1_setup.c
@@ -8,7 +8,8 @@
 #include <common/debug.h>
 #include <plat/arm/common/plat_arm.h>
 #include <plat/arm/soc/common/soc_css.h>
-
+#include <plat/arm/common/arm_def.h>
+#include <drivers/arm/sp805.h>
 #include <sgm_plat_config.h>
 
 void bl1_early_platform_setup(void)
@@ -32,3 +33,13 @@
 	plat_arm_interconnect_enter_coherency();
 #endif
 }
+
+void plat_arm_secure_wdt_start(void)
+{
+	sp805_start(ARM_SP805_TWDG_BASE, ARM_TWDG_LOAD_VAL);
+}
+
+void plat_arm_secure_wdt_stop(void)
+{
+	sp805_stop(ARM_SP805_TWDG_BASE);
+}
diff --git a/plat/hisilicon/hikey/include/hikey_def.h b/plat/hisilicon/hikey/include/hikey_def.h
index b9679f5..4fb3e56 100644
--- a/plat/hisilicon/hikey/include/hikey_def.h
+++ b/plat/hisilicon/hikey/include/hikey_def.h
@@ -40,6 +40,7 @@
  * PL011 related constants
  */
 #define PL011_UART0_BASE		0xF8015000
+#define PL011_UART2_BASE		0xF7112000
 #define PL011_UART3_BASE		0xF7113000
 #define PL011_BAUDRATE			115200
 #define PL011_UART_CLK_IN_HZ		19200000
diff --git a/plat/imx/imx8m/imx8mq/gpc.c b/plat/imx/imx8m/imx8mq/gpc.c
index 02c640b..942ae45 100644
--- a/plat/imx/imx8m/imx8mq/gpc.c
+++ b/plat/imx/imx8m/imx8mq/gpc.c
@@ -119,17 +119,21 @@
 	uint32_t val;
 	int i;
 	/* mask all the interrupt by default */
+	for (i = 0; i < 4; i++) {
+		mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_A53 + i * 4, ~0x0);
+		mmio_write_32(IMX_GPC_BASE + IMR1_CORE1_A53 + i * 4, ~0x0);
+		mmio_write_32(IMX_GPC_BASE + IMR1_CORE2_A53 + i * 4, ~0x0);
+		mmio_write_32(IMX_GPC_BASE + IMR1_CORE3_A53 + i * 4, ~0x0);
+		mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_M4 + i * 4, ~0x0);
+	}
 	/* Due to the hardware design requirement, need to make
 	 * sure GPR interrupt(#32) is unmasked during RUN mode to
 	 * avoid entering DSM mode by mistake.
 	 */
-	for (i = 0; i < 4; i++) {
-		mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_A53 + i * 4, 0xFFFFFFFE);
-		mmio_write_32(IMX_GPC_BASE + IMR1_CORE1_A53 + i * 4, 0xFFFFFFFE);
-		mmio_write_32(IMX_GPC_BASE + IMR1_CORE2_A53 + i * 4, 0xFFFFFFFE);
-		mmio_write_32(IMX_GPC_BASE + IMR1_CORE3_A53 + i * 4, 0xFFFFFFFE);
-		mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_M4 + i * 4, ~0x0);
-	}
+	mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_A53, 0xFFFFFFFE);
+	mmio_write_32(IMX_GPC_BASE + IMR1_CORE1_A53, 0xFFFFFFFE);
+	mmio_write_32(IMX_GPC_BASE + IMR1_CORE2_A53, 0xFFFFFFFE);
+	mmio_write_32(IMX_GPC_BASE + IMR1_CORE3_A53, 0xFFFFFFFE);
 
 	/* use external IRQs to wakeup C0~C3 from LPM */
 	val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC);
@@ -162,4 +166,7 @@
 	 */
 	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/marvell/common/mrvl_sip_svc.c b/plat/marvell/common/mrvl_sip_svc.c
index df21105..0291024 100644
--- a/plat/marvell/common/mrvl_sip_svc.c
+++ b/plat/marvell/common/mrvl_sip_svc.c
@@ -15,6 +15,7 @@
 #include <plat_marvell.h>
 
 #include "comphy/phy-comphy-cp110.h"
+#include <stdbool.h>
 
 /* #define DEBUG_COMPHY */
 #ifdef DEBUG_COMPHY
@@ -38,12 +39,24 @@
 
 #define MAX_LANE_NR		6
 #define MVEBU_COMPHY_OFFSET	0x441000
-#define MVEBU_SD_OFFSET		0x120000
+#define MVEBU_CP_BASE_MASK	(~0xffffff)
 
 /* This macro is used to identify COMPHY related calls from SMC function ID */
 #define is_comphy_fid(fid)	\
 	((fid) >= MV_SIP_COMPHY_POWER_ON && (fid) <= MV_SIP_COMPHY_DIG_RESET)
 
+_Bool is_cp_range_valid(u_register_t *addr)
+{
+	int cp_nr;
+
+	*addr &= MVEBU_CP_BASE_MASK;
+	for (cp_nr = 0; cp_nr < CP_NUM; cp_nr++) {
+		if (*addr == MVEBU_CP_REGS_BASE(cp_nr))
+			return true;
+	}
+
+	return false;
+}
 
 uintptr_t mrvl_sip_smc_handler(uint32_t smc_fid,
 			       u_register_t x1,
@@ -59,20 +72,17 @@
 
 	debug("%s: got SMC (0x%x) x1 0x%lx, x2 0x%lx, x3 0x%lx\n",
 						 __func__, smc_fid, x1, x2, x3);
-	if (is_comphy_fid(smc_fid)) {
-
-		/* some systems passes SD phys address instead of COMPHY phys
-		 * address - convert it
-		 */
-		if (x1 & MVEBU_SD_OFFSET)
-			x1 = (x1 & ~0xffffff) + MVEBU_COMPHY_OFFSET;
 
-		if ((x1 & 0xffffff) != MVEBU_COMPHY_OFFSET) {
+	if (is_comphy_fid(smc_fid)) {
+		/* validate address passed via x1 */
+		if (!is_cp_range_valid(&x1)) {
 			ERROR("%s: Wrong smc (0x%x) address: %lx\n",
 			      __func__, smc_fid, x1);
 			SMC_RET1(handle, SMC_UNK);
 		}
 
+		x1 += MVEBU_COMPHY_OFFSET;
+
 		if (x2 >= MAX_LANE_NR) {
 			ERROR("%s: Wrong smc (0x%x) lane nr: %lx\n",
 			      __func__, smc_fid, x2);
@@ -106,8 +116,7 @@
 
 	/* Miscellaneous FID's' */
 	case MV_SIP_DRAM_SIZE:
-		/* x1:  ap_base_addr */
-		ret = mvebu_get_dram_size(x1);
+		ret = mvebu_get_dram_size(MVEBU_REGS_BASE);
 		SMC_RET1(handle, ret);
 	case MV_SIP_LLC_ENABLE:
 		for (i = 0; i < ap_get_count(); i++)
diff --git a/plat/rockchip/common/aarch32/plat_helpers.S b/plat/rockchip/common/aarch32/plat_helpers.S
new file mode 100644
index 0000000..475c297
--- /dev/null
+++ b/plat/rockchip/common/aarch32/plat_helpers.S
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <common/bl_common.h>
+#include <cortex_a12.h>
+#include <plat_private.h>
+#include <plat_pmu_macros.S>
+
+	.globl	cpuson_entry_point
+	.globl	cpuson_flags
+	.globl	platform_cpu_warmboot
+	.globl	plat_secondary_cold_boot_setup
+	.globl	plat_report_exception
+	.globl	plat_is_my_cpu_primary
+	.globl	plat_my_core_pos
+	.globl	plat_reset_handler
+	.globl	plat_panic_handler
+
+	/*
+	 * void plat_reset_handler(void);
+	 *
+	 * Determine the SOC type and call the appropriate reset
+	 * handler.
+	 *
+	 */
+func plat_reset_handler
+	bx	lr
+endfunc plat_reset_handler
+
+func plat_my_core_pos
+	ldcopr	r0, MPIDR
+	and	r1, r0, #MPIDR_CPU_MASK
+#ifdef PLAT_RK_MPIDR_CLUSTER_MASK
+	and	r0, r0, #PLAT_RK_MPIDR_CLUSTER_MASK
+#else
+	and	r0, r0, #MPIDR_CLUSTER_MASK
+#endif
+	add	r0, r1, r0, LSR #PLAT_RK_CLST_TO_CPUID_SHIFT
+	bx	lr
+endfunc plat_my_core_pos
+
+	/* --------------------------------------------------------------------
+	 * void plat_secondary_cold_boot_setup (void);
+	 *
+	 * This function performs any platform specific actions
+	 * needed for a secondary cpu after a cold reset e.g
+	 * mark the cpu's presence, mechanism to place it in a
+	 * holding pen etc.
+	 * --------------------------------------------------------------------
+	 */
+func plat_secondary_cold_boot_setup
+	/* rk3288 does not do cold boot for secondary CPU */
+cb_panic:
+	b	cb_panic
+endfunc plat_secondary_cold_boot_setup
+
+func plat_is_my_cpu_primary
+	ldcopr	r0, MPIDR
+#ifdef PLAT_RK_MPIDR_CLUSTER_MASK
+	ldr	r1, =(PLAT_RK_MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+#else
+	ldr	r1, =(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+#endif
+	and	r0, r1
+	cmp	r0, #PLAT_RK_PRIMARY_CPU
+	moveq	r0, #1
+	movne	r0, #0
+	bx	lr
+endfunc plat_is_my_cpu_primary
+
+	/* --------------------------------------------------------------------
+	 * void plat_panic_handler(void)
+	 * Call system reset function on panic. Set up an emergency stack so we
+	 * can run C functions (it only needs to last for a few calls until we
+	 * reboot anyway).
+	 * --------------------------------------------------------------------
+	 */
+func plat_panic_handler
+	bl	plat_set_my_stack
+	b	rockchip_soc_soft_reset
+endfunc plat_panic_handler
+
+	/* --------------------------------------------------------------------
+	 * void platform_cpu_warmboot (void);
+	 * cpus online or resume entrypoint
+	 * --------------------------------------------------------------------
+	 */
+func platform_cpu_warmboot _align=16
+	push	{ r4 - r7, lr }
+	ldcopr	r0, MPIDR
+	and	r5, r0, #MPIDR_CPU_MASK
+#ifdef PLAT_RK_MPIDR_CLUSTER_MASK
+	and	r6, r0, #PLAT_RK_MPIDR_CLUSTER_MASK
+#else
+	and	r6, r0, #MPIDR_CLUSTER_MASK
+#endif
+	mov	r0, r6
+
+	func_rockchip_clst_warmboot
+	/* --------------------------------------------------------------------
+	 * big cluster id is 1
+	 * big cores id is from 0-3, little cores id 4-7
+	 * --------------------------------------------------------------------
+	 */
+	add	r7, r5, r6, LSR #PLAT_RK_CLST_TO_CPUID_SHIFT
+	/* --------------------------------------------------------------------
+	 * get per cpuup flag
+         * --------------------------------------------------------------------
+	 */
+	ldr	r4, =cpuson_flags
+	add	r4, r4, r7, lsl #2
+	ldr	r1, [r4]
+	/* --------------------------------------------------------------------
+	 * check cpuon reason
+         * --------------------------------------------------------------------
+	 */
+	cmp	r1, #PMU_CPU_AUTO_PWRDN
+	beq	boot_entry
+	cmp	r1, #PMU_CPU_HOTPLUG
+	beq	boot_entry
+	/* --------------------------------------------------------------------
+	 * If the boot core cpuson_flags or cpuson_entry_point is not
+	 * expection. force the core into wfe.
+	 * --------------------------------------------------------------------
+	 */
+wfe_loop:
+	wfe
+	b	wfe_loop
+boot_entry:
+	mov	r1, #0
+	str	r1, [r4]
+	/* --------------------------------------------------------------------
+	 * get per cpuup boot addr
+	 * --------------------------------------------------------------------
+	 */
+	ldr	r5, =cpuson_entry_point
+	ldr	r2, [r5, r7, lsl #2] /* ehem. #3 */
+	pop	{ r4 - r7, lr }
+
+	bx	r2
+endfunc platform_cpu_warmboot
+
+	/* --------------------------------------------------------------------
+	 * Per-CPU Secure entry point - resume or power up
+	 * --------------------------------------------------------------------
+	 */
+	.section tzfw_coherent_mem, "a"
+	.align  3
+cpuson_entry_point:
+	.rept	PLATFORM_CORE_COUNT
+	.quad	0
+	.endr
+cpuson_flags:
+	.rept	PLATFORM_CORE_COUNT
+	.word	0
+	.endr
+rockchip_clst_warmboot_data
diff --git a/plat/rockchip/common/aarch32/platform_common.c b/plat/rockchip/common/aarch32/platform_common.c
new file mode 100644
index 0000000..9030951
--- /dev/null
+++ b/plat/rockchip/common/aarch32/platform_common.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <lib/utils.h>
+#include <lib/xlat_tables/xlat_tables.h>
+
+#include <plat_private.h>
+
+void plat_configure_mmu_svc_mon(unsigned long total_base,
+				unsigned long total_size,
+				unsigned long ro_start,
+				unsigned long ro_limit,
+				unsigned long coh_start,
+				unsigned long coh_limit)
+{
+	mmap_add_region(total_base, total_base, total_size,
+			MT_MEMORY | MT_RW | MT_SECURE);
+	mmap_add_region(ro_start, ro_start, ro_limit - ro_start,
+			MT_MEMORY | MT_RO | MT_SECURE);
+	mmap_add_region(coh_start, coh_start, coh_limit - coh_start,
+			MT_DEVICE | MT_RW | MT_SECURE);
+	mmap_add(plat_rk_mmap);
+	rockchip_plat_mmu_svc_mon();
+	init_xlat_tables();
+	enable_mmu_svc_mon(0);
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+	return SYS_COUNTER_FREQ_IN_TICKS;
+}
+
+/*
+ * generic pm code does cci handling, but rockchip arm32 platforms
+ * have ever only 1 cluster, so nothing to do.
+ */
+void plat_cci_init(void)
+{
+}
+
+void plat_cci_enable(void)
+{
+}
+
+void plat_cci_disable(void)
+{
+}
diff --git a/plat/rockchip/common/aarch32/pmu_sram_cpus_on.S b/plat/rockchip/common/aarch32/pmu_sram_cpus_on.S
new file mode 100644
index 0000000..a05ae54
--- /dev/null
+++ b/plat/rockchip/common/aarch32/pmu_sram_cpus_on.S
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+
+	.globl pmu_cpuson_entrypoint
+	.macro pmusram_entry_func _name
+	.section .pmusram.entry, "ax"
+	.type \_name, %function
+	.cfi_startproc
+	\_name:
+	.endm
+
+pmusram_entry_func pmu_cpuson_entrypoint
+
+#if PSRAM_CHECK_WAKEUP_CPU
+check_wake_cpus:
+	ldcopr	r0, MPIDR
+	and	r1, r0, #MPIDR_CPU_MASK
+#ifdef PLAT_RK_MPIDR_CLUSTER_MASK
+	and	r0, r0, #PLAT_RK_MPIDR_CLUSTER_MASK
+#else
+	and	r0, r0, #MPIDR_CLUSTER_MASK
+#endif
+	orr	r0, r0, r1
+
+	/* primary_cpu */
+	ldr	r1, boot_mpidr
+	cmp	r0, r1
+	beq	sys_wakeup
+
+	/*
+	 * If the core is not the primary cpu,
+	 * force the core into wfe.
+	 */
+wfe_loop:
+	wfe
+	b	wfe_loop
+sys_wakeup:
+#endif
+
+#if PSRAM_DO_DDR_RESUME
+ddr_resume:
+	ldr	r2, =__bl32_sram_stack_end
+	mov     sp, r2
+	bl	dmc_resume
+#endif
+	bl	sram_restore
+sys_resume:
+	bl	sp_min_warm_entrypoint
+endfunc pmu_cpuson_entrypoint
diff --git a/plat/rockchip/common/pmusram/pmu_sram_cpus_on.S b/plat/rockchip/common/aarch64/pmu_sram_cpus_on.S
similarity index 100%
rename from plat/rockchip/common/pmusram/pmu_sram_cpus_on.S
rename to plat/rockchip/common/aarch64/pmu_sram_cpus_on.S
diff --git a/plat/rockchip/common/bl31_plat_setup.c b/plat/rockchip/common/bl31_plat_setup.c
index 2c970eb..30782d1 100644
--- a/plat/rockchip/common/bl31_plat_setup.c
+++ b/plat/rockchip/common/bl31_plat_setup.c
@@ -78,7 +78,7 @@
 				       coreboot_serial.baud,
 				       &console);
 #else
-	console_16550_register(PLAT_RK_UART_BASE, PLAT_RK_UART_CLOCK,
+	console_16550_register(rockchip_get_uart_base(), PLAT_RK_UART_CLOCK,
 			       PLAT_RK_UART_BAUDRATE, &console);
 #endif
 
diff --git a/plat/rockchip/common/drivers/pmu/pmu_com.h b/plat/rockchip/common/drivers/pmu/pmu_com.h
index 4b4b00f..5359f73 100644
--- a/plat/rockchip/common/drivers/pmu/pmu_com.h
+++ b/plat/rockchip/common/drivers/pmu/pmu_com.h
@@ -88,6 +88,17 @@
 		cluster_id = 0;
 	}
 
+	/*
+	 * wfe/wfi tracking not possible, hopefully the host
+	 * was sucessful in enabling wfe/wfi.
+	 * We'll give a bit of additional time, like the kernel does.
+	 */
+	if ((cluster_id && clstb_cpu_wfe < 0) ||
+	    (!cluster_id && clstl_cpu_wfe < 0)) {
+		mdelay(1);
+		return 0;
+	}
+
 	if (cluster_id)
 		wfie_msk <<= (clstb_cpu_wfe + cpu_id);
 	else
diff --git a/plat/rockchip/common/include/plat_private.h b/plat/rockchip/common/include/plat_private.h
index e8750a5..c0ebefc 100644
--- a/plat/rockchip/common/include/plat_private.h
+++ b/plat/rockchip/common/include/plat_private.h
@@ -68,6 +68,16 @@
 /******************************************************************************
  * Function and variable prototypes
  *****************************************************************************/
+#ifdef AARCH32
+void plat_configure_mmu_svc_mon(unsigned long total_base,
+				unsigned long total_size,
+				unsigned long,
+				unsigned long,
+				unsigned long,
+				unsigned long);
+
+void rockchip_plat_mmu_svc_mon(void);
+#else
 void plat_configure_mmu_el3(unsigned long total_base,
 			    unsigned long total_size,
 			    unsigned long,
@@ -75,6 +85,9 @@
 			    unsigned long,
 			    unsigned long);
 
+void rockchip_plat_mmu_el3(void);
+#endif
+
 void plat_cci_init(void);
 void plat_cci_enable(void);
 void plat_cci_disable(void);
@@ -128,12 +141,12 @@
 extern const unsigned char rockchip_power_domain_tree_desc[];
 
 extern void *pmu_cpuson_entrypoint;
-extern uint64_t cpuson_entry_point[PLATFORM_CORE_COUNT];
+extern u_register_t cpuson_entry_point[PLATFORM_CORE_COUNT];
 extern uint32_t cpuson_flags[PLATFORM_CORE_COUNT];
 
 extern const mmap_region_t plat_rk_mmap[];
 
-void rockchip_plat_mmu_el3(void);
+uint32_t rockchip_get_uart_base(void);
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/plat/rockchip/common/params_setup.c b/plat/rockchip/common/params_setup.c
index dda98d9..8a743bf 100644
--- a/plat/rockchip/common/params_setup.c
+++ b/plat/rockchip/common/params_setup.c
@@ -5,6 +5,7 @@
  */
 
 #include <assert.h>
+#include <errno.h>
 #include <string.h>
 
 #include <common/bl_common.h>
@@ -27,13 +28,97 @@
 static struct gpio_info suspend_gpio[10];
 uint32_t suspend_gpio_cnt;
 static struct apio_info *suspend_apio;
+static uint32_t rk_uart_base = PLAT_RK_UART_BASE;
 
+uint32_t rockchip_get_uart_base(void)
+{
+	return rk_uart_base;
+}
+
+#if COREBOOT
+static int dt_process_fdt(void *blob)
+{
+	return -ENODEV;
+}
+#else
 static uint8_t fdt_buffer[0x10000];
 
 void *plat_get_fdt(void)
 {
 	return &fdt_buffer[0];
 }
+
+static void plat_rockchip_dt_process_fdt_uart(void *fdt)
+{
+	const char *path_name = "/chosen";
+	const char *prop_name = "stdout-path";
+	int node_offset;
+	int stdout_path_len;
+	const char *stdout_path;
+	char serial_char;
+	int serial_no;
+	uint32_t uart_base;
+
+	node_offset = fdt_path_offset(fdt, path_name);
+	if (node_offset < 0)
+		return;
+
+	stdout_path = fdt_getprop(fdt, node_offset, prop_name,
+				  &stdout_path_len);
+	if (stdout_path == NULL)
+		return;
+
+	/*
+	 * We expect something like:
+	 *   "serial0:...""
+	 */
+	if (strncmp("serial", stdout_path, 6) != 0)
+		return;
+
+	serial_char = stdout_path[6];
+	serial_no = serial_char - '0';
+
+	switch (serial_no) {
+	case 0:
+		uart_base = UART0_BASE;
+		break;
+	case 1:
+		uart_base = UART1_BASE;
+		break;
+	case 2:
+		uart_base = UART2_BASE;
+		break;
+#ifdef UART3_BASE
+	case 3:
+		uart_base = UART3_BASE;
+		break;
+#endif
+#ifdef UART4_BASE
+	case 4:
+		uart_base = UART4_BASE;
+		break;
+#endif
+	default:
+		return;
+	}
+
+	rk_uart_base = uart_base;
+}
+
+static int dt_process_fdt(void *blob)
+{
+	void *fdt = plat_get_fdt();
+	int ret;
+
+	ret = fdt_open_into(blob, fdt, 0x10000);
+	if (ret < 0)
+		return ret;
+
+	plat_rockchip_dt_process_fdt_uart(fdt);
+
+	return 0;
+}
+#endif
 
 struct gpio_info *plat_get_rockchip_gpio_reset(void)
 {
@@ -57,18 +142,6 @@
 	return suspend_apio;
 }
 
-static int dt_process_fdt(void *blob)
-{
-	void *fdt = plat_get_fdt();
-	int ret;
-
-	ret = fdt_open_into(blob, fdt, 0x10000);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-
 void params_early_setup(void *plat_param_from_bl2)
 {
 	struct bl31_plat_param *bl2_param;
diff --git a/plat/rockchip/common/plat_topology.c b/plat/rockchip/common/plat_topology.c
index a31e410..4987eeb 100644
--- a/plat/rockchip/common/plat_topology.c
+++ b/plat/rockchip/common/plat_topology.c
@@ -24,7 +24,11 @@
 	unsigned int cluster_id, cpu_id;
 
 	cpu_id = mpidr & MPIDR_AFFLVL_MASK;
+#ifdef PLAT_RK_MPIDR_CLUSTER_MASK
+	cluster_id = mpidr & PLAT_RK_MPIDR_CLUSTER_MASK;
+#else
 	cluster_id = mpidr & MPIDR_CLUSTER_MASK;
+#endif
 
 	cpu_id += (cluster_id >> PLAT_RK_CLST_TO_CPUID_SHIFT);
 
diff --git a/plat/rockchip/common/sp_min_plat_setup.c b/plat/rockchip/common/sp_min_plat_setup.c
new file mode 100644
index 0000000..7cdbaba
--- /dev/null
+++ b/plat/rockchip/common/sp_min_plat_setup.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <drivers/generic_delay_timer.h>
+#include <drivers/ti/uart/uart_16550.h>
+#include <lib/coreboot.h>
+#include <lib/mmio.h>
+#include <plat_private.h>
+#include <plat/common/platform.h>
+
+static entry_point_info_t bl33_ep_info;
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image for
+ * the security state specified. BL33 corresponds to the non-secure image type.
+ * A NULL pointer is returned if the image does not exist.
+ ******************************************************************************/
+entry_point_info_t *sp_min_plat_get_bl33_ep_info(void)
+{
+	entry_point_info_t *next_image_info;
+
+	next_image_info = &bl33_ep_info;
+
+	if (next_image_info->pc == 0U) {
+		return NULL;
+	}
+
+	return next_image_info;
+}
+
+#pragma weak params_early_setup
+void params_early_setup(void *plat_param_from_bl2)
+{
+}
+
+unsigned int plat_is_my_cpu_primary(void);
+
+/*******************************************************************************
+ * Perform any BL32 specific platform actions.
+ ******************************************************************************/
+void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+				  u_register_t arg2, u_register_t arg3)
+{
+	static console_16550_t console;
+	struct rockchip_bl31_params *arg_from_bl2 = (struct rockchip_bl31_params *) arg0;
+	void *plat_params_from_bl2 = (void *) arg1;
+
+	params_early_setup(plat_params_from_bl2);
+
+#if COREBOOT
+	if (coreboot_serial.type)
+		console_16550_register(coreboot_serial.baseaddr,
+				       coreboot_serial.input_hertz,
+				       coreboot_serial.baud,
+				       &console);
+#else
+	console_16550_register(rockchip_get_uart_base(), PLAT_RK_UART_CLOCK,
+			       PLAT_RK_UART_BAUDRATE, &console);
+#endif
+	VERBOSE("sp_min_setup\n");
+
+	/* Passing a NULL context is a critical programming error */
+	assert(arg_from_bl2);
+
+	assert(arg_from_bl2->h.type == PARAM_BL31);
+	assert(arg_from_bl2->h.version >= VERSION_1);
+
+	bl33_ep_info = *arg_from_bl2->bl33_ep_info;
+}
+
+/*******************************************************************************
+ * Perform any sp_min platform setup code
+ ******************************************************************************/
+void sp_min_platform_setup(void)
+{
+	generic_delay_timer_init();
+	plat_rockchip_soc_init();
+
+	/* Initialize the gic cpu and distributor interfaces */
+	plat_rockchip_gic_driver_init();
+	plat_rockchip_gic_init();
+	plat_rockchip_pmu_init();
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only intializes the mmu in a quick and dirty way.
+ ******************************************************************************/
+void sp_min_plat_arch_setup(void)
+{
+	plat_cci_init();
+	plat_cci_enable();
+
+	plat_configure_mmu_svc_mon(BL_CODE_BASE,
+				   BL_COHERENT_RAM_END - BL_CODE_BASE,
+				   BL_CODE_BASE,
+				   BL_CODE_END,
+				   BL_COHERENT_RAM_BASE,
+				   BL_COHERENT_RAM_END);
+}
+
+void sp_min_plat_fiq_handler(uint32_t id)
+{
+	VERBOSE("[sp_min] interrupt #%d\n", id);
+}
diff --git a/plat/rockchip/rk3288/drivers/pmu/plat_pmu_macros.S b/plat/rockchip/rk3288/drivers/pmu/plat_pmu_macros.S
new file mode 100644
index 0000000..2003749
--- /dev/null
+++ b/plat/rockchip/rk3288/drivers/pmu/plat_pmu_macros.S
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+
+.macro	func_rockchip_clst_warmboot
+	/* Nothing to do for rk3288 */
+.endm
+
+.macro rockchip_clst_warmboot_data
+	/* Nothing to do for rk3288 */
+.endm
diff --git a/plat/rockchip/rk3288/drivers/pmu/pmu.c b/plat/rockchip/rk3288/drivers/pmu/pmu.c
new file mode 100644
index 0000000..d6d7098
--- /dev/null
+++ b/plat/rockchip/rk3288/drivers/pmu/pmu.c
@@ -0,0 +1,391 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+
+#include <plat_private.h>
+#include <pmu.h>
+#include <pmu_com.h>
+#include <rk3288_def.h>
+#include <secure.h>
+#include <soc.h>
+
+DEFINE_BAKERY_LOCK(rockchip_pd_lock);
+
+static uint32_t cpu_warm_boot_addr;
+
+static uint32_t store_pmu_pwrmode_con;
+static uint32_t store_sgrf_soc_con0;
+static uint32_t store_sgrf_cpu_con0;
+
+/* These enum are variants of low power mode */
+enum {
+	ROCKCHIP_ARM_OFF_LOGIC_NORMAL = 0,
+	ROCKCHIP_ARM_OFF_LOGIC_DEEP = 1,
+};
+
+static inline int rk3288_pmu_bus_idle(uint32_t req, uint32_t idle)
+{
+	uint32_t mask = BIT(req);
+	uint32_t idle_mask = 0;
+	uint32_t idle_target = 0;
+	uint32_t val;
+	uint32_t wait_cnt = 0;
+
+	switch (req) {
+	case bus_ide_req_gpu:
+		idle_mask = BIT(pmu_idle_ack_gpu) | BIT(pmu_idle_gpu);
+		idle_target = (idle << pmu_idle_ack_gpu) |
+			      (idle << pmu_idle_gpu);
+		break;
+	case bus_ide_req_core:
+		idle_mask = BIT(pmu_idle_ack_core) | BIT(pmu_idle_core);
+		idle_target = (idle << pmu_idle_ack_core) |
+			      (idle << pmu_idle_core);
+		break;
+	case bus_ide_req_cpup:
+		idle_mask = BIT(pmu_idle_ack_cpup) | BIT(pmu_idle_cpup);
+		idle_target = (idle << pmu_idle_ack_cpup) |
+			      (idle << pmu_idle_cpup);
+		break;
+	case bus_ide_req_bus:
+		idle_mask = BIT(pmu_idle_ack_bus) | BIT(pmu_idle_bus);
+		idle_target = (idle << pmu_idle_ack_bus) |
+			      (idle << pmu_idle_bus);
+		break;
+	case bus_ide_req_dma:
+		idle_mask = BIT(pmu_idle_ack_dma) | BIT(pmu_idle_dma);
+		idle_target = (idle << pmu_idle_ack_dma) |
+			      (idle << pmu_idle_dma);
+		break;
+	case bus_ide_req_peri:
+		idle_mask = BIT(pmu_idle_ack_peri) | BIT(pmu_idle_peri);
+		idle_target = (idle << pmu_idle_ack_peri) |
+			      (idle << pmu_idle_peri);
+		break;
+	case bus_ide_req_video:
+		idle_mask = BIT(pmu_idle_ack_video) | BIT(pmu_idle_video);
+		idle_target = (idle << pmu_idle_ack_video) |
+			      (idle << pmu_idle_video);
+		break;
+	case bus_ide_req_hevc:
+		idle_mask = BIT(pmu_idle_ack_hevc) | BIT(pmu_idle_hevc);
+		idle_target = (idle << pmu_idle_ack_hevc) |
+			      (idle << pmu_idle_hevc);
+		break;
+	case bus_ide_req_vio:
+		idle_mask = BIT(pmu_idle_ack_vio) | BIT(pmu_idle_vio);
+		idle_target = (pmu_idle_ack_vio) |
+			      (idle << pmu_idle_vio);
+		break;
+	case bus_ide_req_alive:
+		idle_mask = BIT(pmu_idle_ack_alive) | BIT(pmu_idle_alive);
+		idle_target = (idle << pmu_idle_ack_alive) |
+			      (idle << pmu_idle_alive);
+		break;
+	default:
+		ERROR("%s: Unsupported the idle request\n", __func__);
+		break;
+	}
+
+	val = mmio_read_32(PMU_BASE + PMU_BUS_IDE_REQ);
+	if (idle)
+		val |= mask;
+	else
+		val &= ~mask;
+
+	mmio_write_32(PMU_BASE + PMU_BUS_IDE_REQ, val);
+
+	while ((mmio_read_32(PMU_BASE +
+	       PMU_BUS_IDE_ST) & idle_mask) != idle_target) {
+		wait_cnt++;
+		if (!(wait_cnt % MAX_WAIT_CONUT))
+			WARN("%s:st=%x(%x)\n", __func__,
+			     mmio_read_32(PMU_BASE + PMU_BUS_IDE_ST),
+			     idle_mask);
+	}
+
+	return 0;
+}
+
+static bool rk3288_sleep_disable_osc(void)
+{
+	static const uint32_t reg_offset[] = { GRF_UOC0_CON0, GRF_UOC1_CON0,
+					       GRF_UOC2_CON0 };
+	uint32_t reg, i;
+
+	/*
+	 * if any usb phy is still on(GRF_SIDDQ==0), that means we need the
+	 * function of usb wakeup, so do not switch to 32khz, since the usb phy
+	 * clk does not connect to 32khz osc
+	 */
+	for (i = 0; i < ARRAY_SIZE(reg_offset); i++) {
+		reg = mmio_read_32(GRF_BASE + reg_offset[i]);
+		if (!(reg & GRF_SIDDQ))
+			return false;
+	}
+
+	return true;
+}
+
+static void pmu_set_sleep_mode(int level)
+{
+	uint32_t mode_set, mode_set1;
+	bool osc_disable = rk3288_sleep_disable_osc();
+
+	mode_set = BIT(pmu_mode_glb_int_dis) | BIT(pmu_mode_l2_flush_en) |
+		   BIT(pmu_mode_sref0_enter) | BIT(pmu_mode_sref1_enter) |
+		   BIT(pmu_mode_ddrc0_gt) | BIT(pmu_mode_ddrc1_gt) |
+		   BIT(pmu_mode_en) | BIT(pmu_mode_chip_pd) |
+		   BIT(pmu_mode_scu_pd);
+
+	mode_set1 = BIT(pmu_mode_clr_core) | BIT(pmu_mode_clr_cpup);
+
+	if (level == ROCKCHIP_ARM_OFF_LOGIC_DEEP) {
+		/* arm off, logic deep sleep */
+		mode_set |= BIT(pmu_mode_bus_pd) | BIT(pmu_mode_pmu_use_lf) |
+			    BIT(pmu_mode_ddrio1_ret) |
+			    BIT(pmu_mode_ddrio0_ret) |
+			    BIT(pmu_mode_pmu_alive_use_lf) |
+			    BIT(pmu_mode_pll_pd);
+
+		if (osc_disable)
+			mode_set |= BIT(pmu_mode_osc_dis);
+
+		mode_set1 |= BIT(pmu_mode_clr_alive) | BIT(pmu_mode_clr_bus) |
+			     BIT(pmu_mode_clr_peri) | BIT(pmu_mode_clr_dma);
+
+		mmio_write_32(PMU_BASE + PMU_WAKEUP_CFG1,
+			      pmu_armint_wakeup_en);
+
+		/*
+		 * In deep suspend we use PMU_PMU_USE_LF to let the rk3288
+		 * switch its main clock supply to the alternative 32kHz
+		 * source. Therefore set 30ms on a 32kHz clock for pmic
+		 * stabilization. Similar 30ms on 24MHz for the other
+		 * mode below.
+		 */
+		mmio_write_32(PMU_BASE + PMU_STABL_CNT, 32 * 30);
+
+		/* only wait for stabilization, if we turned the osc off */
+		mmio_write_32(PMU_BASE + PMU_OSC_CNT,
+					 osc_disable ? 32 * 30 : 0);
+	} else {
+		/*
+		 * arm off, logic normal
+		 * if pmu_clk_core_src_gate_en is not set,
+		 * wakeup will be error
+		 */
+		mode_set |= BIT(pmu_mode_core_src_gt);
+
+		mmio_write_32(PMU_BASE + PMU_WAKEUP_CFG1,
+			      BIT(pmu_armint_wakeup_en) |
+			      BIT(pmu_gpioint_wakeup_en));
+
+		/* 30ms on a 24MHz clock for pmic stabilization */
+		mmio_write_32(PMU_BASE + PMU_STABL_CNT, 24000 * 30);
+
+		/* oscillator is still running, so no need to wait */
+		mmio_write_32(PMU_BASE + PMU_OSC_CNT, 0);
+	}
+
+	mmio_write_32(PMU_BASE + PMU_PWRMODE_CON, mode_set);
+	mmio_write_32(PMU_BASE + PMU_PWRMODE_CON1, mode_set1);
+}
+
+static int cpus_power_domain_on(uint32_t cpu_id)
+{
+	uint32_t cpu_pd;
+
+	cpu_pd = PD_CPU0 + cpu_id;
+
+	/* if the core has been on, power it off first */
+	if (pmu_power_domain_st(cpu_pd) == pmu_pd_on) {
+		/* put core in reset - some sort of A12/A17 bug */
+		mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(0),
+			      BIT(cpu_id) | (BIT(cpu_id) << 16));
+
+		pmu_power_domain_ctr(cpu_pd, pmu_pd_off);
+	}
+
+	pmu_power_domain_ctr(cpu_pd, pmu_pd_on);
+
+	/* pull core out of reset */
+	mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(0), BIT(cpu_id) << 16);
+
+	return 0;
+}
+
+static int cpus_power_domain_off(uint32_t cpu_id)
+{
+	uint32_t cpu_pd = PD_CPU0 + cpu_id;
+
+	if (pmu_power_domain_st(cpu_pd) == pmu_pd_off)
+		return 0;
+
+	if (check_cpu_wfie(cpu_id, CKECK_WFEI_MSK))
+		return -EINVAL;
+
+	/* put core in reset - some sort of A12/A17 bug */
+	mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(0),
+		      BIT(cpu_id) | (BIT(cpu_id) << 16));
+
+	pmu_power_domain_ctr(cpu_pd, pmu_pd_off);
+
+	return 0;
+}
+
+static void nonboot_cpus_off(void)
+{
+	uint32_t boot_cpu, cpu;
+
+	boot_cpu = plat_my_core_pos();
+	boot_cpu = MPIDR_AFFLVL0_VAL(read_mpidr());
+
+	/* turn off noboot cpus */
+	for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) {
+		if (cpu == boot_cpu)
+			continue;
+
+		cpus_power_domain_off(cpu);
+	}
+}
+
+void sram_save(void)
+{
+	/* TODO: support the sdram save for rk3288 SoCs*/
+}
+
+void sram_restore(void)
+{
+	/* TODO: support the sdram restore for rk3288 SoCs */
+}
+
+int rockchip_soc_cores_pwr_dm_on(unsigned long mpidr, uint64_t entrypoint)
+{
+	uint32_t cpu_id = plat_core_pos_by_mpidr(mpidr);
+
+	assert(cpu_id < PLATFORM_CORE_COUNT);
+	assert(cpuson_flags[cpu_id] == 0);
+	cpuson_flags[cpu_id] = PMU_CPU_HOTPLUG;
+	cpuson_entry_point[cpu_id] = entrypoint;
+	dsb();
+
+	cpus_power_domain_on(cpu_id);
+
+	/*
+	 * We communicate with the bootrom to active the cpus other
+	 * than cpu0, after a blob of initialize code, they will
+	 * stay at wfe state, once they are actived, they will check
+	 * the mailbox:
+	 * sram_base_addr + 4: 0xdeadbeaf
+	 * sram_base_addr + 8: start address for pc
+	 * The cpu0 need to wait the other cpus other than cpu0 entering
+	 * the wfe state.The wait time is affected by many aspects.
+	 * (e.g: cpu frequency, bootrom frequency, sram frequency, ...)
+	 */
+	mdelay(1); /* ensure the cpus other than cpu0 to startup */
+
+	/* tell the bootrom mailbox where to start from */
+	mmio_write_32(SRAM_BASE + 8, cpu_warm_boot_addr);
+	mmio_write_32(SRAM_BASE + 4, 0xDEADBEAF);
+	dsb();
+	sev();
+
+	return 0;
+}
+
+int rockchip_soc_cores_pwr_dm_on_finish(void)
+{
+	return 0;
+}
+
+int rockchip_soc_sys_pwr_dm_resume(void)
+{
+	mmio_write_32(PMU_BASE + PMU_PWRMODE_CON, store_pmu_pwrmode_con);
+	mmio_write_32(SGRF_BASE + SGRF_CPU_CON(0),
+		      store_sgrf_cpu_con0 | SGRF_DAPDEVICE_MSK);
+
+	/* disable fastboot mode */
+	mmio_write_32(SGRF_BASE + SGRF_SOC_CON(0),
+		      store_sgrf_soc_con0 | SGRF_FAST_BOOT_DIS);
+
+	secure_watchdog_ungate();
+	clk_gate_con_restore();
+	clk_sel_con_restore();
+	clk_plls_resume();
+
+	secure_gic_init();
+	plat_rockchip_gic_init();
+
+	return 0;
+}
+
+int rockchip_soc_sys_pwr_dm_suspend(void)
+{
+	nonboot_cpus_off();
+
+	store_sgrf_cpu_con0 = mmio_read_32(SGRF_BASE + SGRF_CPU_CON(0));
+	store_sgrf_soc_con0 = mmio_read_32(SGRF_BASE + SGRF_SOC_CON(0));
+	store_pmu_pwrmode_con = mmio_read_32(PMU_BASE + PMU_PWRMODE_CON);
+
+	/* save clk-gates and ungate all for suspend */
+	clk_gate_con_save();
+	clk_gate_con_disable();
+	clk_sel_con_save();
+
+	pmu_set_sleep_mode(ROCKCHIP_ARM_OFF_LOGIC_NORMAL);
+
+	clk_plls_suspend();
+	secure_watchdog_gate();
+
+	/*
+	 * The dapswjdp can not auto reset before resume, that cause it may
+	 * access some illegal address during resume. Let's disable it before
+	 * suspend, and the MASKROM will enable it back.
+	 */
+	mmio_write_32(SGRF_BASE + SGRF_CPU_CON(0), SGRF_DAPDEVICE_MSK);
+
+	/*
+	 * SGRF_FAST_BOOT_EN - system to boot from FAST_BOOT_ADDR
+	 */
+	mmio_write_32(SGRF_BASE + SGRF_SOC_CON(0), SGRF_FAST_BOOT_ENA);
+
+	/* boot-address of resuming system is from this register value */
+	mmio_write_32(SGRF_BASE + SGRF_FAST_BOOT_ADDR,
+		      (uint32_t)&pmu_cpuson_entrypoint);
+
+	/* flush all caches - otherwise we might loose the resume address */
+	dcsw_op_all(DC_OP_CISW);
+
+	return 0;
+}
+
+void rockchip_plat_mmu_svc_mon(void)
+{
+}
+
+void plat_rockchip_pmu_init(void)
+{
+	uint32_t cpu;
+
+	cpu_warm_boot_addr = (uint32_t)platform_cpu_warmboot;
+
+	/* on boot all power-domains are on */
+	for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++)
+		cpuson_flags[cpu] = pmu_pd_on;
+
+	nonboot_cpus_off();
+}
diff --git a/plat/rockchip/rk3288/drivers/pmu/pmu.h b/plat/rockchip/rk3288/drivers/pmu/pmu.h
new file mode 100644
index 0000000..06d5528
--- /dev/null
+++ b/plat/rockchip/rk3288/drivers/pmu/pmu.h
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PMU_H
+#define PMU_H
+
+/* Allocate sp reginon in pmusram */
+#define PSRAM_SP_SIZE		0x80
+#define PSRAM_SP_BOTTOM		(PSRAM_SP_TOP - PSRAM_SP_SIZE)
+
+/*****************************************************************************
+ * pmu con,reg
+ *****************************************************************************/
+#define PMU_WAKEUP_CFG0		0x0
+#define PMU_WAKEUP_CFG1		0x4
+#define PMU_PWRDN_CON		0x8
+#define PMU_PWRDN_ST		0xc
+
+#define PMU_PWRMODE_CON		0x18
+#define PMU_BUS_IDE_REQ		0x10
+#define PMU_BUS_IDE_ST		0x14
+
+#define PMU_OSC_CNT		0x20
+#define PMU_PLL_CNT		0x24
+#define PMU_STABL_CNT		0x28
+#define PMU_DDRIO0_PWR_CNT	0x2c
+#define PMU_DDRIO1_PWR_CNT	0x30
+#define PMU_WKUPRST_CNT		0x44
+#define PMU_SFT_CON		0x48
+#define PMU_PWRMODE_CON1	0x90
+
+enum pmu_pdid {
+	PD_CPU0 = 0,
+	PD_CPU1,
+	PD_CPU2,
+	PD_CPU3,
+	PD_BUS = 5,
+	PD_PERI,
+	PD_VIO,
+	PD_VIDEO,
+	PD_GPU,
+	PD_SCU = 11,
+	PD_HEVC = 14,
+	PD_END
+};
+
+enum pmu_bus_ide {
+	bus_ide_req_bus = 0,
+	bus_ide_req_peri,
+	bus_ide_req_gpu,
+	bus_ide_req_video,
+	bus_ide_req_vio,
+	bus_ide_req_core,
+	bus_ide_req_alive,
+	bus_ide_req_dma,
+	bus_ide_req_cpup,
+	bus_ide_req_hevc,
+	bus_ide_req_end
+};
+
+enum pmu_pwrmode {
+	pmu_mode_en = 0,
+	pmu_mode_core_src_gt,
+	pmu_mode_glb_int_dis,
+	pmu_mode_l2_flush_en,
+	pmu_mode_bus_pd,
+	pmu_mode_cpu0_pd,
+	pmu_mode_scu_pd,
+	pmu_mode_pll_pd = 7,
+	pmu_mode_chip_pd,
+	pmu_mode_pwr_off_comb,
+	pmu_mode_pmu_alive_use_lf,
+	pmu_mode_pmu_use_lf,
+	pmu_mode_osc_dis = 12,
+	pmu_mode_input_clamp,
+	pmu_mode_wkup_rst,
+	pmu_mode_sref0_enter,
+	pmu_mode_sref1_enter,
+	pmu_mode_ddrio0_ret,
+	pmu_mode_ddrio1_ret,
+	pmu_mode_ddrc0_gt,
+	pmu_mode_ddrc1_gt,
+	pmu_mode_ddrio0_ret_deq,
+	pmu_mode_ddrio1_ret_deq,
+};
+
+enum pmu_pwrmode1 {
+	pmu_mode_clr_bus = 0,
+	pmu_mode_clr_core,
+	pmu_mode_clr_cpup,
+	pmu_mode_clr_alive,
+	pmu_mode_clr_dma,
+	pmu_mode_clr_peri,
+	pmu_mode_clr_gpu,
+	pmu_mode_clr_video,
+	pmu_mode_clr_hevc,
+	pmu_mode_clr_vio
+};
+
+enum pmu_sft_con {
+	pmu_sft_ddrio0_ret_cfg = 6,
+	pmu_sft_ddrio1_ret_cfg = 9,
+	pmu_sft_l2flsh = 15,
+};
+
+enum pmu_wakeup_cfg1 {
+	pmu_armint_wakeup_en = 0,
+	pmu_gpio_wakeup_negedge,
+	pmu_sdmmc0_wakeup_en,
+	pmu_gpioint_wakeup_en,
+};
+
+enum pmu_bus_idle_st {
+	pmu_idle_bus = 0,
+	pmu_idle_peri,
+	pmu_idle_gpu,
+	pmu_idle_video,
+	pmu_idle_vio,
+	pmu_idle_core,
+	pmu_idle_alive,
+	pmu_idle_dma,
+	pmu_idle_cpup,
+	pmu_idle_hevc,
+	pmu_idle_ack_bus = 16,
+	pmu_idle_ack_peri,
+	pmu_idle_ack_gpu,
+	pmu_idle_ack_video,
+	pmu_idle_ack_vio,
+	pmu_idle_ack_core,
+	pmu_idle_ack_alive,
+	pmu_idle_ack_dma,
+	pmu_idle_ack_cpup,
+	pmu_idle_ack_hevc,
+};
+
+#define CHECK_CPU_WFIE_BASE		(0)
+
+#define clstl_cpu_wfe		-1
+#define clstb_cpu_wfe		-1
+#define CKECK_WFEI_MSK		0
+
+
+#define PD_CTR_LOOP		500
+#define CHK_CPU_LOOP		500
+
+#define MAX_WAIT_CONUT 1000
+
+#endif /* PMU_H */
diff --git a/plat/rockchip/rk3288/drivers/secure/secure.c b/plat/rockchip/rk3288/drivers/secure/secure.c
new file mode 100644
index 0000000..68994e4
--- /dev/null
+++ b/plat/rockchip/rk3288/drivers/secure/secure.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+
+#include <plat_private.h>
+#include <secure.h>
+#include <soc.h>
+
+static void sgrf_ddr_rgn_global_bypass(uint32_t bypass)
+{
+	if (bypass)
+		/* set bypass (non-secure regions) for whole ddr regions */
+		mmio_write_32(SGRF_BASE + SGRF_SOC_CON(21),
+			      SGRF_DDR_RGN_BYPS);
+	else
+		/* cancel bypass for whole ddr regions */
+		mmio_write_32(SGRF_BASE + SGRF_SOC_CON(21),
+			      SGRF_DDR_RGN_NO_BYPS);
+}
+
+/**
+ * There are 8 + 1 regions for DDR secure control:
+ * DDR_RGN_0 ~ DDR_RGN_7: Per DDR_RGNs grain size is 1MB
+ * DDR_RGN_X - the memories of exclude DDR_RGN_0 ~ DDR_RGN_7
+ *
+ * SGRF_SOC_CON6 - start address of RGN_0 + control
+ * SGRF_SOC_CON7 - end address of RGN_0
+ * ...
+ * SGRF_SOC_CON20 - start address of the RGN_7 + control
+ * SGRF_SOC_CON21 - end address of the RGN_7 + RGN_X control
+ *
+ * @rgn - the DDR regions 0 ~ 7 which are can be configured.
+ * The @st and @ed indicate the start and end addresses for which to set
+ * the security, and the unit is byte. When the st_mb == 0, ed_mb == 0, the
+ * address range 0x0 ~ 0xfffff is secure.
+ *
+ * For example, if we would like to set the range [0, 32MB) is security via
+ * DDR_RGN0, then rgn == 0, st_mb == 0, ed_mb == 31.
+ */
+static void sgrf_ddr_rgn_config(uint32_t rgn, uintptr_t st, uintptr_t ed)
+{
+	uintptr_t st_mb, ed_mb;
+
+	assert(rgn <= 7);
+	assert(st < ed);
+
+	/* check aligned 1MB */
+	assert(st % SIZE_M(1) == 0);
+	assert(ed % SIZE_M(1) == 0);
+
+	st_mb = st / SIZE_M(1);
+	ed_mb = ed / SIZE_M(1);
+
+	/* set ddr region addr start */
+	mmio_write_32(SGRF_BASE + SGRF_SOC_CON(6 + (rgn * 2)),
+		      BITS_WITH_WMASK(st_mb, SGRF_DDR_RGN_ADDR_WMSK, 0));
+
+	/* set ddr region addr end */
+	mmio_write_32(SGRF_BASE + SGRF_SOC_CON(6 + (rgn * 2) + 1),
+		      BITS_WITH_WMASK((ed_mb - 1), SGRF_DDR_RGN_ADDR_WMSK, 0));
+
+	/* select region security */
+	mmio_write_32(SGRF_BASE + SGRF_SOC_CON(6 + (rgn * 2)),
+		      SGRF_DDR_RGN_SECURE_SEL);
+
+	/* enable region security */
+	mmio_write_32(SGRF_BASE + SGRF_SOC_CON(6 + (rgn * 2)),
+		      SGRF_DDR_RGN_SECURE_EN);
+}
+
+void secure_watchdog_gate(void)
+{
+	mmio_write_32(SGRF_BASE + SGRF_SOC_CON(0), SGRF_PCLK_WDT_GATE);
+}
+
+void secure_watchdog_ungate(void)
+{
+	mmio_write_32(SGRF_BASE + SGRF_SOC_CON(0), SGRF_PCLK_WDT_UNGATE);
+}
+
+__pmusramfunc void sram_secure_timer_init(void)
+{
+	mmio_write_32(STIMER1_BASE + TIMER_CONTROL_REG, 0);
+
+	mmio_write_32(STIMER1_BASE + TIMER_LOAD_COUNT0, 0xffffffff);
+	mmio_write_32(STIMER1_BASE + TIMER_LOAD_COUNT1, 0xffffffff);
+
+	/* auto reload & enable the timer */
+	mmio_write_32(STIMER1_BASE + TIMER_CONTROL_REG, TIMER_EN);
+}
+
+void secure_gic_init(void)
+{
+	/* (re-)enable non-secure access to the gic*/
+	mmio_write_32(CORE_AXI_BUS_BASE + CORE_AXI_SECURITY0,
+		      AXI_SECURITY0_GIC);
+}
+
+void secure_timer_init(void)
+{
+	mmio_write_32(STIMER1_BASE + TIMER_CONTROL_REG, 0);
+
+	mmio_write_32(STIMER1_BASE + TIMER_LOAD_COUNT0, 0xffffffff);
+	mmio_write_32(STIMER1_BASE + TIMER_LOAD_COUNT1, 0xffffffff);
+
+	/* auto reload & enable the timer */
+	mmio_write_32(STIMER1_BASE + TIMER_CONTROL_REG, TIMER_EN);
+}
+
+void secure_sgrf_init(void)
+{
+	/*
+	 * We use the first sram part to talk to the bootrom,
+	 * so make it secure.
+	 */
+	mmio_write_32(TZPC_BASE + TZPC_R0SIZE, TZPC_SRAM_SECURE_4K(1));
+
+	secure_gic_init();
+
+	/* set all master ip to non-secure */
+	mmio_write_32(SGRF_BASE + SGRF_SOC_CON(2), SGRF_SOC_CON2_MST_NS);
+	mmio_write_32(SGRF_BASE + SGRF_SOC_CON(3), SGRF_SOC_CON3_MST_NS);
+
+	/* setting all configurable ip into non-secure */
+	mmio_write_32(SGRF_BASE + SGRF_SOC_CON(4),
+		      SGRF_SOC_CON4_SECURE_WMSK /*TODO:|SGRF_STIMER_SECURE*/);
+	mmio_write_32(SGRF_BASE + SGRF_SOC_CON(5), SGRF_SOC_CON5_SECURE_WMSK);
+
+	/* secure dma to non-secure */
+	mmio_write_32(TZPC_BASE + TZPC_DECPROT1SET, 0xff);
+	mmio_write_32(TZPC_BASE + TZPC_DECPROT2SET, 0xff);
+	mmio_write_32(SGRF_BASE + SGRF_BUSDMAC_CON(1), 0x3800);
+	dsb();
+
+	/* rst dma1 */
+	mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(1),
+		      RST_DMA1_MSK | (RST_DMA1_MSK << 16));
+	/* rst dma2 */
+	mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(4),
+		      RST_DMA2_MSK | (RST_DMA2_MSK << 16));
+
+	dsb();
+
+	/* release dma1 rst*/
+	mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(1), (RST_DMA1_MSK << 16));
+	/* release dma2 rst*/
+	mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(4), (RST_DMA2_MSK << 16));
+}
+
+void secure_sgrf_ddr_rgn_init(void)
+{
+	sgrf_ddr_rgn_config(0, TZRAM_BASE, TZRAM_SIZE);
+	sgrf_ddr_rgn_global_bypass(0);
+}
diff --git a/plat/rockchip/rk3288/drivers/secure/secure.h b/plat/rockchip/rk3288/drivers/secure/secure.h
new file mode 100644
index 0000000..6c0b2b7
--- /dev/null
+++ b/plat/rockchip/rk3288/drivers/secure/secure.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SECURE_H
+#define SECURE_H
+
+/******************************************************************************
+ * TZPC TrustZone controller
+ ******************************************************************************/
+
+#define TZPC_R0SIZE			0x0
+#define TZPC_SRAM_SECURE_4K(n)		((n) > 0x200 ? 0x200 : (n))
+#define TZPC_DECPROT1STAT		0x80c
+#define TZPC_DECPROT1SET		0x810
+#define TZPC_DECPROT1CLR		0x814
+#define TZPC_DECPROT2STAT		0x818
+#define TZPC_DECPROT2SET		0x818
+#define TZPC_DECPROT2CLR		0x820
+
+/**************************************************
+ * sgrf reg, offset
+ **************************************************/
+/*
+ * soc_con0-5 start at 0x0, soc_con6-... start art 0x50
+ * adjusted for the 5 lower registers
+ */
+#define SGRF_SOC_CON(n)			((((n) < 6) ? 0x0 : 0x38) + (n) * 4)
+#define SGRF_BUSDMAC_CON(n)		(0x20 + (n) * 4)
+#define SGRF_CPU_CON(n)			(0x40 + (n) * 4)
+#define SGRF_SOC_STATUS(n)		(0x100 + (n) * 4)
+#define SGRF_FAST_BOOT_ADDR		0x120
+
+/* SGRF_SOC_CON0 */
+#define SGRF_FAST_BOOT_ENA		BIT_WITH_WMSK(8)
+#define SGRF_FAST_BOOT_DIS		WMSK_BIT(8)
+#define SGRF_PCLK_WDT_GATE		BIT_WITH_WMSK(6)
+#define SGRF_PCLK_WDT_UNGATE		WMSK_BIT(6)
+#define SGRF_PCLK_STIMER_GATE		BIT_WITH_WMSK(4)
+
+#define SGRF_SOC_CON2_MST_NS		0xffe0ffe0
+#define SGRF_SOC_CON3_MST_NS		0x003f003f
+
+/* SGRF_SOC_CON4 */
+#define SGRF_SOC_CON4_SECURE_WMSK	0xffff0000
+#define SGRF_DDRC1_SECURE		BIT_WITH_WMSK(12)
+#define SGRF_DDRC0_SECURE		BIT_WITH_WMSK(11)
+#define SGRF_PMUSRAM_SECURE		BIT_WITH_WMSK(8)
+#define SGRF_WDT_SECURE			BIT_WITH_WMSK(7)
+#define SGRF_STIMER_SECURE		BIT_WITH_WMSK(6)
+
+/* SGRF_SOC_CON5 */
+#define SGRF_SLV_SEC_BYPS		BIT_WITH_WMSK(15)
+#define SGRF_SLV_SEC_NO_BYPS		WMSK_BIT(15)
+#define SGRF_SOC_CON5_SECURE_WMSK	0x00ff0000
+
+/* ddr regions in SGRF_SOC_CON6 and following */
+#define SGRF_DDR_RGN_SECURE_SEL		BIT_WITH_WMSK(15)
+#define SGRF_DDR_RGN_SECURE_EN		BIT_WITH_WMSK(14)
+#define SGRF_DDR_RGN_ADDR_WMSK		0x0fff
+
+/* SGRF_SOC_CON21 */
+/* All security of the DDR RGNs are bypassed */
+#define SGRF_DDR_RGN_BYPS		BIT_WITH_WMSK(15)
+#define SGRF_DDR_RGN_NO_BYPS		WMSK_BIT(15)
+
+/* SGRF_CPU_CON0 */
+#define SGRF_DAPDEVICE_ENA		BIT_WITH_WMSK(0)
+#define SGRF_DAPDEVICE_MSK		WMSK_BIT(0)
+
+/*****************************************************************************
+ * core-axi
+ *****************************************************************************/
+#define CORE_AXI_SECURITY0		0x08
+#define AXI_SECURITY0_GIC		BIT(0)
+
+/*****************************************************************************
+ * secure timer
+ *****************************************************************************/
+#define TIMER_LOAD_COUNT0		0x00
+#define TIMER_LOAD_COUNT1		0x04
+#define TIMER_CURRENT_VALUE0		0x08
+#define TIMER_CURRENT_VALUE1		0x0C
+#define TIMER_CONTROL_REG		0x10
+#define TIMER_INTSTATUS			0x18
+
+#define TIMER_EN			0x1
+
+#define STIMER1_BASE			(STIME_BASE + 0x20)
+
+/* export secure operating APIs */
+void secure_watchdog_gate(void);
+void secure_watchdog_ungate(void);
+void secure_gic_init(void);
+void secure_timer_init(void);
+void secure_sgrf_init(void);
+void secure_sgrf_ddr_rgn_init(void);
+__pmusramfunc void sram_secure_timer_init(void);
+
+#endif /* SECURE_H */
diff --git a/plat/rockchip/rk3288/drivers/soc/soc.c b/plat/rockchip/rk3288/drivers/soc/soc.c
new file mode 100644
index 0000000..36f410b
--- /dev/null
+++ b/plat/rockchip/rk3288/drivers/soc/soc.c
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include <plat_private.h>
+#include <rk3288_def.h>
+#include <soc.h>
+#include <secure.h>
+
+/* sleep data for pll suspend */
+static struct deepsleep_data_s slp_data;
+
+/* Table of regions to map using the MMU. */
+const mmap_region_t plat_rk_mmap[] = {
+	MAP_REGION_FLAT(GIC400_BASE, GIC400_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(STIME_BASE, STIME_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(SGRF_BASE, SGRF_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(TZPC_BASE, TZPC_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(PMUSRAM_BASE, PMUSRAM_SIZE,
+			MT_MEMORY | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(SRAM_BASE, SRAM_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(PMU_BASE, PMU_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(UART0_BASE, UART0_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(UART1_BASE, UART1_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(UART2_BASE, UART2_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(UART3_BASE, UART3_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(UART4_BASE, UART4_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(CRU_BASE, CRU_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(GRF_BASE, GRF_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(DDR_PCTL0_BASE, DDR_PCTL0_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(DDR_PHY0_BASE, DDR_PHY0_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(DDR_PCTL1_BASE, DDR_PCTL1_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(DDR_PHY1_BASE, DDR_PHY1_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(SERVICE_BUS_BASE, SERVICE_BUS_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(CORE_AXI_BUS_BASE, CORE_AXI_BUS_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE),
+	{ 0 }
+};
+
+/* The RockChip power domain tree descriptor */
+const unsigned char rockchip_power_domain_tree_desc[] = {
+	/* No of root nodes */
+	PLATFORM_SYSTEM_COUNT,
+	/* No of children for the root node */
+	PLATFORM_CLUSTER_COUNT,
+	/* No of children for the first cluster node */
+	PLATFORM_CLUSTER0_CORE_COUNT,
+};
+
+void plat_rockchip_soc_init(void)
+{
+	secure_timer_init();
+	secure_sgrf_init();
+	/*
+	 * We cannot enable ddr security at this point, as the kernel
+	 * seems to have an issue with it even living in the same 128MB
+	 * memory block. Only when moving the kernel to the second
+	 * 128MB block does it not conflict, but then we'd loose this
+	 * memory area for use. Late maybe enable
+	 * secure_sgrf_ddr_rgn_init();
+	 */
+}
+
+void regs_update_bits(uintptr_t addr, uint32_t val,
+		      uint32_t mask, uint32_t shift)
+{
+	uint32_t tmp, orig;
+
+	orig = mmio_read_32(addr);
+
+	tmp = orig & ~(mask << shift);
+	tmp |= (val & mask) << shift;
+
+	if (tmp != orig)
+		mmio_write_32(addr, tmp);
+	dsb();
+}
+
+static void pll_save(uint32_t pll_id)
+{
+	uint32_t *pll = slp_data.pll_con[pll_id];
+
+	pll[0] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 0));
+	pll[1] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 1));
+	pll[2] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 2));
+	pll[3] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 3));
+}
+
+void clk_plls_suspend(void)
+{
+	pll_save(NPLL_ID);
+	pll_save(CPLL_ID);
+	pll_save(GPLL_ID);
+	pll_save(APLL_ID);
+	slp_data.pll_mode = mmio_read_32(CRU_BASE + PLL_MODE_CON);
+
+	/*
+	 * Switch PLLs other than DPLL (for SDRAM) to slow mode to
+	 * avoid crashes on resume. The Mask ROM on the system will
+	 * put APLL, CPLL, and GPLL into slow mode at resume time
+	 * anyway (which is why we restore them), but we might not
+	 * even make it to the Mask ROM if this isn't done at suspend
+	 * time.
+	 *
+	 * NOTE: only APLL truly matters here, but we'll do them all.
+	 */
+	mmio_write_32(CRU_BASE + PLL_MODE_CON, 0xf3030000);
+}
+
+void clk_plls_resume(void)
+{
+	/* restore pll-modes */
+	mmio_write_32(CRU_BASE + PLL_MODE_CON,
+		      slp_data.pll_mode | REG_SOC_WMSK);
+}
+
+void clk_gate_con_save(void)
+{
+	uint32_t i = 0;
+
+	for (i = 0; i < CRU_CLKGATES_CON_CNT; i++)
+		slp_data.cru_gate_con[i] =
+			mmio_read_32(CRU_BASE + CRU_CLKGATES_CON(i));
+}
+
+void clk_gate_con_disable(void)
+{
+	uint32_t i;
+
+	for (i = 0; i < CRU_CLKGATES_CON_CNT; i++)
+		mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(i), REG_SOC_WMSK);
+}
+
+void clk_gate_con_restore(void)
+{
+	uint32_t i;
+
+	for (i = 0; i < CRU_CLKGATES_CON_CNT; i++)
+		mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(i),
+			      REG_SOC_WMSK | slp_data.cru_gate_con[i]);
+}
+
+void clk_sel_con_save(void)
+{
+	uint32_t i = 0;
+
+	for (i = 0; i < CRU_CLKSELS_CON_CNT; i++)
+		slp_data.cru_sel_con[i] =
+			mmio_read_32(CRU_BASE + CRU_CLKSELS_CON(i));
+}
+
+void clk_sel_con_restore(void)
+{
+	uint32_t i, val;
+
+	for (i = 0; i < CRU_CLKSELS_CON_CNT; i++) {
+		/* fractional dividers don't have write-masks */
+		if ((i >= 7 && i <= 9) ||
+		    (i >= 17 && i <= 20) ||
+		    (i == 23) || (i == 41))
+			val = slp_data.cru_sel_con[i];
+		else
+			val = slp_data.cru_sel_con[i] | REG_SOC_WMSK;
+
+		mmio_write_32(CRU_BASE + CRU_CLKSELS_CON(i), val);
+	}
+}
+
+void __dead2 rockchip_soc_soft_reset(void)
+{
+	uint32_t temp_val;
+
+	/*
+	 * Switch PLLs other than DPLL (for SDRAM) to slow mode to
+	 * avoid crashes on resume. The Mask ROM on the system will
+	 * put APLL, CPLL, and GPLL into slow mode at resume time
+	 * anyway (which is why we restore them), but we might not
+	 * even make it to the Mask ROM if this isn't done at suspend
+	 * time.
+	 *
+	 * NOTE: only APLL truly matters here, but we'll do them all.
+	 */
+	mmio_write_32(CRU_BASE + PLL_MODE_CON, 0xf3030000);
+
+	temp_val = mmio_read_32(CRU_BASE + CRU_GLB_RST_CON);
+	temp_val &= ~PMU_RST_MASK;
+	temp_val |= PMU_RST_BY_SECOND_SFT;
+	mmio_write_32(CRU_BASE + CRU_GLB_RST_CON, temp_val);
+	mmio_write_32(CRU_BASE + CRU_GLB_SRST_SND, 0xeca8);
+
+	/*
+	 * Maybe the HW needs some times to reset the system,
+	 * so we do not hope the core to excute valid codes.
+	 */
+	while (1)
+		;
+}
diff --git a/plat/rockchip/rk3288/drivers/soc/soc.h b/plat/rockchip/rk3288/drivers/soc/soc.h
new file mode 100644
index 0000000..b96c4dc
--- /dev/null
+++ b/plat/rockchip/rk3288/drivers/soc/soc.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SOC_H
+#define SOC_H
+
+enum plls_id {
+	APLL_ID = 0,
+	DPLL_ID,
+	CPLL_ID,
+	GPLL_ID,
+	NPLL_ID,
+	END_PLL_ID,
+};
+
+
+#define CYCL_24M_CNT_US(us)	(24 * (us))
+#define CYCL_24M_CNT_MS(ms)	((ms) * CYCL_24M_CNT_US(1000))
+
+/*****************************************************************************
+ * grf regs
+ *****************************************************************************/
+#define GRF_UOC0_CON0		0x320
+#define GRF_UOC1_CON0		0x334
+#define GRF_UOC2_CON0		0x348
+#define GRF_SIDDQ		BIT(13)
+
+/*****************************************************************************
+ * cru reg, offset
+ *****************************************************************************/
+#define CRU_SOFTRST_CON		0x1b8
+#define CRU_SOFTRSTS_CON(n)	(CRU_SOFTRST_CON + ((n) * 4))
+#define CRU_SOFTRSTS_CON_CNT	11
+
+#define RST_DMA1_MSK		0x4
+#define RST_DMA2_MSK		0x1
+
+#define CRU_CLKSEL_CON		0x60
+#define CRU_CLKSELS_CON(i)	(CRU_CLKSEL_CON + ((i) * 4))
+#define CRU_CLKSELS_CON_CNT	42
+
+#define CRU_CLKGATE_CON		0x160
+#define CRU_CLKGATES_CON(i)	(CRU_CLKGATE_CON + ((i) * 4))
+#define CRU_CLKGATES_CON_CNT	18
+
+#define CRU_GLB_SRST_FST	0x1b0
+#define CRU_GLB_SRST_SND	0x1b4
+#define CRU_GLB_RST_CON		0x1f0
+
+#define CRU_CONS_GATEID(i)	(16 * (i))
+#define GATE_ID(reg, bit)	(((reg) * 16) + (bit))
+
+#define PMU_RST_MASK		0x3
+#define PMU_RST_BY_FIRST_SFT	(0 << 2)
+#define PMU_RST_BY_SECOND_SFT	(1 << 2)
+#define PMU_RST_NOT_BY_SFT	(2 << 2)
+
+/***************************************************************************
+ * pll
+ ***************************************************************************/
+#define PLL_CON_COUNT		4
+#define PLL_CONS(id, i)		((id) * 0x10 + ((i) * 4))
+#define PLL_PWR_DN_MSK		BIT(1)
+#define PLL_PWR_DN		REG_WMSK_BITS(1, 1, 0x1)
+#define PLL_PWR_ON		REG_WMSK_BITS(0, 1, 0x1)
+#define PLL_RESET		REG_WMSK_BITS(1, 5, 0x1)
+#define PLL_RESET_RESUME	REG_WMSK_BITS(0, 5, 0x1)
+#define PLL_BYPASS_MSK		BIT(0)
+#define PLL_BYPASS_W_MSK	(PLL_BYPASS_MSK << 16)
+#define PLL_BYPASS		REG_WMSK_BITS(1, 0, 0x1)
+#define PLL_NO_BYPASS		REG_WMSK_BITS(0, 0, 0x1)
+
+#define PLL_MODE_CON		0x50
+
+struct deepsleep_data_s {
+	uint32_t pll_con[END_PLL_ID][PLL_CON_COUNT];
+	uint32_t pll_mode;
+	uint32_t cru_sel_con[CRU_CLKSELS_CON_CNT];
+	uint32_t cru_gate_con[CRU_CLKGATES_CON_CNT];
+};
+
+#define REG_W_MSK(bits_shift, msk) \
+		((msk) << ((bits_shift) + 16))
+#define REG_VAL_CLRBITS(val, bits_shift, msk) \
+		((val) & (~((msk) << bits_shift)))
+#define REG_SET_BITS(bits, bits_shift, msk) \
+		(((bits) & (msk)) << (bits_shift))
+#define REG_WMSK_BITS(bits, bits_shift, msk) \
+		(REG_W_MSK(bits_shift, msk) | \
+		REG_SET_BITS(bits, bits_shift, msk))
+#define REG_SOC_WMSK		0xffff0000
+
+#define regs_update_bit_set(addr, shift) \
+		regs_update_bits((addr), 0x1, 0x1, (shift))
+#define regs_update_bit_clr(addr, shift) \
+		regs_update_bits((addr), 0x0, 0x1, (shift))
+
+void regs_update_bits(uintptr_t addr, uint32_t val,
+		      uint32_t mask, uint32_t shift);
+void clk_plls_suspend(void);
+void clk_plls_resume(void);
+void clk_gate_con_save(void);
+void clk_gate_con_disable(void);
+void clk_gate_con_restore(void);
+void clk_sel_con_save(void);
+void clk_sel_con_restore(void);
+#endif /* SOC_H */
diff --git a/plat/rockchip/rk3288/include/plat_sip_calls.h b/plat/rockchip/rk3288/include/plat_sip_calls.h
new file mode 100644
index 0000000..66c4868
--- /dev/null
+++ b/plat/rockchip/rk3288/include/plat_sip_calls.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_SIP_CALLS_H
+#define PLAT_SIP_CALLS_H
+
+#define RK_PLAT_SIP_NUM_CALLS	0
+
+#endif /* PLAT_SIP_CALLS_H */
diff --git a/plat/rockchip/rk3288/include/plat_sp_min.ld.S b/plat/rockchip/rk3288/include/plat_sp_min.ld.S
new file mode 100644
index 0000000..2878437
--- /dev/null
+++ b/plat/rockchip/rk3288/include/plat_sp_min.ld.S
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef ROCKCHIP_PLAT_LD_S
+#define ROCKCHIP_PLAT_LD_S
+
+#include <lib/xlat_tables/xlat_tables_defs.h>
+
+MEMORY {
+    SRAM (rwx): ORIGIN = SRAM_BASE, LENGTH = SRAM_SIZE
+    PMUSRAM (rwx): ORIGIN = PMUSRAM_BASE, LENGTH = PMUSRAM_RSIZE
+}
+
+SECTIONS
+{
+	. = SRAM_BASE;
+	ASSERT(. == ALIGN(PAGE_SIZE),
+		"SRAM_BASE address is not aligned on a page boundary.")
+
+	.text_sram : ALIGN(PAGE_SIZE) {
+		__bl32_sram_text_start = .;
+		*(.sram.text)
+		*(.sram.rodata)
+		__bl32_sram_text_real_end = .;
+		. = ALIGN(PAGE_SIZE);
+		__bl32_sram_text_end = .;
+	} >SRAM
+	ASSERT((__bl32_sram_text_real_end - __bl32_sram_text_start) <=
+		SRAM_TEXT_LIMIT, ".text_sram has exceeded its limit")
+
+	.data_sram : ALIGN(PAGE_SIZE) {
+		__bl32_sram_data_start = .;
+		*(.sram.data)
+		__bl32_sram_data_real_end = .;
+		. = ALIGN(PAGE_SIZE);
+		__bl32_sram_data_end = .;
+	} >SRAM
+	ASSERT((__bl32_sram_data_real_end - __bl32_sram_data_start) <=
+		SRAM_DATA_LIMIT, ".data_sram has exceeded its limit")
+
+	.stack_sram : ALIGN(PAGE_SIZE) {
+		__bl32_sram_stack_start = .;
+		. += PAGE_SIZE;
+		__bl32_sram_stack_end = .;
+	} >SRAM
+
+	. = PMUSRAM_BASE;
+
+	/*
+	 * pmu_cpuson_entrypoint request address
+	 * align 64K when resume, so put it in the
+	 * start of pmusram
+	 */
+	.pmusram : {
+		ASSERT(. == ALIGN(64 * 1024),
+			".pmusram.entry request 64K aligned.");
+		*(.pmusram.entry)
+
+		__bl32_pmusram_text_start = .;
+		*(.pmusram.text)
+		*(.pmusram.rodata)
+		__bl32_pmusram_text_end = .;
+
+		__bl32_pmusram_data_start = .;
+		*(.pmusram.data)
+		__bl32_pmusram_data_end = .;
+	} >PMUSRAM
+}
+
+#endif /* ROCKCHIP_PLAT_LD_S */
diff --git a/plat/rockchip/rk3288/include/platform_def.h b/plat/rockchip/rk3288/include/platform_def.h
new file mode 100644
index 0000000..e24aeff
--- /dev/null
+++ b/plat/rockchip/rk3288/include/platform_def.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <arch.h>
+#include <lib/utils_def.h>
+#include <plat/common/common_def.h>
+
+#include <bl32_param.h>
+#include <rk3288_def.h>
+
+/*******************************************************************************
+ * Platform binary types for linking
+ ******************************************************************************/
+#define PLATFORM_LINKER_FORMAT		"elf32-littlearm"
+#define PLATFORM_LINKER_ARCH		arm
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+
+/* Size of cacheable stacks */
+#if defined(IMAGE_BL1)
+#define PLATFORM_STACK_SIZE 0x440
+#elif defined(IMAGE_BL2)
+#define PLATFORM_STACK_SIZE 0x400
+#elif defined(IMAGE_BL32)
+#define PLATFORM_STACK_SIZE 0x800
+#endif
+
+#define FIRMWARE_WELCOME_STR		"Booting Trusted Firmware\n"
+
+#define PLATFORM_MAX_AFFLVL		MPIDR_AFFLVL2
+#define PLATFORM_SYSTEM_COUNT		1
+#define PLATFORM_CLUSTER_COUNT		1
+#define PLATFORM_CLUSTER0_CORE_COUNT	4
+#define PLATFORM_CORE_COUNT		(PLATFORM_CLUSTER0_CORE_COUNT)
+#define PLATFORM_MAX_CPUS_PER_CLUSTER	4
+#define PLATFORM_NUM_AFFS		(PLATFORM_SYSTEM_COUNT +	\
+					 PLATFORM_CLUSTER_COUNT +	\
+					 PLATFORM_CORE_COUNT)
+
+#define PLAT_RK_CLST_TO_CPUID_SHIFT	6
+
+#define PLAT_MAX_PWR_LVL		MPIDR_AFFLVL2
+
+/*
+ * This macro defines the deepest retention state possible. A higher state
+ * id will represent an invalid or a power down state.
+ */
+#define PLAT_MAX_RET_STATE		U(1)
+
+/*
+ * This macro defines the deepest power down states possible. Any state ID
+ * higher than this is invalid.
+ */
+#define PLAT_MAX_OFF_STATE		U(2)
+
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 32)
+#define PLAT_PHY_ADDR_SPACE_SIZE	(1ULL << 32)
+#define MAX_XLAT_TABLES			8
+#define MAX_MMAP_REGIONS		18
+
+/*******************************************************************************
+ * Declarations and constants to access the mailboxes safely. Each mailbox is
+ * aligned on the biggest cache line size in the platform. This is known only
+ * to the platform as it might have a combination of integrated and external
+ * caches. Such alignment ensures that two maiboxes do not sit on the same cache
+ * line at any cache level. They could belong to different cpus/clusters &
+ * get written while being protected by different locks causing corruption of
+ * a valid mailbox address.
+ ******************************************************************************/
+#define CACHE_WRITEBACK_SHIFT		6
+#define CACHE_WRITEBACK_GRANULE		(1 << CACHE_WRITEBACK_SHIFT)
+
+/*
+ * Define GICD and GICC and GICR base
+ */
+#define PLAT_RK_GICD_BASE		RK3288_GICD_BASE
+#define PLAT_RK_GICC_BASE		RK3288_GICC_BASE
+
+#define PLAT_RK_UART_BASE		UART2_BASE
+#define PLAT_RK_UART_CLOCK		RK3288_UART_CLOCK
+#define PLAT_RK_UART_BAUDRATE		RK3288_BAUDRATE
+
+/* ClusterId is always 0x5 on rk3288, filter it */
+#define PLAT_RK_MPIDR_CLUSTER_MASK	0
+#define PLAT_RK_PRIMARY_CPU		0x0
+
+#define PSRAM_DO_DDR_RESUME		0
+#define PSRAM_CHECK_WAKEUP_CPU		0
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/rockchip/rk3288/include/shared/bl32_param.h b/plat/rockchip/rk3288/include/shared/bl32_param.h
new file mode 100644
index 0000000..743dad4
--- /dev/null
+++ b/plat/rockchip/rk3288/include/shared/bl32_param.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BL32_PARAM_H
+#define BL32_PARAM_H
+
+/*******************************************************************************
+ * Platform memory map related constants
+ ******************************************************************************/
+/* TF txet, ro, rw, Size: 2MB */
+#define TZRAM_BASE		(0x0)
+#define TZRAM_SIZE		(0x200000)
+
+/*******************************************************************************
+ * BL32 specific defines.
+ ******************************************************************************/
+/*
+ * Put BL32 at the top of the Trusted RAM
+ */
+#define BL32_BASE			(TZRAM_BASE + 0x100000)
+#define BL32_LIMIT			(TZRAM_BASE + TZRAM_SIZE)
+
+#endif /* BL32_PARAM_H */
diff --git a/plat/rockchip/rk3288/plat_sip_calls.c b/plat/rockchip/rk3288/plat_sip_calls.c
new file mode 100644
index 0000000..5918d58
--- /dev/null
+++ b/plat/rockchip/rk3288/plat_sip_calls.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <lib/mmio.h>
+
+#include <plat_sip_calls.h>
+#include <rockchip_sip_svc.h>
+
+uintptr_t rockchip_plat_sip_handler(uint32_t smc_fid,
+				   u_register_t x1,
+				   u_register_t x2,
+				   u_register_t x3,
+				   u_register_t x4,
+				   void *cookie,
+				   void *handle,
+				   u_register_t flags)
+{
+	ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
+	SMC_RET1(handle, SMC_UNK);
+}
diff --git a/plat/rockchip/rk3288/platform.mk b/plat/rockchip/rk3288/platform.mk
new file mode 100644
index 0000000..1811b3a
--- /dev/null
+++ b/plat/rockchip/rk3288/platform.mk
@@ -0,0 +1,67 @@
+#
+# Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+ARM_CORTEX_A12		:=	yes
+ARM_ARCH_MAJOR		:=	7
+
+RK_PLAT			:=	plat/rockchip
+RK_PLAT_SOC		:=	${RK_PLAT}/${PLAT}
+RK_PLAT_COMMON		:=	${RK_PLAT}/common
+
+DISABLE_BIN_GENERATION	:=	1
+
+PLAT_INCLUDES		:=	-I${RK_PLAT_COMMON}/				\
+				-I${RK_PLAT_COMMON}/include/			\
+				-I${RK_PLAT_COMMON}/aarch32/			\
+				-I${RK_PLAT_COMMON}/drivers/pmu/		\
+				-I${RK_PLAT_SOC}/				\
+				-I${RK_PLAT_SOC}/drivers/pmu/			\
+				-I${RK_PLAT_SOC}/drivers/secure/		\
+				-I${RK_PLAT_SOC}/drivers/soc/			\
+				-I${RK_PLAT_SOC}/include/			\
+				-I${RK_PLAT_SOC}/include/shared/		\
+
+RK_GIC_SOURCES         :=	drivers/arm/gic/common/gic_common.c		\
+				drivers/arm/gic/v2/gicv2_main.c			\
+				drivers/arm/gic/v2/gicv2_helpers.c		\
+				plat/common/plat_gicv2.c			\
+				${RK_PLAT}/common/rockchip_gicv2.c
+
+PLAT_BL_COMMON_SOURCES	:=	plat/common/aarch32/crash_console_helpers.S	\
+				plat/common/plat_psci_common.c
+
+PLAT_BL_COMMON_SOURCES	+=	lib/xlat_tables/xlat_tables_common.c		\
+				lib/xlat_tables/aarch32/xlat_tables.c
+
+BL32_SOURCES		+=	${RK_GIC_SOURCES}				\
+				drivers/arm/cci/cci.c				\
+				drivers/ti/uart/aarch32/16550_console.S		\
+				drivers/delay_timer/delay_timer.c		\
+				drivers/delay_timer/generic_delay_timer.c	\
+				lib/cpus/aarch32/cortex_a12.S			\
+				${RK_PLAT_COMMON}/aarch32/plat_helpers.S	\
+				${RK_PLAT_COMMON}/params_setup.c		\
+				${RK_PLAT_COMMON}/aarch32/pmu_sram_cpus_on.S	\
+				${RK_PLAT_COMMON}/plat_pm.c			\
+				${RK_PLAT_COMMON}/plat_topology.c		\
+				${RK_PLAT_COMMON}/aarch32/platform_common.c	\
+				${RK_PLAT_COMMON}/rockchip_sip_svc.c		\
+				${RK_PLAT_SOC}/plat_sip_calls.c			\
+				${RK_PLAT_SOC}/drivers/pmu/pmu.c		\
+				${RK_PLAT_SOC}/drivers/secure/secure.c		\
+				${RK_PLAT_SOC}/drivers/soc/soc.c		\
+
+MULTI_CONSOLE_API	:=	1
+
+include lib/coreboot/coreboot.mk
+include lib/libfdt/libfdt.mk
+
+$(eval $(call add_define,PLAT_SP_MIN_EXTRA_LD_SCRIPT))
+
+# Do not enable SVE
+ENABLE_SVE_FOR_NS	:=	0
+
+WORKAROUND_CVE_2017_5715	:=	0
diff --git a/plat/rockchip/rk3288/rk3288_def.h b/plat/rockchip/rk3288/rk3288_def.h
new file mode 100644
index 0000000..7bff865
--- /dev/null
+++ b/plat/rockchip/rk3288/rk3288_def.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RK3288_DEF_H
+#define RK3288_DEF_H
+
+/* Special value used to verify platform parameters from BL2 to BL31 */
+#define RK_BL31_PLAT_PARAM_VAL	0x0f1e2d3c4b5a6978ULL
+
+#define SIZE_K(n)		((n) * 1024)
+#define SIZE_M(n)		((n) * 1024 * 1024)
+
+#define SRAM_TEXT_LIMIT		(4 * 1024)
+#define SRAM_DATA_LIMIT		(4 * 1024)
+
+#define DDR_PCTL0_BASE		0xff610000
+#define DDR_PCTL0_SIZE		SIZE_K(64)
+
+#define DDR_PHY0_BASE		0xff620000
+#define DDR_PHY0_SIZE		SIZE_K(64)
+
+#define DDR_PCTL1_BASE		0xff630000
+#define DDR_PCTL1_SIZE		SIZE_K(64)
+
+#define DDR_PHY1_BASE		0xff640000
+#define DDR_PHY1_SIZE		SIZE_K(64)
+
+#define UART0_BASE		0xff180000
+#define UART0_SIZE		SIZE_K(64)
+
+#define UART1_BASE		0xff190000
+#define UART1_SIZE		SIZE_K(64)
+
+#define UART2_BASE		0xff690000
+#define UART2_SIZE		SIZE_K(64)
+
+#define UART3_BASE		0xff1b0000
+#define UART3_SIZE		SIZE_K(64)
+
+#define UART4_BASE		0xff1c0000
+#define UART4_SIZE		SIZE_K(64)
+
+/* 96k instead of 64k? */
+#define SRAM_BASE		0xff700000
+#define SRAM_SIZE		SIZE_K(64)
+
+#define PMUSRAM_BASE		0xff720000
+#define PMUSRAM_SIZE		SIZE_K(4)
+#define PMUSRAM_RSIZE		SIZE_K(4)
+
+#define PMU_BASE		0xff730000
+#define PMU_SIZE		SIZE_K(64)
+
+#define SGRF_BASE		0xff740000
+#define SGRF_SIZE		SIZE_K(64)
+
+#define CRU_BASE		0xff760000
+#define CRU_SIZE		SIZE_K(64)
+
+#define GRF_BASE		0xff770000
+#define GRF_SIZE		SIZE_K(64)
+
+/* timer 6+7 can be set as secure in SGRF */
+#define STIME_BASE		0xff810000
+#define STIME_SIZE		SIZE_K(64)
+
+#define SERVICE_BUS_BASE	0xffac0000
+#define SERVICE_BUS_SIZE	SIZE_K(64)
+
+#define TZPC_BASE		0xffb00000
+#define TZPC_SIZE		SIZE_K(64)
+
+#define GIC400_BASE		0xffc00000
+#define GIC400_SIZE		SIZE_K(64)
+
+#define CORE_AXI_BUS_BASE	0xffd00000
+#define CORE_AXI_BUS_SIZE	SIZE_M(1)
+
+#define COLD_BOOT_BASE		0xffff0000
+/**************************************************************************
+ * UART related constants
+ **************************************************************************/
+#define RK3288_BAUDRATE		115200
+#define RK3288_UART_CLOCK	24000000
+
+/******************************************************************************
+ * System counter frequency related constants
+ ******************************************************************************/
+#define SYS_COUNTER_FREQ_IN_TICKS	24000000
+
+/******************************************************************************
+ * GIC-400 & interrupt handling related constants
+ ******************************************************************************/
+
+/* Base rk_platform compatible GIC memory map */
+#define RK3288_GICD_BASE		(GIC400_BASE + 0x1000)
+#define RK3288_GICC_BASE		(GIC400_BASE + 0x2000)
+#define RK3288_GICR_BASE		0	/* no GICR in GIC-400 */
+
+/******************************************************************************
+ * sgi, ppi
+ ******************************************************************************/
+#define RK_IRQ_SEC_PHY_TIMER	29
+
+/* what are these, and are they present on rk3288? */
+#define RK_IRQ_SEC_SGI_0	8
+#define RK_IRQ_SEC_SGI_1	9
+#define RK_IRQ_SEC_SGI_2	10
+#define RK_IRQ_SEC_SGI_3	11
+#define RK_IRQ_SEC_SGI_4	12
+#define RK_IRQ_SEC_SGI_5	13
+#define RK_IRQ_SEC_SGI_6	14
+#define RK_IRQ_SEC_SGI_7	15
+
+/*
+ * Define a list of Group 0 interrupts.
+ */
+#define PLAT_RK_GICV2_G0_IRQS						\
+	INTR_PROP_DESC(RK_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY,	\
+		       GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),		\
+	INTR_PROP_DESC(RK_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY,	\
+		       GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL)
+
+#endif /* RK3288_DEF_H */
diff --git a/plat/rockchip/rk3288/sp_min/sp_min-rk3288.mk b/plat/rockchip/rk3288/sp_min/sp_min-rk3288.mk
new file mode 100644
index 0000000..befdca3
--- /dev/null
+++ b/plat/rockchip/rk3288/sp_min/sp_min-rk3288.mk
@@ -0,0 +1,8 @@
+#
+# Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+BL32_SOURCES		+=	plat/common/aarch32/platform_mp_stack.S		\
+				plat/rockchip/common/sp_min_plat_setup.c
diff --git a/plat/rockchip/rk3328/drivers/pmu/pmu.h b/plat/rockchip/rk3328/drivers/pmu/pmu.h
index d98f53c..dfb8912 100644
--- a/plat/rockchip/rk3328/drivers/pmu/pmu.h
+++ b/plat/rockchip/rk3328/drivers/pmu/pmu.h
@@ -49,8 +49,6 @@
 
 extern void *pmu_cpuson_entrypoint_start;
 extern void *pmu_cpuson_entrypoint_end;
-extern uint64_t cpuson_entry_point[PLATFORM_CORE_COUNT];
-extern uint32_t cpuson_flags[PLATFORM_CORE_COUNT];
 
 #define CORES_PM_DISABLE	0x0
 
diff --git a/plat/rockchip/rk3328/drivers/soc/soc.c b/plat/rockchip/rk3328/drivers/soc/soc.c
index d216020..59d8572 100644
--- a/plat/rockchip/rk3328/drivers/soc/soc.c
+++ b/plat/rockchip/rk3328/drivers/soc/soc.c
@@ -19,6 +19,10 @@
 
 /* Table of regions to map using the MMU. */
 const mmap_region_t plat_rk_mmap[] = {
+	MAP_REGION_FLAT(UART0_BASE, UART0_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(UART1_BASE, UART1_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE),
 	MAP_REGION_FLAT(UART2_BASE, UART2_SIZE,
 			MT_DEVICE | MT_RW | MT_SECURE),
 	MAP_REGION_FLAT(PMU_BASE, PMU_SIZE,
diff --git a/plat/rockchip/rk3328/include/platform_def.h b/plat/rockchip/rk3328/include/platform_def.h
index b62c868..3104d9f 100644
--- a/plat/rockchip/rk3328/include/platform_def.h
+++ b/plat/rockchip/rk3328/include/platform_def.h
@@ -105,7 +105,7 @@
 #define PLAT_RK_GICD_BASE	RK3328_GICD_BASE
 #define PLAT_RK_GICC_BASE	RK3328_GICC_BASE
 
-#define PLAT_RK_UART_BASE	RK3328_UART2_BASE
+#define PLAT_RK_UART_BASE	UART2_BASE
 #define PLAT_RK_UART_CLOCK	RK3328_UART_CLOCK
 #define PLAT_RK_UART_BAUDRATE	RK3328_BAUDRATE
 
diff --git a/plat/rockchip/rk3328/platform.mk b/plat/rockchip/rk3328/platform.mk
index 18b1b94..3e70330 100644
--- a/plat/rockchip/rk3328/platform.mk
+++ b/plat/rockchip/rk3328/platform.mk
@@ -8,13 +8,13 @@
 RK_PLAT_SOC		:=	${RK_PLAT}/${PLAT}
 RK_PLAT_COMMON		:=	${RK_PLAT}/common
 
-include lib/libfdt/libfdt.mk
+DISABLE_BIN_GENERATION	:=	1
 
 PLAT_INCLUDES		:=	-Idrivers/arm/gic/common/			\
 				-Idrivers/arm/gic/v2/			\
 				-I${RK_PLAT_COMMON}/                            \
 				-I${RK_PLAT_COMMON}/include/                    \
-				-I${RK_PLAT_COMMON}/pmusram                     \
+				-I${RK_PLAT_COMMON}/aarch64/			\
 				-I${RK_PLAT_COMMON}/drivers/pmu/                \
 				-I${RK_PLAT_COMMON}/drivers/parameter/		\
 				-I${RK_PLAT_SOC}/				\
@@ -40,11 +40,11 @@
 				drivers/delay_timer/generic_delay_timer.c	\
 				lib/cpus/aarch64/aem_generic.S			\
 				lib/cpus/aarch64/cortex_a53.S			\
-				$(LIBFDT_SRCS)					\
 				${RK_PLAT_COMMON}/drivers/parameter/ddr_parameter.c	\
 				${RK_PLAT_COMMON}/aarch64/plat_helpers.S	\
+				${RK_PLAT_COMMON}/params_setup.c		\
 				${RK_PLAT_COMMON}/bl31_plat_setup.c		\
-				${RK_PLAT_COMMON}/pmusram/pmu_sram_cpus_on.S	\
+				${RK_PLAT_COMMON}/aarch64/pmu_sram_cpus_on.S	\
 				${RK_PLAT_COMMON}/plat_pm.c			\
 				${RK_PLAT_COMMON}/plat_topology.c		\
 				${RK_PLAT_COMMON}/aarch64/platform_common.c	\
@@ -54,6 +54,7 @@
 MULTI_CONSOLE_API	:=	1
 
 include lib/coreboot/coreboot.mk
+include lib/libfdt/libfdt.mk
 
 $(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT))
 $(eval $(call add_define,PLAT_SKIP_OPTEE_S_EL1_INT_REGISTER))
diff --git a/plat/rockchip/rk3328/rk3328_def.h b/plat/rockchip/rk3328/rk3328_def.h
index 0ce13ad..60055e8 100644
--- a/plat/rockchip/rk3328/rk3328_def.h
+++ b/plat/rockchip/rk3328/rk3328_def.h
@@ -15,6 +15,12 @@
 /* Special value used to verify platform parameters from BL2 to BL3-1 */
 #define RK_BL31_PLAT_PARAM_VAL	0x0f1e2d3c4b5a6978ULL
 
+#define UART0_BASE		0xff110000
+#define UART0_SIZE		SIZE_K(64)
+
+#define UART1_BASE		0xff120000
+#define UART1_SIZE		SIZE_K(64)
+
 #define UART2_BASE		0xff130000
 #define UART2_SIZE		SIZE_K(64)
 
@@ -97,7 +103,6 @@
 /**************************************************************************
  * UART related constants
  **************************************************************************/
-#define RK3328_UART2_BASE	UART2_BASE
 #define RK3328_BAUDRATE	1500000
 #define RK3328_UART_CLOCK	24000000
 
diff --git a/plat/rockchip/rk3368/drivers/soc/soc.c b/plat/rockchip/rk3368/drivers/soc/soc.c
index 0c34554..7d51bb8 100644
--- a/plat/rockchip/rk3368/drivers/soc/soc.c
+++ b/plat/rockchip/rk3368/drivers/soc/soc.c
@@ -30,7 +30,15 @@
 			MT_MEMORY | MT_RW | MT_SECURE),
 	MAP_REGION_FLAT(PMU_BASE, PMU_SIZE,
 			MT_DEVICE | MT_RW | MT_SECURE),
-	MAP_REGION_FLAT(UART_DBG_BASE, UART_DBG_SIZE,
+	MAP_REGION_FLAT(UART0_BASE, UART0_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(UART1_BASE, UART1_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(UART2_BASE, UART2_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(UART3_BASE, UART3_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(UART4_BASE, UART4_SIZE,
 			MT_DEVICE | MT_RW | MT_SECURE),
 	MAP_REGION_FLAT(CRU_BASE, CRU_SIZE,
 			MT_DEVICE | MT_RW | MT_SECURE),
diff --git a/plat/rockchip/rk3368/include/platform_def.h b/plat/rockchip/rk3368/include/platform_def.h
index 815650f..7b3cc6e 100644
--- a/plat/rockchip/rk3368/include/platform_def.h
+++ b/plat/rockchip/rk3368/include/platform_def.h
@@ -106,7 +106,7 @@
 #define PLAT_RK_GICD_BASE	RK3368_GICD_BASE
 #define PLAT_RK_GICC_BASE	RK3368_GICC_BASE
 
-#define PLAT_RK_UART_BASE	RK3368_UART2_BASE
+#define PLAT_RK_UART_BASE	UART2_BASE
 #define PLAT_RK_UART_CLOCK	RK3368_UART_CLOCK
 #define PLAT_RK_UART_BAUDRATE	RK3368_BAUDRATE
 
diff --git a/plat/rockchip/rk3368/platform.mk b/plat/rockchip/rk3368/platform.mk
index d1315fc..51368de 100644
--- a/plat/rockchip/rk3368/platform.mk
+++ b/plat/rockchip/rk3368/platform.mk
@@ -8,11 +8,11 @@
 RK_PLAT_SOC		:=	${RK_PLAT}/${PLAT}
 RK_PLAT_COMMON		:=	${RK_PLAT}/common
 
-include lib/libfdt/libfdt.mk
+DISABLE_BIN_GENERATION	:=	1
 
 PLAT_INCLUDES		:=	-I${RK_PLAT_COMMON}/				\
 				-I${RK_PLAT_COMMON}/include/			\
-				-I${RK_PLAT_COMMON}/pmusram			\
+				-I${RK_PLAT_COMMON}/aarch64/			\
 				-I${RK_PLAT_COMMON}/drivers/pmu/			\
 				-I${RK_PLAT_SOC}/				\
 				-I${RK_PLAT_SOC}/drivers/pmu/			\
@@ -37,11 +37,10 @@
 				drivers/delay_timer/delay_timer.c		\
 				drivers/delay_timer/generic_delay_timer.c	\
 				lib/cpus/aarch64/cortex_a53.S			\
-				$(LIBFDT_SRCS)					\
 				${RK_PLAT_COMMON}/aarch64/plat_helpers.S	\
 				${RK_PLAT_COMMON}/bl31_plat_setup.c		\
 				${RK_PLAT_COMMON}/params_setup.c                \
-				${RK_PLAT_COMMON}/pmusram/pmu_sram_cpus_on.S		\
+				${RK_PLAT_COMMON}/aarch64/pmu_sram_cpus_on.S	\
 				${RK_PLAT_COMMON}/plat_pm.c			\
 				${RK_PLAT_COMMON}/plat_topology.c		\
 				${RK_PLAT_COMMON}/aarch64/platform_common.c	\
@@ -54,6 +53,7 @@
 MULTI_CONSOLE_API	:=	1
 
 include lib/coreboot/coreboot.mk
+include lib/libfdt/libfdt.mk
 
 $(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT))
 
diff --git a/plat/rockchip/rk3368/rk3368_def.h b/plat/rockchip/rk3368/rk3368_def.h
index 10ac77b..4b0fbab 100644
--- a/plat/rockchip/rk3368/rk3368_def.h
+++ b/plat/rockchip/rk3368/rk3368_def.h
@@ -35,8 +35,20 @@
 #define RK_INTMEM_BASE		0xff8c0000
 #define RK_INTMEM_SIZE		0x10000
 
-#define UART_DBG_BASE		0xff690000
-#define UART_DBG_SIZE		0x10000
+#define UART0_BASE		0xff180000
+#define UART0_SIZE		0x10000
+
+#define UART1_BASE		0xff190000
+#define UART1_SIZE		0x10000
+
+#define UART2_BASE		0xff690000
+#define UART2_SIZE		0x10000
+
+#define UART3_BASE		0xff1b0000
+#define UART3_SIZE		0x10000
+
+#define UART4_BASE		0xff1c0000
+#define UART4_SIZE		0x10000
 
 #define CRU_BASE		0xff760000
 
@@ -57,7 +69,6 @@
 /**************************************************************************
  * UART related constants
  **************************************************************************/
-#define RK3368_UART2_BASE	UART_DBG_BASE
 #define RK3368_BAUDRATE		115200
 #define RK3368_UART_CLOCK	24000000
 
diff --git a/plat/rockchip/rk3399/drivers/m0/src/dram.c b/plat/rockchip/rk3399/drivers/m0/src/dram.c
index b939a96..84e8884 100644
--- a/plat/rockchip/rk3399/drivers/m0/src/dram.c
+++ b/plat/rockchip/rk3399/drivers/m0/src/dram.c
@@ -55,7 +55,7 @@
 	mmio_write_32(CRU_BASE + CRU_DPLL_CON3, PLL_MODE(PLL_NORMAL_MODE));
 }
 
-__attribute__((noreturn)) void main(void)
+__attribute__((noreturn)) void m0_main(void)
 {
 	mmio_setbits_32(PHY_REG(0, 927), (1 << 22));
 	mmio_setbits_32(PHY_REG(1, 927), (1 << 22));
diff --git a/plat/rockchip/rk3399/drivers/m0/src/startup.c b/plat/rockchip/rk3399/drivers/m0/src/startup.c
index dba0313..dfd8af2 100644
--- a/plat/rockchip/rk3399/drivers/m0/src/startup.c
+++ b/plat/rockchip/rk3399/drivers/m0/src/startup.c
@@ -23,7 +23,7 @@
 void WEAK pend_sv_handler(void);
 void WEAK systick_handler(void);
 
-extern int main(void);
+extern int m0_main(void);
 
 /* Function prototypes */
 static void default_reset_handler(void);
@@ -59,12 +59,12 @@
  * This is the code that gets called when the processor first
  * starts execution following a reset event. Only the absolutely
  * necessary set is performed, after which the application
- * supplied main() routine is called.
+ * supplied m0_main() routine is called.
  */
 static void default_reset_handler(void)
 {
 	/* call the application's entry point */
-	main();
+	m0_main();
 }
 
 /**
diff --git a/plat/rockchip/rk3399/drivers/m0/src/suspend.c b/plat/rockchip/rk3399/drivers/m0/src/suspend.c
index 39dfd11..9ad2fa2 100644
--- a/plat/rockchip/rk3399/drivers/m0/src/suspend.c
+++ b/plat/rockchip/rk3399/drivers/m0/src/suspend.c
@@ -11,7 +11,7 @@
 
 #define SCR_SLEEPDEEP_SHIFT	(1 << 2)
 
-__attribute__((noreturn)) void main(void)
+__attribute__((noreturn)) void m0_main(void)
 {
 	unsigned int status_value;
 
diff --git a/plat/rockchip/rk3399/platform.mk b/plat/rockchip/rk3399/platform.mk
index 1013598..f917f61 100644
--- a/plat/rockchip/rk3399/platform.mk
+++ b/plat/rockchip/rk3399/platform.mk
@@ -8,11 +8,11 @@
 RK_PLAT_SOC	:=	${RK_PLAT}/${PLAT}
 RK_PLAT_COMMON	:=	${RK_PLAT}/common
 
-include lib/libfdt/libfdt.mk
+DISABLE_BIN_GENERATION	:=	1
 
 PLAT_INCLUDES		:=	-I${RK_PLAT_COMMON}/			\
 				-I${RK_PLAT_COMMON}/include/		\
-				-I${RK_PLAT_COMMON}/pmusram		\
+				-I${RK_PLAT_COMMON}/aarch64/		\
 				-I${RK_PLAT_COMMON}/drivers/pmu/	\
 				-I${RK_PLAT_SOC}/			\
 				-I${RK_PLAT_SOC}/drivers/pmu/		\
@@ -45,11 +45,10 @@
 			drivers/gpio/gpio.c				\
 			lib/cpus/aarch64/cortex_a53.S			\
 			lib/cpus/aarch64/cortex_a72.S			\
-			$(LIBFDT_SRCS)					\
 			${RK_PLAT_COMMON}/aarch64/plat_helpers.S	\
 			${RK_PLAT_COMMON}/bl31_plat_setup.c		\
 			${RK_PLAT_COMMON}/params_setup.c		\
-			${RK_PLAT_COMMON}/pmusram/pmu_sram_cpus_on.S	\
+			${RK_PLAT_COMMON}/aarch64/pmu_sram_cpus_on.S	\
 			${RK_PLAT_COMMON}/plat_pm.c			\
 			${RK_PLAT_COMMON}/plat_topology.c		\
 			${RK_PLAT_COMMON}/aarch64/platform_common.c	\
@@ -71,6 +70,7 @@
 MULTI_CONSOLE_API	:=	1
 
 include lib/coreboot/coreboot.mk
+include lib/libfdt/libfdt.mk
 
 $(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT))
 
diff --git a/plat/st/common/bl2_io_storage.c b/plat/st/common/bl2_io_storage.c
index f172160..38b2a0b 100644
--- a/plat/st/common/bl2_io_storage.c
+++ b/plat/st/common/bl2_io_storage.c
@@ -54,10 +54,27 @@
 static uintptr_t storage_dev_handle;
 static const io_dev_connector_t *mmc_dev_con;
 
+#ifdef AARCH32_SP_OPTEE
+static const struct stm32image_part_info optee_header_partition_spec = {
+	.name = OPTEE_HEADER_IMAGE_NAME,
+	.binary_type = OPTEE_HEADER_BINARY_TYPE,
+};
+
+static const struct stm32image_part_info optee_pager_partition_spec = {
+	.name = OPTEE_PAGER_IMAGE_NAME,
+	.binary_type = OPTEE_PAGER_BINARY_TYPE,
+};
+
+static const struct stm32image_part_info optee_paged_partition_spec = {
+	.name = OPTEE_PAGED_IMAGE_NAME,
+	.binary_type = OPTEE_PAGED_BINARY_TYPE,
+};
+#else
 static const io_block_spec_t bl32_block_spec = {
 	.offset = BL32_BASE,
 	.length = STM32MP_BL32_SIZE
 };
+#endif
 
 static const io_block_spec_t bl2_block_spec = {
 	.offset = BL2_BASE,
@@ -71,6 +88,11 @@
 
 enum {
 	IMG_IDX_BL33,
+#ifdef AARCH32_SP_OPTEE
+	IMG_IDX_OPTEE_HEADER,
+	IMG_IDX_OPTEE_PAGER,
+	IMG_IDX_OPTEE_PAGED,
+#endif
 	IMG_IDX_NUM
 };
 
@@ -80,6 +102,20 @@
 		.name = BL33_IMAGE_NAME,
 		.binary_type = BL33_BINARY_TYPE,
 	},
+#ifdef AARCH32_SP_OPTEE
+	.part_info[IMG_IDX_OPTEE_HEADER] = {
+		.name = OPTEE_HEADER_IMAGE_NAME,
+		.binary_type = OPTEE_HEADER_BINARY_TYPE,
+	},
+	.part_info[IMG_IDX_OPTEE_PAGER] = {
+		.name = OPTEE_PAGER_IMAGE_NAME,
+		.binary_type = OPTEE_PAGER_BINARY_TYPE,
+	},
+	.part_info[IMG_IDX_OPTEE_PAGED] = {
+		.name = OPTEE_PAGED_IMAGE_NAME,
+		.binary_type = OPTEE_PAGED_BINARY_TYPE,
+	},
+#endif
 };
 
 static io_block_spec_t stm32image_block_spec = {
@@ -105,11 +141,29 @@
 		.image_spec = (uintptr_t)&bl2_block_spec,
 		.check = open_dummy
 	},
+#ifdef AARCH32_SP_OPTEE
+	[BL32_IMAGE_ID] = {
+		.dev_handle = &image_dev_handle,
+		.image_spec = (uintptr_t)&optee_header_partition_spec,
+		.check = open_image
+	},
+	[BL32_EXTRA1_IMAGE_ID] = {
+		.dev_handle = &image_dev_handle,
+		.image_spec = (uintptr_t)&optee_pager_partition_spec,
+		.check = open_image
+	},
+	[BL32_EXTRA2_IMAGE_ID] = {
+		.dev_handle = &image_dev_handle,
+		.image_spec = (uintptr_t)&optee_paged_partition_spec,
+		.check = open_image
+	},
+#else
 	[BL32_IMAGE_ID] = {
 		.dev_handle = &dummy_dev_handle,
 		.image_spec = (uintptr_t)&bl32_block_spec,
 		.check = open_dummy
 	},
+#endif
 	[BL33_IMAGE_ID] = {
 		.dev_handle = &image_dev_handle,
 		.image_spec = (uintptr_t)&bl33_partition_spec,
@@ -162,122 +216,125 @@
 	}
 }
 
-void stm32mp_io_setup(void)
+static void boot_mmc(enum mmc_device_type mmc_dev_type,
+		     uint16_t boot_interface_instance)
 {
 	int io_result __unused;
 	uint8_t idx;
 	struct stm32image_part_info *part;
 	struct stm32_sdmmc2_params params;
 	struct mmc_device_info device_info;
-	uintptr_t mmc_default_instance;
 	const partition_entry_t *entry;
-	boot_api_context_t *boot_context =
-		(boot_api_context_t *)stm32mp_get_boot_ctx_address();
 
-	print_boot_device(boot_context);
+	zeromem(&device_info, sizeof(struct mmc_device_info));
+	zeromem(&params, sizeof(struct stm32_sdmmc2_params));
 
-	if ((boot_context->boot_partition_used_toboot == 1U) ||
-	    (boot_context->boot_partition_used_toboot == 2U)) {
-		INFO("Boot used partition fsbl%d\n",
-		     boot_context->boot_partition_used_toboot);
+	device_info.mmc_dev_type = mmc_dev_type;
+
+	switch (boot_interface_instance) {
+	case 1:
+		params.reg_base = STM32MP_SDMMC1_BASE;
+		break;
+	case 2:
+		params.reg_base = STM32MP_SDMMC2_BASE;
+		break;
+	case 3:
+		params.reg_base = STM32MP_SDMMC3_BASE;
+		break;
+	default:
+		WARN("SDMMC instance not found, using default\n");
+		if (mmc_dev_type == MMC_IS_SD) {
+			params.reg_base = STM32MP_SDMMC1_BASE;
+		} else {
+			params.reg_base = STM32MP_SDMMC2_BASE;
+		}
+		break;
 	}
 
-	io_result = register_io_dev_dummy(&dummy_dev_con);
-	assert(io_result == 0);
+	params.device_info = &device_info;
+	if (stm32_sdmmc2_mmc_init(&params) != 0) {
+		ERROR("SDMMC%u init failed\n", boot_interface_instance);
+		panic();
+	}
 
-	io_result = io_dev_open(dummy_dev_con, dummy_dev_spec,
-				&dummy_dev_handle);
-	assert(io_result == 0);
+	/* Open MMC as a block device to read GPT table */
+	io_result = register_io_dev_block(&mmc_dev_con);
+	if (io_result != 0) {
+		panic();
+	}
 
-	switch (boot_context->boot_interface_selected) {
-	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
-	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
-		dmbsy();
+	io_result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_block_dev_spec,
+				&storage_dev_handle);
+	assert(io_result == 0);
 
-		zeromem(&device_info, sizeof(struct mmc_device_info));
-		zeromem(&params, sizeof(struct stm32_sdmmc2_params));
+	partition_init(GPT_IMAGE_ID);
 
-		if (boot_context->boot_interface_selected ==
-		    BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC) {
-			device_info.mmc_dev_type = MMC_IS_EMMC;
-			mmc_default_instance = STM32MP_SDMMC2_BASE;
-		} else {
-			device_info.mmc_dev_type = MMC_IS_SD;
-			mmc_default_instance = STM32MP_SDMMC1_BASE;
-		}
+	io_result = io_dev_close(storage_dev_handle);
+	assert(io_result == 0);
 
-		switch (boot_context->boot_interface_instance) {
-		case 1:
-			params.reg_base = STM32MP_SDMMC1_BASE;
-			break;
-		case 2:
-			params.reg_base = STM32MP_SDMMC2_BASE;
-			break;
-		case 3:
-			params.reg_base = STM32MP_SDMMC3_BASE;
-			break;
-		default:
-			WARN("SDMMC instance not found, using default\n");
-			params.reg_base = mmc_default_instance;
-			break;
-		}
+	stm32image_dev_info_spec.device_size =
+		stm32_sdmmc2_mmc_get_device_size();
 
-		params.device_info = &device_info;
-		if (stm32_sdmmc2_mmc_init(&params) != 0) {
-			ERROR("SDMMC%u init failed\n",
-			      boot_context->boot_interface_instance);
+	for (idx = 0U; idx < IMG_IDX_NUM; idx++) {
+		part = &stm32image_dev_info_spec.part_info[idx];
+		entry = get_partition_entry(part->name);
+		if (entry == NULL) {
+			ERROR("Partition %s not found\n", part->name);
 			panic();
 		}
 
-		/* Open MMC as a block device to read GPT table */
-		io_result = register_io_dev_block(&mmc_dev_con);
-		if (io_result != 0) {
-			panic();
-		}
+		part->part_offset = entry->start;
+		part->bkp_offset = 0U;
+	}
 
-		io_result = io_dev_open(mmc_dev_con,
-					(uintptr_t)&mmc_block_dev_spec,
-					&storage_dev_handle);
-		assert(io_result == 0);
+	/*
+	 * Re-open MMC with io_mmc, for better perfs compared to
+	 * io_block.
+	 */
+	io_result = register_io_dev_mmc(&mmc_dev_con);
+	assert(io_result == 0);
 
-		partition_init(GPT_IMAGE_ID);
+	io_result = io_dev_open(mmc_dev_con, 0, &storage_dev_handle);
+	assert(io_result == 0);
 
-		io_result = io_dev_close(storage_dev_handle);
-		assert(io_result == 0);
+	io_result = register_io_dev_stm32image(&stm32image_dev_con);
+	assert(io_result == 0);
 
-		stm32image_dev_info_spec.device_size =
-			stm32_sdmmc2_mmc_get_device_size();
+	io_result = io_dev_open(stm32image_dev_con,
+				(uintptr_t)&stm32image_dev_info_spec,
+				&image_dev_handle);
+	assert(io_result == 0);
+}
 
-		for (idx = 0U; idx < IMG_IDX_NUM; idx++) {
-			part = &stm32image_dev_info_spec.part_info[idx];
-			entry = get_partition_entry(part->name);
-			if (entry == NULL) {
-				ERROR("Partition %s not found\n",
-				      part->name);
-				panic();
-			}
+void stm32mp_io_setup(void)
+{
+	int io_result __unused;
+	boot_api_context_t *boot_context =
+		(boot_api_context_t *)stm32mp_get_boot_ctx_address();
 
-			part->part_offset = entry->start;
-			part->bkp_offset = 0U;
-		}
+	print_boot_device(boot_context);
 
-		/*
-		 * Re-open MMC with io_mmc, for better perfs compared to
-		 * io_block.
-		 */
-		io_result = register_io_dev_mmc(&mmc_dev_con);
-		assert(io_result == 0);
+	if ((boot_context->boot_partition_used_toboot == 1U) ||
+	    (boot_context->boot_partition_used_toboot == 2U)) {
+		INFO("Boot used partition fsbl%d\n",
+		     boot_context->boot_partition_used_toboot);
+	}
 
-		io_result = io_dev_open(mmc_dev_con, 0, &storage_dev_handle);
-		assert(io_result == 0);
+	io_result = register_io_dev_dummy(&dummy_dev_con);
+	assert(io_result == 0);
 
-		io_result = register_io_dev_stm32image(&stm32image_dev_con);
-		assert(io_result == 0);
+	io_result = io_dev_open(dummy_dev_con, dummy_dev_spec,
+				&dummy_dev_handle);
+	assert(io_result == 0);
 
-		io_result = io_dev_open(stm32image_dev_con,
-					(uintptr_t)&stm32image_dev_info_spec,
-					&image_dev_handle);
-		assert(io_result == 0);
+	switch (boot_context->boot_interface_selected) {
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
+		dmbsy();
+		boot_mmc(MMC_IS_SD, boot_context->boot_interface_instance);
+		break;
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
+		dmbsy();
+		boot_mmc(MMC_IS_EMMC, boot_context->boot_interface_instance);
 		break;
 
 	default:
diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c
index 2477954..b54486e 100644
--- a/plat/st/stm32mp1/bl2_plat_setup.c
+++ b/plat/st/stm32mp1/bl2_plat_setup.c
@@ -22,6 +22,7 @@
 #include <drivers/st/stm32mp1_pwr.h>
 #include <drivers/st/stm32mp1_ram.h>
 #include <lib/mmio.h>
+#include <lib/optee_utils.h>
 #include <lib/xlat_tables/xlat_tables_v2.h>
 #include <plat/common/platform.h>
 
@@ -136,7 +137,13 @@
 		panic();
 	}
 
+#ifdef AARCH32_SP_OPTEE
+	INFO("BL2 runs OP-TEE setup\n");
+	/* Initialize tzc400 after DDR initialization */
+	stm32mp1_security_setup();
+#else
 	INFO("BL2 runs SP_MIN setup\n");
+#endif
 }
 
 void bl2_el3_plat_arch_setup(void)
@@ -154,11 +161,25 @@
 			BL_CODE_END - BL_CODE_BASE,
 			MT_CODE | MT_SECURE);
 
+#ifdef AARCH32_SP_OPTEE
+	/* OP-TEE image needs post load processing: keep RAM read/write */
+	mmap_add_region(STM32MP_DDR_BASE + dt_get_ddr_size() -
+			STM32MP_DDR_S_SIZE - STM32MP_DDR_SHMEM_SIZE,
+			STM32MP_DDR_BASE + dt_get_ddr_size() -
+			STM32MP_DDR_S_SIZE - STM32MP_DDR_SHMEM_SIZE,
+			STM32MP_DDR_S_SIZE,
+			MT_MEMORY | MT_RW | MT_SECURE);
+
+	mmap_add_region(STM32MP_OPTEE_BASE, STM32MP_OPTEE_BASE,
+			STM32MP_OPTEE_SIZE,
+			MT_MEMORY | MT_RW | MT_SECURE);
+#else
 	/* Prevent corruption of preloaded BL32 */
 	mmap_add_region(BL32_BASE, BL32_BASE,
 			BL32_LIMIT - BL32_BASE,
 			MT_MEMORY | MT_RO | MT_SECURE);
 
+#endif
 	/* Map non secure DDR for BL33 load and DDR training area restore */
 	mmap_add_region(STM32MP_DDR_BASE,
 			STM32MP_DDR_BASE,
@@ -261,3 +282,69 @@
 
 	stm32mp_io_setup();
 }
+
+#if defined(AARCH32_SP_OPTEE)
+/*******************************************************************************
+ * This function can be used by the platforms to update/use image
+ * information for given `image_id`.
+ ******************************************************************************/
+int bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+	int err = 0;
+	bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
+	bl_mem_params_node_t *bl32_mem_params;
+	bl_mem_params_node_t *pager_mem_params;
+	bl_mem_params_node_t *paged_mem_params;
+
+	assert(bl_mem_params != NULL);
+
+	switch (image_id) {
+	case BL32_IMAGE_ID:
+		bl_mem_params->ep_info.pc =
+					bl_mem_params->image_info.image_base;
+
+		pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
+		assert(pager_mem_params != NULL);
+		pager_mem_params->image_info.image_base = STM32MP_OPTEE_BASE;
+		pager_mem_params->image_info.image_max_size =
+			STM32MP_OPTEE_SIZE;
+
+		paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID);
+		assert(paged_mem_params != NULL);
+		paged_mem_params->image_info.image_base = STM32MP_DDR_BASE +
+			(dt_get_ddr_size() - STM32MP_DDR_S_SIZE -
+			 STM32MP_DDR_SHMEM_SIZE);
+		paged_mem_params->image_info.image_max_size =
+			STM32MP_DDR_S_SIZE;
+
+		err = parse_optee_header(&bl_mem_params->ep_info,
+					 &pager_mem_params->image_info,
+					 &paged_mem_params->image_info);
+		if (err) {
+			ERROR("OPTEE header parse error.\n");
+			panic();
+		}
+
+		/* Set optee boot info from parsed header data */
+		bl_mem_params->ep_info.pc =
+				pager_mem_params->image_info.image_base;
+		bl_mem_params->ep_info.args.arg0 =
+				paged_mem_params->image_info.image_base;
+		bl_mem_params->ep_info.args.arg1 = 0; /* Unused */
+		bl_mem_params->ep_info.args.arg2 = 0; /* No DT supported */
+		break;
+
+	case BL33_IMAGE_ID:
+		bl32_mem_params = get_bl_mem_params_node(BL32_IMAGE_ID);
+		assert(bl32_mem_params != NULL);
+		bl32_mem_params->ep_info.lr_svc = bl_mem_params->ep_info.pc;
+		break;
+
+	default:
+		/* Do nothing in default case */
+		break;
+	}
+
+	return err;
+}
+#endif
diff --git a/plat/st/stm32mp1/include/platform_def.h b/plat/st/stm32mp1/include/platform_def.h
index 5019b1a..263e6d6 100644
--- a/plat/st/stm32mp1/include/platform_def.h
+++ b/plat/st/stm32mp1/include/platform_def.h
@@ -25,6 +25,15 @@
 #define PLATFORM_STACK_SIZE		0xC00
 #endif
 
+#ifdef AARCH32_SP_OPTEE
+#define OPTEE_HEADER_IMAGE_NAME		"teeh"
+#define OPTEE_PAGED_IMAGE_NAME		"teed"
+#define OPTEE_PAGER_IMAGE_NAME		"teex"
+#define OPTEE_HEADER_BINARY_TYPE	U(0x20)
+#define OPTEE_PAGER_BINARY_TYPE		U(0x21)
+#define OPTEE_PAGED_BINARY_TYPE		U(0x22)
+#endif
+
 /* SSBL = second stage boot loader */
 #define BL33_IMAGE_NAME			"ssbl"
 #define BL33_BINARY_TYPE		U(0x0)
@@ -57,9 +66,11 @@
 /*******************************************************************************
  * BL32 specific defines.
  ******************************************************************************/
+#ifndef AARCH32_SP_OPTEE
 #define BL32_BASE			STM32MP_BL32_BASE
 #define BL32_LIMIT			(STM32MP_BL32_BASE + \
 					 STM32MP_BL32_SIZE)
+#endif
 
 /*******************************************************************************
  * BL33 specific defines.
diff --git a/plat/st/stm32mp1/plat_bl2_mem_params_desc.c b/plat/st/stm32mp1/plat_bl2_mem_params_desc.c
index 0da93e4..1d407bb 100644
--- a/plat/st/stm32mp1/plat_bl2_mem_params_desc.c
+++ b/plat/st/stm32mp1/plat_bl2_mem_params_desc.c
@@ -27,7 +27,9 @@
 				      VERSION_2, entry_point_info_t,
 				      SECURE | EXECUTABLE | EP_FIRST_EXE),
 
+#if !defined(AARCH32_SP_OPTEE)
 		.ep_info.pc = BL32_BASE,
+#endif
 		.ep_info.spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM,
 					    SPSR_E_LITTLE,
 					    DISABLE_ALL_EXCEPTIONS),
@@ -35,12 +37,47 @@
 		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
 				      VERSION_2, image_info_t,
 				      IMAGE_ATTRIB_PLAT_SETUP),
-
+#if defined(AARCH32_SP_OPTEE)
+		/* optee header is loaded in SYSRAM above BL2 */
+		.image_info.image_base = STM32MP_OPTEE_BASE,
+		.image_info.image_max_size = STM32MP_OPTEE_SIZE,
+#else
 		.image_info.image_base = BL32_BASE,
 		.image_info.image_max_size = BL32_LIMIT - BL32_BASE,
-
+#endif
 		.next_handoff_image_id = BL33_IMAGE_ID,
 	},
+
+#if defined(AARCH32_SP_OPTEE)
+	/* Fill BL32 external 1 image related information */
+	{
+		.image_id = BL32_EXTRA1_IMAGE_ID,
+
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+				      VERSION_2, entry_point_info_t,
+				      SECURE | NON_EXECUTABLE),
+
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+				      VERSION_2, image_info_t,
+				      IMAGE_ATTRIB_SKIP_LOADING),
+
+		.next_handoff_image_id = INVALID_IMAGE_ID,
+	},
+	/* Fill BL32 external 2 image related information */
+	{
+		.image_id = BL32_EXTRA2_IMAGE_ID,
+
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+				      VERSION_2, entry_point_info_t,
+				      SECURE | NON_EXECUTABLE),
+
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+				      VERSION_2, image_info_t,
+				      IMAGE_ATTRIB_SKIP_LOADING),
+
+		.next_handoff_image_id = INVALID_IMAGE_ID,
+	},
+#endif /* AARCH32_SP_OPTEE */
 
 	/* Fill BL33 related information */
 	{
diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk
index 3e34601..4796e91 100644
--- a/plat/st/stm32mp1/platform.mk
+++ b/plat/st/stm32mp1/platform.mk
@@ -18,7 +18,11 @@
 # Number of TF-A copies in the device
 STM32_TF_A_COPIES		:=	2
 $(eval $(call add_define,STM32_TF_A_COPIES))
+ifeq ($(AARCH32_SP),optee)
+PLAT_PARTITION_MAX_ENTRIES	:=	$(shell echo $$(($(STM32_TF_A_COPIES) + 4)))
+else
 PLAT_PARTITION_MAX_ENTRIES	:=	$(shell echo $$(($(STM32_TF_A_COPIES) + 1)))
+endif
 $(eval $(call add_define,PLAT_PARTITION_MAX_ENTRIES))
 
 PLAT_INCLUDES		:=	-Iplat/st/common/include/
@@ -84,6 +88,10 @@
 				plat/st/stm32mp1/plat_bl2_mem_params_desc.c		\
 				plat/st/stm32mp1/plat_image_load.c
 
+ifeq ($(AARCH32_SP),optee)
+BL2_SOURCES		+=	lib/optee/optee_utils.c
+endif
+
 # Macros and rules to build TF binary
 STM32_TF_ELF_LDFLAGS	:=	--hash-style=gnu --as-needed
 STM32_DT_BASENAME	:=	$(DTB_FILE_NAME:.dtb=)
diff --git a/plat/st/stm32mp1/stm32mp1.ld.S b/plat/st/stm32mp1/stm32mp1.ld.S
index c041fb6..b347bad 100644
--- a/plat/st/stm32mp1/stm32mp1.ld.S
+++ b/plat/st/stm32mp1/stm32mp1.ld.S
@@ -58,6 +58,7 @@
         *(.bl2_image*)
         __BL2_IMAGE_END__ = .;
 
+#ifndef AARCH32_SP_OPTEE
         /*
          * bl32 will be settled by bl2.
          * The strongest and only alignment constraint is 8 words to simplify
@@ -67,6 +68,7 @@
         __BL32_IMAGE_START__ = .;
         *(.bl32_image*)
         __BL32_IMAGE_END__ = .;
+#endif
 
         __DATA_END__ = .;
     } >RAM
diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h
index 1c897bd..cff7ddb 100644
--- a/plat/st/stm32mp1/stm32mp1_def.h
+++ b/plat/st/stm32mp1/stm32mp1_def.h
@@ -34,7 +34,10 @@
 /* DDR configuration */
 #define STM32MP_DDR_BASE		U(0xC0000000)
 #define STM32MP_DDR_MAX_SIZE		U(0x40000000)	/* Max 1GB */
-#define STM32MP_DDR_SPEED_DFLT		528
+#ifdef AARCH32_SP_OPTEE
+#define STM32MP_DDR_S_SIZE		U(0x01E00000)	/* 30 MB */
+#define STM32MP_DDR_SHMEM_SIZE		U(0x00200000)	/* 2 MB */
+#endif
 
 /* DDR power initializations */
 #ifndef __ASSEMBLY__
@@ -57,21 +60,38 @@
 					 (STM32MP_PARAM_LOAD_SIZE +	\
 					  STM32MP_HEADER_SIZE))
 
+#ifdef AARCH32_SP_OPTEE
+#define STM32MP_BL32_SIZE		U(0)
+
+#define STM32MP_OPTEE_BASE		STM32MP_SYSRAM_BASE
+
+#define STM32MP_OPTEE_SIZE		(STM32MP_DTB_BASE -  \
+					 STM32MP_OPTEE_BASE)
+#else
 #if STACK_PROTECTOR_ENABLED
 #define STM32MP_BL32_SIZE		U(0x00012000)	/* 72 Ko for BL32 */
 #else
 #define STM32MP_BL32_SIZE		U(0x00011000)	/* 68 Ko for BL32 */
 #endif
+#endif
 
 #define STM32MP_BL32_BASE		(STM32MP_SYSRAM_BASE + \
 					 STM32MP_SYSRAM_SIZE - \
 					 STM32MP_BL32_SIZE)
 
+#ifdef AARCH32_SP_OPTEE
+#if STACK_PROTECTOR_ENABLED
+#define STM32MP_BL2_SIZE		U(0x00019000)	/* 100 Ko for BL2 */
+#else
+#define STM32MP_BL2_SIZE		U(0x00017000)	/* 92 Ko for BL2 */
+#endif
+#else
 #if STACK_PROTECTOR_ENABLED
 #define STM32MP_BL2_SIZE		U(0x00015000)	/* 84 Ko for BL2 */
 #else
 #define STM32MP_BL2_SIZE		U(0x00013000)	/* 76 Ko for BL2 */
 #endif
+#endif
 
 #define STM32MP_BL2_BASE		(STM32MP_BL32_BASE - \
 					 STM32MP_BL2_SIZE)
diff --git a/plat/st/stm32mp1/stm32mp1_security.c b/plat/st/stm32mp1/stm32mp1_security.c
index 0ad43e4..61db2e7 100644
--- a/plat/st/stm32mp1/stm32mp1_security.c
+++ b/plat/st/stm32mp1/stm32mp1_security.c
@@ -14,6 +14,19 @@
 #include <dt-bindings/clock/stm32mp1-clks.h>
 #include <lib/mmio.h>
 
+#define TZC_REGION_NSEC_ALL_ACCESS_RDWR \
+	TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID) | \
+	TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_GPU_ID) | \
+	TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_LCD_ID) | \
+	TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_MDMA_ID) | \
+	TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_M4_ID) | \
+	TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DMA_ID) | \
+	TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_HOST_ID) | \
+	TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_OTG_ID) | \
+	TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_SDMMC_ID) | \
+	TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_ETH_ID) | \
+	TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DAP_ID)
+
 /*******************************************************************************
  * Initialize the TrustZone Controller. Configure Region 0 with Secure RW access
  * and allow Non-Secure masters full access.
@@ -23,31 +36,55 @@
 	unsigned long long region_base, region_top;
 	unsigned long long ddr_base = STM32MP_DDR_BASE;
 	unsigned long long ddr_size = (unsigned long long)dt_get_ddr_size();
+	unsigned long long ddr_top = ddr_base + (ddr_size - 1U);
 
 	tzc400_init(STM32MP1_TZC_BASE);
 
 	tzc400_disable_filters();
 
+#ifdef AARCH32_SP_OPTEE
+	/*
+	 * Region 1 set to cover all non-secure DRAM at 0xC000_0000. Apply the
+	 * same configuration to all filters in the TZC.
+	 */
+	region_base = ddr_base;
+	region_top = ddr_top - STM32MP_DDR_S_SIZE - STM32MP_DDR_SHMEM_SIZE;
+	tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 1,
+				region_base,
+				region_top,
+				TZC_REGION_S_NONE,
+				TZC_REGION_NSEC_ALL_ACCESS_RDWR);
+
-	/* Region 1 set to cover all DRAM at 0xC000_0000. Apply the
+	/* Region 2 set to cover all secure DRAM. */
+	region_base = region_top + 1U;
+	region_top = ddr_top - STM32MP_DDR_SHMEM_SIZE;
+	tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 2,
+				region_base,
+				region_top,
+				TZC_REGION_S_RDWR,
+				0);
+
+	/* Region 3 set to cover non-secure shared memory DRAM. */
+	region_base = region_top + 1U;
+	region_top = ddr_top;
+	tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 3,
+				region_base,
+				region_top,
+				TZC_REGION_S_NONE,
+				TZC_REGION_NSEC_ALL_ACCESS_RDWR);
+#else
+	/*
+	 * Region 1 set to cover all DRAM at 0xC000_0000. Apply the
 	 * same configuration to all filters in the TZC.
 	 */
 	region_base = ddr_base;
-	region_top = ddr_base + (ddr_size - 1U);
+	region_top = ddr_top;
 	tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 1,
-			region_base,
-			region_top,
-			TZC_REGION_S_RDWR,
-			TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID) |
-			TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_GPU_ID) |
-			TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_LCD_ID) |
-			TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_MDMA_ID) |
-			TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_M4_ID) |
-			TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DMA_ID) |
-			TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_HOST_ID) |
-			TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_OTG_ID) |
-			TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_SDMMC_ID) |
-			TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_ETH_ID) |
-			TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DAP_ID));
+				region_base,
+				region_top,
+				TZC_REGION_S_NONE,
+				TZC_REGION_NSEC_ALL_ACCESS_RDWR);
+#endif
 
 	/* Raise an exception if a NS device tries to access secure memory */
 	tzc400_set_action(TZC_ACTION_ERR);
@@ -69,15 +106,12 @@
 
 	tzc400_disable_filters();
 
-	/*
-	 * Region 1 set to cover Non-Secure DRAM at 0x8000_0000. Apply the
-	 * same configuration to all filters in the TZC.
-	 */
+	/* Region 1 set to cover Non-Secure DRAM at 0xC000_0000 */
 	tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 1,
 				STM32MP_DDR_BASE,
 				STM32MP_DDR_BASE +
 				(STM32MP_DDR_MAX_SIZE - 1U),
-				TZC_REGION_S_RDWR,
+				TZC_REGION_S_NONE,
 				TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID) |
 				TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_SDMMC_ID));
 
diff --git a/plat/ti/k3/board/generic/include/board_def.h b/plat/ti/k3/board/generic/include/board_def.h
index 4c8f882..490b975 100644
--- a/plat/ti/k3/board/generic/include/board_def.h
+++ b/plat/ti/k3/board/generic/include/board_def.h
@@ -11,16 +11,9 @@
 
 /* The ports must be in order and contiguous */
 #define K3_CLUSTER0_CORE_COUNT		2
-#define K3_CLUSTER0_MSMC_PORT		0
-
 #define K3_CLUSTER1_CORE_COUNT		2
-#define K3_CLUSTER1_MSMC_PORT		1
-
 #define K3_CLUSTER2_CORE_COUNT		2
-#define K3_CLUSTER2_MSMC_PORT		2
-
 #define K3_CLUSTER3_CORE_COUNT		2
-#define K3_CLUSTER3_MSMC_PORT		3
 
 /*
  * This RAM will be used for the bootloader including code, bss, and stacks.
diff --git a/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.c b/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.c
index 49cecd4..ee1eecf 100644
--- a/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.c
+++ b/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.c
@@ -51,14 +51,14 @@
 };
 
 /**
- * struct k3_sec_proxy_thread - Description of a secure proxy Thread
- * @id:		Thread ID
+ * struct k3_sec_proxy_thread - Description of a Secure Proxy Thread
+ * @name:	Thread Name
  * @data:	Thread Data path region for target
  * @scfg:	Secure Config Region for Thread
  * @rt:		RealTime Region for Thread
  */
 struct k3_sec_proxy_thread {
-	uint32_t id;
+	const char *name;
 	uintptr_t data;
 	uintptr_t scfg;
 	uintptr_t rt;
@@ -83,7 +83,7 @@
  */
 #define SP_THREAD(_x) \
 	[_x] = { \
-		.id = _x, \
+		.name = #_x, \
 		.data = SEC_PROXY_THREAD(SEC_PROXY_DATA_BASE, _x), \
 		.scfg = SEC_PROXY_THREAD(SEC_PROXY_SCFG_BASE, _x), \
 		.rt = SEC_PROXY_THREAD(SEC_PROXY_RT_BASE, _x), \
@@ -131,19 +131,19 @@
 	/* Check for any errors already available */
 	if (mmio_read_32(spt->rt + RT_THREAD_STATUS) &
 	    RT_THREAD_STATUS_ERROR_MASK) {
-		ERROR("Thread %d is corrupted, cannot send data\n", spt->id);
+		ERROR("Thread %s is corrupted, cannot send data\n", spt->name);
 		return -EINVAL;
 	}
 
 	/* Make sure thread is configured for right direction */
 	if ((mmio_read_32(spt->scfg + SCFG_THREAD_CTRL) & SCFG_THREAD_CTRL_DIR_MASK)
 	    != (dir << SCFG_THREAD_CTRL_DIR_SHIFT)) {
-		if (dir)
-			ERROR("Trying to send data on RX Thread %d\n",
-			      spt->id);
+		if (dir == THREAD_IS_TX)
+			ERROR("Trying to send data on RX Thread %s\n",
+			      spt->name);
 		else
-			ERROR("Trying to receive data on TX Thread %d\n",
-			      spt->id);
+			ERROR("Trying to receive data on TX Thread %s\n",
+			      spt->name);
 		return -EINVAL;
 	}
 
@@ -151,10 +151,12 @@
 	uint32_t tick_start = (uint32_t)read_cntpct_el0();
 	uint32_t ticks_per_us = SYS_COUNTER_FREQ_IN_TICKS / 1000000;
 	while (!(mmio_read_32(spt->rt + RT_THREAD_STATUS) & RT_THREAD_STATUS_CUR_CNT_MASK)) {
-		VERBOSE("Waiting for thread %d to clear\n", spt->id);
+		VERBOSE("Waiting for thread %s to %s\n",
+			spt->name, (dir == THREAD_IS_TX) ? "empty" : "fill");
 		if (((uint32_t)read_cntpct_el0() - tick_start) >
 		    (spm.desc.timeout_us * ticks_per_us)) {
-			ERROR("Timeout waiting for thread %d to clear\n", spt->id);
+			ERROR("Timeout waiting for thread %s to %s\n",
+				spt->name, (dir == THREAD_IS_TX) ? "empty" : "fill");
 			return -ETIMEDOUT;
 		}
 	}
@@ -176,13 +178,13 @@
 	/* Check for any errors already available */
 	if (mmio_read_32(spt->rt + RT_THREAD_STATUS) &
 	    RT_THREAD_STATUS_ERROR_MASK) {
-		ERROR("Thread %d is corrupted, cannot send data\n", spt->id);
+		ERROR("Thread %s is corrupted, cannot send data\n", spt->name);
 		return -EINVAL;
 	}
 
 	/* Make sure thread is configured for right direction */
 	if (!(mmio_read_32(spt->scfg + SCFG_THREAD_CTRL) & SCFG_THREAD_CTRL_DIR_MASK)) {
-		ERROR("Cannot clear a transmit thread %d\n", spt->id);
+		ERROR("Cannot clear a transmit thread %s\n", spt->name);
 		return -EINVAL;
 	}
 
@@ -190,10 +192,10 @@
 	uint32_t try_count = 10;
 	while (mmio_read_32(spt->rt + RT_THREAD_STATUS) & RT_THREAD_STATUS_CUR_CNT_MASK) {
 		if (!(try_count--)) {
-			ERROR("Could not clear all messages from thread %d\n", spt->id);
+			ERROR("Could not clear all messages from thread %s\n", spt->name);
 			return -ETIMEDOUT;
 		}
-		WARN("Clearing message from thread %d\n", spt->id);
+		WARN("Clearing message from thread %s\n", spt->name);
 		mmio_read_32(spt->data + spm.desc.data_end_offset);
 	}
 
@@ -216,14 +218,14 @@
 
 	ret = k3_sec_proxy_verify_thread(spt, THREAD_IS_TX);
 	if (ret) {
-		ERROR("Thread %d verification failed (%d)\n", spt->id, ret);
+		ERROR("Thread %s verification failed (%d)\n", spt->name, ret);
 		return ret;
 	}
 
 	/* Check the message size */
 	if (msg->len + sizeof(secure_header) > spm.desc.max_msg_size) {
-		ERROR("Thread %d message length %lu > max msg size\n",
-		      spt->id, msg->len);
+		ERROR("Thread %s message length %lu > max msg size\n",
+		      spt->name, msg->len);
 		return -EINVAL;
 	}
 
@@ -263,7 +265,7 @@
 	if (data_reg <= spm.desc.data_end_offset)
 		mmio_write_32(spt->data + spm.desc.data_end_offset, 0);
 
-	VERBOSE("Message successfully sent on thread %ud\n", id);
+	VERBOSE("Message successfully sent on thread %s\n", spt->name);
 
 	return 0;
 }
@@ -275,7 +277,7 @@
  *
  * Return: 0 if all goes well, else appropriate error message
  */
-int k3_sec_proxy_recv(uint32_t id, struct k3_sec_proxy_msg *msg)
+int k3_sec_proxy_recv(enum k3_sec_proxy_chan_id id, struct k3_sec_proxy_msg *msg)
 {
 	struct k3_sec_proxy_thread *spt = &spm.threads[id];
 	union sec_msg_hdr secure_header;
@@ -284,7 +286,7 @@
 
 	ret = k3_sec_proxy_verify_thread(spt, THREAD_IS_RX);
 	if (ret) {
-		ERROR("Thread %d verification failed (%d)\n", spt->id, ret);
+		ERROR("Thread %s verification failed (%d)\n", spt->name, ret);
 		return ret;
 	}
 
@@ -323,7 +325,7 @@
 	/* TODO: Verify checksum */
 	(void)secure_header.checksum;
 
-	VERBOSE("Message successfully received from thread %ud\n", id);
+	VERBOSE("Message successfully received from thread %s\n", spt->name);
 
 	return 0;
 }
diff --git a/plat/ti/k3/common/drivers/ti_sci/ti_sci.c b/plat/ti/k3/common/drivers/ti_sci/ti_sci.c
index df0b794..ac33278 100644
--- a/plat/ti/k3/common/drivers/ti_sci/ti_sci.c
+++ b/plat/ti/k3/common/drivers/ti_sci/ti_sci.c
@@ -45,7 +45,6 @@
 		.host_id = TI_SCI_HOST_ID,
 		.max_msg_size = TI_SCI_MAX_MESSAGE_SIZE,
 	},
-	.seq = 0x0a,
 };
 
 /**
@@ -89,10 +88,8 @@
 	    tx_message_size < sizeof(*hdr))
 		return -ERANGE;
 
-	info.seq++;
-
 	hdr = (struct ti_sci_msg_hdr *)tx_buf;
-	hdr->seq = info.seq;
+	hdr->seq = ++info.seq;
 	hdr->type = msg_type;
 	hdr->host = info.desc.host_id;
 	hdr->flags = msg_flags | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED;
@@ -119,21 +116,28 @@
 {
 	struct k3_sec_proxy_msg *msg = &xfer->rx_message;
 	struct ti_sci_msg_hdr *hdr;
+	unsigned int retry = 5;
 	int ret;
 
-	/* Receive the response */
-	ret = k3_sec_proxy_recv(chan, msg);
-	if (ret) {
-		ERROR("Message receive failed (%d)\n", ret);
-		return ret;
-	}
+	for (; retry > 0; retry--) {
+		/* Receive the response */
+		ret = k3_sec_proxy_recv(chan, msg);
+		if (ret) {
+			ERROR("Message receive failed (%d)\n", ret);
+			return ret;
+		}
 
-	/* msg is updated by Secure Proxy driver */
-	hdr = (struct ti_sci_msg_hdr *)msg->buf;
+		/* msg is updated by Secure Proxy driver */
+		hdr = (struct ti_sci_msg_hdr *)msg->buf;
 
-	/* Sanity check for message response */
-	if (hdr->seq != info.seq) {
-		ERROR("Message for %d is not expected\n", hdr->seq);
+		/* Sanity check for message response */
+		if (hdr->seq == info.seq)
+			break;
+		else
+			WARN("Message with sequence ID %u is not expected\n", hdr->seq);
+	}
+	if (!retry) {
+		ERROR("Timed out waiting for message\n");
 		return -EINVAL;
 	}
 
@@ -425,7 +429,7 @@
 		return -ERANGE;
 
 	hdr = (struct ti_sci_msg_hdr *)&req;
-	hdr->seq = info.seq;
+	hdr->seq = ++info.seq;
 	hdr->type = TI_SCI_MSG_SET_DEVICE_STATE;
 	hdr->host = info.desc.host_id;
 	/* Setup with NORESPONSE flag to keep response queue clean */
@@ -1408,7 +1412,7 @@
 		return -ERANGE;
 
 	hdr = (struct ti_sci_msg_hdr *)&req;
-	hdr->seq = info.seq;
+	hdr->seq = ++info.seq;
 	hdr->type = TISCI_MSG_SET_PROC_BOOT_CTRL;
 	hdr->host = info.desc.host_id;
 	/* Setup with NORESPONSE flag to keep response queue clean */
@@ -1650,7 +1654,7 @@
 		return -ERANGE;
 
 	hdr = (struct ti_sci_msg_hdr *)&req;
-	hdr->seq = info.seq;
+	hdr->seq = ++info.seq;
 	hdr->type = TISCI_MSG_WAIT_PROC_BOOT_STATUS;
 	hdr->host = info.desc.host_id;
 	/* Setup with NORESPONSE flag to keep response queue clean */
diff --git a/plat/ti/k3/common/k3_bl31_setup.c b/plat/ti/k3/common/k3_bl31_setup.c
index 78fb696..8bd7362 100644
--- a/plat/ti/k3/common/k3_bl31_setup.c
+++ b/plat/ti/k3/common/k3_bl31_setup.c
@@ -21,10 +21,9 @@
 
 /* Table of regions to map using the MMU */
 const mmap_region_t plat_k3_mmap[] = {
-	MAP_REGION_FLAT(SHARED_RAM_BASE, SHARED_RAM_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
-	MAP_REGION_FLAT(K3_USART_BASE_ADDRESS, K3_USART_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
-	MAP_REGION_FLAT(K3_GIC_BASE, K3_GIC_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
-	MAP_REGION_FLAT(SEC_PROXY_RT_BASE, SEC_PROXY_RT_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(K3_USART_BASE,       K3_USART_SIZE,       MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(K3_GIC_BASE,         K3_GIC_SIZE,         MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(SEC_PROXY_RT_BASE,   SEC_PROXY_RT_SIZE,   MT_DEVICE | MT_RW | MT_SECURE),
 	MAP_REGION_FLAT(SEC_PROXY_SCFG_BASE, SEC_PROXY_SCFG_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
 	MAP_REGION_FLAT(SEC_PROXY_DATA_BASE, SEC_PROXY_DATA_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
 	{ /* sentinel */ }
@@ -100,13 +99,13 @@
 void bl31_plat_arch_setup(void)
 {
 	const mmap_region_t bl_regions[] = {
-		MAP_REGION_FLAT(BL31_BASE, BL31_END - BL31_BASE,
-				MT_MEMORY | MT_RW | MT_SECURE),
-		MAP_REGION_FLAT(BL_CODE_BASE, BL_CODE_END - BL_CODE_BASE,
-				MT_CODE | MT_SECURE),
-		MAP_REGION_FLAT(BL_RO_DATA_BASE, BL_RO_DATA_END - BL_RO_DATA_END,
-				MT_RO_DATA | MT_SECURE),
-		{0}
+		MAP_REGION_FLAT(BL31_START,           BL31_END            - BL31_START,           MT_MEMORY  | MT_RW | MT_SECURE),
+		MAP_REGION_FLAT(BL_CODE_BASE,         BL_CODE_END         - BL_CODE_BASE,         MT_CODE    | MT_RO | MT_SECURE),
+		MAP_REGION_FLAT(BL_RO_DATA_BASE,      BL_RO_DATA_END      - BL_RO_DATA_BASE,      MT_RO_DATA | MT_RO | MT_SECURE),
+#if USE_COHERENT_MEM
+		MAP_REGION_FLAT(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, MT_DEVICE  | MT_RW | MT_SECURE),
+#endif
+		{ /* sentinel */ }
 	};
 
 	setup_page_tables(bl_regions, plat_k3_mmap);
diff --git a/plat/ti/k3/common/k3_console.c b/plat/ti/k3/common/k3_console.c
index 31c9632..ba0ddac 100644
--- a/plat/ti/k3/common/k3_console.c
+++ b/plat/ti/k3/common/k3_console.c
@@ -16,6 +16,6 @@
 	static console_16550_t console;
 
 	/* Initialize the console to provide early debug support */
-	console_16550_register(K3_USART_BASE_ADDRESS, K3_USART_CLK_SPEED,
+	console_16550_register(K3_USART_BASE, K3_USART_CLK_SPEED,
 			       K3_USART_BAUD, &console);
 }
diff --git a/plat/ti/k3/common/k3_helpers.S b/plat/ti/k3/common/k3_helpers.S
index 3dfdda4..1ab1af5 100644
--- a/plat/ti/k3/common/k3_helpers.S
+++ b/plat/ti/k3/common/k3_helpers.S
@@ -73,21 +73,17 @@
 	lsr	x1, x1, #MPIDR_AFF1_SHIFT
 	and	x0, x0, #MPIDR_CPU_MASK
 
-#if K3_CLUSTER1_MSMC_PORT != UNUSED
-	cmp	x1, #K3_CLUSTER0_MSMC_PORT
+	cmp	x1, 0
 	b.eq out
 	add	x0, x0, #K3_CLUSTER0_CORE_COUNT
-#if K3_CLUSTER2_MSMC_PORT != UNUSED
-	cmp	x1, #K3_CLUSTER1_MSMC_PORT
+
+	cmp	x1, 1
 	b.eq out
 	add	x0, x0, #K3_CLUSTER1_CORE_COUNT
-#if K3_CLUSTER3_MSMC_PORT != UNUSED
-	cmp	x1, #K3_CLUSTER2_MSMC_PORT
+
+	cmp	x1, 2
 	b.eq out
 	add	x0, x0, #K3_CLUSTER2_CORE_COUNT
-#endif /* K3_CLUSTER3_MSMC_PORT != UNUSED */
-#endif /* K3_CLUSTER2_MSMC_PORT != UNUSED */
-#endif /* K3_CLUSTER1_MSMC_PORT != UNUSED */
 
 out:
 	ret
diff --git a/plat/ti/k3/common/k3_psci.c b/plat/ti/k3/common/k3_psci.c
index f66f12a..c7754e9 100644
--- a/plat/ti/k3/common/k3_psci.c
+++ b/plat/ti/k3/common/k3_psci.c
@@ -17,10 +17,10 @@
 #include <k3_gicv3.h>
 #include <ti_sci.h>
 
+#ifdef TI_AM65X_WORKAROUND
 /* Need to flush psci internal locks before shutdown or their values are lost */
 #include "../../../../lib/psci/psci_private.h"
-
-#define STUB() ERROR("stub %s called\n", __func__)
+#endif
 
 uintptr_t k3_sec_entrypoint;
 
@@ -115,6 +115,7 @@
 	k3_gic_cpuif_enable();
 }
 
+#ifdef TI_AM65X_WORKAROUND
 static void  __dead2 k3_pwr_domain_pwr_down_wfi(const psci_power_state_t
 						  *target_state)
 {
@@ -122,6 +123,7 @@
 	flush_dcache_range((uintptr_t) psci_locks, sizeof(psci_locks));
 	psci_power_down_wfi();
 }
+#endif
 
 static void __dead2 k3_system_reset(void)
 {
@@ -152,7 +154,9 @@
 	.pwr_domain_on = k3_pwr_domain_on,
 	.pwr_domain_off = k3_pwr_domain_off,
 	.pwr_domain_on_finish = k3_pwr_domain_on_finish,
+#ifdef TI_AM65X_WORKAROUND
 	.pwr_domain_pwr_down_wfi = k3_pwr_domain_pwr_down_wfi,
+#endif
 	.system_reset = k3_system_reset,
 	.validate_power_state = k3_validate_power_state,
 	.validate_ns_entrypoint = k3_validate_ns_entrypoint
diff --git a/plat/ti/k3/common/k3_topology.c b/plat/ti/k3/common/k3_topology.c
index 2b98acb..139f1fd 100644
--- a/plat/ti/k3/common/k3_topology.c
+++ b/plat/ti/k3/common/k3_topology.c
@@ -13,15 +13,9 @@
 	PLATFORM_SYSTEM_COUNT,
 	PLATFORM_CLUSTER_COUNT,
 	K3_CLUSTER0_CORE_COUNT,
-#if K3_CLUSTER1_MSMC_PORT != UNUSED
 	K3_CLUSTER1_CORE_COUNT,
-#endif /* K3_CLUSTER1_MSMC_PORT != UNUSED */
-#if K3_CLUSTER2_MSMC_PORT != UNUSED
 	K3_CLUSTER2_CORE_COUNT,
-#endif /* K3_CLUSTER2_MSMC_PORT != UNUSED */
-#if K3_CLUSTER3_MSMC_PORT != UNUSED
 	K3_CLUSTER3_CORE_COUNT,
-#endif /* K3_CLUSTER3_MSMC_PORT != UNUSED */
 };
 
 const unsigned char *plat_get_power_domain_tree_desc(void)
@@ -31,42 +25,22 @@
 
 int plat_core_pos_by_mpidr(u_register_t mpidr)
 {
-	unsigned int cpu_id;
+	unsigned int cluster = MPIDR_AFFLVL1_VAL(mpidr);
+	unsigned int core = MPIDR_AFFLVL0_VAL(mpidr);
 
-	mpidr &= MPIDR_AFFINITY_MASK;
-
-	if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK))
+	if (MPIDR_AFFLVL3_VAL(mpidr) > 0 ||
+	    MPIDR_AFFLVL2_VAL(mpidr) > 0) {
 		return -1;
-
-	cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
+	}
 
-	switch (MPIDR_AFFLVL1_VAL(mpidr)) {
-	case K3_CLUSTER0_MSMC_PORT:
-		if (cpu_id < K3_CLUSTER0_CORE_COUNT)
-			return cpu_id;
+	if (cluster > 0)
+		core += K3_CLUSTER0_CORE_COUNT;
+	if (cluster > 1)
+		core += K3_CLUSTER1_CORE_COUNT;
+	if (cluster > 2)
+		core += K3_CLUSTER2_CORE_COUNT;
+	if (cluster > 3)
 		return -1;
-#if K3_CLUSTER1_MSMC_PORT != UNUSED
-	case K3_CLUSTER1_MSMC_PORT:
-		if (cpu_id < K3_CLUSTER1_CORE_COUNT)
-			return K3_CLUSTER0_CORE_COUNT + cpu_id;
-		return -1;
-#endif /* K3_CLUSTER1_MSMC_PORT != UNUSED */
-#if K3_CLUSTER2_MSMC_PORT != UNUSED
-	case K3_CLUSTER2_MSMC_PORT:
-		if (cpu_id < K3_CLUSTER2_CORE_COUNT)
-			return K3_CLUSTER0_CORE_COUNT +
-			       K3_CLUSTER1_CORE_COUNT + cpu_id;
-		return -1;
-#endif /* K3_CLUSTER2_MSMC_PORT != UNUSED */
-#if K3_CLUSTER3_MSMC_PORT != UNUSED
-	case K3_CLUSTER3_MSMC_PORT:
-		if (cpu_id < K3_CLUSTER3_CORE_COUNT)
-			return K3_CLUSTER0_CORE_COUNT +
-			       K3_CLUSTER1_CORE_COUNT +
-			       K3_CLUSTER2_CORE_COUNT + cpu_id;
-		return -1;
-#endif /* K3_CLUSTER3_MSMC_PORT != UNUSED */
-	default:
-		return -1;
-	}
+
+	return core;
 }
diff --git a/plat/ti/k3/common/plat_common.mk b/plat/ti/k3/common/plat_common.mk
index c91a035..29fcafd 100644
--- a/plat/ti/k3/common/plat_common.mk
+++ b/plat/ti/k3/common/plat_common.mk
@@ -22,6 +22,9 @@
 ERRATA_A53_843419	:=	1
 ERRATA_A53_855873	:=	1
 
+# Split out RO data into a non-executable section
+SEPARATE_CODE_AND_RODATA :=    1
+
 # Leave the caches enabled on core powerdown path
 TI_AM65X_WORKAROUND	:=	1
 $(eval $(call add_define,TI_AM65X_WORKAROUND))
diff --git a/plat/ti/k3/include/platform_def.h b/plat/ti/k3/include/platform_def.h
index f1511c1..690c68e 100644
--- a/plat/ti/k3/include/platform_def.h
+++ b/plat/ti/k3/include/platform_def.h
@@ -29,39 +29,10 @@
 					K3_CLUSTER2_CORE_COUNT + \
 					K3_CLUSTER3_CORE_COUNT)
 
-#define PLATFORM_CLUSTER_COUNT		((K3_CLUSTER0_MSMC_PORT != UNUSED) + \
-					(K3_CLUSTER1_MSMC_PORT != UNUSED) + \
-					(K3_CLUSTER2_MSMC_PORT != UNUSED) + \
-					(K3_CLUSTER3_MSMC_PORT != UNUSED))
-
-#define UNUSED				-1
-
-#if !defined(K3_CLUSTER1_CORE_COUNT) || !defined(K3_CLUSTER1_MSMC_PORT)
-#define K3_CLUSTER1_CORE_COUNT		0
-#define K3_CLUSTER1_MSMC_PORT		UNUSED
-#endif
-
-#if !defined(K3_CLUSTER2_CORE_COUNT) || !defined(K3_CLUSTER2_MSMC_PORT)
-#define K3_CLUSTER2_CORE_COUNT		0
-#define K3_CLUSTER2_MSMC_PORT		UNUSED
-#endif
-
-#if !defined(K3_CLUSTER3_CORE_COUNT) || !defined(K3_CLUSTER3_MSMC_PORT)
-#define K3_CLUSTER3_CORE_COUNT		0
-#define K3_CLUSTER3_MSMC_PORT		UNUSED
-#endif
-
-#if K3_CLUSTER0_MSMC_PORT == UNUSED
-#error "ARM cluster 0 must be used"
-#endif
-
-#if ((K3_CLUSTER1_MSMC_PORT == UNUSED) && (K3_CLUSTER1_CORE_COUNT != 0)) || \
-    ((K3_CLUSTER2_MSMC_PORT == UNUSED) && (K3_CLUSTER2_CORE_COUNT != 0)) || \
-    ((K3_CLUSTER3_MSMC_PORT == UNUSED) && (K3_CLUSTER3_CORE_COUNT != 0))
-#error "Unused ports must have 0 ARM cores"
-#endif
-
-#define PLATFORM_CLUSTER_OFFSET		K3_CLUSTER0_MSMC_PORT
+#define PLATFORM_CLUSTER_COUNT		((K3_CLUSTER0_CORE_COUNT != 0) + \
+					(K3_CLUSTER1_CORE_COUNT != 0) + \
+					(K3_CLUSTER2_CORE_COUNT != 0) + \
+					(K3_CLUSTER3_CORE_COUNT != 0))
 
 #define PLAT_NUM_PWR_DOMAINS		(PLATFORM_SYSTEM_COUNT + \
 					PLATFORM_CLUSTER_COUNT + \
@@ -74,20 +45,14 @@
 
 /*
  * ARM-TF lives in SRAM, partition it here
- */
-
-#define SHARED_RAM_BASE			BL31_LIMIT
-#define SHARED_RAM_SIZE			0x00001000
-
-/*
+ *
  * BL3-1 specific defines.
  *
- * Put BL3-1 at the base of the Trusted SRAM, before SHARED_RAM.
+ * Put BL3-1 at the base of the Trusted SRAM.
  */
 #define BL31_BASE			SEC_SRAM_BASE
-#define BL31_SIZE			(SEC_SRAM_SIZE - SHARED_RAM_SIZE)
+#define BL31_SIZE			SEC_SRAM_SIZE
 #define BL31_LIMIT			(BL31_BASE + BL31_SIZE)
-#define BL31_PROGBITS_LIMIT		BL31_LIMIT
 
 /*
  * Defines the maximum number of translation tables that are allocated by the
@@ -125,8 +90,8 @@
 #define CACHE_WRITEBACK_GRANULE		(1 << CACHE_WRITEBACK_SHIFT)
 
 /* Platform default console definitions */
-#ifndef K3_USART_BASE_ADDRESS
-#define K3_USART_BASE_ADDRESS 0x02800000
+#ifndef K3_USART_BASE
+#define K3_USART_BASE 0x02800000
 #endif
 
 /* USART has a default size for address space */
@@ -137,7 +102,7 @@
 #endif
 
 /* Crash console defaults */
-#define CRASH_CONSOLE_BASE K3_USART_BASE_ADDRESS
+#define CRASH_CONSOLE_BASE K3_USART_BASE
 #define CRASH_CONSOLE_CLK K3_USART_CLK_SPEED
 #define CRASH_CONSOLE_BAUD_RATE K3_USART_BAUD
 
diff --git a/readme.rst b/readme.rst
index 998369f..fc03555 100644
--- a/readme.rst
+++ b/readme.rst
@@ -12,7 +12,7 @@
 such as:
 
 -  The `Power State Coordination Interface (PSCI)`_
--  Trusted Board Boot Requirements (TBBR, Arm DEN0006C-1)
+-  `Trusted Board Boot Requirements CLIENT (TBBR-CLIENT)`_
 -  `SMC Calling Convention`_
 -  `System Control and Management Interface (SCMI)`_
 -  `Software Delegated Exception Interface (SDEI)`_
@@ -320,6 +320,7 @@
 .. _Secure Monitor: http://www.arm.com/products/processors/technologies/trustzone/tee-smc.php
 .. _Power State Coordination Interface (PSCI): PSCI_
 .. _PSCI: http://infocenter.arm.com/help/topic/com.arm.doc.den0022d/Power_State_Coordination_Interface_PDD_v1_1_DEN0022D.pdf
+.. _Trusted Board Boot Requirements CLIENT (TBBR-CLIENT): https://developer.arm.com/docs/den0006/latest/trusted-board-boot-requirements-client-tbbr-client-armv8-a
 .. _SMC Calling Convention: http://infocenter.arm.com/help/topic/com.arm.doc.den0028b/ARM_DEN0028B_SMC_Calling_Convention.pdf
 .. _System Control and Management Interface (SCMI): SCMI_
 .. _SCMI: http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/DEN0056A_System_Control_and_Management_Interface.pdf