Merge changes from topic "sb/dualroot" into integration

* changes:
  plat/arm: Pass cookie argument down to arm_get_rotpk_info()
  plat/arm: Add support for dualroot CoT
  plat/arm: Provide some PROTK files for development
diff --git a/Makefile b/Makefile
index 547b584..3d5b395 100644
--- a/Makefile
+++ b/Makefile
@@ -159,6 +159,14 @@
 endif
 endif
 
+ifneq (${DECRYPTION_SUPPORT},none)
+ENC_ARGS += -f ${FW_ENC_STATUS}
+ENC_ARGS += -k ${ENC_KEY}
+ENC_ARGS += -n ${ENC_NONCE}
+FIP_DEPS += enctool
+FWU_FIP_DEPS += enctool
+endif
+
 ################################################################################
 # Toolchain
 ################################################################################
@@ -412,40 +420,48 @@
 ################################################################################
 
 ifneq (${SPD},none)
-ifeq (${ARCH},aarch32)
+    ifeq (${ARCH},aarch32)
         $(error "Error: SPD is incompatible with AArch32.")
-endif
-ifdef EL3_PAYLOAD_BASE
+    endif
+
+    ifdef EL3_PAYLOAD_BASE
         $(warning "SPD and EL3_PAYLOAD_BASE are incompatible build options.")
         $(warning "The SPD and its BL32 companion will be present but ignored.")
-endif
-	ifeq (${SPD},spmd)
-		# SPMD is located in std_svc directory
-		SPD_DIR := std_svc
-	else
-		# All other SPDs in spd directory
-		SPD_DIR := spd
-	endif
-
-	# We expect to locate an spd.mk under the specified SPD directory
-	SPD_MAKE	:=	$(wildcard services/${SPD_DIR}/${SPD}/${SPD}.mk)
+    endif
 
+    ifeq (${SPD},spmd)
+        $(warning "SPMD is an experimental feature")
+        # SPMD is located in std_svc directory
+        SPD_DIR := std_svc
 
-        ifeq (${SPD_MAKE},)
-                $(error Error: No services/${SPD_DIR}/${SPD}/${SPD}.mk located)
+        ifeq ($(SPMD_SPM_AT_SEL2),1)
+            ifeq ($(CTX_INCLUDE_EL2_REGS),0)
+                $(error SPMD with SPM at S-EL2 requires CTX_INCLUDE_EL2_REGS option)
+            endif
         endif
-        $(info Including ${SPD_MAKE})
-        include ${SPD_MAKE}
+    else
+        # All other SPDs in spd directory
+        SPD_DIR := spd
+    endif
+
+    # We expect to locate an spd.mk under the specified SPD directory
+    SPD_MAKE	:=	$(wildcard services/${SPD_DIR}/${SPD}/${SPD}.mk)
+
+    ifeq (${SPD_MAKE},)
+        $(error Error: No services/${SPD_DIR}/${SPD}/${SPD}.mk located)
+    endif
+    $(info Including ${SPD_MAKE})
+    include ${SPD_MAKE}
 
-        # If there's BL32 companion for the chosen SPD, we expect that the SPD's
-        # Makefile would set NEED_BL32 to "yes". In this case, the build system
-        # supports two mutually exclusive options:
-        # * BL32 is built from source: then BL32_SOURCES must contain the list
-        #   of source files to build BL32
-        # * BL32 is a prebuilt binary: then BL32 must point to the image file
-        #   that will be included in the FIP
-        # If both BL32_SOURCES and BL32 are defined, the binary takes precedence
-        # over the sources.
+    # If there's BL32 companion for the chosen SPD, we expect that the SPD's
+    # Makefile would set NEED_BL32 to "yes". In this case, the build system
+    # supports two mutually exclusive options:
+    # * BL32 is built from source: then BL32_SOURCES must contain the list
+    #   of source files to build BL32
+    # * BL32 is a prebuilt binary: then BL32 must point to the image file
+    #   that will be included in the FIP
+    # If both BL32_SOURCES and BL32 are defined, the binary takes precedence
+    # over the sources.
 endif
 
 ################################################################################
@@ -615,12 +631,26 @@
 
 ifeq ($(MEASURED_BOOT),1)
     ifneq (${TRUSTED_BOARD_BOOT},1)
-        $(error MEASURED_BOOT requires TRUSTED_BOARD_BOOT=1")
+        $(error MEASURED_BOOT requires TRUSTED_BOARD_BOOT=1)
     else
         $(info MEASURED_BOOT is an experimental feature)
     endif
 endif
 
+ifeq (${ARM_XLAT_TABLES_LIB_V1}, 1)
+    ifeq (${ALLOW_RO_XLAT_TABLES}, 1)
+        $(error "ALLOW_RO_XLAT_TABLES requires translation tables library v2")
+    endif
+endif
+
+ifneq (${DECRYPTION_SUPPORT},none)
+    ifeq (${TRUSTED_BOARD_BOOT}, 0)
+        $(error TRUSTED_BOARD_BOOT must be enabled for DECRYPTION_SUPPORT to be set)
+    else
+        $(info DECRYPTION_SUPPORT is an experimental feature)
+    endif
+endif
+
 ################################################################################
 # Process platform overrideable behaviour
 ################################################################################
@@ -694,6 +724,10 @@
 CRTTOOLPATH		?=	tools/cert_create
 CRTTOOL			?=	${CRTTOOLPATH}/cert_create${BIN_EXT}
 
+# Variables for use with Firmware Encryption Tool
+ENCTOOLPATH		?=	tools/encrypt_fw
+ENCTOOL			?=	${ENCTOOLPATH}/encrypt_fw${BIN_EXT}
+
 # Variables for use with Firmware Image Package
 FIPTOOLPATH		?=	tools/fiptool
 FIPTOOL			?=	${FIPTOOLPATH}/fiptool${BIN_EXT}
@@ -701,6 +735,7 @@
 # Variables for use with sptool
 SPTOOLPATH		?=	tools/sptool
 SPTOOL			?=	${SPTOOLPATH}/sptool${BIN_EXT}
+SP_MK_GEN		?=	${SPTOOLPATH}/sp_mk_generator.py
 
 # Variables for use with ROMLIB
 ROMLIBPATH		?=	lib/romlib
@@ -747,12 +782,14 @@
 # Build options checks
 ################################################################################
 
+$(eval $(call assert_boolean,ALLOW_RO_XLAT_TABLES))
 $(eval $(call assert_boolean,COLD_BOOT_SINGLE_CPU))
 $(eval $(call assert_boolean,CREATE_KEYS))
 $(eval $(call assert_boolean,CTX_INCLUDE_AARCH32_REGS))
 $(eval $(call assert_boolean,CTX_INCLUDE_FPREGS))
 $(eval $(call assert_boolean,CTX_INCLUDE_PAUTH_REGS))
 $(eval $(call assert_boolean,CTX_INCLUDE_MTE_REGS))
+$(eval $(call assert_boolean,CTX_INCLUDE_EL2_REGS))
 $(eval $(call assert_boolean,DEBUG))
 $(eval $(call assert_boolean,DYN_DISABLE_AUTH))
 $(eval $(call assert_boolean,EL3_EXCEPTION_HANDLING))
@@ -771,6 +808,7 @@
 $(eval $(call assert_boolean,GICV2_G0_FOR_EL3))
 $(eval $(call assert_boolean,HANDLE_EA_EL3_FIRST))
 $(eval $(call assert_boolean,HW_ASSISTED_COHERENCY))
+$(eval $(call assert_boolean,INVERTED_MEMMAP))
 $(eval $(call assert_boolean,MEASURED_BOOT))
 $(eval $(call assert_boolean,NS_TIMER_SWITCH))
 $(eval $(call assert_boolean,OVERRIDE_LIBC))
@@ -784,6 +822,7 @@
 $(eval $(call assert_boolean,SEPARATE_NOBITS_REGION))
 $(eval $(call assert_boolean,SPIN_ON_BL1_EXIT))
 $(eval $(call assert_boolean,SPM_MM))
+$(eval $(call assert_boolean,SPMD_SPM_AT_SEL2))
 $(eval $(call assert_boolean,TRUSTED_BOARD_BOOT))
 $(eval $(call assert_boolean,USE_COHERENT_MEM))
 $(eval $(call assert_boolean,USE_DEBUGFS))
@@ -795,10 +834,13 @@
 $(eval $(call assert_boolean,BL2_IN_XIP_MEM))
 $(eval $(call assert_boolean,BL2_INV_DCACHE))
 $(eval $(call assert_boolean,USE_SPINLOCK_CAS))
+$(eval $(call assert_boolean,ENCRYPT_BL31))
+$(eval $(call assert_boolean,ENCRYPT_BL32))
 
 $(eval $(call assert_numeric,ARM_ARCH_MAJOR))
 $(eval $(call assert_numeric,ARM_ARCH_MINOR))
 $(eval $(call assert_numeric,BRANCH_PROTECTION))
+$(eval $(call assert_numeric,FW_ENC_STATUS))
 
 ifdef KEY_SIZE
         $(eval $(call assert_numeric,KEY_SIZE))
@@ -814,6 +856,7 @@
 # platform to overwrite the default options
 ################################################################################
 
+$(eval $(call add_define,ALLOW_RO_XLAT_TABLES))
 $(eval $(call add_define,ARM_ARCH_MAJOR))
 $(eval $(call add_define,ARM_ARCH_MINOR))
 $(eval $(call add_define,COLD_BOOT_SINGLE_CPU))
@@ -822,6 +865,8 @@
 $(eval $(call add_define,CTX_INCLUDE_PAUTH_REGS))
 $(eval $(call add_define,EL3_EXCEPTION_HANDLING))
 $(eval $(call add_define,CTX_INCLUDE_MTE_REGS))
+$(eval $(call add_define,CTX_INCLUDE_EL2_REGS))
+$(eval $(call add_define,DECRYPTION_SUPPORT_${DECRYPTION_SUPPORT}))
 $(eval $(call add_define,ENABLE_AMU))
 $(eval $(call add_define,ENABLE_ASSERTIONS))
 $(eval $(call add_define,ENABLE_BTI))
@@ -833,6 +878,8 @@
 $(eval $(call add_define,ENABLE_RUNTIME_INSTRUMENTATION))
 $(eval $(call add_define,ENABLE_SPE_FOR_LOWER_ELS))
 $(eval $(call add_define,ENABLE_SVE_FOR_NS))
+$(eval $(call add_define,ENCRYPT_BL31))
+$(eval $(call add_define,ENCRYPT_BL32))
 $(eval $(call add_define,ERROR_DEPRECATED))
 $(eval $(call add_define,FAULT_INJECTION_SUPPORT))
 $(eval $(call add_define,GICV2_G0_FOR_EL3))
@@ -853,6 +900,7 @@
 $(eval $(call add_define,SPD_${SPD}))
 $(eval $(call add_define,SPIN_ON_BL1_EXIT))
 $(eval $(call add_define,SPM_MM))
+$(eval $(call add_define,SPMD_SPM_AT_SEL2))
 $(eval $(call add_define,TRUSTED_BOARD_BOOT))
 $(eval $(call add_define,USE_COHERENT_MEM))
 $(eval $(call add_define,USE_DEBUGFS))
@@ -889,11 +937,22 @@
 $(eval $(call add_define,USE_ARM_LINK))
 endif
 
+# Generate and include sp_gen.mk if SPD is spmd and SP_LAYOUT_FILE is defined
+ifdef SP_LAYOUT_FILE
+ifeq (${SPD},spmd)
+        -include $(BUILD_PLAT)/sp_gen.mk
+        FIP_DEPS += sp
+        NEED_SP_PKG := yes
+else
+        $(error "SP_LAYOUT_FILE will be used only if SPD=spmd")
+endif
+endif
+
 ################################################################################
 # Build targets
 ################################################################################
 
-.PHONY:	all msg_start clean realclean distclean cscope locate-checkpatch checkcodebase checkpatch fiptool sptool fip fwu_fip certtool dtbs memmap doc
+.PHONY:	all msg_start clean realclean distclean cscope locate-checkpatch checkcodebase checkpatch fiptool sptool fip sp fwu_fip certtool dtbs memmap doc enctool
 .SUFFIXES:
 
 all: msg_start
@@ -941,9 +1000,14 @@
 
 ifeq (${NEED_BL31},yes)
 BL31_SOURCES += ${SPD_SOURCES}
+ifneq (${DECRYPTION_SUPPORT},none)
+$(if ${BL31}, $(eval $(call TOOL_ADD_IMG,bl31,--soc-fw,,$(ENCRYPT_BL31))),\
+	$(eval $(call MAKE_BL,31,soc-fw,,$(ENCRYPT_BL31))))
+else
 $(if ${BL31}, $(eval $(call TOOL_ADD_IMG,bl31,--soc-fw)),\
 	$(eval $(call MAKE_BL,31,soc-fw)))
 endif
+endif
 
 # If a BL32 image is needed but neither BL32 nor BL32_SOURCES is defined, the
 # build system will call TOOL_ADD_IMG to print a warning message and abort the
@@ -952,9 +1016,14 @@
 
 BUILD_BL32 := $(if $(BL32),,$(if $(BL32_SOURCES),1))
 
+ifneq (${DECRYPTION_SUPPORT},none)
+$(if ${BUILD_BL32}, $(eval $(call MAKE_BL,32,tos-fw,,$(ENCRYPT_BL32))),\
+	$(eval $(call TOOL_ADD_IMG,bl32,--tos-fw,,$(ENCRYPT_BL32))))
+else
 $(if ${BUILD_BL32}, $(eval $(call MAKE_BL,32,tos-fw)),\
 	$(eval $(call TOOL_ADD_IMG,bl32,--tos-fw)))
 endif
+endif
 
 # Add the BL33 image if required by the platform
 ifeq (${NEED_BL33},yes)
@@ -971,6 +1040,17 @@
     $(eval $(call MAKE_DTBS,$(BUILD_PLAT)/fdts,$(FDT_SOURCES)))
 endif
 
+# Add Secure Partition packages
+ifeq (${NEED_SP_PKG},yes)
+$(BUILD_PLAT)/sp_gen.mk: ${SP_MK_GEN} ${SP_LAYOUT_FILE} | ${BUILD_PLAT}
+	${Q}${PYTHON} "$<" "$@" $(filter-out $<,$^) $(BUILD_PLAT)
+sp: $(SPTOOL) $(DTBS) $(BUILD_PLAT)/sp_gen.mk
+	${Q}$(SPTOOL) $(SPTOOL_ARGS)
+	@${ECHO_BLANK_LINE}
+	@echo "Built SP Images successfully"
+	@${ECHO_BLANK_LINE}
+endif
+
 locate-checkpatch:
 ifndef CHECKPATCH
 	$(error "Please set CHECKPATCH to point to the Linux checkpatch.pl file, eg: CHECKPATCH=../linux/scripts/checkpatch.pl")
@@ -985,6 +1065,7 @@
 	$(call SHELL_REMOVE_DIR,${BUILD_PLAT})
 	${Q}${MAKE} --no-print-directory -C ${FIPTOOLPATH} clean
 	${Q}${MAKE} PLAT=${PLAT} --no-print-directory -C ${CRTTOOLPATH} clean
+	${Q}${MAKE} PLAT=${PLAT} --no-print-directory -C ${ENCTOOLPATH} clean
 	${Q}${MAKE} --no-print-directory -C ${ROMLIBPATH} clean
 
 realclean distclean:
@@ -994,6 +1075,7 @@
 	${Q}${MAKE} --no-print-directory -C ${FIPTOOLPATH} clean
 	${Q}${MAKE} --no-print-directory -C ${SPTOOLPATH} clean
 	${Q}${MAKE} PLAT=${PLAT} --no-print-directory -C ${CRTTOOLPATH} clean
+	${Q}${MAKE} PLAT=${PLAT} --no-print-directory -C ${ENCTOOLPATH} realclean
 	${Q}${MAKE} --no-print-directory -C ${ROMLIBPATH} clean
 
 checkcodebase:		locate-checkpatch
@@ -1089,12 +1171,21 @@
 
 # Call print_memory_map tool
 memmap: all
-	${Q}${PYTHON} $(PRINT_MEMORY_MAP) $(BUILD_PLAT)
+	${Q}${PYTHON} ${PRINT_MEMORY_MAP} ${BUILD_PLAT} ${INVERTED_MEMMAP}
 
 doc:
 	@echo "  BUILD DOCUMENTATION"
 	${Q}${MAKE} --no-print-directory -C ${DOCS_PATH} html
 
+enctool: ${ENCTOOL}
+
+.PHONY: ${ENCTOOL}
+${ENCTOOL}:
+	${Q}${MAKE} PLAT=${PLAT} BUILD_INFO=0 --no-print-directory -C ${ENCTOOLPATH}
+	@${ECHO_BLANK_LINE}
+	@echo "Built $@ successfully"
+	@${ECHO_BLANK_LINE}
+
 cscope:
 	@echo "  CSCOPE"
 	${Q}find ${CURDIR} -name "*.[chsS]" > cscope.files
@@ -1131,7 +1222,9 @@
 	@echo "  cscope         Generate cscope index"
 	@echo "  distclean      Remove all build artifacts for all platforms"
 	@echo "  certtool       Build the Certificate generation tool"
+	@echo "  enctool        Build the Firmware encryption tool"
 	@echo "  fiptool        Build the Firmware Image Package (FIP) creation tool"
+	@echo "  sp             Build the Secure Partition Packages"
 	@echo "  sptool         Build the Secure Partition Package creation tool"
 	@echo "  dtbs           Build the Device Tree Blobs (if required for the platform)"
 	@echo "  memmap         Print the memory map of the built binaries"
diff --git a/bl1/aarch32/bl1_exceptions.S b/bl1/aarch32/bl1_exceptions.S
index f2af9ab..493d2ca 100644
--- a/bl1/aarch32/bl1_exceptions.S
+++ b/bl1/aarch32/bl1_exceptions.S
@@ -80,7 +80,7 @@
 
 	add	r8, r8, #ENTRY_POINT_INFO_ARGS_OFFSET
 	ldm	r8, {r0, r1, r2, r3}
-	eret
+	exception_return
 endfunc bl1_aarch32_smc_handler
 
 	/* -----------------------------------------------------
diff --git a/bl2/aarch32/bl2_el3_entrypoint.S b/bl2/aarch32/bl2_el3_entrypoint.S
index 9b4da6b..2e851e6 100644
--- a/bl2/aarch32/bl2_el3_entrypoint.S
+++ b/bl2/aarch32/bl2_el3_entrypoint.S
@@ -87,5 +87,5 @@
 
 	add	r8, r8, #ENTRY_POINT_INFO_ARGS_OFFSET
 	ldm	r8, {r0, r1, r2, r3}
-	eret
+	exception_return
 endfunc bl2_run_next_image
diff --git a/bl32/tsp/tsp_main.c b/bl32/tsp/tsp_main.c
index e1d961c..9da2f9a 100644
--- a/bl32/tsp/tsp_main.c
+++ b/bl32/tsp/tsp_main.c
@@ -273,11 +273,11 @@
 	spin_lock(&console_lock);
 	INFO("TSP: cpu 0x%lx resumed. maximum off power level %lld\n",
 	     read_mpidr(), max_off_pwrlvl);
-	INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu suspend requests\n",
+	INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu resume requests\n",
 		read_mpidr(),
 		tsp_stats[linear_id].smc_count,
 		tsp_stats[linear_id].eret_count,
-		tsp_stats[linear_id].cpu_suspend_count);
+		tsp_stats[linear_id].cpu_resume_count);
 	spin_unlock(&console_lock);
 #endif
 	/* Indicate to the SPD that we have completed this request */
diff --git a/docs/about/maintainers.rst b/docs/about/maintainers.rst
index 802dafc..2bf5eb7 100644
--- a/docs/about/maintainers.rst
+++ b/docs/about/maintainers.rst
@@ -53,7 +53,6 @@
 :M: Remi Pommarel <repk@triplefau.lt>
 :G: `remi-triplefault`_
 :F: docs/plat/meson-gxl.rst
-:F: drivers/amlogic/gxl
 :F: plat/amlogic/gxl/
 
 Amlogic Meson S905X2 (G12A) platform port
@@ -61,7 +60,6 @@
 :M: Carlo Caione <ccaione@baylibre.com>
 :G: `carlocaione`_
 :F: docs/plat/meson-g12a.rst
-:F: drivers/amlogic/g12a
 :F: plat/amlogic/g12a/
 
 Amlogic Meson A113D (AXG) platform port
@@ -69,7 +67,6 @@
 :M: Carlo Caione <ccaione@baylibre.com>
 :G: `carlocaione`_
 :F: docs/plat/meson-axg.rst
-:F: drivers/amlogic/axg
 :F: plat/amlogic/axg/
 
 Armv7-A architecture port
@@ -152,7 +149,7 @@
 --------------------------------------
 :M: Konstantin Porotchkin <kostap@marvell.com>
 :G: `kostapr`_
-:F: docs/marvell/
+:F: docs/plat/marvell/
 :F: plat/marvell/
 :F: drivers/marvell/
 :F: tools/marvell/
@@ -197,14 +194,14 @@
 ------------------------
 :M: Jacky Bai <ping.bai@nxp.com>
 :G: `JackyBai`_
-:F: doc/plat/imx8m.rst
+:F: docs/plat/imx8m.rst
 :F: plat/imx/imx8m/
 
 OP-TEE dispatcher
 -----------------
 :M: Jens Wiklander <jens.wiklander@linaro.org>
 :G: `jenswi-linaro`_
-:F: docs/spd/optee-dispatcher.rst
+:F: docs/components/spd/optee-dispatcher.rst
 :F: services/spd/opteed/
 
 QEMU platform port
@@ -219,7 +216,7 @@
 :M: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
 :G: `grandpaul`_
 :F: docs/plat/rpi3.rst
-:F: plat/rpi3/
+:F: plat/rpi/rpi3/
 :F: drivers/rpi3/
 :F: include/drivers/rpi3/
 
@@ -273,8 +270,8 @@
 --------------------------
 :M: Varun Wadekar <vwadekar@nvidia.com>
 :G: `vwadekar`_
-:F: docs/spd/tlk-dispatcher.rst
-:F: docs/spd/trusty-dispatcher.rst
+:F: docs/components/spd/tlk-dispatcher.rst
+:F: docs/components/spd/trusty-dispatcher.rst
 :F: include/bl32/payloads/tlk.h
 :F: services/spd/tlkd/
 :F: services/spd/trusty/
diff --git a/docs/change-log-upcoming.rst b/docs/change-log-upcoming.rst
index 14280cb..15f39de 100644
--- a/docs/change-log-upcoming.rst
+++ b/docs/change-log-upcoming.rst
@@ -33,6 +33,7 @@
 
 - Libraries
    - Example: "Introduce BTI support in Library at ROM (romlib)"
+   - Add Firmware Configuration Framework (fconf).
 
 - New Platforms Support
    - Example: "qemu/qemu_sbsa: New platform support added for QEMU SBSA platform"
@@ -45,6 +46,7 @@
 
 - Security
    - Example: "UBSAN support and handlers"
+   - Add support for optional firmware encryption feature (experimental).
 
 - Tools
    - Example: "fiptool: Add support to build fiptool on Windows."
diff --git a/docs/design/auth-framework.rst b/docs/design/auth-framework.rst
index 93f691b..1a53e22 100644
--- a/docs/design/auth-framework.rst
+++ b/docs/design/auth-framework.rst
@@ -621,7 +621,7 @@
 
 The CoT can be found in ``drivers/auth/tbbr/tbbr_cot.c``. This CoT consists of
 an array of pointers to image descriptors and it is registered in the framework
-using the macro ``REGISTER_COT(cot_desc)``, where 'cot_desc' must be the name
+using the macro ``REGISTER_COT(cot_desc)``, where ``cot_desc`` must be the name
 of the array (passing a pointer or any other type of indirection will cause the
 registration process to fail).
 
@@ -870,32 +870,32 @@
 Trusted World public key needs to be extracted from the certificate. A new entry
 is created in the ``authenticated_data`` array for that purpose. In that entry,
 the corresponding parameter descriptor must be specified along with the buffer
-address to store the parameter value. In this case, the ``tz_world_pk`` descriptor
-is used to extract the public key from an x509v3 extension with OID
+address to store the parameter value. In this case, the ``trusted_world_pk``
+descriptor is used to extract the public key from an x509v3 extension with OID
 ``TRUSTED_WORLD_PK_OID``. The BL31 key certificate will use this descriptor as
 parameter in the signature authentication method. The key is stored in the
-``plat_tz_world_pk_buf`` buffer.
+``trusted_world_pk_buf`` buffer.
 
 The **BL31 Key certificate** is authenticated by checking its digital signature
 using the Trusted World public key obtained previously from the Trusted Key
 certificate. In the image descriptor, we specify a single authentication method
-by signature whose public key is the ``tz_world_pk``. Once this certificate has
-been authenticated, we have to extract the BL31 public key, stored in the
-extension specified by ``bl31_content_pk``. This key will be copied to the
-``plat_content_pk`` buffer.
+by signature whose public key is the ``trusted_world_pk``. Once this certificate
+has been authenticated, we have to extract the BL31 public key, stored in the
+extension specified by ``soc_fw_content_pk``. This key will be copied to the
+``content_pk_buf`` buffer.
 
 The **BL31 certificate** is authenticated by checking its digital signature
 using the BL31 public key obtained previously from the BL31 Key certificate.
-We specify the authentication method using ``bl31_content_pk`` as public key.
+We specify the authentication method using ``soc_fw_content_pk`` as public key.
 After authentication, we need to extract the BL31 hash, stored in the extension
-specified by ``bl31_hash``. This hash will be copied to the ``plat_bl31_hash_buf``
-buffer.
+specified by ``soc_fw_hash``. This hash will be copied to the
+``soc_fw_hash_buf`` buffer.
 
 The **BL31 image** is authenticated by calculating its hash and matching it
 with the hash obtained from the BL31 certificate. The image descriptor contains
 a single authentication method by hash. The parameters to the hash method are
-the reference hash, ``bl31_hash``, and the data to be hashed. In this case, it is
-the whole image, so we specify ``raw_data``.
+the reference hash, ``soc_fw_hash``, and the data to be hashed. In this case,
+it is the whole image, so we specify ``raw_data``.
 
 The image parser library
 ~~~~~~~~~~~~~~~~~~~~~~~~
@@ -934,7 +934,7 @@
 based on mbed TLS, which can be found in
 ``drivers/auth/mbedtls/mbedtls_crypto.c``. This library is registered in the
 authentication framework using the macro ``REGISTER_CRYPTO_LIB()`` and exports
-three functions:
+four functions:
 
 .. code:: c
 
@@ -945,6 +945,11 @@
                          void *pk_ptr, unsigned int pk_len);
     int verify_hash(void *data_ptr, unsigned int data_len,
                     void *digest_info_ptr, unsigned int digest_info_len);
+    int auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr,
+                     size_t len, const void *key, unsigned int key_len,
+                     unsigned int key_flags, const void *iv,
+                     unsigned int iv_len, const void *tag,
+                     unsigned int tag_len)
 
 The mbedTLS library algorithm support is configured by both the
 ``TF_MBEDTLS_KEY_ALG`` and ``TF_MBEDTLS_KEY_SIZE`` variables.
@@ -957,6 +962,9 @@
 -  ``TF_MBEDTLS_KEY_SIZE`` sets the supported RSA key size for TFA. Valid values
    include 1024, 2048, 3072 and 4096.
 
+-  ``TF_MBEDTLS_USE_AES_GCM`` enables the authenticated decryption support based
+   on AES-GCM algorithm. Valid values are 0 and 1.
+
 .. note::
    If code size is a concern, the build option ``MBEDTLS_SHA256_SMALLER`` can
    be defined in the platform Makefile. It will make mbed TLS use an
@@ -965,6 +973,6 @@
 
 --------------
 
-*Copyright (c) 2017-2019, Arm Limited and Contributors. All rights reserved.*
+*Copyright (c) 2017-2020, Arm Limited and Contributors. All rights reserved.*
 
 .. _TBBR-Client specification: https://developer.arm.com/docs/den0006/latest/trusted-board-boot-requirements-client-tbbr-client-armv8-a
diff --git a/docs/design/trusted-board-boot.rst b/docs/design/trusted-board-boot.rst
index 49e8adb..4802c97 100644
--- a/docs/design/trusted-board-boot.rst
+++ b/docs/design/trusted-board-boot.rst
@@ -229,6 +229,34 @@
 Instructions for building and using the tool can be found at
 :ref:`tools_build_cert_create`.
 
+Authenticated Encryption Framework
+----------------------------------
+
+The authenticated encryption framework included in TF-A provides support to
+implement the optional firmware encryption feature. This feature can be
+optionally enabled on platforms to implement the optional requirement:
+R060_TBBR_FUNCTION as specified in the `Trusted Board Boot Requirements (TBBR)`_
+document.
+
+Note that due to security considerations and complexity of this feature, it is
+marked as experimental.
+
+Firmware Encryption Tool
+------------------------
+
+The ``encrypt_fw`` tool is built and runs on the host machine as part of the
+TF-A build process when ``DECRYPTION_SUPPORT != none``. It takes the plain
+firmware image as input and generates the encrypted firmware image which can
+then be passed as input to the ``fiptool`` utility for creating the FIP.
+
+The encrypted firmwares are also stored individually in the output build
+directory.
+
+The tool resides in the ``tools/encrypt_fw`` directory. It uses OpenSSL SSL
+library version 1.0.1 or later to do authenticated encryption operation.
+Instructions for building and using the tool can be found in the
+:ref:`tools_build_enctool`.
+
 --------------
 
 *Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved.*
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index 8854a79..f138feb 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -160,6 +160,12 @@
 -  ``DEBUG``: Chooses between a debug and release build. It can take either 0
    (release) or 1 (debug) as values. 0 is the default.
 
+-  ``DECRYPTION_SUPPORT``: This build flag enables the user to select the
+   authenticated decryption algorithm to be used to decrypt firmware/s during
+   boot. It accepts 2 values: ``aes_gcm`` and ``none``. The default value of
+   this flag is ``none`` to disable firmware decryption which is an optional
+   feature as per TBBR. Also, it is an experimental feature.
+
 -  ``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.
@@ -257,6 +263,22 @@
    platform hook needs to be implemented. The value is passed as the last
    component of the option ``-fstack-protector-$ENABLE_STACK_PROTECTOR``.
 
+-  ``ENCRYPT_BL31``: Binary flag to enable encryption of BL31 firmware. This
+   flag depends on ``DECRYPTION_SUPPORT`` build flag which is marked as
+   experimental.
+
+-  ``ENCRYPT_BL32``: Binary flag to enable encryption of Secure BL32 payload.
+   This flag depends on ``DECRYPTION_SUPPORT`` build flag which is marked as
+   experimental.
+
+-  ``ENC_KEY``: A 32-byte (256-bit) symmetric key in hex string format. It could
+   either be SSK or BSSK depending on ``FW_ENC_STATUS`` flag. This value depends
+   on ``DECRYPTION_SUPPORT`` build flag which is marked as experimental.
+
+-  ``ENC_NONCE``: A 12-byte (96-bit) encryption nonce or Initialization Vector
+   (IV) in hex string format. This value depends on ``DECRYPTION_SUPPORT``
+   build flag which is marked as experimental.
+
 -  ``ERROR_DEPRECATED``: This option decides whether to treat the usage of
    deprecated platform APIs, helper functions or drivers within Trusted
    Firmware as error. It can take the value 1 (flag the use of deprecated
@@ -281,6 +303,18 @@
 -  ``FWU_FIP_NAME``: This is an optional build option which specifies the FWU
    FIP filename for the ``fwu_fip`` target. Default is ``fwu_fip.bin``.
 
+-  ``FW_ENC_STATUS``: Top level firmware's encryption numeric flag, values:
+
+   ::
+
+     0: Encryption is done with Secret Symmetric Key (SSK) which is common
+        for a class of devices.
+     1: Encryption is done with Binding Secret Symmetric Key (BSSK) which is
+        unique per device.
+
+   This flag depends on ``DECRYPTION_SUPPORT`` build flag which is marked as
+   experimental.
+
 -  ``GENERATE_COT``: Boolean flag used to build and execute the ``cert_create``
    tool to create certificates as per the Chain of Trust described in
    :ref:`Trusted Board Boot`. The build system then calls ``fiptool`` to
@@ -340,6 +374,11 @@
    translation library (xlat tables v2) must be used; version 1 of translation
    library is not supported.
 
+-  ``INVERTED_MEMMAP``: memmap tool print by default lower addresses at the
+   bottom, higher addresses at the top. This buid flag can be set to '1' to
+   invert this behavior. Lower addresses will be printed at the top and higher
+   addresses at the bottom.
+
 -  ``JUNO_AARCH32_EL3_RUNTIME``: This build flag enables you to execute EL3
    runtime software in AArch32 mode, which is required to run AArch32 on Juno.
    By default this flag is set to '0'. Enabling this flag builds BL1 and BL2 in
@@ -522,6 +561,11 @@
 -  ``SPM_MM`` : Boolean option to enable the Management Mode (MM)-based Secure
    Partition Manager (SPM) implementation. The default value is ``0``.
 
+-  ``SP_LAYOUT_FILE``: Platform provided path to JSON file containing the
+   description of secure partitions. Build system will parse this file and
+   package all secure partition blobs in FIP. This file not necessarily be
+   part of TF-A tree. Only avaialbe when ``SPD=spmd``.
+
 -  ``SP_MIN_WITH_SECURE_FIQ``: Boolean flag to indicate the SP_MIN handles
    secure interrupts (caught through the FIQ line). Platforms can enable
    this directive if they need to handle such interruption. When enabled,
diff --git a/docs/getting_started/porting-guide.rst b/docs/getting_started/porting-guide.rst
index e8357b3..d634d2e 100644
--- a/docs/getting_started/porting-guide.rst
+++ b/docs/getting_started/porting-guide.rst
@@ -872,6 +872,35 @@
 
 On success the function should return 0 and a negative error code otherwise.
 
+Function : plat_get_enc_key_info() [when FW_ENC_STATUS == 0 or 1]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+    Arguments : enum fw_enc_status_t fw_enc_status, uint8_t *key,
+                size_t *key_len, unsigned int *flags, const uint8_t *img_id,
+                size_t img_id_len
+    Return    : int
+
+This function provides a symmetric key (either SSK or BSSK depending on
+fw_enc_status) which is invoked during runtime decryption of encrypted
+firmware images. `plat/common/plat_bl_common.c` provides a dummy weak
+implementation for testing purposes which must be overridden by the platform
+trying to implement a real world firmware encryption use-case.
+
+It also allows the platform to pass symmetric key identifier rather than
+actual symmetric key which is useful in cases where the crypto backend provides
+secure storage for the symmetric key. So in this case ``ENC_KEY_IS_IDENTIFIER``
+flag must be set in ``flags``.
+
+In addition to above a platform may also choose to provide an image specific
+symmetric key/identifier using img_id.
+
+On success the function should return 0 and a negative error code otherwise.
+
+Note that this API depends on ``DECRYPTION_SUPPORT`` build flag which is
+marked as experimental.
+
 Common optional modifications
 -----------------------------
 
diff --git a/docs/getting_started/prerequisites.rst b/docs/getting_started/prerequisites.rst
index 3e0c8ff..13e25cd 100644
--- a/docs/getting_started/prerequisites.rst
+++ b/docs/getting_started/prerequisites.rst
@@ -60,7 +60,7 @@
 
 The following libraries are required for Trusted Board Boot support:
 
-- mbed TLS == 2.16.2 (tag: ``mbedtls-2.16.2``)
+- mbed TLS == 2.18.0 (tag: ``mbedtls-2.18.0``)
 
 These tools are optional:
 
diff --git a/docs/getting_started/tools-build.rst b/docs/getting_started/tools-build.rst
index bb707cb..c050f58 100644
--- a/docs/getting_started/tools-build.rst
+++ b/docs/getting_started/tools-build.rst
@@ -135,6 +135,33 @@
 
     ./tools/cert_create/cert_create -h
 
+.. _tools_build_enctool:
+
+Building the Firmware Encryption Tool
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The ``encrypt_fw`` tool is built as part of the TF-A build process when the
+``fip`` make target is specified, DECRYPTION_SUPPORT and TBB are enabled, but
+it can also be built separately with the following command:
+
+.. code:: shell
+
+    make PLAT=<platform> [DEBUG=1] [V=1] enctool
+
+``DEBUG=1`` builds the tool in debug mode. ``V=1`` makes the build process more
+verbose. The following command should be used to obtain help about the tool:
+
+.. code:: shell
+
+    ./tools/encrypt_fw/encrypt_fw -h
+
+Note that the enctool in its current implementation only supports encryption
+key to be provided in plain format. A typical implementation can very well
+extend this tool to support custom techniques to protect encryption key.
+
+Also, a user may choose to provide encryption key or nonce as an input file
+via using ``cat <filename>`` instead of a hex string.
+
 --------------
 
 *Copyright (c) 2019, Arm Limited. All rights reserved.*
diff --git a/docs/plat/arm/fvp/index.rst b/docs/plat/arm/fvp/index.rst
index 40e9661..169b6f3 100644
--- a/docs/plat/arm/fvp/index.rst
+++ b/docs/plat/arm/fvp/index.rst
@@ -26,6 +26,8 @@
 -  ``FVP_Base_Cortex-A57x2-A53x4``
 -  ``FVP_Base_Cortex-A57x4-A53x4``
 -  ``FVP_Base_Cortex-A57x4``
+-  ``FVP_Base_Cortex-A65x4`` (Version 11.9 build 41)
+-  ``FVP_Base_Cortex-A65AEx8`` (Version 11.9 build 41)
 -  ``FVP_Base_Cortex-A72x4-A53x4``
 -  ``FVP_Base_Cortex-A72x4``
 -  ``FVP_Base_Cortex-A73x4-A53x4``
@@ -628,7 +630,7 @@
 
 --------------
 
-*Copyright (c) 2019, Arm Limited. All rights reserved.*
+*Copyright (c) 2019-2020, Arm Limited. All rights reserved.*
 
 .. _TB_FW_CONFIG for FVP: ../plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
 .. _Arm's website: `FVP models`_
diff --git a/docs/plat/index.rst b/docs/plat/index.rst
index 63d29a9..a6ef188 100644
--- a/docs/plat/index.rst
+++ b/docs/plat/index.rst
@@ -9,6 +9,7 @@
 
    allwinner
    arm/index
+   meson-axg
    meson-gxbb
    meson-gxl
    meson-g12a
@@ -53,4 +54,4 @@
 
 --------------
 
-*Copyright (c) 2019, Arm Limited. All rights reserved.*
+*Copyright (c) 2019-2020, Arm Limited. All rights reserved.*
diff --git a/docs/plat/qemu.rst b/docs/plat/qemu.rst
index 88196bc..afa32c1 100644
--- a/docs/plat/qemu.rst
+++ b/docs/plat/qemu.rst
@@ -21,11 +21,13 @@
 
 -  Only cold boot is supported
 -  No build instructions for QEMU\_EFI.fd and rootfs-arm64.cpio.gz
--  No instructions for how to load a BL32 (Secure Payload)
 
 ``QEMU_EFI.fd`` can be dowloaded from
 http://snapshots.linaro.org/components/kernel/leg-virt-tianocore-edk2-upstream/latest/QEMU-KERNEL-AARCH64/RELEASE_GCC5/QEMU_EFI.fd
 
+Booting via semi-hosting option
+-------------------------------
+
 Boot binaries, except BL1, are primarily loaded via semi-hosting so all
 binaries has to reside in the same directory as QEMU is started from. This
 is conveniently achieved with symlinks the local names as:
@@ -50,3 +52,52 @@
         -append "console=ttyAMA0,38400 keep_bootcon root=/dev/vda2"   \
         -initrd rootfs-arm64.cpio.gz -smp 2 -m 1024 -bios bl1.bin   \
         -d unimp -semihosting-config enable,target=native
+
+Booting via flash based firmwares
+---------------------------------
+
+Boot firmwares are loaded via secure FLASH0 device so ``bl1.bin`` and
+``fip.bin`` should be concatenated to create a ``flash.bin`` that is flashed
+onto secure FLASH0.
+
+-  ``bl32.bin`` -> BL32 (``tee-header_v2.bin``)
+-  ``bl32_extra1.bin`` -> BL32 Extra1 (``tee-pager_v2.bin``)
+-  ``bl32_extra2.bin`` -> BL32 Extra2 (``tee-pageable_v2.bin``)
+-  ``bl33.bin`` -> BL33 (``QEMU_EFI.fd``)
+-  ``Image`` -> linux/arch/arm64/boot/Image
+
+To build:
+
+.. code:: shell
+
+    make CROSS_COMPILE=aarch64-linux-gnu- PLAT=qemu BL32=bl32.bin \
+        BL32_EXTRA1=bl32_extra1.bin BL32_EXTRA2=bl32_extra2.bin \
+        BL33=bl33.bin BL32_RAM_LOCATION=tdram SPD=opteed all fip
+
+To build with TBBR enabled, BL31 and BL32 encrypted with test key:
+
+.. code:: shell
+
+    make CROSS_COMPILE=aarch64-linux-gnu- PLAT=qemu BL32=bl32.bin \
+        BL32_EXTRA1=bl32_extra1.bin BL32_EXTRA2=bl32_extra2.bin \
+        BL33=bl33.bin BL32_RAM_LOCATION=tdram SPD=opteed all fip \
+        MBEDTLS_DIR=<path-to-mbedtls-repo> TRUSTED_BOARD_BOOT=1 \
+        GENERATE_COT=1 DECRYPTION_SUPPORT=aes_gcm FW_ENC_STATUS=0 \
+        ENCRYPT_BL31=1 ENCRYPT_BL32=1
+
+To build flash.bin:
+
+.. code:: shell
+
+    dd if=build/qemu/release/bl1.bin of=flash.bin bs=4096 conv=notrunc
+    dd if=build/qemu/release/fip.bin of=flash.bin seek=64 bs=4096 conv=notrunc
+
+To start (QEMU v2.6.0):
+
+.. code:: shell
+
+    qemu-system-aarch64 -nographic -machine virt,secure=on -cpu cortex-a57  \
+        -kernel Image -no-acpi                     \
+        -append 'console=ttyAMA0,38400 keep_bootcon root=/dev/vda2'  \
+        -initrd rootfs-arm64.cpio.gz -smp 2 -m 1024 -bios flash.bin   \
+        -d unimp
diff --git a/drivers/allwinner/sunxi_msgbox.c b/drivers/allwinner/sunxi_msgbox.c
new file mode 100644
index 0000000..cc4a6ff
--- /dev/null
+++ b/drivers/allwinner/sunxi_msgbox.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+
+#include <drivers/delay_timer.h>
+#include <lib/bakery_lock.h>
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+
+#include <sunxi_mmap.h>
+
+#define REMOTE_IRQ_EN_REG	0x0040
+#define REMOTE_IRQ_STAT_REG	0x0050
+#define LOCAL_IRQ_EN_REG	0x0060
+#define LOCAL_IRQ_STAT_REG	0x0070
+
+#define RX_IRQ(n)		BIT(0 + 2 * (n))
+#define TX_IRQ(n)		BIT(1 + 2 * (n))
+
+#define FIFO_STAT_REG(n)	(0x0100 + 0x4 * (n))
+#define FIFO_STAT_MASK		GENMASK(0, 0)
+
+#define MSG_STAT_REG(n)		(0x0140 + 0x4 * (n))
+#define MSG_STAT_MASK		GENMASK(2, 0)
+
+#define MSG_DATA_REG(n)		(0x0180 + 0x4 * (n))
+
+#define RX_CHAN			1
+#define TX_CHAN			0
+
+#define MHU_MAX_SLOT_ID		31
+
+#define MHU_TIMEOUT_DELAY	10
+#define MHU_TIMEOUT_ITERS	10000
+
+static DEFINE_BAKERY_LOCK(mhu_secure_message_lock);
+
+static bool sunxi_msgbox_last_tx_done(unsigned int chan)
+{
+	uint32_t stat = mmio_read_32(SUNXI_MSGBOX_BASE + REMOTE_IRQ_STAT_REG);
+
+	return (stat & RX_IRQ(chan)) == 0U;
+}
+
+static bool sunxi_msgbox_peek_data(unsigned int chan)
+{
+	uint32_t stat = mmio_read_32(SUNXI_MSGBOX_BASE + MSG_STAT_REG(chan));
+
+	return (stat & MSG_STAT_MASK) != 0U;
+}
+
+void mhu_secure_message_start(unsigned int slot_id __unused)
+{
+	uint32_t timeout = MHU_TIMEOUT_ITERS;
+
+	bakery_lock_get(&mhu_secure_message_lock);
+
+	/* Wait for all previous messages to be acknowledged. */
+	while (!sunxi_msgbox_last_tx_done(TX_CHAN) && --timeout)
+		udelay(MHU_TIMEOUT_DELAY);
+}
+
+void mhu_secure_message_send(unsigned int slot_id)
+{
+	mmio_write_32(SUNXI_MSGBOX_BASE + MSG_DATA_REG(TX_CHAN), BIT(slot_id));
+}
+
+uint32_t mhu_secure_message_wait(void)
+{
+	uint32_t timeout = MHU_TIMEOUT_ITERS;
+	uint32_t msg = 0;
+
+	/* Wait for a message from the SCP. */
+	while (!sunxi_msgbox_peek_data(RX_CHAN) && --timeout)
+		udelay(MHU_TIMEOUT_DELAY);
+
+	/* Return the most recent message in the FIFO. */
+	while (sunxi_msgbox_peek_data(RX_CHAN))
+		msg = mmio_read_32(SUNXI_MSGBOX_BASE + MSG_DATA_REG(RX_CHAN));
+
+	return msg;
+}
+
+void mhu_secure_message_end(unsigned int slot_id)
+{
+	/* Acknowledge a response by clearing the IRQ status. */
+	mmio_write_32(SUNXI_MSGBOX_BASE + LOCAL_IRQ_STAT_REG, RX_IRQ(RX_CHAN));
+
+	bakery_lock_release(&mhu_secure_message_lock);
+}
diff --git a/drivers/amlogic/console/aarch64/meson_console.S b/drivers/amlogic/console/aarch64/meson_console.S
index e645cba..39c2545 100644
--- a/drivers/amlogic/console/aarch64/meson_console.S
+++ b/drivers/amlogic/console/aarch64/meson_console.S
@@ -46,14 +46,14 @@
 	/* -----------------------------------------------
 	 * int console_meson_register(uintptr_t base,
 	 *     uint32_t clk, uint32_t baud,
-	 *     console_meson_t *console);
+	 *     console_t *console);
 	 * Function to initialize and register a new MESON
 	 * console. Storage passed in for the console struct
 	 * *must* be persistent (i.e. not from the stack).
 	 * In: x0 - UART register base address
 	 *     w1 - UART clock in Hz
 	 *     w2 - Baud rate
-	 *     x3 - pointer to empty console_meson_t struct
+	 *     x3 - pointer to empty console_t struct
 	 * Out: return 1 on success, 0 on error
 	 * Clobber list : x0, x1, x2, x6, x7, x14
 	 * -----------------------------------------------
@@ -62,7 +62,7 @@
 	mov	x7, x30
 	mov	x6, x3
 	cbz	x6, register_fail
-	str	x0, [x6, #CONSOLE_T_MESON_BASE]
+	str	x0, [x6, #CONSOLE_T_BASE]
 
 	bl	console_meson_init
 	cbz	x0, register_fail
@@ -128,7 +128,7 @@
 endfunc console_meson_init
 
 	/* --------------------------------------------------------
-	 * int console_meson_putc(int c, console_meson_t *console)
+	 * int console_meson_putc(int c, console_t *console)
 	 * Function to output a character over the console. It
 	 * returns the character printed on success or -1 on error.
 	 * In : w0 - character to be printed
@@ -142,7 +142,7 @@
 	cmp	x1, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	x1, [x1, #CONSOLE_T_MESON_BASE]
+	ldr	x1, [x1, #CONSOLE_T_BASE]
 	b	console_meson_core_putc
 endfunc console_meson_putc
 
@@ -179,7 +179,7 @@
 endfunc console_meson_core_putc
 
 	/* ---------------------------------------------
-	 * int console_meson_getc(console_meson_t *console)
+	 * int console_meson_getc(console_t *console)
 	 * Function to get a character from the console.
 	 * It returns the character grabbed on success
 	 * or -1 if no character is available.
@@ -193,7 +193,7 @@
 	cmp	x0, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	x0, [x0, #CONSOLE_T_MESON_BASE]
+	ldr	x0, [x0, #CONSOLE_T_BASE]
 	b	console_meson_core_getc
 endfunc console_meson_getc
 
@@ -224,7 +224,7 @@
 endfunc console_meson_core_getc
 
 	/* ---------------------------------------------
-	 * int console_meson_flush(console_meson_t *console)
+	 * int console_meson_flush(console_t *console)
 	 * Function to force a write of all buffered
 	 * data that hasn't been output.
 	 * In : x0 - pointer to console_t structure
@@ -237,7 +237,7 @@
 	cmp	x0, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	x0, [x0, #CONSOLE_T_MESON_BASE]
+	ldr	x0, [x0, #CONSOLE_T_BASE]
 	b	console_meson_core_flush
 endfunc console_meson_flush
 
diff --git a/drivers/arm/css/scp/css_pm_scmi.c b/drivers/arm/css/scp/css_pm_scmi.c
index 097d2eb..aeb7eda 100644
--- a/drivers/arm/css/scp/css_pm_scmi.c
+++ b/drivers/arm/css/scp/css_pm_scmi.c
@@ -224,8 +224,8 @@
 
 	SCMI_SET_PWR_STATE_MAX_PWR_LVL(scmi_pwr_state, lvl - 1);
 
-	core_pos = plat_core_pos_by_mpidr(mpidr);
-	assert(core_pos >= 0 && (core_pos < PLATFORM_CORE_COUNT));
+	core_pos = (unsigned int)plat_core_pos_by_mpidr(mpidr);
+	assert(core_pos < PLATFORM_CORE_COUNT);
 
 	css_scp_core_pos_to_scmi_channel(core_pos, &domain_id,
 			&channel_id);
@@ -256,8 +256,8 @@
 		return PSCI_E_INVALID_PARAMS;
 	}
 
-	cpu_idx = plat_core_pos_by_mpidr(mpidr);
-	assert(cpu_idx > -1);
+	cpu_idx = (unsigned int)plat_core_pos_by_mpidr(mpidr);
+	assert(cpu_idx < PLATFORM_CORE_COUNT);
 
 	css_scp_core_pos_to_scmi_channel(cpu_idx, &domain_id, &channel_id);
 	ret = scmi_pwr_state_get(scmi_handles[channel_id],
diff --git a/drivers/arm/css/scpi/css_scpi.c b/drivers/arm/css/scpi/css_scpi.c
index c56b7c4..416356b 100644
--- a/drivers/arm/css/scpi/css_scpi.c
+++ b/drivers/arm/css/scpi/css_scpi.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -51,7 +51,7 @@
 	mhu_secure_message_send(SCPI_MHU_SLOT_ID);
 }
 
-static void scpi_secure_message_receive(scpi_cmd_t *cmd)
+static int scpi_secure_message_receive(scpi_cmd_t *cmd)
 {
 	uint32_t mhu_status;
 
@@ -63,7 +63,7 @@
 	if (mhu_status != (1 << SCPI_MHU_SLOT_ID)) {
 		ERROR("MHU: Unexpected protocol (MHU status: 0x%x)\n",
 			mhu_status);
-		panic();
+		return -1;
 	}
 
 	/*
@@ -74,6 +74,8 @@
 	dmbld();
 
 	memcpy(cmd, (void *) SCPI_SHARED_MEM_SCP_TO_AP, sizeof(*cmd));
+
+	return 0;
 }
 
 static void scpi_secure_message_end(void)
@@ -84,14 +86,19 @@
 int scpi_wait_ready(void)
 {
 	scpi_cmd_t scpi_cmd;
+	int rc;
 
 	VERBOSE("Waiting for SCP_READY command...\n");
 
 	/* Get a message from the SCP */
 	scpi_secure_message_start();
-	scpi_secure_message_receive(&scpi_cmd);
+	rc = scpi_secure_message_receive(&scpi_cmd);
 	scpi_secure_message_end();
 
+	/* If no message was received, don't send a response */
+	if (rc != 0)
+		return rc;
+
 	/* We are expecting 'SCP Ready', produce correct error if it's not */
 	scpi_status_t status = SCP_OK;
 	if (scpi_cmd.id != SCPI_CMD_SCP_READY) {
@@ -209,7 +216,8 @@
 	 * Send message and wait for SCP's response
 	 */
 	scpi_secure_message_send(0);
-	scpi_secure_message_receive(&response);
+	if (scpi_secure_message_receive(&response) != 0)
+		goto exit;
 
 	if (response.status != SCP_OK)
 		goto exit;
@@ -254,7 +262,9 @@
 	*payload_addr = system_state & 0xff;
 	scpi_secure_message_send(sizeof(*payload_addr));
 
-	scpi_secure_message_receive(&response);
+	/* If no response is received, fill in an error status */
+	if (scpi_secure_message_receive(&response) != 0)
+		response.status = SCP_E_TIMEOUT;
 
 	scpi_secure_message_end();
 
diff --git a/drivers/arm/pl011/aarch32/pl011_console.S b/drivers/arm/pl011/aarch32/pl011_console.S
index 05c8250..93045f0 100644
--- a/drivers/arm/pl011/aarch32/pl011_console.S
+++ b/drivers/arm/pl011/aarch32/pl011_console.S
@@ -91,14 +91,14 @@
 	/* -------------------------------------------------------
 	 * int console_pl011_register(uintptr_t baseaddr,
 	 *     uint32_t clock, uint32_t baud,
-	 *     console_pl011_t *console);
+	 *     console_t *console);
 	 * Function to initialize and register a new PL011
 	 * 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_pl011_t struct
+	 *     r3 - pointer to empty console_t struct
 	 * Out: return 1 on success, 0 on error
 	 * Clobber list : r0, r1, r2
 	 * -------------------------------------------------------
@@ -108,7 +108,7 @@
 	mov	r4, r3
 	cmp	r4, #0
 	beq	register_fail
-	str	r0, [r4, #CONSOLE_T_PL011_BASE]
+	str	r0, [r4, #CONSOLE_T_BASE]
 
 	bl console_pl011_core_init
 	cmp	r0, #0
@@ -159,7 +159,7 @@
 endfunc console_pl011_core_putc
 
 	/* --------------------------------------------------------
-	 * int console_pl011_putc(int c, console_pl011_t *console)
+	 * int console_pl011_putc(int c, console_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
@@ -173,7 +173,7 @@
 	cmp	r1, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	r1, [r1, #CONSOLE_T_PL011_BASE]
+	ldr	r1, [r1, #CONSOLE_T_BASE]
 	b	console_pl011_core_putc
 endfunc console_pl011_putc
 
@@ -203,7 +203,7 @@
 endfunc console_pl011_core_getc
 
 	/* ------------------------------------------------
-	 * int console_pl011_getc(console_pl011_t *console)
+	 * int console_pl011_getc(console_t *console)
 	 * Function to get a character from the console.
 	 * It returns the character grabbed on success
 	 * or -1 if no character is available.
@@ -217,7 +217,7 @@
 	cmp	r0, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	r0, [r0, #CONSOLE_T_PL011_BASE]
+	ldr	r0, [r0, #CONSOLE_T_BASE]
 	b	console_pl011_core_getc
 endfunc console_pl011_getc
 
@@ -248,7 +248,7 @@
 endfunc console_pl011_core_flush
 
 	/* ---------------------------------------------
-	 * int console_pl011_flush(console_pl011_t *console)
+	 * int console_pl011_flush(console_t *console)
 	 * Function to force a write of all buffered
 	 * data that hasn't been output.
 	 * In : r0 - pointer to console_t structure
@@ -261,6 +261,6 @@
 	cmp	r0, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	r0, [r0, #CONSOLE_T_PL011_BASE]
+	ldr	r0, [r0, #CONSOLE_T_BASE]
 	b	console_pl011_core_flush
 endfunc console_pl011_flush
diff --git a/drivers/arm/pl011/aarch64/pl011_console.S b/drivers/arm/pl011/aarch64/pl011_console.S
index 04de99f..3a2a3cd 100644
--- a/drivers/arm/pl011/aarch64/pl011_console.S
+++ b/drivers/arm/pl011/aarch64/pl011_console.S
@@ -80,14 +80,14 @@
 	/* -----------------------------------------------
 	 * int console_pl011_register(uintptr_t baseaddr,
 	 *     uint32_t clock, uint32_t baud,
-	 *     console_pl011_t *console);
+	 *     console_t *console);
 	 * Function to initialize and register a new PL011
 	 * console. Storage passed in for the console struct
 	 * *must* be persistent (i.e. not from the stack).
 	 * In: x0 - UART register base address
 	 *     w1 - UART clock in Hz
 	 *     w2 - Baud rate
-	 *     x3 - pointer to empty console_pl011_t struct
+	 *     x3 - pointer to empty console_t struct
 	 * Out: return 1 on success, 0 on error
 	 * Clobber list : x0, x1, x2, x6, x7, x14
 	 * -----------------------------------------------
@@ -96,7 +96,7 @@
 	mov	x7, x30
 	mov	x6, x3
 	cbz	x6, register_fail
-	str	x0, [x6, #CONSOLE_T_PL011_BASE]
+	str	x0, [x6, #CONSOLE_T_BASE]
 
 	bl	console_pl011_core_init
 	cbz	x0, register_fail
@@ -143,7 +143,7 @@
 endfunc console_pl011_core_putc
 
 	/* --------------------------------------------------------
-	 * int console_pl011_putc(int c, console_pl011_t *console)
+	 * int console_pl011_putc(int c, console_t *console)
 	 * Function to output a character over the console. It
 	 * returns the character printed on success or -1 on error.
 	 * In : w0 - character to be printed
@@ -157,7 +157,7 @@
 	cmp	x1, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	x1, [x1, #CONSOLE_T_PL011_BASE]
+	ldr	x1, [x1, #CONSOLE_T_BASE]
 	b	console_pl011_core_putc
 endfunc console_pl011_putc
 
@@ -189,7 +189,7 @@
 endfunc console_pl011_core_getc
 
 	/* ---------------------------------------------
-	 * int console_pl011_getc(console_pl011_t *console)
+	 * int console_pl011_getc(console_t *console)
 	 * Function to get a character from the console.
 	 * It returns the character grabbed on success
 	 * or -1 if no character is available.
@@ -203,7 +203,7 @@
 	cmp	x0, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	x0, [x0, #CONSOLE_T_PL011_BASE]
+	ldr	x0, [x0, #CONSOLE_T_BASE]
 	b	console_pl011_core_getc
 endfunc console_pl011_getc
 
@@ -231,7 +231,7 @@
 endfunc console_pl011_core_flush
 
 	/* ---------------------------------------------
-	 * int console_pl011_flush(console_pl011_t *console)
+	 * int console_pl011_flush(console_t *console)
 	 * Function to force a write of all buffered
 	 * data that hasn't been output.
 	 * In : x0 - pointer to console_t structure
@@ -244,6 +244,6 @@
 	cmp	x0, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	x0, [x0, #CONSOLE_T_PL011_BASE]
+	ldr	x0, [x0, #CONSOLE_T_BASE]
 	b	console_pl011_core_flush
 endfunc console_pl011_flush
diff --git a/drivers/auth/crypto_mod.c b/drivers/auth/crypto_mod.c
index 110c504..c63ff08 100644
--- a/drivers/auth/crypto_mod.c
+++ b/drivers/auth/crypto_mod.c
@@ -124,3 +124,35 @@
 	return crypto_lib_desc.calc_hash(alg, data_ptr, data_len, output);
 }
 #endif	/* MEASURED_BOOT */
+
+/*
+ * Authenticated decryption of data
+ *
+ * Parameters:
+ *
+ *   dec_algo: authenticated decryption algorithm
+ *   data_ptr, len: data to be decrypted (inout param)
+ *   key, key_len, key_flags: symmetric decryption key
+ *   iv, iv_len: initialization vector
+ *   tag, tag_len: authentication tag
+ */
+int crypto_mod_auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr,
+			    size_t len, const void *key, unsigned int key_len,
+			    unsigned int key_flags, const void *iv,
+			    unsigned int iv_len, const void *tag,
+			    unsigned int tag_len)
+{
+	assert(crypto_lib_desc.auth_decrypt != NULL);
+	assert(data_ptr != NULL);
+	assert(len != 0U);
+	assert(key != NULL);
+	assert(key_len != 0U);
+	assert(iv != NULL);
+	assert((iv_len != 0U) && (iv_len <= CRYPTO_MAX_IV_SIZE));
+	assert(tag != NULL);
+	assert((tag_len != 0U) && (tag_len <= CRYPTO_MAX_TAG_SIZE));
+
+	return crypto_lib_desc.auth_decrypt(dec_algo, data_ptr, len, key,
+					    key_len, key_flags, iv, iv_len, tag,
+					    tag_len);
+}
diff --git a/drivers/auth/cryptocell/712/cryptocell_crypto.c b/drivers/auth/cryptocell/712/cryptocell_crypto.c
index 25eb6bc..c7ee36f 100644
--- a/drivers/auth/cryptocell/712/cryptocell_crypto.c
+++ b/drivers/auth/cryptocell/712/cryptocell_crypto.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -22,6 +22,7 @@
 #include <lib/utils.h>
 
 #include <mbedtls/oid.h>
+#include <mbedtls/x509.h>
 
 #define LIB_NAME		"CryptoCell 712 SBROM"
 #define RSA_SALT_LEN		32
@@ -301,5 +302,5 @@
 /*
  * Register crypto library descriptor
  */
-REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash);
+REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL);
 
diff --git a/drivers/auth/mbedtls/mbedtls_common.mk b/drivers/auth/mbedtls/mbedtls_common.mk
index 4b83015..044b368 100644
--- a/drivers/auth/mbedtls/mbedtls_common.mk
+++ b/drivers/auth/mbedtls/mbedtls_common.mk
@@ -23,13 +23,17 @@
 
 
 LIBMBEDTLS_SRCS		:= $(addprefix ${MBEDTLS_DIR}/library/,	\
+					aes.c 					\
 					asn1parse.c 				\
 					asn1write.c 				\
+					cipher.c 				\
+					cipher_wrap.c 				\
 					memory_buffer_alloc.c			\
 					oid.c 					\
 					platform.c 				\
 					platform_util.c				\
 					bignum.c				\
+					gcm.c 					\
 					md.c					\
 					md_wrap.c				\
 					pk.c 					\
@@ -87,11 +91,17 @@
     $(error "TF_MBEDTLS_KEY_ALG=${TF_MBEDTLS_KEY_ALG} not supported on mbed TLS")
 endif
 
+ifeq (${DECRYPTION_SUPPORT}, aes_gcm)
+    TF_MBEDTLS_USE_AES_GCM	:=	1
+else
+    TF_MBEDTLS_USE_AES_GCM	:=	0
+endif
+
 # Needs to be set to drive mbed TLS configuration correctly
 $(eval $(call add_define,TF_MBEDTLS_KEY_ALG_ID))
 $(eval $(call add_define,TF_MBEDTLS_KEY_SIZE))
 $(eval $(call add_define,TF_MBEDTLS_HASH_ALG_ID))
-
+$(eval $(call add_define,TF_MBEDTLS_USE_AES_GCM))
 
 $(eval $(call MAKE_LIB,mbedtls))
 
diff --git a/drivers/auth/mbedtls/mbedtls_crypto.c b/drivers/auth/mbedtls/mbedtls_crypto.c
index 04fbc64..6d6efb5 100644
--- a/drivers/auth/mbedtls/mbedtls_crypto.c
+++ b/drivers/auth/mbedtls/mbedtls_crypto.c
@@ -4,19 +4,23 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <assert.h>
 #include <stddef.h>
 #include <string.h>
 
 /* mbed TLS headers */
+#include <mbedtls/gcm.h>
 #include <mbedtls/md.h>
 #include <mbedtls/memory_buffer_alloc.h>
 #include <mbedtls/oid.h>
 #include <mbedtls/platform.h>
+#include <mbedtls/x509.h>
 
 #include <common/debug.h>
 #include <drivers/auth/crypto_mod.h>
 #include <drivers/auth/mbedtls/mbedtls_common.h>
 #include <drivers/auth/mbedtls/mbedtls_config.h>
+#include <plat/common/platform.h>
 
 #define LIB_NAME		"mbed TLS"
 
@@ -226,11 +230,121 @@
 }
 #endif /* MEASURED_BOOT */
 
+#if TF_MBEDTLS_USE_AES_GCM
+/*
+ * Stack based buffer allocation for decryption operation. It could
+ * be configured to balance stack usage vs execution speed.
+ */
+#define DEC_OP_BUF_SIZE		128
+
+static int aes_gcm_decrypt(void *data_ptr, size_t len, const void *key,
+			   unsigned int key_len, const void *iv,
+			   unsigned int iv_len, const void *tag,
+			   unsigned int tag_len)
+{
+	mbedtls_gcm_context ctx;
+	mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
+	unsigned char buf[DEC_OP_BUF_SIZE];
+	unsigned char tag_buf[CRYPTO_MAX_TAG_SIZE];
+	unsigned char *pt = data_ptr;
+	size_t dec_len;
+	int diff, i, rc;
+
+	mbedtls_gcm_init(&ctx);
+
+	rc = mbedtls_gcm_setkey(&ctx, cipher, key, key_len * 8);
+	if (rc != 0) {
+		rc = CRYPTO_ERR_DECRYPTION;
+		goto exit_gcm;
+	}
+
+	rc = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT, iv, iv_len, NULL, 0);
+	if (rc != 0) {
+		rc = CRYPTO_ERR_DECRYPTION;
+		goto exit_gcm;
+	}
+
+	while (len > 0) {
+		dec_len = MIN(sizeof(buf), len);
+
+		rc = mbedtls_gcm_update(&ctx, dec_len, pt, buf);
+		if (rc != 0) {
+			rc = CRYPTO_ERR_DECRYPTION;
+			goto exit_gcm;
+		}
+
+		memcpy(pt, buf, dec_len);
+		pt += dec_len;
+		len -= dec_len;
+	}
+
+	rc = mbedtls_gcm_finish(&ctx, tag_buf, sizeof(tag_buf));
+	if (rc != 0) {
+		rc = CRYPTO_ERR_DECRYPTION;
+		goto exit_gcm;
+	}
+
+	/* Check tag in "constant-time" */
+	for (diff = 0, i = 0; i < tag_len; i++)
+		diff |= ((const unsigned char *)tag)[i] ^ tag_buf[i];
+
+	if (diff != 0) {
+		rc = CRYPTO_ERR_DECRYPTION;
+		goto exit_gcm;
+	}
+
+	/* GCM decryption success */
+	rc = CRYPTO_SUCCESS;
+
+exit_gcm:
+	mbedtls_gcm_free(&ctx);
+	return rc;
+}
+
+/*
+ * Authenticated decryption of an image
+ */
+static int auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr,
+			size_t len, const void *key, unsigned int key_len,
+			unsigned int key_flags, const void *iv,
+			unsigned int iv_len, const void *tag,
+			unsigned int tag_len)
+{
+	int rc;
+
+	assert((key_flags & ENC_KEY_IS_IDENTIFIER) == 0);
+
+	switch (dec_algo) {
+	case CRYPTO_GCM_DECRYPT:
+		rc = aes_gcm_decrypt(data_ptr, len, key, key_len, iv, iv_len,
+				     tag, tag_len);
+		if (rc != 0)
+			return rc;
+		break;
+	default:
+		return CRYPTO_ERR_DECRYPTION;
+	}
+
+	return CRYPTO_SUCCESS;
+}
+#endif /* TF_MBEDTLS_USE_AES_GCM */
+
 /*
  * Register crypto library descriptor
  */
 #if MEASURED_BOOT
-REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash);
+#if TF_MBEDTLS_USE_AES_GCM
+REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash,
+		    auth_decrypt);
+#else
+REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash,
+		    NULL);
+#endif
+#else /* MEASURED_BOOT */
+#if TF_MBEDTLS_USE_AES_GCM
+REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash,
+		    auth_decrypt);
 #else
-REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash);
+REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL);
+#endif
 #endif /* MEASURED_BOOT */
diff --git a/drivers/cadence/uart/aarch64/cdns_console.S b/drivers/cadence/uart/aarch64/cdns_console.S
index ecd0c47..8e5d6a1 100644
--- a/drivers/cadence/uart/aarch64/cdns_console.S
+++ b/drivers/cadence/uart/aarch64/cdns_console.S
@@ -56,14 +56,14 @@
 	/* -----------------------------------------------
 	 * int console_cdns_register(uintptr_t baseaddr,
 	 *     uint32_t clock, uint32_t baud,
-	 *     console_cdns_t *console);
+	 *     console_t *console);
 	 * Function to initialize and register a new CDNS
 	 * console. Storage passed in for the console struct
 	 * *must* be persistent (i.e. not from the stack).
 	 * In: x0 - UART register base address
 	 *     w1 - UART clock in Hz
 	 *     w2 - Baud rate
-	 *     x3 - pointer to empty console_16550_t struct
+	 *     x3 - pointer to empty console_t struct
 	 * Out: return 1 on success, 0 on error
 	 * Clobber list : x0, x1, x2, x6, x7, x14
 	 * -----------------------------------------------
@@ -72,7 +72,7 @@
 	mov	x7, x30
 	mov	x6, x3
 	cbz	x6, register_fail
-	str	x0, [x6, #CONSOLE_T_CDNS_BASE]
+	str	x0, [x6, #CONSOLE_T_BASE]
 
 	bl	console_cdns_core_init
 	cbz	x0, register_fail
@@ -119,7 +119,7 @@
 endfunc console_cdns_core_putc
 
 	/* --------------------------------------------------------
-	 * int console_cdns_putc(int c, console_cdns_t *cdns)
+	 * int console_cdns_putc(int c, console_t *cdns)
 	 * Function to output a character over the console. It
 	 * returns the character printed on success or -1 on error.
 	 * In : w0 - character to be printed
@@ -133,7 +133,7 @@
 	cmp	x1, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	x1, [x1, #CONSOLE_T_CDNS_BASE]
+	ldr	x1, [x1, #CONSOLE_T_BASE]
 	b	console_cdns_core_putc
 endfunc console_cdns_putc
 
@@ -165,7 +165,7 @@
 endfunc console_cdns_core_getc
 
 	/* ---------------------------------------------
-	 * int console_cdns_getc(console_cdns_t *console)
+	 * int console_cdns_getc(console_t *console)
 	 * Function to get a character from the console.
 	 * It returns the character grabbed on success
 	 * or -1 if no character is available.
@@ -179,7 +179,7 @@
 	cmp	x0, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	x0, [x0, #CONSOLE_T_CDNS_BASE]
+	ldr	x0, [x0, #CONSOLE_T_BASE]
 	b	console_cdns_core_getc
 endfunc console_cdns_getc
 
@@ -203,7 +203,7 @@
 endfunc console_cdns_core_flush
 
 	/* ---------------------------------------------
-	 * int console_cdns_flush(console_pl011_t *console)
+	 * int console_cdns_flush(console_t *console)
 	 * Function to force a write of all buffered
 	 * data that hasn't been output.
 	 * In : x0 - pointer to console_t structure
@@ -216,6 +216,6 @@
 	cmp	x0, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	x0, [x0, #CONSOLE_T_CDNS_BASE]
+	ldr	x0, [x0, #CONSOLE_T_BASE]
 	b	console_cdns_core_flush
 endfunc console_cdns_flush
diff --git a/drivers/console/aarch32/skeleton_console.S b/drivers/console/aarch32/skeleton_console.S
index 45ad139..c594f7e 100644
--- a/drivers/console/aarch32/skeleton_console.S
+++ b/drivers/console/aarch32/skeleton_console.S
@@ -50,7 +50,7 @@
 	 * by later console callback (e.g. putc).
 	 * Example:
 	 */
-	str	r1, [r0, #CONSOLE_T_XXX_BASE]
+	str	r1, [r0, #CONSOLE_T_BASE]
 	str	r2, [r0, #CONSOLE_T_XXX_SOME_OTHER_VALUE]
 
 	/*
@@ -87,7 +87,7 @@
 	 * console_xxx_t structure pointed to by r1.
 	 * Example:
 	 */
-	ldr	r1, [r1, #CONSOLE_T_XXX_BASE]
+	ldr	r1, [r1, #CONSOLE_T_BASE]
 
 	/*
 	 * Write r0 to hardware.
@@ -125,7 +125,7 @@
 	 * console_xxx_t structure pointed to by r0.
 	 * Example:
 	 */
-	ldr	r1, [r0, #CONSOLE_T_XXX_BASE]
+	ldr	r1, [r0, #CONSOLE_T_BASE]
 
 	/*
 	 * Try to read character into r0 from hardware.
@@ -159,7 +159,7 @@
 	 * console_xxx_t structure pointed to by r0.
 	 * Example:
 	 */
-	ldr	r1, [r0, #CONSOLE_T_XXX_BASE]
+	ldr	r1, [r0, #CONSOLE_T_BASE]
 
 	/*
 	 * Flush all remaining output from hardware FIFOs. Do not return until
diff --git a/drivers/console/aarch64/skeleton_console.S b/drivers/console/aarch64/skeleton_console.S
index 957ed83..9a85867 100644
--- a/drivers/console/aarch64/skeleton_console.S
+++ b/drivers/console/aarch64/skeleton_console.S
@@ -50,7 +50,7 @@
 	 * by later console callback (e.g. putc).
 	 * Example:
 	 */
-	str	x1, [x0, #CONSOLE_T_XXX_BASE]
+	str	x1, [x0, #CONSOLE_T_BASE]
 	str	x2, [x0, #CONSOLE_T_XXX_SOME_OTHER_VALUE]
 
 	/*
@@ -87,7 +87,7 @@
 	 * console_xxx_t structure pointed to by x1.
 	 * Example:
 	 */
-	ldr	x1, [x1, #CONSOLE_T_XXX_BASE]
+	ldr	x1, [x1, #CONSOLE_T_BASE]
 
 	/*
 	 * Write w0 to hardware.
@@ -125,7 +125,7 @@
 	 * console_xxx_t structure pointed to by x0.
 	 * Example:
 	 */
-	ldr	x1, [x0, #CONSOLE_T_XXX_BASE]
+	ldr	x1, [x0, #CONSOLE_T_BASE]
 
 	/*
 	 * Try to read character into w0 from hardware.
@@ -159,7 +159,7 @@
 	 * console_xxx_t structure pointed to by x0.
 	 * Example:
 	 */
-	ldr	x1, [x0, #CONSOLE_T_XXX_BASE]
+	ldr	x1, [x0, #CONSOLE_T_BASE]
 
 	/*
 	 * Flush all remaining output from hardware FIFOs. Do not return until
diff --git a/drivers/coreboot/cbmem_console/aarch64/cbmem_console.S b/drivers/coreboot/cbmem_console/aarch64/cbmem_console.S
index fd04c2e..a4a7bf8 100644
--- a/drivers/coreboot/cbmem_console/aarch64/cbmem_console.S
+++ b/drivers/coreboot/cbmem_console/aarch64/cbmem_console.S
@@ -35,7 +35,7 @@
 	 * -----------------------------------------------
 	 */
 func console_cbmc_register
-	str	x0, [x1, #CONSOLE_T_CBMC_BASE]
+	str	x0, [x1, #CONSOLE_T_BASE]
 	ldr	w2, [x0]
 	str	w2, [x1, #CONSOLE_T_CBMC_SIZE]
 	mov	x0, x1
@@ -54,7 +54,7 @@
 	 */
 func console_cbmc_putc
 	ldr	w2, [x1, #CONSOLE_T_CBMC_SIZE]
-	ldr	x1, [x1, #CONSOLE_T_CBMC_BASE]
+	ldr	x1, [x1, #CONSOLE_T_BASE]
 	add	x1, x1, #8		/* keep address of body in x1 */
 
 	ldr	w16, [x1, #-4]		/* load cursor (one u32 before body) */
@@ -93,7 +93,7 @@
 func console_cbmc_flush
 	mov	x5, x30
 	ldr	x1, [x0, #CONSOLE_T_CBMC_SIZE]
-	ldr	x0, [x0, #CONSOLE_T_CBMC_BASE]
+	ldr	x0, [x0, #CONSOLE_T_BASE]
 	add	x1, x1, #8		/* add size of console header */
 	bl	clean_dcache_range	/* (clobbers x2 and x3) */
 	mov	x0, #0
diff --git a/drivers/imx/uart/imx_uart.h b/drivers/imx/uart/imx_uart.h
index 4f6d3de..a133024 100644
--- a/drivers/imx/uart/imx_uart.h
+++ b/drivers/imx/uart/imx_uart.h
@@ -154,15 +154,10 @@
 
 #ifndef __ASSEMBLER__
 
-typedef struct {
-	console_t console;
-	uintptr_t base;
-} console_imx_uart_t;
-
 int console_imx_uart_register(uintptr_t baseaddr,
 			      uint32_t clock,
 			      uint32_t baud,
-			      console_imx_uart_t *console);
+			      console_t *console);
 #endif /*__ASSEMBLER__*/
 
 #endif /* IMX_UART_H */
diff --git a/drivers/io/io_encrypted.c b/drivers/io/io_encrypted.c
new file mode 100644
index 0000000..744ca83
--- /dev/null
+++ b/drivers/io/io_encrypted.c
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2020, Linaro Limited. All rights reserved.
+ * Author: Sumit Garg <sumit.garg@linaro.org>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/auth/crypto_mod.h>
+#include <drivers/io/io_driver.h>
+#include <drivers/io/io_encrypted.h>
+#include <drivers/io/io_storage.h>
+#include <lib/utils.h>
+#include <plat/common/platform.h>
+#include <tools_share/firmware_encrypted.h>
+#include <tools_share/uuid.h>
+
+static uintptr_t backend_dev_handle;
+static uintptr_t backend_dev_spec;
+static uintptr_t backend_handle;
+static uintptr_t backend_image_spec;
+
+static io_dev_info_t enc_dev_info;
+
+/* Encrypted firmware driver functions */
+static int enc_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info);
+static int enc_file_open(io_dev_info_t *dev_info, const uintptr_t spec,
+			  io_entity_t *entity);
+static int enc_file_len(io_entity_t *entity, size_t *length);
+static int enc_file_read(io_entity_t *entity, uintptr_t buffer, size_t length,
+			  size_t *length_read);
+static int enc_file_close(io_entity_t *entity);
+static int enc_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params);
+static int enc_dev_close(io_dev_info_t *dev_info);
+
+static inline int is_valid_header(struct fw_enc_hdr *header)
+{
+	if (header->magic == ENC_HEADER_MAGIC)
+		return 1;
+	else
+		return 0;
+}
+
+static io_type_t device_type_enc(void)
+{
+	return IO_TYPE_ENCRYPTED;
+}
+
+static const io_dev_connector_t enc_dev_connector = {
+	.dev_open = enc_dev_open
+};
+
+static const io_dev_funcs_t enc_dev_funcs = {
+	.type = device_type_enc,
+	.open = enc_file_open,
+	.seek = NULL,
+	.size = enc_file_len,
+	.read = enc_file_read,
+	.write = NULL,
+	.close = enc_file_close,
+	.dev_init = enc_dev_init,
+	.dev_close = enc_dev_close,
+};
+
+static int enc_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info)
+{
+	assert(dev_info != NULL);
+
+	enc_dev_info.funcs = &enc_dev_funcs;
+	*dev_info = &enc_dev_info;
+
+	return 0;
+}
+
+static int enc_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params)
+{
+	int result;
+	unsigned int image_id = (unsigned int)init_params;
+
+	/* Obtain a reference to the image by querying the platform layer */
+	result = plat_get_image_source(image_id, &backend_dev_handle,
+				       &backend_dev_spec);
+	if (result != 0) {
+		WARN("Failed to obtain reference to image id=%u (%i)\n",
+			image_id, result);
+		return -ENOENT;
+	}
+
+	return result;
+}
+
+static int enc_dev_close(io_dev_info_t *dev_info)
+{
+	backend_dev_handle = (uintptr_t)NULL;
+	backend_dev_spec = (uintptr_t)NULL;
+
+	return 0;
+}
+
+static int enc_file_open(io_dev_info_t *dev_info, const uintptr_t spec,
+			 io_entity_t *entity)
+{
+	int result;
+
+	assert(spec != 0);
+	assert(entity != NULL);
+
+	backend_image_spec = spec;
+
+	result = io_open(backend_dev_handle, backend_image_spec,
+			 &backend_handle);
+	if (result != 0) {
+		WARN("Failed to open backend device (%i)\n", result);
+		result = -ENOENT;
+	}
+
+	return result;
+}
+
+static int enc_file_len(io_entity_t *entity, size_t *length)
+{
+	int result;
+
+	assert(entity != NULL);
+	assert(length != NULL);
+
+	result = io_size(backend_handle, length);
+	if (result != 0) {
+		WARN("Failed to read blob length (%i)\n", result);
+		return -ENOENT;
+	}
+
+	/*
+	 * Encryption header is attached at the beginning of the encrypted file
+	 * and is not considered a part of the payload.
+	 */
+	if (*length < sizeof(struct fw_enc_hdr))
+		return -EIO;
+
+	*length -= sizeof(struct fw_enc_hdr);
+
+	return result;
+}
+
+static int enc_file_read(io_entity_t *entity, uintptr_t buffer, size_t length,
+			 size_t *length_read)
+{
+	int result;
+	struct fw_enc_hdr header;
+	enum fw_enc_status_t fw_enc_status;
+	size_t bytes_read;
+	uint8_t key[ENC_MAX_KEY_SIZE];
+	size_t key_len = sizeof(key);
+	unsigned int key_flags = 0;
+	const io_uuid_spec_t *uuid_spec = (io_uuid_spec_t *)backend_image_spec;
+
+	assert(entity != NULL);
+	assert(length_read != NULL);
+
+	result = io_read(backend_handle, (uintptr_t)&header, sizeof(header),
+			 &bytes_read);
+	if (result != 0) {
+		WARN("Failed to read encryption header (%i)\n", result);
+		return -ENOENT;
+	}
+
+	if (!is_valid_header(&header)) {
+		WARN("Encryption header check failed.\n");
+		return -ENOENT;
+	}
+
+	VERBOSE("Encryption header looks OK.\n");
+	fw_enc_status = header.flags & FW_ENC_STATUS_FLAG_MASK;
+
+	if ((header.iv_len > ENC_MAX_IV_SIZE) ||
+	    (header.tag_len > ENC_MAX_TAG_SIZE)) {
+		WARN("Incorrect IV or tag length\n");
+		return -ENOENT;
+	}
+
+	result = io_read(backend_handle, buffer, length, &bytes_read);
+	if (result != 0) {
+		WARN("Failed to read encrypted payload (%i)\n", result);
+		return -ENOENT;
+	}
+
+	*length_read = bytes_read;
+
+	result = plat_get_enc_key_info(fw_enc_status, key, &key_len, &key_flags,
+				       (uint8_t *)&uuid_spec->uuid,
+				       sizeof(uuid_t));
+	if (result != 0) {
+		WARN("Failed to obtain encryption key (%i)\n", result);
+		return -ENOENT;
+	}
+
+	result = crypto_mod_auth_decrypt(header.dec_algo,
+					 (void *)buffer, *length_read, key,
+					 key_len, key_flags, header.iv,
+					 header.iv_len, header.tag,
+					 header.tag_len);
+	memset(key, 0, key_len);
+
+	if (result != 0) {
+		ERROR("File decryption failed (%i)\n", result);
+		return -ENOENT;
+	}
+
+	return result;
+}
+
+static int enc_file_close(io_entity_t *entity)
+{
+	io_close(backend_handle);
+
+	backend_image_spec = (uintptr_t)NULL;
+	entity->info = 0;
+
+	return 0;
+}
+
+/* Exported functions */
+
+/* Register the Encrypted Firmware driver with the IO abstraction */
+int register_io_dev_enc(const io_dev_connector_t **dev_con)
+{
+	int result;
+
+	assert(dev_con != NULL);
+
+	result = io_register_device(&enc_dev_info);
+	if (result == 0)
+		*dev_con = &enc_dev_connector;
+
+	return result;
+}
diff --git a/drivers/marvell/uart/a3700_console.S b/drivers/marvell/uart/a3700_console.S
index da1ce35..ecd494c 100644
--- a/drivers/marvell/uart/a3700_console.S
+++ b/drivers/marvell/uart/a3700_console.S
@@ -110,7 +110,7 @@
 	.globl console_a3700_register
 
 	/* -----------------------------------------------
-	 * int console_a3700_register(console_16550_t *console,
+	 * int console_a3700_register(console_t *console,
 		uintptr_t base, uint32_t clk, uint32_t baud)
 	 * Function to initialize and register a new a3700
 	 * console. Storage passed in for the console struct
@@ -118,7 +118,7 @@
 	 * In: x0 - UART register base address
 	 *     w1 - UART clock in Hz
 	 *     w2 - Baud rate
-	 *     x3 - pointer to empty console_a3700_t struct
+	 *     x3 - pointer to empty console_t struct
 	 * Out: return 1 on success, 0 on error
 	 * Clobber list : x0, x1, x2, x6, x7, x14
 	 * -----------------------------------------------
@@ -127,7 +127,7 @@
 	mov	x7, x30
 	mov	x6, x3
 	cbz	x6, register_fail
-	str	x0, [x6, #CONSOLE_T_A3700_BASE]
+	str	x0, [x6, #CONSOLE_T_BASE]
 
 	bl	console_a3700_core_init
 	cbz	x0, register_fail
@@ -178,7 +178,7 @@
 endfunc console_a3700_core_putc
 
 	/* --------------------------------------------------------
-	 * int console_a3700_putc(int c, console_a3700_t *console)
+	 * int console_a3700_putc(int c, console_t *console)
 	 * Function to output a character over the console. It
 	 * returns the character printed on success or -1 on error.
 	 * In : w0 - character to be printed
@@ -188,7 +188,7 @@
 	 * --------------------------------------------------------
 	 */
 func console_a3700_putc
-	ldr	x1, [x1, #CONSOLE_T_A3700_BASE]
+	ldr	x1, [x1, #CONSOLE_T_BASE]
 	b	console_a3700_core_putc
 endfunc console_a3700_putc
 
@@ -208,7 +208,7 @@
 endfunc console_a3700_core_getc
 
 	/* ---------------------------------------------
-	 * int console_a3700_getc(console_a3700_t *console)
+	 * int console_a3700_getc(console_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.
@@ -218,7 +218,7 @@
 	 * ---------------------------------------------
 	 */
 func console_a3700_getc
-	ldr	x0, [x0, #CONSOLE_T_A3700_BASE]
+	ldr	x0, [x0, #CONSOLE_T_BASE]
 	b	console_a3700_core_getc
 endfunc console_a3700_getc
 
@@ -237,7 +237,7 @@
 endfunc console_a3700_core_flush
 
 	/* ---------------------------------------------
-	 * int console_a3700_flush(console_a3700_t *console)
+	 * int console_a3700_flush(console_t *console)
 	 * Function to force a write of all buffered
 	 * data that hasn't been output.
 	 * In : x0 - pointer to console_t structure
@@ -246,7 +246,7 @@
 	 * ---------------------------------------------
 	 */
 func console_a3700_flush
-	ldr	x0, [x0, #CONSOLE_T_A3700_BASE]
+	ldr	x0, [x0, #CONSOLE_T_BASE]
 	b	console_a3700_core_flush
 endfunc console_a3700_flush
 
diff --git a/drivers/renesas/rcar/console/rcar_console.S b/drivers/renesas/rcar/console/rcar_console.S
index 859efec..4d006b7 100644
--- a/drivers/renesas/rcar/console/rcar_console.S
+++ b/drivers/renesas/rcar/console/rcar_console.S
@@ -20,14 +20,14 @@
 	/* -----------------------------------------------
 	 * int console_rcar_register(
 	 *      uintptr_t base, uint32_t clk, uint32_t baud,
-	 *      console_rcar_t *console)
+	 *      console_t *console)
 	 * Function to initialize and register a new rcar
 	 * console. Storage passed in for the console struct
 	 * *must* be persistent (i.e. not from the stack).
 	 * In: x0 - UART register base address
 	 *     w1 - UART clock in Hz
 	 *     w2 - Baud rate
-	 *     x3 - pointer to empty console_rcar_t struct
+	 *     x3 - pointer to empty console_t struct
 	 * Out: return 1 on success, 0 on error
 	 * Clobber list : x0, x1, x2, x6, x7, x14
 	 * -----------------------------------------------
@@ -36,7 +36,7 @@
 	mov	x7, x30
 	mov	x6, x3
 	cbz	x6, register_fail
-	str	x0, [x6, #CONSOLE_T_RCAR_BASE]
+	str	x0, [x6, #CONSOLE_T_BASE]
 
 	bl	rcar_log_init
 	cbz	x0, register_fail
@@ -68,11 +68,11 @@
 endfunc console_rcar_init
 
 	/* --------------------------------------------------------
-	 * int console_rcar_putc(int c, console_rcar_t *console)
+	 * int console_rcar_putc(int c, console_t *console)
 	 * Function to output a character over the console. It
 	 * returns the character printed on success or -1 on error.
 	 * In : w0 - character to be printed
-	 *      x1 - pointer to console_rcar_t structure
+	 *      x1 - pointer to console_t structure
 	 * Out : return -1 on error else return character.
 	 * Clobber list : x2
 	 * --------------------------------------------------------
diff --git a/drivers/renesas/rcar/scif/scif.S b/drivers/renesas/rcar/scif/scif.S
index 8309bb2..064aba4 100644
--- a/drivers/renesas/rcar/scif/scif.S
+++ b/drivers/renesas/rcar/scif/scif.S
@@ -126,14 +126,14 @@
 	/* -----------------------------------------------
 	 * int console_rcar_register(
 	 *      uintptr_t base, uint32_t clk, uint32_t baud,
-	 *      console_rcar_t *console)
+	 *      console_t *console)
 	 * Function to initialize and register a new rcar
 	 * console. Storage passed in for the console struct
 	 * *must* be persistent (i.e. not from the stack).
 	 * In: x0 - UART register base address
 	 *     w1 - UART clock in Hz
 	 *     w2 - Baud rate
-	 *     x3 - pointer to empty console_rcar_t struct
+	 *     x3 - pointer to empty console_t struct
 	 * Out: return 1 on success, 0 on error
 	 * Clobber list : x0, x1, x2, x6, x7, x14
 	 * -----------------------------------------------
@@ -142,7 +142,7 @@
 	mov	x7, x30
 	mov	x6, x3
 	cbz	x6, register_fail
-	str	x0, [x6, #CONSOLE_T_RCAR_BASE]
+	str	x0, [x6, #CONSOLE_T_BASE]
 
 	bl	console_rcar_init
 
diff --git a/drivers/st/uart/aarch32/stm32_console.S b/drivers/st/uart/aarch32/stm32_console.S
index ca3c1f6..0ed37d1 100644
--- a/drivers/st/uart/aarch32/stm32_console.S
+++ b/drivers/st/uart/aarch32/stm32_console.S
@@ -91,14 +91,14 @@
 	/* -------------------------------------------------------
 	 * int console_stm32_register(uintptr_t baseaddr,
 	 *     uint32_t clock, uint32_t baud,
-	 *     struct console_stm32 *console);
+	 *     console_t *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
+	 *     r3 - pointer to empty console_t struct
 	 * Out: return 1 on success, 0 on error
 	 * Clobber list : r0, r1, r2
 	 * -------------------------------------------------------
@@ -108,7 +108,7 @@
 	mov	r4, r3
 	cmp	r4, #0
 	beq	register_fail
-	str	r0, [r4, #CONSOLE_T_STM32_BASE]
+	str	r0, [r4, #CONSOLE_T_BASE]
 
 	bl console_stm32_core_init
 	cmp	r0, #0
@@ -157,7 +157,7 @@
 endfunc console_stm32_core_putc
 
 	/* ------------------------------------------------------------
-	 * int console_stm32_putc(int c, struct console_stm32 *console)
+	 * int console_stm32_putc(int c, console_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
@@ -171,7 +171,7 @@
 	cmp	r1, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	r1, [r1, #CONSOLE_T_STM32_BASE]
+	ldr	r1, [r1, #CONSOLE_T_BASE]
 	b	console_stm32_core_putc
 endfunc console_stm32_putc
 
@@ -219,7 +219,7 @@
 endfunc console_stm32_core_flush
 
 	/* ------------------------------------------------------
-	 * int console_stm32_flush(struct console_stm32 *console)
+	 * int console_stm32_flush(console_t *console)
 	 * Function to force a write of all buffered
 	 * data that hasn't been output.
 	 * In : r0 - pointer to console_t structure
@@ -232,6 +232,6 @@
 	cmp	r0, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	r0, [r0, #CONSOLE_T_STM32_BASE]
+	ldr	r0, [r0, #CONSOLE_T_BASE]
 	b	console_stm32_core_flush
 endfunc console_stm32_flush
diff --git a/drivers/ti/uart/aarch32/16550_console.S b/drivers/ti/uart/aarch32/16550_console.S
index 5cd9b30..bc0b3ab 100644
--- a/drivers/ti/uart/aarch32/16550_console.S
+++ b/drivers/ti/uart/aarch32/16550_console.S
@@ -91,7 +91,7 @@
 	/* -------------------------------------------------------
 	 * int console_16550_register(uintptr_t baseaddr,
 	 *     uint32_t clock, uint32_t baud,
-	 *     console_16550_t *console);
+	 *     console_t *console);
 	 * Function to initialize and register a new 16550
 	 * console. Storage passed in for the console struct
 	 * *must* be persistent (i.e. not from the stack).
@@ -101,7 +101,7 @@
 	 * In: r0 - UART register base address
 	 *     r1 - UART clock in Hz
 	 *     r2 - Baud rate (ignored if r1 is 0)
-	 *     r3 - pointer to empty console_16550_t struct
+	 *     r3 - pointer to empty console_t struct
 	 * Out: return 1 on success, 0 on error
 	 * Clobber list : r0, r1, r2
 	 * -------------------------------------------------------
@@ -111,7 +111,7 @@
 	mov	r4, r3
 	cmp	r4, #0
 	beq	register_fail
-	str	r0, [r4, #CONSOLE_T_16550_BASE]
+	str	r0, [r4, #CONSOLE_T_BASE]
 
 	/* A clock rate of zero means to skip the initialisation. */
 	cmp	r1, #0
@@ -167,7 +167,7 @@
 endfunc console_16550_core_putc
 
 	/* --------------------------------------------------------
-	 * int console_16550_putc(int c, console_16550_t *console)
+	 * int console_16550_putc(int c, console_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
@@ -181,7 +181,7 @@
 	cmp	r1, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	r1, [r1, #CONSOLE_T_16550_BASE]
+	ldr	r1, [r1, #CONSOLE_T_BASE]
 	b	console_16550_core_putc
 endfunc console_16550_putc
 
@@ -213,7 +213,7 @@
 endfunc console_16550_core_getc
 
 	/* ---------------------------------------------
-	 * int console_16550_getc(console_16550_t *console)
+	 * int console_16550_getc(console_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.
@@ -227,7 +227,7 @@
 	cmp	r0, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	r0, [r0, #CONSOLE_T_16550_BASE]
+	ldr	r0, [r0, #CONSOLE_T_BASE]
 	b	console_16550_core_getc
 endfunc console_16550_getc
 
@@ -257,7 +257,7 @@
 endfunc console_16550_core_flush
 
 	/* ---------------------------------------------
-	 * int console_16550_flush(console_pl011_t *console)
+	 * int console_16550_flush(console_t *console)
 	 * Function to force a write of all buffered
 	 * data that hasn't been output.
 	 * In : r0 - pointer to console_t structure
@@ -270,6 +270,6 @@
 	cmp	r0, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	r0, [r0, #CONSOLE_T_16550_BASE]
+	ldr	r0, [r0, #CONSOLE_T_BASE]
 	b	console_16550_core_flush
 endfunc console_16550_flush
diff --git a/drivers/ti/uart/aarch64/16550_console.S b/drivers/ti/uart/aarch64/16550_console.S
index 80c1b86..0640227 100644
--- a/drivers/ti/uart/aarch64/16550_console.S
+++ b/drivers/ti/uart/aarch64/16550_console.S
@@ -88,7 +88,7 @@
 	/* -----------------------------------------------
 	 * int console_16550_register(uintptr_t baseaddr,
 	 *     uint32_t clock, uint32_t baud,
-	 *     console_16550_t *console);
+	 *     console_t *console);
 	 * Function to initialize and register a new 16550
 	 * console. Storage passed in for the console struct
 	 * *must* be persistent (i.e. not from the stack).
@@ -98,7 +98,7 @@
 	 * In: x0 - UART register base address
 	 *     w1 - UART clock in Hz
 	 *     w2 - Baud rate (ignored if w1 is 0)
-	 *     x3 - pointer to empty console_16550_t struct
+	 *     x3 - pointer to empty console_t struct
 	 * Out: return 1 on success, 0 on error
 	 * Clobber list : x0, x1, x2, x6, x7, x14
 	 * -----------------------------------------------
@@ -107,7 +107,7 @@
 	mov	x7, x30
 	mov	x6, x3
 	cbz	x6, register_fail
-	str	x0, [x6, #CONSOLE_T_16550_BASE]
+	str	x0, [x6, #CONSOLE_T_BASE]
 
 	/* A clock rate of zero means to skip the initialisation. */
 	cbz	w1, register_16550
@@ -161,7 +161,7 @@
 endfunc console_16550_core_putc
 
 	/* --------------------------------------------------------
-	 * int console_16550_putc(int c, console_16550_t *console)
+	 * int console_16550_putc(int c, console_t *console)
 	 * Function to output a character over the console. It
 	 * returns the character printed on success or -1 on error.
 	 * In : w0 - character to be printed
@@ -175,7 +175,7 @@
 	cmp	x1, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	x1, [x1, #CONSOLE_T_16550_BASE]
+	ldr	x1, [x1, #CONSOLE_T_BASE]
 	b	console_16550_core_putc
 endfunc console_16550_putc
 
@@ -206,7 +206,7 @@
 endfunc console_16550_core_getc
 
 	/* ---------------------------------------------
-	 * int console_16550_getc(console_16550_t *console)
+	 * int console_16550_getc(console_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.
@@ -220,7 +220,7 @@
 	cmp	x1, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	x0, [x0, #CONSOLE_T_16550_BASE]
+	ldr	x0, [x0, #CONSOLE_T_BASE]
 	b	console_16550_core_getc
 endfunc console_16550_getc
 
@@ -250,7 +250,7 @@
 endfunc console_16550_core_flush
 
 	/* ---------------------------------------------
-	 * int console_16550_flush(console_pl011_t *console)
+	 * int console_16550_flush(console_t *console)
 	 * Function to force a write of all buffered
 	 * data that hasn't been output.
 	 * In : x0 - pointer to console_t structure
@@ -263,6 +263,6 @@
 	cmp	x0, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	x0, [x0, #CONSOLE_T_16550_BASE]
+	ldr	x0, [x0, #CONSOLE_T_BASE]
 	b	console_16550_core_flush
 endfunc console_16550_flush
diff --git a/fdts/a5ds.dts b/fdts/a5ds.dts
index 31d635a..7334c45 100644
--- a/fdts/a5ds.dts
+++ b/fdts/a5ds.dts
@@ -136,4 +136,23 @@
 			reg = <0x1a050000 0x1000>;
 		};
 	};
+	v2m_fixed_3v3: fixed-regulator-0 {
+		compatible = "regulator-fixed";
+		regulator-name = "3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+	};
+
+	ethernet@4020000 {
+		compatible = "smsc,lan9220", "smsc,lan9115";
+		reg = <0x40200000 0x10000>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 43 0xf04>;
+		reg-io-width = <4>;
+		phy-mode = "mii";
+		smsc,irq-active-high;
+		vdd33a-supply = <&v2m_fixed_3v3>;
+		vddvario-supply = <&v2m_fixed_3v3>;
+       };
 };
diff --git a/fdts/fvp-base-gicv3-psci-dynamiq-2t.dts b/fdts/fvp-base-gicv3-psci-dynamiq-2t.dts
index daa2e66..6e63b43 100644
--- a/fdts/fvp-base-gicv3-psci-dynamiq-2t.dts
+++ b/fdts/fvp-base-gicv3-psci-dynamiq-2t.dts
@@ -8,34 +8,181 @@
 
 #include "fvp-base-gicv3-psci-dynamiq-common.dtsi"
 
-&CPU0 {
-	reg = <0x0 0x0>;
-};
+&CPU_MAP {
+	/delete-node/ cluster0;
 
-&CPU1 {
-	reg = <0x0 0x1>;
+	cluster0 {
+		core0 {
+			thread0 {
+				cpu = <&CPU0>;
+			};
+			thread1 {
+				cpu = <&CPU1>;
+			};
+		};
+		core1 {
+			thread0 {
+				cpu = <&CPU2>;
+			};
+			thread1 {
+				cpu = <&CPU3>;
+			};
+		};
+		core2 {
+			thread0 {
+				cpu = <&CPU4>;
+			};
+			thread1 {
+				cpu = <&CPU5>;
+			};
+		};
+		core3 {
+			thread0 {
+				cpu = <&CPU6>;
+			};
+			thread1 {
+				cpu = <&CPU7>;
+			};
+		};
+		core4 {
+			thread0 {
+				cpu = <&CPU8>;
+			};
+			thread1 {
+				cpu = <&CPU9>;
+			};
+		};
+		core5 {
+			thread0 {
+				cpu = <&CPU10>;
+			};
+			thread1 {
+				cpu = <&CPU11>;
+			};
+		};
+		core6 {
+			thread0 {
+				cpu = <&CPU12>;
+			};
+			thread1 {
+				cpu = <&CPU13>;
+			};
+		};
+		core7 {
+			thread0 {
+				cpu = <&CPU14>;
+			};
+			thread1 {
+				cpu = <&CPU15>;
+			};
+		};
+	};
 };
 
-&CPU2 {
-	reg = <0x0 0x100>;
-};
+/ {
+	cpus {
+		CPU0:cpu@0 {
+			reg = <0x0 0x0>;
+		};
 
-&CPU3 {
-	reg = <0x0 0x101>;
-};
+		CPU1:cpu@1 {
+			reg = <0x0 0x1>;
+		};
 
-&CPU4 {
-	reg = <0x0 0x200>;
-};
+		CPU2:cpu@2 {
+			reg = <0x0 0x100>;
+		};
 
-&CPU5 {
-	reg = <0x0 0x201>;
-};
+		CPU3:cpu@3 {
+			reg = <0x0 0x101>;
+		};
 
-&CPU6 {
-	reg = <0x0 0x300>;
-};
+		CPU4:cpu@100 {
+			reg = <0x0 0x200>;
+		};
+
+		CPU5:cpu@101 {
+			reg = <0x0 0x201>;
+		};
+
+		CPU6:cpu@102 {
+			reg = <0x0 0x300>;
+		};
+
+		CPU7:cpu@103 {
+			reg = <0x0 0x301>;
+		};
+
+		CPU8:cpu@200 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0x0 0x400>;
+			enable-method = "psci";
+			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+			next-level-cache = <&L2_0>;
+		};
+
+		CPU9:cpu@201 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0x0 0x401>;
+			enable-method = "psci";
+			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+			next-level-cache = <&L2_0>;
+		};
+
+		CPU10:cpu@202 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0x0 0x500>;
+			enable-method = "psci";
+			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+			next-level-cache = <&L2_0>;
+		};
+
+		CPU11:cpu@203 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0x0 0x501>;
+			enable-method = "psci";
+			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+			next-level-cache = <&L2_0>;
+		};
+
+		CPU12:cpu@300 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0x0 0x600>;
+			enable-method = "psci";
+			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+			next-level-cache = <&L2_0>;
+		};
+
+		CPU13:cpu@301 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0x0 0x601>;
+			enable-method = "psci";
+			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+			next-level-cache = <&L2_0>;
+		};
+
+		CPU14:cpu@302 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0x0 0x700>;
+			enable-method = "psci";
+			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+			next-level-cache = <&L2_0>;
+		};
 
-&CPU7 {
-	reg = <0x0 0x301>;
+		CPU15:cpu@303 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0x0 0x701>;
+			enable-method = "psci";
+			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+			next-level-cache = <&L2_0>;
+		};
+	};
 };
diff --git a/include/arch/aarch32/asm_macros.S b/include/arch/aarch32/asm_macros.S
index 8cfa212..ea1636e 100644
--- a/include/arch/aarch32/asm_macros.S
+++ b/include/arch/aarch32/asm_macros.S
@@ -95,11 +95,24 @@
 
 #if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION)
 	/*
+	 * Macro for mitigating against speculative execution.
 	 * ARMv7 cores without Virtualization extension do not support the
 	 * eret instruction.
 	 */
-	.macro eret
+	.macro exception_return
 	movs	pc, lr
+	dsb	nsh
+	isb
+	.endm
+
+#else
+	/*
+	 * Macro for mitigating against speculative execution beyond ERET.
+	 */
+	.macro exception_return
+	eret
+	dsb	nsh
+	isb
 	.endm
 #endif
 
diff --git a/include/arch/aarch32/smccc_macros.S b/include/arch/aarch32/smccc_macros.S
index 4ec2292..ea7835a 100644
--- a/include/arch/aarch32/smccc_macros.S
+++ b/include/arch/aarch32/smccc_macros.S
@@ -235,7 +235,7 @@
 
 	/* Restore the rest of the general purpose registers */
 	ldm	r0, {r0-r12}
-	eret
+	exception_return
 	.endm
 
 #endif /* SMCCC_MACROS_S */
diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h
index 1faddbe..b0c2650 100644
--- a/include/arch/aarch64/arch.h
+++ b/include/arch/aarch64/arch.h
@@ -97,6 +97,32 @@
 #define ICC_SGI0R_EL1		S3_0_c12_c11_7
 
 /*******************************************************************************
+ * Definitions for EL2 system registers for save/restore routine
+ ******************************************************************************/
+
+#define CNTPOFF_EL2		S3_4_C14_C0_6
+#define HAFGRTR_EL2		S3_4_C3_C1_6
+#define HDFGRTR_EL2		S3_4_C3_C1_4
+#define HDFGWTR_EL2		S3_4_C3_C1_5
+#define HFGITR_EL2		S3_4_C1_C1_6
+#define HFGRTR_EL2		S3_4_C1_C1_4
+#define HFGWTR_EL2		S3_4_C1_C1_5
+#define ICH_HCR_EL2		S3_4_C12_C11_0
+#define ICH_VMCR_EL2		S3_4_C12_C11_7
+#define MPAMVPM0_EL2		S3_4_C10_C5_0
+#define MPAMVPM1_EL2		S3_4_C10_C5_1
+#define MPAMVPM2_EL2		S3_4_C10_C5_2
+#define MPAMVPM3_EL2		S3_4_C10_C5_3
+#define MPAMVPM4_EL2		S3_4_C10_C5_4
+#define MPAMVPM5_EL2		S3_4_C10_C5_5
+#define MPAMVPM6_EL2		S3_4_C10_C5_6
+#define MPAMVPM7_EL2		S3_4_C10_C5_7
+#define MPAMVPMV_EL2		S3_4_C10_C4_1
+#define TRFCR_EL2		S3_4_C1_C2_1
+#define PMSCR_EL2		S3_4_C9_C9_0
+#define TFSR_EL2		S3_4_C5_C6_0
+
+/*******************************************************************************
  * Generic timer memory mapped registers & offsets
  ******************************************************************************/
 #define CNTCR_OFF			U(0x000)
diff --git a/include/drivers/amlogic/meson_console.h b/include/drivers/amlogic/meson_console.h
index 70e3b0b..8d52d79 100644
--- a/include/drivers/amlogic/meson_console.h
+++ b/include/drivers/amlogic/meson_console.h
@@ -9,17 +9,10 @@
 
 #include <drivers/console.h>
 
-#define CONSOLE_T_MESON_BASE	CONSOLE_T_DRVDATA
-
 #ifndef __ASSEMBLER__
 
 #include <stdint.h>
 
-typedef struct {
-	console_t console;
-	uintptr_t base;
-} console_meson_t;
-
 /*
  * Initialize a new meson console instance and register it with the console
  * framework. The |console| pointer must point to storage that will be valid
@@ -30,7 +23,7 @@
  * order to make this function future-proof.
  */
 int console_meson_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud,
-			   console_meson_t *console);
+			   console_t *console);
 
 #endif /*__ASSEMBLER__*/
 
diff --git a/include/drivers/arm/pl011.h b/include/drivers/arm/pl011.h
index 8733d19..ebc6643 100644
--- a/include/drivers/arm/pl011.h
+++ b/include/drivers/arm/pl011.h
@@ -81,17 +81,10 @@
 
 #endif /* !PL011_GENERIC_UART */
 
-#define CONSOLE_T_PL011_BASE	CONSOLE_T_DRVDATA
-
 #ifndef __ASSEMBLER__
 
 #include <stdint.h>
 
-typedef struct {
-	console_t console;
-	uintptr_t base;
-} console_pl011_t;
-
 /*
  * Initialize a new PL011 console instance and register it with the console
  * framework. The |console| pointer must point to storage that will be valid
@@ -99,7 +92,7 @@
  * Its contents will be reinitialized from scratch.
  */
 int console_pl011_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud,
-			   console_pl011_t *console);
+			   console_t *console);
 
 #endif /*__ASSEMBLER__*/
 
diff --git a/include/drivers/auth/crypto_mod.h b/include/drivers/auth/crypto_mod.h
index f211035..71cf673 100644
--- a/include/drivers/auth/crypto_mod.h
+++ b/include/drivers/auth/crypto_mod.h
@@ -13,9 +13,18 @@
 	CRYPTO_ERR_INIT,
 	CRYPTO_ERR_HASH,
 	CRYPTO_ERR_SIGNATURE,
+	CRYPTO_ERR_DECRYPTION,
 	CRYPTO_ERR_UNKNOWN
 };
 
+#define CRYPTO_MAX_IV_SIZE		16U
+#define CRYPTO_MAX_TAG_SIZE		16U
+
+/* Decryption algorithm */
+enum crypto_dec_algo {
+	CRYPTO_GCM_DECRYPT = 0
+};
+
 /*
  * Cryptographic library descriptor
  */
@@ -44,6 +53,15 @@
 			 unsigned int data_len, unsigned char *output);
 #endif /* MEASURED_BOOT */
 
+	/*
+	 * Authenticated decryption. Return one of the
+	 * 'enum crypto_ret_value' options.
+	 */
+	int (*auth_decrypt)(enum crypto_dec_algo dec_algo, void *data_ptr,
+			    size_t len, const void *key, unsigned int key_len,
+			    unsigned int key_flags, const void *iv,
+			    unsigned int iv_len, const void *tag,
+			    unsigned int tag_len);
 } crypto_lib_desc_t;
 
 /* Public functions */
@@ -54,6 +72,11 @@
 				void *pk_ptr, unsigned int pk_len);
 int crypto_mod_verify_hash(void *data_ptr, unsigned int data_len,
 			   void *digest_info_ptr, unsigned int digest_info_len);
+int crypto_mod_auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr,
+			    size_t len, const void *key, unsigned int key_len,
+			    unsigned int key_flags, const void *iv,
+			    unsigned int iv_len, const void *tag,
+			    unsigned int tag_len);
 
 #if MEASURED_BOOT
 int crypto_mod_calc_hash(unsigned int alg, void *data_ptr,
@@ -61,21 +84,24 @@
 
 /* Macro to register a cryptographic library */
 #define REGISTER_CRYPTO_LIB(_name, _init, _verify_signature, _verify_hash, \
-							     _calc_hash) \
+			    _calc_hash, _auth_decrypt) \
 	const crypto_lib_desc_t crypto_lib_desc = { \
 		.name = _name, \
 		.init = _init, \
 		.verify_signature = _verify_signature, \
 		.verify_hash = _verify_hash, \
-		.calc_hash = _calc_hash \
+		.calc_hash = _calc_hash, \
+		.auth_decrypt = _auth_decrypt \
 	}
 #else
-#define REGISTER_CRYPTO_LIB(_name, _init, _verify_signature, _verify_hash) \
+#define REGISTER_CRYPTO_LIB(_name, _init, _verify_signature, _verify_hash, \
+			    _auth_decrypt) \
 	const crypto_lib_desc_t crypto_lib_desc = { \
 		.name = _name, \
 		.init = _init, \
 		.verify_signature = _verify_signature, \
-		.verify_hash = _verify_hash \
+		.verify_hash = _verify_hash, \
+		.auth_decrypt = _auth_decrypt \
 	}
 #endif	/* MEASURED_BOOT */
 
diff --git a/include/drivers/auth/mbedtls/mbedtls_config.h b/include/drivers/auth/mbedtls/mbedtls_config.h
index 6e179bb..dc00da7 100644
--- a/include/drivers/auth/mbedtls/mbedtls_config.h
+++ b/include/drivers/auth/mbedtls/mbedtls_config.h
@@ -79,6 +79,12 @@
 #define MBEDTLS_X509_USE_C
 #define MBEDTLS_X509_CRT_PARSE_C
 
+#if TF_MBEDTLS_USE_AES_GCM
+#define MBEDTLS_AES_C
+#define MBEDTLS_CIPHER_C
+#define MBEDTLS_GCM_C
+#endif
+
 /* MPI / BIGNUM options */
 #define MBEDTLS_MPI_WINDOW_SIZE			2
 
diff --git a/include/drivers/cadence/cdns_uart.h b/include/drivers/cadence/cdns_uart.h
index 64a062c..46ba466 100644
--- a/include/drivers/cadence/cdns_uart.h
+++ b/include/drivers/cadence/cdns_uart.h
@@ -25,17 +25,10 @@
 #define R_UART_TX	0x30
 #define R_UART_RX	0x30
 
-#define CONSOLE_T_CDNS_BASE	CONSOLE_T_DRVDATA
-
 #ifndef __ASSEMBLER__
 
 #include <stdint.h>
 
-typedef struct {
-	console_t console;
-	uintptr_t base;
-} console_cdns_t;
-
 /*
  * Initialize a new Cadence console instance and register it with the console
  * framework. The |console| pointer must point to storage that will be valid
@@ -43,7 +36,7 @@
  * Its contents will be reinitialized from scratch.
  */
 int console_cdns_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud,
-			  console_cdns_t *console);
+			  console_t *console);
 
 #endif /*__ASSEMBLER__*/
 
diff --git a/include/drivers/console.h b/include/drivers/console.h
index a4859d8..761816a 100644
--- a/include/drivers/console.h
+++ b/include/drivers/console.h
@@ -14,7 +14,8 @@
 #define CONSOLE_T_PUTC			(U(2) * REGSZ)
 #define CONSOLE_T_GETC			(U(3) * REGSZ)
 #define CONSOLE_T_FLUSH			(U(4) * REGSZ)
-#define CONSOLE_T_DRVDATA		(U(5) * REGSZ)
+#define CONSOLE_T_BASE			(U(5) * REGSZ)
+#define CONSOLE_T_DRVDATA		(U(6) * REGSZ)
 
 #define CONSOLE_FLAG_BOOT		(U(1) << 0)
 #define CONSOLE_FLAG_RUNTIME		(U(1) << 1)
@@ -43,6 +44,7 @@
 	int (*const putc)(int character, struct console *console);
 	int (*const getc)(struct console *console);
 	int (*const flush)(struct console *console);
+	uintptr_t base;
 	/* Additional private driver data may follow here. */
 } console_t;
 
diff --git a/include/drivers/coreboot/cbmem_console.h b/include/drivers/coreboot/cbmem_console.h
index 40c90e6..30b39f1 100644
--- a/include/drivers/coreboot/cbmem_console.h
+++ b/include/drivers/coreboot/cbmem_console.h
@@ -9,14 +9,12 @@
 
 #include <drivers/console.h>
 
-#define CONSOLE_T_CBMC_BASE	CONSOLE_T_DRVDATA
-#define CONSOLE_T_CBMC_SIZE	(CONSOLE_T_DRVDATA + REGSZ)
+#define CONSOLE_T_CBMC_SIZE	CONSOLE_T_DRVDATA
 
 #ifndef __ASSEMBLER__
 
 typedef struct {
 	console_t console;
-	uintptr_t base;
 	uint32_t size;
 } console_cbmc_t;
 
diff --git a/include/drivers/io/io_encrypted.h b/include/drivers/io/io_encrypted.h
new file mode 100644
index 0000000..9dcf061
--- /dev/null
+++ b/include/drivers/io/io_encrypted.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2020, Linaro Limited. All rights reserved.
+ * Author: Sumit Garg <sumit.garg@linaro.org>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IO_ENCRYPTED_H
+#define IO_ENCRYPTED_H
+
+struct io_dev_connector;
+
+int register_io_dev_enc(const struct io_dev_connector **dev_con);
+
+#endif /* IO_ENCRYPTED_H */
diff --git a/include/drivers/io/io_storage.h b/include/drivers/io/io_storage.h
index a301ad5..f2d641c 100644
--- a/include/drivers/io/io_storage.h
+++ b/include/drivers/io/io_storage.h
@@ -25,6 +25,7 @@
 	IO_TYPE_MTD,
 	IO_TYPE_MMC,
 	IO_TYPE_STM32IMAGE,
+	IO_TYPE_ENCRYPTED,
 	IO_TYPE_MAX
 } io_type_t;
 
diff --git a/include/drivers/marvell/uart/a3700_console.h b/include/drivers/marvell/uart/a3700_console.h
index 517f01a..5e3ab05 100644
--- a/include/drivers/marvell/uart/a3700_console.h
+++ b/include/drivers/marvell/uart/a3700_console.h
@@ -54,17 +54,10 @@
 #define UART_CTRL_TXFIFO_RESET	(1 << 15)
 #define UARTLSR_TXFIFOEMPTY	(1 << 6)
 
-#define CONSOLE_T_A3700_BASE	CONSOLE_T_DRVDATA
-
 #ifndef __ASSEMBLER__
 
 #include <stdint.h>
 
-typedef struct {
-	console_t console;
-	uintptr_t base;
-} console_a3700_t;
-
 /*
  * Initialize a new a3700 console instance and register it with the console
  * framework. The |console| pointer must point to storage that will be valid
@@ -72,7 +65,7 @@
  * Its contents will be reinitialized from scratch.
  */
 int console_a3700_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud,
-			   console_a3700_t *console);
+			   console_t *console);
 
 #endif /*__ASSEMBLER__*/
 
diff --git a/include/drivers/renesas/rcar/console/console.h b/include/drivers/renesas/rcar/console/console.h
index 0e4ed8f..7d5b5d3 100644
--- a/include/drivers/renesas/rcar/console/console.h
+++ b/include/drivers/renesas/rcar/console/console.h
@@ -7,17 +7,10 @@
 #ifndef RCAR_PRINTF_H
 #define RCAR_PRINTF_H
 
-#define CONSOLE_T_RCAR_BASE	CONSOLE_T_DRVDATA
-
 #ifndef __ASSEMBLER__
 
 #include <stdint.h>
 
-typedef struct {
-	console_t console;
-	uintptr_t base;
-} console_rcar_t;
-
 /*
  * Initialize a new rcar console instance and register it with the console
  * framework. The |console| pointer must point to storage that will be valid
@@ -25,7 +18,7 @@
  * Its contents will be reinitialized from scratch.
  */
 int console_rcar_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud,
-			  console_rcar_t *console);
+			  console_t *console);
 
 #endif /*__ASSEMBLER__*/
 
diff --git a/include/drivers/st/stm32_console.h b/include/drivers/st/stm32_console.h
index a2ad87c..8d9187d 100644
--- a/include/drivers/st/stm32_console.h
+++ b/include/drivers/st/stm32_console.h
@@ -9,17 +9,10 @@
 
 #include <drivers/console.h>
 
-#define CONSOLE_T_STM32_BASE	CONSOLE_T_DRVDATA
-
 #ifndef __ASSEMBLER__
 
 #include <stdint.h>
 
-struct console_stm32 {
-	console_t console;
-	uintptr_t base;
-};
-
 /*
  * Initialize a new STM32 console instance and register it with the console
  * framework. The |console| pointer must point to storage that will be valid
@@ -27,7 +20,7 @@
  * Its contents will be reinitialized from scratch.
  */
 int console_stm32_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud,
-			   struct console_stm32 *console);
+			   console_t *console);
 
 #endif /*__ASSEMBLER__*/
 
diff --git a/include/drivers/ti/uart/uart_16550.h b/include/drivers/ti/uart/uart_16550.h
index 2b95fa3..bddd997 100644
--- a/include/drivers/ti/uart/uart_16550.h
+++ b/include/drivers/ti/uart/uart_16550.h
@@ -71,17 +71,10 @@
 #define UARTLSR_RDR_BIT		(0)		/* Rx Data Ready Bit */
 #define UARTLSR_RDR		(1 << UARTLSR_RDR_BIT)	/* Rx Data Ready */
 
-#define CONSOLE_T_16550_BASE	CONSOLE_T_DRVDATA
-
 #ifndef __ASSEMBLER__
 
 #include <stdint.h>
 
-typedef struct {
-	console_t console;
-	uintptr_t base;
-} console_16550_t;
-
 /*
  * Initialize a new 16550 console instance and register it with the console
  * framework. The |console| pointer must point to storage that will be valid
@@ -94,7 +87,7 @@
  * case as well.
  */
 int console_16550_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud,
-			   console_16550_t *console);
+			   console_t *console);
 
 #endif /*__ASSEMBLER__*/
 
diff --git a/include/export/common/tbbr/tbbr_img_def_exp.h b/include/export/common/tbbr/tbbr_img_def_exp.h
index ff0d16c..89dbc58 100644
--- a/include/export/common/tbbr/tbbr_img_def_exp.h
+++ b/include/export/common/tbbr/tbbr_img_def_exp.h
@@ -85,7 +85,15 @@
 /* Binary with STM32 header */
 #define STM32_IMAGE_ID			U(29)
 
+/* Encrypted image identifier */
+#define ENC_IMAGE_ID			U(30)
+
 /* Define size of the array */
-#define MAX_NUMBER_IDS			U(30)
+#if defined(SPD_spmd)
+#define MAX_SP_IDS			U(8)
+#define MAX_NUMBER_IDS			MAX_SP_IDS + U(31)
+#else
+#define MAX_NUMBER_IDS			U(31)
+#endif
 
 #endif /* ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_TBBR_TBBR_IMG_DEF_EXP_H */
diff --git a/include/lib/el3_runtime/aarch64/context.h b/include/lib/el3_runtime/aarch64/context.h
index 4158c02..e061950 100644
--- a/include/lib/el3_runtime/aarch64/context.h
+++ b/include/lib/el3_runtime/aarch64/context.h
@@ -68,7 +68,7 @@
  * registers are only 32-bits wide but are stored as 64-bit values for
  * convenience
  ******************************************************************************/
-#define CTX_SYSREGS_OFFSET	(CTX_EL3STATE_OFFSET + CTX_EL3STATE_END)
+#define CTX_EL1_SYSREGS_OFFSET	(CTX_EL3STATE_OFFSET + CTX_EL3STATE_END)
 #define CTX_SPSR_EL1		U(0x0)
 #define CTX_ELR_EL1		U(0x8)
 #define CTX_SCTLR_EL1		U(0x10)
@@ -138,13 +138,118 @@
 /*
  * End of system registers.
  */
-#define CTX_SYSREGS_END		CTX_MTE_REGS_END
+#define CTX_EL1_SYSREGS_END		CTX_MTE_REGS_END
+
+/*
+ * EL2 register set
+ */
+
+#if CTX_INCLUDE_EL2_REGS
+/* For later discussion
+ * ICH_AP0R<n>_EL2
+ * ICH_AP1R<n>_EL2
+ * AMEVCNTVOFF0<n>_EL2
+ * AMEVCNTVOFF1<n>_EL2
+ * ICH_LR<n>_EL2
+ */
+#define CTX_EL2_SYSREGS_OFFSET	(CTX_EL1_SYSREGS_OFFSET + CTX_EL1_SYSREGS_END)
+
+#define CTX_ACTLR_EL2		U(0x0)
+#define CTX_AFSR0_EL2		U(0x8)
+#define CTX_AFSR1_EL2		U(0x10)
+#define CTX_AMAIR_EL2		U(0x18)
+#define CTX_CNTHCTL_EL2		U(0x20)
+#define CTX_CNTHP_CTL_EL2	U(0x28)
+#define CTX_CNTHP_CVAL_EL2	U(0x30)
+#define CTX_CNTHP_TVAL_EL2	U(0x38)
+#define CTX_CNTVOFF_EL2		U(0x40)
+#define CTX_CPTR_EL2		U(0x48)
+#define CTX_DBGVCR32_EL2	U(0x50)
+#define CTX_ELR_EL2		U(0x58)
+#define CTX_ESR_EL2		U(0x60)
+#define CTX_FAR_EL2		U(0x68)
+#define CTX_FPEXC32_EL2		U(0x70)
+#define CTX_HACR_EL2		U(0x78)
+#define CTX_HCR_EL2		U(0x80)
+#define CTX_HPFAR_EL2		U(0x88)
+#define CTX_HSTR_EL2		U(0x90)
+#define CTX_ICC_SRE_EL2		U(0x98)
+#define CTX_ICH_HCR_EL2		U(0xa0)
+#define CTX_ICH_VMCR_EL2	U(0xa8)
+#define CTX_MAIR_EL2		U(0xb0)
+#define CTX_MDCR_EL2		U(0xb8)
+#define CTX_PMSCR_EL2		U(0xc0)
+#define CTX_SCTLR_EL2		U(0xc8)
+#define CTX_SPSR_EL2		U(0xd0)
+#define CTX_SP_EL2		U(0xd8)
+#define CTX_TCR_EL2		U(0xe0)
+#define CTX_TRFCR_EL2		U(0xe8)
+#define CTX_TTBR0_EL2		U(0xf0)
+#define CTX_VBAR_EL2		U(0xf8)
+#define CTX_VMPIDR_EL2		U(0x100)
+#define CTX_VPIDR_EL2		U(0x108)
+#define CTX_VTCR_EL2		U(0x110)
+#define CTX_VTTBR_EL2		U(0x118)
+
+// Only if MTE registers in use
+#define CTX_TFSR_EL2		U(0x120)
+
+// Only if ENABLE_MPAM_FOR_LOWER_ELS==1
+#define CTX_MPAM2_EL2		U(0x128)
+#define CTX_MPAMHCR_EL2		U(0x130)
+#define CTX_MPAMVPM0_EL2	U(0x138)
+#define CTX_MPAMVPM1_EL2	U(0x140)
+#define CTX_MPAMVPM2_EL2	U(0x148)
+#define CTX_MPAMVPM3_EL2	U(0x150)
+#define CTX_MPAMVPM4_EL2	U(0x158)
+#define CTX_MPAMVPM5_EL2	U(0x160)
+#define CTX_MPAMVPM6_EL2	U(0x168)
+#define CTX_MPAMVPM7_EL2	U(0x170)
+#define CTX_MPAMVPMV_EL2	U(0x178)
+
+// Starting with Armv8.6
+#define CTX_HAFGRTR_EL2		U(0x180)
+#define CTX_HDFGRTR_EL2		U(0x188)
+#define CTX_HDFGWTR_EL2		U(0x190)
+#define CTX_HFGITR_EL2		U(0x198)
+#define CTX_HFGRTR_EL2		U(0x1a0)
+#define CTX_HFGWTR_EL2		U(0x1a8)
+#define CTX_CNTPOFF_EL2		U(0x1b0)
+
+// Starting with Armv8.4
+#define CTX_CNTHPS_CTL_EL2	U(0x1b8)
+#define CTX_CNTHPS_CVAL_EL2	U(0x1c0)
+#define CTX_CNTHPS_TVAL_EL2	U(0x1c8)
+#define CTX_CNTHVS_CTL_EL2	U(0x1d0)
+#define CTX_CNTHVS_CVAL_EL2	U(0x1d8)
+#define CTX_CNTHVS_TVAL_EL2	U(0x1e0)
+#define CTX_CNTHV_CTL_EL2	U(0x1e8)
+#define CTX_CNTHV_CVAL_EL2	U(0x1f0)
+#define CTX_CNTHV_TVAL_EL2	U(0x1f8)
+#define CTX_CONTEXTIDR_EL2	U(0x200)
+#define CTX_SDER32_EL2		U(0x208)
+#define CTX_TTBR1_EL2		U(0x210)
+#define CTX_VDISR_EL2		U(0x218)
+#define CTX_VNCR_EL2		U(0x220)
+#define CTX_VSESR_EL2		U(0x228)
+#define CTX_VSTCR_EL2		U(0x230)
+#define CTX_VSTTBR_EL2		U(0x238)
+
+// Starting with Armv8.5
+#define CTX_SCXTNUM_EL2		U(0x240)
+/* Align to the next 16 byte boundary */
+#define CTX_EL2_SYSREGS_END	U(0x250)
+#endif /* CTX_INCLUDE_EL2_REGS */
 
 /*******************************************************************************
  * Constants that allow assembler code to access members of and the 'fp_regs'
  * structure at their correct offsets.
  ******************************************************************************/
-#define CTX_FPREGS_OFFSET	(CTX_SYSREGS_OFFSET + CTX_SYSREGS_END)
+#if CTX_INCLUDE_EL2_REGS
+# define CTX_FPREGS_OFFSET	(CTX_EL2_SYSREGS_OFFSET + CTX_EL2_SYSREGS_END)
+#else
+# define CTX_FPREGS_OFFSET	(CTX_EL1_SYSREGS_OFFSET + CTX_EL1_SYSREGS_END)
+#endif
 #if CTX_INCLUDE_FPREGS
 #define CTX_FP_Q0		U(0x0)
 #define CTX_FP_Q1		U(0x10)
@@ -235,7 +340,10 @@
 
 /* Constants to determine the size of individual context structures */
 #define CTX_GPREG_ALL		(CTX_GPREGS_END >> DWORD_SHIFT)
-#define CTX_SYSREG_ALL		(CTX_SYSREGS_END >> DWORD_SHIFT)
+#define CTX_EL1_SYSREGS_ALL	(CTX_EL1_SYSREGS_END >> DWORD_SHIFT)
+#if CTX_INCLUDE_EL2_REGS
+# define CTX_EL2_SYSREGS_ALL	(CTX_EL2_SYSREGS_END >> DWORD_SHIFT)
+#endif
 #if CTX_INCLUDE_FPREGS
 # define CTX_FPREG_ALL		(CTX_FPREGS_END >> DWORD_SHIFT)
 #endif
@@ -256,10 +364,18 @@
 
 /*
  * AArch64 EL1 system register context structure for preserving the
- * architectural state during switches from one security state to
- * another in EL1.
+ * architectural state during world switches.
  */
-DEFINE_REG_STRUCT(el1_sys_regs, CTX_SYSREG_ALL);
+DEFINE_REG_STRUCT(el1_sysregs, CTX_EL1_SYSREGS_ALL);
+
+
+/*
+ * AArch64 EL2 system register context structure for preserving the
+ * architectural state during world switches.
+ */
+#if CTX_INCLUDE_EL2_REGS
+DEFINE_REG_STRUCT(el2_sysregs, CTX_EL2_SYSREGS_ALL);
+#endif
 
 /*
  * AArch64 floating point register context structure for preserving
@@ -304,7 +420,10 @@
 typedef struct cpu_context {
 	gp_regs_t gpregs_ctx;
 	el3_state_t el3state_ctx;
-	el1_sys_regs_t sysregs_ctx;
+	el1_sysregs_t el1_sysregs_ctx;
+#if CTX_INCLUDE_EL2_REGS
+	el2_sysregs_t el2_sysregs_ctx;
+#endif
 #if CTX_INCLUDE_FPREGS
 	fp_regs_t fpregs_ctx;
 #endif
@@ -319,7 +438,10 @@
 #if CTX_INCLUDE_FPREGS
 # define get_fpregs_ctx(h)	(&((cpu_context_t *) h)->fpregs_ctx)
 #endif
-#define get_sysregs_ctx(h)	(&((cpu_context_t *) h)->sysregs_ctx)
+#define get_el1_sysregs_ctx(h)	(&((cpu_context_t *) h)->el1_sysregs_ctx)
+#if CTX_INCLUDE_EL2_REGS
+# define get_el2_sysregs_ctx(h)	(&((cpu_context_t *) h)->el2_sysregs_ctx)
+#endif
 #define get_gpregs_ctx(h)	(&((cpu_context_t *) h)->gpregs_ctx)
 #define get_cve_2018_3639_ctx(h)	(&((cpu_context_t *) h)->cve_2018_3639_ctx)
 #if CTX_INCLUDE_PAUTH_REGS
@@ -333,8 +455,12 @@
  */
 CASSERT(CTX_GPREGS_OFFSET == __builtin_offsetof(cpu_context_t, gpregs_ctx), \
 	assert_core_context_gp_offset_mismatch);
-CASSERT(CTX_SYSREGS_OFFSET == __builtin_offsetof(cpu_context_t, sysregs_ctx), \
-	assert_core_context_sys_offset_mismatch);
+CASSERT(CTX_EL1_SYSREGS_OFFSET == __builtin_offsetof(cpu_context_t, el1_sysregs_ctx), \
+	assert_core_context_el1_sys_offset_mismatch);
+#if CTX_INCLUDE_EL2_REGS
+CASSERT(CTX_EL2_SYSREGS_OFFSET == __builtin_offsetof(cpu_context_t, el2_sysregs_ctx), \
+	assert_core_context_el2_sys_offset_mismatch);
+#endif
 #if CTX_INCLUDE_FPREGS
 CASSERT(CTX_FPREGS_OFFSET == __builtin_offsetof(cpu_context_t, fpregs_ctx), \
 	assert_core_context_fp_offset_mismatch);
@@ -387,8 +513,14 @@
 /*******************************************************************************
  * Function prototypes
  ******************************************************************************/
-void el1_sysregs_context_save(el1_sys_regs_t *regs);
-void el1_sysregs_context_restore(el1_sys_regs_t *regs);
+void el1_sysregs_context_save(el1_sysregs_t *regs);
+void el1_sysregs_context_restore(el1_sysregs_t *regs);
+
+#if CTX_INCLUDE_EL2_REGS
+void el2_sysregs_context_save(el2_sysregs_t *regs);
+void el2_sysregs_context_restore(el2_sysregs_t *regs);
+#endif
+
 #if CTX_INCLUDE_FPREGS
 void fpregs_context_save(fp_regs_t *regs);
 void fpregs_context_restore(fp_regs_t *regs);
diff --git a/include/lib/el3_runtime/context_mgmt.h b/include/lib/el3_runtime/context_mgmt.h
index 17955e3..b36cd3d 100644
--- a/include/lib/el3_runtime/context_mgmt.h
+++ b/include/lib/el3_runtime/context_mgmt.h
@@ -36,6 +36,11 @@
 void cm_prepare_el3_exit(uint32_t security_state);
 
 #ifdef __aarch64__
+#if CTX_INCLUDE_EL2_REGS
+void cm_el2_sysregs_context_save(uint32_t security_state);
+void cm_el2_sysregs_context_restore(uint32_t security_state);
+#endif
+
 void cm_el1_sysregs_context_save(uint32_t security_state);
 void cm_el1_sysregs_context_restore(uint32_t security_state);
 void cm_set_elr_el3(uint32_t security_state, uintptr_t entrypoint);
diff --git a/include/lib/fconf/fconf.h b/include/lib/fconf/fconf.h
index f58ff57..0401e5c 100644
--- a/include/lib/fconf/fconf.h
+++ b/include/lib/fconf/fconf.h
@@ -14,9 +14,9 @@
 
 #define FCONF_REGISTER_POPULATOR(name, callback)				\
 	__attribute__((used, section(".fconf_populator")))			\
-	const struct fconf_populator name##__populator = {			\
-		.info = #name,							\
-		.populate = callback						\
+	const struct fconf_populator (name##__populator) = {			\
+		.info = (#name),						\
+		.populate = (callback)						\
 	};
 
 /*
diff --git a/include/lib/object_pool.h b/include/lib/object_pool.h
index 0f85331..66e8c47 100644
--- a/include/lib/object_pool.h
+++ b/include/lib/object_pool.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -56,13 +56,13 @@
  */
 static inline void *pool_alloc_n(struct object_pool *pool, size_t count)
 {
-	if (pool->used + count > pool->capacity) {
+	if ((pool->used + count) > pool->capacity) {
 		ERROR("Cannot allocate %zu objects out of pool (%zu objects left).\n",
 		      count, pool->capacity - pool->used);
 		panic();
 	}
 
-	void *obj = (char *)(pool->objects) + pool->obj_size * pool->used;
+	void *obj = (char *)(pool->objects) + (pool->obj_size * pool->used);
 	pool->used += count;
 	return obj;
 }
diff --git a/include/lib/xlat_tables/xlat_tables_v2.h b/include/lib/xlat_tables/xlat_tables_v2.h
index 0e09998..a80fab0 100644
--- a/include/lib/xlat_tables/xlat_tables_v2.h
+++ b/include/lib/xlat_tables/xlat_tables_v2.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -345,6 +345,16 @@
 				   size_t size, uint32_t attr);
 int xlat_change_mem_attributes(uintptr_t base_va, size_t size, uint32_t attr);
 
+#if PLAT_RO_XLAT_TABLES
+/*
+ * Change the memory attributes of the memory region encompassing the higher
+ * level translation tables to secure read-only data.
+ *
+ * Return 0 on success, a negative error code on error.
+ */
+int xlat_make_tables_readonly(void);
+#endif
+
 /*
  * Query the memory attributes of a memory page in a set of translation tables.
  *
diff --git a/include/lib/xlat_tables/xlat_tables_v2_helpers.h b/include/lib/xlat_tables/xlat_tables_v2_helpers.h
index b17b71a..c88fa4d 100644
--- a/include/lib/xlat_tables/xlat_tables_v2_helpers.h
+++ b/include/lib/xlat_tables/xlat_tables_v2_helpers.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -70,6 +70,9 @@
 	 */
 	uint64_t (*tables)[XLAT_TABLE_ENTRIES];
 	int tables_num;
+#if PLAT_RO_XLAT_TABLES
+	bool readonly_tables;
+#endif
 	/*
 	 * Keep track of how many regions are mapped in each table. The base
 	 * table can't be unmapped so it isn't needed to keep track of it.
@@ -122,6 +125,14 @@
 	/* do nothing */
 #endif /* PLAT_XLAT_TABLES_DYNAMIC */
 
+#if PLAT_RO_XLAT_TABLES
+#define XLAT_CTX_INIT_TABLE_ATTR()					\
+	.readonly_tables = false,
+#else
+#define XLAT_CTX_INIT_TABLE_ATTR()
+	/* do nothing */
+#endif
+
 #define REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, _mmap_count,		\
 			_xlat_tables_count, _virt_addr_space_size,	\
 			_phy_addr_space_size, _xlat_regime, _section_name)\
@@ -142,22 +153,63 @@
 	XLAT_ALLOC_DYNMAP_STRUCT(_ctx_name, _xlat_tables_count)		\
 									\
 	static xlat_ctx_t _ctx_name##_xlat_ctx = {			\
-		.va_max_address = (_virt_addr_space_size) - 1UL,	\
 		.pa_max_address = (_phy_addr_space_size) - 1ULL,	\
+		.va_max_address = (_virt_addr_space_size) - 1UL,	\
 		.mmap = _ctx_name##_mmap,				\
 		.mmap_num = (_mmap_count),				\
-		.base_level = GET_XLAT_TABLE_LEVEL_BASE(_virt_addr_space_size),\
+		.tables = _ctx_name##_xlat_tables,			\
+		.tables_num = _xlat_tables_count,			\
+		 XLAT_CTX_INIT_TABLE_ATTR()				\
+		 XLAT_REGISTER_DYNMAP_STRUCT(_ctx_name)			\
+		.next_table = 0,					\
 		.base_table = _ctx_name##_base_xlat_table,		\
 		.base_table_entries =					\
 			GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size),\
+		.max_pa = 0U,						\
+		.max_va = 0U,						\
+		.base_level = GET_XLAT_TABLE_LEVEL_BASE(_virt_addr_space_size),\
+		.initialized = false,					\
+		.xlat_regime = (_xlat_regime)				\
+	}
+
+#define REGISTER_XLAT_CONTEXT_RO_BASE_TABLE(_ctx_name, _mmap_count,	\
+			_xlat_tables_count, _virt_addr_space_size,	\
+			_phy_addr_space_size, _xlat_regime, _section_name)\
+	CASSERT(CHECK_PHY_ADDR_SPACE_SIZE(_phy_addr_space_size),	\
+		assert_invalid_physical_addr_space_sizefor_##_ctx_name);\
+									\
+	static mmap_region_t _ctx_name##_mmap[_mmap_count + 1];		\
+									\
+	static uint64_t _ctx_name##_xlat_tables[_xlat_tables_count]	\
+		[XLAT_TABLE_ENTRIES]					\
+		__aligned(XLAT_TABLE_SIZE) __section(_section_name);	\
+									\
+	static uint64_t _ctx_name##_base_xlat_table			\
+		[GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size)]	\
+		__aligned(GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size)\
+			* sizeof(uint64_t))				\
+		__section(".rodata");					\
+									\
+	XLAT_ALLOC_DYNMAP_STRUCT(_ctx_name, _xlat_tables_count)		\
+									\
+	static xlat_ctx_t _ctx_name##_xlat_ctx = {			\
+		.pa_max_address = (_phy_addr_space_size) - 1ULL,	\
+		.va_max_address = (_virt_addr_space_size) - 1UL,	\
+		.mmap = _ctx_name##_mmap,				\
+		.mmap_num = (_mmap_count),				\
 		.tables = _ctx_name##_xlat_tables,			\
 		.tables_num = _xlat_tables_count,			\
+		 XLAT_CTX_INIT_TABLE_ATTR()				\
 		 XLAT_REGISTER_DYNMAP_STRUCT(_ctx_name)			\
-		.xlat_regime = (_xlat_regime),				\
+		.next_table = 0,					\
+		.base_table = _ctx_name##_base_xlat_table,		\
+		.base_table_entries =					\
+			GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size),\
 		.max_pa = 0U,						\
 		.max_va = 0U,						\
-		.next_table = 0,					\
+		.base_level = GET_XLAT_TABLE_LEVEL_BASE(_virt_addr_space_size),\
 		.initialized = false,					\
+		.xlat_regime = (_xlat_regime)				\
 	}
 
 #endif /*__ASSEMBLER__*/
diff --git a/include/plat/arm/board/common/board_css_def.h b/include/plat/arm/board/common/board_css_def.h
index 4637b67..b79e0d5 100644
--- a/include/plat/arm/board/common/board_css_def.h
+++ b/include/plat/arm/board/common/board_css_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -50,13 +50,6 @@
 #define PLAT_ARM_NVM_BASE		V2M_FLASH0_BASE
 #define PLAT_ARM_NVM_SIZE		(V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE)
 
-/*
- * Required platform porting definitions common to all ARM CSS-based
- * development platforms
- */
-#define PLAT_ARM_DRAM2_BASE			ULL(0x880000000)
-#define PLAT_ARM_DRAM2_SIZE			ULL(0x180000000)
-
 /* UART related constants */
 #define PLAT_ARM_BOOT_UART_BASE			SOC_CSS_UART0_BASE
 #define PLAT_ARM_BOOT_UART_CLK_IN_HZ		SOC_CSS_UART0_CLK_IN_HZ
diff --git a/include/plat/arm/common/fconf_arm_sp_getter.h b/include/plat/arm/common/fconf_arm_sp_getter.h
new file mode 100644
index 0000000..38c30fb
--- /dev/null
+++ b/include/plat/arm/common/fconf_arm_sp_getter.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FCONF_ARM_SP_GETTER_H
+#define FCONF_ARM_SP_GETTER_H
+
+#include <lib/fconf/fconf.h>
+#include <tools_share/uuid.h>
+
+/* arm_sp getter */
+#define arm__sp_getter(prop)	arm_sp.prop
+
+#define ARM_SP_MAX_SIZE		U(0x10000)
+
+struct arm_sp_t {
+	unsigned int		number_of_sp;
+	union uuid_helper_t	uuids[MAX_SP_IDS];
+	uintptr_t		load_addr[MAX_SP_IDS];
+};
+
+int fconf_populate_arm_sp(uintptr_t config);
+
+extern struct arm_sp_t arm_sp;
+
+extern bl_mem_params_node_t sp_mem_params_descs[MAX_SP_IDS];
+
+#endif /* FCONF_ARM_SP_GETTER_H */
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index 45c099f..babde41 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -152,7 +152,8 @@
 int arm_io_setup(void);
 
 /* Security utility functions */
-void arm_tzc400_setup(const arm_tzc_regions_info_t *tzc_regions);
+void arm_tzc400_setup(uintptr_t tzc_base,
+			const arm_tzc_regions_info_t *tzc_regions);
 struct tzc_dmc500_driver_data;
 void arm_tzc_dmc500_setup(struct tzc_dmc500_driver_data *plat_driver_data,
 			const arm_tzc_regions_info_t *tzc_regions);
@@ -237,6 +238,11 @@
 void arm_free_init_memory(void);
 
 /*
+ * Make the higher level translation tables read-only
+ */
+void arm_xlat_make_tables_readonly(void);
+
+/*
  * Mandatory functions required in ARM standard platforms
  */
 unsigned int plat_arm_get_cluster_core_count(u_register_t mpidr);
diff --git a/include/plat/arm/css/common/css_def.h b/include/plat/arm/css/common/css_def.h
index 7b61484..d599352 100644
--- a/include/plat/arm/css/common/css_def.h
+++ b/include/plat/arm/css/common/css_def.h
@@ -189,9 +189,6 @@
 /* Load address of Non-Secure Image for CSS platform ports */
 #define PLAT_ARM_NS_IMAGE_BASE		U(0xE0000000)
 
-/* TZC related constants */
-#define PLAT_ARM_TZC_FILTERS		TZC_400_REGION_ATTR_FILTER_BIT_ALL
-
 /*
  * Parsing of CPU and Cluster states, as returned by 'Get CSS Power State' SCP
  * command
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index f5bd298..5b5ebb9 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -27,6 +27,7 @@
 struct mmap_region;
 struct spm_mm_boot_info;
 struct sp_res_desc;
+enum fw_enc_status_t;
 
 /*******************************************************************************
  * plat_get_rotpk_info() flags
@@ -37,6 +38,15 @@
 #define ROTPK_NOT_DEPLOYED		(1 << 1)
 
 /*******************************************************************************
+ * plat_get_enc_key_info() flags
+ ******************************************************************************/
+/*
+ * Flag used to notify caller that information provided in key buffer is an
+ * identifier rather than an actual key.
+ */
+#define ENC_KEY_IS_IDENTIFIER		(1 << 0)
+
+/*******************************************************************************
  * Function declarations
  ******************************************************************************/
 /*******************************************************************************
@@ -265,6 +275,9 @@
 int plat_set_nv_ctr2(void *cookie, const struct auth_img_desc_s *img_desc,
 		unsigned int nv_ctr);
 int get_mbedtls_heap_helper(void **heap_addr, size_t *heap_size);
+int plat_get_enc_key_info(enum fw_enc_status_t fw_enc_status, uint8_t *key,
+			  size_t *key_len, unsigned int *flags,
+			  const uint8_t *img_id, size_t img_id_len);
 
 /*******************************************************************************
  * Secure Partitions functions
diff --git a/include/services/spm_core_manifest.h b/include/services/spm_core_manifest.h
index 06ecc13..7874882 100644
--- a/include/services/spm_core_manifest.h
+++ b/include/services/spm_core_manifest.h
@@ -21,13 +21,6 @@
 	uint32_t minor_version;
 
 	/*
-	 * Run-Time Exception Level (mandatory):
-	 * - 1: SEL1
-	 * - 2: SEL2
-	 */
-	uint32_t runtime_el;
-
-	/*
 	 * Run-Time Execution state (optional):
 	 * - 0: AArch64 (default)
 	 * - 1: AArch32
diff --git a/include/services/spmd_svc.h b/include/services/spmd_svc.h
index 6e4caf2..a766dcf 100644
--- a/include/services/spmd_svc.h
+++ b/include/services/spmd_svc.h
@@ -11,7 +11,7 @@
 #include <services/spci_svc.h>
 #include <stdint.h>
 
-int32_t spmd_setup(void);
+int spmd_setup(void);
 uint64_t spmd_smc_handler(uint32_t smc_fid,
 			  uint64_t x1,
 			  uint64_t x2,
diff --git a/include/tools_share/firmware_encrypted.h b/include/tools_share/firmware_encrypted.h
new file mode 100644
index 0000000..7ca634f
--- /dev/null
+++ b/include/tools_share/firmware_encrypted.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2020, Linaro Limited. All rights reserved.
+ * Author: Sumit Garg <sumit.garg@linaro.org>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FIRMWARE_ENCRYPTED_H
+#define FIRMWARE_ENCRYPTED_H
+
+#include <stdint.h>
+
+/* This is used as a signature to validate the encryption header */
+#define ENC_HEADER_MAGIC		0xAA640001U
+
+/* Firmware encryption status flag mask */
+#define FW_ENC_STATUS_FLAG_MASK		0x1
+
+/*
+ * SSK: Secret Symmetric Key
+ * BSSK: Binding Secret Symmetric Key
+ */
+enum fw_enc_status_t {
+	FW_ENC_WITH_SSK = 0,
+	FW_ENC_WITH_BSSK = 1,
+};
+
+#define ENC_MAX_IV_SIZE			16U
+#define ENC_MAX_TAG_SIZE		16U
+#define ENC_MAX_KEY_SIZE		32U
+
+struct fw_enc_hdr {
+	uint32_t magic;
+	uint16_t dec_algo;
+	uint16_t flags;
+	uint16_t iv_len;
+	uint16_t tag_len;
+	uint8_t iv[ENC_MAX_IV_SIZE];
+	uint8_t tag[ENC_MAX_TAG_SIZE];
+};
+
+#endif /* FIRMWARE_ENCRYPTED_H */
diff --git a/lib/aarch64/cache_helpers.S b/lib/aarch64/cache_helpers.S
index 9ef8ca7..de9c8e4 100644
--- a/lib/aarch64/cache_helpers.S
+++ b/lib/aarch64/cache_helpers.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -30,7 +30,7 @@
 	dc	\op, x0
 	add	x0, x0, x2
 	cmp	x0, x1
-	b.lo    loop_\op
+	b.lo	loop_\op
 	dsb	sy
 exit_loop_\op:
 	ret
@@ -140,7 +140,7 @@
 level_done:
 	add	x10, x10, #2		// increment cache number
 	cmp	x3, x10
-	b.hi    loop1
+	b.hi	loop1
 	msr	csselr_el1, xzr		// select cache level 0 in csselr
 	dsb	sy			// barrier to complete final cache operation
 	isb
diff --git a/lib/coreboot/coreboot_table.c b/lib/coreboot/coreboot_table.c
index 63bdc63..253fac2 100644
--- a/lib/coreboot/coreboot_table.c
+++ b/lib/coreboot/coreboot_table.c
@@ -75,7 +75,7 @@
 static void setup_cbmem_console(uintptr_t baseaddr)
 {
 	static console_cbmc_t console;
-	assert(!console.base);		/* should only have one CBMEM console */
+	assert(!console.console.base);	/* should only have one CBMEM console */
 
 	/* CBMEM console structure stores its size in first header field. */
 	uint32_t size = *(uint32_t *)baseaddr;
diff --git a/lib/cpus/aarch64/denver.S b/lib/cpus/aarch64/denver.S
index c377b28..e260f8d 100644
--- a/lib/cpus/aarch64/denver.S
+++ b/lib/cpus/aarch64/denver.S
@@ -156,12 +156,12 @@
 	 * ----------------------------------------------------
 	 */
 func denver_enable_dco
-	mov	x3, x30
+	mov	x18, x30
 	bl	plat_my_core_pos
 	mov	x1, #1
 	lsl	x1, x1, x0
 	msr	s3_0_c15_c0_2, x1
-	mov	x30, x3
+	mov	x30, x18
 	ret
 endfunc denver_enable_dco
 
@@ -171,7 +171,7 @@
 	 */
 func denver_disable_dco
 
-	mov	x3, x30
+	mov	x18, x30
 
 	/* turn off background work */
 	bl	plat_my_core_pos
@@ -188,7 +188,7 @@
 	and	x2, x2, x1
 	cbnz	x2, 1b
 
-	mov	x30, x3
+	mov	x30, x18
 	ret
 endfunc denver_disable_dco
 
diff --git a/lib/el3_runtime/aarch64/context.S b/lib/el3_runtime/aarch64/context.S
index 9bd25ba..30ad7b7 100644
--- a/lib/el3_runtime/aarch64/context.S
+++ b/lib/el3_runtime/aarch64/context.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,6 +9,11 @@
 #include <assert_macros.S>
 #include <context.h>
 
+#if CTX_INCLUDE_EL2_REGS
+	.global	el2_sysregs_context_save
+	.global	el2_sysregs_context_restore
+#endif
+
 	.global	el1_sysregs_context_save
 	.global	el1_sysregs_context_restore
 #if CTX_INCLUDE_FPREGS
@@ -19,6 +24,385 @@
 	.global	restore_gp_pmcr_pauth_regs
 	.global	el3_exit
 
+#if CTX_INCLUDE_EL2_REGS
+
+/* -----------------------------------------------------
+ * The following function strictly follows the AArch64
+ * PCS to use x9-x17 (temporary caller-saved registers)
+ * to save EL2 system register context. It assumes that
+ * 'x0' is pointing to a 'el2_sys_regs' structure where
+ * the register context will be saved.
+ *
+ * The following registers are not added.
+ * AMEVCNTVOFF0<n>_EL2
+ * AMEVCNTVOFF1<n>_EL2
+ * ICH_AP0R<n>_EL2
+ * ICH_AP1R<n>_EL2
+ * ICH_LR<n>_EL2
+ * -----------------------------------------------------
+ */
+
+func el2_sysregs_context_save
+	mrs	x9, actlr_el2
+	mrs	x10, afsr0_el2
+	stp	x9, x10, [x0, #CTX_ACTLR_EL2]
+
+	mrs	x11, afsr1_el2
+	mrs	x12, amair_el2
+	stp	x11, x12, [x0, #CTX_AFSR1_EL2]
+
+	mrs	x13, cnthctl_el2
+	mrs	x14, cnthp_ctl_el2
+	stp	x13, x14, [x0, #CTX_CNTHCTL_EL2]
+
+	mrs	x15, cnthp_cval_el2
+	mrs	x16, cnthp_tval_el2
+	stp	x15, x16, [x0, #CTX_CNTHP_CVAL_EL2]
+
+	mrs	x17, cntvoff_el2
+	mrs	x9, cptr_el2
+	stp	x17, x9, [x0, #CTX_CNTVOFF_EL2]
+
+	mrs	x10, dbgvcr32_el2
+	mrs	x11, elr_el2
+	stp	x10, x11, [x0, #CTX_DBGVCR32_EL2]
+
+	mrs	x14, esr_el2
+	mrs	x15, far_el2
+	stp	x14, x15, [x0, #CTX_ESR_EL2]
+
+	mrs	x16, fpexc32_el2
+	mrs	x17, hacr_el2
+	stp	x16, x17, [x0, #CTX_FPEXC32_EL2]
+
+	mrs	x9, hcr_el2
+	mrs	x10, hpfar_el2
+	stp	x9, x10, [x0, #CTX_HCR_EL2]
+
+	mrs	x11, hstr_el2
+	mrs	x12, ICC_SRE_EL2
+	stp	x11, x12, [x0, #CTX_HSTR_EL2]
+
+	mrs	x13, ICH_HCR_EL2
+	mrs	x14, ICH_VMCR_EL2
+	stp	x13, x14, [x0, #CTX_ICH_HCR_EL2]
+
+	mrs	x15, mair_el2
+	mrs	x16, mdcr_el2
+	stp	x15, x16, [x0, #CTX_MAIR_EL2]
+
+	mrs	x17, PMSCR_EL2
+	mrs	x9, sctlr_el2
+	stp	x17, x9, [x0, #CTX_PMSCR_EL2]
+
+	mrs	x10, spsr_el2
+	mrs	x11, sp_el2
+	stp	x10, x11, [x0, #CTX_SPSR_EL2]
+
+	mrs	x12, tcr_el2
+	mrs	x13, TRFCR_EL2
+	stp	x12, x13, [x0, #CTX_TCR_EL2]
+
+	mrs	x14, ttbr0_el2
+	mrs	x15, vbar_el2
+	stp	x14, x15, [x0, #CTX_TTBR0_EL2]
+
+	mrs	x16, vmpidr_el2
+	mrs	x17, vpidr_el2
+	stp	x16, x17, [x0, #CTX_VMPIDR_EL2]
+
+	mrs	x9, vtcr_el2
+	mrs	x10, vttbr_el2
+	stp	x9, x10, [x0, #CTX_VTCR_EL2]
+
+#if CTX_INCLUDE_MTE_REGS
+	mrs	x11, TFSR_EL2
+	str	x11, [x0, #CTX_TFSR_EL2]
+#endif
+
+#if ENABLE_MPAM_FOR_LOWER_ELS
+	mrs	x9, MPAM2_EL2
+	mrs	x10, MPAMHCR_EL2
+	stp	x9, x10, [x0, #CTX_MPAM2_EL2]
+
+	mrs	x11, MPAMVPM0_EL2
+	mrs	x12, MPAMVPM1_EL2
+	stp	x11, x12, [x0, #CTX_MPAMVPM0_EL2]
+
+	mrs	x13, MPAMVPM2_EL2
+	mrs	x14, MPAMVPM3_EL2
+	stp	x13, x14, [x0, #CTX_MPAMVPM2_EL2]
+
+	mrs	x15, MPAMVPM4_EL2
+	mrs	x16, MPAMVPM5_EL2
+	stp	x15, x16, [x0, #CTX_MPAMVPM4_EL2]
+
+	mrs	x17, MPAMVPM6_EL2
+	mrs	x9, MPAMVPM7_EL2
+	stp	x17, x9, [x0, #CTX_MPAMVPM6_EL2]
+
+	mrs	x10, MPAMVPMV_EL2
+	str	x10, [x0, #CTX_MPAMVPMV_EL2]
+#endif
+
+
+#if ARM_ARCH_AT_LEAST(8, 6)
+	mrs	x11, HAFGRTR_EL2
+	mrs	x12, HDFGRTR_EL2
+	stp	x11, x12, [x0, #CTX_HAFGRTR_EL2]
+
+	mrs	x13, HDFGWTR_EL2
+	mrs	x14, HFGITR_EL2
+	stp	x13, x14, [x0, #CTX_HDFGWTR_EL2]
+
+	mrs	x15, HFGRTR_EL2
+	mrs	x16, HFGWTR_EL2
+	stp	x15, x16, [x0, #CTX_HFGRTR_EL2]
+
+	mrs	x17, CNTPOFF_EL2
+	str	x17, [x0, #CTX_CNTPOFF_EL2]
+#endif
+
+#if ARM_ARCH_AT_LEAST(8, 4)
+	mrs	x9, cnthps_ctl_el2
+	mrs	x10, cnthps_cval_el2
+	stp	x9, x10, [x0, #CTX_CNTHPS_CTL_EL2]
+
+	mrs	x11, cnthps_tval_el2
+	mrs	x12, cnthvs_ctl_el2
+	stp	x11, x12, [x0, #CTX_CNTHPS_TVAL_EL2]
+
+	mrs	x13, cnthvs_cval_el2
+	mrs	x14, cnthvs_tval_el2
+	stp	x13, x14, [x0, #CTX_CNTHVS_CVAL_EL2]
+
+	mrs	x15, cnthv_ctl_el2
+	mrs	x16, cnthv_cval_el2
+	stp	x15, x16, [x0, #CTX_CNTHV_CTL_EL2]
+
+	mrs	x17, cnthv_tval_el2
+	mrs	x9, contextidr_el2
+	stp	x17, x9, [x0, #CTX_CNTHV_TVAL_EL2]
+
+	mrs	x10, sder32_el2
+	str	x10, [x0, #CTX_SDER32_EL2]
+
+	mrs	x11, ttbr1_el2
+	str	x11, [x0, #CTX_TTBR1_EL2]
+
+	mrs	x12, vdisr_el2
+	str	x12, [x0, #CTX_VDISR_EL2]
+
+	mrs	x13, vncr_el2
+	str	x13, [x0, #CTX_VNCR_EL2]
+
+	mrs	x14, vsesr_el2
+	str	x14, [x0, #CTX_VSESR_EL2]
+
+	mrs	x15, vstcr_el2
+	str	x15, [x0, #CTX_VSTCR_EL2]
+
+	mrs	x16, vsttbr_el2
+	str	x16, [x0, #CTX_VSTTBR_EL2]
+#endif
+
+#if ARM_ARCH_AT_LEAST(8, 5)
+	mrs	x17, scxtnum_el2
+	str	x17, [x0, #CTX_SCXTNUM_EL2]
+#endif
+
+	ret
+endfunc el2_sysregs_context_save
+
+/* -----------------------------------------------------
+ * The following function strictly follows the AArch64
+ * PCS to use x9-x17 (temporary caller-saved registers)
+ * to restore EL2 system register context.  It assumes
+ * that 'x0' is pointing to a 'el2_sys_regs' structure
+ * from where the register context will be restored
+
+ * The following registers are not restored
+ * AMEVCNTVOFF0<n>_EL2
+ * AMEVCNTVOFF1<n>_EL2
+ * ICH_AP0R<n>_EL2
+ * ICH_AP1R<n>_EL2
+ * ICH_LR<n>_EL2
+ * -----------------------------------------------------
+ */
+func el2_sysregs_context_restore
+
+	ldp	x9, x10, [x0, #CTX_ACTLR_EL2]
+	msr	actlr_el2, x9
+	msr	afsr0_el2, x10
+
+	ldp	x11, x12, [x0, #CTX_AFSR1_EL2]
+	msr	afsr1_el2, x11
+	msr	amair_el2, x12
+
+	ldp	x13, x14, [x0, #CTX_CNTHCTL_EL2]
+	msr	cnthctl_el2, x13
+	msr	cnthp_ctl_el2, x14
+
+	ldp	x15, x16, [x0, #CTX_CNTHP_CVAL_EL2]
+	msr	cnthp_cval_el2, x15
+	msr	cnthp_tval_el2, x16
+
+	ldp	x17, x9, [x0, #CTX_CNTVOFF_EL2]
+	msr	cntvoff_el2, x17
+	msr	cptr_el2, x9
+
+	ldp	x10, x11, [x0, #CTX_DBGVCR32_EL2]
+	msr	dbgvcr32_el2, x10
+	msr	elr_el2, x11
+
+	ldp	x14, x15, [x0, #CTX_ESR_EL2]
+	msr	esr_el2, x14
+	msr	far_el2, x15
+
+	ldp	x16, x17, [x0, #CTX_FPEXC32_EL2]
+	msr	fpexc32_el2, x16
+	msr	hacr_el2, x17
+
+	ldp	x9, x10, [x0, #CTX_HCR_EL2]
+	msr	hcr_el2, x9
+	msr	hpfar_el2, x10
+
+	ldp	x11, x12, [x0, #CTX_HSTR_EL2]
+	msr	hstr_el2, x11
+	msr	ICC_SRE_EL2, x12
+
+	ldp	x13, x14, [x0, #CTX_ICH_HCR_EL2]
+	msr	ICH_HCR_EL2, x13
+	msr	ICH_VMCR_EL2, x14
+
+	ldp	x15, x16, [x0, #CTX_MAIR_EL2]
+	msr	mair_el2, x15
+	msr	mdcr_el2, x16
+
+	ldp	x17, x9, [x0, #CTX_PMSCR_EL2]
+	msr	PMSCR_EL2, x17
+	msr	sctlr_el2, x9
+
+	ldp	x10, x11, [x0, #CTX_SPSR_EL2]
+	msr	spsr_el2, x10
+	msr	sp_el2, x11
+
+	ldp	x12, x13, [x0, #CTX_TCR_EL2]
+	msr	tcr_el2, x12
+	msr	TRFCR_EL2, x13
+
+	ldp	x14, x15, [x0, #CTX_TTBR0_EL2]
+	msr	ttbr0_el2, x14
+	msr	vbar_el2, x15
+
+	ldp	x16, x17, [x0, #CTX_VMPIDR_EL2]
+	msr	vmpidr_el2, x16
+	msr	vpidr_el2, x17
+
+	ldp	x9, x10, [x0, #CTX_VTCR_EL2]
+	msr	vtcr_el2, x9
+	msr	vttbr_el2, x10
+
+#if CTX_INCLUDE_MTE_REGS
+	ldr	x11, [x0, #CTX_TFSR_EL2]
+	msr	TFSR_EL2, x11
+#endif
+
+#if ENABLE_MPAM_FOR_LOWER_ELS
+	ldp	x9, x10, [x0, #CTX_MPAM2_EL2]
+	msr	MPAM2_EL2, x9
+	msr	MPAMHCR_EL2, x10
+
+	ldp	x11, x12, [x0, #CTX_MPAMVPM0_EL2]
+	msr	MPAMVPM0_EL2, x11
+	msr	MPAMVPM1_EL2, x12
+
+	ldp	x13, x14, [x0, #CTX_MPAMVPM2_EL2]
+	msr	MPAMVPM2_EL2, x13
+	msr	MPAMVPM3_EL2, x14
+
+	ldp	x15, x16, [x0, #CTX_MPAMVPM4_EL2]
+	msr	MPAMVPM4_EL2, x15
+	msr	MPAMVPM5_EL2, x16
+
+	ldp	x17, x9, [x0, #CTX_MPAMVPM6_EL2]
+	msr	MPAMVPM6_EL2, x17
+	msr	MPAMVPM7_EL2, x9
+
+	ldr	x10, [x0, #CTX_MPAMVPMV_EL2]
+	msr	MPAMVPMV_EL2, x10
+#endif
+
+#if ARM_ARCH_AT_LEAST(8, 6)
+	ldp	x11, x12, [x0, #CTX_HAFGRTR_EL2]
+	msr	HAFGRTR_EL2, x11
+	msr	HDFGRTR_EL2, x12
+
+	ldp	x13, x14, [x0, #CTX_HDFGWTR_EL2]
+	msr	HDFGWTR_EL2, x13
+	msr	HFGITR_EL2, x14
+
+	ldp	x15, x16, [x0, #CTX_HFGRTR_EL2]
+	msr	HFGRTR_EL2, x15
+	msr	HFGWTR_EL2, x16
+
+	ldr	x17, [x0, #CTX_CNTPOFF_EL2]
+	msr	CNTPOFF_EL2, x17
+#endif
+
+#if ARM_ARCH_AT_LEAST(8, 4)
+	ldp	x9, x10, [x0, #CTX_CNTHPS_CTL_EL2]
+	msr	cnthps_ctl_el2, x9
+	msr	cnthps_cval_el2, x10
+
+	ldp	x11, x12, [x0, #CTX_CNTHPS_TVAL_EL2]
+	msr	cnthps_tval_el2, x11
+	msr	cnthvs_ctl_el2, x12
+
+	ldp	x13, x14, [x0, #CTX_CNTHVS_CVAL_EL2]
+	msr	cnthvs_cval_el2, x13
+	msr	cnthvs_tval_el2, x14
+
+	ldp	x15, x16, [x0, #CTX_CNTHV_CTL_EL2]
+	msr	cnthv_ctl_el2, x15
+	msr	cnthv_cval_el2, x16
+
+	ldp	x17, x9, [x0, #CTX_CNTHV_TVAL_EL2]
+	msr	cnthv_tval_el2, x17
+	msr	contextidr_el2, x9
+
+	ldr	x10, [x0, #CTX_SDER32_EL2]
+	msr	sder32_el2, x10
+
+	ldr	x11, [x0, #CTX_TTBR1_EL2]
+	msr	ttbr1_el2, x11
+
+	ldr	x12, [x0, #CTX_VDISR_EL2]
+	msr	vdisr_el2, x12
+
+	ldr	x13, [x0, #CTX_VNCR_EL2]
+	msr	vncr_el2, x13
+
+	ldr	x14, [x0, #CTX_VSESR_EL2]
+	msr	vsesr_el2, x14
+
+	ldr	x15, [x0, #CTX_VSTCR_EL2]
+	msr	vstcr_el2, x15
+
+	ldr	x16, [x0, #CTX_VSTTBR_EL2]
+	msr	vsttbr_el2, x16
+#endif
+
+#if ARM_ARCH_AT_LEAST(8, 5)
+	ldr	x17, [x0, #CTX_SCXTNUM_EL2]
+	msr	scxtnum_el2, x17
+#endif
+
+	ret
+endfunc el2_sysregs_context_restore
+
+#endif /* CTX_INCLUDE_EL2_REGS */
+
 /* ------------------------------------------------------------------
  * The following function strictly follows the AArch64 PCS to use
  * x9-x17 (temporary caller-saved registers) to save EL1 system
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index 546e39e..0314a85 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -234,7 +234,7 @@
 	 * and other EL2 registers are set up by cm_prepare_ns_entry() as they
 	 * are not part of the stored cpu_context.
 	 */
-	write_ctx_reg(get_sysregs_ctx(ctx), CTX_SCTLR_EL1, sctlr_elx);
+	write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SCTLR_EL1, sctlr_elx);
 
 	/*
 	 * Base the context ACTLR_EL1 on the current value, as it is
@@ -244,7 +244,7 @@
 	 * be zero.
 	 */
 	actlr_elx = read_actlr_el1();
-	write_ctx_reg((get_sysregs_ctx(ctx)), (CTX_ACTLR_EL1), (actlr_elx));
+	write_ctx_reg((get_el1_sysregs_ctx(ctx)), (CTX_ACTLR_EL1), (actlr_elx));
 
 	/*
 	 * Populate EL3 state so that we've the right context
@@ -336,7 +336,7 @@
 						 CTX_SCR_EL3);
 		if ((scr_el3 & SCR_HCE_BIT) != 0U) {
 			/* Use SCTLR_EL1.EE value to initialise sctlr_el2 */
-			sctlr_elx = read_ctx_reg(get_sysregs_ctx(ctx),
+			sctlr_elx = read_ctx_reg(get_el1_sysregs_ctx(ctx),
 							   CTX_SCTLR_EL1);
 			sctlr_elx &= SCTLR_EE_BIT;
 			sctlr_elx |= SCTLR_EL2_RES1;
@@ -530,6 +530,52 @@
 	cm_set_next_eret_context(security_state);
 }
 
+#if CTX_INCLUDE_EL2_REGS
+/*******************************************************************************
+ * Save EL2 sysreg context
+ ******************************************************************************/
+void cm_el2_sysregs_context_save(uint32_t security_state)
+{
+	u_register_t scr_el3 = read_scr();
+
+	/*
+	 * Always save the non-secure EL2 context, only save the
+	 * S-EL2 context if S-EL2 is enabled.
+	 */
+	if ((security_state == NON_SECURE) ||
+	    ((scr_el3 & SCR_EEL2_BIT) != 0U)) {
+		cpu_context_t *ctx;
+
+		ctx = cm_get_context(security_state);
+		assert(ctx != NULL);
+
+		el2_sysregs_context_save(get_el2_sysregs_ctx(ctx));
+	}
+}
+
+/*******************************************************************************
+ * Restore EL2 sysreg context
+ ******************************************************************************/
+void cm_el2_sysregs_context_restore(uint32_t security_state)
+{
+	u_register_t scr_el3 = read_scr();
+
+	/*
+	 * Always restore the non-secure EL2 context, only restore the
+	 * S-EL2 context if S-EL2 is enabled.
+	 */
+	if ((security_state == NON_SECURE) ||
+	    ((scr_el3 & SCR_EEL2_BIT) != 0U)) {
+		cpu_context_t *ctx;
+
+		ctx = cm_get_context(security_state);
+		assert(ctx != NULL);
+
+		el2_sysregs_context_restore(get_el2_sysregs_ctx(ctx));
+	}
+}
+#endif /* CTX_INCLUDE_EL2_REGS */
+
 /*******************************************************************************
  * The next four functions are used by runtime services to save and restore
  * EL1 context on the 'cpu_context' structure for the specified security
@@ -542,7 +588,7 @@
 	ctx = cm_get_context(security_state);
 	assert(ctx != NULL);
 
-	el1_sysregs_context_save(get_sysregs_ctx(ctx));
+	el1_sysregs_context_save(get_el1_sysregs_ctx(ctx));
 
 #if IMAGE_BL31
 	if (security_state == SECURE)
@@ -559,7 +605,7 @@
 	ctx = cm_get_context(security_state);
 	assert(ctx != NULL);
 
-	el1_sysregs_context_restore(get_sysregs_ctx(ctx));
+	el1_sysregs_context_restore(get_el1_sysregs_ctx(ctx));
 
 #if IMAGE_BL31
 	if (security_state == SECURE)
diff --git a/lib/xlat_tables_v2/ro_xlat_tables.mk b/lib/xlat_tables_v2/ro_xlat_tables.mk
new file mode 100644
index 0000000..7991e1a
--- /dev/null
+++ b/lib/xlat_tables_v2/ro_xlat_tables.mk
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2020, ARM Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+ifeq (${USE_DEBUGFS}, 1)
+    $(error "Debugfs requires functionality from the dynamic translation \
+             library and is incompatible with ALLOW_RO_XLAT_TABLES.")
+endif
+
+ifeq (${ARCH},aarch32)
+    ifeq (${RESET_TO_SP_MIN},1)
+       $(error "RESET_TO_SP_MIN requires functionality from the dynamic \
+                translation library and is incompatible with \
+                ALLOW_RO_XLAT_TABLES.")
+    endif
+else # if AArch64
+    ifeq (${PLAT},tegra)
+        $(error "Tegra requires functionality from the dynamic translation \
+                 library and is incompatible with ALLOW_RO_XLAT_TABLES.")
+    endif
+    ifeq (${RESET_TO_BL31},1)
+        $(error "RESET_TO_BL31 requires functionality from the dynamic \
+                 translation library and is incompatible with \
+                 ALLOW_RO_XLAT_TABLES.")
+    endif
+    ifeq (${SPD},trusty)
+        $(error "Trusty requires functionality from the dynamic translation \
+                 library and is incompatible with ALLOW_RO_XLAT_TABLES.")
+    endif
+    ifeq (${SPM_MM},1)
+        $(error "SPM_MM requires functionality to change memory region \
+                 attributes, which is not possible once the translation tables \
+                 have been made read-only.")
+    endif
+endif
diff --git a/lib/xlat_tables_v2/xlat_tables.mk b/lib/xlat_tables_v2/xlat_tables.mk
index c946315..bcc3e68 100644
--- a/lib/xlat_tables_v2/xlat_tables.mk
+++ b/lib/xlat_tables_v2/xlat_tables.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -13,3 +13,7 @@
 
 XLAT_TABLES_LIB_V2	:=	1
 $(eval $(call add_define,XLAT_TABLES_LIB_V2))
+
+ifeq (${ALLOW_RO_XLAT_TABLES}, 1)
+    include lib/xlat_tables_v2/ro_xlat_tables.mk
+endif
diff --git a/lib/xlat_tables_v2/xlat_tables_context.c b/lib/xlat_tables_v2/xlat_tables_context.c
index f4b64b3..adca578 100644
--- a/lib/xlat_tables_v2/xlat_tables_context.c
+++ b/lib/xlat_tables_v2/xlat_tables_context.c
@@ -1,9 +1,10 @@
 /*
- * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <arch_helpers.h>
 #include <assert.h>
 
 #include <platform_def.h>
@@ -24,8 +25,14 @@
  * Allocate and initialise the default translation context for the BL image
  * currently executing.
  */
+#if PLAT_RO_XLAT_TABLES
+REGISTER_XLAT_CONTEXT_RO_BASE_TABLE(tf, MAX_MMAP_REGIONS, MAX_XLAT_TABLES,
+		PLAT_VIRT_ADDR_SPACE_SIZE, PLAT_PHY_ADDR_SPACE_SIZE,
+		EL_REGIME_INVALID, "xlat_table");
+#else
 REGISTER_XLAT_CONTEXT(tf, MAX_MMAP_REGIONS, MAX_XLAT_TABLES,
 		PLAT_VIRT_ADDR_SPACE_SIZE, PLAT_PHY_ADDR_SPACE_SIZE);
+#endif
 
 void mmap_add_region(unsigned long long base_pa, uintptr_t base_va, size_t size,
 		     unsigned int attr)
@@ -119,6 +126,75 @@
 	return xlat_change_mem_attributes_ctx(&tf_xlat_ctx, base_va, size, attr);
 }
 
+#if PLAT_RO_XLAT_TABLES
+/* Change the memory attributes of the descriptors which resolve the address
+ * range that belongs to the translation tables themselves, which are by default
+ * mapped as part of read-write data in the BL image's memory.
+ *
+ * Since the translation tables map themselves via these level 3 (page)
+ * descriptors, any change applied to them with the MMU on would introduce a
+ * chicken and egg problem because of the break-before-make sequence.
+ * Eventually, it would reach the descriptor that resolves the very table it
+ * belongs to and the invalidation (break step) would cause the subsequent write
+ * (make step) to it to generate an MMU fault. Therefore, the MMU is disabled
+ * before making the change.
+ *
+ * No assumption is made about what data this function needs, therefore all the
+ * caches are flushed in order to ensure coherency. A future optimization would
+ * be to only flush the required data to main memory.
+ */
+int xlat_make_tables_readonly(void)
+{
+	assert(tf_xlat_ctx.initialized == true);
+#ifdef __aarch64__
+	if (tf_xlat_ctx.xlat_regime == EL1_EL0_REGIME) {
+		disable_mmu_el1();
+	} else if (tf_xlat_ctx.xlat_regime == EL3_REGIME) {
+		disable_mmu_el3();
+	} else {
+		assert(tf_xlat_ctx.xlat_regime == EL2_REGIME);
+		return -1;
+	}
+
+	/* Flush all caches. */
+	dcsw_op_all(DCCISW);
+#else /* !__aarch64__ */
+	assert(tf_xlat_ctx.xlat_regime == EL1_EL0_REGIME);
+	/* On AArch32, we flush the caches before disabling the MMU. The reason
+	 * for this is that the dcsw_op_all AArch32 function pushes some
+	 * registers onto the stack under the assumption that it is writing to
+	 * cache, which is not true with the MMU off. This would result in the
+	 * stack becoming corrupted and a wrong/junk value for the LR being
+	 * restored at the end of the routine.
+	 */
+	dcsw_op_all(DC_OP_CISW);
+	disable_mmu_secure();
+#endif
+
+	int rc = xlat_change_mem_attributes_ctx(&tf_xlat_ctx,
+				(uintptr_t)tf_xlat_ctx.tables,
+				tf_xlat_ctx.tables_num * XLAT_TABLE_SIZE,
+				MT_RO_DATA | MT_SECURE);
+
+#ifdef __aarch64__
+	if (tf_xlat_ctx.xlat_regime == EL1_EL0_REGIME) {
+		enable_mmu_el1(0U);
+	} else {
+		assert(tf_xlat_ctx.xlat_regime == EL3_REGIME);
+		enable_mmu_el3(0U);
+	}
+#else /* !__aarch64__ */
+	enable_mmu_svc_mon(0U);
+#endif
+
+	if (rc == 0) {
+		tf_xlat_ctx.readonly_tables = true;
+	}
+
+	return rc;
+}
+#endif /* PLAT_RO_XLAT_TABLES */
+
 /*
  * If dynamic allocation of new regions is disabled then by the time we call the
  * function enabling the MMU, we'll have registered all the memory regions to
diff --git a/make_helpers/build_macros.mk b/make_helpers/build_macros.mk
index b6925d3..20a36fe 100644
--- a/make_helpers/build_macros.mk
+++ b/make_helpers/build_macros.mk
@@ -79,36 +79,52 @@
 endef
 
 # IMG_LINKERFILE defines the linker script corresponding to a BL stage
-#   $(1) = BL stage (2, 30, 31, 32, 33)
+#   $(1) = BL stage (1, 2, 2u, 31, 32)
 define IMG_LINKERFILE
     ${BUILD_DIR}/bl$(1).ld
 endef
 
 # IMG_MAPFILE defines the output file describing the memory map corresponding
 # to a BL stage
-#   $(1) = BL stage (2, 30, 31, 32, 33)
+#   $(1) = BL stage (1, 2, 2u, 31, 32)
 define IMG_MAPFILE
     ${BUILD_DIR}/bl$(1).map
 endef
 
 # IMG_ELF defines the elf file corresponding to a BL stage
-#   $(1) = BL stage (2, 30, 31, 32, 33)
+#   $(1) = BL stage (1, 2, 2u, 31, 32)
 define IMG_ELF
     ${BUILD_DIR}/bl$(1).elf
 endef
 
 # IMG_DUMP defines the symbols dump file corresponding to a BL stage
-#   $(1) = BL stage (2, 30, 31, 32, 33)
+#   $(1) = BL stage (1, 2, 2u, 31, 32)
 define IMG_DUMP
     ${BUILD_DIR}/bl$(1).dump
 endef
 
 # IMG_BIN defines the default image file corresponding to a BL stage
-#   $(1) = BL stage (2, 30, 31, 32, 33)
+#   $(1) = BL stage (1, 2, 2u, 31, 32)
 define IMG_BIN
     ${BUILD_PLAT}/bl$(1).bin
 endef
 
+# IMG_ENC_BIN defines the default encrypted image file corresponding to a
+# BL stage
+#   $(1) = BL stage (2, 30, 31, 32, 33)
+define IMG_ENC_BIN
+    ${BUILD_PLAT}/bl$(1)_enc.bin
+endef
+
+# ENCRYPT_FW invokes enctool to encrypt firmware binary
+#   $(1) = input firmware binary
+#   $(2) = output encrypted firmware binary
+define ENCRYPT_FW
+$(2): $(1) enctool
+	$$(ECHO) "  ENC     $$<"
+	$$(Q)$$(ENCTOOL) $$(ENC_ARGS) -i $$< -o $$@
+endef
+
 # TOOL_ADD_PAYLOAD appends the command line arguments required by fiptool to
 # package a new payload and/or by cert_create to generate certificate.
 # Optionally, it adds the dependency on this payload
@@ -116,11 +132,17 @@
 #   $(2) = command line option for the specified payload (i.e. --soc-fw)
 #   $(3) = tool target dependency (optional) (ex. build/fvp/release/bl31.bin)
 #   $(4) = FIP prefix (optional) (if FWU_, target is fwu_fip instead of fip)
+#   $(5) = encrypted payload (optional) (ex. build/fvp/release/bl31_enc.bin)
 define TOOL_ADD_PAYLOAD
+ifneq ($(5),)
+    $(4)FIP_ARGS += $(2) $(5)
+    $(if $(3),$(4)CRT_DEPS += $(1))
+else
     $(4)FIP_ARGS += $(2) $(1)
+    $(if $(3),$(4)CRT_DEPS += $(3))
+endif
     $(if $(3),$(4)FIP_DEPS += $(3))
     $(4)CRT_ARGS += $(2) $(1)
-    $(if $(3),$(4)CRT_DEPS += $(3))
 endef
 
 # TOOL_ADD_IMG_PAYLOAD works like TOOL_ADD_PAYLOAD, but applies image filters
@@ -130,6 +152,7 @@
 #   $(3) = command line option for the specified payload (ex. --soc-fw)
 #   $(4) = tool target dependency (optional) (ex. build/fvp/release/bl31.bin)
 #   $(5) = FIP prefix (optional) (if FWU_, target is fwu_fip instead of fip)
+#   $(6) = encrypted payload (optional) (ex. build/fvp/release/bl31_enc.bin)
 
 define TOOL_ADD_IMG_PAYLOAD
 
@@ -143,10 +166,10 @@
 
 $(PROCESSED_PATH): $(4)
 
-$(call TOOL_ADD_PAYLOAD,$(PROCESSED_PATH),$(3),$(PROCESSED_PATH),$(5))
+$(call TOOL_ADD_PAYLOAD,$(PROCESSED_PATH),$(3),$(PROCESSED_PATH),$(5),$(6))
 
 else
-$(call TOOL_ADD_PAYLOAD,$(2),$(3),$(4),$(5))
+$(call TOOL_ADD_PAYLOAD,$(2),$(3),$(4),$(5),$(6))
 endif
 endef
 
@@ -164,6 +187,7 @@
 #   $(1) = image_type (scp_bl2, bl33, etc.)
 #   $(2) = command line option for fiptool (--scp-fw, --nt-fw, etc)
 #   $(3) = FIP prefix (optional) (if FWU_, target is fwu_fip instead of fip)
+#   $(4) = Image encryption flag (optional) (0, 1)
 # Example:
 #   $(eval $(call TOOL_ADD_IMG,bl33,--nt-fw))
 define TOOL_ADD_IMG
@@ -173,7 +197,14 @@
 
     $(3)CRT_DEPS += check_$(1)
     $(3)FIP_DEPS += check_$(1)
+ifeq ($(4),1)
+    $(eval ENC_BIN := ${BUILD_PLAT}/$(1)_enc.bin)
+    $(call ENCRYPT_FW,$(value $(_V)),$(ENC_BIN))
+    $(call TOOL_ADD_IMG_PAYLOAD,$(1),$(value $(_V)),$(2),$(ENC_BIN),$(3), \
+		$(ENC_BIN))
+else
     $(call TOOL_ADD_IMG_PAYLOAD,$(1),$(value $(_V)),$(2),,$(3))
+endif
 
 .PHONY: check_$(1)
 check_$(1):
@@ -237,7 +268,7 @@
 # MAKE_C builds a C source file and generates the dependency file
 #   $(1) = output directory
 #   $(2) = source file (%.c)
-#   $(3) = BL stage (2, 2u, 30, 31, 32, 33)
+#   $(3) = BL stage (1, 2, 2u, 31, 32)
 define MAKE_C
 
 $(eval OBJ := $(1)/$(patsubst %.c,%.o,$(notdir $(2))))
@@ -257,7 +288,7 @@
 # MAKE_S builds an assembly source file and generates the dependency file
 #   $(1) = output directory
 #   $(2) = assembly file (%.S)
-#   $(3) = BL stage (2, 2u, 30, 31, 32, 33)
+#   $(3) = BL stage (1, 2, 2u, 31, 32)
 define MAKE_S
 
 $(eval OBJ := $(1)/$(patsubst %.S,%.o,$(notdir $(2))))
@@ -276,7 +307,7 @@
 # MAKE_LD generate the linker script using the C preprocessor
 #   $(1) = output linker script
 #   $(2) = input template
-#   $(3) = BL stage (2, 2u, 30, 31, 32, 33)
+#   $(3) = BL stage (1, 2, 2u, 31, 32)
 define MAKE_LD
 
 $(eval DEP := $(1).d)
@@ -310,7 +341,7 @@
 # MAKE_OBJS builds both C and assembly source files
 #   $(1) = output directory
 #   $(2) = list of source files (both C and assembly)
-#   $(3) = BL stage (2, 30, 31, 32, 33)
+#   $(3) = BL stage (1, 2, 2u, 31, 32)
 define MAKE_OBJS
         $(eval C_OBJS := $(filter %.c,$(2)))
         $(eval REMAIN := $(filter-out %.c,$(2)))
@@ -387,9 +418,10 @@
 
 # MAKE_BL macro defines the targets and options to build each BL image.
 # Arguments:
-#   $(1) = BL stage (2, 2u, 30, 31, 32, 33)
+#   $(1) = BL stage (1, 2, 2u, 31, 32)
 #   $(2) = FIP command line option (if empty, image will not be included in the FIP)
 #   $(3) = FIP prefix (optional) (if FWU_, target is fwu_fip instead of fip)
+#   $(4) = BL encryption flag (optional) (0, 1)
 define MAKE_BL
         $(eval BUILD_DIR  := ${BUILD_PLAT}/bl$(1))
         $(eval BL_SOURCES := $(BL$(call uppercase,$(1))_SOURCES))
@@ -400,6 +432,7 @@
         $(eval ELF        := $(call IMG_ELF,$(1)))
         $(eval DUMP       := $(call IMG_DUMP,$(1)))
         $(eval BIN        := $(call IMG_BIN,$(1)))
+        $(eval ENC_BIN    := $(call IMG_ENC_BIN,$(1)))
         $(eval BL_LINKERFILE := $(BL$(call uppercase,$(1))_LINKERFILE))
         $(eval BL_LIBS    := $(BL$(call uppercase,$(1))_LIBS))
         # We use sort only to get a list of unique object directory names.
@@ -480,7 +513,13 @@
 
 all: bl$(1)
 
+ifeq ($(4),1)
+$(call ENCRYPT_FW,$(BIN),$(ENC_BIN))
+$(if $(2),$(call TOOL_ADD_IMG_PAYLOAD,bl$(1),$(BIN),--$(2),$(ENC_BIN),$(3), \
+		$(ENC_BIN)))
+else
 $(if $(2),$(call TOOL_ADD_IMG_PAYLOAD,bl$(1),$(BIN),--$(2),$(BIN),$(3)))
+endif
 
 endef
 
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index e8e990d..03322db 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -65,6 +65,9 @@
 # Debug build
 DEBUG				:= 0
 
+# By default disable authenticated decryption support.
+DECRYPTION_SUPPORT		:= none
+
 # Build platform
 DEFAULT_PLAT			:= fvp
 
@@ -106,6 +109,18 @@
 # Use BRANCH_PROTECTION to enable PAUTH.
 ENABLE_PAUTH			:= 0
 
+# By default BL31 encryption disabled
+ENCRYPT_BL31			:= 0
+
+# By default BL32 encryption disabled
+ENCRYPT_BL32			:= 0
+
+# Default dummy firmware encryption key
+ENC_KEY	:= 1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef
+
+# Default dummy nonce for firmware encryption
+ENC_NONCE			:= 1234567890abcdef12345678
+
 # Build flag to treat usage of deprecated platform and framework APIs as error.
 ERROR_DEPRECATED		:= 0
 
@@ -121,6 +136,9 @@
 # Default FWU_FIP file name
 FWU_FIP_NAME			:= fwu_fip.bin
 
+# By default firmware encryption with SSK
+FW_ENC_STATUS			:= 0
+
 # For Chain of Trust
 GENERATE_COT			:= 0
 
@@ -188,6 +206,9 @@
 # Enable the Management Mode (MM)-based Secure Partition Manager implementation
 SPM_MM				:= 0
 
+# Use SPM at S-EL2 as a default config for SPMD
+SPMD_SPM_AT_SEL2		:= 1
+
 # Flag to introduce an infinite loop in BL1 just before it exits into the next
 # image. This is meant to help debugging the post-BL2 phase.
 SPIN_ON_BL1_EXIT		:= 0
@@ -207,6 +228,13 @@
 # Build option to choose whether Trusted Firmware uses library at ROM
 USE_ROMLIB			:= 0
 
+# Build option to choose whether the xlat tables of BL images can be read-only.
+# Note that this only serves as a higher level option to PLAT_RO_XLAT_TABLES,
+# which is the per BL-image option that actually enables the read-only tables
+# API. The reason for having this additional option is to have a common high
+# level makefile where we can check for incompatible features/build options.
+ALLOW_RO_XLAT_TABLES		:= 0
+
 # Chain of trust.
 COT				:= tbbr
 
@@ -255,3 +283,8 @@
 
 # Enable Link Time Optimization
 ENABLE_LTO			:= 0
+
+# Build flag to include EL2 registers in cpu context save and restore during
+# S-EL2 firmware entry/exit. This flag is to be used with SPD=spmd option.
+# Default is 0.
+CTX_INCLUDE_EL2_REGS		:= 0
diff --git a/plat/allwinner/common/allwinner-common.mk b/plat/allwinner/common/allwinner-common.mk
index 98bcf3e..e60ebc6 100644
--- a/plat/allwinner/common/allwinner-common.mk
+++ b/plat/allwinner/common/allwinner-common.mk
@@ -20,6 +20,8 @@
 				${AW_PLAT}/common/sunxi_common.c
 
 BL31_SOURCES		+=	drivers/allwinner/axp/common.c		\
+				drivers/allwinner/sunxi_msgbox.c	\
+				drivers/arm/css/scpi/css_scpi.c		\
 				drivers/arm/gic/common/gic_common.c	\
 				drivers/arm/gic/v2/gicv2_helpers.c	\
 				drivers/arm/gic/v2/gicv2_main.c		\
diff --git a/plat/allwinner/common/include/platform_def.h b/plat/allwinner/common/include/platform_def.h
index 32a7c04..975cc48 100644
--- a/plat/allwinner/common/include/platform_def.h
+++ b/plat/allwinner/common/include/platform_def.h
@@ -13,8 +13,13 @@
 
 #include <sunxi_mmap.h>
 
-#define BL31_BASE			SUNXI_SRAM_A2_BASE
-#define BL31_LIMIT			(SUNXI_SRAM_A2_BASE + SUNXI_SRAM_A2_SIZE)
+#define BL31_BASE			(SUNXI_SRAM_A2_BASE + 0x4000)
+#define BL31_LIMIT			(SUNXI_SRAM_A2_BASE + \
+					 SUNXI_SRAM_A2_SIZE - SUNXI_SCP_SIZE)
+
+/* The SCP firmware is allocated the last 16KiB of SRAM A2. */
+#define SUNXI_SCP_BASE			BL31_LIMIT
+#define SUNXI_SCP_SIZE			0x4000
 
 /* Overwrite U-Boot SPL, but reserve the first page for the SPL header. */
 #define BL31_NOBITS_BASE		(SUNXI_SRAM_A1_BASE + 0x1000)
@@ -35,6 +40,9 @@
 #define MAX_MMAP_REGIONS		(3 + PLATFORM_MMAP_REGIONS)
 #define MAX_XLAT_TABLES			1
 
+#define PLAT_CSS_SCP_COM_SHARED_MEM_BASE \
+	(SUNXI_SRAM_A2_BASE + SUNXI_SRAM_A2_SIZE - 0x200)
+
 #define PLAT_MAX_PWR_LVL_STATES		U(2)
 #define PLAT_MAX_RET_STATE		U(1)
 #define PLAT_MAX_OFF_STATE		U(2)
@@ -51,7 +59,7 @@
 #define PLATFORM_CORE_COUNT		(PLATFORM_CLUSTER_COUNT * \
 					 PLATFORM_MAX_CPUS_PER_CLUSTER)
 #define PLATFORM_MAX_CPUS_PER_CLUSTER	U(4)
-#define PLATFORM_MMAP_REGIONS		4
+#define PLATFORM_MMAP_REGIONS		5
 #define PLATFORM_STACK_SIZE		(0x1000 / PLATFORM_CORE_COUNT)
 
 #ifndef SPD_none
diff --git a/plat/allwinner/common/sunxi_bl31_setup.c b/plat/allwinner/common/sunxi_bl31_setup.c
index a24527c..e836a34 100644
--- a/plat/allwinner/common/sunxi_bl31_setup.c
+++ b/plat/allwinner/common/sunxi_bl31_setup.c
@@ -28,7 +28,7 @@
 static entry_point_info_t bl32_image_ep_info;
 static entry_point_info_t bl33_image_ep_info;
 
-static console_16550_t console;
+static console_t console;
 
 static const gicv2_driver_data_t sunxi_gic_data = {
 	.gicd_base = SUNXI_GICD_BASE,
diff --git a/plat/allwinner/common/sunxi_common.c b/plat/allwinner/common/sunxi_common.c
index 3759c28..0ca18ad 100644
--- a/plat/allwinner/common/sunxi_common.c
+++ b/plat/allwinner/common/sunxi_common.c
@@ -21,6 +21,8 @@
 static const mmap_region_t sunxi_mmap[PLATFORM_MMAP_REGIONS + 1] = {
 	MAP_REGION_FLAT(SUNXI_SRAM_BASE, SUNXI_SRAM_SIZE,
 			MT_RW_DATA | MT_SECURE),
+	MAP_REGION_FLAT(SUNXI_SCP_BASE, SUNXI_SCP_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE | MT_EXECUTE_NEVER),
 	MAP_REGION_FLAT(SUNXI_DEV_BASE, SUNXI_DEV_SIZE,
 			MT_DEVICE | MT_RW | MT_SECURE | MT_EXECUTE_NEVER),
 	MAP_REGION(SUNXI_DRAM_BASE, SUNXI_DRAM_VIRT_BASE, SUNXI_DRAM_SEC_SIZE,
@@ -175,7 +177,7 @@
  */
 void sunxi_execute_arisc_code(uint32_t *code, size_t size, uint16_t param)
 {
-	uintptr_t arisc_reset_vec = SUNXI_SRAM_A2_BASE - 0x4000 + 0x100;
+	uintptr_t arisc_reset_vec = SUNXI_SRAM_A2_BASE + 0x100;
 
 	do {
 		bakery_lock_get(&arisc_lock);
diff --git a/plat/allwinner/common/sunxi_pm.c b/plat/allwinner/common/sunxi_pm.c
index 9b074d2..e0fa5b3 100644
--- a/plat/allwinner/common/sunxi_pm.c
+++ b/plat/allwinner/common/sunxi_pm.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -10,6 +10,7 @@
 
 #include <arch_helpers.h>
 #include <common/debug.h>
+#include <drivers/arm/css/css_scpi.h>
 #include <drivers/arm/gicv2.h>
 #include <drivers/delay_timer.h>
 #include <lib/mmio.h>
@@ -17,6 +18,7 @@
 #include <plat/common/platform.h>
 
 #include <sunxi_cpucfg.h>
+#include <sunxi_def.h>
 #include <sunxi_mmap.h>
 #include <sunxi_private.h>
 
@@ -24,25 +26,88 @@
 #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 && \
-	MPIDR_AFFLVL2_VAL(mpidr) == 0 && \
-	MPIDR_AFFLVL1_VAL(mpidr) < PLATFORM_CLUSTER_COUNT && \
-	MPIDR_AFFLVL0_VAL(mpidr) < PLATFORM_MAX_CPUS_PER_CLUSTER)
+#define CPU_PWR_LVL			MPIDR_AFFLVL0
+#define CLUSTER_PWR_LVL			MPIDR_AFFLVL1
+#define SYSTEM_PWR_LVL			MPIDR_AFFLVL2
+
+#define CPU_PWR_STATE(state) \
+	((state)->pwr_domain_state[CPU_PWR_LVL])
+#define CLUSTER_PWR_STATE(state) \
+	((state)->pwr_domain_state[CLUSTER_PWR_LVL])
+#define SYSTEM_PWR_STATE(state) \
+	((state)->pwr_domain_state[SYSTEM_PWR_LVL])
+
+#define mpidr_is_valid(mpidr) (plat_core_pos_by_mpidr(mpidr) >= 0)
+
+/*
+ * The addresses for the SCP exception vectors are defined in the or1k
+ * architecture specification.
+ */
+#define OR1K_VEC_FIRST			0x01
+#define OR1K_VEC_LAST			0x0e
+#define OR1K_VEC_ADDR(n)		(0x100 * (n))
+
+/*
+ * This magic value is the little-endian representation of the or1k
+ * instruction "l.mfspr r2, r0, 0x12", which is guaranteed to be the
+ * first instruction in the SCP firmware.
+ */
+#define SCP_FIRMWARE_MAGIC		0xb4400012
+
+static bool scpi_available;
+
+static inline scpi_power_state_t scpi_map_state(plat_local_state_t psci_state)
+{
+	if (is_local_state_run(psci_state))
+		return scpi_power_on;
+	if (is_local_state_retn(psci_state))
+		return scpi_power_retention;
+	return scpi_power_off;
+}
+
+static void sunxi_cpu_standby(plat_local_state_t cpu_state)
+{
+	u_register_t scr = read_scr_el3();
+
+	assert(is_local_state_retn(cpu_state));
+
+	write_scr_el3(scr | SCR_IRQ_BIT);
+	wfi();
+	write_scr_el3(scr);
+}
 
 static int sunxi_pwr_domain_on(u_register_t mpidr)
 {
 	if (mpidr_is_valid(mpidr) == 0)
 		return PSCI_E_INTERN_FAIL;
 
-	sunxi_cpu_on(mpidr);
+	if (scpi_available) {
+		scpi_set_css_power_state(mpidr,
+					 scpi_power_on,
+					 scpi_power_on,
+					 scpi_power_on);
+	} else {
+		sunxi_cpu_on(mpidr);
+	}
 
 	return PSCI_E_SUCCESS;
 }
 
 static void sunxi_pwr_domain_off(const psci_power_state_t *target_state)
 {
-	gicv2_cpuif_disable();
+	plat_local_state_t cpu_pwr_state     = CPU_PWR_STATE(target_state);
+	plat_local_state_t cluster_pwr_state = CLUSTER_PWR_STATE(target_state);
+	plat_local_state_t system_pwr_state  = SYSTEM_PWR_STATE(target_state);
+
+	if (is_local_state_off(cpu_pwr_state))
+		gicv2_cpuif_disable();
+
+	if (scpi_available) {
+		scpi_set_css_power_state(read_mpidr(),
+					 scpi_map_state(cpu_pwr_state),
+					 scpi_map_state(cluster_pwr_state),
+					 scpi_map_state(system_pwr_state));
+	}
 }
 
 static void __dead2 sunxi_pwr_down_wfi(const psci_power_state_t *target_state)
@@ -55,12 +120,26 @@
 
 static void sunxi_pwr_domain_on_finish(const psci_power_state_t *target_state)
 {
-	gicv2_pcpu_distif_init();
-	gicv2_cpuif_enable();
+	if (is_local_state_off(SYSTEM_PWR_STATE(target_state)))
+		gicv2_distif_init();
+	if (is_local_state_off(CPU_PWR_STATE(target_state))) {
+		gicv2_pcpu_distif_init();
+		gicv2_cpuif_enable();
+	}
 }
 
 static void __dead2 sunxi_system_off(void)
 {
+	gicv2_cpuif_disable();
+
+	if (scpi_available) {
+		/* Send the power down request to the SCP */
+		uint32_t ret = scpi_sys_power_state(scpi_system_shutdown);
+
+		if (ret != SCP_OK)
+			ERROR("PSCI: SCPI %s failed: %d\n", "shutdown", ret);
+	}
+
 	/* Turn off all secondary CPUs */
 	sunxi_disable_secondary_cpus(read_mpidr());
 
@@ -74,6 +153,16 @@
 
 static void __dead2 sunxi_system_reset(void)
 {
+	gicv2_cpuif_disable();
+
+	if (scpi_available) {
+		/* Send the system reset request to the SCP */
+		uint32_t ret = scpi_sys_power_state(scpi_system_reboot);
+
+		if (ret != SCP_OK)
+			ERROR("PSCI: SCPI %s failed: %d\n", "reboot", ret);
+	}
+
 	/* Reset the whole system when the watchdog times out */
 	mmio_write_32(SUNXI_WDOG0_CFG_REG, 1);
 	/* Enable the watchdog with the shortest timeout (0.5 seconds) */
@@ -86,6 +175,40 @@
 	panic();
 }
 
+static int sunxi_validate_power_state(unsigned int power_state,
+				      psci_power_state_t *req_state)
+{
+	unsigned int power_level = psci_get_pstate_pwrlvl(power_state);
+	unsigned int type = psci_get_pstate_type(power_state);
+
+	assert(req_state != NULL);
+
+	if (power_level > PLAT_MAX_PWR_LVL)
+		return PSCI_E_INVALID_PARAMS;
+
+	if (type == PSTATE_TYPE_STANDBY) {
+		/* Only one retention power state is supported. */
+		if (psci_get_pstate_id(power_state) > 0)
+			return PSCI_E_INVALID_PARAMS;
+		/* The SoC cannot be suspended without losing state */
+		if (power_level == SYSTEM_PWR_LVL)
+			return PSCI_E_INVALID_PARAMS;
+		for (unsigned int i = 0; i <= power_level; ++i)
+			req_state->pwr_domain_state[i] = PLAT_MAX_RET_STATE;
+	} else {
+		/* Only one off power state is supported. */
+		if (psci_get_pstate_id(power_state) > 0)
+			return PSCI_E_INVALID_PARAMS;
+		for (unsigned int i = 0; i <= power_level; ++i)
+			req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
+	}
+	/* Higher power domain levels should all remain running */
+	for (unsigned int i = power_level + 1; i <= PLAT_MAX_PWR_LVL; ++i)
+		req_state->pwr_domain_state[i] = PSCI_LOCAL_STATE_RUN;
+
+	return PSCI_E_SUCCESS;
+}
+
 static int sunxi_validate_ns_entrypoint(uintptr_t ns_entrypoint)
 {
 	/* The non-secure entry point must be in DRAM */
@@ -95,13 +218,45 @@
 	return PSCI_E_INVALID_ADDRESS;
 }
 
+static void sunxi_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+	assert(req_state);
+
+	for (unsigned int i = 0; i <= PLAT_MAX_PWR_LVL; ++i)
+		req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
+}
+
+static int sunxi_get_node_hw_state(u_register_t mpidr,
+				   unsigned int power_level)
+{
+	unsigned int cluster_state, cpu_state;
+	unsigned int cpu = MPIDR_AFFLVL0_VAL(mpidr);
+
+	/* SoC power level (always on if PSCI works). */
+	if (power_level == SYSTEM_PWR_LVL)
+		return HW_ON;
+	if (scpi_get_css_power_state(mpidr, &cpu_state, &cluster_state))
+		return PSCI_E_NOT_SUPPORTED;
+	/* Cluster power level (full power state available). */
+	if (power_level == CLUSTER_PWR_LVL) {
+		if (cluster_state == scpi_power_on)
+			return HW_ON;
+		if (cluster_state == scpi_power_retention)
+			return HW_STANDBY;
+		return HW_OFF;
+	}
+	/* CPU power level (one bit boolean for on or off). */
+	return ((cpu_state & BIT(cpu)) != 0) ? HW_ON : HW_OFF;
+}
+
 static plat_psci_ops_t sunxi_psci_ops = {
+	.cpu_standby			= sunxi_cpu_standby,
 	.pwr_domain_on			= sunxi_pwr_domain_on,
 	.pwr_domain_off			= sunxi_pwr_domain_off,
-	.pwr_domain_pwr_down_wfi	= sunxi_pwr_down_wfi,
 	.pwr_domain_on_finish		= sunxi_pwr_domain_on_finish,
 	.system_off			= sunxi_system_off,
 	.system_reset			= sunxi_system_reset,
+	.validate_power_state		= sunxi_validate_power_state,
 	.validate_ns_entrypoint		= sunxi_validate_ns_entrypoint,
 };
 
@@ -110,13 +265,44 @@
 {
 	assert(psci_ops);
 
-	for (int cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu += 1) {
+	/* Program all CPU entry points. */
+	for (unsigned int cpu = 0; cpu < PLATFORM_CORE_COUNT; ++cpu) {
 		mmio_write_32(SUNXI_CPUCFG_RVBAR_LO_REG(cpu),
 			      sec_entrypoint & 0xffffffff);
 		mmio_write_32(SUNXI_CPUCFG_RVBAR_HI_REG(cpu),
 			      sec_entrypoint >> 32);
 	}
 
+	/* Check for a valid SCP firmware, and boot the SCP if found. */
+	if (mmio_read_32(SUNXI_SCP_BASE) == SCP_FIRMWARE_MAGIC) {
+		/* Program SCP exception vectors to the firmware entrypoint. */
+		for (unsigned int i = OR1K_VEC_FIRST; i <= OR1K_VEC_LAST; ++i) {
+			uint32_t vector = SUNXI_SRAM_A2_BASE + OR1K_VEC_ADDR(i);
+			uint32_t offset = SUNXI_SCP_BASE - vector;
+
+			mmio_write_32(vector, offset >> 2);
+			clean_dcache_range(vector, sizeof(uint32_t));
+		}
+		/* Take the SCP out of reset. */
+		mmio_setbits_32(SUNXI_R_CPUCFG_BASE, BIT(0));
+		/* Wait for the SCP firmware to boot. */
+		if (scpi_wait_ready() == 0)
+			scpi_available = true;
+	}
+
+	NOTICE("PSCI: System suspend is %s\n",
+	       scpi_available ? "available via SCPI" : "unavailable");
+	if (scpi_available) {
+		/* Suspend is only available via SCPI. */
+		sunxi_psci_ops.pwr_domain_suspend = sunxi_pwr_domain_off;
+		sunxi_psci_ops.pwr_domain_suspend_finish = sunxi_pwr_domain_on_finish;
+		sunxi_psci_ops.get_sys_suspend_power_state = sunxi_get_sys_suspend_power_state;
+		sunxi_psci_ops.get_node_hw_state = sunxi_get_node_hw_state;
+	} else {
+		/* This is only needed when SCPI is unavailable. */
+		sunxi_psci_ops.pwr_domain_pwr_down_wfi = sunxi_pwr_down_wfi;
+	}
+
 	*psci_ops = &sunxi_psci_ops;
 
 	return 0;
diff --git a/plat/allwinner/sun50i_a64/include/sunxi_mmap.h b/plat/allwinner/sun50i_a64/include/sunxi_mmap.h
index db44091..9d2542f 100644
--- a/plat/allwinner/sun50i_a64/include/sunxi_mmap.h
+++ b/plat/allwinner/sun50i_a64/include/sunxi_mmap.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
  */
@@ -14,8 +14,8 @@
 #define SUNXI_SRAM_SIZE			0x00044000
 #define SUNXI_SRAM_A1_BASE		0x00010000
 #define SUNXI_SRAM_A1_SIZE		0x00008000
-#define SUNXI_SRAM_A2_BASE		0x00044000
-#define SUNXI_SRAM_A2_SIZE		0x00010000
+#define SUNXI_SRAM_A2_BASE		0x00040000
+#define SUNXI_SRAM_A2_SIZE		0x00014000
 #define SUNXI_SRAM_C_BASE		0x00018000
 #define SUNXI_SRAM_C_SIZE		0x0001c000
 #define SUNXI_DEV_BASE			0x01000000
diff --git a/plat/allwinner/sun50i_h6/include/sunxi_mmap.h b/plat/allwinner/sun50i_h6/include/sunxi_mmap.h
index f36491a..0e204d0 100644
--- a/plat/allwinner/sun50i_h6/include/sunxi_mmap.h
+++ b/plat/allwinner/sun50i_h6/include/sunxi_mmap.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
  */
@@ -14,8 +14,8 @@
 #define SUNXI_SRAM_SIZE			0x000f8000
 #define SUNXI_SRAM_A1_BASE		0x00020000
 #define SUNXI_SRAM_A1_SIZE		0x00008000
-#define SUNXI_SRAM_A2_BASE		0x00104000
-#define SUNXI_SRAM_A2_SIZE		0x00014000
+#define SUNXI_SRAM_A2_BASE		0x00100000
+#define SUNXI_SRAM_A2_SIZE		0x00018000
 #define SUNXI_SRAM_C_BASE		0x00028000
 #define SUNXI_SRAM_C_SIZE		0x0001e000
 #define SUNXI_DEV_BASE			0x01000000
diff --git a/plat/amlogic/common/aml_console.c b/plat/amlogic/common/aml_console.c
index 352279b..e21d707 100644
--- a/plat/amlogic/common/aml_console.c
+++ b/plat/amlogic/common/aml_console.c
@@ -11,7 +11,7 @@
 /*******************************************************************************
  * Function that sets up the console
  ******************************************************************************/
-static console_meson_t aml_console;
+static console_t aml_console;
 
 void aml_console_init(void)
 {
@@ -28,6 +28,6 @@
 		panic();
 	}
 
-	console_set_scope(&aml_console.console,
+	console_set_scope(&aml_console,
 			  CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME);
 }
diff --git a/plat/arm/board/fvp/fdts/fvp_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_fw_config.dts
index d0f6033..9a4a057 100644
--- a/plat/arm/board/fvp/fdts/fvp_fw_config.dts
+++ b/plat/arm/board/fvp/fdts/fvp_fw_config.dts
@@ -69,6 +69,12 @@
 		mbedtls_heap_size = <0x0>;
 	};
 
+	/*
+	 * Though TF-A is UUID RFC 4122 compliant meaning fields are stored in
+	 * network order (big endian), UUID's mentioned in this file are are
+	 * stored in machine order (little endian).
+	 * This will be fixed in future.
+	 */
 	arm-io_policies {
 		fip-handles {
 			compatible = "arm,io-fip-handle";
@@ -93,4 +99,17 @@
 			nt_fw_content_cert_uuid = <0xf3c1c48e 0x11e4635d 0xee87a9a7 0xa73fb240>;
 		};
 	};
+
+	secure-partitions {
+		compatible = "arm,sp";
+		cactus {
+			uuid = <0x1e67b5b4 0xe14f904a 0x13fb1fb8 0xcbdae1da>;
+			load-address = <0x7000000>;
+		};
+
+		ivy {
+			uuid = <0x092358d1 0xb94723f0 0x64447c82 0xc88f57f5>;
+			load-address = <0x7100000>;
+		};
+	};
 };
diff --git a/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts b/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
index e1c106f..c94a209 100644
--- a/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
+++ b/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
@@ -11,7 +11,6 @@
 	attribute {
 		maj_ver = <0x0>;
 		min_ver = <0x9>;
-		runtime_el = <0x1>;
 		exec_state = <0x0>;
 		load_address = <0x0 0x6000000>;
 		entrypoint = <0x0 0x6000000>;
diff --git a/plat/arm/board/fvp/fvp_def.h b/plat/arm/board/fvp/fvp_def.h
index 347ba2e..909b687 100644
--- a/plat/arm/board/fvp/fvp_def.h
+++ b/plat/arm/board/fvp/fvp_def.h
@@ -52,8 +52,10 @@
 #define DEVICE1_BASE			UL(0x2e000000)
 #define DEVICE1_SIZE			UL(0x1A00000)
 #else
-#define DEVICE1_BASE			UL(0x2f000000)
-#define DEVICE1_SIZE			UL(0x200000)
+/* GICv2 and GICv3 mapping: GICD + CORE_COUNT * 128KB */
+#define DEVICE1_BASE			BASE_GICD_BASE
+#define DEVICE1_SIZE			((BASE_GICR_BASE - BASE_GICD_BASE) + \
+					 (PLATFORM_CORE_COUNT * 0x20000))
 #define NSRAM_BASE			UL(0x2e000000)
 #define NSRAM_SIZE			UL(0x10000)
 #endif
@@ -110,7 +112,7 @@
 #define FVP_SP810_CTRL_TIM3_OV		BIT_32(22)
 
 /*******************************************************************************
- * GIC-400 & interrupt handling related constants
+ * GIC & interrupt handling related constants
  ******************************************************************************/
 /* VE compatible GIC memory map */
 #define VE_GICD_BASE			UL(0x2c001000)
@@ -128,7 +130,6 @@
 #define FVP_IRQ_TZ_WDOG			56
 #define FVP_IRQ_SEC_SYS_TIMER		57
 
-
 /*******************************************************************************
  * TrustZone address space controller related constants
  ******************************************************************************/
diff --git a/plat/arm/board/fvp/fvp_security.c b/plat/arm/board/fvp/fvp_security.c
index 80ec217..937f09f 100644
--- a/plat/arm/board/fvp/fvp_security.c
+++ b/plat/arm/board/fvp/fvp_security.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -22,5 +22,5 @@
 	 */
 
 	if ((get_arm_config()->flags & ARM_CONFIG_HAS_TZC) != 0U)
-		arm_tzc400_setup(NULL);
+		arm_tzc400_setup(PLAT_ARM_TZC_BASE, NULL);
 }
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 4176968..05c11ce 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -292,7 +292,7 @@
     ifeq (${RESET_TO_SP_MIN},1)
         BL32_CFLAGS	+=	-DPLAT_XLAT_TABLES_DYNAMIC=1
     endif
-else # if AArch64
+else # AArch64
     ifeq (${RESET_TO_BL31},1)
         BL31_CFLAGS	+=	-DPLAT_XLAT_TABLES_DYNAMIC=1
     endif
@@ -301,6 +301,17 @@
     endif
 endif
 
+ifeq (${ALLOW_RO_XLAT_TABLES}, 1)
+    ifeq (${ARCH},aarch32)
+        BL32_CFLAGS	+=	-DPLAT_RO_XLAT_TABLES=1
+    else # AArch64
+        BL31_CFLAGS	+=	-DPLAT_RO_XLAT_TABLES=1
+        ifeq (${SPD},tspd)
+            BL32_CFLAGS	+=	-DPLAT_RO_XLAT_TABLES=1
+        endif
+    endif
+endif
+
 ifeq (${USE_DEBUGFS},1)
     BL31_CFLAGS	+=	-DPLAT_XLAT_TABLES_DYNAMIC=1
 endif
diff --git a/plat/arm/board/juno/include/platform_def.h b/plat/arm/board/juno/include/platform_def.h
index eddd7e5..cfac801 100644
--- a/plat/arm/board/juno/include/platform_def.h
+++ b/plat/arm/board/juno/include/platform_def.h
@@ -50,6 +50,9 @@
 #define NSRAM_BASE			UL(0x2e000000)
 #define NSRAM_SIZE			UL(0x00008000)	/* 32KB */
 
+#define PLAT_ARM_DRAM2_BASE		ULL(0x880000000)
+#define PLAT_ARM_DRAM2_SIZE		ULL(0x180000000)
+
 /* virtual address used by dynamic mem_protect for chunk_base */
 #define PLAT_ARM_MEM_PROTEC_VA_FRAME	UL(0xc0000000)
 
@@ -212,6 +215,9 @@
 		TZC_REGION_ACCESS_RDWR(TZC400_NSAID_GPU)	|	\
 		TZC_REGION_ACCESS_RDWR(TZC400_NSAID_CORESIGHT))
 
+/* TZC related constants */
+#define PLAT_ARM_TZC_FILTERS		TZC_400_REGION_ATTR_FILTER_BIT_ALL
+
 /*
  * Required ARM CSS based platform porting definitions
  */
diff --git a/plat/arm/board/juno/juno_security.c b/plat/arm/board/juno/juno_security.c
index 32823e0..1e64c02 100644
--- a/plat/arm/board/juno/juno_security.c
+++ b/plat/arm/board/juno/juno_security.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -127,13 +127,13 @@
 	init_debug_cfg();
 	/* Initialize the TrustZone Controller */
 #ifdef JUNO_TZMP1
-	arm_tzc400_setup(juno_tzmp1_tzc_regions);
+	arm_tzc400_setup(PLAT_ARM_TZC_BASE, juno_tzmp1_tzc_regions);
 	INFO("TZC protected shared memory base address for TZMP usecase: %p\n",
 	     (void *)JUNO_AP_TZC_SHARE_DRAM1_BASE);
 	INFO("TZC protected shared memory end address for TZMP usecase: %p\n",
 	     (void *)JUNO_AP_TZC_SHARE_DRAM1_END);
 #else
-	arm_tzc400_setup(NULL);
+	arm_tzc400_setup(PLAT_ARM_TZC_BASE, NULL);
 #endif
 	/* Do ARM CSS internal NIC setup */
 	css_init_nic400();
diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk
index 27650d2..f07c1b1 100644
--- a/plat/arm/board/juno/platform.mk
+++ b/plat/arm/board/juno/platform.mk
@@ -155,6 +155,14 @@
     endif
 endif
 
+ifeq (${ALLOW_RO_XLAT_TABLES}, 1)
+    ifeq (${JUNO_AARCH32_EL3_RUNTIME}, 1)
+        BL32_CFLAGS	+=	-DPLAT_RO_XLAT_TABLES=1
+    else
+        BL31_CFLAGS	+=	-DPLAT_RO_XLAT_TABLES=1
+    endif
+endif
+
 # Add the FDT_SOURCES and options for Dynamic Config
 FDT_SOURCES		+=	plat/arm/board/juno/fdts/${PLAT}_fw_config.dts
 TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
diff --git a/plat/arm/board/rddaniel/include/platform_def.h b/plat/arm/board/rddaniel/include/platform_def.h
index 5163602..790ed69 100644
--- a/plat/arm/board/rddaniel/include/platform_def.h
+++ b/plat/arm/board/rddaniel/include/platform_def.h
@@ -21,6 +21,21 @@
 #define CSS_SYSTEM_PWR_DMN_LVL		ARM_PWR_LVL2
 #define PLAT_MAX_PWR_LVL		ARM_PWR_LVL1
 
+/* TZC Related Constants */
+#define PLAT_ARM_TZC_BASE		UL(0x21830000)
+#define PLAT_ARM_TZC_FILTERS		TZC_400_REGION_ATTR_FILTER_BIT(0)
+
+#define TZC400_OFFSET			UL(0x1000000)
+#define TZC400_COUNT			4
+
+#define TZC400_BASE(n)			(PLAT_ARM_TZC_BASE + \
+					 (n * TZC400_OFFSET))
+
+#define TZC_NSAID_ALL_AP		U(0)
+
+#define PLAT_ARM_TZC_NS_DEV_ACCESS	\
+		(TZC_REGION_ACCESS_RDWR(TZC_NSAID_ALL_AP))
+
 /*
  * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes
  */
diff --git a/plat/arm/board/rddaniel/platform.mk b/plat/arm/board/rddaniel/platform.mk
index c7e3c7d..ca26474 100644
--- a/plat/arm/board/rddaniel/platform.mk
+++ b/plat/arm/board/rddaniel/platform.mk
@@ -18,6 +18,8 @@
 				${RDDANIEL_BASE}/rddaniel_security.c	\
 				${RDDANIEL_BASE}/rddaniel_err.c		\
 				lib/utils/mem_region.c			\
+				drivers/arm/tzc/tzc400.c		\
+				plat/arm/common/arm_tzc400.c		\
 				plat/arm/common/arm_nor_psci_mem_protect.c
 
 BL31_SOURCES		+=	${SGI_CPU_SOURCES}			\
diff --git a/plat/arm/board/rddaniel/rddaniel_security.c b/plat/arm/board/rddaniel/rddaniel_security.c
index 6aa38c8..1247db8 100644
--- a/plat/arm/board/rddaniel/rddaniel_security.c
+++ b/plat/arm/board/rddaniel/rddaniel_security.c
@@ -4,9 +4,19 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <plat/arm/common/plat_arm.h>
 #include <platform_def.h>
 
+static const arm_tzc_regions_info_t tzc_regions[] = {
+	ARM_TZC_REGIONS_DEF,
+	{}
+};
+
 /* Initialize the secure environment */
 void plat_arm_security_setup(void)
 {
+	int i;
+
+	for (i = 0; i < TZC400_COUNT; i++)
+		arm_tzc400_setup(TZC400_BASE(i), tzc_regions);
 }
diff --git a/plat/arm/board/sgm775/include/platform_def.h b/plat/arm/board/sgm775/include/platform_def.h
index d165ff9..e83cd57 100644
--- a/plat/arm/board/sgm775/include/platform_def.h
+++ b/plat/arm/board/sgm775/include/platform_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -12,6 +12,9 @@
 #define PLAT_MAX_CPUS_PER_CLUSTER	U(8)
 #define PLAT_MAX_PE_PER_CPU		U(1)
 
+#define PLAT_ARM_DRAM2_BASE		ULL(0x880000000)
+#define PLAT_ARM_DRAM2_SIZE		ULL(0x180000000)
+
 /*
  * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes
  */
diff --git a/plat/arm/common/arm_bl2_setup.c b/plat/arm/common/arm_bl2_setup.c
index dd39208..136e65a 100644
--- a/plat/arm/common/arm_bl2_setup.c
+++ b/plat/arm/common/arm_bl2_setup.c
@@ -205,6 +205,13 @@
  ******************************************************************************/
 int arm_bl2_plat_handle_post_image_load(unsigned int image_id)
 {
+#if defined(SPD_spmd)
+	/* For Secure Partitions we don't need post processing */
+	if ((image_id >= (MAX_NUMBER_IDS - MAX_SP_IDS)) &&
+		(image_id < MAX_NUMBER_IDS)) {
+		return 0;
+	}
+#endif
 	return arm_bl2_handle_post_image_load(image_id);
 }
 
diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c
index c135d7f..85535c1 100644
--- a/plat/arm/common/arm_bl31_setup.c
+++ b/plat/arm/common/arm_bl31_setup.c
@@ -256,9 +256,14 @@
 
 	/* Initialize the runtime console */
 	arm_console_runtime_init();
+
 #if RECLAIM_INIT_CODE
 	arm_free_init_memory();
 #endif
+
+#if PLAT_RO_XLAT_TABLES
+	arm_xlat_make_tables_readonly();
+#endif
 }
 
 #if RECLAIM_INIT_CODE
diff --git a/plat/arm/common/arm_common.c b/plat/arm/common/arm_common.c
index d1e9620..d1eee08 100644
--- a/plat/arm/common/arm_common.c
+++ b/plat/arm/common/arm_common.c
@@ -25,6 +25,26 @@
  * conflicts with the definition in plat/common. */
 #pragma weak plat_get_syscnt_freq2
 
+/*******************************************************************************
+ * Changes the memory attributes for the region of mapped memory where the BL
+ * image's translation tables are located such that the tables will have
+ * read-only permissions.
+ ******************************************************************************/
+#if PLAT_RO_XLAT_TABLES
+void arm_xlat_make_tables_readonly(void)
+{
+	int rc = xlat_make_tables_readonly();
+
+	if (rc != 0) {
+		ERROR("Failed to make translation tables read-only at EL%u.\n",
+		      get_current_el());
+		panic();
+	}
+
+	INFO("Translation tables are now read-only at EL%u.\n",
+	     get_current_el());
+}
+#endif
 
 void arm_setup_romlib(void)
 {
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index 3521780..65f6bf3 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -182,6 +182,9 @@
 else
 ARM_IO_SOURCES		+=	plat/arm/common/arm_fconf_io_storage.c		\
 				plat/arm/common/fconf/arm_fconf_io.c
+ifeq (${SPD},spmd)
+ARM_IO_SOURCES		+=	plat/arm/common/fconf/arm_fconf_sp.c
+endif
 endif
 
 BL1_SOURCES		+=	drivers/io/io_fip.c				\
diff --git a/plat/arm/common/arm_console.c b/plat/arm/common/arm_console.c
index 123811d..0cac5d9 100644
--- a/plat/arm/common/arm_console.c
+++ b/plat/arm/common/arm_console.c
@@ -16,8 +16,8 @@
 /*******************************************************************************
  * Functions that set up the console
  ******************************************************************************/
-static console_pl011_t arm_boot_console;
-static console_pl011_t arm_runtime_console;
+static console_t arm_boot_console;
+static console_t arm_runtime_console;
 
 /* Initialize the console to provide early debug support */
 void __init arm_console_boot_init(void)
@@ -35,13 +35,13 @@
 		panic();
 	}
 
-	console_set_scope(&arm_boot_console.console, CONSOLE_FLAG_BOOT);
+	console_set_scope(&arm_boot_console, CONSOLE_FLAG_BOOT);
 }
 
 void arm_console_boot_end(void)
 {
 	(void)console_flush();
-	(void)console_unregister(&arm_boot_console.console);
+	(void)console_unregister(&arm_boot_console);
 }
 
 /* Initialize the runtime console */
@@ -54,7 +54,7 @@
 	if (rc == 0)
 		panic();
 
-	console_set_scope(&arm_runtime_console.console, CONSOLE_FLAG_RUNTIME);
+	console_set_scope(&arm_runtime_console, CONSOLE_FLAG_RUNTIME);
 }
 
 void arm_console_runtime_end(void)
diff --git a/plat/arm/common/arm_dyn_cfg.c b/plat/arm/common/arm_dyn_cfg.c
index 443d40f..df75307 100644
--- a/plat/arm/common/arm_dyn_cfg.c
+++ b/plat/arm/common/arm_dyn_cfg.c
@@ -21,7 +21,6 @@
 #include <lib/fconf/fconf_tbbr_getter.h>
 #include <plat/arm/common/arm_dyn_cfg_helpers.h>
 #include <plat/arm/common/plat_arm.h>
-#include <plat/common/platform.h>
 
 #if TRUSTED_BOARD_BOOT
 
diff --git a/plat/arm/common/arm_fconf_io_storage.c b/plat/arm/common/arm_fconf_io_storage.c
index 341622a..6fcfbd6 100644
--- a/plat/arm/common/arm_fconf_io_storage.c
+++ b/plat/arm/common/arm_fconf_io_storage.c
@@ -12,7 +12,6 @@
 #include <drivers/io/io_memmap.h>
 #include <drivers/io/io_storage.h>
 #include <lib/utils.h>
-#include <tools_share/firmware_image_package.h>
 
 #include <plat/arm/common/arm_fconf_getter.h>
 #include <plat/arm/common/arm_fconf_io_storage.h>
diff --git a/plat/arm/common/arm_image_load.c b/plat/arm/common/arm_image_load.c
index 2faaa76..593199d 100644
--- a/plat/arm/common/arm_image_load.c
+++ b/plat/arm/common/arm_image_load.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -7,6 +7,9 @@
 #include <assert.h>
 #include <common/bl_common.h>
 #include <common/desc_image_load.h>
+#if defined(SPD_spmd)
+#include <plat/arm/common/fconf_arm_sp_getter.h>
+#endif
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
 
@@ -29,12 +32,62 @@
 		next_bl_params_cpy_ptr);
 }
 
+#if defined(SPD_spmd)
+/*******************************************************************************
+ * This function appends Secure Partitions to list of loadable images.
+ ******************************************************************************/
+void plat_add_sp_images_load_info(struct bl_load_info *load_info)
+{
+	bl_load_info_node_t *node_info = load_info->head;
+	unsigned int index = 0;
+
+	if (sp_mem_params_descs[index].image_id == 0) {
+		ERROR("No Secure Partition Image available\n");
+		return;
+	}
+
+	/* Traverse through the bl images list */
+	do {
+		node_info = node_info->next_load_info;
+	} while (node_info->next_load_info != NULL);
+
+	for (; index < MAX_SP_IDS; index++) {
+		/* Populate the image information */
+		node_info->image_id = sp_mem_params_descs[index].image_id;
+		node_info->image_info = &sp_mem_params_descs[index].image_info;
+
+		if ((index + 1U) == MAX_SP_IDS) {
+			INFO("Reached Max number of SPs\n");
+			return;
+		}
+
+		if (sp_mem_params_descs[index + 1U].image_id == 0) {
+			return;
+		}
+
+		node_info->next_load_info =
+			&sp_mem_params_descs[index + 1U].load_node_mem;
+		node_info = node_info->next_load_info;
+
+	}
+}
+#endif
+
 /*******************************************************************************
  * This function returns the list of loadable images.
  ******************************************************************************/
 struct bl_load_info *plat_get_bl_image_load_info(void)
 {
+#if defined(SPD_spmd)
+	bl_load_info_t *bl_load_info;
+
+	bl_load_info = get_bl_load_info_from_mem_params_desc();
+	plat_add_sp_images_load_info(bl_load_info);
+
+	return bl_load_info;
+#else
 	return get_bl_load_info_from_mem_params_desc();
+#endif
 }
 
 /*******************************************************************************
diff --git a/plat/arm/common/arm_tzc400.c b/plat/arm/common/arm_tzc400.c
index 34e650f..370ef0a 100644
--- a/plat/arm/common/arm_tzc400.c
+++ b/plat/arm/common/arm_tzc400.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -19,7 +19,8 @@
  * When booting an EL3 payload, this is simplified: we configure region 0 with
  * secure access only and do not enable any other region.
  ******************************************************************************/
-void arm_tzc400_setup(const arm_tzc_regions_info_t *tzc_regions)
+void arm_tzc400_setup(uintptr_t tzc_base,
+			const arm_tzc_regions_info_t *tzc_regions)
 {
 #ifndef EL3_PAYLOAD_BASE
 	unsigned int region_index = 1U;
@@ -32,7 +33,7 @@
 
 	INFO("Configuring TrustZone Controller\n");
 
-	tzc400_init(PLAT_ARM_TZC_BASE);
+	tzc400_init(tzc_base);
 
 	/* Disable filters. */
 	tzc400_disable_filters();
@@ -74,5 +75,5 @@
 
 void plat_arm_security_setup(void)
 {
-	arm_tzc400_setup(NULL);
+	arm_tzc400_setup(PLAT_ARM_TZC_BASE, NULL);
 }
diff --git a/plat/arm/common/fconf/arm_fconf_io.c b/plat/arm/common/fconf/arm_fconf_io.c
index 3c0586f..cfcddc2 100644
--- a/plat/arm/common/fconf/arm_fconf_io.c
+++ b/plat/arm/common/fconf/arm_fconf_io.c
@@ -59,9 +59,9 @@
 #ifdef IMAGE_BL2
 
 #if TRUSTED_BOARD_BOOT
-#define FCONF_ARM_IO_UUID_NUMBER	19
+#define FCONF_ARM_IO_UUID_NUMBER	U(19)
 #else
-#define FCONF_ARM_IO_UUID_NUMBER	10
+#define FCONF_ARM_IO_UUID_NUMBER	U(10)
 #endif
 
 static io_uuid_spec_t fconf_arm_uuids[FCONF_ARM_IO_UUID_NUMBER];
diff --git a/plat/arm/common/fconf/arm_fconf_sp.c b/plat/arm/common/fconf/arm_fconf_sp.c
new file mode 100644
index 0000000..bb88aff
--- /dev/null
+++ b/plat/arm/common/fconf/arm_fconf_sp.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <common/fdt_wrappers.h>
+#include <drivers/io/io_storage.h>
+#include <lib/object_pool.h>
+#include <libfdt.h>
+#include <plat/arm/common/arm_fconf_getter.h>
+#include <plat/arm/common/arm_fconf_io_storage.h>
+#include <plat/arm/common/fconf_arm_sp_getter.h>
+#include <platform_def.h>
+#include <tools_share/firmware_image_package.h>
+
+#ifdef IMAGE_BL2
+
+bl_mem_params_node_t sp_mem_params_descs[MAX_SP_IDS];
+
+struct arm_sp_t arm_sp;
+
+int fconf_populate_arm_sp(uintptr_t config)
+{
+	int sp_node, node, err;
+	union uuid_helper_t uuid_helper;
+	unsigned int index = 0;
+	const unsigned int sp_start_index = MAX_NUMBER_IDS - MAX_SP_IDS;
+
+	/* As libfdt use void *, we can't avoid this cast */
+	const void *dtb = (void *)config;
+
+	/* Assert the node offset point to "arm,sp" compatible property */
+	const char *compatible_str = "arm,sp";
+
+	node = fdt_node_offset_by_compatible(dtb, -1, compatible_str);
+	if (node < 0) {
+		ERROR("FCONF: Can't find %s in dtb\n", compatible_str);
+		return node;
+	}
+
+	fdt_for_each_subnode(sp_node, dtb, node) {
+		err = fdtw_read_array(dtb, sp_node, "uuid", 4,
+				      &uuid_helper.word);
+		if (err < 0) {
+			ERROR("FCONF: cannot read SP uuid\n");
+			return -1;
+		}
+
+		arm_sp.uuids[index] = uuid_helper;
+
+		err = fdtw_read_cells(dtb, sp_node, "load-address", 1,
+			&arm_sp.load_addr[index]);
+		if (err < 0) {
+			ERROR("FCONF: cannot read SP load address\n");
+			return -1;
+		}
+
+		VERBOSE("FCONF: %s UUID %x-%x-%x-%x load_addr=%lx\n",
+			__func__,
+			uuid_helper.word[0],
+			uuid_helper.word[1],
+			uuid_helper.word[2],
+			uuid_helper.word[3],
+			arm_sp.load_addr[index]);
+
+		/* Add SP information in mem param descriptor */
+		sp_mem_params_descs[index].image_id = sp_start_index + index;
+		SET_PARAM_HEAD(&sp_mem_params_descs[index].image_info,
+					PARAM_IMAGE_BINARY, VERSION_2, 0);
+		sp_mem_params_descs[index].image_info.image_max_size =
+							ARM_SP_MAX_SIZE;
+		sp_mem_params_descs[index].next_handoff_image_id =
+							INVALID_IMAGE_ID;
+		sp_mem_params_descs[index].image_info.image_base =
+							arm_sp.load_addr[index];
+
+		/* Add SP information in IO policies structure */
+		policies[sp_start_index + index].image_spec =
+						(uintptr_t)&arm_sp.uuids[index];
+		policies[sp_start_index + index].dev_handle = &fip_dev_handle;
+		policies[sp_start_index + index].check = open_fip;
+
+		index++;
+
+		if (index >= MAX_SP_IDS) {
+			ERROR("FCONF: reached max number of SPs\n");
+			return -1;
+		}
+	}
+
+	if ((sp_node < 0) && (sp_node != -FDT_ERR_NOTFOUND)) {
+		ERROR("%d: fdt_for_each_subnode(): %d\n", __LINE__, node);
+		return sp_node;
+	}
+
+	arm_sp.number_of_sp = index;
+	return 0;
+}
+
+FCONF_REGISTER_POPULATOR(arm_sp, fconf_populate_arm_sp);
+
+#endif /* IMAGE_BL2 */
diff --git a/plat/arm/common/sp_min/arm_sp_min_setup.c b/plat/arm/common/sp_min/arm_sp_min_setup.c
index 0cc746b..cbbdfa2 100644
--- a/plat/arm/common/sp_min/arm_sp_min_setup.c
+++ b/plat/arm/common/sp_min/arm_sp_min_setup.c
@@ -167,6 +167,10 @@
 {
 	/* Initialize the runtime console */
 	arm_console_runtime_init();
+
+#if PLAT_RO_XLAT_TABLES
+	arm_xlat_make_tables_readonly();
+#endif
 }
 
 /*******************************************************************************
diff --git a/plat/arm/common/tsp/arm_tsp_setup.c b/plat/arm/common/tsp/arm_tsp_setup.c
index aefdf89..a4da8c3 100644
--- a/plat/arm/common/tsp/arm_tsp_setup.c
+++ b/plat/arm/common/tsp/arm_tsp_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -28,7 +28,7 @@
 /*******************************************************************************
  * Initialize the UART
  ******************************************************************************/
-static console_pl011_t arm_tsp_runtime_console;
+static console_t arm_tsp_runtime_console;
 
 void arm_tsp_early_platform_setup(void)
 {
@@ -43,7 +43,7 @@
 	if (rc == 0)
 		panic();
 
-	console_set_scope(&arm_tsp_runtime_console.console,
+	console_set_scope(&arm_tsp_runtime_console,
 			  CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME);
 }
 
@@ -79,4 +79,8 @@
 
 	setup_page_tables(bl_regions, plat_arm_get_mmap());
 	enable_mmu_el1(0);
+
+#if PLAT_RO_XLAT_TABLES
+	arm_xlat_make_tables_readonly();
+#endif
 }
diff --git a/plat/arm/css/sgi/include/sgi_base_platform_def.h b/plat/arm/css/sgi/include/sgi_base_platform_def.h
index 4986378..9a482d0 100644
--- a/plat/arm/css/sgi/include/sgi_base_platform_def.h
+++ b/plat/arm/css/sgi/include/sgi_base_platform_def.h
@@ -123,6 +123,9 @@
 #define PLAT_ARM_NSRAM_BASE		0x06000000
 #define PLAT_ARM_NSRAM_SIZE		0x00080000	/* 512KB */
 
+#define PLAT_ARM_DRAM2_BASE		ULL(0x8080000000)
+#define PLAT_ARM_DRAM2_SIZE		ULL(0x180000000)
+
 #define PLAT_ARM_G1S_IRQ_PROPS(grp)	CSS_G1S_IRQ_PROPS(grp)
 #define PLAT_ARM_G0_IRQ_PROPS(grp)	ARM_G0_IRQ_PROPS(grp)
 
diff --git a/plat/common/plat_bl_common.c b/plat/common/plat_bl_common.c
index 6070db2..de6c1d1 100644
--- a/plat/common/plat_bl_common.c
+++ b/plat/common/plat_bl_common.c
@@ -11,6 +11,7 @@
 #include <common/debug.h>
 #include <lib/xlat_tables/xlat_tables_compat.h>
 #include <plat/common/platform.h>
+#include <tools_share/firmware_encrypted.h>
 
 /*
  * The following platform functions are weakly defined. The Platforms
@@ -22,6 +23,7 @@
 #pragma weak bl2_plat_handle_pre_image_load
 #pragma weak bl2_plat_handle_post_image_load
 #pragma weak plat_try_next_boot_source
+#pragma weak plat_get_enc_key_info
 
 void bl2_el3_plat_prepare_exit(void)
 {
@@ -53,6 +55,31 @@
 }
 
 /*
+ * Weak implementation to provide dummy decryption key only for test purposes,
+ * platforms must override this API for any real world firmware encryption
+ * use-case.
+ */
+int plat_get_enc_key_info(enum fw_enc_status_t fw_enc_status, uint8_t *key,
+			  size_t *key_len, unsigned int *flags,
+			  const uint8_t *img_id, size_t img_id_len)
+{
+#define DUMMY_FIP_ENC_KEY { 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, \
+			    0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, \
+			    0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, \
+			    0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef }
+
+	const uint8_t dummy_key[] = DUMMY_FIP_ENC_KEY;
+
+	assert(*key_len >= sizeof(dummy_key));
+
+	*key_len = sizeof(dummy_key);
+	memcpy(key, dummy_key, *key_len);
+	*flags = 0;
+
+	return 0;
+}
+
+/*
  * Set up the page tables for the generic and platform-specific memory regions.
  * The size of the Trusted SRAM seen by the BL image must be specified as well
  * as an array specifying the generic memory regions which can be;
diff --git a/plat/common/plat_spmd_manifest.c b/plat/common/plat_spmd_manifest.c
index 4c78979..9c3dc71 100644
--- a/plat/common/plat_spmd_manifest.c
+++ b/plat/common/plat_spmd_manifest.c
@@ -37,12 +37,6 @@
 		return -ENOENT;
 	}
 
-	rc = fdtw_read_cells(fdt, node, "runtime_el", 1, &attr->runtime_el);
-	if (rc) {
-		ERROR("Missing SPM core runtime EL in manifest.\n");
-		return -ENOENT;
-	}
-
 	rc = fdtw_read_cells(fdt, node, "exec_state", 1, &attr->exec_state);
 	if (rc)
 		NOTICE("Execution state not specified in SPM core manifest.\n");
@@ -61,7 +55,6 @@
 
 	VERBOSE("SPM core manifest attribute section:\n");
 	VERBOSE("  version: %x.%x\n", attr->major_version, attr->minor_version);
-	VERBOSE("  runtime_el: 0x%x\n", attr->runtime_el);
 	VERBOSE("  binary_size: 0x%x\n", attr->binary_size);
 	VERBOSE("  load_address: 0x%llx\n", attr->load_address);
 	VERBOSE("  entrypoint: 0x%llx\n", attr->entrypoint);
diff --git a/plat/hisilicon/hikey/hikey_bl1_setup.c b/plat/hisilicon/hikey/hikey_bl1_setup.c
index a97d763..86e4fd6 100644
--- a/plat/hisilicon/hikey/hikey_bl1_setup.c
+++ b/plat/hisilicon/hikey/hikey_bl1_setup.c
@@ -26,7 +26,7 @@
 
 /* Data structure which holds the extents of the trusted RAM for BL1 */
 static meminfo_t bl1_tzram_layout;
-static console_pl011_t console;
+static console_t console;
 
 enum {
 	BOOT_NORMAL = 0,
diff --git a/plat/hisilicon/hikey/hikey_bl2_setup.c b/plat/hisilicon/hikey/hikey_bl2_setup.c
index 96136ec..feb7f8a 100644
--- a/plat/hisilicon/hikey/hikey_bl2_setup.c
+++ b/plat/hisilicon/hikey/hikey_bl2_setup.c
@@ -32,7 +32,7 @@
 #define BL2_RW_BASE		(BL_CODE_END)
 
 static meminfo_t bl2_el3_tzram_layout;
-static console_pl011_t console;
+static console_t console;
 
 enum {
 	BOOT_MODE_RECOVERY = 0,
diff --git a/plat/hisilicon/hikey/hikey_bl31_setup.c b/plat/hisilicon/hikey/hikey_bl31_setup.c
index 0326e9f..7d008e7 100644
--- a/plat/hisilicon/hikey/hikey_bl31_setup.c
+++ b/plat/hisilicon/hikey/hikey_bl31_setup.c
@@ -27,7 +27,7 @@
 
 static entry_point_info_t bl32_ep_info;
 static entry_point_info_t bl33_ep_info;
-static console_pl011_t console;
+static console_t console;
 
 /******************************************************************************
  * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0
diff --git a/plat/hisilicon/hikey960/hikey960_bl1_setup.c b/plat/hisilicon/hikey960/hikey960_bl1_setup.c
index 4a7036c..0a2d062 100644
--- a/plat/hisilicon/hikey960/hikey960_bl1_setup.c
+++ b/plat/hisilicon/hikey960/hikey960_bl1_setup.c
@@ -41,7 +41,7 @@
 
 /* Data structure which holds the extents of the trusted RAM for BL1 */
 static meminfo_t bl1_tzram_layout;
-static console_pl011_t console;
+static console_t console;
 
 /******************************************************************************
  * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0
diff --git a/plat/hisilicon/hikey960/hikey960_bl2_setup.c b/plat/hisilicon/hikey960/hikey960_bl2_setup.c
index 35d7692..c1c2a8c 100644
--- a/plat/hisilicon/hikey960/hikey960_bl2_setup.c
+++ b/plat/hisilicon/hikey960/hikey960_bl2_setup.c
@@ -32,7 +32,7 @@
 #define BL2_RW_BASE		(BL_CODE_END)
 
 static meminfo_t bl2_el3_tzram_layout;
-static console_pl011_t console;
+static console_t console;
 extern int load_lpm3(void);
 
 enum {
diff --git a/plat/hisilicon/hikey960/hikey960_bl31_setup.c b/plat/hisilicon/hikey960/hikey960_bl31_setup.c
index 9383265..d3b4e4f 100644
--- a/plat/hisilicon/hikey960/hikey960_bl31_setup.c
+++ b/plat/hisilicon/hikey960/hikey960_bl31_setup.c
@@ -29,7 +29,7 @@
 
 static entry_point_info_t bl32_ep_info;
 static entry_point_info_t bl33_ep_info;
-static console_pl011_t console;
+static console_t console;
 
 /******************************************************************************
  * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0
diff --git a/plat/hisilicon/hikey960/hikey960_pm.c b/plat/hisilicon/hikey960/hikey960_pm.c
index ede893e..9f96fc3 100644
--- a/plat/hisilicon/hikey960/hikey960_pm.c
+++ b/plat/hisilicon/hikey960/hikey960_pm.c
@@ -33,7 +33,7 @@
 #define AXI_CONF_BASE		0x820
 
 static unsigned int uart_base;
-static console_pl011_t console;
+static console_t console;
 static uintptr_t hikey960_sec_entrypoint;
 
 static void hikey960_pwr_domain_standby(plat_local_state_t cpu_state)
diff --git a/plat/hisilicon/poplar/bl1_plat_setup.c b/plat/hisilicon/poplar/bl1_plat_setup.c
index 08ad67c..047ba62 100644
--- a/plat/hisilicon/poplar/bl1_plat_setup.c
+++ b/plat/hisilicon/poplar/bl1_plat_setup.c
@@ -28,7 +28,7 @@
 /* Data structure which holds the extents of the trusted RAM for BL1 */
 static meminfo_t bl1_tzram_layout;
 static meminfo_t bl2_tzram_layout;
-static console_pl011_t console;
+static console_t console;
 
 /*
  * Cannot use default weak implementation in bl1_main.c because BL1 RW data is
diff --git a/plat/hisilicon/poplar/bl2_plat_setup.c b/plat/hisilicon/poplar/bl2_plat_setup.c
index cc9d975..482935c 100644
--- a/plat/hisilicon/poplar/bl2_plat_setup.c
+++ b/plat/hisilicon/poplar/bl2_plat_setup.c
@@ -25,7 +25,7 @@
 #include "plat_private.h"
 
 static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE);
-static console_pl011_t console;
+static console_t console;
 
 /*******************************************************************************
  * Transfer SCP_BL2 from Trusted RAM using the SCP Download protocol.
diff --git a/plat/hisilicon/poplar/bl31_plat_setup.c b/plat/hisilicon/poplar/bl31_plat_setup.c
index 981ef37..a4e17ca 100644
--- a/plat/hisilicon/poplar/bl31_plat_setup.c
+++ b/plat/hisilicon/poplar/bl31_plat_setup.c
@@ -29,7 +29,7 @@
 
 static entry_point_info_t bl32_image_ep_info;
 static entry_point_info_t bl33_image_ep_info;
-static console_pl011_t console;
+static console_t console;
 
 static void hisi_tzpc_sec_init(void)
 {
diff --git a/plat/imx/common/aarch32/imx_uart_console.S b/plat/imx/common/aarch32/imx_uart_console.S
index 1c729b1..1a1229a 100644
--- a/plat/imx/common/aarch32/imx_uart_console.S
+++ b/plat/imx/common/aarch32/imx_uart_console.S
@@ -20,7 +20,7 @@
 	mov	r4, r3
 	cmp	r4, #0
 	beq	register_fail
-	str	r0, [r4, #CONSOLE_T_DRVDATA]
+	str	r0, [r4, #CONSOLE_T_BASE]
 
 	bl	console_imx_uart_core_init
 	cmp	r0, #0
@@ -35,16 +35,16 @@
 endfunc console_imx_uart_register
 
 func console_imx_uart_putc
-	ldr	r1, [r1, #CONSOLE_T_DRVDATA]
+	ldr	r1, [r1, #CONSOLE_T_BASE]
 	b console_imx_uart_core_putc
 endfunc console_imx_uart_putc
 
 func console_imx_uart_getc
-	ldr	r0, [r0, #CONSOLE_T_DRVDATA]
+	ldr	r0, [r0, #CONSOLE_T_BASE]
 	b console_imx_uart_core_getc
 endfunc console_imx_uart_getc
 
 func console_imx_uart_flush
-	ldr	r0, [r0, #CONSOLE_T_DRVDATA]
+	ldr	r0, [r0, #CONSOLE_T_BASE]
 	b console_imx_uart_core_flush
 endfunc console_imx_uart_flush
diff --git a/plat/imx/common/imx_uart_console.S b/plat/imx/common/imx_uart_console.S
index 3bdeea2..0cb4fb8 100644
--- a/plat/imx/common/imx_uart_console.S
+++ b/plat/imx/common/imx_uart_console.S
@@ -25,7 +25,7 @@
 	mov	x7, x30
 	mov	x6, x3
 	cbz	x6, register_fail
-	str	x0, [x6, #CONSOLE_T_DRVDATA]
+	str	x0, [x6, #CONSOLE_T_BASE]
 
 	bl	console_imx_uart_init
 	cbz	x0, register_fail
@@ -44,7 +44,7 @@
 endfunc console_imx_uart_init
 
 func console_imx_uart_putc
-	ldr	x1, [x1, #CONSOLE_T_DRVDATA]
+	ldr	x1, [x1, #CONSOLE_T_BASE]
 	cbz	x1, putc_error
 
 	/* Prepare '\r' to '\n' */
@@ -68,7 +68,7 @@
 endfunc console_imx_uart_putc
 
 func console_imx_uart_getc
-	ldr	x0, [x0, #CONSOLE_T_DRVDATA]
+	ldr	x0, [x0, #CONSOLE_T_BASE]
 	cbz	x0, getc_error
 1:
 	ldr	w1, [x0, #UTS]
diff --git a/plat/imx/common/include/imx8_lpuart.h b/plat/imx/common/include/imx8_lpuart.h
index 0ea284f..26470e0 100644
--- a/plat/imx/common/include/imx8_lpuart.h
+++ b/plat/imx/common/include/imx8_lpuart.h
@@ -54,13 +54,8 @@
 
 #include <stdint.h>
 
-typedef struct {
-	console_t console;
-	uintptr_t base;
-} console_lpuart_t;
-
 int console_lpuart_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud,
-			   console_lpuart_t *console);
+			   console_t *console);
 #endif /*__ASSEMBLER__*/
 
 #endif /* IMX8_LPUART_H */
diff --git a/plat/imx/common/include/imx_uart.h b/plat/imx/common/include/imx_uart.h
index cc1b531..6c4d62f 100644
--- a/plat/imx/common/include/imx_uart.h
+++ b/plat/imx/common/include/imx_uart.h
@@ -11,13 +11,8 @@
 
 #ifndef __ASSEMBLER__
 
-typedef struct {
-	console_t console;
-	uintptr_t base;
-} console_uart_t;
-
 int console_imx_uart_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud,
-			   console_uart_t *console);
+			      console_t *console);
 #endif /*__ASSEMBLER__*/
 
 #endif  /* IMX_UART_H */
diff --git a/plat/imx/common/lpuart_console.S b/plat/imx/common/lpuart_console.S
index d8dac2c..98b3588 100644
--- a/plat/imx/common/lpuart_console.S
+++ b/plat/imx/common/lpuart_console.S
@@ -20,7 +20,7 @@
 	mov	x7, x30
 	mov	x6, x3
 	cbz	x6, register_fail
-	str	x0, [x6, #CONSOLE_T_DRVDATA]
+	str	x0, [x6, #CONSOLE_T_BASE]
 
 	bl	console_lpuart_init
 	cbz	x0, register_fail
@@ -39,7 +39,7 @@
 endfunc console_lpuart_init
 
 func console_lpuart_putc
-	ldr	x1, [x1, #CONSOLE_T_DRVDATA]
+	ldr	x1, [x1, #CONSOLE_T_BASE]
 	cbz	x1, putc_error
 	/* Prepare '\r' to '\n' */
 	cmp	w0, #0xA
@@ -62,7 +62,7 @@
 endfunc console_lpuart_putc
 
 func console_lpuart_getc
-	ldr	x0, [x0, #CONSOLE_T_DRVDATA]
+	ldr	x0, [x0, #CONSOLE_T_BASE]
 	cbz	x0, getc_error
 	/* Check if the receive FIFO state */
 	ret
diff --git a/plat/imx/imx7/common/imx7_bl2_el3_common.c b/plat/imx/imx7/common/imx7_bl2_el3_common.c
index a1e2aaf..7f156e3 100644
--- a/plat/imx/imx7/common/imx7_bl2_el3_common.c
+++ b/plat/imx/imx7/common/imx7_bl2_el3_common.c
@@ -150,7 +150,7 @@
 void bl2_el3_early_platform_setup(u_register_t arg1, u_register_t arg2,
 				  u_register_t arg3, u_register_t arg4)
 {
-	static console_imx_uart_t console;
+	static console_t console;
 	int console_scope = CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME;
 
 	/* Initialize common components */
@@ -170,7 +170,7 @@
 				  PLAT_IMX7_BOOT_UART_CLK_IN_HZ,
 				  PLAT_IMX7_CONSOLE_BAUDRATE,
 				  &console);
-	console_set_scope(&console.console, console_scope);
+	console_set_scope(&console, console_scope);
 
 	/* Open handles to persistent storage */
 	plat_imx7_io_setup();
diff --git a/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c b/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c
index 4c5f4f0..40110d7 100644
--- a/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c
+++ b/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c
@@ -97,7 +97,7 @@
 void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
 		u_register_t arg2, u_register_t arg3)
 {
-	static console_uart_t console;
+	static console_t console;
 	int i;
 
 	/* Enable CSU NS access permission */
@@ -114,7 +114,7 @@
 	console_imx_uart_register(IMX_BOOT_UART_BASE, IMX_BOOT_UART_CLK_IN_HZ,
 		IMX_CONSOLE_BAUDRATE, &console);
 	/* This console is only used for boot stage */
-	console_set_scope(&console.console, CONSOLE_FLAG_BOOT);
+	console_set_scope(&console, CONSOLE_FLAG_BOOT);
 
 	/*
 	 * tell BL3-1 where the non-secure software image is located
diff --git a/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c b/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c
index a347389..05b5970 100644
--- a/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c
+++ b/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c
@@ -133,7 +133,7 @@
 	imx8m_caam_init();
 
 #if DEBUG_CONSOLE
-	static console_uart_t console;
+	static console_t console;
 
 	console_imx_uart_register(IMX_BOOT_UART_BASE, IMX_BOOT_UART_CLK_IN_HZ,
 		IMX_CONSOLE_BAUDRATE, &console);
diff --git a/plat/imx/imx8m/include/imx_rdc.h b/plat/imx/imx8m/include/imx_rdc.h
index 6be8550..e25b0e6 100644
--- a/plat/imx/imx8m/include/imx_rdc.h
+++ b/plat/imx/imx8m/include/imx_rdc.h
@@ -13,9 +13,9 @@
 
 #define MDAn(x)		(IMX_RDC_BASE + 0x200 + (x) * 4)
 #define PDAPn(x)	(IMX_RDC_BASE + 0x400 + (x) * 4)
-#define MRSAn(x)	(IMX_RDC_BASE + 0x800 + (x) * 4)
-#define MREAn(x)	(IMX_RDC_BASE + 0x804 + (x) * 4)
-#define MRCn(x)		(IMX_RDC_BASE + 0x808 + (x) * 4)
+#define MRSAn(x)	(IMX_RDC_BASE + 0x800 + (x) * 0x10)
+#define MREAn(x)	(IMX_RDC_BASE + 0x804 + (x) * 0x10)
+#define MRCn(x)		(IMX_RDC_BASE + 0x808 + (x) * 0x10)
 
 #define LCK		BIT(31)
 #define SREQ		BIT(30)
diff --git a/plat/imx/imx8qm/imx8qm_bl31_setup.c b/plat/imx/imx8qm/imx8qm_bl31_setup.c
index 9232cbc..cffb140 100644
--- a/plat/imx/imx8qm/imx8qm_bl31_setup.c
+++ b/plat/imx/imx8qm/imx8qm_bl31_setup.c
@@ -295,7 +295,7 @@
 				u_register_t arg2, u_register_t arg3)
 {
 #if DEBUG_CONSOLE
-	static console_lpuart_t console;
+	static console_t console;
 #endif
 	if (sc_ipc_open(&ipc_handle, SC_IPC_BASE) != SC_ERR_NONE)
 		panic();
diff --git a/plat/imx/imx8qx/imx8qx_bl31_setup.c b/plat/imx/imx8qx/imx8qx_bl31_setup.c
index 58c82ce..97d2227 100644
--- a/plat/imx/imx8qx/imx8qx_bl31_setup.c
+++ b/plat/imx/imx8qx/imx8qx_bl31_setup.c
@@ -255,7 +255,7 @@
 				u_register_t arg2, u_register_t arg3)
 {
 #if DEBUG_CONSOLE
-	static console_lpuart_t console;
+	static console_t console;
 #endif
 	if (sc_ipc_open(&ipc_handle, SC_IPC_BASE) != SC_ERR_NONE)
 		panic();
diff --git a/plat/intel/soc/agilex/bl2_plat_setup.c b/plat/intel/soc/agilex/bl2_plat_setup.c
index f328207..a87dea8 100644
--- a/plat/intel/soc/agilex/bl2_plat_setup.c
+++ b/plat/intel/soc/agilex/bl2_plat_setup.c
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
- * Copyright (c) 2019, Intel Corporation. All rights reserved.
+ * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2020, Intel Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -20,6 +20,7 @@
 #include "agilex_pinmux.h"
 #include "ccu/ncore_ccu.h"
 #include "qspi/cadence_qspi.h"
+#include "socfpga_emac.h"
 #include "socfpga_handoff.h"
 #include "socfpga_mailbox.h"
 #include "socfpga_private.h"
@@ -51,7 +52,7 @@
 void bl2_el3_early_platform_setup(u_register_t x0, u_register_t x1,
 				u_register_t x2, u_register_t x4)
 {
-	static console_16550_t console;
+	static console_t console;
 	handoff reverse_handoff_ptr;
 
 	generic_delay_timer_init();
@@ -72,6 +73,7 @@
 
 	socfpga_delay_timer_init();
 	init_ncore_ccu();
+	socfpga_emac_init();
 	init_hard_memory_controller();
 	mailbox_init();
 
diff --git a/plat/intel/soc/agilex/bl31_plat_setup.c b/plat/intel/soc/agilex/bl31_plat_setup.c
index 4b11440..6f32aff 100644
--- a/plat/intel/soc/agilex/bl31_plat_setup.c
+++ b/plat/intel/soc/agilex/bl31_plat_setup.c
@@ -37,7 +37,7 @@
 void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
 				u_register_t arg2, u_register_t arg3)
 {
-	static console_16550_t console;
+	static console_t console;
 
 	console_16550_register(PLAT_UART0_BASE, PLAT_UART_CLOCK, PLAT_BAUDRATE,
 		&console);
diff --git a/plat/intel/soc/agilex/platform.mk b/plat/intel/soc/agilex/platform.mk
index f47c3f1..0a91c23 100644
--- a/plat/intel/soc/agilex/platform.mk
+++ b/plat/intel/soc/agilex/platform.mk
@@ -1,6 +1,6 @@
 #
-# Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
-# Copyright (c) 2019, Intel Corporation. All rights reserved.
+# Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2019-2020, Intel Corporation. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -42,6 +42,7 @@
 		plat/intel/soc/common/socfpga_delay_timer.c		\
 		plat/intel/soc/common/socfpga_image_load.c		\
 		plat/intel/soc/common/socfpga_storage.c			\
+		plat/intel/soc/common/soc/socfpga_emac.c		\
 		plat/intel/soc/common/soc/socfpga_handoff.c		\
 		plat/intel/soc/common/soc/socfpga_mailbox.c		\
 		plat/intel/soc/common/soc/socfpga_reset_manager.c	\
diff --git a/plat/intel/soc/common/include/platform_def.h b/plat/intel/soc/common/include/platform_def.h
index 8a681e6..046d138 100644
--- a/plat/intel/soc/common/include/platform_def.h
+++ b/plat/intel/soc/common/include/platform_def.h
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
- * Copyright (c) 2019, Intel Corporation. All rights reserved.
+ * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2020, Intel Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -169,6 +169,14 @@
 #define PLAT_UART_CLOCK		(100000000)
 
 /*******************************************************************************
+ * PHY related constants
+ ******************************************************************************/
+
+#define EMAC0_PHY_MODE			PHY_INTERFACE_MODE_RGMII
+#define EMAC1_PHY_MODE			PHY_INTERFACE_MODE_RGMII
+#define EMAC2_PHY_MODE			PHY_INTERFACE_MODE_RGMII
+
+/*******************************************************************************
  * System counter frequency related constants
  ******************************************************************************/
 #define PLAT_SYS_COUNTER_FREQ_IN_TICKS	(400000000)
diff --git a/plat/intel/soc/common/include/socfpga_emac.h b/plat/intel/soc/common/include/socfpga_emac.h
new file mode 100644
index 0000000..5b98006
--- /dev/null
+++ b/plat/intel/soc/common/include/socfpga_emac.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2020, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SOCFPGA_EMAC_H
+#define SOCFPGA_EMAC_H
+
+/* EMAC PHY Mode */
+
+#define PHY_INTERFACE_MODE_GMII_MII		0
+#define PHY_INTERFACE_MODE_RGMII		1
+#define PHY_INTERFACE_MODE_RMII			2
+#define PHY_INTERFACE_MODE_RESET		3
+
+/* Mask Definitions */
+
+#define PHY_INTF_SEL_MSK			0x3
+#define FPGAINTF_EN_3_EMAC_MSK(x)		(1 << (x * 8))
+
+void socfpga_emac_init(void);
+
+#endif /* SOCFPGA_EMAC_H */
diff --git a/plat/intel/soc/common/include/socfpga_mailbox.h b/plat/intel/soc/common/include/socfpga_mailbox.h
index 7d725b0..3c56d15 100644
--- a/plat/intel/soc/common/include/socfpga_mailbox.h
+++ b/plat/intel/soc/common/include/socfpga_mailbox.h
@@ -126,9 +126,9 @@
 void mailbox_set_qspi_close(void);
 void mailbox_set_qspi_open(void);
 void mailbox_set_qspi_direct(void);
-int mailbox_send_cmd(int job_id, unsigned int cmd, uint64_t *args,
+int mailbox_send_cmd(int job_id, unsigned int cmd, uint32_t *args,
 			int len, int urgent, uint32_t *response, int resp_len);
-int mailbox_send_cmd_async(int job_id, unsigned int cmd, uint64_t *args,
+int mailbox_send_cmd_async(int job_id, unsigned int cmd, uint32_t *args,
 				int len, int urgent);
 int mailbox_read_response(int job_id, uint32_t *response, int resp_len);
 int mailbox_get_qspi_clock(void);
@@ -140,7 +140,7 @@
 
 int mailbox_rsu_get_spt_offset(uint32_t *resp_buf, uint32_t resp_buf_len);
 int mailbox_rsu_status(uint32_t *resp_buf, uint32_t resp_buf_len);
-int mailbox_rsu_update(uint64_t *flash_offset);
-int mailbox_hps_stage_notify(uint64_t execution_stage);
+int mailbox_rsu_update(uint32_t *flash_offset);
+int mailbox_hps_stage_notify(uint32_t execution_stage);
 
 #endif /* SOCFPGA_MBOX_H */
diff --git a/plat/intel/soc/common/include/socfpga_sip_svc.h b/plat/intel/soc/common/include/socfpga_sip_svc.h
index 2b1d983..19a52f7 100644
--- a/plat/intel/soc/common/include/socfpga_sip_svc.h
+++ b/plat/intel/soc/common/include/socfpga_sip_svc.h
@@ -10,9 +10,11 @@
 
 /* SiP status response */
 #define INTEL_SIP_SMC_STATUS_OK				0
-#define INTEL_SIP_SMC_STATUS_ERROR			0x4
 #define INTEL_SIP_SMC_STATUS_BUSY			0x1
 #define INTEL_SIP_SMC_STATUS_REJECTED			0x2
+#define INTEL_SIP_SMC_STATUS_ERROR			0x4
+#define INTEL_SIP_SMC_RSU_ERROR				0x7
+
 
 /* SMC SiP service function identifier */
 #define INTEL_SIP_SMC_FPGA_CONFIG_START			0xC2000001
diff --git a/plat/intel/soc/common/include/socfpga_system_manager.h b/plat/intel/soc/common/include/socfpga_system_manager.h
index 68e30b8..76565bc 100644
--- a/plat/intel/soc/common/include/socfpga_system_manager.h
+++ b/plat/intel/soc/common/include/socfpga_system_manager.h
@@ -13,6 +13,11 @@
 
 #define SOCFPGA_SYSMGR_SDMMC				0x28
 
+#define SOCFPGA_SYSMGR_EMAC_0				0x44
+#define SOCFPGA_SYSMGR_EMAC_1				0x48
+#define SOCFPGA_SYSMGR_EMAC_2				0x4c
+#define SOCFPGA_SYSMGR_FPGAINTF_EN_3			0x70
+
 #define SOCFPGA_SYSMGR_NOC_TIMEOUT			0xc0
 #define SOCFPGA_SYSMGR_NOC_IDLEREQ_SET			0xc4
 #define SOCFPGA_SYSMGR_NOC_IDLEREQ_CLR			0xc8
diff --git a/plat/intel/soc/common/soc/socfpga_emac.c b/plat/intel/soc/common/soc/socfpga_emac.c
new file mode 100644
index 0000000..cacfd53
--- /dev/null
+++ b/plat/intel/soc/common/soc/socfpga_emac.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2020, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/mmio.h>
+#include <platform_def.h>
+
+#include "socfpga_emac.h"
+#include "socfpga_reset_manager.h"
+#include "socfpga_system_manager.h"
+
+void socfpga_emac_init(void)
+{
+	mmio_setbits_32(SOCFPGA_RSTMGR(PER0MODRST),
+		RSTMGR_PER0MODRST_EMAC0 |
+		RSTMGR_PER0MODRST_EMAC1 |
+		RSTMGR_PER0MODRST_EMAC2);
+
+	mmio_clrsetbits_32(SOCFPGA_SYSMGR(EMAC_0),
+		PHY_INTF_SEL_MSK, EMAC0_PHY_MODE);
+	mmio_clrsetbits_32(SOCFPGA_SYSMGR(EMAC_1),
+		PHY_INTF_SEL_MSK, EMAC1_PHY_MODE);
+	mmio_clrsetbits_32(SOCFPGA_SYSMGR(EMAC_2),
+		PHY_INTF_SEL_MSK, EMAC2_PHY_MODE);
+
+	mmio_clrbits_32(SOCFPGA_SYSMGR(FPGAINTF_EN_3),
+		FPGAINTF_EN_3_EMAC_MSK(0) |
+		FPGAINTF_EN_3_EMAC_MSK(1) |
+		FPGAINTF_EN_3_EMAC_MSK(2));
+
+	mmio_clrbits_32(SOCFPGA_RSTMGR(PER0MODRST),
+		RSTMGR_PER0MODRST_EMAC0 |
+		RSTMGR_PER0MODRST_EMAC1 |
+		RSTMGR_PER0MODRST_EMAC2);
+}
+
diff --git a/plat/intel/soc/common/soc/socfpga_mailbox.c b/plat/intel/soc/common/soc/socfpga_mailbox.c
index 8ce40a7..d066f27 100644
--- a/plat/intel/soc/common/soc/socfpga_mailbox.c
+++ b/plat/intel/soc/common/soc/socfpga_mailbox.c
@@ -11,7 +11,7 @@
 #include "socfpga_mailbox.h"
 #include "socfpga_sip_svc.h"
 
-static int fill_mailbox_circular_buffer(uint32_t header_cmd, uint64_t *args,
+static int fill_mailbox_circular_buffer(uint32_t header_cmd, uint32_t *args,
 					int len)
 {
 	uint32_t cmd_free_offset;
@@ -167,7 +167,7 @@
 	}
 }
 
-int mailbox_send_cmd_async(int job_id, unsigned int cmd, uint64_t *args,
+int mailbox_send_cmd_async(int job_id, unsigned int cmd, uint32_t *args,
 			  int len, int urgent)
 {
 	if (urgent)
@@ -184,7 +184,7 @@
 	return 0;
 }
 
-int mailbox_send_cmd(int job_id, unsigned int cmd, uint64_t *args,
+int mailbox_send_cmd(int job_id, unsigned int cmd, uint32_t *args,
 			int len, int urgent, uint32_t *response, int resp_len)
 {
 	int status = 0;
@@ -252,7 +252,7 @@
 
 void mailbox_qspi_set_cs(int device_select)
 {
-	uint64_t cs_setting = device_select;
+	uint32_t cs_setting = device_select;
 
 	/* QSPI device select settings at 31:28 */
 	cs_setting = (cs_setting << 28);
@@ -304,13 +304,13 @@
 	return ret;
 }
 
-int mailbox_rsu_update(uint64_t *flash_offset)
+int mailbox_rsu_update(uint32_t *flash_offset)
 {
 	return mailbox_send_cmd(MBOX_JOB_ID, MBOX_RSU_UPDATE,
 				flash_offset, 2, 0, NULL, 0);
 }
 
-int mailbox_hps_stage_notify(uint64_t execution_stage)
+int mailbox_hps_stage_notify(uint32_t execution_stage)
 {
 	return mailbox_send_cmd(MBOX_JOB_ID, MBOX_HPS_STAGE_NOTIFY,
 				&execution_stage, 1, 0, NULL, 0);
diff --git a/plat/intel/soc/common/socfpga_psci.c b/plat/intel/soc/common/socfpga_psci.c
index d48fb5d..4b57b8f 100644
--- a/plat/intel/soc/common/socfpga_psci.c
+++ b/plat/intel/soc/common/socfpga_psci.c
@@ -134,8 +134,13 @@
 
 static void __dead2 socfpga_system_reset(void)
 {
+	uint32_t addr_buf[2];
+
+	memcpy(addr_buf, &intel_rsu_update_address,
+			sizeof(intel_rsu_update_address));
+
 	if (intel_rsu_update_address)
-		mailbox_rsu_update(&intel_rsu_update_address);
+		mailbox_rsu_update(addr_buf);
 	else
 		mailbox_reset_cold();
 
diff --git a/plat/intel/soc/common/socfpga_sip_svc.c b/plat/intel/soc/common/socfpga_sip_svc.c
index 1c3d45b..a20baab 100644
--- a/plat/intel/soc/common/socfpga_sip_svc.c
+++ b/plat/intel/soc/common/socfpga_sip_svc.c
@@ -61,7 +61,7 @@
 
 static int intel_fpga_sdm_write_buffer(struct fpga_config_info *buffer)
 {
-	uint64_t args[3];
+	uint32_t args[3];
 
 	while (max_blocks > 0 && buffer->size > buffer->size_written) {
 		args[0] = (1<<8);
@@ -374,7 +374,7 @@
 static uint32_t intel_rsu_status(uint64_t *respbuf, uint32_t respbuf_sz)
 {
 	if (mailbox_rsu_status((uint32_t *)respbuf, respbuf_sz) < 0)
-		return INTEL_SIP_SMC_STATUS_ERROR;
+		return INTEL_SIP_SMC_RSU_ERROR;
 
 	return INTEL_SIP_SMC_STATUS_OK;
 }
@@ -385,10 +385,10 @@
 	return INTEL_SIP_SMC_STATUS_OK;
 }
 
-static uint32_t intel_rsu_notify(uint64_t execution_stage)
+static uint32_t intel_rsu_notify(uint32_t execution_stage)
 {
 	if (mailbox_hps_stage_notify(execution_stage) < 0)
-		return INTEL_SIP_SMC_STATUS_ERROR;
+		return INTEL_SIP_SMC_RSU_ERROR;
 
 	return INTEL_SIP_SMC_STATUS_OK;
 }
@@ -397,14 +397,14 @@
 					uint32_t *ret_stat)
 {
 	if (mailbox_rsu_status((uint32_t *)respbuf, respbuf_sz) < 0)
-		return INTEL_SIP_SMC_STATUS_ERROR;
+		return INTEL_SIP_SMC_RSU_ERROR;
 
 	*ret_stat = respbuf[8];
 	return INTEL_SIP_SMC_STATUS_OK;
 }
 
 /* Mailbox services */
-static uint32_t intel_mbox_send_cmd(uint32_t cmd, uint64_t *args, int len,
+static uint32_t intel_mbox_send_cmd(uint32_t cmd, uint32_t *args, int len,
 				    int urgent, uint32_t *response,
 				    int resp_len, int *mbox_status,
 				    int *len_in_resp)
@@ -542,7 +542,7 @@
 	case INTEL_SIP_SMC_MBOX_SEND_CMD:
 		x5 = SMC_GET_GP(handle, CTX_GPREG_X5);
 		x6 = SMC_GET_GP(handle, CTX_GPREG_X6);
-		status = intel_mbox_send_cmd(x1, (uint64_t *)x2, x3, x4,
+		status = intel_mbox_send_cmd(x1, (uint32_t *)x2, x3, x4,
 					     (uint32_t *)x5, x6, &mbox_status,
 					     &len_in_resp);
 		SMC_RET4(handle, status, mbox_status, x5, len_in_resp);
diff --git a/plat/intel/soc/stratix10/bl2_plat_setup.c b/plat/intel/soc/stratix10/bl2_plat_setup.c
index 78ca253..721a690 100644
--- a/plat/intel/soc/stratix10/bl2_plat_setup.c
+++ b/plat/intel/soc/stratix10/bl2_plat_setup.c
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
- * Copyright (c) 2019, Intel Corporation. All rights reserved.
+ * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2020, Intel Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -16,6 +16,7 @@
 #include <lib/xlat_tables/xlat_tables.h>
 
 #include "qspi/cadence_qspi.h"
+#include "socfpga_emac.h"
 #include "socfpga_handoff.h"
 #include "socfpga_mailbox.h"
 #include "socfpga_private.h"
@@ -50,7 +51,7 @@
 void bl2_el3_early_platform_setup(u_register_t x0, u_register_t x1,
 				u_register_t x2, u_register_t x4)
 {
-	static console_16550_t console;
+	static console_t console;
 	handoff reverse_handoff_ptr;
 
 	generic_delay_timer_init();
@@ -69,6 +70,7 @@
 	console_16550_register(PLAT_UART0_BASE, get_uart_clk(), PLAT_BAUDRATE,
 		&console);
 
+	socfpga_emac_init();
 	socfpga_delay_timer_init();
 	init_hard_memory_controller();
 	mailbox_init();
diff --git a/plat/intel/soc/stratix10/bl31_plat_setup.c b/plat/intel/soc/stratix10/bl31_plat_setup.c
index 4c31238..5813c8f 100644
--- a/plat/intel/soc/stratix10/bl31_plat_setup.c
+++ b/plat/intel/soc/stratix10/bl31_plat_setup.c
@@ -45,7 +45,7 @@
 void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
 				u_register_t arg2, u_register_t arg3)
 {
-	static console_16550_t console;
+	static console_t console;
 
 	console_16550_register(PLAT_UART0_BASE, PLAT_UART_CLOCK, PLAT_BAUDRATE,
 		&console);
diff --git a/plat/intel/soc/stratix10/platform.mk b/plat/intel/soc/stratix10/platform.mk
index efbab24..112317b 100644
--- a/plat/intel/soc/stratix10/platform.mk
+++ b/plat/intel/soc/stratix10/platform.mk
@@ -1,6 +1,6 @@
 #
-# Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
-# Copyright (c) 2019, Intel Corporation. All rights reserved.
+# Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2019-2020, Intel Corporation. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -42,6 +42,7 @@
 		plat/intel/soc/common/socfpga_delay_timer.c		\
 		plat/intel/soc/common/socfpga_image_load.c		\
 		plat/intel/soc/common/socfpga_storage.c			\
+		plat/intel/soc/common/soc/socfpga_emac.c		\
 		plat/intel/soc/common/soc/socfpga_handoff.c		\
 		plat/intel/soc/common/soc/socfpga_mailbox.c		\
 		plat/intel/soc/common/soc/socfpga_reset_manager.c	\
diff --git a/plat/layerscape/common/aarch64/ls_console.S b/plat/layerscape/common/aarch64/ls_console.S
index f8948b4..c1bd3f7 100644
--- a/plat/layerscape/common/aarch64/ls_console.S
+++ b/plat/layerscape/common/aarch64/ls_console.S
@@ -81,7 +81,7 @@
 	.globl console_ls_16550_register
 
 	/* -----------------------------------------------
-	 * int console_ls_16550_register(console_ls_16550_t *console,
+	 * int console_ls_16550_register(console_t *console,
 	 *	uintptr_t base, uint32_t clk, uint32_t baud)
 	 * Function to initialize and register a new 16550
 	 * console. Storage passed in for the console struct
@@ -89,7 +89,7 @@
 	 * In: x0 - UART register base address
 	 *     w1 - UART clock in Hz
 	 *     w2 - Baud rate
-	 *     x3 - pointer to empty console_ls_16550_t struct
+	 *     x3 - pointer to empty console_t struct
 	 * Out: return 1 on success, 0 on error
 	 * Clobber list : x0, x1, x2, x6, x7, x14
 	 * -----------------------------------------------
@@ -98,7 +98,7 @@
 	mov	x7, x30
 	mov	x6, x3
 	cbz	x6, register_fail
-	str	x0, [x6, #CONSOLE_T_16550_BASE]
+	str	x0, [x6, #CONSOLE_T_BASE]
 
 	bl	console_ls_16550_core_init
 	cbz	x0, register_fail
@@ -150,7 +150,7 @@
 endfunc console_ls_16550_core_putc
 
 	/* --------------------------------------------------------
-	 * int console_16550_putc(int c, console_ls_16550_t *console)
+	 * int console_16550_putc(int c, console_t *console)
 	 * Function to output a character over the console. It
 	 * returns the character printed on success or -1 on error.
 	 * In : w0 - character to be printed
@@ -164,7 +164,7 @@
 	cmp	x1, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	x1, [x1, #CONSOLE_T_16550_BASE]
+	ldr	x1, [x1, #CONSOLE_T_BASE]
 	b	console_ls_16550_core_putc
 endfunc console_ls_16550_putc
 
@@ -195,7 +195,7 @@
 endfunc console_ls_16550_core_getc
 
 	/* ---------------------------------------------
-	 * int console_ls_16550_getc(console_ls_16550_t *console)
+	 * int console_ls_16550_getc(console_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.
@@ -209,7 +209,7 @@
 	cmp	x1, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	x0, [x0, #CONSOLE_T_16550_BASE]
+	ldr	x0, [x0, #CONSOLE_T_BASE]
 	b	console_ls_16550_core_getc
 endfunc console_ls_16550_getc
 
@@ -239,7 +239,7 @@
 endfunc console_ls_16550_core_flush
 
 	/* ---------------------------------------------
-	 * int console_ls_16550_flush(console_ls_16550_t *console)
+	 * int console_ls_16550_flush(console_t *console)
 	 * Function to force a write of all buffered
 	 * data that hasn't been output.
 	 * In : x0 - pointer to console_t structure
@@ -252,6 +252,6 @@
 	cmp	x0, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	x0, [x0, #CONSOLE_T_16550_BASE]
+	ldr	x0, [x0, #CONSOLE_T_BASE]
 	b	console_ls_16550_core_flush
 endfunc console_ls_16550_flush
diff --git a/plat/layerscape/common/include/ls_16550.h b/plat/layerscape/common/include/ls_16550.h
index cb4514f..95a64ad 100644
--- a/plat/layerscape/common/include/ls_16550.h
+++ b/plat/layerscape/common/include/ls_16550.h
@@ -61,17 +61,10 @@
 #define UARTLSR_OVRF		(1 << 2)	/* Rx Overrun Error */
 #define UARTLSR_RDR		(1 << 2)	/* Rx Data Ready */
 
-#define CONSOLE_T_16550_BASE	CONSOLE_T_DRVDATA
-
 #ifndef __ASSEMBLER__
 
 #include <stdint.h>
 
-typedef struct {
-	console_t console;
-	uintptr_t base;
-} console_ls_16550_t;
-
 /*
  * Initialize a new 16550 console instance and register it with the console
  * framework. The |console| pointer must point to storage that will be valid
@@ -79,7 +72,7 @@
  * Its contents will be reinitialized from scratch.
  */
 int console_ls_16550_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud,
-			   console_ls_16550_t *console);
+			      console_t *console);
 
 #endif /*__ASSEMBLER__*/
 
diff --git a/plat/layerscape/common/ls_bl1_setup.c b/plat/layerscape/common/ls_bl1_setup.c
index fff065e..fa69be2 100644
--- a/plat/layerscape/common/ls_bl1_setup.c
+++ b/plat/layerscape/common/ls_bl1_setup.c
@@ -23,7 +23,7 @@
  ******************************************************************************/
 void ls_bl1_early_platform_setup(void)
 {
-	static console_ls_16550_t console;
+	static console_t console;
 
 #if !LS1043_DISABLE_TRUSTED_WDOG
 	/* TODO: Enable watchdog */
diff --git a/plat/layerscape/common/ls_bl2_setup.c b/plat/layerscape/common/ls_bl2_setup.c
index 35f42e1..6ca66bd 100644
--- a/plat/layerscape/common/ls_bl2_setup.c
+++ b/plat/layerscape/common/ls_bl2_setup.c
@@ -23,7 +23,7 @@
  ******************************************************************************/
 void ls_bl2_early_platform_setup(meminfo_t *mem_layout)
 {
-	static console_ls_16550_t console;
+	static console_t console;
 
 	/* Initialize the console to provide early debug support */
 	console_ls_16550_register(LS_TF_UART_BASE, LS_TF_UART_CLOCK,
diff --git a/plat/layerscape/common/ls_bl31_setup.c b/plat/layerscape/common/ls_bl31_setup.c
index 03e5807..7a91aef 100644
--- a/plat/layerscape/common/ls_bl31_setup.c
+++ b/plat/layerscape/common/ls_bl31_setup.c
@@ -67,7 +67,7 @@
 void ls_bl31_early_platform_setup(void *from_bl2,
 				void *plat_params_from_bl2)
 {
-	static console_ls_16550_t console;
+	static console_t console;
 
 	/* Initialize the console to provide early debug support */
 	console_ls_16550_register(LS_TF_UART_BASE, LS_TF_UART_CLOCK,
@@ -182,7 +182,7 @@
  ******************************************************************************/
 void ls_bl31_plat_runtime_setup(void)
 {
-	static console_ls_16550_t console;
+	static console_t console;
 
 	/* Initialize the runtime console */
 	console_ls_16550_register(PLAT_LS1043_UART_BASE, PLAT_LS1043_UART_CLOCK,
diff --git a/plat/layerscape/common/tsp/ls_tsp_setup.c b/plat/layerscape/common/tsp/ls_tsp_setup.c
index f3b6027..969d0b8 100644
--- a/plat/layerscape/common/tsp/ls_tsp_setup.c
+++ b/plat/layerscape/common/tsp/ls_tsp_setup.c
@@ -30,7 +30,7 @@
  ******************************************************************************/
 void ls_tsp_early_platform_setup(void)
 {
-	static console_ls_16550_t console;
+	static console_t console;
 	/*
 	 * Initialize a different console than already in use to display
 	 * messages from TSP
diff --git a/plat/marvell/common/marvell_console.c b/plat/marvell/common/marvell_console.c
index 22c5eb3..1716661 100644
--- a/plat/marvell/common/marvell_console.c
+++ b/plat/marvell/common/marvell_console.c
@@ -14,16 +14,15 @@
 
 #ifdef PLAT_a3700
 #include <drivers/marvell/uart/a3700_console.h>
-
-static console_a3700_t marvell_boot_console;
-static console_a3700_t marvell_runtime_console;
+#define console_marvell_register console_a3700_register
 #else
 #include <drivers/ti/uart/uart_16550.h>
-
-static console_16550_t marvell_boot_console;
-static console_16550_t marvell_runtime_console;
+#define console_marvell_register console_16550_register
 #endif
 
+static console_t marvell_boot_console;
+static console_t marvell_runtime_console;
+
 /*******************************************************************************
  * Functions that set up the console
  ******************************************************************************/
@@ -32,15 +31,10 @@
 void marvell_console_boot_init(void)
 {
 	int rc =
-#ifdef PLAT_a3700
-	console_a3700_register(
-#else
-	console_16550_register(
-#endif
-				PLAT_MARVELL_BOOT_UART_BASE,
-				PLAT_MARVELL_BOOT_UART_CLK_IN_HZ,
-				MARVELL_CONSOLE_BAUDRATE,
-				&marvell_boot_console);
+	console_marvell_register(PLAT_MARVELL_BOOT_UART_BASE,
+				 PLAT_MARVELL_BOOT_UART_CLK_IN_HZ,
+				 MARVELL_CONSOLE_BAUDRATE,
+				 &marvell_boot_console);
 	if (rc == 0) {
 		/*
 		 * The crash console doesn't use the multi console API, it uses
@@ -50,40 +44,33 @@
 		panic();
 	}
 
-	console_set_scope(&marvell_boot_console.console,
-			  CONSOLE_FLAG_BOOT);
+	console_set_scope(&marvell_boot_console, CONSOLE_FLAG_BOOT);
 }
 
 void marvell_console_boot_end(void)
 {
 	(void)console_flush();
 
-	(void)console_unregister(&marvell_boot_console.console);
+	(void)console_unregister(&marvell_boot_console);
 }
 
 /* Initialize the runtime console */
 void marvell_console_runtime_init(void)
 {
 	int rc =
-#ifdef PLAT_a3700
-	console_a3700_register(
-#else
-	console_16550_register(
-#endif
-				PLAT_MARVELL_BOOT_UART_BASE,
-				PLAT_MARVELL_BOOT_UART_CLK_IN_HZ,
-				MARVELL_CONSOLE_BAUDRATE,
-				&marvell_runtime_console);
+	console_marvell_register(PLAT_MARVELL_BOOT_UART_BASE,
+				 PLAT_MARVELL_BOOT_UART_CLK_IN_HZ,
+				 MARVELL_CONSOLE_BAUDRATE,
+				 &marvell_runtime_console);
 	if (rc == 0)
 		panic();
 
-	console_set_scope(&marvell_runtime_console.console,
-			  CONSOLE_FLAG_RUNTIME);
+	console_set_scope(&marvell_runtime_console, CONSOLE_FLAG_RUNTIME);
 }
 
 void marvell_console_runtime_end(void)
 {
 	(void)console_flush();
 
-	(void)console_unregister(&marvell_runtime_console.console);
+	(void)console_unregister(&marvell_runtime_console);
 }
diff --git a/plat/mediatek/mt8173/bl31_plat_setup.c b/plat/mediatek/mt8173/bl31_plat_setup.c
index 73a479b..bd7d0b0 100644
--- a/plat/mediatek/mt8173/bl31_plat_setup.c
+++ b/plat/mediatek/mt8173/bl31_plat_setup.c
@@ -100,7 +100,7 @@
 void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
 				u_register_t arg2, u_register_t arg3)
 {
-	static console_16550_t console;
+	static console_t console;
 
 	console_16550_register(MT8173_UART0_BASE, MT8173_UART_CLOCK, MT8173_BAUDRATE, &console);
 
diff --git a/plat/mediatek/mt8173/drivers/wdt/wdt.c b/plat/mediatek/mt8173/drivers/wdt/wdt.c
new file mode 100644
index 0000000..40f57ee
--- /dev/null
+++ b/plat/mediatek/mt8173/drivers/wdt/wdt.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2020, Google LLC. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <mt8173_def.h>
+#include <plat_sip_calls.h>
+#include <lib/psci/psci.h>
+#include <smccc_helpers.h>
+#include <wdt.h>
+
+#define WDT_BASE		(RGU_BASE + 0)
+#define WDT_MODE		(WDT_BASE + 0x00)
+#define WDT_LENGTH		(WDT_BASE + 0x04)
+#define WDT_RESTART		(WDT_BASE + 0x08)
+#define WDT_SWRST		(WDT_BASE + 0x14)
+
+#define WDT_MODE_DUAL_MODE	0x40
+#define WDT_MODE_IRQ		0x8
+#define WDT_MODE_KEY		0x22000000
+#define WDT_MODE_EXTEN		0x4
+#define WDT_MODE_EN		0x1
+#define WDT_LENGTH_KEY		0x8
+#define WDT_RESTART_KEY		0x1971
+#define WDT_SWRST_KEY		0x1209
+
+
+#define WDT_MIN_TIMEOUT 1
+#define WDT_MAX_TIMEOUT 31
+
+enum smcwd_call {
+	SMCWD_INFO		= 0,
+	SMCWD_SET_TIMEOUT	= 1,
+	SMCWD_ENABLE		= 2,
+	SMCWD_PET		= 3,
+};
+
+static int wdt_enabled_before_suspend;
+
+/*
+ * We expect the WDT registers to be correctly initialized by BL2 firmware
+ * (which may be board specific), so we do not reinitialize them here.
+ */
+
+void wdt_trigger_reset(void)
+{
+	mmio_write_32(WDT_SWRST, WDT_SWRST_KEY);
+}
+
+void wdt_pet(void)
+{
+	mmio_write_32(WDT_RESTART, WDT_RESTART_KEY);
+}
+
+int wdt_set_timeout(uint32_t timeout)
+{
+	/* One tick here equals 512 32KHz ticks. 512 / 32000 * 125 / 2 = 1 */
+	uint32_t ticks = timeout * 125 / 2;
+
+	if (timeout < WDT_MIN_TIMEOUT || timeout > WDT_MAX_TIMEOUT)
+		return PSCI_E_INVALID_PARAMS;
+
+	mmio_write_32(WDT_LENGTH, ticks << 5 | WDT_LENGTH_KEY);
+
+	return PSCI_E_SUCCESS;
+}
+
+void wdt_set_enable(int enable)
+{
+	if (enable)
+		wdt_pet();
+	mmio_clrsetbits_32(WDT_MODE, WDT_MODE_EN,
+			   WDT_MODE_KEY | (enable ? WDT_MODE_EN : 0));
+}
+
+void wdt_suspend(void)
+{
+	wdt_enabled_before_suspend = mmio_read_32(WDT_MODE) & WDT_MODE_EN;
+	if (wdt_enabled_before_suspend)
+		wdt_set_enable(0);
+}
+
+void wdt_resume(void)
+{
+	if (wdt_enabled_before_suspend)
+		wdt_set_enable(1);
+}
+
+uint64_t wdt_smc_handler(uint32_t x1,
+			uint32_t x2,
+			void *handle)
+{
+	int ret;
+
+	switch (x1) {
+	case SMCWD_INFO:
+		SMC_RET3(handle, PSCI_E_SUCCESS,
+			 WDT_MIN_TIMEOUT, WDT_MAX_TIMEOUT);
+	case SMCWD_SET_TIMEOUT:
+		ret = wdt_set_timeout(x2);
+		SMC_RET1(handle, ret);
+	case SMCWD_ENABLE:
+		wdt_set_enable(x2 > 0);
+		SMC_RET1(handle, PSCI_E_SUCCESS);
+	case SMCWD_PET:
+		wdt_pet();
+		SMC_RET1(handle, PSCI_E_SUCCESS);
+	default:
+		ERROR("Unimplemented SMCWD call (%d)\n", x1);
+		SMC_RET1(handle, PSCI_E_NOT_SUPPORTED);
+	}
+}
diff --git a/plat/mediatek/mt8173/drivers/wdt/wdt.h b/plat/mediatek/mt8173/drivers/wdt/wdt.h
new file mode 100644
index 0000000..7262a57
--- /dev/null
+++ b/plat/mediatek/mt8173/drivers/wdt/wdt.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2020, Google LLC. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef WDT_H
+#define WDT_H
+
+#include "stdint.h"
+
+void wdt_pet(void);
+void wdt_resume(void);
+void wdt_set_enable(int enable);
+int wdt_set_timeout(uint32_t timeout);
+uint64_t wdt_smc_handler(uint32_t x1, uint32_t x2, void *handle);
+void wdt_suspend(void);
+void wdt_trigger_reset(void);
+
+#endif /* WDT_H */
diff --git a/plat/mediatek/mt8173/include/mt8173_def.h b/plat/mediatek/mt8173/include/mt8173_def.h
index 58962f0..378b4da 100644
--- a/plat/mediatek/mt8173/include/mt8173_def.h
+++ b/plat/mediatek/mt8173/include/mt8173_def.h
@@ -80,18 +80,6 @@
 #define PLAT_MT_CCI_CLUSTER0_SL_IFACE_IX	4
 #define PLAT_MT_CCI_CLUSTER1_SL_IFACE_IX	3
 
-/*******************************************************************************
- * WDT related constants
- ******************************************************************************/
-#define MTK_WDT_BASE		(RGU_BASE + 0)
-#define MTK_WDT_SWRST		(MTK_WDT_BASE + 0x0014)
-
-#define MTK_WDT_MODE_DUAL_MODE	0x0040
-#define MTK_WDT_MODE_IRQ	0x0008
-#define MTK_WDT_MODE_KEY	0x22000000
-#define MTK_WDT_MODE_EXTEN	0x0004
-#define MTK_WDT_SWRST_KEY	0x1209
-
 /* FIQ platform related define */
 #define MT_IRQ_SEC_SGI_0	8
 #define MT_IRQ_SEC_SGI_1	9
diff --git a/plat/mediatek/mt8173/include/plat_sip_calls.h b/plat/mediatek/mt8173/include/plat_sip_calls.h
index 88202cc..ce9951a 100644
--- a/plat/mediatek/mt8173/include/plat_sip_calls.h
+++ b/plat/mediatek/mt8173/include/plat_sip_calls.h
@@ -10,7 +10,7 @@
 /*******************************************************************************
  * Plat SiP function constants
  ******************************************************************************/
-#define MTK_PLAT_SIP_NUM_CALLS	6
+#define MTK_PLAT_SIP_NUM_CALLS	7
 
 #define MTK_SIP_PWR_ON_MTCMOS			0x82000402
 #define MTK_SIP_PWR_OFF_MTCMOS			0x82000403
@@ -18,5 +18,6 @@
 #define MTK_SIP_SET_HDCP_KEY_NUM		0x82000405
 #define MTK_SIP_CLR_HDCP_KEY			0x82000406
 #define MTK_SIP_SET_HDCP_KEY_EX			0x82000407
+#define MTK_SIP_SMC_WATCHDOG			0x82003D06
 
 #endif /* PLAT_SIP_CALLS_H */
diff --git a/plat/mediatek/mt8173/plat_pm.c b/plat/mediatek/mt8173/plat_pm.c
index 67f1c73..e72a343 100644
--- a/plat/mediatek/mt8173/plat_pm.c
+++ b/plat/mediatek/mt8173/plat_pm.c
@@ -27,6 +27,7 @@
 #include <spm_hotplug.h>
 #include <spm_mcdi.h>
 #include <spm_suspend.h>
+#include <wdt.h>
 
 #define MTK_PWR_LVL0	0
 #define MTK_PWR_LVL1	1
@@ -350,6 +351,7 @@
 	}
 
 	if (MTK_SYSTEM_PWR_STATE(state) == MTK_LOCAL_STATE_OFF) {
+		wdt_suspend();
 		disable_scu(mpidr);
 		generic_timer_backup();
 		spm_system_suspend();
@@ -409,6 +411,7 @@
 		plat_arm_gic_init();
 		spm_system_suspend_finish();
 		enable_scu(mpidr);
+		wdt_resume();
 	}
 
 	/* Perform the common cluster specific operations */
@@ -455,11 +458,7 @@
 	/* Write the System Configuration Control Register */
 	INFO("MTK System Reset\n");
 
-	mmio_clrsetbits_32(MTK_WDT_BASE,
-		(MTK_WDT_MODE_DUAL_MODE | MTK_WDT_MODE_IRQ),
-		MTK_WDT_MODE_KEY);
-	mmio_setbits_32(MTK_WDT_BASE, (MTK_WDT_MODE_KEY | MTK_WDT_MODE_EXTEN));
-	mmio_setbits_32(MTK_WDT_SWRST, MTK_WDT_SWRST_KEY);
+	wdt_trigger_reset();
 
 	wfi();
 	ERROR("MTK System Reset: operation not handled.\n");
diff --git a/plat/mediatek/mt8173/plat_sip_calls.c b/plat/mediatek/mt8173/plat_sip_calls.c
index 102feb2..da9b91d 100644
--- a/plat/mediatek/mt8173/plat_sip_calls.c
+++ b/plat/mediatek/mt8173/plat_sip_calls.c
@@ -12,6 +12,7 @@
 #include <mtcmos.h>
 #include <mtk_sip_svc.h>
 #include <plat_sip_calls.h>
+#include <wdt.h>
 
 /* Authorized secure register list */
 enum {
@@ -102,6 +103,9 @@
 		ret = crypt_clear_hdcp_key();
 		SMC_RET1(handle, ret);
 
+	case MTK_SIP_SMC_WATCHDOG:
+		return wdt_smc_handler(x1, x2, handle);
+
 	default:
 		ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
 		break;
diff --git a/plat/mediatek/mt8173/platform.mk b/plat/mediatek/mt8173/platform.mk
index a66c49b..f62802c 100644
--- a/plat/mediatek/mt8173/platform.mk
+++ b/plat/mediatek/mt8173/platform.mk
@@ -15,6 +15,7 @@
 				-I${MTK_PLAT_SOC}/drivers/rtc/			\
 				-I${MTK_PLAT_SOC}/drivers/spm/			\
 				-I${MTK_PLAT_SOC}/drivers/timer/		\
+				-I${MTK_PLAT_SOC}/drivers/wdt/			\
 				-I${MTK_PLAT_SOC}/include/
 
 PLAT_BL_COMMON_SOURCES	:=	lib/xlat_tables/xlat_tables_common.c		\
@@ -50,6 +51,7 @@
 				${MTK_PLAT_SOC}/drivers/spm/spm_mcdi.c		\
 				${MTK_PLAT_SOC}/drivers/spm/spm_suspend.c	\
 				${MTK_PLAT_SOC}/drivers/timer/mt_cpuxgpt.c	\
+				${MTK_PLAT_SOC}/drivers/wdt/wdt.c		\
 				${MTK_PLAT_SOC}/plat_pm.c			\
 				${MTK_PLAT_SOC}/plat_sip_calls.c		\
 				${MTK_PLAT_SOC}/plat_topology.c			\
diff --git a/plat/mediatek/mt8183/bl31_plat_setup.c b/plat/mediatek/mt8183/bl31_plat_setup.c
index 8204d77..e96b4ad 100644
--- a/plat/mediatek/mt8183/bl31_plat_setup.c
+++ b/plat/mediatek/mt8183/bl31_plat_setup.c
@@ -112,7 +112,7 @@
 void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
 				u_register_t arg2, u_register_t arg3)
 {
-	static console_16550_t console;
+	static console_t console;
 
 	params_early_setup(arg1);
 
diff --git a/plat/mediatek/mt8183/drivers/emi_mpu/emi_mpu.c b/plat/mediatek/mt8183/drivers/emi_mpu/emi_mpu.c
index 64d8548..56d2ce2 100644
--- a/plat/mediatek/mt8183/drivers/emi_mpu/emi_mpu.c
+++ b/plat/mediatek/mt8183/drivers/emi_mpu/emi_mpu.c
@@ -138,15 +138,9 @@
 				(FORBIDDEN << 6));
 	emi_mpu_set_region_protection(0x52900000UL, 0x5FFFFFFFUL, 2,
 				(FORBIDDEN << 3 | FORBIDDEN << 6));
-	emi_mpu_set_region_protection(0x60000000UL, 0x7FFFFFFFUL, 3,
-				(FORBIDDEN << 3 | FORBIDDEN << 6));
-	emi_mpu_set_region_protection(0x80000000UL, 0x9FFFFFFFUL, 4,
-				(FORBIDDEN << 3 | FORBIDDEN << 6));
-	emi_mpu_set_region_protection(0xA0000000UL, 0xBFFFFFFFUL, 5,
-				(FORBIDDEN << 3 | FORBIDDEN << 6));
-	emi_mpu_set_region_protection(0xC0000000UL, 0xDFFFFFFFUL, 6,
+	emi_mpu_set_region_protection(0x60000000UL, 0xFFFFFFFFUL, 3,
 				(FORBIDDEN << 3 | FORBIDDEN << 6));
-	emi_mpu_set_region_protection(0xE0000000UL, 0xFFFFFFFFUL, 7,
+	emi_mpu_set_region_protection(0x100000000UL, 0x23FFFFFFFUL, 4,
 				(FORBIDDEN << 3 | FORBIDDEN << 6));
 	dump_emi_mpu_regions();
 }
diff --git a/plat/nvidia/tegra/common/aarch64/tegra_helpers.S b/plat/nvidia/tegra/common/aarch64/tegra_helpers.S
index 13ca6aa..7cba3a4 100644
--- a/plat/nvidia/tegra/common/aarch64/tegra_helpers.S
+++ b/plat/nvidia/tegra/common/aarch64/tegra_helpers.S
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -18,21 +19,16 @@
 /*******************************************************************************
  * Implementation defined ACTLR_EL3 bit definitions
  ******************************************************************************/
-#define ACTLR_EL3_L2ACTLR_BIT		(U(1) << 6)
-#define ACTLR_EL3_L2ECTLR_BIT		(U(1) << 5)
-#define ACTLR_EL3_L2CTLR_BIT		(U(1) << 4)
-#define ACTLR_EL3_CPUECTLR_BIT		(U(1) << 1)
-#define ACTLR_EL3_CPUACTLR_BIT		(U(1) << 0)
-#define ACTLR_EL3_ENABLE_ALL_MASK	(ACTLR_EL3_L2ACTLR_BIT | \
-								ACTLR_EL3_L2ECTLR_BIT | \
-					 			ACTLR_EL3_L2CTLR_BIT | \
-					 			ACTLR_EL3_CPUECTLR_BIT | \
-					 			ACTLR_EL3_CPUACTLR_BIT)
-#define ACTLR_EL3_ENABLE_ALL_ACCESS	(ACTLR_EL3_L2ACTLR_BIT | \
-					 			ACTLR_EL3_L2ECTLR_BIT | \
-					 			ACTLR_EL3_L2CTLR_BIT | \
-					 			ACTLR_EL3_CPUECTLR_BIT | \
-					 			ACTLR_EL3_CPUACTLR_BIT)
+#define ACTLR_ELx_L2ACTLR_BIT		(U(1) << 6)
+#define ACTLR_ELx_L2ECTLR_BIT		(U(1) << 5)
+#define ACTLR_ELx_L2CTLR_BIT		(U(1) << 4)
+#define ACTLR_ELx_CPUECTLR_BIT		(U(1) << 1)
+#define ACTLR_ELx_CPUACTLR_BIT		(U(1) << 0)
+#define ACTLR_ELx_ENABLE_ALL_ACCESS	(ACTLR_ELx_L2ACTLR_BIT | \
+					 ACTLR_ELx_L2ECTLR_BIT | \
+					 ACTLR_ELx_L2CTLR_BIT | \
+					 ACTLR_ELx_CPUECTLR_BIT | \
+					 ACTLR_ELx_CPUACTLR_BIT)
 
 	/* Global functions */
 	.globl	plat_is_my_cpu_primary
@@ -93,15 +89,11 @@
 	 * -------------------------------------------------------
 	 */
 	mrs	x0, actlr_el3
-	mov	x1, #ACTLR_EL3_ENABLE_ALL_MASK
-	bic	x0, x0, x1
-	mov	x1, #ACTLR_EL3_ENABLE_ALL_ACCESS
+	mov	x1, #ACTLR_ELx_ENABLE_ALL_ACCESS
 	orr	x0, x0, x1
 	msr	actlr_el3, x0
 	mrs	x0, actlr_el2
-	mov	x1, #ACTLR_EL3_ENABLE_ALL_MASK
-	bic	x0, x0, x1
-	mov	x1, #ACTLR_EL3_ENABLE_ALL_ACCESS
+	mov	x1, #ACTLR_ELx_ENABLE_ALL_ACCESS
 	orr	x0, x0, x1
 	msr	actlr_el2, x0
 	isb
diff --git a/plat/nvidia/tegra/common/drivers/spe/shared_console.S b/plat/nvidia/tegra/common/drivers/spe/shared_console.S
index 0be34e4..6df73ec 100644
--- a/plat/nvidia/tegra/common/drivers/spe/shared_console.S
+++ b/plat/nvidia/tegra/common/drivers/spe/shared_console.S
@@ -49,14 +49,14 @@
 	/* -------------------------------------------------
 	 * int console_spe_register(uintptr_t baseaddr,
 	 *     uint32_t clock, uint32_t baud,
-	 *     console_spe_t *console);
+	 *     console_t *console);
 	 * Function to initialize and register a new spe
 	 * console. Storage passed in for the console struct
 	 * *must* be persistent (i.e. not from the stack).
 	 * In: x0 - UART register base address
 	 *     w1 - UART clock in Hz
 	 *     w2 - Baud rate
-	 *     x3 - pointer to empty console_spe_t struct
+	 *     x3 - pointer to empty console_t struct
 	 * Out: return 1 on success, 0 on error
 	 * Clobber list : x0, x1, x2, x6, x7, x14
 	 * -------------------------------------------------
@@ -69,7 +69,7 @@
 	check_if_console_is_ready x0, x1, x2, register_fail
 
 	cbz	x3, register_fail
-	str	x0, [x3, #CONSOLE_T_DRVDATA]
+	str	x0, [x3, #CONSOLE_T_BASE]
 	mov	x0, x3
 	finish_console_register spe putc=1, getc=1, flush=1
 
@@ -122,7 +122,7 @@
 endfunc console_spe_core_putc
 
 	/* --------------------------------------------------------
-	 * int console_spe_putc(int c, console_spe_t *console)
+	 * int console_spe_putc(int c, console_t *console)
 	 * Function to output a character over the console. It
 	 * returns the character printed on success or -1 on error.
 	 * In : w0 - character to be printed
@@ -132,12 +132,12 @@
 	 * --------------------------------------------------------
 	 */
 func console_spe_putc
-	ldr	x1, [x1, #CONSOLE_T_DRVDATA]
+	ldr	x1, [x1, #CONSOLE_T_BASE]
 	b	console_spe_core_putc
 endfunc console_spe_putc
 
 	/* ---------------------------------------------
-	 * int console_spe_getc(console_spe_t *console)
+	 * int console_spe_getc(console_t *console)
 	 * Function to get a character from the console.
 	 * It returns the character grabbed on success
 	 * or -1 if no character is available.
@@ -174,7 +174,7 @@
 endfunc console_spe_core_flush
 
 	/* ---------------------------------------------
-	 * int console_spe_flush(console_spe_t *console)
+	 * int console_spe_flush(console_t *console)
 	 * Function to force a write of all buffered
 	 * data that hasn't been output.
 	 * In : x0 - pointer to console_t structure
@@ -183,6 +183,6 @@
 	 * ---------------------------------------------
 	 */
 func console_spe_flush
-	ldr	x0, [x0, #CONSOLE_T_DRVDATA]
+	ldr	x0, [x0, #CONSOLE_T_BASE]
 	b	console_spe_core_flush
 endfunc console_spe_flush
diff --git a/plat/nvidia/tegra/common/tegra_fiq_glue.c b/plat/nvidia/tegra/common/tegra_fiq_glue.c
index 60b5595..dee99fb 100644
--- a/plat/nvidia/tegra/common/tegra_fiq_glue.c
+++ b/plat/nvidia/tegra/common/tegra_fiq_glue.c
@@ -1,5 +1,6 @@
 /*
- * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -12,7 +13,6 @@
 #include <common/debug.h>
 #include <context.h>
 #include <denver.h>
-#include <lib/bakery_lock.h>
 #include <lib/el3_runtime/context_mgmt.h>
 #include <plat/common/platform.h>
 
@@ -25,8 +25,6 @@
 /* Legacy FIQ used by earlier Tegra platforms */
 #define LEGACY_FIQ_PPI_WDT		28U
 
-static DEFINE_BAKERY_LOCK(tegra_fiq_lock);
-
 /*******************************************************************************
  * Static variables
  ******************************************************************************/
@@ -57,8 +55,6 @@
 	 */
 	irq = plat_ic_get_pending_interrupt_id();
 
-	bakery_lock_get(&tegra_fiq_lock);
-
 	/*
 	 * Jump to NS world only if the NS world's FIQ handler has
 	 * been registered
@@ -107,8 +103,6 @@
 		plat_ic_end_of_interrupt(irq);
 	}
 
-	bakery_lock_release(&tegra_fiq_lock);
-
 	return 0;
 }
 
@@ -155,7 +149,7 @@
 {
 	cpu_context_t *ctx = cm_get_context(NON_SECURE);
 	gp_regs_t *gpregs_ctx = get_gpregs_ctx(ctx);
-	const el1_sys_regs_t *el1state_ctx = get_sysregs_ctx(ctx);
+	const el1_sysregs_t *el1state_ctx = get_el1_sysregs_ctx(ctx);
 	uint32_t cpu = plat_my_core_pos();
 	uint64_t val;
 
diff --git a/plat/nvidia/tegra/include/drivers/pmc.h b/plat/nvidia/tegra/include/drivers/pmc.h
index 32252a2..8752b84 100644
--- a/plat/nvidia/tegra/include/drivers/pmc.h
+++ b/plat/nvidia/tegra/include/drivers/pmc.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -18,27 +19,37 @@
 #define PMC_DPD_ENABLE_0			U(0x24)
 #define PMC_PWRGATE_STATUS			U(0x38)
 #define PMC_PWRGATE_TOGGLE			U(0x30)
-#define PMC_SECURE_SCRATCH0			U(0xb0)
-#define PMC_SECURE_SCRATCH5			U(0xc4)
+#define PMC_SCRATCH1				U(0x54)
 #define PMC_CRYPTO_OP_0				U(0xf4)
 #define  PMC_TOGGLE_START			U(0x100)
+#define PMC_SCRATCH31				U(0x118)
+#define PMC_SCRATCH32				U(0x11C)
+#define PMC_SCRATCH33				U(0x120)
 #define PMC_SCRATCH39				U(0x138)
+#define PMC_SCRATCH40				U(0x13C)
 #define PMC_SCRATCH41 				U(0x140)
-#define PMC_SECURE_SCRATCH6			U(0x224)
-#define PMC_SECURE_SCRATCH7			U(0x228)
-#define PMC_SECURE_DISABLE2			U(0x2c4)
+#define PMC_SCRATCH42				U(0x144)
+#define PMC_SCRATCH43				U(0x22C)
+#define PMC_SCRATCH44				U(0x230)
+#define PMC_SCRATCH45				U(0x234)
+#define PMC_SCRATCH46				U(0x238)
+#define PMC_SCRATCH47				U(0x23C)
+#define PMC_SCRATCH48				U(0x240)
+#define PMC_SCRATCH50				U(0x248)
+#define PMC_SCRATCH51				U(0x24C)
+#define PMC_TSC_MULT_0				U(0x2B4)
+#define PMC_STICKY_BIT				U(0x2C0)
+#define PMC_SECURE_DISABLE2			U(0x2C4)
 #define  PMC_SECURE_DISABLE2_WRITE22_ON		(U(1) << 28)
-#define PMC_SECURE_SCRATCH8			U(0x300)
-#define PMC_SECURE_SCRATCH79			U(0x41c)
 #define PMC_FUSE_CONTROL_0			U(0x450)
-#define PMC_SECURE_SCRATCH22			U(0x338)
-#define PMC_SECURE_DISABLE3			U(0x2d8)
+#define PMC_SECURE_DISABLE3			U(0x2D8)
 #define  PMC_SECURE_DISABLE3_WRITE34_ON		(U(1) << 20)
 #define  PMC_SECURE_DISABLE3_WRITE35_ON		(U(1) << 22)
+#define PMC_SECURE_SCRATCH22			U(0x338)
 #define PMC_SECURE_SCRATCH34			U(0x368)
 #define PMC_SECURE_SCRATCH35			U(0x36c)
-#define PMC_SECURE_SCRATCH80			U(0xa98)
-#define PMC_SECURE_SCRATCH119			U(0xb34)
+#define PMC_SCRATCH56				U(0x600)
+#define PMC_SCRATCH57				U(0x604)
 #define PMC_SCRATCH201				U(0x844)
 
 static inline uint32_t tegra_pmc_read_32(uint32_t off)
diff --git a/plat/nvidia/tegra/include/drivers/security_engine.h b/plat/nvidia/tegra/include/drivers/security_engine.h
index 8a24924..5ae6257 100644
--- a/plat/nvidia/tegra/include/drivers/security_engine.h
+++ b/plat/nvidia/tegra/include/drivers/security_engine.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
- * Copyright (c) 2017, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2017-2020, NVIDIA CORPORATION.  All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -55,5 +55,6 @@
 int tegra_se_suspend(void);
 void tegra_se_resume(void);
 int tegra_se_save_tzram(void);
+int32_t tegra_se_save_sha256_hash(uint64_t bl31_base, uint32_t src_len_inbyte);
 
 #endif /* SECURITY_ENGINE_H */
diff --git a/plat/nvidia/tegra/include/drivers/spe.h b/plat/nvidia/tegra/include/drivers/spe.h
index 0d6d69d..e0f8714 100644
--- a/plat/nvidia/tegra/include/drivers/spe.h
+++ b/plat/nvidia/tegra/include/drivers/spe.h
@@ -11,11 +11,6 @@
 
 #include <drivers/console.h>
 
-typedef struct {
-	console_t console;
-	uintptr_t base;
-} console_spe_t;
-
 /*
  * Initialize a new spe console instance and register it with the console
  * framework. The |console| pointer must point to storage that will be valid
@@ -23,6 +18,6 @@
  * Its contents will be reinitialized from scratch.
  */
 int console_spe_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud,
-			   console_spe_t *console);
+			 console_t *console);
 
 #endif /* SPE_H */
diff --git a/plat/nvidia/tegra/include/t186/tegra_def.h b/plat/nvidia/tegra/include/t186/tegra_def.h
index f2a2334..3d037e1 100644
--- a/plat/nvidia/tegra/include/t186/tegra_def.h
+++ b/plat/nvidia/tegra/include/t186/tegra_def.h
@@ -213,6 +213,14 @@
 #define  RNG_MUTEX_WATCHDOG_NS_LIMIT	U(0xFE0)
 
 /*******************************************************************************
+ * Tegra HSP doorbell #0 constants
+ ******************************************************************************/
+#define TEGRA_HSP_DBELL_BASE		U(0x03C90000)
+#define HSP_DBELL_1_ENABLE		U(0x104)
+#define HSP_DBELL_3_TRIGGER		U(0x300)
+#define HSP_DBELL_3_ENABLE		U(0x304)
+
+/*******************************************************************************
  * Tegra Clock and Reset Controller constants
  ******************************************************************************/
 #define TEGRA_CAR_RESET_BASE		U(0x05000000)
@@ -238,6 +246,7 @@
  * Tegra scratch registers constants
  ******************************************************************************/
 #define TEGRA_SCRATCH_BASE		U(0x0C390000)
+#define  SECURE_SCRATCH_RSV0_HI		U(0x654)
 #define  SECURE_SCRATCH_RSV1_LO		U(0x658)
 #define  SECURE_SCRATCH_RSV1_HI		U(0x65C)
 #define  SECURE_SCRATCH_RSV6		U(0x680)
@@ -247,6 +256,15 @@
 #define  SECURE_SCRATCH_RSV53_HI	U(0x7FC)
 #define  SECURE_SCRATCH_RSV55_LO	U(0x808)
 #define  SECURE_SCRATCH_RSV55_HI	U(0x80C)
+#define  SECURE_SCRATCH_RSV63_LO	U(0x848)
+#define  SECURE_SCRATCH_RSV63_HI	U(0x84C)
+#define  SECURE_SCRATCH_RSV64_LO	U(0x850)
+#define  SECURE_SCRATCH_RSV64_HI	U(0x854)
+#define  SECURE_SCRATCH_RSV65_LO	U(0x858)
+#define  SECURE_SCRATCH_RSV65_HI	U(0x85c)
+#define  SECURE_SCRATCH_RSV66_LO	U(0x860)
+#define  SECURE_SCRATCH_RSV66_HI	U(0x864)
+#define  SECURE_SCRATCH_RSV68_LO	U(0x870)
 
 #define SCRATCH_RESET_VECTOR_LO		SECURE_SCRATCH_RSV1_LO
 #define SCRATCH_RESET_VECTOR_HI		SECURE_SCRATCH_RSV1_HI
@@ -281,6 +299,13 @@
 #define TEGRA_TZRAM_SIZE		U(0x40000)
 
 /*******************************************************************************
+ * Tegra CCPLEX-BPMP IPC constants
+ ******************************************************************************/
+#define TEGRA_BPMP_IPC_TX_PHYS_BASE	U(0x3004C000)
+#define TEGRA_BPMP_IPC_RX_PHYS_BASE	U(0x3004D000)
+#define TEGRA_BPMP_IPC_CH_MAP_SIZE	U(0x1000) /* 4KB */
+
+/*******************************************************************************
  * Tegra DRAM memory base address
  ******************************************************************************/
 #define TEGRA_DRAM_BASE			ULL(0x80000000)
diff --git a/plat/nvidia/tegra/include/t210/tegra_def.h b/plat/nvidia/tegra/include/t210/tegra_def.h
index 4a39aa1..e8bce5e 100644
--- a/plat/nvidia/tegra/include/t210/tegra_def.h
+++ b/plat/nvidia/tegra/include/t210/tegra_def.h
@@ -144,6 +144,9 @@
 #define  SE_CLK_ENB_BIT			(U(1) << 31)
 #define TEGRA_CLK_OUT_ENB_W		U(0x364)
 #define  ENTROPY_RESET_BIT 		(U(1) << 21)
+#define TEGRA_CLK_RST_CTL_CLK_SRC_SE	U(0x42C)
+#define  SE_CLK_SRC_MASK		(U(7) << 29)
+#define  SE_CLK_SRC_CLK_M		(U(6) << 29)
 #define TEGRA_RST_DEV_SET_V		U(0x430)
 #define  SE_RESET_BIT			(U(1) << 31)
 #define  HDA_RESET_BIT			(U(1) << 29)
diff --git a/plat/nvidia/tegra/soc/t132/plat_setup.c b/plat/nvidia/tegra/soc/t132/plat_setup.c
index 4bfc2de..43acdd6 100644
--- a/plat/nvidia/tegra/soc/t132/plat_setup.c
+++ b/plat/nvidia/tegra/soc/t132/plat_setup.c
@@ -92,7 +92,7 @@
  ******************************************************************************/
 void plat_enable_console(int32_t id)
 {
-	static console_16550_t uart_console;
+	static console_t uart_console;
 	uint32_t console_clock;
 
 	if ((id > 0) && (id < TEGRA132_MAX_UART_PORTS)) {
@@ -109,7 +109,7 @@
 					     console_clock,
 					     TEGRA_CONSOLE_BAUDRATE,
 					     &uart_console);
-		console_set_scope(&uart_console.console, CONSOLE_FLAG_BOOT |
+		console_set_scope(&uart_console, CONSOLE_FLAG_BOOT |
 			CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH);
 	}
 }
diff --git a/plat/nvidia/tegra/soc/t186/drivers/se/se.c b/plat/nvidia/tegra/soc/t186/drivers/se/se.c
new file mode 100644
index 0000000..dfb9de8
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t186/drivers/se/se.c
@@ -0,0 +1,278 @@
+/*
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <drivers/delay_timer.h>
+#include <errno.h>
+#include <string.h>
+
+#include <bpmp_ipc.h>
+#include <pmc.h>
+#include <security_engine.h>
+#include <tegra186_private.h>
+#include <tegra_private.h>
+
+#include "se_private.h"
+
+/*******************************************************************************
+ * Constants and Macros
+ ******************************************************************************/
+#define SE0_MAX_BUSY_TIMEOUT_MS		U(100)	/* 100ms */
+#define BYTES_IN_WORD			U(4)
+#define SHA256_MAX_HASH_RESULT		U(7)
+#define SHA256_DST_SIZE			U(32)
+#define SHA_FIRST_OP			U(1)
+#define MAX_SHA_ENGINE_CHUNK_SIZE	U(0xFFFFFF)
+#define SHA256_MSG_LENGTH_ONETIME	U(0xffff)
+
+/*
+ * Check that SE operation has completed after kickoff
+ * This function is invoked after an SE operation has been started,
+ * and it checks the following conditions:
+ * 1. SE0_INT_STATUS = SE0_OP_DONE
+ * 2. SE0_STATUS = IDLE
+ * 3. SE0_ERR_STATUS is clean.
+ */
+static int32_t tegra_se_operation_complete(void)
+{
+	uint32_t val = 0U;
+
+	/* Read SE0 interrupt register to ensure H/W operation complete */
+	val = tegra_se_read_32(SE0_INT_STATUS_REG_OFFSET);
+	if (SE0_INT_OP_DONE(val) == SE0_INT_OP_DONE_CLEAR) {
+		ERROR("%s: Engine busy state too many times! val = 0x%x\n",
+			__func__, val);
+		return -ETIMEDOUT;
+	}
+
+	/* Read SE0 status idle to ensure H/W operation complete */
+	val = tegra_se_read_32(SE0_SHA_STATUS_0);
+	if (val != SE0_SHA_STATUS_IDLE) {
+		ERROR("%s: Idle state timeout! val = 0x%x\n", __func__,
+			val);
+		return -ETIMEDOUT;
+	}
+
+	/* Ensure that no errors are thrown during operation */
+	val = tegra_se_read_32(SE0_ERR_STATUS_REG_OFFSET);
+	if (val != SE0_ERR_STATUS_CLEAR) {
+		ERROR("%s: Error during SE operation! val = 0x%x",
+			__func__, val);
+		return -ENOTSUP;
+	}
+
+	return 0;
+}
+
+/*
+ * Security engine primitive normal operations
+ */
+static int32_t tegra_se_start_normal_operation(uint64_t src_addr,
+		uint32_t nbytes, uint32_t last_buf, uint32_t src_len_inbytes)
+{
+	int32_t ret = 0;
+	uint32_t val = 0U;
+	uint32_t src_in_lo;
+	uint32_t src_in_msb;
+	uint32_t src_in_hi;
+
+	if ((src_addr == 0UL) || (nbytes == 0U))
+		return -EINVAL;
+
+	src_in_lo = (uint32_t)src_addr;
+	src_in_msb = ((uint32_t)(src_addr >> 32U) & 0xffU);
+	src_in_hi = ((src_in_msb << SE0_IN_HI_ADDR_HI_0_MSB_SHIFT) |
+				(nbytes & 0xffffffU));
+
+	/* set SRC_IN_ADDR_LO and SRC_IN_ADDR_HI*/
+	tegra_se_write_32(SE0_IN_ADDR, src_in_lo);
+	tegra_se_write_32(SE0_IN_HI_ADDR_HI, src_in_hi);
+
+	val = tegra_se_read_32(SE0_INT_STATUS_REG_OFFSET);
+	if (val > 0U) {
+		tegra_se_write_32(SE0_INT_STATUS_REG_OFFSET, 0x00000U);
+	}
+
+	/* Enable SHA interrupt for SE0 Operation */
+	tegra_se_write_32(SE0_SHA_INT_ENABLE, 0x1aU);
+
+	/* flush to DRAM for SE to use the updated contents */
+	flush_dcache_range(src_addr, src_len_inbytes);
+
+	/* Start SHA256 operation */
+	if (last_buf == 1U) {
+		tegra_se_write_32(SE0_OPERATION_REG_OFFSET, SE0_OP_START |
+				SE0_UNIT_OPERATION_PKT_LASTBUF_FIELD);
+	} else {
+		tegra_se_write_32(SE0_OPERATION_REG_OFFSET, SE0_OP_START);
+	}
+
+	/* Wait for SE-operation to finish */
+	udelay(SE0_MAX_BUSY_TIMEOUT_MS * 100U);
+
+	/* Check SE0 operation status */
+	ret = tegra_se_operation_complete();
+	if (ret != 0) {
+		ERROR("SE operation complete Failed! 0x%x", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int32_t tegra_se_calculate_sha256_hash(uint64_t src_addr,
+						uint32_t src_len_inbyte)
+{
+	uint32_t val, last_buf, i;
+	int32_t ret = 0;
+	uint32_t operations;
+	uint64_t src_len_inbits;
+	uint32_t len_bits_msb;
+	uint32_t len_bits_lsb;
+	uint32_t number_of_operations, max_bytes, bytes_left, remaining_bytes;
+
+	if (src_len_inbyte > MAX_SHA_ENGINE_CHUNK_SIZE) {
+		ERROR("SHA input chunk size too big: 0x%x\n", src_len_inbyte);
+		return -EINVAL;
+	}
+
+	if (src_addr == 0UL) {
+		return -EINVAL;
+	}
+
+	/* number of bytes per operation */
+	max_bytes = SHA256_HASH_SIZE_BYTES * SHA256_MSG_LENGTH_ONETIME;
+
+	src_len_inbits = src_len_inbyte * 8U;
+	len_bits_msb = (uint32_t)(src_len_inbits >> 32U);
+	len_bits_lsb = (uint32_t)(src_len_inbits & 0xFFFFFFFF);
+
+	/* program SE0_CONFIG for SHA256 operation */
+	val = SE0_CONFIG_ENC_ALG_SHA | SE0_CONFIG_ENC_MODE_SHA256 |
+		SE0_CONFIG_DEC_ALG_NOP | SE0_CONFIG_DST_HASHREG;
+	tegra_se_write_32(SE0_SHA_CONFIG, val);
+
+	/* set SE0_SHA_MSG_LENGTH registers */
+	tegra_se_write_32(SE0_SHA_MSG_LENGTH_0, len_bits_lsb);
+	tegra_se_write_32(SE0_SHA_MSG_LEFT_0, len_bits_lsb);
+	tegra_se_write_32(SE0_SHA_MSG_LENGTH_1, len_bits_msb);
+
+	/* zero out unused SE0_SHA_MSG_LENGTH and SE0_SHA_MSG_LEFT */
+	tegra_se_write_32(SE0_SHA_MSG_LENGTH_2, 0U);
+	tegra_se_write_32(SE0_SHA_MSG_LENGTH_3, 0U);
+	tegra_se_write_32(SE0_SHA_MSG_LEFT_1, 0U);
+	tegra_se_write_32(SE0_SHA_MSG_LEFT_2, 0U);
+	tegra_se_write_32(SE0_SHA_MSG_LEFT_3, 0U);
+
+	number_of_operations = src_len_inbyte / max_bytes;
+	remaining_bytes = src_len_inbyte % max_bytes;
+	if (remaining_bytes > 0U) {
+		number_of_operations += 1U;
+	}
+
+	/*
+	 * 1. Operations == 1:	program SE0_SHA_TASK register to initiate SHA256
+	 *			hash generation by setting
+	 *			1(SE0_SHA_CONFIG_HW_INIT_HASH) to SE0_SHA_TASK
+	 *			and start SHA256-normal operation.
+	 * 2. 1 < Operations < number_of_operations: program SE0_SHA_TASK to
+	 *			0(SE0_SHA_CONFIG_HW_INIT_HASH_DISABLE) to load
+	 *			intermediate SHA256 digest result from
+	 *			HASH_RESULT register to continue SHA256
+	 *			generation and start SHA256-normal operation.
+	 * 3. Operations == number_of_operations: continue with step 2 and set
+	 *			max_bytes to bytes_left to process final
+	 *			hash-result generation and
+	 *			start SHA256-normal operation.
+	 */
+	bytes_left = src_len_inbyte;
+	for (operations = 1U; operations <= number_of_operations;
+								operations++) {
+		if (operations == SHA_FIRST_OP) {
+			val = SE0_SHA_CONFIG_HW_INIT_HASH;
+		} else {
+			/* Load intermediate SHA digest result to
+			 * SHA:HASH_RESULT(0..7) to continue the SHA
+			 * calculation and tell the SHA engine to use it.
+			 */
+			for (i = 0U; (i / BYTES_IN_WORD) <=
+				SHA256_MAX_HASH_RESULT; i += BYTES_IN_WORD) {
+				val = tegra_se_read_32(SE0_SHA_HASH_RESULT_0 +
+									i);
+				tegra_se_write_32(SE0_SHA_HASH_RESULT_0 + i,
+									val);
+			}
+			val = SE0_SHA_CONFIG_HW_INIT_HASH_DISABLE;
+			if (len_bits_lsb <= (max_bytes * 8U)) {
+				len_bits_lsb = (remaining_bytes * 8U);
+			} else {
+				len_bits_lsb -= (max_bytes * 8U);
+			}
+			tegra_se_write_32(SE0_SHA_MSG_LEFT_0, len_bits_lsb);
+		}
+		tegra_se_write_32(SE0_SHA_TASK_CONFIG, val);
+
+		max_bytes = (SHA256_HASH_SIZE_BYTES *
+						SHA256_MSG_LENGTH_ONETIME);
+		if (bytes_left < max_bytes) {
+			max_bytes = bytes_left;
+			last_buf = 1U;
+		} else {
+			bytes_left = bytes_left - max_bytes;
+			last_buf = 0U;
+		}
+		/* start operation */
+		ret = tegra_se_start_normal_operation(src_addr, max_bytes,
+					last_buf, src_len_inbyte);
+		if (ret != 0) {
+			ERROR("Error during SE operation! 0x%x", ret);
+			return -EINVAL;
+		}
+	}
+
+	return ret;
+}
+
+/*
+ * Handler to generate SHA256 and save SHA256 hash to PMC-Scratch register.
+ */
+int32_t tegra_se_save_sha256_hash(uint64_t bl31_base, uint32_t src_len_inbyte)
+{
+	int32_t ret = 0;
+	uint32_t val = 0U, hash_offset = 0U, scratch_offset = 0U, security;
+
+	/*
+	 * Set SE_SOFT_SETTINGS=SE_SECURE to prevent NS process to change SE
+	 * registers.
+	 */
+	security = tegra_se_read_32(SE0_SECURITY);
+	tegra_se_write_32(SE0_SECURITY, security | SE0_SECURITY_SE_SOFT_SETTING);
+
+	ret = tegra_se_calculate_sha256_hash(bl31_base, src_len_inbyte);
+	if (ret != 0L) {
+		ERROR("%s: SHA256 generation failed\n", __func__);
+		return ret;
+	}
+
+	/*
+	 * Reset SE_SECURE to previous value.
+	 */
+	tegra_se_write_32(SE0_SECURITY, security);
+
+	/* read SHA256_HASH_RESULT and save to PMC Scratch registers */
+	scratch_offset = SECURE_SCRATCH_TZDRAM_SHA256_HASH_START;
+	while (scratch_offset <= SECURE_SCRATCH_TZDRAM_SHA256_HASH_END) {
+
+		val = tegra_se_read_32(SE0_SHA_HASH_RESULT_0 + hash_offset);
+		mmio_write_32(TEGRA_SCRATCH_BASE + scratch_offset, val);
+
+		hash_offset += BYTES_IN_WORD;
+		scratch_offset += BYTES_IN_WORD;
+	}
+
+	return ret;
+}
+
diff --git a/plat/nvidia/tegra/soc/t186/drivers/se/se_private.h b/plat/nvidia/tegra/soc/t186/drivers/se/se_private.h
new file mode 100644
index 0000000..7aa0dd6
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t186/drivers/se/se_private.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SE_PRIVATE_H
+#define SE_PRIVATE_H
+
+#include <lib/utils_def.h>
+
+/* SE0 security register */
+#define SE0_SECURITY				U(0x18)
+#define SE0_SECURITY_SE_SOFT_SETTING		(((uint32_t)1) << 16U)
+
+/* SE0 config register */
+#define SE0_SHA_CONFIG				U(0x104)
+#define SE0_SHA_TASK_CONFIG			U(0x108)
+#define SE0_SHA_CONFIG_HW_INIT_HASH		((1U) << 0U)
+#define SE0_SHA_CONFIG_HW_INIT_HASH_DISABLE	U(0)
+
+#define SE0_CONFIG_ENC_ALG_SHIFT		U(12)
+#define SE0_CONFIG_ENC_ALG_SHA	\
+		(((uint32_t)3) << SE0_CONFIG_ENC_ALG_SHIFT)
+#define SE0_CONFIG_DEC_ALG_SHIFT		U(8)
+#define SE0_CONFIG_DEC_ALG_NOP	\
+		(((uint32_t)0) << SE0_CONFIG_DEC_ALG_SHIFT)
+#define SE0_CONFIG_DST_SHIFT			U(2)
+#define SE0_CONFIG_DST_HASHREG	\
+		(((uint32_t)1) << SE0_CONFIG_DST_SHIFT)
+#define SHA256_HASH_SIZE_BYTES			U(256)
+
+#define SE0_CONFIG_ENC_MODE_SHIFT		U(24)
+#define SE0_CONFIG_ENC_MODE_SHA256	\
+			(((uint32_t)5) << SE0_CONFIG_ENC_MODE_SHIFT)
+
+/* SHA input message length */
+#define SE0_SHA_MSG_LENGTH_0			U(0x11c)
+#define SE0_SHA_MSG_LENGTH_1			U(0x120)
+#define SE0_SHA_MSG_LENGTH_2			U(0x124)
+#define SE0_SHA_MSG_LENGTH_3			U(0x128)
+
+/* SHA input message left  */
+#define SE0_SHA_MSG_LEFT_0			U(0x12c)
+#define SE0_SHA_MSG_LEFT_1			U(0x130)
+#define SE0_SHA_MSG_LEFT_2			U(0x134)
+#define SE0_SHA_MSG_LEFT_3			U(0x138)
+
+/* SE Hash Result */
+#define SE0_SHA_HASH_RESULT_0			U(0x13c)
+
+/* SE OPERATION */
+#define SE0_OPERATION_REG_OFFSET		U(0x17c)
+#define SE0_UNIT_OPERATION_PKT_LASTBUF_SHIFT	U(16)
+#define SE0_UNIT_OPERATION_PKT_LASTBUF_FIELD	\
+		(((uint32_t)0x1) << SE0_UNIT_OPERATION_PKT_LASTBUF_SHIFT)
+#define SE0_OPERATION_SHIFT			U(0)
+#define SE0_OP_START	\
+		(((uint32_t)0x1) << SE0_OPERATION_SHIFT)
+
+/* SE Interrupt */
+#define SE0_SHA_INT_ENABLE			U(0x180)
+
+#define SE0_INT_STATUS_REG_OFFSET		U(0x184)
+#define SE0_INT_OP_DONE_SHIFT			U(4)
+#define SE0_INT_OP_DONE_CLEAR	\
+		(((uint32_t)0) << SE0_INT_OP_DONE_SHIFT)
+#define SE0_INT_OP_DONE(x)	\
+		((x) & (((uint32_t)0x1) << SE0_INT_OP_DONE_SHIFT))
+
+/* SE SHA status */
+#define SE0_SHA_STATUS_0			U(0x188)
+#define SE0_SHA_STATUS_IDLE			U(0)
+
+/* SE error status */
+#define SE0_ERR_STATUS_REG_OFFSET		U(0x18c)
+#define SE0_ERR_STATUS_CLEAR			U(0)
+#define SE0_IN_ADDR				U(0x10c)
+#define SE0_IN_HI_ADDR_HI			U(0x110)
+#define SE0_IN_HI_ADDR_HI_0_MSB_SHIFT		U(24)
+
+/* SE error status */
+#define SECURE_SCRATCH_TZDRAM_SHA256_HASH_START	SECURE_SCRATCH_RSV63_LO
+#define SECURE_SCRATCH_TZDRAM_SHA256_HASH_END	SECURE_SCRATCH_RSV66_HI
+
+/*******************************************************************************
+ * Inline functions definition
+ ******************************************************************************/
+
+static inline uint32_t tegra_se_read_32(uint32_t offset)
+{
+	return mmio_read_32((uint32_t)(TEGRA_SE0_BASE + offset));
+}
+
+static inline void tegra_se_write_32(uint32_t offset, uint32_t val)
+{
+	mmio_write_32(((uint32_t)(TEGRA_SE0_BASE + offset)), val);
+}
+
+#endif /* SE_PRIVATE_H */
diff --git a/plat/nvidia/tegra/soc/t186/plat_memctrl.c b/plat/nvidia/tegra/soc/t186/plat_memctrl.c
index 4ca5e77..a97496b 100644
--- a/plat/nvidia/tegra/soc/t186/plat_memctrl.c
+++ b/plat/nvidia/tegra/soc/t186/plat_memctrl.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -10,7 +11,11 @@
 #include <mce.h>
 #include <memctrl_v2.h>
 #include <tegra_mc_def.h>
+#include <tegra186_private.h>
 #include <tegra_platform.h>
+#include <tegra_private.h>
+
+extern uint64_t tegra_bl31_phys_base;
 
 /*******************************************************************************
  * Array to hold stream_id override config register offsets
@@ -540,6 +545,13 @@
 void plat_memctrl_tzdram_setup(uint64_t phys_base, uint64_t size_in_bytes)
 {
 	uint32_t val;
+	uint64_t src_base_tzdram;
+	const plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params();
+	uint64_t src_len_in_bytes = BL31_END - BL31_START;
+
+	/* base address of BL3-1 source in TZDRAM */
+	src_base_tzdram = params_from_bl2->tzdram_base +
+	      tegra186_get_cpu_reset_handler_size();
 
 	/*
 	 * Setup the Memory controller to allow only secure accesses to
@@ -569,6 +581,15 @@
 	mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_TZDRAM_ADDR_HI, val);
 
 	/*
+	 * save tzdram_addr_lo and ATF-size, this would be used in SC7-RF to
+	 * generate SHA256.
+	 */
+	mmio_write_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV68_LO,
+			(uint32_t)src_base_tzdram);
+	mmio_write_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV0_HI,
+			(uint32_t)src_len_in_bytes);
+
+	/*
 	 * MCE propagates the security configuration values across the
 	 * CCPLEX.
 	 */
diff --git a/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c
index 2000e53..a0879cc 100644
--- a/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c
+++ b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c
@@ -6,6 +6,7 @@
  */
 
 #include <assert.h>
+#include <stdbool.h>
 #include <string.h>
 
 #include <arch.h>
@@ -19,9 +20,10 @@
 #include <lib/psci/psci.h>
 #include <plat/common/platform.h>
 
+#include <bpmp_ipc.h>
 #include <mce.h>
+#include <security_engine.h>
 #include <smmu.h>
-#include <stdbool.h>
 #include <t18x_ari.h>
 #include <tegra186_private.h>
 #include <tegra_private.h>
@@ -280,8 +282,33 @@
 	uint8_t stateid_afflvl2 = pwr_domain_state[PLAT_MAX_PWR_LVL] &
 		TEGRA186_STATE_ID_MASK;
 	uint64_t val;
+	uint64_t src_len_in_bytes = (uint64_t)(((uintptr_t)(&__BL31_END__) -
+					(uintptr_t)BL31_BASE));
+	int32_t ret;
 
 	if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) {
+		val = params_from_bl2->tzdram_base +
+		      tegra186_get_cpu_reset_handler_size();
+
+		/* Initialise communication channel with BPMP */
+		assert(tegra_bpmp_ipc_init() == 0);
+
+		/* Enable SE clock */
+		ret = tegra_bpmp_ipc_enable_clock(TEGRA_CLK_SE);
+		if (ret != 0) {
+			ERROR("Failed to enable clock\n");
+			return ret;
+		}
+
+		/*
+		 * Generate/save SHA256 of ATF during SC7 entry
+		 */
+		if (tegra_se_save_sha256_hash(BL31_BASE,
+					(uint32_t)src_len_in_bytes) != 0) {
+			ERROR("Hash calculation failed. Reboot\n");
+			(void)tegra_soc_prepare_system_reset();
+		}
+
 		/*
 		 * The TZRAM loses power when we enter system suspend. To
 		 * allow graceful exit from system suspend, we need to copy
@@ -291,6 +318,12 @@
 			tegra186_get_cpu_reset_handler_size();
 		memcpy16((void *)(uintptr_t)val, (void *)(uintptr_t)BL31_BASE,
 			 (uintptr_t)BL31_END - (uintptr_t)BL31_BASE);
+
+		ret = tegra_bpmp_ipc_disable_clock(TEGRA_CLK_SE);
+		if (ret != 0) {
+			ERROR("Failed to disable clock\n");
+			return ret;
+		}
 	}
 
 	return PSCI_E_SUCCESS;
diff --git a/plat/nvidia/tegra/soc/t186/plat_setup.c b/plat/nvidia/tegra/soc/t186/plat_setup.c
index 06a3284..e5d0d01 100644
--- a/plat/nvidia/tegra/soc/t186/plat_setup.c
+++ b/plat/nvidia/tegra/soc/t186/plat_setup.c
@@ -106,6 +106,12 @@
 			MT_DEVICE | MT_RW | MT_SECURE),
 	MAP_REGION_FLAT(TEGRA_SMMU0_BASE, 0x1000000U, /* 64KB */
 			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(TEGRA_HSP_DBELL_BASE, 0x10000U, /* 64KB */
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(TEGRA_BPMP_IPC_TX_PHYS_BASE, TEGRA_BPMP_IPC_CH_MAP_SIZE, /* 4KB */
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(TEGRA_BPMP_IPC_RX_PHYS_BASE, TEGRA_BPMP_IPC_CH_MAP_SIZE, /* 4KB */
+			MT_DEVICE | MT_RW | MT_SECURE),
 	{0}
 };
 
@@ -150,7 +156,7 @@
  ******************************************************************************/
 void plat_enable_console(int32_t id)
 {
-	static console_16550_t uart_console;
+	static console_t uart_console;
 	uint32_t console_clock;
 
 	if ((id > 0) && (id < TEGRA186_MAX_UART_PORTS)) {
@@ -167,7 +173,7 @@
 					     console_clock,
 					     TEGRA_CONSOLE_BAUDRATE,
 					     &uart_console);
-		console_set_scope(&uart_console.console, CONSOLE_FLAG_BOOT |
+		console_set_scope(&uart_console, CONSOLE_FLAG_BOOT |
 			CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH);
 	}
 }
diff --git a/plat/nvidia/tegra/soc/t186/platform_t186.mk b/plat/nvidia/tegra/soc/t186/platform_t186.mk
index 197e4c6..d79155f 100644
--- a/plat/nvidia/tegra/soc/t186/platform_t186.mk
+++ b/plat/nvidia/tegra/soc/t186/platform_t186.mk
@@ -30,10 +30,10 @@
 PLATFORM_MAX_CPUS_PER_CLUSTER		:= 4
 $(eval $(call add_define,PLATFORM_MAX_CPUS_PER_CLUSTER))
 
-MAX_XLAT_TABLES				:= 24
+MAX_XLAT_TABLES				:= 25
 $(eval $(call add_define,MAX_XLAT_TABLES))
 
-MAX_MMAP_REGIONS			:= 25
+MAX_MMAP_REGIONS			:= 27
 $(eval $(call add_define,MAX_MMAP_REGIONS))
 
 # platform files
@@ -42,6 +42,8 @@
 BL31_SOURCES		+=	drivers/ti/uart/aarch64/16550_console.S	\
 				lib/cpus/aarch64/denver.S		\
 				lib/cpus/aarch64/cortex_a57.S		\
+				${COMMON_DIR}/drivers/bpmp_ipc/intf.c   \
+				${COMMON_DIR}/drivers/bpmp_ipc/ivc.c    \
 				${COMMON_DIR}/drivers/gpcdma/gpcdma.c	\
 				${COMMON_DIR}/drivers/memctrl/memctrl_v2.c \
 				${COMMON_DIR}/drivers/smmu/smmu.c	\
@@ -49,6 +51,7 @@
 				${SOC_DIR}/drivers/mce/ari.c		\
 				${SOC_DIR}/drivers/mce/nvg.c		\
 				${SOC_DIR}/drivers/mce/aarch64/nvg_helpers.S \
+				$(SOC_DIR)/drivers/se/se.c \
 				${SOC_DIR}/plat_memctrl.c		\
 				${SOC_DIR}/plat_psci_handlers.c		\
 				${SOC_DIR}/plat_setup.c			\
diff --git a/plat/nvidia/tegra/soc/t194/plat_memctrl.c b/plat/nvidia/tegra/soc/t194/plat_memctrl.c
index 2208b85..d5f72b6 100644
--- a/plat/nvidia/tegra/soc/t194/plat_memctrl.c
+++ b/plat/nvidia/tegra/soc/t194/plat_memctrl.c
@@ -138,7 +138,11 @@
 	MC_STREAMID_OVERRIDE_CFG_MIU2R,
 	MC_STREAMID_OVERRIDE_CFG_MIU2W,
 	MC_STREAMID_OVERRIDE_CFG_MIU3R,
-	MC_STREAMID_OVERRIDE_CFG_MIU3W
+	MC_STREAMID_OVERRIDE_CFG_MIU3W,
+	MC_STREAMID_OVERRIDE_CFG_MIU4R,
+	MC_STREAMID_OVERRIDE_CFG_MIU4W,
+	MC_STREAMID_OVERRIDE_CFG_MIU5R,
+	MC_STREAMID_OVERRIDE_CFG_MIU5W
 };
 
 /*******************************************************************************
@@ -268,416 +272,13 @@
 	mc_make_sec_cfg(MIU2R, NON_SECURE, OVERRIDE, DISABLE),
 	mc_make_sec_cfg(MIU2W, NON_SECURE, OVERRIDE, DISABLE),
 	mc_make_sec_cfg(MIU3R, NON_SECURE, OVERRIDE, DISABLE),
-	mc_make_sec_cfg(MIU3W, NON_SECURE, OVERRIDE, DISABLE)
+	mc_make_sec_cfg(MIU3W, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(MIU4R, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(MIU4W, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(MIU5R, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(MIU5W, NON_SECURE, OVERRIDE, DISABLE)
 };
 
-/* To be called by common memctrl_v2.c */
-static void tegra194_memctrl_reconfig_mss_clients(void)
-{
-	uint32_t reg_val, wdata_0, wdata_1, wdata_2;
-
-	wdata_0 = MC_CLIENT_HOTRESET_CTRL0_HC_FLUSH_ENB |
-		  MC_CLIENT_HOTRESET_CTRL0_SATA_FLUSH_ENB |
-		  MC_CLIENT_HOTRESET_CTRL0_VIC_FLUSH_ENB |
-		  MC_CLIENT_HOTRESET_CTRL0_XUSB_HOST_FLUSH_ENB |
-		  MC_CLIENT_HOTRESET_CTRL0_XUSB_DEV_FLUSH_ENB |
-		  MC_CLIENT_HOTRESET_CTRL0_TSEC_FLUSH_ENB |
-		  MC_CLIENT_HOTRESET_CTRL0_SDMMC3A_FLUSH_ENB;
-	if (tegra_platform_is_silicon()) {
-		wdata_0 |= MC_CLIENT_HOTRESET_CTRL0_SDMMC1A_FLUSH_ENB;
-	}
-
-	tegra_mc_write_32(MC_CLIENT_HOTRESET_CTRL0, wdata_0);
-
-	/* Wait for HOTRESET STATUS to indicate FLUSH_DONE */
-	do {
-		reg_val = tegra_mc_read_32(MC_CLIENT_HOTRESET_STATUS0);
-	} while ((reg_val & wdata_0) != wdata_0);
-
-	wdata_1 = MC_CLIENT_HOTRESET_CTRL1_SDMMC4A_FLUSH_ENB |
-		  MC_CLIENT_HOTRESET_CTRL1_SE_FLUSH_ENB |
-		  MC_CLIENT_HOTRESET_CTRL1_ETR_FLUSH_ENB |
-		  MC_CLIENT_HOTRESET_CTRL1_TSECB_FLUSH_ENB|
-		  MC_CLIENT_HOTRESET_CTRL1_AXIS_FLUSH_ENB |
-		  MC_CLIENT_HOTRESET_CTRL1_UFSHC_FLUSH_ENB |
-		  MC_CLIENT_HOTRESET_CTRL1_NVDISPLAY_FLUSH_ENB |
-		  MC_CLIENT_HOTRESET_CTRL1_BPMP_FLUSH_ENB |
-		  MC_CLIENT_HOTRESET_CTRL1_AON_FLUSH_ENB |
-		  MC_CLIENT_HOTRESET_CTRL1_SCE_FLUSH_ENB |
-		  MC_CLIENT_HOTRESET_CTRL1_VIFAL_FLUSH_ENB;
-	if (tegra_platform_is_silicon()) {
-		wdata_1 |= MC_CLIENT_HOTRESET_CTRL1_APE_FLUSH_ENB |
-			MC_CLIENT_HOTRESET_CTRL1_EQOS_FLUSH_ENB |
-			MC_CLIENT_HOTRESET_CTRL1_RCE_FLUSH_ENB;
-	}
-	tegra_mc_write_32(MC_CLIENT_HOTRESET_CTRL1, wdata_1);
-	/* Wait for HOTRESET STATUS to indicate FLUSH_DONE */
-	do {
-		reg_val = tegra_mc_read_32(MC_CLIENT_HOTRESET_STATUS1);
-	} while ((reg_val & wdata_1) != wdata_1);
-
-	wdata_2 = MC_CLIENT_HOTRESET_CTRL2_PCIE_FLUSH_ENB |
-		MC_CLIENT_HOTRESET_CTRL2_AONDMA_FLUSH_ENB |
-		MC_CLIENT_HOTRESET_CTRL2_BPMPDMA_FLUSH_ENB |
-		MC_CLIENT_HOTRESET_CTRL2_SCEDMA_FLUSH_ENB;
-	if (tegra_platform_is_silicon()) {
-		wdata_2 |= MC_CLIENT_HOTRESET_CTRL2_RCEDMA_FLUSH_ENB |
-			MC_CLIENT_HOTRESET_CTRL2_PCIE_FLUSH_ENB |
-			MC_CLIENT_HOTRESET_CTRL2_PCIE5A_FLUSH_ENB |
-			MC_CLIENT_HOTRESET_CTRL2_PCIE3A_FLUSH_ENB |
-			MC_CLIENT_HOTRESET_CTRL2_PCIE3_FLUSH_ENB |
-			MC_CLIENT_HOTRESET_CTRL2_PCIE0A_FLUSH_ENB |
-			MC_CLIENT_HOTRESET_CTRL2_PCIE0A2_FLUSH_ENB |
-			MC_CLIENT_HOTRESET_CTRL2_PCIE4A_FLUSH_ENB;
-	}
-	tegra_mc_write_32(MC_CLIENT_HOTRESET_CTRL2, wdata_2);
-	/* Wait for HOTRESET STATUS to indicate FLUSH_DONE */
-	do {
-		reg_val = tegra_mc_read_32(MC_CLIENT_HOTRESET_STATUS2);
-	} while ((reg_val & wdata_2) != wdata_2);
-
-	/*
-	 * Change MEMTYPE_OVERRIDE from SO_DEV -> PASSTHRU for boot and
-	 * strongly ordered MSS clients.
-	 *
-	 * MC clients with default SO_DEV override still enabled at TSA:
-	 * EQOSW, SATAW, XUSB_DEVW, XUSB_HOSTW, PCIe0w, PCIe1w, PCIe2w,
-	 * PCIe3w, PCIe4w and PCIe5w.
-	 */
-	mc_set_tsa_w_passthrough(AONDMAW);
-	mc_set_tsa_w_passthrough(AONW);
-	mc_set_tsa_w_passthrough(APEDMAW);
-	mc_set_tsa_w_passthrough(APEW);
-	mc_set_tsa_w_passthrough(AXISW);
-	mc_set_tsa_w_passthrough(BPMPDMAW);
-	mc_set_tsa_w_passthrough(BPMPW);
-	mc_set_tsa_w_passthrough(EQOSW);
-	mc_set_tsa_w_passthrough(ETRW);
-	mc_set_tsa_w_passthrough(RCEDMAW);
-	mc_set_tsa_w_passthrough(RCEW);
-	mc_set_tsa_w_passthrough(SCEDMAW);
-	mc_set_tsa_w_passthrough(SCEW);
-	mc_set_tsa_w_passthrough(SDMMCW);
-	mc_set_tsa_w_passthrough(SDMMCWA);
-	mc_set_tsa_w_passthrough(SDMMCWAB);
-	mc_set_tsa_w_passthrough(SESWR);
-	mc_set_tsa_w_passthrough(TSECSWR);
-	mc_set_tsa_w_passthrough(TSECSWRB);
-	mc_set_tsa_w_passthrough(UFSHCW);
-	mc_set_tsa_w_passthrough(VICSWR);
-	mc_set_tsa_w_passthrough(VIFALW);
-	/*
-	 * set HUB2 as SO_DEV_HUBID
-	 */
-	reg_val = tsa_read_32(PCIE0W);
-	mc_set_tsa_hub2(reg_val, PCIE0W);
-	reg_val = tsa_read_32(PCIE1W);
-	mc_set_tsa_hub2(reg_val, PCIE1W);
-	reg_val = tsa_read_32(PCIE2AW);
-	mc_set_tsa_hub2(reg_val, PCIE2AW);
-	reg_val = tsa_read_32(PCIE3W);
-	mc_set_tsa_hub2(reg_val, PCIE3W);
-	reg_val = tsa_read_32(PCIE4W);
-	mc_set_tsa_hub2(reg_val, PCIE4W);
-	reg_val = tsa_read_32(SATAW);
-	mc_set_tsa_hub2(reg_val, SATAW);
-	reg_val = tsa_read_32(XUSB_DEVW);
-	mc_set_tsa_hub2(reg_val, XUSB_DEVW);
-	reg_val = tsa_read_32(XUSB_HOSTW);
-	mc_set_tsa_hub2(reg_val, XUSB_HOSTW);
-
-	/*
-	 * Hw Bug: 200385660, 200394107
-	 * PCIE datapath hangs when there are more than 28 outstanding
-	 * requests on data backbone for x1 controller. This is seen
-	 * on third party PCIE IP, C1 - PCIE1W, C2 - PCIE2AW and C3 - PCIE3W.
-	 *
-	 * Setting Reorder depth limit, 16 which is < 28.
-	 */
-	mc_set_tsa_depth_limit(REORDER_DEPTH_LIMIT, PCIE1W);
-	mc_set_tsa_depth_limit(REORDER_DEPTH_LIMIT, PCIE2AW);
-	mc_set_tsa_depth_limit(REORDER_DEPTH_LIMIT, PCIE3W);
-
-	/* Ordered MC Clients on Xavier are EQOS, SATA, XUSB, PCIe1 and PCIe3
-	 * ISO clients(DISP, VI, EQOS) should never snoop caches and
-	 *     don't need ROC/PCFIFO ordering.
-	 * ISO clients(EQOS) that need ordering should use PCFIFO ordering
-	 *     and bypass ROC ordering by using FORCE_NON_COHERENT path.
-	 * FORCE_NON_COHERENT/FORCE_COHERENT config take precedence
-	 *     over SMMU attributes.
-	 * Force all Normal memory transactions from ISO and non-ISO to be
-	 *     non-coherent(bypass ROC, avoid cache snoop to avoid perf hit).
-	 * Force the SO_DEV transactions from ordered ISO clients(EQOS) to
-	 *     non-coherent path and enable MC PCFIFO interlock for ordering.
-	 * Force the SO_DEV transactions from ordered non-ISO clients (PCIe,
-	 *     XUSB, SATA) to coherent so that the transactions are
-	 *     ordered by ROC.
-	 * PCFIFO ensure write ordering.
-	 * Read after Write ordering is maintained/enforced by MC clients.
-	 * Clients that need PCIe type write ordering must
-	 *     go through ROC ordering.
-	 * Ordering enable for Read clients is not necessary.
-	 * R5's and A9 would get necessary ordering from AXI and
-	 *     don't need ROC ordering enable:
-	 *     - MMIO ordering is through dev mapping and MMIO
-	 *       accesses bypass SMMU.
-	 *     - Normal memory is accessed through SMMU and ordering is
-	 *       ensured by client and AXI.
-	 *     - Ack point for Normal memory is WCAM in MC.
-	 *     - MMIO's can be early acked and AXI ensures dev memory ordering,
-	 *       Client ensures read/write direction change ordering.
-	 *     - See Bug 200312466 for more details.
-	 */
-	mc_set_txn_override(AONDMAR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(AONDMAW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(AONR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(AONW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(APEDMAR, CGID_TAG_ADR, SO_DEV_CLIENT_AXI_ID, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
-	mc_set_txn_override(APEDMAW, CGID_TAG_ADR, SO_DEV_CLIENT_AXI_ID, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
-	mc_set_txn_override(APER, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
-	mc_set_txn_override(APEW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
-	mc_set_txn_override(AXISR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(AXISW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(BPMPDMAR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(BPMPDMAW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(BPMPR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(BPMPW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(EQOSR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
-	mc_set_txn_override(EQOSW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
-	mc_set_txn_override(ETRR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(ETRW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(HOST1XDMAR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(MPCORER, CGID_TAG_ADR, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE);
-	mc_set_txn_override(MPCOREW, CGID_TAG_ADR, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE);
-	mc_set_txn_override(NVDISPLAYR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
-	mc_set_txn_override(NVDISPLAYR1, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
-	mc_set_txn_override(PCIE0R, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
-	mc_set_txn_override(PCIE0R1, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
-	mc_set_txn_override(PCIE0W, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
-	mc_set_txn_override(PCIE1R, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
-	mc_set_txn_override(PCIE1W, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
-	if (tegra_platform_is_silicon()) {
-		mc_set_txn_override(PCIE2AR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
-		mc_set_txn_override(PCIE2AW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
-		mc_set_txn_override(PCIE3R, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
-		mc_set_txn_override(PCIE3W, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
-		mc_set_txn_override(PCIE4R, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
-		mc_set_txn_override(PCIE4W, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
-		mc_set_txn_override(PCIE5R, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
-		mc_set_txn_override(PCIE5W, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
-		mc_set_txn_override(PCIE5R1, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
-	}
-	mc_set_txn_override(PTCR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
-	mc_set_txn_override(RCEDMAR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(RCEDMAW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(RCER, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(RCEW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(SATAR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
-	mc_set_txn_override(SATAW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
-	mc_set_txn_override(SCEDMAR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(SCEDMAW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(SCER, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(SCEW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(SDMMCR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(SDMMCRAB, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(SDMMCRA, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(SDMMCW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(SDMMCWA, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(SDMMCWAB, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	/*
-	 * TO DO: make SESRD/WR FORCE_COHERENT once SE+TZ with SMMU is enabled.
-	*/
-	mc_set_txn_override(SESRD, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
-	mc_set_txn_override(SESWR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
-	mc_set_txn_override(TSECSRD, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(TSECSRDB, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(TSECSWR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(TSECSWRB, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(UFSHCR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(UFSHCW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(VICSRD, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(VICSRD1, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(VICSWR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(VIFALR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
-	mc_set_txn_override(VIFALW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
-	mc_set_txn_override(XUSB_DEVR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
-	mc_set_txn_override(XUSB_DEVW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
-	mc_set_txn_override(XUSB_HOSTR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
-	mc_set_txn_override(XUSB_HOSTW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT_SNOOP, FORCE_COHERENT_SNOOP);
-	mc_set_txn_override(AXIAPR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(AXIAPW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(DLA0FALRDB, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(DLA0FALWRB, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(DLA0RDA, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(DLA0RDA1, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(DLA0WRA, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(DLA1FALRDB, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(DLA1FALWRB, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(DLA1RDA, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(DLA1RDA1, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(DLA1WRA, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(HDAR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
-	mc_set_txn_override(HDAW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
-	mc_set_txn_override(ISPFALR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(ISPFALW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(ISPRA, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(ISPRA1, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(ISPWA, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(ISPWB, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(NVDEC1SRD, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(NVDEC1SRD1, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(NVDEC1SWR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(NVDECSRD, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(NVDECSRD1, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(NVDECSWR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(NVENC1SRD, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(NVENC1SRD1, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(NVENC1SWR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(NVENCSRD, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(NVENCSRD1, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(NVENCSWR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(NVJPGSRD, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(NVJPGSWR, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(PVA0RDA, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(PVA0RDA1, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(PVA0RDB, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(PVA0RDB1, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(PVA0RDC, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(PVA0WRA, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(PVA0WRB, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(PVA0WRC, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(PVA1RDA, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(PVA1RDA1, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(PVA1RDB, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(PVA1RDB1, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(PVA1RDC, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(PVA1WRA, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(PVA1WRB, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(PVA1WRC, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_COHERENT, FORCE_COHERENT);
-	mc_set_txn_override(VIW, CGID_TAG_ADR, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
-
-	if (tegra_platform_is_silicon()) {
-		mc_set_txn_override(MIU0R, CGID_TAG_ADR, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE);
-		mc_set_txn_override(MIU0W, CGID_TAG_ADR, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE);
-		mc_set_txn_override(MIU1R, CGID_TAG_ADR, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE);
-		mc_set_txn_override(MIU1W, CGID_TAG_ADR, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE);
-		mc_set_txn_override(MIU2R, CGID_TAG_ADR, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE);
-		mc_set_txn_override(MIU2W, CGID_TAG_ADR, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE);
-		mc_set_txn_override(MIU3R, CGID_TAG_ADR, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE);
-		mc_set_txn_override(MIU3W, CGID_TAG_ADR, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE);
-		mc_set_txn_override(MIU4R, CGID_TAG_ADR, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE);
-		mc_set_txn_override(MIU4W, CGID_TAG_ADR, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE);
-		mc_set_txn_override(MIU5R, CGID_TAG_ADR, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE);
-		mc_set_txn_override(MIU5W, CGID_TAG_ADR, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE);
-		mc_set_txn_override(MIU6R, CGID_TAG_ADR, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE);
-		mc_set_txn_override(MIU6W, CGID_TAG_ADR, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE);
-		mc_set_txn_override(MIU7R, CGID_TAG_ADR, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE);
-		mc_set_txn_override(MIU7W, CGID_TAG_ADR, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE);
-	}
-
-	/*
-	 * At this point, ordering can occur at SCF. So, remove PCFIFO's
-	 * control over ordering requests.
-	 *
-	 * Change PCFIFO_*_ORDERED_CLIENT from ORDERED -> UNORDERED for
-	 * boot and strongly ordered MSS clients
-	 */
-	reg_val = MC_PCFIFO_CLIENT_CONFIG2_RESET_VAL &
-		mc_set_pcfifo_unordered_boot_so_mss(2, XUSB_HOSTW) &
-		mc_set_pcfifo_unordered_boot_so_mss(2, TSECSWR);
-	tegra_mc_write_32(MC_PCFIFO_CLIENT_CONFIG2, reg_val);
-
-	reg_val = MC_PCFIFO_CLIENT_CONFIG3_RESET_VAL &
-		mc_set_pcfifo_unordered_boot_so_mss(3, SDMMCWA) &
-		mc_set_pcfifo_unordered_boot_so_mss(3, SDMMCW) &
-		mc_set_pcfifo_unordered_boot_so_mss(3, SDMMCWAB) &
-		mc_set_pcfifo_unordered_boot_so_mss(3, VICSWR) &
-		mc_set_pcfifo_unordered_boot_so_mss(3, APEW);
-	tegra_mc_write_32(MC_PCFIFO_CLIENT_CONFIG3, reg_val);
-
-	reg_val = MC_PCFIFO_CLIENT_CONFIG4_RESET_VAL &
-		mc_set_pcfifo_unordered_boot_so_mss(4, SESWR) &
-		mc_set_pcfifo_unordered_boot_so_mss(4, ETRW) &
-		mc_set_pcfifo_unordered_boot_so_mss(4, TSECSWRB) &
-		mc_set_pcfifo_unordered_boot_so_mss(4, AXISW) &
-		mc_set_pcfifo_unordered_boot_so_mss(4, UFSHCW) &
-		mc_set_pcfifo_unordered_boot_so_mss(4, BPMPW) &
-		mc_set_pcfifo_unordered_boot_so_mss(4, BPMPDMAW) &
-		mc_set_pcfifo_unordered_boot_so_mss(4, AONW) &
-		mc_set_pcfifo_unordered_boot_so_mss(4, AONDMAW) &
-		mc_set_pcfifo_unordered_boot_so_mss(4, SCEW) &
-		mc_set_pcfifo_unordered_boot_so_mss(4, SCEDMAW);
-	/* EQOSW has PCFIFO order enabled. */
-	reg_val |= mc_set_pcfifo_unordered_boot_so_mss(4, EQOSW);
-	tegra_mc_write_32(MC_PCFIFO_CLIENT_CONFIG4, reg_val);
-
-	reg_val = MC_PCFIFO_CLIENT_CONFIG5_RESET_VAL &
-		mc_set_pcfifo_unordered_boot_so_mss(5, APEDMAW) &
-		mc_set_pcfifo_unordered_boot_so_mss(5, VIFALW);
-	tegra_mc_write_32(MC_PCFIFO_CLIENT_CONFIG5, reg_val);
-
-	reg_val = MC_PCFIFO_CLIENT_CONFIG6_RESET_VAL &
-		mc_set_pcfifo_unordered_boot_so_mss(6, RCEW) &
-		mc_set_pcfifo_unordered_boot_so_mss(6, RCEDMAW) &
-		mc_set_pcfifo_unordered_boot_so_mss(6, PCIE0W);
-	tegra_mc_write_32(MC_PCFIFO_CLIENT_CONFIG6, reg_val);
-
-	reg_val = MC_PCFIFO_CLIENT_CONFIG7_RESET_VAL &
-		mc_set_pcfifo_unordered_boot_so_mss(7, PCIE4W) &
-		mc_set_pcfifo_unordered_boot_so_mss(7, PCIE5W);
-	tegra_mc_write_32(MC_PCFIFO_CLIENT_CONFIG7, reg_val);
-
-	/* Set Order Id only for the clients having non zero order id */
-	reg_val = mc_client_order_id(MC_CLIENT_ORDER_ID_9_RESET_VAL, 9, XUSB_HOSTW);
-	tegra_mc_write_32(MC_CLIENT_ORDER_ID_9, reg_val);
-
-	reg_val = mc_client_order_id(MC_CLIENT_ORDER_ID_27_RESET_VAL, 27, PCIE0W);
-	tegra_mc_write_32(MC_CLIENT_ORDER_ID_27, reg_val);
-
-	reg_val = mc_client_order_id(MC_CLIENT_ORDER_ID_28_RESET_VAL, 28, PCIE4W);
-	reg_val = mc_client_order_id(reg_val, 28, PCIE5W);
-	tegra_mc_write_32(MC_CLIENT_ORDER_ID_28, reg_val);
-
-	/*
-	 * Set VC Id only for the clients having different reset values like
-	 * SDMMCRAB, SDMMCWAB, SESRD, SESWR, TSECSRD,TSECSRDB, TSECSWR and
-	 * TSECSWRB clients
-	 */
-	reg_val = mc_hub_vc_id(MC_HUB_PC_VC_ID_0_RESET_VAL, 0, APB);
-	tegra_mc_write_32(MC_HUB_PC_VC_ID_0, reg_val);
-
-	/* SDMMCRAB and SDMMCWAB clients */
-	reg_val = mc_hub_vc_id(MC_HUB_PC_VC_ID_2_RESET_VAL, 2, SD);
-	tegra_mc_write_32(MC_HUB_PC_VC_ID_2, reg_val);
-
-	reg_val = mc_hub_vc_id(MC_HUB_PC_VC_ID_4_RESET_VAL, 4, NIC);
-	tegra_mc_write_32(MC_HUB_PC_VC_ID_4, reg_val);
-
-	reg_val = mc_hub_vc_id(MC_HUB_PC_VC_ID_12_RESET_VAL, 12, UFSHCPC2);
-	tegra_mc_write_32(MC_HUB_PC_VC_ID_12, reg_val);
-
-	wdata_0 = MC_CLIENT_HOTRESET_CTRL0_RESET_VAL;
-	tegra_mc_write_32(MC_CLIENT_HOTRESET_CTRL0, wdata_0);
-
-	wdata_1 = MC_CLIENT_HOTRESET_CTRL1_RESET_VAL;
-	tegra_mc_write_32(MC_CLIENT_HOTRESET_CTRL1, wdata_1);
-
-	wdata_2 = MC_CLIENT_HOTRESET_CTRL2_RESET_VAL;
-	tegra_mc_write_32(MC_CLIENT_HOTRESET_CTRL2, wdata_2);
-
-	reg_val = MC_COALESCE_CTRL_COALESCER_ENABLE;
-	tegra_mc_write_32(MC_COALESCE_CTRL, reg_val);
-
-	/*
-	 * WAR to hardware bug 1953865: Coalescer must be disabled
-	 * for PVA0RDC and PVA1RDC interfaces.
-	 */
-	reg_val = tegra_mc_read_32(MC_COALESCE_CONFIG_6_0);
-	reg_val &= ~(MC_COALESCE_CONFIG_6_0_PVA0RDC_COALESCER_ENABLED |
-		     MC_COALESCE_CONFIG_6_0_PVA1RDC_COALESCER_ENABLED);
-	tegra_mc_write_32(MC_COALESCE_CONFIG_6_0, reg_val);
-}
-
 /*******************************************************************************
  * Struct to hold the memory controller settings
  ******************************************************************************/
@@ -685,8 +286,7 @@
 	.streamid_override_cfg = tegra194_streamid_override_regs,
 	.num_streamid_override_cfgs = (uint32_t)ARRAY_SIZE(tegra194_streamid_override_regs),
 	.streamid_security_cfg = tegra194_streamid_sec_cfgs,
-	.num_streamid_security_cfgs = (uint32_t)ARRAY_SIZE(tegra194_streamid_sec_cfgs),
-	.reconfig_mss_clients = tegra194_memctrl_reconfig_mss_clients
+	.num_streamid_security_cfgs = (uint32_t)ARRAY_SIZE(tegra194_streamid_sec_cfgs)
 };
 
 /*******************************************************************************
diff --git a/plat/nvidia/tegra/soc/t194/plat_setup.c b/plat/nvidia/tegra/soc/t194/plat_setup.c
index 3640ade..235fba4 100644
--- a/plat/nvidia/tegra/soc/t194/plat_setup.c
+++ b/plat/nvidia/tegra/soc/t194/plat_setup.c
@@ -163,18 +163,18 @@
 	uint32_t console_clock = 0U;
 
 #if ENABLE_CONSOLE_SPE
-	static console_spe_t spe_console;
+	static console_t spe_console;
 
 	if (id == TEGRA_CONSOLE_SPE_ID) {
 		(void)console_spe_register(TEGRA_CONSOLE_SPE_BASE,
 					   console_clock,
 					   TEGRA_CONSOLE_BAUDRATE,
 					   &spe_console);
-		console_set_scope(&spe_console.console, CONSOLE_FLAG_BOOT |
+		console_set_scope(&spe_console, CONSOLE_FLAG_BOOT |
 			CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH);
 	}
 #else
-	static console_16550_t uart_console;
+	static console_t uart_console;
 
 	if ((id > 0) && (id < TEGRA194_MAX_UART_PORTS)) {
 		/*
@@ -190,7 +190,7 @@
 					     console_clock,
 					     TEGRA_CONSOLE_BAUDRATE,
 					     &uart_console);
-		console_set_scope(&uart_console.console, CONSOLE_FLAG_BOOT |
+		console_set_scope(&uart_console, CONSOLE_FLAG_BOOT |
 			CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH);
 	}
 #endif
diff --git a/plat/nvidia/tegra/soc/t210/drivers/se/se_private.h b/plat/nvidia/tegra/soc/t210/drivers/se/se_private.h
index 352107d..c44b0fc 100644
--- a/plat/nvidia/tegra/soc/t210/drivers/se/se_private.h
+++ b/plat/nvidia/tegra/soc/t210/drivers/se/se_private.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
- * Copyright (c) 2017, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2017-2020, NVIDIA CORPORATION.  All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -15,6 +15,9 @@
  * PMC registers
  */
 
+/* SC7 context save scratch register for T210 */
+#define PMC_SCRATCH43_REG_OFFSET		U(0x22C)
+
 /* Secure scratch registers */
 #define PMC_SECURE_SCRATCH4_OFFSET		0xC0U
 #define PMC_SECURE_SCRATCH5_OFFSET		0xC4U
@@ -435,6 +438,7 @@
 		((x) & ((0x1U) << SE_TZRAM_OP_REQ_SHIFT))
 
 /* SE Interrupt */
+#define SE_INT_ENABLE_REG_OFFSET		U(0xC)
 #define SE_INT_STATUS_REG_OFFSET		0x10U
 #define SE_INT_OP_DONE_SHIFT			4
 #define SE_INT_OP_DONE_CLEAR	\
diff --git a/plat/nvidia/tegra/soc/t210/drivers/se/security_engine.c b/plat/nvidia/tegra/soc/t210/drivers/se/security_engine.c
index d5e0491..635018d 100644
--- a/plat/nvidia/tegra/soc/t210/drivers/se/security_engine.c
+++ b/plat/nvidia/tegra/soc/t210/drivers/se/security_engine.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
- * Copyright (c) 2017, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2017-2020, NVIDIA CORPORATION.  All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -20,8 +20,8 @@
  * Constants and Macros
  ******************************************************************************/
 
-#define TIMEOUT_100MS	100U	// Timeout in 100ms
-#define RNG_AES_KEY_INDEX   1
+#define TIMEOUT_100MS		100U	/* Timeout in 100ms */
+#define RNG_AES_KEY_INDEX	1
 
 /*******************************************************************************
  * Data structure and global variables
@@ -68,14 +68,12 @@
  * #--------------------------------#
  */
 
-/* Known pattern data */
-static const uint32_t se_ctx_known_pattern_data[SE_CTX_KNOWN_PATTERN_SIZE_WORDS] = {
+/* Known pattern data for T210 */
+static const uint8_t se_ctx_known_pattern_data[SE_CTX_KNOWN_PATTERN_SIZE] = {
 	/* 128 bit AES block */
-	0x0C0D0E0F,
-	0x08090A0B,
-	0x04050607,
-	0x00010203,
-};
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+	};
 
 /* SE input and output linked list buffers */
 static tegra_se_io_lst_t se1_src_ll_buf;
@@ -85,6 +83,9 @@
 static tegra_se_io_lst_t se2_src_ll_buf;
 static tegra_se_io_lst_t se2_dst_ll_buf;
 
+/* SE1 context buffer, 132 blocks */
+static __aligned(64) uint8_t se1_ctx_buf[SE_CTX_DRBG_BUFER_SIZE];
+
 /* SE1 security engine device handle */
 static tegra_se_dev_t se_dev_1 = {
 	.se_num = 1,
@@ -97,10 +98,10 @@
 	/* Setup DST buffers for SE operations */
 	.dst_ll_buf = &se1_dst_ll_buf,
 	/* Setup context save destination */
-	.ctx_save_buf = (uint32_t *)(TEGRA_TZRAM_CARVEOUT_BASE),
+	.ctx_save_buf = (uint32_t *)&se1_ctx_buf
 };
 
-/* SE2 security engine device handle */
+/* SE2 security engine device handle (T210B01 only) */
 static tegra_se_dev_t se_dev_2 = {
 	.se_num = 2,
 	/* Setup base address for se */
@@ -112,7 +113,7 @@
 	/* Setup DST buffers for SE operations */
 	.dst_ll_buf = &se2_dst_ll_buf,
 	/* Setup context save destination */
-	.ctx_save_buf = (uint32_t *)(TEGRA_TZRAM_CARVEOUT_BASE + 0x1000),
+	.ctx_save_buf = (uint32_t *)(TEGRA_TZRAM_CARVEOUT_BASE + 0x1000)
 };
 
 static bool ecid_valid;
@@ -202,18 +203,6 @@
 }
 
 /*
- * Returns true if the SE engine is configured to perform SE context save in
- * hardware.
- */
-static inline bool tegra_se_atomic_save_enabled(const tegra_se_dev_t *se_dev)
-{
-	uint32_t val;
-
-	val = tegra_se_read_32(se_dev, SE_CTX_SAVE_AUTO_REG_OFFSET);
-	return (SE_CTX_SAVE_AUTO_ENABLE(val) == SE_CTX_SAVE_AUTO_EN);
-}
-
-/*
  * Wait for SE engine to be idle and clear pending interrupts before
  * starting the next SE operation.
  */
@@ -223,6 +212,9 @@
 	uint32_t val = 0;
 	uint32_t timeout;
 
+	/* disable SE interrupt to prevent interrupt issued by SE operation */
+	tegra_se_write_32(se_dev, SE_INT_ENABLE_REG_OFFSET, 0U);
+
 	/* Wait for previous operation to finish */
 	val = tegra_se_read_32(se_dev, SE_STATUS_OFFSET);
 	for (timeout = 0; (val != 0U) && (timeout < TIMEOUT_100MS); timeout++) {
@@ -629,19 +621,19 @@
 {
 	uint32_t val = 0;
 	int ret = 0;
-	/* First the modulus and then the exponent must be
+	/* For T210, First the modulus and then exponent must be
 	 * encrypted and saved. This is repeated for SLOT 0
 	 * and SLOT 1. Hence the order:
-	 * SLOT 0 exponent : RSA_KEY_INDEX : 0
 	 * SLOT 0 modulus : RSA_KEY_INDEX : 1
-	 * SLOT 1 exponent : RSA_KEY_INDEX : 2
+	 * SLOT 0 exponent : RSA_KEY_INDEX : 0
 	 * SLOT 1 modulus : RSA_KEY_INDEX : 3
+	 * SLOT 1 exponent : RSA_KEY_INDEX : 2
 	 */
 	const unsigned int key_index_mod[TEGRA_SE_RSA_KEYSLOT_COUNT][2] = {
 		/* RSA key slot 0 */
-		{SE_RSA_KEY_INDEX_SLOT0_EXP, SE_RSA_KEY_INDEX_SLOT0_MOD},
+		{SE_RSA_KEY_INDEX_SLOT0_MOD, SE_RSA_KEY_INDEX_SLOT0_EXP},
 		/* RSA key slot 1 */
-		{SE_RSA_KEY_INDEX_SLOT1_EXP, SE_RSA_KEY_INDEX_SLOT1_MOD},
+		{SE_RSA_KEY_INDEX_SLOT1_MOD, SE_RSA_KEY_INDEX_SLOT1_EXP},
 	};
 
 	se_dev->dst_ll_buf->last_buff_num = 0;
@@ -876,8 +868,8 @@
 
 	/* Write lp context buffer address into PMC scratch register */
 	if (se_dev->se_num == 1) {
-		/* SE context address */
-		mmio_write_32((uint64_t)TEGRA_PMC_BASE + PMC_SECURE_SCRATCH117_OFFSET,
+		/* SE context address, support T210 only */
+		mmio_write_32((uint64_t)TEGRA_PMC_BASE + PMC_SCRATCH43_REG_OFFSET,
 				((uint64_t)(se_dev->ctx_save_buf)));
 	} else if (se_dev->se_num == 2) {
 		/* SE2 & PKA1 context address */
@@ -909,7 +901,10 @@
 
 	/* Generate random SRK to initialize DRBG */
 	tegra_se_generate_srk(&se_dev_1);
-	tegra_se_generate_srk(&se_dev_2);
+
+	if (tegra_chipid_is_t210_b01()) {
+		tegra_se_generate_srk(&se_dev_2);
+	}
 
 	/* determine if ECID is valid */
 	val = mmio_read_32(TEGRA_FUSE_BASE + FUSE_JTAG_SECUREID_VALID);
@@ -932,6 +927,18 @@
 	val &= ~ENTROPY_RESET_BIT;
 	mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEVICES_W, val);
 
+	if (!tegra_chipid_is_t210_b01()) {
+
+		/*
+		 * T210 SE clock source is turned off in kernel, to simplify
+		 * SE clock source setting, we switch SE clock source to
+		 * CLK_M, SE_CLK_DIVISOR = 0. T210 B01 SE clock source is
+		 * always on, so don't need this setting.
+		 */
+		mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_CLK_RST_CTL_CLK_SRC_SE,
+			      SE_CLK_SRC_CLK_M);
+	}
+
 	/* Enable SE clock */
 	val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_CLK_OUT_ENB_V);
 	val |= SE_CLK_ENB_BIT;
@@ -975,43 +982,25 @@
 
 	tegra_se_enable_clocks();
 
-	if (tegra_se_atomic_save_enabled(&se_dev_2) &&
-			tegra_se_atomic_save_enabled(&se_dev_1)) {
-		/* Atomic context save se2 and pka1 */
+	if (tegra_chipid_is_t210_b01()) {
+		/* It is T210 B01, Atomic context save se2 and pka1 */
 		INFO("%s: SE2/PKA1 atomic context save\n", __func__);
-		if (ret == 0) {
-			ret = tegra_se_context_save_atomic(&se_dev_2);
-		}
-
-		/* Atomic context save se */
-		if (ret == 0) {
-			INFO("%s: SE1 atomic context save\n", __func__);
-			ret = tegra_se_context_save_atomic(&se_dev_1);
+		ret = tegra_se_context_save_atomic(&se_dev_2);
+		if (ret != 0) {
+			ERROR("%s: SE2 ctx save failed (%d)\n", __func__, ret);
 		}
 
-		if (ret == 0) {
-			INFO("%s: SE atomic context save done\n", __func__);
-		}
-	} else if (!tegra_se_atomic_save_enabled(&se_dev_2) &&
-			!tegra_se_atomic_save_enabled(&se_dev_1)) {
-		/* SW context save se2 and pka1 */
-		INFO("%s: SE2/PKA1 legacy(SW) context save\n", __func__);
-		if (ret == 0) {
-			ret = tegra_se_context_save_sw(&se_dev_2);
-		}
-
-		/* SW context save se */
-		if (ret == 0) {
-			INFO("%s: SE1 legacy(SW) context save\n", __func__);
-			ret = tegra_se_context_save_sw(&se_dev_1);
-		}
-
-		if (ret == 0) {
-			INFO("%s: SE SW context save done\n", __func__);
+		ret = tegra_se_context_save_atomic(&se_dev_1);
+		if (ret != 0) {
+			ERROR("%s: SE1 ctx save failed (%d)\n", __func__, ret);
 		}
 	} else {
-		ERROR("%s: One SE set for atomic CTX save, the other is not\n",
-			 __func__);
+		/* It is T210, SW context save se */
+		INFO("%s: SE1 legacy(SW) context save\n", __func__);
+		ret = tegra_se_context_save_sw(&se_dev_1);
+		if (ret != 0) {
+			ERROR("%s: SE1 ctx save failed (%d)\n", __func__, ret);
+		}
 	}
 
 	tegra_se_disable_clocks();
@@ -1080,5 +1069,8 @@
 void tegra_se_resume(void)
 {
 	tegra_se_warm_boot_resume(&se_dev_1);
-	tegra_se_warm_boot_resume(&se_dev_2);
+
+	if (tegra_chipid_is_t210_b01()) {
+		tegra_se_warm_boot_resume(&se_dev_2);
+	}
 }
diff --git a/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c
index 832b8d6..f29e624 100644
--- a/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c
+++ b/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c
@@ -210,12 +210,9 @@
 		assert((stateid_afflvl1 == PLAT_MAX_OFF_STATE) ||
 			(stateid_afflvl1 == PSTATE_ID_SOC_POWERDN));
 
-		if (tegra_chipid_is_t210_b01()) {
-
-			/* Suspend se/se2 and pka1 */
-			if (tegra_se_suspend() != 0) {
-				ret = PSCI_E_INTERN_FAIL;
-			}
+		/* Suspend se/se2 and pka1 for T210 B01 and se for T210 */
+		if (tegra_se_suspend() != 0) {
+			ret = PSCI_E_INTERN_FAIL;
 		}
 
 	} else if (stateid_afflvl1 == PSTATE_ID_CLUSTER_IDLE) {
diff --git a/plat/nvidia/tegra/soc/t210/plat_setup.c b/plat/nvidia/tegra/soc/t210/plat_setup.c
index c32772d..933e925 100644
--- a/plat/nvidia/tegra/soc/t210/plat_setup.c
+++ b/plat/nvidia/tegra/soc/t210/plat_setup.c
@@ -119,7 +119,7 @@
  ******************************************************************************/
 void plat_enable_console(int32_t id)
 {
-	static console_16550_t uart_console;
+	static console_t uart_console;
 	uint32_t console_clock;
 
 	if ((id > 0) && (id < TEGRA210_MAX_UART_PORTS)) {
@@ -136,7 +136,7 @@
 					     console_clock,
 					     TEGRA_CONSOLE_BAUDRATE,
 					     &uart_console);
-		console_set_scope(&uart_console.console, CONSOLE_FLAG_BOOT |
+		console_set_scope(&uart_console, CONSOLE_FLAG_BOOT |
 			CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH);
 	}
 }
@@ -174,9 +174,7 @@
 	}
 
 	/* Initialize security engine driver */
-	if (tegra_chipid_is_t210_b01()) {
-		tegra_se_init();
-	}
+	tegra_se_init();
 }
 
 /* Secure IRQs for Tegra186 */
diff --git a/plat/nvidia/tegra/soc/t210/plat_sip_calls.c b/plat/nvidia/tegra/soc/t210/plat_sip_calls.c
index 7e0f5c1..7d26fe7 100644
--- a/plat/nvidia/tegra/soc/t210/plat_sip_calls.c
+++ b/plat/nvidia/tegra/soc/t210/plat_sip_calls.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -50,24 +51,32 @@
 	if (!ns)
 		SMC_RET1(handle, SMC_UNK);
 
-	switch (smc_fid) {
-	case TEGRA_SIP_PMC_COMMANDS:
-
+	if (smc_fid == TEGRA_SIP_PMC_COMMANDS) {
 		/* check the address is within PMC range and is 4byte aligned */
 		if ((x2 >= TEGRA_PMC_SIZE) || (x2 & 0x3))
 			return -EINVAL;
 
-		/* pmc_secure_scratch registers are not accessible */
-		if (((x2 >= PMC_SECURE_SCRATCH0) && (x2 <= PMC_SECURE_SCRATCH5)) ||
-		    ((x2 >= PMC_SECURE_SCRATCH6) && (x2 <= PMC_SECURE_SCRATCH7)) ||
-		    ((x2 >= PMC_SECURE_SCRATCH8) && (x2 <= PMC_SECURE_SCRATCH79)) ||
-		    ((x2 >= PMC_SECURE_SCRATCH80) && (x2 <= PMC_SECURE_SCRATCH119)))
-				return -EFAULT;
-
+		switch (x2) {
+		/* Black listed PMC registers */
+		case PMC_SCRATCH1:
+		case PMC_SCRATCH31 ... PMC_SCRATCH33:
+		case PMC_SCRATCH40:
+		case PMC_SCRATCH42:
+		case PMC_SCRATCH43 ... PMC_SCRATCH48:
+		case PMC_SCRATCH50 ... PMC_SCRATCH51:
+		case PMC_SCRATCH56 ... PMC_SCRATCH57:
 		/* PMC secure-only registers are not accessible */
-		if ((x2 == PMC_DPD_ENABLE_0) || (x2 == PMC_FUSE_CONTROL_0) ||
-		    (x2 == PMC_CRYPTO_OP_0))
+		case PMC_DPD_ENABLE_0:
+		case PMC_FUSE_CONTROL_0:
+		case PMC_CRYPTO_OP_0:
+		case PMC_TSC_MULT_0:
+		case PMC_STICKY_BIT:
+			ERROR("%s: error offset=0x%llx\n", __func__, x2);
 			return -EFAULT;
+		default:
+			/* Valid register */
+			break;
+		}
 
 		/* Perform PMC read/write */
 		if (x1 == PMC_READ) {
@@ -78,13 +87,9 @@
 		} else {
 			return -EINVAL;
 		}
-
-		break;
-
-	default:
+	} else {
 		ERROR("%s: unsupported function ID\n", __func__);
 		return -ENOTSUP;
 	}
-
 	return 0;
 }
diff --git a/plat/nvidia/tegra/soc/t210/platform_t210.mk b/plat/nvidia/tegra/soc/t210/platform_t210.mk
index 0d27bcd..ba827a0 100644
--- a/plat/nvidia/tegra/soc/t210/platform_t210.mk
+++ b/plat/nvidia/tegra/soc/t210/platform_t210.mk
@@ -46,7 +46,6 @@
 ERRATA_A57_826974		:=	1
 ERRATA_A57_826977		:=	1
 ERRATA_A57_828024		:=	1
-ERRATA_A57_829520		:=	1
 ERRATA_A57_833471		:=	1
 
 # Enable workarounds for selected Cortex-A53 erratas.
diff --git a/plat/qemu/common/qemu_console.c b/plat/qemu/common/qemu_console.c
index fec1828..1f00f8a 100644
--- a/plat/qemu/common/qemu_console.c
+++ b/plat/qemu/common/qemu_console.c
@@ -9,7 +9,7 @@
 #include <drivers/console.h>
 #include <drivers/arm/pl011.h>
 
-static console_pl011_t console;
+static console_t console;
 
 void qemu_console_init(void)
 {
@@ -17,7 +17,7 @@
 			       PLAT_QEMU_BOOT_UART_CLK_IN_HZ,
 			       PLAT_QEMU_CONSOLE_BAUDRATE, &console);
 
-	console_set_scope(&console.console, CONSOLE_FLAG_BOOT |
+	console_set_scope(&console, CONSOLE_FLAG_BOOT |
 			  CONSOLE_FLAG_RUNTIME);
 }
 
diff --git a/plat/qemu/common/qemu_io_storage.c b/plat/qemu/common/qemu_io_storage.c
index 0e81cd1..1107e44 100644
--- a/plat/qemu/common/qemu_io_storage.c
+++ b/plat/qemu/common/qemu_io_storage.c
@@ -12,6 +12,7 @@
 #include <common/bl_common.h>
 #include <common/debug.h>
 #include <drivers/io/io_driver.h>
+#include <drivers/io/io_encrypted.h>
 #include <drivers/io/io_fip.h>
 #include <drivers/io/io_memmap.h>
 #include <drivers/io/io_semihosting.h>
@@ -47,6 +48,10 @@
 static uintptr_t memmap_dev_handle;
 static const io_dev_connector_t *sh_dev_con;
 static uintptr_t sh_dev_handle;
+#ifndef DECRYPTION_SUPPORT_none
+static const io_dev_connector_t *enc_dev_con;
+static uintptr_t enc_dev_handle;
+#endif
 
 static const io_block_spec_t fip_block_spec = {
 	.offset = PLAT_QEMU_FIP_BASE,
@@ -172,10 +177,11 @@
 #endif /* TRUSTED_BOARD_BOOT */
 };
 
-
-
 static int open_fip(const uintptr_t spec);
 static int open_memmap(const uintptr_t spec);
+#ifndef DECRYPTION_SUPPORT_none
+static int open_enc_fip(const uintptr_t spec);
+#endif
 
 struct plat_io_policy {
 	uintptr_t *dev_handle;
@@ -190,16 +196,46 @@
 		(uintptr_t)&fip_block_spec,
 		open_memmap
 	},
+	[ENC_IMAGE_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)NULL,
+		open_fip
+	},
 	[BL2_IMAGE_ID] = {
 		&fip_dev_handle,
 		(uintptr_t)&bl2_uuid_spec,
 		open_fip
 	},
+#if ENCRYPT_BL31 && !defined(DECRYPTION_SUPPORT_none)
+	[BL31_IMAGE_ID] = {
+		&enc_dev_handle,
+		(uintptr_t)&bl31_uuid_spec,
+		open_enc_fip
+	},
+#else
 	[BL31_IMAGE_ID] = {
 		&fip_dev_handle,
 		(uintptr_t)&bl31_uuid_spec,
 		open_fip
 	},
+#endif
+#if ENCRYPT_BL32 && !defined(DECRYPTION_SUPPORT_none)
+	[BL32_IMAGE_ID] = {
+		&enc_dev_handle,
+		(uintptr_t)&bl32_uuid_spec,
+		open_enc_fip
+	},
+	[BL32_EXTRA1_IMAGE_ID] = {
+		&enc_dev_handle,
+		(uintptr_t)&bl32_extra1_uuid_spec,
+		open_enc_fip
+	},
+	[BL32_EXTRA2_IMAGE_ID] = {
+		&enc_dev_handle,
+		(uintptr_t)&bl32_extra2_uuid_spec,
+		open_enc_fip
+	},
+#else
 	[BL32_IMAGE_ID] = {
 		&fip_dev_handle,
 		(uintptr_t)&bl32_uuid_spec,
@@ -215,6 +251,7 @@
 		(uintptr_t)&bl32_extra2_uuid_spec,
 		open_fip
 	},
+#endif
 	[BL33_IMAGE_ID] = {
 		&fip_dev_handle,
 		(uintptr_t)&bl33_uuid_spec,
@@ -271,7 +308,7 @@
 
 	/* See if a Firmware Image Package is available */
 	result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
-	if (result == 0) {
+	if (result == 0 && spec != (uintptr_t)NULL) {
 		result = io_open(fip_dev_handle, spec, &local_image_handle);
 		if (result == 0) {
 			VERBOSE("Using FIP\n");
@@ -281,6 +318,25 @@
 	return result;
 }
 
+#ifndef DECRYPTION_SUPPORT_none
+static int open_enc_fip(const uintptr_t spec)
+{
+	int result;
+	uintptr_t local_image_handle;
+
+	/* See if an encrypted FIP is available */
+	result = io_dev_init(enc_dev_handle, (uintptr_t)ENC_IMAGE_ID);
+	if (result == 0) {
+		result = io_open(enc_dev_handle, spec, &local_image_handle);
+		if (result == 0) {
+			VERBOSE("Using encrypted FIP\n");
+			io_close(local_image_handle);
+		}
+	}
+	return result;
+}
+#endif
+
 static int open_memmap(const uintptr_t spec)
 {
 	int result;
@@ -333,6 +389,15 @@
 				&memmap_dev_handle);
 	assert(io_result == 0);
 
+#ifndef DECRYPTION_SUPPORT_none
+	io_result = register_io_dev_enc(&enc_dev_con);
+	assert(io_result == 0);
+
+	io_result = io_dev_open(enc_dev_con, (uintptr_t)NULL,
+				&enc_dev_handle);
+	assert(io_result == 0);
+#endif
+
 	/* Register the additional IO devices on this platform */
 	io_result = register_io_dev_sh(&sh_dev_con);
 	assert(io_result == 0);
diff --git a/plat/qemu/qemu/include/platform_def.h b/plat/qemu/qemu/include/platform_def.h
index cce992f..ed4b748 100644
--- a/plat/qemu/qemu/include/platform_def.h
+++ b/plat/qemu/qemu/include/platform_def.h
@@ -172,7 +172,7 @@
 #define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 32)
 #define MAX_MMAP_REGIONS		11
 #define MAX_XLAT_TABLES			6
-#define MAX_IO_DEVICES			3
+#define MAX_IO_DEVICES			4
 #define MAX_IO_HANDLES			4
 
 /*
@@ -196,8 +196,8 @@
 #define QEMU_FLASH1_BASE		0x04000000
 #define QEMU_FLASH1_SIZE		0x04000000
 
-#define PLAT_QEMU_FIP_BASE		QEMU_FLASH1_BASE
-#define PLAT_QEMU_FIP_MAX_SIZE		QEMU_FLASH1_SIZE
+#define PLAT_QEMU_FIP_BASE		0x00040000
+#define PLAT_QEMU_FIP_MAX_SIZE		0x00400000
 
 #define DEVICE0_BASE			0x08000000
 #define DEVICE0_SIZE			0x01000000
diff --git a/plat/qemu/qemu/platform.mk b/plat/qemu/qemu/platform.mk
index bc10569..928d69a 100644
--- a/plat/qemu/qemu/platform.mk
+++ b/plat/qemu/qemu/platform.mk
@@ -128,6 +128,11 @@
 BL2_SOURCES		+=	lib/optee/optee_utils.c
 endif
 
+ifneq (${DECRYPTION_SUPPORT},none)
+BL1_SOURCES		+=	drivers/io/io_encrypted.c
+BL2_SOURCES		+=	drivers/io/io_encrypted.c
+endif
+
 QEMU_GICV2_SOURCES	:=	drivers/arm/gic/v2/gicv2_helpers.c	\
 				drivers/arm/gic/v2/gicv2_main.c		\
 				drivers/arm/gic/common/gic_common.c	\
@@ -165,11 +170,19 @@
 # Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images
 # in the FIP if the platform requires.
 ifneq ($(BL32_EXTRA1),)
+ifneq (${DECRYPTION_SUPPORT},none)
+$(eval $(call TOOL_ADD_IMG,bl32_extra1,--tos-fw-extra1,,$(ENCRYPT_BL32)))
+else
 $(eval $(call TOOL_ADD_IMG,bl32_extra1,--tos-fw-extra1))
 endif
+endif
 ifneq ($(BL32_EXTRA2),)
+ifneq (${DECRYPTION_SUPPORT},none)
+$(eval $(call TOOL_ADD_IMG,bl32_extra2,--tos-fw-extra2,,$(ENCRYPT_BL32)))
+else
 $(eval $(call TOOL_ADD_IMG,bl32_extra2,--tos-fw-extra2))
 endif
+endif
 
 SEPARATE_CODE_AND_RODATA := 1
 ENABLE_STACK_PROTECTOR	 := 0
diff --git a/plat/renesas/rcar/rcar_common.c b/plat/renesas/rcar/rcar_common.c
index 4ea753f..dec7229 100644
--- a/plat/renesas/rcar/rcar_common.c
+++ b/plat/renesas/rcar/rcar_common.c
@@ -70,8 +70,8 @@
 
 #include <drivers/renesas/rcar/console/console.h>
 
-static console_rcar_t rcar_boot_console;
-static console_rcar_t rcar_runtime_console;
+static console_t rcar_boot_console;
+static console_t rcar_runtime_console;
 
 void rcar_console_boot_init(void)
 {
@@ -81,7 +81,7 @@
 	if (!ret)
 		panic();
 
-	console_set_scope(&rcar_boot_console.console, CONSOLE_FLAG_BOOT);
+	console_set_scope(&rcar_boot_console, CONSOLE_FLAG_BOOT);
 }
 
 void rcar_console_boot_end(void)
@@ -96,7 +96,7 @@
 	if (!ret)
 		panic();
 
-	console_set_scope(&rcar_boot_console.console, CONSOLE_FLAG_RUNTIME);
+	console_set_scope(&rcar_boot_console, CONSOLE_FLAG_RUNTIME);
 }
 
 void rcar_console_runtime_end(void)
diff --git a/plat/rockchip/common/bl31_plat_setup.c b/plat/rockchip/common/bl31_plat_setup.c
index c4a0359..98ef415 100644
--- a/plat/rockchip/common/bl31_plat_setup.c
+++ b/plat/rockchip/common/bl31_plat_setup.c
@@ -57,7 +57,7 @@
 void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
 				u_register_t arg2, u_register_t arg3)
 {
-	static console_16550_t console;
+	static console_t console;
 
 	params_early_setup(arg1);
 
diff --git a/plat/rockchip/common/sp_min_plat_setup.c b/plat/rockchip/common/sp_min_plat_setup.c
index 6d15075..0237b16 100644
--- a/plat/rockchip/common/sp_min_plat_setup.c
+++ b/plat/rockchip/common/sp_min_plat_setup.c
@@ -52,7 +52,7 @@
 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;
+	static console_t console;
 
 	params_early_setup(arg1);
 
diff --git a/plat/rpi/common/rpi3_common.c b/plat/rpi/common/rpi3_common.c
index ff33694..27281f2 100644
--- a/plat/rpi/common/rpi3_common.c
+++ b/plat/rpi/common/rpi3_common.c
@@ -102,7 +102,7 @@
 /*******************************************************************************
  * Function that sets up the console
  ******************************************************************************/
-static console_16550_t rpi3_console;
+static console_t rpi3_console;
 
 void rpi3_console_init(unsigned int base_clk_rate)
 {
@@ -123,7 +123,7 @@
 		panic();
 	}
 
-	console_set_scope(&rpi3_console.console, console_scope);
+	console_set_scope(&rpi3_console, console_scope);
 }
 
 /*******************************************************************************
diff --git a/plat/socionext/synquacer/sq_bl31_setup.c b/plat/socionext/synquacer/sq_bl31_setup.c
index b864021..9723ef9 100644
--- a/plat/socionext/synquacer/sq_bl31_setup.c
+++ b/plat/socionext/synquacer/sq_bl31_setup.c
@@ -16,7 +16,7 @@
 #include <lib/mmio.h>
 #include <sq_common.h>
 
-static console_pl011_t console;
+static console_t console;
 static entry_point_info_t bl32_image_ep_info;
 static entry_point_info_t bl33_image_ep_info;
 
@@ -69,8 +69,7 @@
 			       PLAT_SQ_BOOT_UART_CLK_IN_HZ,
 			       SQ_CONSOLE_BAUDRATE, &console);
 
-	console_set_scope(&console.console, CONSOLE_FLAG_BOOT |
-			  CONSOLE_FLAG_RUNTIME);
+	console_set_scope(&console, CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME);
 
 	/* There are no parameters from BL2 if BL31 is a reset vector */
 	assert(arg0 == 0U);
diff --git a/plat/socionext/uniphier/uniphier_console.S b/plat/socionext/uniphier/uniphier_console.S
index 1113c6e..f3dde0c 100644
--- a/plat/socionext/uniphier/uniphier_console.S
+++ b/plat/socionext/uniphier/uniphier_console.S
@@ -17,7 +17,7 @@
  */
 	.globl	uniphier_console_putc
 func uniphier_console_putc
-	ldr	x1, [x1, #CONSOLE_T_DRVDATA]
+	ldr	x1, [x1, #CONSOLE_T_BASE]
 
 	/* Wait until the transmitter FIFO gets empty */
 0:	ldr	w2, [x1, #UNIPHIER_UART_LSR]
@@ -36,7 +36,7 @@
  */
 	.globl	uniphier_console_getc
 func uniphier_console_getc
-	ldr	x0, [x0, #CONSOLE_T_DRVDATA]
+	ldr	x0, [x0, #CONSOLE_T_BASE]
 
 	ldr	w1, [x0, #UNIPHIER_UART_LSR]
 	tbz	w1, #UNIPHIER_UART_LSR_DR_BIT, 0f
@@ -55,7 +55,7 @@
  */
 	.global uniphier_console_flush
 func uniphier_console_flush
-	ldr	x0, [x0, #CONSOLE_T_DRVDATA]
+	ldr	x0, [x0, #CONSOLE_T_BASE]
 
 	/* wait until the transmitter gets empty */
 0:	ldr	w1, [x0, #UNIPHIER_UART_LSR]
diff --git a/plat/socionext/uniphier/uniphier_console_setup.c b/plat/socionext/uniphier/uniphier_console_setup.c
index 1851e4d..e2ae8bf 100644
--- a/plat/socionext/uniphier/uniphier_console_setup.c
+++ b/plat/socionext/uniphier/uniphier_console_setup.c
@@ -17,28 +17,21 @@
 #define UNIPHIER_UART_OFFSET	0x100
 #define UNIPHIER_UART_NR_PORTS	4
 
-struct uniphier_console {
-	struct console console;
-	uintptr_t base;
-};
-
 /* These callbacks are implemented in assembly to use crash_console_helpers.S */
 int uniphier_console_putc(int character, struct console *console);
 int uniphier_console_getc(struct console *console);
 int uniphier_console_flush(struct console *console);
 
-static struct uniphier_console uniphier_console = {
-	.console = {
-		.flags = CONSOLE_FLAG_BOOT |
+static console_t uniphier_console = {
+	.flags = CONSOLE_FLAG_BOOT |
 #if DEBUG
-			 CONSOLE_FLAG_RUNTIME |
+		 CONSOLE_FLAG_RUNTIME |
 #endif
-			 CONSOLE_FLAG_CRASH |
-			 CONSOLE_FLAG_TRANSLATE_CRLF,
-		.putc = uniphier_console_putc,
-		.getc = uniphier_console_getc,
-		.flush = uniphier_console_flush,
-	},
+		 CONSOLE_FLAG_CRASH |
+		 CONSOLE_FLAG_TRANSLATE_CRLF,
+	.putc = uniphier_console_putc,
+	.getc = uniphier_console_getc,
+	.flush = uniphier_console_flush,
 };
 
 static const uintptr_t uniphier_uart_base[] = {
@@ -86,7 +79,7 @@
 		plat_error_handler(-EINVAL);
 
 	uniphier_console.base = base;
-	console_register(&uniphier_console.console);
+	console_register(&uniphier_console);
 
 	/*
 	 * The hardware might be still printing characters queued up in the
diff --git a/plat/socionext/uniphier/uniphier_io_storage.c b/plat/socionext/uniphier/uniphier_io_storage.c
index 96180f1..77d1eaf 100644
--- a/plat/socionext/uniphier/uniphier_io_storage.c
+++ b/plat/socionext/uniphier/uniphier_io_storage.c
@@ -21,9 +21,8 @@
 #include "uniphier.h"
 
 #define UNIPHIER_ROM_REGION_BASE	0x00000000ULL
-#define UNIPHIER_ROM_REGION_SIZE	0x10000000ULL
+#define UNIPHIER_ROM_REGION_SIZE	0x04000000ULL
 
-#define UNIPHIER_OCM_REGION_BASE	0x30000000ULL
 #define UNIPHIER_OCM_REGION_SIZE	0x00040000ULL
 
 #define UNIPHIER_BLOCK_BUF_OFFSET	0x04200000UL
@@ -278,12 +277,20 @@
 	return uniphier_io_memmap_setup(0x70000);
 }
 
-static int uniphier_io_usb_setup(unsigned int soc_id, size_t buffer_offset)
+static const uintptr_t uniphier_ocm_base[] = {
+	[UNIPHIER_SOC_LD11] = 0x30000000,
+	[UNIPHIER_SOC_LD20] = 0x30000000,
+	[UNIPHIER_SOC_PXS3] = 0x30000000,
+};
+
+static int uniphier_io_rom_api_setup(unsigned int soc)
 {
-	struct io_block_dev_spec *block_dev_spec;
+	uintptr_t ocm_base;
 	int ret;
 
-	/* use ROM API for loading images from USB storage */
+	assert(soc < ARRAY_SIZE(uniphier_ocm_base));
+	ocm_base = uniphier_ocm_base[soc];
+
 	ret = mmap_add_dynamic_region(UNIPHIER_ROM_REGION_BASE,
 				      UNIPHIER_ROM_REGION_BASE,
 				      UNIPHIER_ROM_REGION_SIZE,
@@ -296,14 +303,26 @@
 	 * load functions provided by the ROM use this memory region as a work
 	 * area, but do not cater to cache coherency.
 	 */
-	ret = mmap_add_dynamic_region(UNIPHIER_OCM_REGION_BASE,
-				      UNIPHIER_OCM_REGION_BASE,
+	ret = mmap_add_dynamic_region(ocm_base, ocm_base,
 				      UNIPHIER_OCM_REGION_SIZE,
 				      MT_DEVICE | MT_RW | MT_SECURE);
 	if (ret)
 		return ret;
 
+	return 0;
+}
+
+static int uniphier_io_usb_setup(unsigned int soc, size_t buffer_offset)
+{
+	struct io_block_dev_spec *block_dev_spec;
+	int ret;
+
+	/* use ROM API for loading images from USB storage */
+	ret = uniphier_io_rom_api_setup(soc);
+	if (ret)
+		return ret;
+
-	ret = uniphier_usb_init(soc_id, &block_dev_spec);
+	ret = uniphier_usb_init(soc, &block_dev_spec);
 	if (ret)
 		return ret;
 
diff --git a/plat/socionext/uniphier/uniphier_soc_info.c b/plat/socionext/uniphier/uniphier_soc_info.c
index 377532d..0e7a2d1 100644
--- a/plat/socionext/uniphier/uniphier_soc_info.c
+++ b/plat/socionext/uniphier/uniphier_soc_info.c
@@ -4,18 +4,25 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <common/bl_common.h>
 #include <lib/mmio.h>
 
 #include "uniphier.h"
 
-#define UNIPHIER_REVISION		0x5f800000
+#define UNIPHIER_REVISION		0x5f800000UL
+#define UNIPHIER_REVISION_NEW		0x1f800000UL
 
 static unsigned int uniphier_get_revision_field(unsigned int mask,
 						unsigned int shift)
 {
-	uint32_t revision = mmio_read_32(UNIPHIER_REVISION);
+	uintptr_t reg;
+
+	if (BL_CODE_BASE >= 0x80000000UL)
+		reg = UNIPHIER_REVISION;
+	else
+		reg = UNIPHIER_REVISION_NEW;
 
-	return (revision >> shift) & mask;
+	return (mmio_read_32(reg) >> shift) & mask;
 }
 
 unsigned int uniphier_get_soc_type(void)
diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c
index d9e29b4..024dbe0 100644
--- a/plat/st/stm32mp1/bl2_plat_setup.c
+++ b/plat/st/stm32mp1/bl2_plat_setup.c
@@ -31,7 +31,7 @@
 #include <stm32mp1_context.h>
 #include <stm32mp1_dbgmcu.h>
 
-static struct console_stm32 console;
+static console_t console;
 static struct stm32mp_auth_ops stm32mp1_auth_ops;
 
 static void print_reset_reason(void)
@@ -273,7 +273,7 @@
 		panic();
 	}
 
-	console_set_scope(&console.console, CONSOLE_FLAG_BOOT |
+	console_set_scope(&console, CONSOLE_FLAG_BOOT |
 			  CONSOLE_FLAG_CRASH | CONSOLE_FLAG_TRANSLATE_CRLF);
 
 	stm32mp_print_cpuinfo();
diff --git a/plat/st/stm32mp1/sp_min/sp_min_setup.c b/plat/st/stm32mp1/sp_min/sp_min_setup.c
index e10dfbf..4e74c27 100644
--- a/plat/st/stm32mp1/sp_min/sp_min_setup.c
+++ b/plat/st/stm32mp1/sp_min/sp_min_setup.c
@@ -35,7 +35,7 @@
  ******************************************************************************/
 static entry_point_info_t bl33_image_ep_info;
 
-static struct console_stm32 console;
+static console_t console;
 
 /*******************************************************************************
  * Interrupt handler for FIQ (secure IRQ)
@@ -142,7 +142,7 @@
 #ifdef DEBUG
 		console_flags |= CONSOLE_FLAG_RUNTIME;
 #endif
-		console_set_scope(&console.console, console_flags);
+		console_set_scope(&console, console_flags);
 	}
 }
 
diff --git a/plat/ti/k3/common/k3_console.c b/plat/ti/k3/common/k3_console.c
index ba0ddac..8c44c17 100644
--- a/plat/ti/k3/common/k3_console.c
+++ b/plat/ti/k3/common/k3_console.c
@@ -13,7 +13,7 @@
 
 void bl31_console_setup(void)
 {
-	static console_16550_t console;
+	static console_t console;
 
 	/* Initialize the console to provide early debug support */
 	console_16550_register(K3_USART_BASE, K3_USART_CLK_SPEED,
diff --git a/plat/xilinx/versal/bl31_versal_setup.c b/plat/xilinx/versal/bl31_versal_setup.c
index a5cf05e..03b7fbb 100644
--- a/plat/xilinx/versal/bl31_versal_setup.c
+++ b/plat/xilinx/versal/bl31_versal_setup.c
@@ -22,7 +22,7 @@
 
 static entry_point_info_t bl32_image_ep_info;
 static entry_point_info_t bl33_image_ep_info;
-static console_pl011_t versal_runtime_console;
+static console_t versal_runtime_console;
 
 /*
  * Return a pointer to the 'entry_point_info' structure of the next image for
@@ -71,7 +71,7 @@
 	if (rc == 0)
 		panic();
 
-	console_set_scope(&versal_runtime_console.console, CONSOLE_FLAG_BOOT |
+	console_set_scope(&versal_runtime_console, CONSOLE_FLAG_BOOT |
 			  CONSOLE_FLAG_RUNTIME);
 
 	/* Initialize the platform config for future decision making */
diff --git a/plat/xilinx/zynqmp/bl31_zynqmp_setup.c b/plat/xilinx/zynqmp/bl31_zynqmp_setup.c
index 6e0e811..b6d8770 100644
--- a/plat/xilinx/zynqmp/bl31_zynqmp_setup.c
+++ b/plat/xilinx/zynqmp/bl31_zynqmp_setup.c
@@ -62,12 +62,12 @@
 {
 	uint64_t atf_handoff_addr;
 	/* Register the console to provide early debug support */
-	static console_cdns_t bl31_boot_console;
+	static console_t bl31_boot_console;
 	(void)console_cdns_register(ZYNQMP_UART_BASE,
 				       zynqmp_get_uart_clk(),
 				       ZYNQMP_UART_BAUDRATE,
 				       &bl31_boot_console);
-	console_set_scope(&bl31_boot_console.console,
+	console_set_scope(&bl31_boot_console,
 			  CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_BOOT);
 
 	/* Initialize the platform config for future decision making */
diff --git a/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c b/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c
index 7f0ac74..5e770f7 100644
--- a/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c
+++ b/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c
@@ -21,12 +21,12 @@
 	 * Register a different console than already in use to display
 	 * messages from TSP
 	 */
-	static console_cdns_t tsp_boot_console;
+	static console_t tsp_boot_console;
 	(void)console_cdns_register(ZYNQMP_UART_BASE,
 				       zynqmp_get_uart_clk(),
 				       ZYNQMP_UART_BAUDRATE,
 				       &tsp_boot_console);
-	console_set_scope(&tsp_boot_console.console,
+	console_set_scope(&tsp_boot_console,
 			  CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_BOOT);
 
 	/* Initialize the platform config for future decision making */
diff --git a/services/spd/trusty/trusty.c b/services/spd/trusty/trusty.c
index 092ffa8..ba2f4a6 100644
--- a/services/spd/trusty/trusty.c
+++ b/services/spd/trusty/trusty.c
@@ -150,9 +150,9 @@
 	(void)memcpy(&ctx->fiq_gpregs, get_gpregs_ctx(handle), sizeof(ctx->fiq_gpregs));
 	ctx->fiq_pc = SMC_GET_EL3(handle, CTX_ELR_EL3);
 	ctx->fiq_cpsr = SMC_GET_EL3(handle, CTX_SPSR_EL3);
-	ctx->fiq_sp_el1 = read_ctx_reg(get_sysregs_ctx(handle), CTX_SP_EL1);
+	ctx->fiq_sp_el1 = read_ctx_reg(get_el1_sysregs_ctx(handle), CTX_SP_EL1);
 
-	write_ctx_reg(get_sysregs_ctx(handle), CTX_SP_EL1, ctx->fiq_handler_sp);
+	write_ctx_reg(get_el1_sysregs_ctx(handle), CTX_SP_EL1, ctx->fiq_handler_sp);
 	cm_set_elr_spsr_el3(NON_SECURE, ctx->fiq_handler_pc, (uint32_t)ctx->fiq_handler_cpsr);
 
 	SMC_RET0(handle);
@@ -211,7 +211,7 @@
 	 */
 	(void)memcpy(get_gpregs_ctx(handle), &ctx->fiq_gpregs, sizeof(ctx->fiq_gpregs));
 	ctx->fiq_handler_active = 0;
-	write_ctx_reg(get_sysregs_ctx(handle), CTX_SP_EL1, ctx->fiq_sp_el1);
+	write_ctx_reg(get_el1_sysregs_ctx(handle), CTX_SP_EL1, ctx->fiq_sp_el1);
 	cm_set_elr_spsr_el3(NON_SECURE, ctx->fiq_pc, (uint32_t)ctx->fiq_cpsr);
 
 	SMC_RET0(handle);
diff --git a/services/std_svc/spm_mm/spm_mm_setup.c b/services/std_svc/spm_mm/spm_mm_setup.c
index ccb2f90..468e5b3 100644
--- a/services/std_svc/spm_mm/spm_mm_setup.c
+++ b/services/std_svc/spm_mm/spm_mm_setup.c
@@ -116,17 +116,17 @@
 		      xlat_ctx->pa_max_address, xlat_ctx->va_max_address,
 		      EL1_EL0_REGIME);
 
-	write_ctx_reg(get_sysregs_ctx(ctx), CTX_MAIR_EL1,
+	write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_MAIR_EL1,
 		      mmu_cfg_params[MMU_CFG_MAIR]);
 
-	write_ctx_reg(get_sysregs_ctx(ctx), CTX_TCR_EL1,
+	write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_TCR_EL1,
 		      mmu_cfg_params[MMU_CFG_TCR]);
 
-	write_ctx_reg(get_sysregs_ctx(ctx), CTX_TTBR0_EL1,
+	write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_TTBR0_EL1,
 		      mmu_cfg_params[MMU_CFG_TTBR0]);
 
 	/* Setup SCTLR_EL1 */
-	u_register_t sctlr_el1 = read_ctx_reg(get_sysregs_ctx(ctx), CTX_SCTLR_EL1);
+	u_register_t sctlr_el1 = read_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SCTLR_EL1);
 
 	sctlr_el1 |=
 		/*SCTLR_EL1_RES1 |*/
@@ -160,7 +160,7 @@
 		SCTLR_UMA_BIT
 	);
 
-	write_ctx_reg(get_sysregs_ctx(ctx), CTX_SCTLR_EL1, sctlr_el1);
+	write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SCTLR_EL1, sctlr_el1);
 
 	/*
 	 * Setup other system registers
@@ -168,10 +168,10 @@
 	 */
 
 	/* Shim Exception Vector Base Address */
-	write_ctx_reg(get_sysregs_ctx(ctx), CTX_VBAR_EL1,
+	write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_VBAR_EL1,
 			SPM_SHIM_EXCEPTIONS_PTR);
 
-	write_ctx_reg(get_sysregs_ctx(ctx), CTX_CNTKCTL_EL1,
+	write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_CNTKCTL_EL1,
 		      EL0PTEN_BIT | EL0VTEN_BIT | EL0PCTEN_BIT | EL0VCTEN_BIT);
 
 	/*
@@ -181,7 +181,7 @@
 	 * TTA: Enable access to trace registers.
 	 * ZEN (v8.2): Trap SVE instructions and access to SVE registers.
 	 */
-	write_ctx_reg(get_sysregs_ctx(ctx), CTX_CPACR_EL1,
+	write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_CPACR_EL1,
 			CPACR_EL1_FPEN(CPACR_EL1_FP_TRAP_NONE));
 
 	/*
diff --git a/services/std_svc/spmd/spmd_main.c b/services/std_svc/spmd/spmd_main.c
index 677f639..2cdf4f5 100644
--- a/services/std_svc/spmd/spmd_main.c
+++ b/services/std_svc/spmd/spmd_main.c
@@ -33,9 +33,25 @@
 /*******************************************************************************
  * SPM Core attribute information read from its manifest.
  ******************************************************************************/
-spmc_manifest_sect_attribute_t spmc_attrs;
+static spmc_manifest_sect_attribute_t spmc_attrs;
 
 /*******************************************************************************
+ * SPM Core entry point information. Discovered on the primary core and reused
+ * on secondary cores.
+ ******************************************************************************/
+static entry_point_info_t *spmc_ep_info;
+
+/*******************************************************************************
+ * Static function declaration.
+ ******************************************************************************/
+static int32_t	spmd_init(void);
+static int	spmd_spmc_init(void *rd_base, size_t rd_size);
+static uint64_t	spmd_spci_error_return(void *handle, int error_code);
+static uint64_t	spmd_smc_forward(uint32_t smc_fid, bool secure_origin,
+				 uint64_t x1, uint64_t x2, uint64_t x3,
+				 uint64_t x4, void *handle);
+
+/*******************************************************************************
  * This function takes an SP context pointer and performs a synchronous entry
  * into it.
  ******************************************************************************/
@@ -49,17 +65,19 @@
 
 	/* Restore the context assigned above */
 	cm_el1_sysregs_context_restore(SECURE);
+#if SPMD_SPM_AT_SEL2
+	cm_el2_sysregs_context_restore(SECURE);
+#endif
 	cm_set_next_eret_context(SECURE);
 
-	/* Invalidate TLBs at EL1. */
-	tlbivmalle1();
-	dsbish();
-
-	/* Enter Secure Partition */
+	/* Enter SPMC */
 	rc = spmd_spm_core_enter(&spmc_ctx->c_rt_ctx);
 
 	/* Save secure state */
 	cm_el1_sysregs_context_save(SECURE);
+#if SPMD_SPM_AT_SEL2
+	cm_el2_sysregs_context_save(SECURE);
+#endif
 
 	return rc;
 }
@@ -109,63 +127,21 @@
 }
 
 /*******************************************************************************
- * Initialize context of SPM core.
+ * Load SPMC manifest, init SPMC.
  ******************************************************************************/
-int32_t spmd_setup(void)
+static int spmd_spmc_init(void *rd_base, size_t rd_size)
 {
 	int rc;
-	void *rd_base;
-	size_t rd_size;
-	entry_point_info_t *spmc_ep_info;
-	uintptr_t rd_base_align;
-	uintptr_t rd_size_align;
 	uint32_t ep_attr;
-
-	spmc_ep_info = bl31_plat_get_next_image_ep_info(SECURE);
-	if (!spmc_ep_info) {
-		WARN("No SPM core image provided by BL2 boot loader, Booting "
-		     "device without SP initialization. SMC`s destined for SPM "
-		     "core will return SMC_UNK\n");
-		return 1;
-	}
-
-	/* Under no circumstances will this parameter be 0 */
-	assert(spmc_ep_info->pc != 0U);
-
-	/*
-	 * Check if BL32 ep_info has a reference to 'tos_fw_config'. This will
-	 * be used as a manifest for the SPM core at the next lower EL/mode.
-	 */
-	if (spmc_ep_info->args.arg0 == 0U || spmc_ep_info->args.arg2 == 0U) {
-		ERROR("Invalid or absent SPM core manifest\n");
-		panic();
-	}
-
-	/* Obtain whereabouts of SPM core manifest */
-	rd_base = (void *) spmc_ep_info->args.arg0;
-	rd_size = spmc_ep_info->args.arg2;
-
-	rd_base_align = page_align((uintptr_t) rd_base, DOWN);
-	rd_size_align = page_align((uintptr_t) rd_size, UP);
-
-	/* Map the manifest in the SPMD translation regime first */
-	VERBOSE("SPM core manifest base : 0x%lx\n", rd_base_align);
-	VERBOSE("SPM core manifest size : 0x%lx\n", rd_size_align);
-	rc = mmap_add_dynamic_region((unsigned long long) rd_base_align,
-				     (uintptr_t) rd_base_align,
-				     rd_size_align,
-				     MT_RO_DATA);
-	if (rc < 0) {
-		ERROR("Error while mapping SPM core manifest (%d).\n", rc);
-		panic();
-	}
+	unsigned int linear_id = plat_my_core_pos();
+	spmd_spm_core_context_t *spm_ctx = &spm_core_context[linear_id];
 
 	/* Load the SPM core manifest */
 	rc = plat_spm_core_manifest_load(&spmc_attrs, rd_base, rd_size);
-	if (rc < 0) {
+	if (rc != 0) {
 		WARN("No or invalid SPM core manifest image provided by BL2 "
 		     "boot loader. ");
-		goto error;
+		return 1;
 	}
 
 	/*
@@ -177,22 +153,14 @@
 		WARN("Unsupported SPCI version (%x.%x) specified in SPM core "
 		     "manifest image provided by BL2 boot loader.\n",
 		     spmc_attrs.major_version, spmc_attrs.minor_version);
-		goto error;
+		return 1;
 	}
 
 	INFO("SPCI version (%x.%x).\n", spmc_attrs.major_version,
 	     spmc_attrs.minor_version);
 
-	/* Validate the SPM core runtime EL */
-	if ((spmc_attrs.runtime_el != MODE_EL1) &&
-	    (spmc_attrs.runtime_el != MODE_EL2)) {
-		WARN("Unsupported SPM core run time EL%x specified in "
-		     "manifest image provided by BL2 boot loader.\n",
-		     spmc_attrs.runtime_el);
-		goto error;
-	}
-
-	INFO("SPM core run time EL%x.\n", spmc_attrs.runtime_el);
+	INFO("SPM core run time EL%x.\n",
+	     SPMD_SPM_AT_SEL2 ? MODE_EL2 : MODE_EL1);
 
 	/* Validate the SPM core execution state */
 	if ((spmc_attrs.exec_state != MODE_RW_64) &&
@@ -200,42 +168,39 @@
 		WARN("Unsupported SPM core execution state %x specified in "
 		     "manifest image provided by BL2 boot loader.\n",
 		     spmc_attrs.exec_state);
-		goto error;
+		return 1;
 	}
 
 	INFO("SPM core execution state %x.\n", spmc_attrs.exec_state);
 
-	/* Ensure manifest has not requested S-EL2 in AArch32 state */
-	if ((spmc_attrs.exec_state == MODE_RW_32) &&
-	    (spmc_attrs.runtime_el == MODE_EL2)) {
-		WARN("Invalid combination of SPM core execution state (%x) "
-		     "and run time EL (%x).\n", spmc_attrs.exec_state,
-		     spmc_attrs.runtime_el);
-		goto error;
+#if SPMD_SPM_AT_SEL2
+	/* Ensure manifest has not requested AArch32 state in S-EL2 */
+	if (spmc_attrs.exec_state == MODE_RW_32) {
+		WARN("AArch32 state at S-EL2 is not supported.\n");
+		return 1;
 	}
 
 	/*
 	 * Check if S-EL2 is supported on this system if S-EL2
 	 * is required for SPM
 	 */
-	if (spmc_attrs.runtime_el == MODE_EL2) {
-		uint64_t sel2 = read_id_aa64pfr0_el1();
+	uint64_t sel2 = read_id_aa64pfr0_el1();
 
-		sel2 >>= ID_AA64PFR0_SEL2_SHIFT;
-		sel2 &= ID_AA64PFR0_SEL2_MASK;
+	sel2 >>= ID_AA64PFR0_SEL2_SHIFT;
+	sel2 &= ID_AA64PFR0_SEL2_MASK;
 
-		if (!sel2) {
-			WARN("SPM core run time EL: S-EL%x is not supported "
-			     "but specified in manifest image provided by "
-			     "BL2 boot loader.\n", spmc_attrs.runtime_el);
-			goto error;
-		}
+	if (!sel2) {
+		WARN("SPM core run time S-EL2 is not supported.");
+		return 1;
 	}
+#endif /* SPMD_SPM_AT_SEL2 */
 
 	/* Initialise an entrypoint to set up the CPU context */
 	ep_attr = SECURE | EP_ST_ENABLE;
-	if (read_sctlr_el3() & SCTLR_EE_BIT)
+	if (read_sctlr_el3() & SCTLR_EE_BIT) {
 		ep_attr |= EP_EE_BIG;
+	}
+
 	SET_PARAM_HEAD(spmc_ep_info, PARAM_EP, VERSION_1, ep_attr);
 	assert(spmc_ep_info->pc == BL32_BASE);
 
@@ -250,14 +215,22 @@
 						 DAIF_IRQ_BIT |
 						 DAIF_ABT_BIT);
 	} else {
-		spmc_ep_info->spsr = SPSR_64(spmc_attrs.runtime_el,
+
+#if SPMD_SPM_AT_SEL2
+		static const uint32_t runtime_el = MODE_EL2;
+#else
+		static const uint32_t runtime_el = MODE_EL1;
+#endif
+		spmc_ep_info->spsr = SPSR_64(runtime_el,
 					     MODE_SP_ELX,
 					     DISABLE_ALL_EXCEPTIONS);
 	}
 
 	/* Initialise SPM core context with this entry point information */
-	cm_setup_context(&(spm_core_context[plat_my_core_pos()].cpu_ctx),
-			 spmc_ep_info);
+	cm_setup_context(&spm_ctx->cpu_ctx, spmc_ep_info);
+
+	/* Reuse PSCI affinity states to mark this SPMC context as off */
+	spm_ctx->state = AFF_STATE_OFF;
 
 	INFO("SPM core setup done.\n");
 
@@ -265,23 +238,122 @@
 	bl31_register_bl32_init(&spmd_init);
 
 	return 0;
+}
 
-error:
-	WARN("Booting device without SPM initialization. "
-	     "SPCI SMCs destined for SPM core will return "
-	     "ENOTSUPPORTED\n");
+/*******************************************************************************
+ * Initialize context of SPM core.
+ ******************************************************************************/
+int spmd_setup(void)
+{
+	int rc;
+	void *rd_base;
+	size_t rd_size;
+	uintptr_t rd_base_align;
+	uintptr_t rd_size_align;
 
-	rc = mmap_remove_dynamic_region(rd_base_align, rd_size_align);
-	if (rc < 0) {
-		ERROR("Error while unmapping SPM core manifest (%d).\n",
-		      rc);
+	spmc_ep_info = bl31_plat_get_next_image_ep_info(SECURE);
+	if (!spmc_ep_info) {
+		WARN("No SPM core image provided by BL2 boot loader, Booting "
+		     "device without SP initialization. SMC`s destined for SPM "
+		     "core will return SMC_UNK\n");
+		return 1;
+	}
+
+	/* Under no circumstances will this parameter be 0 */
+	assert(spmc_ep_info->pc != 0U);
+
+	/*
+	 * Check if BL32 ep_info has a reference to 'tos_fw_config'. This will
+	 * be used as a manifest for the SPM core at the next lower EL/mode.
+	 */
+	if (spmc_ep_info->args.arg0 == 0U || spmc_ep_info->args.arg2 == 0U) {
+		ERROR("Invalid or absent SPM core manifest\n");
 		panic();
 	}
 
-	return 1;
+	/* Obtain whereabouts of SPM core manifest */
+	rd_base = (void *) spmc_ep_info->args.arg0;
+	rd_size = spmc_ep_info->args.arg2;
+
+	rd_base_align = page_align((uintptr_t) rd_base, DOWN);
+	rd_size_align = page_align((uintptr_t) rd_size, UP);
+
+	/* Map the manifest in the SPMD translation regime first */
+	VERBOSE("SPM core manifest base : 0x%lx\n", rd_base_align);
+	VERBOSE("SPM core manifest size : 0x%lx\n", rd_size_align);
+	rc = mmap_add_dynamic_region((unsigned long long) rd_base_align,
+				     (uintptr_t) rd_base_align,
+				     rd_size_align,
+				     MT_RO_DATA);
+	if (rc != 0) {
+		ERROR("Error while mapping SPM core manifest (%d).\n", rc);
+		panic();
+	}
+
+	/* Load manifest, init SPMC */
+	rc = spmd_spmc_init(rd_base, rd_size);
+	if (rc != 0) {
+		int mmap_rc;
+
+		WARN("Booting device without SPM initialization. "
+		     "SPCI SMCs destined for SPM core will return "
+		     "ENOTSUPPORTED\n");
+
+		mmap_rc = mmap_remove_dynamic_region(rd_base_align,
+						     rd_size_align);
+		if (mmap_rc != 0) {
+			ERROR("Error while unmapping SPM core manifest (%d).\n",
+			      mmap_rc);
+			panic();
+		}
+
+		return rc;
+	}
+
+	return 0;
 }
 
 /*******************************************************************************
+ * Forward SMC to the other security state
+ ******************************************************************************/
+static uint64_t spmd_smc_forward(uint32_t smc_fid, bool secure_origin,
+				 uint64_t x1, uint64_t x2, uint64_t x3,
+				 uint64_t x4, void *handle)
+{
+	uint32_t secure_state_in = (secure_origin) ? SECURE : NON_SECURE;
+	uint32_t secure_state_out = (!secure_origin) ? SECURE : NON_SECURE;
+
+	/* Save incoming security state */
+	cm_el1_sysregs_context_save(secure_state_in);
+#if SPMD_SPM_AT_SEL2
+	cm_el2_sysregs_context_save(secure_state_in);
+#endif
+
+	/* Restore outgoing security state */
+	cm_el1_sysregs_context_restore(secure_state_out);
+#if SPMD_SPM_AT_SEL2
+	cm_el2_sysregs_context_restore(secure_state_out);
+#endif
+	cm_set_next_eret_context(secure_state_out);
+
+	SMC_RET8(cm_get_context(secure_state_out), smc_fid, x1, x2, x3, x4,
+			SMC_GET_GP(handle, CTX_GPREG_X5),
+			SMC_GET_GP(handle, CTX_GPREG_X6),
+			SMC_GET_GP(handle, CTX_GPREG_X7));
+}
+
+/*******************************************************************************
+ * Return SPCI_ERROR with specified error code
+ ******************************************************************************/
+static uint64_t spmd_spci_error_return(void *handle, int error_code)
+{
+	SMC_RET8(handle, SPCI_ERROR,
+		 SPCI_TARGET_INFO_MBZ, error_code,
+		 SPCI_PARAM_MBZ, SPCI_PARAM_MBZ, SPCI_PARAM_MBZ,
+		 SPCI_PARAM_MBZ, SPCI_PARAM_MBZ);
+}
+
+/*******************************************************************************
  * This function handles all SMCs in the range reserved for SPCI. Each call is
  * either forwarded to the other security state or handled by the SPM dispatcher
  ******************************************************************************/
@@ -289,19 +361,12 @@
 			  uint64_t x3, uint64_t x4, void *cookie, void *handle,
 			  uint64_t flags)
 {
-	uint32_t in_sstate;
-	uint32_t out_sstate;
-	int32_t ret;
 	spmd_spm_core_context_t *ctx = &spm_core_context[plat_my_core_pos()];
+	bool secure_origin;
+	int32_t ret;
 
 	/* Determine which security state this SMC originated from */
-	if (is_caller_secure(flags)) {
-		in_sstate = SECURE;
-		out_sstate = NON_SECURE;
-	} else {
-		in_sstate = NON_SECURE;
-		out_sstate = SECURE;
-	}
+	secure_origin = is_caller_secure(flags);
 
 	INFO("SPM: 0x%x, 0x%llx, 0x%llx, 0x%llx, 0x%llx, "
 	     "0x%llx, 0x%llx, 0x%llx\n",
@@ -316,20 +381,12 @@
 		 * this CPU. If so, then indicate that the SPM core initialised
 		 * unsuccessfully.
 		 */
-		if ((in_sstate == SECURE) && (ctx->state == SPMC_STATE_RESET))
+		if (secure_origin && (ctx->state == SPMC_STATE_RESET)) {
 			spmd_spm_core_sync_exit(x2);
-
-		/* Save incoming security state */
-		cm_el1_sysregs_context_save(in_sstate);
-
-		/* Restore outgoing security state */
-		cm_el1_sysregs_context_restore(out_sstate);
-		cm_set_next_eret_context(out_sstate);
+		}
 
-		SMC_RET8(cm_get_context(out_sstate), smc_fid, x1, x2, x3, x4,
-			 SMC_GET_GP(handle, CTX_GPREG_X5),
-			 SMC_GET_GP(handle, CTX_GPREG_X6),
-			 SMC_GET_GP(handle, CTX_GPREG_X7));
+		return spmd_smc_forward(smc_fid, secure_origin,
+					x1, x2, x3, x4, handle);
 		break; /* not reached */
 
 	case SPCI_VERSION:
@@ -353,29 +410,18 @@
 		 */
 
 		/*
-		 * Check if w1 holds a valid SPCI fid. This is an
+		 * Check if x1 holds a valid SPCI fid. This is an
 		 * optimization.
 		 */
-		if (!is_spci_fid(x1))
-			SMC_RET8(handle, SPCI_ERROR,
-				 SPCI_TARGET_INFO_MBZ, SPCI_ERROR_NOT_SUPPORTED,
-				 SPCI_PARAM_MBZ, SPCI_PARAM_MBZ, SPCI_PARAM_MBZ,
-				 SPCI_PARAM_MBZ, SPCI_PARAM_MBZ);
+		if (!is_spci_fid(x1)) {
+			return spmd_spci_error_return(handle,
+						      SPCI_ERROR_NOT_SUPPORTED);
+		}
 
 		/* Forward SMC from Normal world to the SPM core */
-		if (in_sstate == NON_SECURE) {
-			/* Save incoming security state */
-			cm_el1_sysregs_context_save(in_sstate);
-
-			/* Restore outgoing security state */
-			cm_el1_sysregs_context_restore(out_sstate);
-			cm_set_next_eret_context(out_sstate);
-
-			SMC_RET8(cm_get_context(out_sstate), smc_fid,
-				 x1, x2, x3, x4,
-				 SMC_GET_GP(handle, CTX_GPREG_X5),
-				 SMC_GET_GP(handle, CTX_GPREG_X6),
-				 SMC_GET_GP(handle, CTX_GPREG_X7));
+		if (!secure_origin) {
+			return spmd_smc_forward(smc_fid, secure_origin,
+						x1, x2, x3, x4, handle);
 		} else {
 			/*
 			 * Return success if call was from secure world i.e. all
@@ -387,6 +433,7 @@
 				 SMC_GET_GP(handle, CTX_GPREG_X6),
 				 SMC_GET_GP(handle, CTX_GPREG_X7));
 		}
+
 		break; /* not reached */
 
 	case SPCI_RX_RELEASE:
@@ -395,11 +442,9 @@
 	case SPCI_RXTX_UNMAP:
 	case SPCI_MSG_RUN:
 		/* This interface must be invoked only by the Normal world */
-		if (in_sstate == SECURE) {
-			SMC_RET8(handle, SPCI_ERROR,
-				 SPCI_TARGET_INFO_MBZ, SPCI_ERROR_NOT_SUPPORTED,
-				 SPCI_PARAM_MBZ, SPCI_PARAM_MBZ, SPCI_PARAM_MBZ,
-				 SPCI_PARAM_MBZ, SPCI_PARAM_MBZ);
+		if (secure_origin) {
+			return spmd_spci_error_return(handle,
+						      SPCI_ERROR_NOT_SUPPORTED);
 		}
 
 		/* Fall through to forward the call to the other world */
@@ -430,17 +475,8 @@
 		 * simply forward the call to the Normal world.
 		 */
 
-		/* Save incoming security state */
-		cm_el1_sysregs_context_save(in_sstate);
-
-		/* Restore outgoing security state */
-		cm_el1_sysregs_context_restore(out_sstate);
-		cm_set_next_eret_context(out_sstate);
-
-		SMC_RET8(cm_get_context(out_sstate), smc_fid, x1, x2, x3, x4,
-			 SMC_GET_GP(handle, CTX_GPREG_X5),
-			 SMC_GET_GP(handle, CTX_GPREG_X6),
-			 SMC_GET_GP(handle, CTX_GPREG_X7));
+		return spmd_smc_forward(smc_fid, secure_origin,
+					x1, x2, x3, x4, handle);
 		break; /* not reached */
 
 	case SPCI_MSG_WAIT:
@@ -449,39 +485,25 @@
 		 * this CPU from the Secure world. If so, then indicate that the
 		 * SPM core initialised successfully.
 		 */
-		if ((in_sstate == SECURE) && (ctx->state == SPMC_STATE_RESET)) {
+		if (secure_origin && (ctx->state == SPMC_STATE_RESET)) {
 			spmd_spm_core_sync_exit(0);
 		}
 
-		/* Intentional fall-through */
+		/* Fall through to forward the call to the other world */
 
 	case SPCI_MSG_YIELD:
 		/* This interface must be invoked only by the Secure world */
-		if (in_sstate == NON_SECURE) {
-			SMC_RET8(handle, SPCI_ERROR,
-				 SPCI_TARGET_INFO_MBZ, SPCI_ERROR_NOT_SUPPORTED,
-				 SPCI_PARAM_MBZ, SPCI_PARAM_MBZ, SPCI_PARAM_MBZ,
-				 SPCI_PARAM_MBZ, SPCI_PARAM_MBZ);
+		if (!secure_origin) {
+			return spmd_spci_error_return(handle,
+						      SPCI_ERROR_NOT_SUPPORTED);
 		}
 
-		/* Save incoming security state */
-		cm_el1_sysregs_context_save(in_sstate);
-
-		/* Restore outgoing security state */
-		cm_el1_sysregs_context_restore(out_sstate);
-		cm_set_next_eret_context(out_sstate);
-
-		SMC_RET8(cm_get_context(out_sstate), smc_fid, x1, x2, x3, x4,
-			 SMC_GET_GP(handle, CTX_GPREG_X5),
-			 SMC_GET_GP(handle, CTX_GPREG_X6),
-			 SMC_GET_GP(handle, CTX_GPREG_X7));
+		return spmd_smc_forward(smc_fid, secure_origin,
+					x1, x2, x3, x4, handle);
 		break; /* not reached */
 
 	default:
 		WARN("SPM: Unsupported call 0x%08x\n", smc_fid);
-		SMC_RET8(handle, SPCI_ERROR,
-			 SPCI_TARGET_INFO_MBZ, SPCI_ERROR_NOT_SUPPORTED,
-			 SPCI_PARAM_MBZ, SPCI_PARAM_MBZ, SPCI_PARAM_MBZ,
-			 SPCI_PARAM_MBZ, SPCI_PARAM_MBZ);
+		return spmd_spci_error_return(handle, SPCI_ERROR_NOT_SUPPORTED);
 	}
 }
diff --git a/tools/encrypt_fw/Makefile b/tools/encrypt_fw/Makefile
new file mode 100644
index 0000000..cb81d0b
--- /dev/null
+++ b/tools/encrypt_fw/Makefile
@@ -0,0 +1,65 @@
+#
+# Copyright (c) 2019, Linaro Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+PROJECT		:= encrypt_fw
+V		?= 0
+BUILD_INFO	?= 1
+DEBUG		:= 0
+BINARY		:= ${PROJECT}${BIN_EXT}
+OPENSSL_DIR	:= /usr
+
+OBJECTS := src/encrypt.o \
+           src/cmd_opt.o \
+           src/main.o
+
+HOSTCCFLAGS := -Wall -std=c99
+
+MAKE_HELPERS_DIRECTORY := ../../make_helpers/
+include ${MAKE_HELPERS_DIRECTORY}build_macros.mk
+include ${MAKE_HELPERS_DIRECTORY}build_env.mk
+
+ifeq (${DEBUG},1)
+  HOSTCCFLAGS += -g -O0 -DDEBUG -DLOG_LEVEL=40
+else
+ifeq (${BUILD_INFO},1)
+  HOSTCCFLAGS += -O2 -DLOG_LEVEL=20
+else
+  HOSTCCFLAGS += -O2 -DLOG_LEVEL=10
+endif
+endif
+ifeq (${V},0)
+  Q := @
+else
+  Q :=
+endif
+
+# Make soft links and include from local directory otherwise wrong headers
+# could get pulled in from firmware tree.
+INC_DIR := -I ./include -I ../../include/tools_share -I ${OPENSSL_DIR}/include
+LIB_DIR := -L ${OPENSSL_DIR}/lib
+LIB := -lssl -lcrypto
+
+HOSTCC ?= gcc
+
+.PHONY: all clean realclean
+
+all: clean ${BINARY}
+
+${BINARY}: ${OBJECTS} Makefile
+	@echo "  HOSTLD  $@"
+	@echo 'const char build_msg[] = "Built : "__TIME__", "__DATE__;' | \
+                ${HOSTCC} -c ${HOSTCCFLAGS} -xc - -o src/build_msg.o
+	${Q}${HOSTCC} src/build_msg.o ${OBJECTS} ${LIB_DIR} ${LIB} -o $@
+
+%.o: %.c
+	@echo "  HOSTCC  $<"
+	${Q}${HOSTCC} -c ${HOSTCCFLAGS} ${INC_DIR} $< -o $@
+
+clean:
+	$(call SHELL_DELETE_ALL, src/build_msg.o ${OBJECTS})
+
+realclean: clean
+	$(call SHELL_DELETE,${BINARY})
diff --git a/tools/encrypt_fw/include/cmd_opt.h b/tools/encrypt_fw/include/cmd_opt.h
new file mode 100644
index 0000000..bd7d31f
--- /dev/null
+++ b/tools/encrypt_fw/include/cmd_opt.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019, Linaro Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CMD_OPT_H
+#define CMD_OPT_H
+
+#include <getopt.h>
+
+#define CMD_OPT_MAX_NUM			64
+
+/* Supported long command line option types */
+enum {
+	CMD_OPT_FW
+};
+
+/* Structure to define a command line option */
+typedef struct cmd_opt_s {
+	struct option long_opt;
+	const char *help_msg;
+} cmd_opt_t;
+
+/* Exported API*/
+void cmd_opt_add(const cmd_opt_t *cmd_opt);
+const struct option *cmd_opt_get_array(void);
+const char *cmd_opt_get_name(int idx);
+const char *cmd_opt_get_help_msg(int idx);
+
+#endif /* CMD_OPT_H */
diff --git a/tools/encrypt_fw/include/debug.h b/tools/encrypt_fw/include/debug.h
new file mode 100644
index 0000000..ee8f1f5
--- /dev/null
+++ b/tools/encrypt_fw/include/debug.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef DEBUG_H
+#define DEBUG_H
+
+#include <stdio.h>
+
+/* The log output macros print output to the console. These macros produce
+ * compiled log output only if the LOG_LEVEL defined in the makefile (or the
+ * make command line) is greater or equal than the level required for that
+ * type of log output.
+ * The format expected is the same as for printf(). For example:
+ * INFO("Info %s.\n", "message")    -> INFO:    Info message.
+ * WARN("Warning %s.\n", "message") -> WARNING: Warning message.
+ */
+
+#define LOG_LEVEL_NONE			0
+#define LOG_LEVEL_ERROR			10
+#define LOG_LEVEL_NOTICE		20
+#define LOG_LEVEL_WARNING		30
+#define LOG_LEVEL_INFO			40
+#define LOG_LEVEL_VERBOSE		50
+
+
+#if LOG_LEVEL >= LOG_LEVEL_NOTICE
+# define NOTICE(...)	printf("NOTICE:  " __VA_ARGS__)
+#else
+# define NOTICE(...)
+#endif
+
+#if LOG_LEVEL >= LOG_LEVEL_ERROR
+# define ERROR(...)	printf("ERROR:   " __VA_ARGS__)
+#else
+# define ERROR(...)
+#endif
+
+#if LOG_LEVEL >= LOG_LEVEL_WARNING
+# define WARN(...)	printf("WARNING: " __VA_ARGS__)
+#else
+# define WARN(...)
+#endif
+
+#if LOG_LEVEL >= LOG_LEVEL_INFO
+# define INFO(...)	printf("INFO:    " __VA_ARGS__)
+#else
+# define INFO(...)
+#endif
+
+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
+# define VERBOSE(...)	printf("VERBOSE: " __VA_ARGS__)
+#else
+# define VERBOSE(...)
+#endif
+
+#endif /* DEBUG_H */
diff --git a/tools/encrypt_fw/include/encrypt.h b/tools/encrypt_fw/include/encrypt.h
new file mode 100644
index 0000000..25d3011
--- /dev/null
+++ b/tools/encrypt_fw/include/encrypt.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2019, Linaro Limited. All rights reserved.
+ * Author: Sumit Garg <sumit.garg@linaro.org>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef ENCRYPT_H
+#define ENCRYPT_H
+
+/* Supported key algorithms */
+enum {
+	KEY_ALG_GCM		/* AES-GCM (default) */
+};
+
+int encrypt_file(unsigned short fw_enc_status, int enc_alg, char *key_string,
+		 char *nonce_string, const char *ip_name, const char *op_name);
+
+#endif /* ENCRYPT_H */
diff --git a/tools/encrypt_fw/src/cmd_opt.c b/tools/encrypt_fw/src/cmd_opt.c
new file mode 100644
index 0000000..64180d1
--- /dev/null
+++ b/tools/encrypt_fw/src/cmd_opt.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <cmd_opt.h>
+#include <getopt.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include "debug.h"
+
+/* Command line options */
+static struct option long_opt[CMD_OPT_MAX_NUM+1];
+static const char *help_msg[CMD_OPT_MAX_NUM+1];
+static int num_reg_opt;
+
+void cmd_opt_add(const cmd_opt_t *cmd_opt)
+{
+	assert(cmd_opt != NULL);
+
+	if (num_reg_opt >= CMD_OPT_MAX_NUM) {
+		ERROR("Out of memory. Please increase CMD_OPT_MAX_NUM\n");
+		exit(1);
+	}
+
+	long_opt[num_reg_opt].name = cmd_opt->long_opt.name;
+	long_opt[num_reg_opt].has_arg = cmd_opt->long_opt.has_arg;
+	long_opt[num_reg_opt].flag = 0;
+	long_opt[num_reg_opt].val = cmd_opt->long_opt.val;
+
+	help_msg[num_reg_opt] = cmd_opt->help_msg;
+
+	num_reg_opt++;
+}
+
+const struct option *cmd_opt_get_array(void)
+{
+	return long_opt;
+}
+
+const char *cmd_opt_get_name(int idx)
+{
+	if (idx >= num_reg_opt) {
+		return NULL;
+	}
+
+	return long_opt[idx].name;
+}
+
+const char *cmd_opt_get_help_msg(int idx)
+{
+	if (idx >= num_reg_opt) {
+		return NULL;
+	}
+
+	return help_msg[idx];
+}
diff --git a/tools/encrypt_fw/src/encrypt.c b/tools/encrypt_fw/src/encrypt.c
new file mode 100644
index 0000000..18a514c
--- /dev/null
+++ b/tools/encrypt_fw/src/encrypt.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2019, Linaro Limited. All rights reserved.
+ * Author: Sumit Garg <sumit.garg@linaro.org>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <firmware_encrypted.h>
+#include <openssl/evp.h>
+#include <stdio.h>
+#include <string.h>
+#include "debug.h"
+#include "encrypt.h"
+
+#define BUFFER_SIZE		256
+#define IV_SIZE			12
+#define IV_STRING_SIZE		24
+#define TAG_SIZE		16
+#define KEY_SIZE		32
+#define KEY_STRING_SIZE		64
+
+static int gcm_encrypt(unsigned short fw_enc_status, char *key_string,
+		       char *nonce_string, const char *ip_name,
+		       const char *op_name)
+{
+	FILE *ip_file;
+	FILE *op_file;
+	EVP_CIPHER_CTX *ctx;
+	unsigned char data[BUFFER_SIZE], enc_data[BUFFER_SIZE];
+	unsigned char key[KEY_SIZE], iv[IV_SIZE], tag[TAG_SIZE];
+	int bytes, enc_len = 0, i, j, ret = 0;
+	struct fw_enc_hdr header;
+
+	memset(&header, 0, sizeof(struct fw_enc_hdr));
+
+	if (strlen(key_string) != KEY_STRING_SIZE) {
+		ERROR("Unsupported key size: %lu\n", strlen(key_string));
+		return -1;
+	}
+
+	for (i = 0, j = 0; i < KEY_SIZE; i++, j += 2) {
+		if (sscanf(&key_string[j], "%02hhx", &key[i]) != 1) {
+			ERROR("Incorrect key format\n");
+			return -1;
+		}
+	}
+
+	if (strlen(nonce_string) != IV_STRING_SIZE) {
+		ERROR("Unsupported IV size: %lu\n", strlen(nonce_string));
+		return -1;
+	}
+
+	for (i = 0, j = 0; i < IV_SIZE; i++, j += 2) {
+		if (sscanf(&nonce_string[j], "%02hhx", &iv[i]) != 1) {
+			ERROR("Incorrect IV format\n");
+			return -1;
+		}
+	}
+
+	ip_file = fopen(ip_name, "rb");
+	if (ip_file == NULL) {
+		ERROR("Cannot read %s\n", ip_name);
+		return -1;
+	}
+
+	op_file = fopen(op_name, "wb");
+	if (op_file == NULL) {
+		ERROR("Cannot write %s\n", op_name);
+		fclose(ip_file);
+		return -1;
+	}
+
+	ret = fseek(op_file, sizeof(struct fw_enc_hdr), SEEK_SET);
+	if (ret) {
+		ERROR("fseek failed\n");
+		goto out_file;
+	}
+
+	ctx = EVP_CIPHER_CTX_new();
+	if (ctx == NULL) {
+		ERROR("EVP_CIPHER_CTX_new failed\n");
+		ret = -1;
+		goto out_file;
+	}
+
+	ret = EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
+	if (ret != 1) {
+		ERROR("EVP_EncryptInit_ex failed\n");
+		ret = -1;
+		goto out;
+	}
+
+	ret = EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv);
+	if (ret != 1) {
+		ERROR("EVP_EncryptInit_ex failed\n");
+		goto out;
+	}
+
+	while ((bytes = fread(data, 1, BUFFER_SIZE, ip_file)) != 0) {
+		ret = EVP_EncryptUpdate(ctx, enc_data, &enc_len, data, bytes);
+		if (ret != 1) {
+			ERROR("EVP_EncryptUpdate failed\n");
+			ret = -1;
+			goto out;
+		}
+
+		fwrite(enc_data, 1, enc_len, op_file);
+	}
+
+	ret = EVP_EncryptFinal_ex(ctx, enc_data, &enc_len);
+	if (ret != 1) {
+		ERROR("EVP_EncryptFinal_ex failed\n");
+		ret = -1;
+		goto out;
+	}
+
+	ret = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, TAG_SIZE, tag);
+	if (ret != 1) {
+		ERROR("EVP_CIPHER_CTX_ctrl failed\n");
+		ret = -1;
+		goto out;
+	}
+
+	header.magic = ENC_HEADER_MAGIC;
+	header.flags |= fw_enc_status & FW_ENC_STATUS_FLAG_MASK;
+	header.dec_algo = KEY_ALG_GCM;
+	header.iv_len = IV_SIZE;
+	header.tag_len = TAG_SIZE;
+	memcpy(header.iv, iv, IV_SIZE);
+	memcpy(header.tag, tag, TAG_SIZE);
+
+	ret = fseek(op_file, 0, SEEK_SET);
+	if (ret) {
+		ERROR("fseek failed\n");
+		goto out;
+	}
+
+	fwrite(&header, 1, sizeof(struct fw_enc_hdr), op_file);
+
+out:
+	EVP_CIPHER_CTX_free(ctx);
+
+out_file:
+	fclose(ip_file);
+	fclose(op_file);
+
+	/*
+	 * EVP_* APIs returns 1 as success but enctool considers
+	 * 0 as success.
+	 */
+	if (ret == 1)
+		ret = 0;
+
+	return ret;
+}
+
+int encrypt_file(unsigned short fw_enc_status, int enc_alg, char *key_string,
+		 char *nonce_string, const char *ip_name, const char *op_name)
+{
+	switch (enc_alg) {
+	case KEY_ALG_GCM:
+		return gcm_encrypt(fw_enc_status, key_string, nonce_string,
+				   ip_name, op_name);
+	default:
+		return -1;
+	}
+}
diff --git a/tools/encrypt_fw/src/main.c b/tools/encrypt_fw/src/main.c
new file mode 100644
index 0000000..39b7af7
--- /dev/null
+++ b/tools/encrypt_fw/src/main.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2019, Linaro Limited. All rights reserved.
+ * Author: Sumit Garg <sumit.garg@linaro.org>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <ctype.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include <openssl/conf.h>
+
+#include "cmd_opt.h"
+#include "debug.h"
+#include "encrypt.h"
+#include "firmware_encrypted.h"
+
+#define NUM_ELEM(x)			((sizeof(x)) / (sizeof(x[0])))
+#define HELP_OPT_MAX_LEN		128
+
+/* Global options */
+
+/* Info messages created in the Makefile */
+extern const char build_msg[];
+
+static char *key_algs_str[] = {
+	[KEY_ALG_GCM] = "gcm",
+};
+
+static void print_help(const char *cmd, const struct option *long_opt)
+{
+	int rem, i = 0;
+	const struct option *opt;
+	char line[HELP_OPT_MAX_LEN];
+	char *p;
+
+	assert(cmd != NULL);
+	assert(long_opt != NULL);
+
+	printf("\n\n");
+	printf("The firmware encryption tool loads the binary image and\n"
+	       "outputs encrypted binary image using an encryption key\n"
+	       "provided as an input hex string.\n");
+	printf("\n");
+	printf("Usage:\n");
+	printf("\t%s [OPTIONS]\n\n", cmd);
+
+	printf("Available options:\n");
+	opt = long_opt;
+	while (opt->name) {
+		p = line;
+		rem = HELP_OPT_MAX_LEN;
+		if (isalpha(opt->val)) {
+			/* Short format */
+			sprintf(p, "-%c,", (char)opt->val);
+			p += 3;
+			rem -= 3;
+		}
+		snprintf(p, rem, "--%s %s", opt->name,
+			 (opt->has_arg == required_argument) ? "<arg>" : "");
+		printf("\t%-32s %s\n", line, cmd_opt_get_help_msg(i));
+		opt++;
+		i++;
+	}
+	printf("\n");
+}
+
+static int get_key_alg(const char *key_alg_str)
+{
+	int i;
+
+	for (i = 0 ; i < NUM_ELEM(key_algs_str) ; i++) {
+		if (strcmp(key_alg_str, key_algs_str[i]) == 0) {
+			return i;
+		}
+	}
+
+	return -1;
+}
+
+static void parse_fw_enc_status_flag(const char *arg,
+				     unsigned short *fw_enc_status)
+{
+	unsigned long flag;
+	char *endptr;
+
+	flag = strtoul(arg, &endptr, 16);
+	if (*endptr != '\0' || flag > FW_ENC_WITH_BSSK) {
+		ERROR("Invalid fw_enc_status flag '%s'\n", arg);
+		exit(1);
+	}
+
+	*fw_enc_status = flag & FW_ENC_STATUS_FLAG_MASK;
+}
+
+/* Common command line options */
+static const cmd_opt_t common_cmd_opt[] = {
+	{
+		{ "help", no_argument, NULL, 'h' },
+		"Print this message and exit"
+	},
+	{
+		{ "fw-enc-status", required_argument, NULL, 'f' },
+		"Firmware encryption status flag (with SSK=0 or BSSK=1)."
+	},
+	{
+		{ "key-alg", required_argument, NULL, 'a' },
+		"Encryption key algorithm: 'gcm' (default)"
+	},
+	{
+		{ "key", required_argument, NULL, 'k' },
+		"Encryption key (for supported algorithm)."
+	},
+	{
+		{ "nonce", required_argument, NULL, 'n' },
+		"Nonce or Initialization Vector (for supported algorithm)."
+	},
+	{
+		{ "in", required_argument, NULL, 'i' },
+		"Input filename to be encrypted."
+	},
+	{
+		{ "out", required_argument, NULL, 'o' },
+		"Encrypted output filename."
+	},
+};
+
+int main(int argc, char *argv[])
+{
+	int i, key_alg, ret;
+	int c, opt_idx = 0;
+	const struct option *cmd_opt;
+	char *key = NULL;
+	char *nonce = NULL;
+	char *in_fn = NULL;
+	char *out_fn = NULL;
+	unsigned short fw_enc_status = 0;
+
+	NOTICE("Firmware Encryption Tool: %s\n", build_msg);
+
+	/* Set default options */
+	key_alg = KEY_ALG_GCM;
+
+	/* Add common command line options */
+	for (i = 0; i < NUM_ELEM(common_cmd_opt); i++) {
+		cmd_opt_add(&common_cmd_opt[i]);
+	}
+
+	/* Get the command line options populated during the initialization */
+	cmd_opt = cmd_opt_get_array();
+
+	while (1) {
+		/* getopt_long stores the option index here. */
+		c = getopt_long(argc, argv, "a:f:hi:k:n:o:", cmd_opt, &opt_idx);
+
+		/* Detect the end of the options. */
+		if (c == -1) {
+			break;
+		}
+
+		switch (c) {
+		case 'a':
+			key_alg = get_key_alg(optarg);
+			if (key_alg < 0) {
+				ERROR("Invalid key algorithm '%s'\n", optarg);
+				exit(1);
+			}
+			break;
+		case 'f':
+			parse_fw_enc_status_flag(optarg, &fw_enc_status);
+			break;
+		case 'k':
+			key = optarg;
+			break;
+		case 'i':
+			in_fn = optarg;
+			break;
+		case 'o':
+			out_fn = optarg;
+			break;
+		case 'n':
+			nonce = optarg;
+			break;
+		case 'h':
+			print_help(argv[0], cmd_opt);
+			exit(0);
+		case '?':
+		default:
+			print_help(argv[0], cmd_opt);
+			exit(1);
+		}
+	}
+
+	if (!key) {
+		ERROR("Key must not be NULL\n");
+		exit(1);
+	}
+
+	if (!nonce) {
+		ERROR("Nonce must not be NULL\n");
+		exit(1);
+	}
+
+	if (!in_fn) {
+		ERROR("Input filename must not be NULL\n");
+		exit(1);
+	}
+
+	if (!out_fn) {
+		ERROR("Output filename must not be NULL\n");
+		exit(1);
+	}
+
+	ret = encrypt_file(fw_enc_status, key_alg, key, nonce, in_fn, out_fn);
+
+	CRYPTO_cleanup_all_ex_data();
+
+	return ret;
+}
diff --git a/tools/memory/print_memory_map.py b/tools/memory/print_memory_map.py
index 35cccd3..8a84018 100755
--- a/tools/memory/print_memory_map.py
+++ b/tools/memory/print_memory_map.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python3
 #
-# Copyright (c) 2019, Arm Limited. All rights reserved.
+# Copyright (c) 2019-2020, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -22,6 +22,7 @@
                 '__DATA_START__', '__DATA_END__',
                 '__STACKS_START__', '__STACKS_END__',
                 '__BSS_END',
+                '__COHERENT_RAM_START__', '__COHERENT_RAM_END__',
                ]
 
 # Regex to extract address from map file
@@ -31,8 +32,11 @@
 address_list = []
 
 # Get the directory from command line or use a default one
+inverted_print = True
 if len(sys.argv) >= 2:
     build_dir = sys.argv[1]
+    if len(sys.argv) >= 3:
+        inverted_print = sys.argv[2] == '0'
 else:
     build_dir = 'build/fvp/debug'
 
@@ -43,7 +47,10 @@
         with open (file_path, 'rt') as mapfile:
             for line in mapfile:
                 for symbol in blx_symbols:
-                    if line.find(symbol) > 0 and line.find("ASSERT") < 0:
+                    # Regex to find symbol definition
+                    line_pattern = re.compile(r"\b0x\w*\s*" + symbol + "\s= .")
+                    match = line_pattern.search(line)
+                    if match:
                         # Extract address from line
                         match = address_pattern.search(line)
                         if match:
@@ -52,17 +59,21 @@
 # Sort by address
 address_list.sort(key=operator.itemgetter(0))
 
+# Invert list for lower address at bottom
+if inverted_print:
+    address_list = reversed(address_list)
+
 # Generate memory view
-print('{:-^87}'.format('Memory Map from: ' + build_dir))
-for address in reversed(address_list):
+print('{:-^93}'.format('Memory Map from: ' + build_dir))
+for address in address_list:
     if "bl1" in address[2]:
-        print(address[0], '+{:-^20}+ |{:^20}| |{:^20}|'.format(address[1], '', ''))
+        print(address[0], '+{:-^22}+ |{:^22}| |{:^22}|'.format(address[1], '', ''))
     elif "bl2" in address[2]:
-        print(address[0], '|{:^20}| +{:-^20}+ |{:^20}|'.format('', address[1], ''))
+        print(address[0], '|{:^22}| +{:-^22}+ |{:^22}|'.format('', address[1], ''))
     elif "bl31" in address[2]:
-        print(address[0], '|{:^20}| |{:^20}| +{:-^20}+'.format('', '', address[1]))
+        print(address[0], '|{:^22}| |{:^22}| +{:-^22}+'.format('', '', address[1]))
     else:
-        print(address[0], '|{:^20}| |{:^20}| +{:-^20}+'.format('', '', address[1]))
+        print(address[0], '|{:^22}| |{:^22}| +{:-^22}+'.format('', '', address[1]))
 
-print('{:^20}{:_^20}   {:_^20}   {:_^20}'.format('', '', '', ''))
-print('{:^20}{:^20}   {:^20}   {:^20}'.format('address', 'bl1', 'bl2', 'bl31'))
+print('{:^20}{:_^22}   {:_^22}   {:_^22}'.format('', '', '', ''))
+print('{:^20}{:^22}   {:^22}   {:^22}'.format('address', 'bl1', 'bl2', 'bl31'))
diff --git a/tools/sptool/sp_mk_generator.py b/tools/sptool/sp_mk_generator.py
new file mode 100755
index 0000000..6b6fa19
--- /dev/null
+++ b/tools/sptool/sp_mk_generator.py
@@ -0,0 +1,100 @@
+#!/usr/bin/python3
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+"""
+This script is invoked by Make system and generates secure partition makefile.
+It expects platform provided secure partition layout file which contains list
+of Secure Partition Images and Partition manifests(PM).
+Layout file can exist outside of TF-A tree and the paths of Image and PM files
+must be relative to it.
+
+This script parses the layout file and generates a make file which updates
+FDT_SOURCES, FIP_ARGS and SPTOOL_ARGS which are used in later build steps.
+This script also gets SP "uuid" from parsing its PM and converting it to a
+standard format.
+
+param1: Generated mk file "sp_gen.mk"
+param2: "SP_LAYOUT_FILE", json file containing platform provided information
+param3: plat out directory
+
+Generated "sp_gen.mk" file contains triplet of following information for each
+Secure Partition entry
+    FDT_SOURCES +=  sp1.dts
+    SPTOOL_ARGS += -i sp1.bin:sp1.dtb -o sp1.pkg
+    FIP_ARGS += --blob uuid=XXXXX-XXX...,file=sp1.pkg
+
+A typical SP_LAYOUT_FILE file will look like
+{
+        "SP1" : {
+                "image": "sp1.bin",
+                "pm": "test/sp1.dts"
+        },
+
+        "SP2" : {
+                "image": "sp2.bin",
+                "pm": "test/sp2.dts"
+        }
+
+        ...
+}
+
+"""
+
+import getopt
+import json
+import os
+import re
+import sys
+import uuid
+
+with open(sys.argv[2],'r') as in_file:
+    data = json.load(in_file)
+json_file = os.path.abspath(sys.argv[2])
+json_dir = os.path.dirname(json_file)
+gen_file = sys.argv[1]
+out_dir = sys.argv[3][2:]
+dtb_dir = out_dir + "/fdts/"
+print(dtb_dir)
+
+with open(gen_file, 'w') as out_file:
+    for key in data.keys():
+
+        """
+        Append FDT_SOURCES
+        """
+        dts = os.path.join(json_dir, data[key]['pm'])
+        dtb = dtb_dir + os.path.basename(data[key]['pm'][:-1] + "b")
+        out_file.write("FDT_SOURCES += " + dts + "\n")
+
+        """
+        Update SPTOOL_ARGS
+        """
+        dst = out_dir + "/" + key + ".pkg"
+        src = [ json_dir + "/" + data[key]['image'] , dtb  ]
+        out_file.write("SPTOOL_ARGS += -i " + ":".join(src) + " -o " + dst + "\n")
+
+        """
+        Extract uuid from partition manifest
+        """
+        pm_file = open(dts)
+        key = "uuid"
+
+        for line in pm_file:
+            if key in line:
+                uuid_hex = re.findall(r'\<(.+?)\>', line)[0];
+
+        # PM has uuid in format 0xABC... 0x... 0x... 0x...
+        # Get rid of '0x' and spaces and convert to string of hex digits
+        uuid_hex = uuid_hex.replace('0x','').replace(' ','')
+        # make UUID from a string of hex digits
+        uuid_std = uuid.UUID(uuid_hex)
+        # convert UUID to a string of hex digits in standard form
+        uuid_std = str(uuid_std)
+
+        """
+        Append FIP_ARGS
+        """
+        out_file.write("FIP_ARGS += --blob uuid=" + uuid_std + ",file=" + dst + "\n")
+        out_file.write("\n")