Merge "locks: bakery: add a DMB to the 'read_cache_op' macro" into integration
diff --git a/Makefile b/Makefile
index f3cb9be..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
 ################################################################################
@@ -623,7 +631,7 @@
 
 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
@@ -635,6 +643,14 @@
     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
 ################################################################################
@@ -708,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}
@@ -814,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))
@@ -843,6 +866,7 @@
 $(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))
@@ -854,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))
@@ -926,7 +952,7 @@
 # Build targets
 ################################################################################
 
-.PHONY:	all msg_start clean realclean distclean cscope locate-checkpatch checkcodebase checkpatch fiptool sptool fip sp 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
@@ -974,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
@@ -985,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)
@@ -1029,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:
@@ -1038,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
@@ -1139,6 +1177,15 @@
 	@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
@@ -1175,6 +1222,7 @@
 	@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"
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/bl1/bl1.ld.S b/bl1/bl1.ld.S
index b20859b..e65ab90 100644
--- a/bl1/bl1.ld.S
+++ b/bl1/bl1.ld.S
@@ -1,11 +1,12 @@
 /*
- * 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
  */
 
 #include <platform_def.h>
 
+#include <common/bl_common.ld.h>
 #include <lib/xlat_tables/xlat_tables_defs.h>
 
 OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
@@ -148,15 +149,7 @@
         __BSS_END__ = .;
     } >RAM
 
-    /*
-     * The xlat_table section is for full, aligned page tables (4K).
-     * Removing them from .bss avoids forcing 4K alignment on
-     * the .bss section. The tables are initialized to zero by the translation
-     * tables library.
-     */
-    xlat_table (NOLOAD) : {
-        *(xlat_table)
-    } >RAM
+    XLAT_TABLE_SECTION >RAM
 
 #if USE_COHERENT_MEM
     /*
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/bl2/bl2.ld.S b/bl2/bl2.ld.S
index c1338e2..d08b046 100644
--- a/bl2/bl2.ld.S
+++ b/bl2/bl2.ld.S
@@ -6,6 +6,7 @@
 
 #include <platform_def.h>
 
+#include <common/bl_common.ld.h>
 #include <lib/xlat_tables/xlat_tables_defs.h>
 
 OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
@@ -125,15 +126,7 @@
         __BSS_END__ = .;
     } >RAM
 
-    /*
-     * The xlat_table section is for full, aligned page tables (4K).
-     * Removing them from .bss avoids forcing 4K alignment on
-     * the .bss section. The tables are initialized to zero by the translation
-     * tables library.
-     */
-    xlat_table (NOLOAD) : {
-        *(xlat_table)
-    } >RAM
+    XLAT_TABLE_SECTION >RAM
 
 #if USE_COHERENT_MEM
     /*
diff --git a/bl2/bl2_el3.ld.S b/bl2/bl2_el3.ld.S
index b6570ee..a72818c 100644
--- a/bl2/bl2_el3.ld.S
+++ b/bl2/bl2_el3.ld.S
@@ -1,11 +1,12 @@
 /*
- * 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
  */
 
 #include <platform_def.h>
 
+#include <common/bl_common.ld.h>
 #include <lib/xlat_tables/xlat_tables_defs.h>
 
 OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
@@ -188,15 +189,7 @@
         __BSS_END__ = .;
     } >RAM
 
-    /*
-     * The xlat_table section is for full, aligned page tables (4K).
-     * Removing them from .bss avoids forcing 4K alignment on
-     * the .bss section. The tables are initialized to zero by the translation
-     * tables library.
-     */
-    xlat_table (NOLOAD) : {
-        *(xlat_table)
-    } >RAM
+    XLAT_TABLE_SECTION >RAM
 
 #if USE_COHERENT_MEM
     /*
diff --git a/bl2u/bl2u.ld.S b/bl2u/bl2u.ld.S
index 8d257ce..96545a3 100644
--- a/bl2u/bl2u.ld.S
+++ b/bl2u/bl2u.ld.S
@@ -1,11 +1,12 @@
 /*
- * 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
  */
 
 #include <platform_def.h>
 
+#include <common/bl_common.ld.h>
 #include <lib/xlat_tables/xlat_tables_defs.h>
 
 OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
@@ -102,15 +103,7 @@
         __BSS_END__ = .;
     } >RAM
 
-    /*
-     * The xlat_table section is for full, aligned page tables (4K).
-     * Removing them from .bss avoids forcing 4K alignment on
-     * the .bss section. The tables are initialized to zero by the translation
-     * tables library.
-     */
-    xlat_table (NOLOAD) : {
-        *(xlat_table)
-    } >RAM
+    XLAT_TABLE_SECTION >RAM
 
 #if USE_COHERENT_MEM
     /*
diff --git a/bl31/aarch64/crash_reporting.S b/bl31/aarch64/crash_reporting.S
index 97db2a1..d56b513 100644
--- a/bl31/aarch64/crash_reporting.S
+++ b/bl31/aarch64/crash_reporting.S
@@ -16,6 +16,7 @@
 	.globl	report_unhandled_exception
 	.globl	report_unhandled_interrupt
 	.globl	el3_panic
+	.globl	elx_panic
 
 #if CRASH_REPORTING
 
@@ -59,7 +60,11 @@
 excpt_msg:
 	.asciz "Unhandled Exception in EL3.\nx30"
 intr_excpt_msg:
-	.asciz "Unhandled Interrupt Exception in EL3.\nx30"
+	.ascii "Unhandled Interrupt Exception in EL3.\n"
+x30_msg:
+	.asciz "x30"
+excpt_msg_el:
+	.asciz "Unhandled Exception from EL"
 
 	/*
 	 * Helper function to print from crash buf.
@@ -170,7 +175,6 @@
 	b	do_crash_reporting
 endfunc report_unhandled_exception
 
-
 	/* -----------------------------------------------------
 	 * This function allows to report a crash (if crash
 	 * reporting is enabled) when an unhandled interrupt
@@ -188,6 +192,112 @@
 endfunc report_unhandled_interrupt
 
 	/* -----------------------------------------------------
+	 * This function allows to report a crash from the lower
+	 * exception level (if crash reporting is enabled) when
+	 * panic() is invoked from C Runtime.
+	 * It prints the CPU state via the crash console making
+	 * use of 'cpu_context' structure where general purpose
+	 * registers are saved and the crash buf.
+	 * This function will not return.
+	 *
+ 	 * x0: Exception level
+	 * -----------------------------------------------------
+	 */
+func elx_panic
+	msr	spsel, #MODE_SP_ELX
+	mov	x8, x0
+
+	/* Print the crash message */
+	adr	x4, excpt_msg_el
+	bl	asm_print_str
+
+	/* Print exception level */
+	add	x0, x8, #'0'
+	bl	plat_crash_console_putc
+	bl	asm_print_newline
+
+	/* Report x0 - x29 values stored in 'gpregs_ctx' structure */
+	/* Store the ascii list pointer in x6 */
+	adr	x6, gp_regs
+	add	x7, sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0
+
+print_next:
+	ldrb	w4, [x6]
+	/* Test whether we are at end of list */
+	cbz	w4, print_x30
+	mov	x4, x6
+	/* asm_print_str updates x4 to point to next entry in list */
+	bl	asm_print_str
+	/* x0 = number of symbols printed + 1 */
+	sub	x0, x4, x6
+	/* Update x6 with the updated list pointer */
+	mov	x6, x4
+	bl	print_alignment
+	ldr	x4, [x7], #REGSZ
+	bl	asm_print_hex
+	bl	asm_print_newline
+	b	print_next
+
+print_x30:
+	adr	x4, x30_msg
+	bl	asm_print_str
+
+	/* Print spaces to align "x30" string */
+	mov	x0, #4
+	bl	print_alignment
+
+	/* Report x30 */
+	ldr	x4, [x7]
+
+	/* ----------------------------------------------------------------
+	 * Different virtual address space size can be defined for each EL.
+	 * Ensure that we use the proper one by reading the corresponding
+	 * TCR_ELx register.
+	 * ----------------------------------------------------------------
+	 */
+	cmp	x8, #MODE_EL2
+	b.lt	from_el1	/* EL1 */
+	mrs	x2, sctlr_el2
+	mrs	x1, tcr_el2
+
+	/* ----------------------------------------------------------------
+	 * Check if pointer authentication is enabled at the specified EL.
+	 * If it isn't, we can then skip stripping a PAC code.
+	 * ----------------------------------------------------------------
+	 */
+test_pauth:
+	tst	x2, #(SCTLR_EnIA_BIT | SCTLR_EnIB_BIT)
+	b.eq	no_pauth
+
+	/* Demangle address */
+	and	x1, x1, #0x3F	/* T0SZ = TCR_ELx[5:0] */
+	sub	x1, x1, #64
+	neg	x1, x1		/* bottom_pac_bit = 64 - T0SZ */
+	mov	x2, #-1
+	lsl	x2, x2, x1
+	bic	x4, x4, x2
+
+no_pauth:
+	bl	asm_print_hex
+	bl	asm_print_newline
+
+	/* tpidr_el3 contains the address to cpu_data structure */
+	mrs	x0, tpidr_el3
+	/* Calculate the Crash buffer offset in cpu_data */
+	add	x0, x0, #CPU_DATA_CRASH_BUF_OFFSET
+	/* Store crash buffer address in tpidr_el3 */
+	msr	tpidr_el3, x0
+
+	/* Print the rest of crash dump */
+	b	print_el3_sys_regs
+
+from_el1:
+	mrs	x2, sctlr_el1
+	mrs	x1, tcr_el1
+	b	test_pauth
+endfunc	elx_panic
+
+	/* -----------------------------------------------------
 	 * This function allows to report a crash (if crash
 	 * reporting is enabled) when panic() is invoked from
 	 * C Runtime. It prints the CPU state via the crash
@@ -200,9 +310,7 @@
 	prepare_crash_buf_save_x0_x1
 	adr	x0, panic_msg
 	mov	sp, x0
-	/* This call will not return */
-	b	do_crash_reporting
-endfunc el3_panic
+	/* Fall through to 'do_crash_reporting' */
 
 	/* ------------------------------------------------------------
 	 * The common crash reporting functionality. It requires x0
@@ -223,7 +331,7 @@
 	 *     the crash buf to the crash console.
 	 * ------------------------------------------------------------
 	 */
-func do_crash_reporting
+do_crash_reporting:
 	/* Retrieve the crash buf from tpidr_el3 */
 	mrs	x0, tpidr_el3
 	/* Store x2 - x6, x30 in the crash buffer */
@@ -240,9 +348,9 @@
 	/* Print spaces to align "x30" string */
 	mov	x0, #4
 	bl	print_alignment
-	/* load the crash buf address */
+	/* Load the crash buf address */
 	mrs	x0, tpidr_el3
-	/* report x30 first from the crash buf */
+	/* Report x30 first from the crash buf */
 	ldr	x4, [x0, #REGSZ * 7]
 
 #if ENABLE_PAUTH
@@ -256,7 +364,7 @@
 	/* Now mov x7 into crash buf */
 	str	x7, [x0, #REGSZ * 7]
 
-	/* Report x0 - x29 values stored in crash buf*/
+	/* Report x0 - x29 values stored in crash buf */
 	/* Store the ascii list pointer in x6 */
 	adr	x6, gp_regs
 	/* Print x0 to x7 from the crash buf */
@@ -279,6 +387,7 @@
 	bl	size_controlled_print
 
 	/* Print the el3 sys registers */
+print_el3_sys_regs:
 	adr	x6, el3_sys_regs
 	mrs	x8, scr_el3
 	mrs	x9, sctlr_el3
@@ -354,7 +463,7 @@
 
 	/* Done reporting */
 	no_ret	plat_panic_handler
-endfunc do_crash_reporting
+endfunc el3_panic
 
 #else	/* CRASH_REPORTING */
 func report_unhandled_exception
@@ -363,7 +472,6 @@
 endfunc report_unhandled_exception
 #endif	/* CRASH_REPORTING */
 
-
 func crash_panic
 	no_ret	plat_panic_handler
 endfunc crash_panic
diff --git a/bl31/bl31.ld.S b/bl31/bl31.ld.S
index 4a1c5f3..e0138ac 100644
--- a/bl31/bl31.ld.S
+++ b/bl31/bl31.ld.S
@@ -6,6 +6,7 @@
 
 #include <platform_def.h>
 
+#include <common/bl_common.ld.h>
 #include <lib/xlat_tables/xlat_tables_defs.h>
 
 OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
@@ -287,15 +288,7 @@
         __BSS_END__ = .;
     } >NOBITS
 
-    /*
-     * The xlat_table section is for full, aligned page tables (4K).
-     * Removing them from .bss avoids forcing 4K alignment on
-     * the .bss section. The tables are initialized to zero by the translation
-     * tables library.
-     */
-    xlat_table (NOLOAD) : {
-        *(xlat_table)
-    } >NOBITS
+    XLAT_TABLE_SECTION >NOBITS
 
 #if USE_COHERENT_MEM
     /*
diff --git a/bl32/sp_min/sp_min.ld.S b/bl32/sp_min/sp_min.ld.S
index 6997a7f..3b1ca1b 100644
--- a/bl32/sp_min/sp_min.ld.S
+++ b/bl32/sp_min/sp_min.ld.S
@@ -1,11 +1,12 @@
 /*
- * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include <platform_def.h>
 
+#include <common/bl_common.ld.h>
 #include <lib/xlat_tables/xlat_tables_defs.h>
 
 OUTPUT_FORMAT(elf32-littlearm)
@@ -196,15 +197,7 @@
         __BSS_END__ = .;
     } >RAM
 
-    /*
-     * The xlat_table section is for full, aligned page tables (4K).
-     * Removing them from .bss avoids forcing 4K alignment on
-     * the .bss section. The tables are initialized to zero by the translation
-     * tables library.
-     */
-    xlat_table (NOLOAD) : {
-        *(xlat_table)
-    } >RAM
+    XLAT_TABLE_SECTION >RAM
 
      __BSS_SIZE__ = SIZEOF(.bss);
 
diff --git a/bl32/tsp/tsp.ld.S b/bl32/tsp/tsp.ld.S
index 592e245..da60c63 100644
--- a/bl32/tsp/tsp.ld.S
+++ b/bl32/tsp/tsp.ld.S
@@ -4,6 +4,7 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <common/bl_common.ld.h>
 #include <lib/xlat_tables/xlat_tables_defs.h>
 #include <platform_def.h>
 
@@ -125,15 +126,7 @@
         __BSS_END__ = .;
     } >RAM
 
-    /*
-     * The xlat_table section is for full, aligned page tables (4K).
-     * Removing them from .bss avoids forcing 4K alignment on
-     * the .bss section. The tables are initialized to zero by the translation
-     * tables library.
-     */
-    xlat_table (NOLOAD) : {
-        *(xlat_table)
-    } >RAM
+    XLAT_TABLE_SECTION >RAM
 
 #if USE_COHERENT_MEM
     /*
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/common/aarch64/debug.S b/common/aarch64/debug.S
index e6e3298..7db2439 100644
--- a/common/aarch64/debug.S
+++ b/common/aarch64/debug.S
@@ -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
  */
@@ -156,16 +156,32 @@
 
 /* This is for the non el3 BL stages to compile through */
 	.weak el3_panic
+	.weak elx_panic
 
 func do_panic
 #if CRASH_REPORTING
 	str	x0, [sp, #-0x10]!
 	mrs	x0, currentel
-	ubfx	x0, x0, #2, #2
-	cmp	x0, #0x3
+	ubfx	x0, x0, #MODE_EL_SHIFT, #MODE_EL_WIDTH
+	cmp	x0, #MODE_EL3
+#if !HANDLE_EA_EL3_FIRST
 	ldr	x0, [sp], #0x10
 	b.eq	el3_panic
-#endif
+#else
+	b.ne	to_panic_common
+
+	/* Check EL the exception taken from */
+	mrs	x0, spsr_el3
+	ubfx	x0, x0, #SPSR_EL_SHIFT, #SPSR_EL_WIDTH
+	cmp	x0, #MODE_EL3
+	b.ne	elx_panic
+	ldr	x0, [sp], #0x10
+	b	el3_panic
+
+to_panic_common:
+	ldr	x0, [sp], #0x10
+#endif /* HANDLE_EA_EL3_FIRST */
+#endif /* CRASH_REPORTING */
 
 panic_common:
 /*
diff --git a/common/backtrace/backtrace.c b/common/backtrace/backtrace.c
index 907117f..ef57500 100644
--- a/common/backtrace/backtrace.c
+++ b/common/backtrace/backtrace.c
@@ -37,7 +37,7 @@
 	uintptr_t return_addr;
 };
 
-static const char *get_el_str(unsigned int el)
+const char *get_el_str(unsigned int el)
 {
 	if (el == 3U) {
 		return "EL3";
diff --git a/docs/change-log-upcoming.rst b/docs/change-log-upcoming.rst
index c4e8bb0..f86280f 100644
--- a/docs/change-log-upcoming.rst
+++ b/docs/change-log-upcoming.rst
@@ -24,6 +24,8 @@
 
 - Build System
    - Add support for documentation build as a target in Makefile
+   - Add ``COT`` build option to select the chain of trust to use when the
+     Trusted Boot feature is enabled (default: ``tbbr``).
 
 - CPU Support
    - Example: "cortex-a55: Workaround for erratum 1221012"
@@ -40,12 +42,15 @@
 
 - Platforms
    - Example: "arm/common: Introduce wrapper functions to setup secure watchdog"
+   - plat/arm: Add support for the new `dualroot` chain of trust.
 
 - PSCI
    - Example: "Adding new optional PSCI hook ``pwr_domain_on_finish_late``"
 
 - Security
    - Example: "UBSAN support and handlers"
+   - Add support for optional firmware encryption feature (experimental).
+   - Introduce a new `dualroot` chain of trust.
 
 - 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 ae77391..1a53e22 100644
--- a/docs/design/auth-framework.rst
+++ b/docs/design/auth-framework.rst
@@ -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
diff --git a/docs/design/firmware-design.rst b/docs/design/firmware-design.rst
index d0d6ef6..8297dc7 100644
--- a/docs/design/firmware-design.rst
+++ b/docs/design/firmware-design.rst
@@ -1177,83 +1177,104 @@
 
 ::
 
-    x0  :0x000000004F00007C
-    x1  :0x0000000007FFFFFF
-    x2  :0x0000000004014D50
-    x3  :0x0000000000000000
-    x4  :0x0000000088007998
-    x5  :0x00000000001343AC
-    x6  :0x0000000000000016
-    x7  :0x00000000000B8A38
-    x8  :0x00000000001343AC
-    x9  :0x00000000000101A8
-    x10 :0x0000000000000002
-    x11 :0x000000000000011C
-    x12 :0x00000000FEFDC644
-    x13 :0x00000000FED93FFC
-    x14 :0x0000000000247950
-    x15 :0x00000000000007A2
-    x16 :0x00000000000007A4
-    x17 :0x0000000000247950
-    x18 :0x0000000000000000
-    x19 :0x00000000FFFFFFFF
-    x20 :0x0000000004014D50
-    x21 :0x000000000400A38C
-    x22 :0x0000000000247950
-    x23 :0x0000000000000010
-    x24 :0x0000000000000024
-    x25 :0x00000000FEFDC868
-    x26 :0x00000000FEFDC86A
-    x27 :0x00000000019EDEDC
-    x28 :0x000000000A7CFDAA
-    x29 :0x0000000004010780
-    x30 :0x000000000400F004
-    scr_el3 :0x0000000000000D3D
-    sctlr_el3   :0x0000000000C8181F
-    cptr_el3    :0x0000000000000000
-    tcr_el3 :0x0000000080803520
-    daif    :0x00000000000003C0
-    mair_el3    :0x00000000000004FF
-    spsr_el3    :0x00000000800003CC
-    elr_el3 :0x000000000400C0CC
-    ttbr0_el3   :0x00000000040172A0
-    esr_el3 :0x0000000096000210
-    sp_el3  :0x0000000004014D50
-    far_el3 :0x000000004F00007C
-    spsr_el1    :0x0000000000000000
-    elr_el1 :0x0000000000000000
-    spsr_abt    :0x0000000000000000
-    spsr_und    :0x0000000000000000
-    spsr_irq    :0x0000000000000000
-    spsr_fiq    :0x0000000000000000
-    sctlr_el1   :0x0000000030C81807
-    actlr_el1   :0x0000000000000000
-    cpacr_el1   :0x0000000000300000
-    csselr_el1  :0x0000000000000002
-    sp_el1  :0x0000000004028800
-    esr_el1 :0x0000000000000000
-    ttbr0_el1   :0x000000000402C200
-    ttbr1_el1   :0x0000000000000000
-    mair_el1    :0x00000000000004FF
-    amair_el1   :0x0000000000000000
-    tcr_el1 :0x0000000000003520
-    tpidr_el1   :0x0000000000000000
-    tpidr_el0   :0x0000000000000000
-    tpidrro_el0 :0x0000000000000000
-    dacr32_el2  :0x0000000000000000
-    ifsr32_el2  :0x0000000000000000
-    par_el1 :0x0000000000000000
-    far_el1 :0x0000000000000000
-    afsr0_el1   :0x0000000000000000
-    afsr1_el1   :0x0000000000000000
-    contextidr_el1  :0x0000000000000000
-    vbar_el1    :0x0000000004027000
-    cntp_ctl_el0    :0x0000000000000000
-    cntp_cval_el0   :0x0000000000000000
-    cntv_ctl_el0    :0x0000000000000000
-    cntv_cval_el0   :0x0000000000000000
-    cntkctl_el1 :0x0000000000000000
-    sp_el0  :0x0000000004010780
+    x0             = 0x000000002a4a0000
+    x1             = 0x0000000000000001
+    x2             = 0x0000000000000002
+    x3             = 0x0000000000000003
+    x4             = 0x0000000000000004
+    x5             = 0x0000000000000005
+    x6             = 0x0000000000000006
+    x7             = 0x0000000000000007
+    x8             = 0x0000000000000008
+    x9             = 0x0000000000000009
+    x10            = 0x0000000000000010
+    x11            = 0x0000000000000011
+    x12            = 0x0000000000000012
+    x13            = 0x0000000000000013
+    x14            = 0x0000000000000014
+    x15            = 0x0000000000000015
+    x16            = 0x0000000000000016
+    x17            = 0x0000000000000017
+    x18            = 0x0000000000000018
+    x19            = 0x0000000000000019
+    x20            = 0x0000000000000020
+    x21            = 0x0000000000000021
+    x22            = 0x0000000000000022
+    x23            = 0x0000000000000023
+    x24            = 0x0000000000000024
+    x25            = 0x0000000000000025
+    x26            = 0x0000000000000026
+    x27            = 0x0000000000000027
+    x28            = 0x0000000000000028
+    x29            = 0x0000000000000029
+    x30            = 0x0000000088000b78
+    scr_el3        = 0x000000000003073d
+    sctlr_el3      = 0x00000000b0cd183f
+    cptr_el3       = 0x0000000000000000
+    tcr_el3        = 0x000000008080351c
+    daif           = 0x00000000000002c0
+    mair_el3       = 0x00000000004404ff
+    spsr_el3       = 0x0000000060000349
+    elr_el3        = 0x0000000088000114
+    ttbr0_el3      = 0x0000000004018201
+    esr_el3        = 0x00000000be000000
+    far_el3        = 0x0000000000000000
+    spsr_el1       = 0x0000000000000000
+    elr_el1        = 0x0000000000000000
+    spsr_abt       = 0x0000000000000000
+    spsr_und       = 0x0000000000000000
+    spsr_irq       = 0x0000000000000000
+    spsr_fiq       = 0x0000000000000000
+    sctlr_el1      = 0x0000000030d00800
+    actlr_el1      = 0x0000000000000000
+    cpacr_el1      = 0x0000000000000000
+    csselr_el1     = 0x0000000000000000
+    sp_el1         = 0x0000000000000000
+    esr_el1        = 0x0000000000000000
+    ttbr0_el1      = 0x0000000000000000
+    ttbr1_el1      = 0x0000000000000000
+    mair_el1       = 0x0000000000000000
+    amair_el1      = 0x0000000000000000
+    tcr_el1        = 0x0000000000000000
+    tpidr_el1      = 0x0000000000000000
+    tpidr_el0      = 0x0000000000000000
+    tpidrro_el0    = 0x0000000000000000
+    par_el1        = 0x0000000000000000
+    mpidr_el1      = 0x0000000080000000
+    afsr0_el1      = 0x0000000000000000
+    afsr1_el1      = 0x0000000000000000
+    contextidr_el1 = 0x0000000000000000
+    vbar_el1       = 0x0000000000000000
+    cntp_ctl_el0   = 0x0000000000000000
+    cntp_cval_el0  = 0x0000000000000000
+    cntv_ctl_el0   = 0x0000000000000000
+    cntv_cval_el0  = 0x0000000000000000
+    cntkctl_el1    = 0x0000000000000000
+    sp_el0         = 0x0000000004014940
+    isr_el1        = 0x0000000000000000
+    dacr32_el2     = 0x0000000000000000
+    ifsr32_el2     = 0x0000000000000000
+    icc_hppir0_el1 = 0x00000000000003ff
+    icc_hppir1_el1 = 0x00000000000003ff
+    icc_ctlr_el3   = 0x0000000000080400
+    gicd_ispendr regs (Offsets 0x200-0x278)
+    Offset		    Value
+    0x200:	     0x0000000000000000
+    0x208:	     0x0000000000000000
+    0x210:	     0x0000000000000000
+    0x218:	     0x0000000000000000
+    0x220:	     0x0000000000000000
+    0x228:	     0x0000000000000000
+    0x230:	     0x0000000000000000
+    0x238:	     0x0000000000000000
+    0x240:	     0x0000000000000000
+    0x248:	     0x0000000000000000
+    0x250:	     0x0000000000000000
+    0x258:	     0x0000000000000000
+    0x260:	     0x0000000000000000
+    0x268:	     0x0000000000000000
+    0x270:	     0x0000000000000000
+    0x278:	     0x0000000000000000
 
 Guidelines for Reset Handlers
 -----------------------------
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/design_documents/cmake_framework.rst b/docs/design_documents/cmake_framework.rst
new file mode 100644
index 0000000..d88942e
--- /dev/null
+++ b/docs/design_documents/cmake_framework.rst
@@ -0,0 +1,165 @@
+TF-A CMake buildsystem
+======================
+
+:Author: Balint Dobszay
+:Organization: Arm Limited
+:Contact: Balint Dobszay <balint.dobszay@arm.com>
+:Status: Accepted
+
+.. contents:: Table of Contents
+
+Abstract
+--------
+This document presents a proposal for a new buildsystem for TF-A using CMake,
+and as part of this a reusable CMake framework for embedded projects. For a
+summary about the proposal, please see the `Phabricator wiki page
+<https://developer.trustedfirmware.org/w/tf_a/cmake-buildsystem-proposal/>`_. As
+mentioned there, the proposal consists of two phases. The subject of this
+document is the first phase only.
+
+Introduction
+------------
+The current Makefile based buildsystem of TF-A has become complicated and hard
+to maintain, there is a need for a new, more flexible solution. The proposal is
+to use CMake language for the new buildsystem. The main reasons of this decision
+are the following:
+
+* It is a well-established, mature tool, widely accepted by open-source
+  projects.
+* TF-M is already using CMake, reducing fragmentation for tf.org projects can be
+  beneficial.
+* CMake has various advantages over Make, e.g.:
+
+  * Host and target system agnostic project.
+  * CMake project is scalable, supports project modularization.
+  * Supports software integration.
+  * Out-of-the-box support for integration with several tools (e.g. project
+    generation for various IDEs, integration with cppcheck, etc).
+
+Of course there are drawbacks too:
+
+* Language is problematic (e.g. variable scope).
+* Not embedded approach.
+
+To overcome these and other problems, we need to create workarounds for some
+tasks, wrap CMake functions, etc. Since this functionality can be useful in
+other embedded projects too, it is beneficial to collect the new code into a
+reusable framework and store this in a separate repository. The following
+diagram provides an overview of the framework structure:
+
+|Framework structure|
+
+Main features
+-------------
+
+Structured configuration description
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+In the current Makefile system the build configuration description, validation,
+processing, and the target creation, source file description are mixed and
+spread across several files. One of the goals of the framework is to organize
+this.
+
+The framework provides a solution to describe the input build parameters, flags,
+macros, etc. in a structured way. It contains two utilities for this purpose:
+
+* Map: simple key-value pair implementation.
+* Group: collection of related maps.
+
+The related parameters shall be packed into a group (or "setting group"). The
+setting groups shall be defined and filled with content in config files.
+Currently the config files are created and edited manually, but later a
+configuration management tool (e.g. Kconfig) shall be used to generate these
+files. Therefore, the framework does not contain parameter validation and
+conflict checking, these shall be handled by the configuration tool.
+
+Target description
+^^^^^^^^^^^^^^^^^^
+The framework provides an API called STGT ('simple target') to describe the
+targets, i.e. what is the build output, what source files are used, what
+libraries are linked, etc. The API wraps the CMake target functions, and also
+extends the built-in functionality, it can use the setting groups described in
+the previous section. A group can be applied onto a target, i.e. a collection of
+macros, flags, etc. can be applied onto the given output executable/library.
+This provides a more granular way than the current Makefile system where most of
+these are global and applied onto each target.
+
+Compiler abstraction
+^^^^^^^^^^^^^^^^^^^^
+Apart from the built-in CMake usage of the compiler, there are some common tasks
+that CMake does not solve (e.g. preprocessing a file). For these tasks the
+framework uses wrapper functions instead of direct calls to the compiler. This
+way it is not tied to one specific compiler.
+
+External tools
+^^^^^^^^^^^^^^
+In the TF-A buildsystem some external tools are used, e.g. fiptool for image
+generation or dtc for device tree compilation. These tools have to be found
+and/or built by the framework. For this, the CMake find_package functionality is
+used, any other necessary tools can be added later.
+
+Workflow
+--------
+The following diagram demonstrates the development workflow using the framework:
+
+|Framework workflow|
+
+The process can be split into two main phases:
+
+In the provisioning phase, first we have to obtain the necessary resources, i.e.
+clone the code repository and other dependencies. Next we have to do the
+configuration, preferably using a config tool like KConfig.
+
+In the development phase first we run CMake, which will generate the buildsystem
+using the selected generator backend (currently only the Makefile generator is
+supported). After this we run the selected build tool which in turn calls the
+compiler, linker, packaging tool, etc. Finally we can run and debug the output
+executables.
+
+Usually during development only the steps in this second phase have to be
+repeated, while the provisioning phase needs to be done only once (or rarely).
+
+Example
+-------
+This is a short example for the basic framework usage.
+
+First, we create a setting group called *mem_conf* and fill it with several
+parameters. It is worth noting the difference between *CONFIG* and *DEFINE*
+types: the former is only a CMake domain option, the latter is only a C language
+macro.
+
+Next, we create a target called *fw1* and add the *mem_conf* setting group to
+it. This means that all source and header files used by the target will have all
+the parameters declared in the setting group. Then we set the target type to
+executable, and add some source files. Since the target has the parameters from
+the settings group, we can use it for conditionally adding source files. E.g.
+*dram_controller.c* will only be added if MEM_TYPE equals dram.
+
+.. code-block:: cmake
+
+   group_new(NAME mem_conf)
+   group_add(NAME mem_conf TYPE DEFINE KEY MEM_SIZE VAL 1024)
+   group_add(NAME mem_conf TYPE CONFIG DEFINE KEY MEM_TYPE VAL dram)
+   group_add(NAME mem_conf TYPE CFLAG KEY -Os)
+
+   stgt_create(NAME fw1)
+   stgt_add_setting(NAME fw1 GROUPS mem_conf)
+   stgt_set_target(NAME fw1 TYPE exe)
+
+   stgt_add_src(NAME fw1 SRC
+       ${CMAKE_SOURCE_DIR}/main.c
+   )
+
+   stgt_add_src_cond(NAME fw1 KEY MEM_TYPE VAL dram SRC
+       ${CMAKE_SOURCE_DIR}/dram_controller.c
+   )
+
+.. |Framework structure| image::
+   ../resources/diagrams/cmake_framework_structure.png
+   :width: 75 %
+
+.. |Framework workflow| image::
+   ../resources/diagrams/cmake_framework_workflow.png
+
+--------------
+
+*Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved.*
diff --git a/docs/design_documents/index.rst b/docs/design_documents/index.rst
new file mode 100644
index 0000000..187510a
--- /dev/null
+++ b/docs/design_documents/index.rst
@@ -0,0 +1,13 @@
+Design Documents
+================
+
+.. toctree::
+   :maxdepth: 1
+   :caption: Contents
+   :numbered:
+
+   cmake_framework
+
+--------------
+
+*Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.*
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index da5dcbf..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
diff --git a/docs/getting_started/porting-guide.rst b/docs/getting_started/porting-guide.rst
index e8357b3..d634d2e7 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/index.rst b/docs/index.rst
index 5088bfd..7413edd 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -14,6 +14,7 @@
    plat/index
    perf/index
    security_advisories/index
+   design_documents/index
    change-log
    change-log-upcoming
    glossary
@@ -82,7 +83,7 @@
 
 --------------
 
-*Copyright (c) 2013-2019, Arm Limited and Contributors. All rights reserved.*
+*Copyright (c) 2013-2020, Arm Limited and Contributors. All rights reserved.*
 
 .. _Armv7-A and Armv8-A: https://developer.arm.com/products/architecture/a-profile
 .. _Secure Monitor: http://www.arm.com/products/processors/technologies/trustzone/tee-smc.php
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/docs/resources/diagrams/cmake_framework_structure.png b/docs/resources/diagrams/cmake_framework_structure.png
new file mode 100644
index 0000000..6006f1c
--- /dev/null
+++ b/docs/resources/diagrams/cmake_framework_structure.png
Binary files differ
diff --git a/docs/resources/diagrams/cmake_framework_workflow.png b/docs/resources/diagrams/cmake_framework_workflow.png
new file mode 100644
index 0000000..7311529
--- /dev/null
+++ b/docs/resources/diagrams/cmake_framework_workflow.png
Binary files differ
diff --git a/drivers/arm/gic/v3/gicdv3_helpers.c b/drivers/arm/gic/v3/gicdv3_helpers.c
new file mode 100644
index 0000000..3f5ff45
--- /dev/null
+++ b/drivers/arm/gic/v3/gicdv3_helpers.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include "gicv3_private.h"
+
+/*******************************************************************************
+ * GIC Distributor interface accessors for bit operations
+ ******************************************************************************/
+
+/*
+ * Accessor to read the GIC Distributor IGRPMODR corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+uint32_t gicd_read_igrpmodr(uintptr_t base, unsigned int id)
+{
+	return GICD_READ(IGRPMODR, base, id);
+}
+
+/*
+ * Accessor to write the GIC Distributor IGRPMODR corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+void gicd_write_igrpmodr(uintptr_t base, unsigned int id, uint32_t val)
+{
+	GICD_WRITE(IGRPMODR, base, id, val);
+}
+
+/*
+ * Accessor to get the bit corresponding to interrupt ID
+ * in GIC Distributor IGRPMODR.
+ */
+unsigned int gicd_get_igrpmodr(uintptr_t base, unsigned int id)
+{
+	return GICD_GET_BIT(IGRPMODR, base, id);
+}
+
+/*
+ * Accessor to set the bit corresponding to interrupt ID
+ * in GIC Distributor IGRPMODR.
+ */
+void gicd_set_igrpmodr(uintptr_t base, unsigned int id)
+{
+	GICD_SET_BIT(IGRPMODR, base, id);
+}
+
+/*
+ * Accessor to clear the bit corresponding to interrupt ID
+ * in GIC Distributor IGRPMODR.
+ */
+void gicd_clr_igrpmodr(uintptr_t base, unsigned int id)
+{
+	GICD_CLR_BIT(IGRPMODR, base, id);
+}
diff --git a/drivers/arm/gic/v3/gicrv3_helpers.c b/drivers/arm/gic/v3/gicrv3_helpers.c
new file mode 100644
index 0000000..294acda
--- /dev/null
+++ b/drivers/arm/gic/v3/gicrv3_helpers.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2015-2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <common/interrupt_props.h>
+#include <drivers/arm/gicv3.h>
+#include "gicv3_private.h"
+
+/*******************************************************************************
+ * GIC Redistributor functions
+ * Note: The raw register values correspond to multiple interrupt IDs and
+ * the number of interrupt IDs involved depends on the register accessed.
+ ******************************************************************************/
+
+/*
+ * Accessor to read the GIC Redistributor IPRIORITYR corresponding to the
+ * interrupt `id`, 4 interrupts IDs at a time.
+ */
+unsigned int gicr_read_ipriorityr(uintptr_t base, unsigned int id)
+{
+	unsigned int n = id >> IPRIORITYR_SHIFT;
+
+	return mmio_read_32(base + GICR_IPRIORITYR + (n << 2));
+}
+
+/*
+ * Accessor to write the GIC Redistributor IPRIORITYR corresponding to the
+ * interrupt `id`, 4 interrupts IDs at a time.
+ */
+void gicr_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned int n = id >> IPRIORITYR_SHIFT;
+
+	mmio_write_32(base + GICR_IPRIORITYR + (n << 2), val);
+}
+
+/*
+ * Accessor to set the byte corresponding to interrupt ID
+ * in GIC Redistributor IPRIORITYR.
+ */
+void gicr_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri)
+{
+	GICR_WRITE_8(IPRIORITYR, base, id, pri & GIC_PRI_MASK);
+}
+
+/*
+ * Accessor to get the bit corresponding to interrupt ID
+ * from GIC Redistributor IGROUPR0.
+ */
+unsigned int gicr_get_igroupr0(uintptr_t base, unsigned int id)
+{
+	unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U);
+	unsigned int reg_val = gicr_read_igroupr0(base);
+
+	return (reg_val >> bit_num) & 0x1U;
+}
+
+/*
+ * Accessor to set the bit corresponding to interrupt ID
+ * in GIC Redistributor IGROUPR0.
+ */
+void gicr_set_igroupr0(uintptr_t base, unsigned int id)
+{
+	unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U);
+	unsigned int reg_val = gicr_read_igroupr0(base);
+
+	gicr_write_igroupr0(base, reg_val | (1U << bit_num));
+}
+
+/*
+ * Accessor to clear the bit corresponding to interrupt ID
+ * in GIC Redistributor IGROUPR0.
+ */
+void gicr_clr_igroupr0(uintptr_t base, unsigned int id)
+{
+	unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U);
+	unsigned int reg_val = gicr_read_igroupr0(base);
+
+	gicr_write_igroupr0(base, reg_val & ~(1U << bit_num));
+}
+
+/*
+ * Accessor to get the bit corresponding to interrupt ID
+ * from GIC Redistributor IGRPMODR0.
+ */
+unsigned int gicr_get_igrpmodr0(uintptr_t base, unsigned int id)
+{
+	unsigned int bit_num = id & ((1U << IGRPMODR_SHIFT) - 1U);
+	unsigned int reg_val = gicr_read_igrpmodr0(base);
+
+	return (reg_val >> bit_num) & 0x1U;
+}
+
+/*
+ * Accessor to set the bit corresponding to interrupt ID
+ * in GIC Redistributor IGRPMODR0.
+ */
+void gicr_set_igrpmodr0(uintptr_t base, unsigned int id)
+{
+	unsigned int bit_num = id & ((1U << IGRPMODR_SHIFT) - 1U);
+	unsigned int reg_val = gicr_read_igrpmodr0(base);
+
+	gicr_write_igrpmodr0(base, reg_val | (1U << bit_num));
+}
+
+/*
+ * Accessor to clear the bit corresponding to interrupt ID
+ * in GIC Redistributor IGRPMODR0.
+ */
+void gicr_clr_igrpmodr0(uintptr_t base, unsigned int id)
+{
+	unsigned int bit_num = id & ((1U << IGRPMODR_SHIFT) - 1U);
+	unsigned int reg_val = gicr_read_igrpmodr0(base);
+
+	gicr_write_igrpmodr0(base, reg_val & ~(1U << bit_num));
+}
+
+/*
+ * Accessor to set the bit corresponding to interrupt ID
+ * in GIC Redistributor ISENABLER0.
+ */
+void gicr_set_isenabler0(uintptr_t base, unsigned int id)
+{
+	unsigned int bit_num = id & ((1U << ISENABLER_SHIFT) - 1U);
+
+	gicr_write_isenabler0(base, (1U << bit_num));
+}
+
+/*
+ * Accessor to set the bit corresponding to interrupt ID in GIC Redistributor
+ * ICENABLER0.
+ */
+void gicr_set_icenabler0(uintptr_t base, unsigned int id)
+{
+	unsigned int bit_num = id & ((1U << ICENABLER_SHIFT) - 1U);
+
+	gicr_write_icenabler0(base, (1U << bit_num));
+}
+
+/*
+ * Accessor to set the bit corresponding to interrupt ID in GIC Redistributor
+ * ISACTIVER0.
+ */
+unsigned int gicr_get_isactiver0(uintptr_t base, unsigned int id)
+{
+	unsigned int bit_num = id & ((1U << ISACTIVER_SHIFT) - 1U);
+	unsigned int reg_val = gicr_read_isactiver0(base);
+
+	return (reg_val >> bit_num) & 0x1U;
+}
+
+/*
+ * Accessor to clear the bit corresponding to interrupt ID in GIC Redistributor
+ * ICPENDRR0.
+ */
+void gicr_set_icpendr0(uintptr_t base, unsigned int id)
+{
+	unsigned int bit_num = id & ((1U << ICPENDR_SHIFT) - 1U);
+
+	gicr_write_icpendr0(base, (1U << bit_num));
+}
+
+/*
+ * Accessor to set the bit corresponding to interrupt ID in GIC Redistributor
+ * ISPENDR0.
+ */
+void gicr_set_ispendr0(uintptr_t base, unsigned int id)
+{
+	unsigned int bit_num = id & ((1U << ISPENDR_SHIFT) - 1U);
+
+	gicr_write_ispendr0(base, (1U << bit_num));
+}
+
+/*
+ * Accessor to set the bit fields corresponding to interrupt ID
+ * in GIC Redistributor ICFGR0.
+ */
+void gicr_set_icfgr0(uintptr_t base, unsigned int id, unsigned int cfg)
+{
+	/* Interrupt configuration is a 2-bit field */
+	unsigned int bit_num = id & ((1U << ICFGR_SHIFT) - 1U);
+	unsigned int bit_shift = bit_num << 1U;
+
+	uint32_t reg_val = gicr_read_icfgr0(base);
+
+	/* Clear the field, and insert required configuration */
+	reg_val &= ~(GIC_CFG_MASK << bit_shift);
+	reg_val |= ((cfg & GIC_CFG_MASK) << bit_shift);
+
+	gicr_write_icfgr0(base, reg_val);
+}
+
+/*
+ * Accessor to set the bit fields corresponding to interrupt ID
+ * in GIC Redistributor ICFGR1.
+ */
+void gicr_set_icfgr1(uintptr_t base, unsigned int id, unsigned int cfg)
+{
+	/* Interrupt configuration is a 2-bit field */
+	unsigned int bit_num = id & ((1U << ICFGR_SHIFT) - 1U);
+	unsigned int bit_shift = bit_num << 1U;
+
+	uint32_t reg_val = gicr_read_icfgr1(base);
+
+	/* Clear the field, and insert required configuration */
+	reg_val &= ~(GIC_CFG_MASK << bit_shift);
+	reg_val |= ((cfg & GIC_CFG_MASK) << bit_shift);
+
+	gicr_write_icfgr1(base, reg_val);
+}
diff --git a/drivers/arm/gic/v3/gicv3_helpers.c b/drivers/arm/gic/v3/gicv3_helpers.c
index 710532e..d5aaf96 100644
--- a/drivers/arm/gic/v3/gicv3_helpers.c
+++ b/drivers/arm/gic/v3/gicv3_helpers.c
@@ -15,263 +15,6 @@
 #include "../common/gic_common_private.h"
 #include "gicv3_private.h"
 
-/*
- * Accessor to read the GIC Distributor IGRPMODR corresponding to the
- * interrupt `id`, 32 interrupt IDs at a time.
- */
-unsigned int gicd_read_igrpmodr(uintptr_t base, unsigned int id)
-{
-	unsigned int n = id >> IGRPMODR_SHIFT;
-
-	return mmio_read_32(base + GICD_IGRPMODR + (n << 2));
-}
-
-/*
- * Accessor to write the GIC Distributor IGRPMODR corresponding to the
- * interrupt `id`, 32 interrupt IDs at a time.
- */
-void gicd_write_igrpmodr(uintptr_t base, unsigned int id, unsigned int val)
-{
-	unsigned int n = id >> IGRPMODR_SHIFT;
-
-	mmio_write_32(base + GICD_IGRPMODR + (n << 2), val);
-}
-
-/*
- * Accessor to get the bit corresponding to interrupt ID
- * in GIC Distributor IGRPMODR.
- */
-unsigned int gicd_get_igrpmodr(uintptr_t base, unsigned int id)
-{
-	unsigned int bit_num = id & ((1U << IGRPMODR_SHIFT) - 1U);
-	unsigned int reg_val = gicd_read_igrpmodr(base, id);
-
-	return (reg_val >> bit_num) & 0x1U;
-}
-
-/*
- * Accessor to set the bit corresponding to interrupt ID
- * in GIC Distributor IGRPMODR.
- */
-void gicd_set_igrpmodr(uintptr_t base, unsigned int id)
-{
-	unsigned int bit_num = id & ((1U << IGRPMODR_SHIFT) - 1U);
-	unsigned int reg_val = gicd_read_igrpmodr(base, id);
-
-	gicd_write_igrpmodr(base, id, reg_val | (1U << bit_num));
-}
-
-/*
- * Accessor to clear the bit corresponding to interrupt ID
- * in GIC Distributor IGRPMODR.
- */
-void gicd_clr_igrpmodr(uintptr_t base, unsigned int id)
-{
-	unsigned int bit_num = id & ((1U << IGRPMODR_SHIFT) - 1U);
-	unsigned int reg_val = gicd_read_igrpmodr(base, id);
-
-	gicd_write_igrpmodr(base, id, reg_val & ~(1U << bit_num));
-}
-
-/*
- * Accessor to read the GIC Re-distributor IPRIORITYR corresponding to the
- * interrupt `id`, 4 interrupts IDs at a time.
- */
-unsigned int gicr_read_ipriorityr(uintptr_t base, unsigned int id)
-{
-	unsigned int n = id >> IPRIORITYR_SHIFT;
-
-	return mmio_read_32(base + GICR_IPRIORITYR + (n << 2));
-}
-
-/*
- * Accessor to write the GIC Re-distributor IPRIORITYR corresponding to the
- * interrupt `id`, 4 interrupts IDs at a time.
- */
-void gicr_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val)
-{
-	unsigned int n = id >> IPRIORITYR_SHIFT;
-
-	mmio_write_32(base + GICR_IPRIORITYR + (n << 2), val);
-}
-
-/*
- * Accessor to get the bit corresponding to interrupt ID
- * from GIC Re-distributor IGROUPR0.
- */
-unsigned int gicr_get_igroupr0(uintptr_t base, unsigned int id)
-{
-	unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U);
-	unsigned int reg_val = gicr_read_igroupr0(base);
-
-	return (reg_val >> bit_num) & 0x1U;
-}
-
-/*
- * Accessor to set the bit corresponding to interrupt ID
- * in GIC Re-distributor IGROUPR0.
- */
-void gicr_set_igroupr0(uintptr_t base, unsigned int id)
-{
-	unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U);
-	unsigned int reg_val = gicr_read_igroupr0(base);
-
-	gicr_write_igroupr0(base, reg_val | (1U << bit_num));
-}
-
-/*
- * Accessor to clear the bit corresponding to interrupt ID
- * in GIC Re-distributor IGROUPR0.
- */
-void gicr_clr_igroupr0(uintptr_t base, unsigned int id)
-{
-	unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U);
-	unsigned int reg_val = gicr_read_igroupr0(base);
-
-	gicr_write_igroupr0(base, reg_val & ~(1U << bit_num));
-}
-
-/*
- * Accessor to get the bit corresponding to interrupt ID
- * from GIC Re-distributor IGRPMODR0.
- */
-unsigned int gicr_get_igrpmodr0(uintptr_t base, unsigned int id)
-{
-	unsigned int bit_num = id & ((1U << IGRPMODR_SHIFT) - 1U);
-	unsigned int reg_val = gicr_read_igrpmodr0(base);
-
-	return (reg_val >> bit_num) & 0x1U;
-}
-
-/*
- * Accessor to set the bit corresponding to interrupt ID
- * in GIC Re-distributor IGRPMODR0.
- */
-void gicr_set_igrpmodr0(uintptr_t base, unsigned int id)
-{
-	unsigned int bit_num = id & ((1U << IGRPMODR_SHIFT) - 1U);
-	unsigned int reg_val = gicr_read_igrpmodr0(base);
-
-	gicr_write_igrpmodr0(base, reg_val | (1U << bit_num));
-}
-
-/*
- * Accessor to clear the bit corresponding to interrupt ID
- * in GIC Re-distributor IGRPMODR0.
- */
-void gicr_clr_igrpmodr0(uintptr_t base, unsigned int id)
-{
-	unsigned int bit_num = id & ((1U << IGRPMODR_SHIFT) - 1U);
-	unsigned int reg_val = gicr_read_igrpmodr0(base);
-
-	gicr_write_igrpmodr0(base, reg_val & ~(1U << bit_num));
-}
-
-/*
- * Accessor to set the bit corresponding to interrupt ID
- * in GIC Re-distributor ISENABLER0.
- */
-void gicr_set_isenabler0(uintptr_t base, unsigned int id)
-{
-	unsigned int bit_num = id & ((1U << ISENABLER_SHIFT) - 1U);
-
-	gicr_write_isenabler0(base, (1U << bit_num));
-}
-
-/*
- * Accessor to set the bit corresponding to interrupt ID in GIC Re-distributor
- * ICENABLER0.
- */
-void gicr_set_icenabler0(uintptr_t base, unsigned int id)
-{
-	unsigned int bit_num = id & ((1U << ICENABLER_SHIFT) - 1U);
-
-	gicr_write_icenabler0(base, (1U << bit_num));
-}
-
-/*
- * Accessor to set the bit corresponding to interrupt ID in GIC Re-distributor
- * ISACTIVER0.
- */
-unsigned int gicr_get_isactiver0(uintptr_t base, unsigned int id)
-{
-	unsigned int bit_num = id & ((1U << ISACTIVER_SHIFT) - 1U);
-	unsigned int reg_val = gicr_read_isactiver0(base);
-
-	return (reg_val >> bit_num) & 0x1U;
-}
-
-/*
- * Accessor to clear the bit corresponding to interrupt ID in GIC Re-distributor
- * ICPENDRR0.
- */
-void gicr_set_icpendr0(uintptr_t base, unsigned int id)
-{
-	unsigned int bit_num = id & ((1U << ICPENDR_SHIFT) - 1U);
-
-	gicr_write_icpendr0(base, (1U << bit_num));
-}
-
-/*
- * Accessor to set the bit corresponding to interrupt ID in GIC Re-distributor
- * ISPENDR0.
- */
-void gicr_set_ispendr0(uintptr_t base, unsigned int id)
-{
-	unsigned int bit_num = id & ((1U << ISPENDR_SHIFT) - 1U);
-
-	gicr_write_ispendr0(base, (1U << bit_num));
-}
-
-/*
- * Accessor to set the byte corresponding to interrupt ID
- * in GIC Re-distributor IPRIORITYR.
- */
-void gicr_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri)
-{
-	uint8_t val = pri & GIC_PRI_MASK;
-
-	mmio_write_8(base + GICR_IPRIORITYR + id, val);
-}
-
-/*
- * Accessor to set the bit fields corresponding to interrupt ID
- * in GIC Re-distributor ICFGR0.
- */
-void gicr_set_icfgr0(uintptr_t base, unsigned int id, unsigned int cfg)
-{
-	/* Interrupt configuration is a 2-bit field */
-	unsigned int bit_num = id & ((1U << ICFGR_SHIFT) - 1U);
-	unsigned int bit_shift = bit_num << 1U;
-
-	uint32_t reg_val = gicr_read_icfgr0(base);
-
-	/* Clear the field, and insert required configuration */
-	reg_val &= ~(GIC_CFG_MASK << bit_shift);
-	reg_val |= ((cfg & GIC_CFG_MASK) << bit_shift);
-
-	gicr_write_icfgr0(base, reg_val);
-}
-
-/*
- * Accessor to set the bit fields corresponding to interrupt ID
- * in GIC Re-distributor ICFGR1.
- */
-void gicr_set_icfgr1(uintptr_t base, unsigned int id, unsigned int cfg)
-{
-	/* Interrupt configuration is a 2-bit field */
-	unsigned int bit_num = id & ((1U << ICFGR_SHIFT) - 1U);
-	unsigned int bit_shift = bit_num << 1U;
-
-	uint32_t reg_val = gicr_read_icfgr1(base);
-
-	/* Clear the field, and insert required configuration */
-	reg_val &= ~(GIC_CFG_MASK << bit_shift);
-	reg_val |= ((cfg & GIC_CFG_MASK) << bit_shift);
-
-	gicr_write_icfgr1(base, reg_val);
-}
-
 /******************************************************************************
  * This function marks the core as awake in the re-distributor and
  * ensures that the interface is active.
@@ -292,7 +35,6 @@
 		;
 }
 
-
 /******************************************************************************
  * This function marks the core as asleep in the re-distributor and ensures
  * that the interface is quiescent.
diff --git a/drivers/arm/gic/v3/gicv3_private.h b/drivers/arm/gic/v3/gicv3_private.h
index 327a9a1..dae01cb 100644
--- a/drivers/arm/gic/v3/gicv3_private.h
+++ b/drivers/arm/gic/v3/gicv3_private.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -24,6 +24,100 @@
 #define RWP_TRUE		U(1)
 #define RWP_FALSE		U(0)
 
+/* Calculate GIC register bit number corresponding to its interrupt ID */
+#define	BIT_NUM(REG, id)	\
+	((id) & ((1U << REG##_SHIFT) - 1U))
+
+/* Calculate 8-bit GICD register offset corresponding to its interrupt ID */
+#define	GICD_OFFSET_8(REG, id)	\
+	GICD_##REG + (id)
+
+/* Calculate 32-bit GICD register offset corresponding to its interrupt ID */
+#define	GICD_OFFSET(REG, id)	\
+	GICD_##REG + (((id) >> REG##_SHIFT) << 2)
+
+/* Calculate 64-bit GICD register offset corresponding to its interrupt ID */
+#define	GICD_OFFSET_64(REG, id)	\
+	GICD_##REG + (((id) >> REG##_SHIFT) << 3)
+
+/* Read 32-bit GIC Distributor register corresponding to its interrupt ID */
+#define GICD_READ(REG, base, id)	\
+	mmio_read_32((base) + GICD_OFFSET(REG, (id)))
+
+/* Read 64-bit GIC Distributor register corresponding to its interrupt ID */
+#define GICD_READ_64(REG, base, id)	\
+	mmio_read_64((base) + GICD_OFFSET_64(REG, (id)))
+
+/* Write to 64-bit GIC Distributor register corresponding to its interrupt ID */
+#define GICD_WRITE_64(REG, base, id, val)	\
+	mmio_write_64((base) + GICD_OFFSET_64(REG, (id)), (val))
+
+/* Write to 32-bit GIC Distributor register corresponding to its interrupt ID */
+#define GICD_WRITE(REG, base, id, val)		\
+	mmio_write_32((base) + GICD_OFFSET(REG, (id)), (val))
+
+/* Write to 8-bit GIC Distributor register corresponding to its interrupt ID */
+#define GICD_WRITE_8(REG, base, id, val)	\
+	mmio_write_8((base) + GICD_OFFSET_8(REG, (id)), (val))
+
+/*
+ * Bit operations on GIC Distributor register corresponding
+ * to its interrupt ID
+ */
+/* Get bit in GIC Distributor register */
+#define GICD_GET_BIT(REG, base, id)				\
+	((mmio_read_32((base) + GICD_OFFSET(REG, (id))) >>	\
+		BIT_NUM(REG, (id))) & 1U)
+
+/* Set bit in GIC Distributor register */
+#define GICD_SET_BIT(REG, base, id)				\
+	mmio_setbits_32((base) + GICD_OFFSET(REG, (id)),	\
+		((uint32_t)1 << BIT_NUM(REG, (id))))
+
+/* Clear bit in GIC Distributor register */
+#define GICD_CLR_BIT(REG, base, id)				\
+	mmio_clrbits_32((base) + GICD_OFFSET(REG, (id)),	\
+		((uint32_t)1 << BIT_NUM(REG, (id))))
+
+/* Write bit in GIC Distributor register */
+#define	GICD_WRITE_BIT(REG, base, id)				\
+	mmio_write_32((base) + GICD_OFFSET(REG, (id)),	\
+		((uint32_t)1 << BIT_NUM(REG, (id))))
+
+/*
+ * Calculate GICv3 GICR register offset
+ */
+#define GICR_OFFSET(REG, id)	\
+	GICR_##REG + (((id) >> REG##_SHIFT) << 2)
+
+/* Write to GIC Redistributor register corresponding to its interrupt ID */
+#define GICR_WRITE_8(REG, base, id, val)			\
+	mmio_write_8((base) + GICR_##REG + (id), (val))
+
+/*
+ * Bit operations on GIC Redistributor register
+ * corresponding to its interrupt ID
+ */
+/* Get bit in GIC Redistributor register */
+#define GICR_GET_BIT(REG, base, id)				\
+	((mmio_read_32((base) + GICR_OFFSET(REG, (id))) >>	\
+		BIT_NUM(REG, (id))) & 1U)
+
+/* Write bit in GIC Redistributor register */
+#define	GICR_WRITE_BIT(REG, base, id)				\
+	mmio_write_32((base) + GICR_OFFSET(REG, (id)),	\
+		((uint32_t)1 << BIT_NUM(REG, (id))))
+
+/* Set bit in GIC Redistributor register */
+#define	GICR_SET_BIT(REG, base, id)				\
+	mmio_setbits_32((base) + GICR_OFFSET(REG, (id)),	\
+		((uint32_t)1 << BIT_NUM(REG, (id))))
+
+/* Clear bit in GIC Redistributor register */
+#define	GICR_CLR_BIT(REG, base, id)				\
+	mmio_clrbits_32((base) + GICR_OFFSET(REG, (id)),	\
+		((uint32_t)1 << BIT_NUM(REG, (id))))
+
 /*
  * Macro to convert an mpidr to a value suitable for programming into a
  * GICD_IROUTER. Bits[31:24] in the MPIDR are cleared as they are not relevant
@@ -63,9 +157,9 @@
  * Note: The raw register values correspond to multiple interrupt IDs and
  * the number of interrupt IDs involved depends on the register accessed.
  ******************************************************************************/
-unsigned int gicd_read_igrpmodr(uintptr_t base, unsigned int id);
+uint32_t gicd_read_igrpmodr(uintptr_t base, unsigned int id);
 unsigned int gicr_read_ipriorityr(uintptr_t base, unsigned int id);
-void gicd_write_igrpmodr(uintptr_t base, unsigned int id, unsigned int val);
+void gicd_write_igrpmodr(uintptr_t base, unsigned int id, uint32_t val);
 void gicr_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val);
 
 /*******************************************************************************
@@ -121,27 +215,27 @@
  */
 static inline void gicd_wait_for_pending_write(uintptr_t gicd_base)
 {
-	while ((gicd_read_ctlr(gicd_base) & GICD_CTLR_RWP_BIT) != 0U)
-		;
+	while ((gicd_read_ctlr(gicd_base) & GICD_CTLR_RWP_BIT) != 0U) {
+	}
 }
 
-static inline unsigned int gicd_read_pidr2(uintptr_t base)
+static inline uint32_t gicd_read_pidr2(uintptr_t base)
 {
 	return mmio_read_32(base + GICD_PIDR2_GICV3);
 }
 
-static inline unsigned long long gicd_read_irouter(uintptr_t base, unsigned int id)
+static inline uint64_t gicd_read_irouter(uintptr_t base, unsigned int id)
 {
 	assert(id >= MIN_SPI_ID);
-	return mmio_read_64(base + GICD_IROUTER + (id << 3));
+	return GICD_READ_64(IROUTER, base, id);
 }
 
 static inline void gicd_write_irouter(uintptr_t base,
 				      unsigned int id,
-				      unsigned long long affinity)
+				      uint64_t affinity)
 {
 	assert(id >= MIN_SPI_ID);
-	mmio_write_64(base + GICD_IROUTER + (id << 3), affinity);
+	GICD_WRITE_64(IROUTER, base, id, affinity);
 }
 
 static inline void gicd_clr_ctlr(uintptr_t base,
@@ -149,8 +243,9 @@
 				 unsigned int rwp)
 {
 	gicd_write_ctlr(base, gicd_read_ctlr(base) & ~bitmap);
-	if (rwp != 0U)
+	if (rwp != 0U) {
 		gicd_wait_for_pending_write(base);
+	}
 }
 
 static inline void gicd_set_ctlr(uintptr_t base,
@@ -158,8 +253,9 @@
 				 unsigned int rwp)
 {
 	gicd_write_ctlr(base, gicd_read_ctlr(base) | bitmap);
-	if (rwp != 0U)
+	if (rwp != 0U) {
 		gicd_wait_for_pending_write(base);
+	}
 }
 
 /*******************************************************************************
@@ -175,17 +271,17 @@
 	mmio_write_32(base + GICR_CTLR, val);
 }
 
-static inline unsigned long long gicr_read_typer(uintptr_t base)
+static inline uint64_t gicr_read_typer(uintptr_t base)
 {
 	return mmio_read_64(base + GICR_TYPER);
 }
 
-static inline unsigned int gicr_read_waker(uintptr_t base)
+static inline uint32_t gicr_read_waker(uintptr_t base)
 {
 	return mmio_read_32(base + GICR_WAKER);
 }
 
-static inline void gicr_write_waker(uintptr_t base, unsigned int val)
+static inline void gicr_write_waker(uintptr_t base, uint32_t val)
 {
 	mmio_write_32(base + GICR_WAKER, val);
 }
@@ -199,14 +295,14 @@
  */
 static inline void gicr_wait_for_pending_write(uintptr_t gicr_base)
 {
-	while ((gicr_read_ctlr(gicr_base) & GICR_CTLR_RWP_BIT) != 0U)
-		;
+	while ((gicr_read_ctlr(gicr_base) & GICR_CTLR_RWP_BIT) != 0U) {
+	}
 }
 
 static inline void gicr_wait_for_upstream_pending_write(uintptr_t gicr_base)
 {
-	while ((gicr_read_ctlr(gicr_base) & GICR_CTLR_UWP_BIT) != 0U)
-		;
+	while ((gicr_read_ctlr(gicr_base) & GICR_CTLR_UWP_BIT) != 0U) {
+	}
 }
 
 /* Private implementation of Distributor power control hooks */
@@ -214,7 +310,7 @@
 void arm_gicv3_distif_post_restore(unsigned int rdist_proc_num);
 
 /*******************************************************************************
- * GIC Re-distributor functions for accessing entire registers.
+ * GIC Redistributor functions for accessing entire registers.
  * Note: The raw register values correspond to multiple interrupt IDs and
  * the number of interrupt IDs involved depends on the register accessed.
  ******************************************************************************/
@@ -341,7 +437,7 @@
 	return mmio_read_32(base + GITS_CTLR);
 }
 
-static inline void gits_write_ctlr(uintptr_t base, unsigned int val)
+static inline void gits_write_ctlr(uintptr_t base, uint32_t val)
 {
 	mmio_write_32(base + GITS_CTLR, val);
 }
@@ -366,13 +462,15 @@
 	mmio_write_64(base + GITS_CWRITER, val);
 }
 
-static inline uint64_t gits_read_baser(uintptr_t base, unsigned int its_table_id)
+static inline uint64_t gits_read_baser(uintptr_t base,
+					unsigned int its_table_id)
 {
 	assert(its_table_id < 8U);
 	return mmio_read_64(base + GITS_BASER + (8U * its_table_id));
 }
 
-static inline void gits_write_baser(uintptr_t base, unsigned int its_table_id, uint64_t val)
+static inline void gits_write_baser(uintptr_t base, unsigned int its_table_id,
+					uint64_t val)
 {
 	assert(its_table_id < 8U);
 	mmio_write_64(base + GITS_BASER + (8U * its_table_id), val);
@@ -384,9 +482,8 @@
 static inline void gits_wait_for_quiescent_bit(uintptr_t gits_base)
 {
 	assert((gits_read_ctlr(gits_base) & GITS_CTLR_ENABLED_BIT) == 0U);
-	while ((gits_read_ctlr(gits_base) & GITS_CTLR_QUIESCENT_BIT) == 0U)
-		;
+	while ((gits_read_ctlr(gits_base) & GITS_CTLR_QUIESCENT_BIT) == 0U) {
+	}
 }
 
-
 #endif /* GICV3_PRIVATE_H */
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/dualroot/cot.c b/drivers/auth/dualroot/cot.c
new file mode 100644
index 0000000..eb0b020
--- /dev/null
+++ b/drivers/auth/dualroot/cot.c
@@ -0,0 +1,814 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+
+#include <platform_def.h>
+
+#include <drivers/auth/mbedtls/mbedtls_config.h>
+#include <drivers/auth/auth_mod.h>
+#include <tools_share/dualroot_oid.h>
+
+/*
+ * TODO: Remove dependency on mbedTLS. The chain of trust should be agnostic of
+ * the specific cryptographic library in use.
+*/
+/*
+ * Maximum key and hash sizes (in DER format).
+ *
+ * Both RSA and ECDSA keys may be used at the same time. In this case, the key
+ * buffers must be big enough to hold either. As RSA keys are bigger than ECDSA
+ * ones for all key sizes we support, they impose the minimum size of these
+ * buffers.
+ */
+#if TF_MBEDTLS_USE_RSA
+#if TF_MBEDTLS_KEY_SIZE == 1024
+#define PK_DER_LEN			162
+#elif TF_MBEDTLS_KEY_SIZE == 2048
+#define PK_DER_LEN			294
+#elif TF_MBEDTLS_KEY_SIZE == 3072
+#define PK_DER_LEN			422
+#elif TF_MBEDTLS_KEY_SIZE == 4096
+#define PK_DER_LEN			550
+#else
+#error "Invalid value for TF_MBEDTLS_KEY_SIZE"
+#endif
+#else /* Only using ECDSA keys. */
+#define PK_DER_LEN			91
+#endif
+
+#if TF_MBEDTLS_HASH_ALG_ID == TF_MBEDTLS_SHA256
+#define HASH_DER_LEN			51
+#elif TF_MBEDTLS_HASH_ALG_ID == TF_MBEDTLS_SHA384
+#define HASH_DER_LEN			67
+#elif TF_MBEDTLS_HASH_ALG_ID == TF_MBEDTLS_SHA512
+#define HASH_DER_LEN			83
+#else
+#error "Invalid value for TF_MBEDTLS_HASH_ALG_ID"
+#endif
+
+/*
+ * Allocate static buffers to store the authentication parameters extracted from
+ * the certificates.
+ */
+static unsigned char tb_fw_hash_buf[HASH_DER_LEN];
+static unsigned char tb_fw_config_hash_buf[HASH_DER_LEN];
+static unsigned char hw_config_hash_buf[HASH_DER_LEN];
+static unsigned char scp_fw_hash_buf[HASH_DER_LEN];
+static unsigned char nt_world_bl_hash_buf[HASH_DER_LEN];
+
+#ifdef IMAGE_BL2
+static unsigned char soc_fw_hash_buf[HASH_DER_LEN];
+static unsigned char tos_fw_hash_buf[HASH_DER_LEN];
+static unsigned char tos_fw_extra1_hash_buf[HASH_DER_LEN];
+static unsigned char tos_fw_extra2_hash_buf[HASH_DER_LEN];
+static unsigned char soc_fw_config_hash_buf[HASH_DER_LEN];
+static unsigned char tos_fw_config_hash_buf[HASH_DER_LEN];
+static unsigned char nt_fw_config_hash_buf[HASH_DER_LEN];
+
+static unsigned char trusted_world_pk_buf[PK_DER_LEN];
+static unsigned char content_pk_buf[PK_DER_LEN];
+#endif
+
+/*
+ * Parameter type descriptors.
+ */
+static auth_param_type_desc_t trusted_nv_ctr = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_NV_CTR, TRUSTED_FW_NVCOUNTER_OID);
+static auth_param_type_desc_t subject_pk = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_PUB_KEY, 0);
+static auth_param_type_desc_t sig = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_SIG, 0);
+static auth_param_type_desc_t sig_alg = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_SIG_ALG, 0);
+static auth_param_type_desc_t raw_data = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_RAW_DATA, 0);
+
+static auth_param_type_desc_t tb_fw_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, TRUSTED_BOOT_FW_HASH_OID);
+static auth_param_type_desc_t tb_fw_config_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, TRUSTED_BOOT_FW_CONFIG_HASH_OID);
+static auth_param_type_desc_t hw_config_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, HW_CONFIG_HASH_OID);
+#ifdef IMAGE_BL1
+static auth_param_type_desc_t scp_bl2u_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, SCP_FWU_CFG_HASH_OID);
+static auth_param_type_desc_t bl2u_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, AP_FWU_CFG_HASH_OID);
+static auth_param_type_desc_t ns_bl2u_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, FWU_HASH_OID);
+#endif /* IMAGE_BL1 */
+
+#ifdef IMAGE_BL2
+static auth_param_type_desc_t non_trusted_nv_ctr = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_NV_CTR, NON_TRUSTED_FW_NVCOUNTER_OID);
+
+static auth_param_type_desc_t trusted_world_pk = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_PUB_KEY, TRUSTED_WORLD_PK_OID);
+static auth_param_type_desc_t scp_fw_content_pk = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_PUB_KEY, SCP_FW_CONTENT_CERT_PK_OID);
+static auth_param_type_desc_t soc_fw_content_pk = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_PUB_KEY, SOC_FW_CONTENT_CERT_PK_OID);
+static auth_param_type_desc_t tos_fw_content_pk = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_PUB_KEY, TRUSTED_OS_FW_CONTENT_CERT_PK_OID);
+static auth_param_type_desc_t prot_pk = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_PUB_KEY, PROT_PK_OID);
+
+static auth_param_type_desc_t scp_fw_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, SCP_FW_HASH_OID);
+static auth_param_type_desc_t soc_fw_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, SOC_AP_FW_HASH_OID);
+static auth_param_type_desc_t soc_fw_config_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, SOC_FW_CONFIG_HASH_OID);
+static auth_param_type_desc_t tos_fw_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, TRUSTED_OS_FW_HASH_OID);
+static auth_param_type_desc_t tos_fw_config_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, TRUSTED_OS_FW_CONFIG_HASH_OID);
+static auth_param_type_desc_t tos_fw_extra1_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, TRUSTED_OS_FW_EXTRA1_HASH_OID);
+static auth_param_type_desc_t tos_fw_extra2_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, TRUSTED_OS_FW_EXTRA2_HASH_OID);
+static auth_param_type_desc_t nt_world_bl_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID);
+static auth_param_type_desc_t nt_fw_config_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, NON_TRUSTED_FW_CONFIG_HASH_OID);
+#endif /* IMAGE_BL2 */
+
+
+/* BL2 */
+static const auth_img_desc_t trusted_boot_fw_cert = {
+	.img_id = TRUSTED_BOOT_FW_CERT_ID,
+	.img_type = IMG_CERT,
+	.parent = NULL,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_SIG,
+			.param.sig = {
+				.pk = &subject_pk,
+				.sig = &sig,
+				.alg = &sig_alg,
+				.data = &raw_data
+			}
+		},
+		[1] = {
+			.type = AUTH_METHOD_NV_CTR,
+			.param.nv_ctr = {
+				.cert_nv_ctr = &trusted_nv_ctr,
+				.plat_nv_ctr = &trusted_nv_ctr
+			}
+		}
+	},
+	.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+		[0] = {
+			.type_desc = &tb_fw_hash,
+			.data = {
+				.ptr = (void *)tb_fw_hash_buf,
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		},
+		[1] = {
+			.type_desc = &tb_fw_config_hash,
+			.data = {
+				.ptr = (void *)tb_fw_config_hash_buf,
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		},
+		[2] = {
+			.type_desc = &hw_config_hash,
+			.data = {
+				.ptr = (void *)hw_config_hash_buf,
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		}
+	}
+};
+
+#ifdef IMAGE_BL1
+static const auth_img_desc_t bl2_image = {
+	.img_id = BL2_IMAGE_ID,
+	.img_type = IMG_RAW,
+	.parent = &trusted_boot_fw_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_HASH,
+			.param.hash = {
+				.data = &raw_data,
+				.hash = &tb_fw_hash
+			}
+		}
+	}
+};
+#endif /* IMAGE_BL1 */
+
+/* HW Config */
+static const auth_img_desc_t hw_config = {
+	.img_id = HW_CONFIG_ID,
+	.img_type = IMG_RAW,
+	.parent = &trusted_boot_fw_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_HASH,
+			.param.hash = {
+				.data = &raw_data,
+				.hash = &hw_config_hash
+			}
+		}
+	}
+};
+
+/* TB FW Config */
+#ifdef IMAGE_BL1
+static const auth_img_desc_t tb_fw_config = {
+	.img_id = TB_FW_CONFIG_ID,
+	.img_type = IMG_RAW,
+	.parent = &trusted_boot_fw_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_HASH,
+			.param.hash = {
+				.data = &raw_data,
+				.hash = &tb_fw_config_hash
+			}
+		}
+	}
+};
+#endif /* IMAGE_BL1 */
+
+#ifdef IMAGE_BL2
+/* Trusted key certificate */
+static const auth_img_desc_t trusted_key_cert = {
+	.img_id = TRUSTED_KEY_CERT_ID,
+	.img_type = IMG_CERT,
+	.parent = NULL,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_SIG,
+			.param.sig = {
+				.pk = &subject_pk,
+				.sig = &sig,
+				.alg = &sig_alg,
+				.data = &raw_data
+			}
+		},
+		[1] = {
+			.type = AUTH_METHOD_NV_CTR,
+			.param.nv_ctr = {
+				.cert_nv_ctr = &trusted_nv_ctr,
+				.plat_nv_ctr = &trusted_nv_ctr
+			}
+		}
+	},
+	.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+		[0] = {
+			.type_desc = &trusted_world_pk,
+			.data = {
+				.ptr = (void *)trusted_world_pk_buf,
+				.len = (unsigned int)PK_DER_LEN
+			}
+		},
+	}
+};
+
+/* SCP Firmware */
+static const auth_img_desc_t scp_fw_key_cert = {
+	.img_id = SCP_FW_KEY_CERT_ID,
+	.img_type = IMG_CERT,
+	.parent = &trusted_key_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_SIG,
+			.param.sig = {
+				.pk = &trusted_world_pk,
+				.sig = &sig,
+				.alg = &sig_alg,
+				.data = &raw_data
+			}
+		},
+		[1] = {
+			.type = AUTH_METHOD_NV_CTR,
+			.param.nv_ctr = {
+				.cert_nv_ctr = &trusted_nv_ctr,
+				.plat_nv_ctr = &trusted_nv_ctr
+			}
+		}
+	},
+	.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+		[0] = {
+			.type_desc = &scp_fw_content_pk,
+			.data = {
+				.ptr = (void *)content_pk_buf,
+				.len = (unsigned int)PK_DER_LEN
+			}
+		}
+	}
+};
+
+static const auth_img_desc_t scp_fw_content_cert = {
+	.img_id = SCP_FW_CONTENT_CERT_ID,
+	.img_type = IMG_CERT,
+	.parent = &scp_fw_key_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_SIG,
+			.param.sig = {
+				.pk = &scp_fw_content_pk,
+				.sig = &sig,
+				.alg = &sig_alg,
+				.data = &raw_data
+			}
+		},
+		[1] = {
+			.type = AUTH_METHOD_NV_CTR,
+			.param.nv_ctr = {
+				.cert_nv_ctr = &trusted_nv_ctr,
+				.plat_nv_ctr = &trusted_nv_ctr
+			}
+		}
+	},
+	.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+		[0] = {
+			.type_desc = &scp_fw_hash,
+			.data = {
+				.ptr = (void *)scp_fw_hash_buf,
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		}
+	}
+};
+
+static const auth_img_desc_t scp_bl2_image = {
+	.img_id = SCP_BL2_IMAGE_ID,
+	.img_type = IMG_RAW,
+	.parent = &scp_fw_content_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_HASH,
+			.param.hash = {
+				.data = &raw_data,
+				.hash = &scp_fw_hash
+			}
+		}
+	}
+};
+
+/* SoC Firmware */
+static const auth_img_desc_t soc_fw_key_cert = {
+	.img_id = SOC_FW_KEY_CERT_ID,
+	.img_type = IMG_CERT,
+	.parent = &trusted_key_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_SIG,
+			.param.sig = {
+				.pk = &trusted_world_pk,
+				.sig = &sig,
+				.alg = &sig_alg,
+				.data = &raw_data
+			}
+		},
+		[1] = {
+			.type = AUTH_METHOD_NV_CTR,
+			.param.nv_ctr = {
+				.cert_nv_ctr = &trusted_nv_ctr,
+				.plat_nv_ctr = &trusted_nv_ctr
+			}
+		}
+	},
+	.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+		[0] = {
+			.type_desc = &soc_fw_content_pk,
+			.data = {
+				.ptr = (void *)content_pk_buf,
+				.len = (unsigned int)PK_DER_LEN
+			}
+		}
+	}
+};
+
+static const auth_img_desc_t soc_fw_content_cert = {
+	.img_id = SOC_FW_CONTENT_CERT_ID,
+	.img_type = IMG_CERT,
+	.parent = &soc_fw_key_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_SIG,
+			.param.sig = {
+				.pk = &soc_fw_content_pk,
+				.sig = &sig,
+				.alg = &sig_alg,
+				.data = &raw_data
+			}
+		},
+		[1] = {
+			.type = AUTH_METHOD_NV_CTR,
+			.param.nv_ctr = {
+				.cert_nv_ctr = &trusted_nv_ctr,
+				.plat_nv_ctr = &trusted_nv_ctr
+			}
+		}
+	},
+	.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+		[0] = {
+			.type_desc = &soc_fw_hash,
+			.data = {
+				.ptr = (void *)soc_fw_hash_buf,
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		},
+		[1] = {
+			.type_desc = &soc_fw_config_hash,
+			.data = {
+				.ptr = (void *)soc_fw_config_hash_buf,
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		}
+	}
+};
+
+static const auth_img_desc_t bl31_image = {
+	.img_id = BL31_IMAGE_ID,
+	.img_type = IMG_RAW,
+	.parent = &soc_fw_content_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_HASH,
+			.param.hash = {
+				.data = &raw_data,
+				.hash = &soc_fw_hash
+			}
+		}
+	}
+};
+
+/* SOC FW Config */
+static const auth_img_desc_t soc_fw_config = {
+	.img_id = SOC_FW_CONFIG_ID,
+	.img_type = IMG_RAW,
+	.parent = &soc_fw_content_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_HASH,
+			.param.hash = {
+				.data = &raw_data,
+				.hash = &soc_fw_config_hash
+			}
+		}
+	}
+};
+
+/* Trusted OS Firmware */
+static const auth_img_desc_t trusted_os_fw_key_cert = {
+	.img_id = TRUSTED_OS_FW_KEY_CERT_ID,
+	.img_type = IMG_CERT,
+	.parent = &trusted_key_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_SIG,
+			.param.sig = {
+				.pk = &trusted_world_pk,
+				.sig = &sig,
+				.alg = &sig_alg,
+				.data = &raw_data
+			}
+		},
+		[1] = {
+			.type = AUTH_METHOD_NV_CTR,
+			.param.nv_ctr = {
+				.cert_nv_ctr = &trusted_nv_ctr,
+				.plat_nv_ctr = &trusted_nv_ctr
+			}
+		}
+	},
+	.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+		[0] = {
+			.type_desc = &tos_fw_content_pk,
+			.data = {
+				.ptr = (void *)content_pk_buf,
+				.len = (unsigned int)PK_DER_LEN
+			}
+		}
+	}
+};
+
+static const auth_img_desc_t trusted_os_fw_content_cert = {
+	.img_id = TRUSTED_OS_FW_CONTENT_CERT_ID,
+	.img_type = IMG_CERT,
+	.parent = &trusted_os_fw_key_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_SIG,
+			.param.sig = {
+				.pk = &tos_fw_content_pk,
+				.sig = &sig,
+				.alg = &sig_alg,
+				.data = &raw_data
+			}
+		},
+		[1] = {
+			.type = AUTH_METHOD_NV_CTR,
+			.param.nv_ctr = {
+				.cert_nv_ctr = &trusted_nv_ctr,
+				.plat_nv_ctr = &trusted_nv_ctr
+			}
+		}
+	},
+	.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+		[0] = {
+			.type_desc = &tos_fw_hash,
+			.data = {
+				.ptr = (void *)tos_fw_hash_buf,
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		},
+		[1] = {
+			.type_desc = &tos_fw_extra1_hash,
+			.data = {
+				.ptr = (void *)tos_fw_extra1_hash_buf,
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		},
+		[2] = {
+			.type_desc = &tos_fw_extra2_hash,
+			.data = {
+				.ptr = (void *)tos_fw_extra2_hash_buf,
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		},
+		[3] = {
+			.type_desc = &tos_fw_config_hash,
+			.data = {
+				.ptr = (void *)tos_fw_config_hash_buf,
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		}
+	}
+};
+
+static const auth_img_desc_t bl32_image = {
+	.img_id = BL32_IMAGE_ID,
+	.img_type = IMG_RAW,
+	.parent = &trusted_os_fw_content_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_HASH,
+			.param.hash = {
+				.data = &raw_data,
+				.hash = &tos_fw_hash
+			}
+		}
+	}
+};
+
+static const auth_img_desc_t bl32_extra1_image = {
+	.img_id = BL32_EXTRA1_IMAGE_ID,
+	.img_type = IMG_RAW,
+	.parent = &trusted_os_fw_content_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_HASH,
+			.param.hash = {
+				.data = &raw_data,
+				.hash = &tos_fw_extra1_hash
+			}
+		}
+	}
+};
+
+static const auth_img_desc_t bl32_extra2_image = {
+	.img_id = BL32_EXTRA2_IMAGE_ID,
+	.img_type = IMG_RAW,
+	.parent = &trusted_os_fw_content_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_HASH,
+			.param.hash = {
+				.data = &raw_data,
+				.hash = &tos_fw_extra2_hash
+			}
+		}
+	}
+};
+
+/* TOS FW Config */
+static const auth_img_desc_t tos_fw_config = {
+	.img_id = TOS_FW_CONFIG_ID,
+	.img_type = IMG_RAW,
+	.parent = &trusted_os_fw_content_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_HASH,
+			.param.hash = {
+				.data = &raw_data,
+				.hash = &tos_fw_config_hash
+			}
+		}
+	}
+};
+
+/* Non-Trusted Firmware */
+static const auth_img_desc_t non_trusted_fw_content_cert = {
+	.img_id = NON_TRUSTED_FW_CONTENT_CERT_ID,
+	.img_type = IMG_CERT,
+	.parent = NULL, /* Root certificate.  */
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_SIG,
+			.param.sig = {
+				.pk = &prot_pk,
+				.sig = &sig,
+				.alg = &sig_alg,
+				.data = &raw_data
+			}
+		},
+		[1] = {
+			.type = AUTH_METHOD_NV_CTR,
+			.param.nv_ctr = {
+				.cert_nv_ctr = &non_trusted_nv_ctr,
+				.plat_nv_ctr = &non_trusted_nv_ctr
+			}
+		}
+	},
+	.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+		[0] = {
+			.type_desc = &nt_world_bl_hash,
+			.data = {
+				.ptr = (void *)nt_world_bl_hash_buf,
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		},
+		[1] = {
+			.type_desc = &nt_fw_config_hash,
+			.data = {
+				.ptr = (void *)nt_fw_config_hash_buf,
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		}
+	}
+};
+
+static const auth_img_desc_t bl33_image = {
+	.img_id = BL33_IMAGE_ID,
+	.img_type = IMG_RAW,
+	.parent = &non_trusted_fw_content_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_HASH,
+			.param.hash = {
+				.data = &raw_data,
+				.hash = &nt_world_bl_hash
+			}
+		}
+	}
+};
+
+/* NT FW Config */
+static const auth_img_desc_t nt_fw_config = {
+	.img_id = NT_FW_CONFIG_ID,
+	.img_type = IMG_RAW,
+	.parent = &non_trusted_fw_content_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_HASH,
+			.param.hash = {
+				.data = &raw_data,
+				.hash = &nt_fw_config_hash
+			}
+		}
+	}
+};
+
+#else  /* IMAGE_BL2 */
+
+/* FWU auth descriptor */
+static const auth_img_desc_t fwu_cert = {
+	.img_id = FWU_CERT_ID,
+	.img_type = IMG_CERT,
+	.parent = NULL,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_SIG,
+			.param.sig = {
+				.pk = &subject_pk,
+				.sig = &sig,
+				.alg = &sig_alg,
+				.data = &raw_data
+			}
+		}
+	},
+	.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+		[0] = {
+			.type_desc = &scp_bl2u_hash,
+			.data = {
+				.ptr = (void *)scp_fw_hash_buf,
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		},
+		[1] = {
+			.type_desc = &bl2u_hash,
+			.data = {
+				.ptr = (void *)tb_fw_hash_buf,
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		},
+		[2] = {
+			.type_desc = &ns_bl2u_hash,
+			.data = {
+				.ptr = (void *)nt_world_bl_hash_buf,
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		}
+	}
+};
+
+/* SCP_BL2U */
+static const auth_img_desc_t scp_bl2u_image = {
+	.img_id = SCP_BL2U_IMAGE_ID,
+	.img_type = IMG_RAW,
+	.parent = &fwu_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_HASH,
+			.param.hash = {
+				.data = &raw_data,
+				.hash = &scp_bl2u_hash
+			}
+		}
+	}
+};
+
+/* BL2U */
+static const auth_img_desc_t bl2u_image = {
+	.img_id = BL2U_IMAGE_ID,
+	.img_type = IMG_RAW,
+	.parent = &fwu_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_HASH,
+			.param.hash = {
+				.data = &raw_data,
+				.hash = &bl2u_hash
+			}
+		}
+	}
+};
+
+/* NS_BL2U */
+static const auth_img_desc_t ns_bl2u_image = {
+	.img_id = NS_BL2U_IMAGE_ID,
+	.img_type = IMG_RAW,
+	.parent = &fwu_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_HASH,
+			.param.hash = {
+				.data = &raw_data,
+				.hash = &ns_bl2u_hash
+			}
+		}
+	}
+};
+#endif /* IMAGE_BL2 */
+
+/*
+ * Chain of trust definition
+ */
+#ifdef IMAGE_BL1
+static const auth_img_desc_t * const cot_desc[] = {
+	[TRUSTED_BOOT_FW_CERT_ID]		=	&trusted_boot_fw_cert,
+	[BL2_IMAGE_ID]				=	&bl2_image,
+	[HW_CONFIG_ID]				=	&hw_config,
+	[TB_FW_CONFIG_ID]			=	&tb_fw_config,
+	[FWU_CERT_ID]				=	&fwu_cert,
+	[SCP_BL2U_IMAGE_ID]			=	&scp_bl2u_image,
+	[BL2U_IMAGE_ID]				=	&bl2u_image,
+	[NS_BL2U_IMAGE_ID]			=	&ns_bl2u_image
+};
+#else /* IMAGE_BL2 */
+static const auth_img_desc_t * const cot_desc[] = {
+	[TRUSTED_BOOT_FW_CERT_ID]		=	&trusted_boot_fw_cert,
+	[HW_CONFIG_ID]				=	&hw_config,
+	[TRUSTED_KEY_CERT_ID]			=	&trusted_key_cert,
+	[SCP_FW_KEY_CERT_ID]			=	&scp_fw_key_cert,
+	[SCP_FW_CONTENT_CERT_ID]		=	&scp_fw_content_cert,
+	[SCP_BL2_IMAGE_ID]			=	&scp_bl2_image,
+	[SOC_FW_KEY_CERT_ID]			=	&soc_fw_key_cert,
+	[SOC_FW_CONTENT_CERT_ID]		=	&soc_fw_content_cert,
+	[BL31_IMAGE_ID]				=	&bl31_image,
+	[SOC_FW_CONFIG_ID]			=	&soc_fw_config,
+	[TRUSTED_OS_FW_KEY_CERT_ID]		=	&trusted_os_fw_key_cert,
+	[TRUSTED_OS_FW_CONTENT_CERT_ID]		=	&trusted_os_fw_content_cert,
+	[BL32_IMAGE_ID]				=	&bl32_image,
+	[BL32_EXTRA1_IMAGE_ID]			=	&bl32_extra1_image,
+	[BL32_EXTRA2_IMAGE_ID]			=	&bl32_extra2_image,
+	[TOS_FW_CONFIG_ID]			=	&tos_fw_config,
+	[NON_TRUSTED_FW_CONTENT_CERT_ID]	=	&non_trusted_fw_content_cert,
+	[BL33_IMAGE_ID]				=	&bl33_image,
+	[NT_FW_CONFIG_ID]			=	&nt_fw_config,
+};
+#endif
+
+/* Register the CoT in the authentication module */
+REGISTER_COT(cot_desc);
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);
+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, NULL);
+#endif
 #endif /* MEASURED_BOOT */
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/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/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 b0c2650..2b2c116 100644
--- a/include/arch/aarch64/arch.h
+++ b/include/arch/aarch64/arch.h
@@ -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.
  * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
@@ -452,6 +452,9 @@
 #define SPSR_M_AARCH64		U(0x0)
 #define SPSR_M_AARCH32		U(0x1)
 
+#define SPSR_EL_SHIFT		U(2)
+#define SPSR_EL_WIDTH		U(2)
+
 #define SPSR_SSBS_BIT_AARCH64	BIT_64(12)
 #define SPSR_SSBS_BIT_AARCH32	BIT_64(23)
 
@@ -557,6 +560,7 @@
 
 #define MODE_EL_SHIFT		U(0x2)
 #define MODE_EL_MASK		U(0x3)
+#define MODE_EL_WIDTH		U(0x2)
 #define MODE_EL3		U(0x3)
 #define MODE_EL2		U(0x2)
 #define MODE_EL1		U(0x1)
diff --git a/include/bl32/payloads/tlk.h b/include/bl32/payloads/tlk.h
index ce8e3e8..fe6f352 100644
--- a/include/bl32/payloads/tlk.h
+++ b/include/bl32/payloads/tlk.h
@@ -27,6 +27,7 @@
 #define TLK_SYSTEM_SUSPEND	TLK_TOS_YIELD_FID(0xE001)
 #define TLK_SYSTEM_RESUME	TLK_TOS_YIELD_FID(0xE002)
 #define TLK_SYSTEM_OFF		TLK_TOS_YIELD_FID(0xE003)
+#define TLK_IRQ_FIRED		TLK_TOS_YIELD_FID(0xE004)
 
 /*
  * SMC function IDs that TLK uses to signal various forms of completions
@@ -39,6 +40,7 @@
 #define TLK_SUSPEND_DONE	(0x32000005 | (ULL(1) << 31))
 #define TLK_RESUME_DONE		(0x32000006 | (ULL(1) << 31))
 #define TLK_SYSTEM_OFF_DONE	(0x32000007 | (ULL(1) << 31))
+#define TLK_IRQ_DONE		(0x32000008 | (ULL(1) << 31))
 
 /*
  * Trusted Application specific function IDs
diff --git a/include/common/bl_common.ld.h b/include/common/bl_common.ld.h
new file mode 100644
index 0000000..32c54b4
--- /dev/null
+++ b/include/common/bl_common.ld.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BL_COMMON_LD_H
+#define BL_COMMON_LD_H
+
+/*
+ * The xlat_table section is for full, aligned page tables (4K).
+ * Removing them from .bss avoids forcing 4K alignment on
+ * the .bss section. The tables are initialized to zero by the translation
+ * tables library.
+ */
+#define XLAT_TABLE_SECTION				\
+	xlat_table (NOLOAD) : {				\
+		*(xlat_table)				\
+	}
+
+#endif /* BL_COMMON_LD_H */
diff --git a/include/common/debug.h b/include/common/debug.h
index 245e698..9aef15b 100644
--- a/include/common/debug.h
+++ b/include/common/debug.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -91,6 +91,7 @@
 
 #if ENABLE_BACKTRACE
 void backtrace(const char *cookie);
+const char *get_el_str(unsigned int el);
 #else
 #define backtrace(x)
 #endif
diff --git a/include/drivers/arm/gicv3.h b/include/drivers/arm/gicv3.h
index c4f42d0..e6339bc 100644
--- a/include/drivers/arm/gicv3.h
+++ b/include/drivers/arm/gicv3.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
  */
@@ -32,7 +32,7 @@
 #define GICD_SETSPI_NSR		U(0x40)
 #define GICD_CLRSPI_NSR		U(0x48)
 #define GICD_SETSPI_SR		U(0x50)
-#define GICD_CLRSPI_SR		U(0x50)
+#define GICD_CLRSPI_SR		U(0x58)
 #define GICD_IGRPMODR		U(0xd00)
 /*
  * GICD_IROUTER<n> register is at 0x6000 + 8n, where n is the interrupt id and
@@ -79,7 +79,7 @@
 #define NUM_OF_DIST_REGS	30
 
 /*******************************************************************************
- * GICv3 Re-distributor interface registers & constants
+ * GICv3 Redistributor interface registers & constants
  ******************************************************************************/
 #define GICR_PCPUBASE_SHIFT	0x11
 #define GICR_SGIBASE_OFFSET	U(65536)	/* 64 KB */
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/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/export/common/tbbr/tbbr_img_def_exp.h b/include/export/common/tbbr/tbbr_img_def_exp.h
index 3602554..89dbc58 100644
--- a/include/export/common/tbbr/tbbr_img_def_exp.h
+++ b/include/export/common/tbbr/tbbr_img_def_exp.h
@@ -85,12 +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 */
 #if defined(SPD_spmd)
 #define MAX_SP_IDS			U(8)
-#define MAX_NUMBER_IDS			MAX_SP_IDS + U(30)
+#define MAX_NUMBER_IDS			MAX_SP_IDS + U(31)
 #else
-#define MAX_NUMBER_IDS			U(30)
+#define MAX_NUMBER_IDS			U(31)
 #endif
 
 #endif /* ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_TBBR_TBBR_IMG_DEF_EXP_H */
diff --git a/include/lib/xlat_tables/xlat_tables_v2.h b/include/lib/xlat_tables/xlat_tables_v2.h
index a80fab0..ab311f4 100644
--- a/include/lib/xlat_tables/xlat_tables_v2.h
+++ b/include/lib/xlat_tables/xlat_tables_v2.h
@@ -164,14 +164,20 @@
  *   Would typically be PLAT_VIRT_ADDR_SPACE_SIZE
  *   (resp. PLAT_PHY_ADDR_SPACE_SIZE) for the translation context describing the
  *   BL image currently executing.
+
+ * _base_table_section:
+ *   Specify the name of the section where the base translation tables have to
+ *   be placed by the linker.
  */
 #define REGISTER_XLAT_CONTEXT(_ctx_name, _mmap_count, _xlat_tables_count, \
-			_virt_addr_space_size, _phy_addr_space_size)	\
+			      _virt_addr_space_size, _phy_addr_space_size, \
+			      _base_table_section)			\
 	REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, (_mmap_count),	\
 					 (_xlat_tables_count),		\
 					 (_virt_addr_space_size),	\
 					 (_phy_addr_space_size),	\
-					 EL_REGIME_INVALID, "xlat_table")
+					 EL_REGIME_INVALID,		\
+					 "xlat_table", (_base_table_section))
 
 /*
  * Same as REGISTER_XLAT_CONTEXT plus the additional parameters:
@@ -191,7 +197,9 @@
 					 (_xlat_tables_count),		\
 					 (_virt_addr_space_size),	\
 					 (_phy_addr_space_size),	\
-					 (_xlat_regime), (_section_name))
+					 (_xlat_regime),		\
+					 (_section_name), ".bss"	\
+)
 
 /******************************************************************************
  * Generic translation table APIs.
diff --git a/include/lib/xlat_tables/xlat_tables_v2_helpers.h b/include/lib/xlat_tables/xlat_tables_v2_helpers.h
index c88fa4d..62f853d 100644
--- a/include/lib/xlat_tables/xlat_tables_v2_helpers.h
+++ b/include/lib/xlat_tables/xlat_tables_v2_helpers.h
@@ -24,6 +24,7 @@
 #include <platform_def.h>
 
 #include <lib/cassert.h>
+#include <lib/utils_def.h>
 #include <lib/xlat_tables/xlat_tables_arch.h>
 #include <lib/xlat_tables/xlat_tables_defs.h>
 
@@ -135,7 +136,8 @@
 
 #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)\
+			_phy_addr_space_size, _xlat_regime,		\
+			_table_section, _base_table_section)		\
 	CASSERT(CHECK_PHY_ADDR_SPACE_SIZE(_phy_addr_space_size),	\
 		assert_invalid_physical_addr_space_sizefor_##_ctx_name);\
 									\
@@ -143,52 +145,13 @@
 									\
 	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));				\
-									\
-	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)			\
-		.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);	\
+		__aligned(XLAT_TABLE_SIZE) __section(_table_section);	\
 									\
 	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");					\
+		__section(_base_table_section);				\
 									\
 	XLAT_ALLOC_DYNMAP_STRUCT(_ctx_name, _xlat_tables_count)		\
 									\
@@ -198,13 +161,13 @@
 		.mmap = _ctx_name##_mmap,				\
 		.mmap_num = (_mmap_count),				\
 		.tables = _ctx_name##_xlat_tables,			\
-		.tables_num = _xlat_tables_count,			\
+		.tables_num = ARRAY_SIZE(_ctx_name##_xlat_tables),	\
 		 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),\
+			ARRAY_SIZE(_ctx_name##_base_xlat_table),	\
 		.max_pa = 0U,						\
 		.max_va = 0U,						\
 		.base_level = GET_XLAT_TABLE_LEVEL_BASE(_virt_addr_space_size),\
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index ff1b979..babde41 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -268,7 +268,7 @@
  * Optional functions in ARM standard platforms
  */
 void plat_arm_override_gicr_frames(const uintptr_t *plat_gicr_frames);
-int arm_get_rotpk_info(void **key_ptr, unsigned int *key_len,
+int arm_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
 	unsigned int *flags);
 int arm_get_rotpk_info_regs(void **key_ptr, unsigned int *key_len,
 	unsigned int *flags);
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/tools_share/dualroot_oid.h b/include/tools_share/dualroot_oid.h
new file mode 100644
index 0000000..3e88a6d
--- /dev/null
+++ b/include/tools_share/dualroot_oid.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef DUALROOT_OID_H
+#define DUALROOT_OID_H
+
+/* Reuse the Object IDs defined by TBBR for certificate extensions. */
+#include "tbbr_oid.h"
+
+/*
+ * Platform root-of-trust public key.
+ * Arbitrary value that does not conflict with any of the TBBR reserved OIDs.
+ */
+#define PROT_PK_OID				"1.3.6.1.4.1.4128.2100.1102"
+
+#endif /* DUALROOT_OID_H */
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/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/xlat_tables_v2/xlat_tables_context.c b/lib/xlat_tables_v2/xlat_tables_context.c
index adca578..a1c974e 100644
--- a/lib/xlat_tables_v2/xlat_tables_context.c
+++ b/lib/xlat_tables_v2/xlat_tables_context.c
@@ -26,14 +26,15 @@
  * 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");
+#define BASE_XLAT_TABLE_SECTION		".rodata"
 #else
-REGISTER_XLAT_CONTEXT(tf, MAX_MMAP_REGIONS, MAX_XLAT_TABLES,
-		PLAT_VIRT_ADDR_SPACE_SIZE, PLAT_PHY_ADDR_SPACE_SIZE);
+#define BASE_XLAT_TABLE_SECTION		".bss"
 #endif
 
+REGISTER_XLAT_CONTEXT(tf, MAX_MMAP_REGIONS, MAX_XLAT_TABLES,
+		      PLAT_VIRT_ADDR_SPACE_SIZE, PLAT_PHY_ADDR_SPACE_SIZE,
+		      BASE_XLAT_TABLE_SECTION);
+
 void mmap_add_region(unsigned long long base_pa, uintptr_t base_va, size_t size,
 		     unsigned int attr)
 {
diff --git a/make_helpers/build_macros.mk b/make_helpers/build_macros.mk
index 032e42c..20a36fe 100644
--- a/make_helpers/build_macros.mk
+++ b/make_helpers/build_macros.mk
@@ -109,6 +109,22 @@
     ${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):
@@ -390,6 +421,7 @@
 #   $(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 9273469..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
 
diff --git a/make_helpers/tbbr/tbbr_tools.mk b/make_helpers/tbbr/tbbr_tools.mk
index 9c47cc7..f0adfe1 100644
--- a/make_helpers/tbbr/tbbr_tools.mk
+++ b/make_helpers/tbbr/tbbr_tools.mk
@@ -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
 #
@@ -23,6 +23,7 @@
 #   KEY_ALG
 #   KEY_SIZE
 #   ROT_KEY
+#   PROT_KEY
 #   TRUSTED_WORLD_KEY
 #   NON_TRUSTED_WORLD_KEY
 #   SCP_BL2_KEY
@@ -57,6 +58,7 @@
 $(if ${HASH_ALG},$(eval $(call CERT_ADD_CMD_OPT,${HASH_ALG},--hash-alg)))
 $(if ${ROT_KEY},$(eval $(call CERT_ADD_CMD_OPT,${ROT_KEY},--rot-key)))
 $(if ${ROT_KEY},$(eval $(call CERT_ADD_CMD_OPT,${ROT_KEY},--rot-key,FWU_)))
+$(if ${PROT_KEY},$(eval $(call CERT_ADD_CMD_OPT,${PROT_KEY},--prot-key)))
 $(if ${TRUSTED_WORLD_KEY},$(eval $(call CERT_ADD_CMD_OPT,${TRUSTED_WORLD_KEY},--trusted-world-key)))
 $(if ${NON_TRUSTED_WORLD_KEY},$(eval $(call CERT_ADD_CMD_OPT,${NON_TRUSTED_WORLD_KEY},--non-trusted-world-key)))
 
@@ -93,5 +95,7 @@
 ifneq (${BL33},)
     $(if ${BL33_KEY},$(eval $(call CERT_ADD_CMD_OPT,${BL33_KEY},--nt-fw-key)))
     $(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/nt_fw_content.crt,--nt-fw-cert))
+ifneq (${COT},dualroot)
     $(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/nt_fw_key.crt,--nt-fw-key-cert))
 endif
+endif
diff --git a/plat/arm/board/common/board_arm_trusted_boot.c b/plat/arm/board/common/board_arm_trusted_boot.c
index 3c19230..38cbba9 100644
--- a/plat/arm/board/common/board_arm_trusted_boot.c
+++ b/plat/arm/board/common/board_arm_trusted_boot.c
@@ -16,8 +16,12 @@
 #include <plat/common/common_def.h>
 #include <plat/common/platform.h>
 #include <platform_def.h>
-#include <tools_share/tbbr_oid.h>
 
+#if defined(ARM_COT_tbbr)
+#include <tools_share/tbbr_oid.h>
+#elif defined(ARM_COT_dualroot)
+#include <tools_share/dualroot_oid.h>
+#endif
 
 #if !ARM_CRYPTOCELL_INTEG
 #if !ARM_ROTPK_LOCATION_ID
@@ -108,10 +112,10 @@
 #endif
 
 /*
- * Wraper function for most Arm platforms to get ROTPK hash.
+ * Wrapper function for most Arm platforms to get ROTPK hash.
  */
-int arm_get_rotpk_info(void **key_ptr, unsigned int *key_len,
-			unsigned int *flags)
+static int get_rotpk_info(void **key_ptr, unsigned int *key_len,
+				unsigned int *flags)
 {
 #if ARM_CRYPTOCELL_INTEG
 	return arm_get_rotpk_info_cc(key_ptr, key_len, flags);
@@ -125,10 +129,44 @@
 #else
 	return 1;
 #endif
-
 #endif /* ARM_CRYPTOCELL_INTEG */
 }
 
+#if defined(ARM_COT_tbbr)
+
+int arm_get_rotpk_info(void *cookie __unused, void **key_ptr,
+		       unsigned int *key_len, unsigned int *flags)
+{
+	return get_rotpk_info(key_ptr, key_len, flags);
+}
+
+#elif defined(ARM_COT_dualroot)
+
+int arm_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+		       unsigned int *flags)
+{
+	/*
+	 * Return the right root of trust key hash based on the cookie value:
+	 *  - NULL means the primary ROTPK.
+	 *  - Otherwise, interpret cookie as the OID of the certificate
+	 *    extension containing the key.
+	 */
+	if (cookie == NULL) {
+		return get_rotpk_info(key_ptr, key_len, flags);
+	} else if (strcmp(cookie, PROT_PK_OID) == 0) {
+		extern unsigned char arm_protpk_hash[];
+		extern unsigned char arm_protpk_hash_end[];
+		*key_ptr = arm_protpk_hash;
+		*key_len = arm_protpk_hash_end - arm_protpk_hash;
+		*flags = ROTPK_IS_HASH;
+		return 0;
+	} else {
+		/* Invalid key ID. */
+		return 1;
+	}
+}
+#endif
+
 /*
  * Return the non-volatile counter value stored in the platform. The cookie
  * will contain the OID of the counter in the certificate.
diff --git a/plat/arm/board/common/board_common.mk b/plat/arm/board/common/board_common.mk
index 459156b..1885a60 100644
--- a/plat/arm/board/common/board_common.mk
+++ b/plat/arm/board/common/board_common.mk
@@ -68,4 +68,25 @@
 BL2_SOURCES		+=	plat/arm/board/common/board_arm_trusted_boot.c \
 				plat/arm/board/common/rotpk/arm_dev_rotpk.S
 
+# Allows platform code to provide implementation variants depending on the
+# selected chain of trust.
+$(eval $(call add_define,ARM_COT_${COT}))
+
+ifeq (${COT},dualroot)
+# Platform Root of Trust key files.
+ARM_PROT_KEY		:=	plat/arm/board/common/protpk/arm_protprivk_rsa.pem
+ARM_PROTPK_HASH		:=	plat/arm/board/common/protpk/arm_protpk_rsa_sha256.bin
+
+# Provide the private key to cert_create tool. It needs it to sign the images.
+PROT_KEY		:=	${ARM_PROT_KEY}
+
+$(eval $(call add_define_val,ARM_PROTPK_HASH,'"$(ARM_PROTPK_HASH)"'))
+
+BL1_SOURCES		+=	plat/arm/board/common/protpk/arm_dev_protpk.S
+BL2_SOURCES		+=	plat/arm/board/common/protpk/arm_dev_protpk.S
+
+$(BUILD_PLAT)/bl1/arm_dev_protpk.o: $(ARM_PROTPK_HASH)
+$(BUILD_PLAT)/bl2/arm_dev_protpk.o: $(ARM_PROTPK_HASH)
+endif
+
 endif
diff --git a/plat/arm/board/common/protpk/README b/plat/arm/board/common/protpk/README
new file mode 100644
index 0000000..3aca180
--- /dev/null
+++ b/plat/arm/board/common/protpk/README
@@ -0,0 +1,14 @@
+This directory contains some development keys to be used as the platform
+root-of-trust key.
+
+* arm_protprivk_rsa.pem is a 2K RSA private key in PEM format. It has been
+  generated using the openssl command line tool:
+
+  openssl genrsa 2048 > arm_protprivk_rsa.pem
+
+* arm_protpk_rsa_sha256.bin is the SHA-256 hash of the DER-encoded public key
+  associated with the above private key. It has been generated using the openssl
+  command line tool:
+
+  openssl rsa -in arm_protprivk_rsa.pem -pubout -outform DER | \
+    openssl dgst -sha256 -binary > arm_protpk_rsa_sha256.bin
diff --git a/plat/arm/board/common/protpk/arm_dev_protpk.S b/plat/arm/board/common/protpk/arm_dev_protpk.S
new file mode 100644
index 0000000..2688cbb
--- /dev/null
+++ b/plat/arm/board/common/protpk/arm_dev_protpk.S
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+	.global arm_protpk_hash
+	.global arm_protpk_hash_end
+
+	.section .rodata.arm_protpk_hash, "a"
+
+arm_protpk_hash:
+	/* DER header. */
+	.byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48
+	.byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
+	/* Key hash. */
+	.incbin ARM_PROTPK_HASH
+arm_protpk_hash_end:
diff --git a/plat/arm/board/common/protpk/arm_protpk_rsa_sha256.bin b/plat/arm/board/common/protpk/arm_protpk_rsa_sha256.bin
new file mode 100644
index 0000000..587da66
--- /dev/null
+++ b/plat/arm/board/common/protpk/arm_protpk_rsa_sha256.bin
@@ -0,0 +1 @@
+œó6{W*Â…`Ÿtíve×·§è£	€¾PžÆK{9
\ No newline at end of file
diff --git a/plat/arm/board/common/protpk/arm_protprivk_rsa.pem b/plat/arm/board/common/protpk/arm_protprivk_rsa.pem
new file mode 100644
index 0000000..eeaad9e
--- /dev/null
+++ b/plat/arm/board/common/protpk/arm_protprivk_rsa.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAzR0h/Z4Up17wfuRlYrUWseGDmlGKpl1PflGiYbyVmI7PwTTp
+y/T77EiljGp52suLWntHsc0lee50pW16DU2c5bVfmyofau3GjJ1Yqw5XFAahr6eM
+/0mkN8utrevvcRT9CP07D+zdhb/WlRUAnedqr/AUHU8BXS+Bxe8P0Z0Z7+DKjYZp
+thzXxsjKM02BFFzNwyVrlyBFDkW/53A4M+dpmuWDjAGCJH88W/u0LdmLcii11IzD
+/Ofz8Jxc/ZhqL+9FFK4qU+AJp8yXAnACSB46DlNltJrode0y5tmPhtS37ZF7EFb8
+UZWwZVgtuQyuyz9RYUS6jtiGuq6s8GlRwjTe7wIDAQABAoIBAFoWIYeyln+sQxR4
+W88umfkmgxaUGcFX2kIwuJEUst9+WeERzF24C62LeqphWYOvQlVLMAH3iC41fSXr
+H2AYZoC9WHBd386nAD1iHj+C3Nv+zaTIgjTdszKOUonAxjl0bm40SmyELAdCaoyv
+3MV9jm4Xk74LpR24b9bvWJNH3MxttH9hiYS+n0IzeTXDfO8GrNvHh92zx+jo8yMm
+Khhu+TDC9jA2pHpJcF/0EXxYMhwYiQT16nnHb+xMgS4JpalQhvVK01s4VYGHRoFk
+K6xh4TIS336LDLyalrGsPlfNfEdx+DimShDIfBUx9Jp3Pp11TUQUz4rhIHB9WdfG
+b6bV4wECgYEA+cgPS2TQ7XQ1RJq1S7OGePtBXvnoH226KwGS6Fey8838tLxbblim
+MU+EOYs3O66V6U2YpzmIakXo8030k8thY+jKbZl3l0m/hMuPOG66hfE5i7dYsiP4
+atok5wFiNeNYYjHMEayzk53MhG8EOh36msAO7ohKmenONUBA7pk6yTkCgYEA0jhk
+HPshwi+wKkx+JLTnuoEgx40tkRgSF2xBqKssMTasaQmX8qG+w9CEs0R8nZCI70Vc
+tXSFcidjdkHUVE2WsygIFuS1tbsAnpaxtn3E6rjie30X/Z280+TV0HjR0EMETmwl
+ShC5lZ0oP3LpEZfjbR5qs2kFW4MOxA7tjQVaMWcCgYEA5ZbVMBifzdMl70RA5i9C
+qEtSQAl3KgRCvar5rKSHsX+iC0Kiy9+iCusq/3WONEZ6NvMDIJpKYFyYDaOW7o5f
+m2TrRChu+1lnN5mfsGBfBCTBH0JMvZlAin6ussLb0eqBX+ijyY8zlLjTttsQSJcr
+tThZwTj3UVfOGbZQuL+RgEkCgYBXO3U3nXI9vUIx2zoBC1yZRNoQVGITMlTXiWGZ
+lyYoadKTZ5q44Sti4BUguounaoGYIEU/OtHhM70PJnPwY53kS/lHXrKUbbvtEwU9
+f+UFraC1s4wP/rOLjgq3jlsqO5T+4dt7Z4NLNUKtSYazeT6zWgrW1f6WIcUv0C38
+9bqegwKBgFCK3Oa5ibL5sPaPQ/1UfdeW4JVuu6A4JhHS7r+cVLsmcrvE1Qv7Wcvw
+B5aqXeqLu2dtIN8/f++3tzccs9LXKY/fh72D4TVjfrqOSSZoGTH9l4U5NXbqWM3I
+skkAYb2bMST/d1qSyYesgXVNAlaQHRh3vEz8x853nJ3v9OFj8/rW
+-----END RSA PRIVATE KEY-----
diff --git a/plat/arm/board/fvp/fvp_trusted_boot.c b/plat/arm/board/fvp/fvp_trusted_boot.c
index a09b80e..8825198a 100644
--- a/plat/arm/board/fvp/fvp_trusted_boot.c
+++ b/plat/arm/board/fvp/fvp_trusted_boot.c
@@ -30,7 +30,7 @@
 int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
 			unsigned int *flags)
 {
-	return arm_get_rotpk_info(key_ptr, key_len, flags);
+	return arm_get_rotpk_info(cookie, key_ptr, key_len, flags);
 }
 
 /*
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 05c11ce..c32b302 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -56,6 +56,8 @@
 FVP_GICV3_SOURCES	:=	drivers/arm/gic/common/gic_common.c	\
 				drivers/arm/gic/v3/gicv3_main.c		\
 				drivers/arm/gic/v3/gicv3_helpers.c	\
+				drivers/arm/gic/v3/gicdv3_helpers.c	\
+				drivers/arm/gic/v3/gicrv3_helpers.c	\
 				plat/common/plat_gicv3.c		\
 				plat/arm/common/arm_gicv3.c
 
diff --git a/plat/arm/board/n1sdp/platform.mk b/plat/arm/board/n1sdp/platform.mk
index 8816670..5856c9f 100644
--- a/plat/arm/board/n1sdp/platform.mk
+++ b/plat/arm/board/n1sdp/platform.mk
@@ -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
 #
@@ -18,6 +18,8 @@
 N1SDP_GIC_SOURCES	:=	drivers/arm/gic/common/gic_common.c	\
 				drivers/arm/gic/v3/gicv3_main.c		\
 				drivers/arm/gic/v3/gicv3_helpers.c	\
+				drivers/arm/gic/v3/gicdv3_helpers.c	\
+				drivers/arm/gic/v3/gicrv3_helpers.c	\
 				drivers/arm/gic/v3/gic600_multichip.c	\
 				plat/common/plat_gicv3.c		\
 				plat/arm/common/arm_gicv3.c		\
@@ -63,6 +65,9 @@
 # When building for systems with hardware-assisted coherency, there's no need to
 # use USE_COHERENT_MEM. Require that USE_COHERENT_MEM must be set to 0 too.
 USE_COHERENT_MEM			:=	0
+
+# Enable the flag since N1SDP has a system level cache
+NEOVERSE_N1_EXTERNAL_LLC		:=	1
 include plat/arm/common/arm_common.mk
 include plat/arm/css/common/css_common.mk
 include plat/arm/board/common/board_common.mk
diff --git a/plat/arm/board/rde1edge/rde1edge_trusted_boot.c b/plat/arm/board/rde1edge/rde1edge_trusted_boot.c
index c271f7f..4592b8f 100644
--- a/plat/arm/board/rde1edge/rde1edge_trusted_boot.c
+++ b/plat/arm/board/rde1edge/rde1edge_trusted_boot.c
@@ -22,5 +22,5 @@
 int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
 			unsigned int *flags)
 {
-	return arm_get_rotpk_info(key_ptr, key_len, flags);
+	return arm_get_rotpk_info(cookie, key_ptr, key_len, flags);
 }
diff --git a/plat/arm/board/rdn1edge/rdn1edge_trusted_boot.c b/plat/arm/board/rdn1edge/rdn1edge_trusted_boot.c
index c271f7f..4592b8f 100644
--- a/plat/arm/board/rdn1edge/rdn1edge_trusted_boot.c
+++ b/plat/arm/board/rdn1edge/rdn1edge_trusted_boot.c
@@ -22,5 +22,5 @@
 int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
 			unsigned int *flags)
 {
-	return arm_get_rotpk_info(key_ptr, key_len, flags);
+	return arm_get_rotpk_info(cookie, key_ptr, key_len, flags);
 }
diff --git a/plat/arm/board/sgi575/sgi575_trusted_boot.c b/plat/arm/board/sgi575/sgi575_trusted_boot.c
index c271f7f..4592b8f 100644
--- a/plat/arm/board/sgi575/sgi575_trusted_boot.c
+++ b/plat/arm/board/sgi575/sgi575_trusted_boot.c
@@ -22,5 +22,5 @@
 int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
 			unsigned int *flags)
 {
-	return arm_get_rotpk_info(key_ptr, key_len, flags);
+	return arm_get_rotpk_info(cookie, key_ptr, key_len, flags);
 }
diff --git a/plat/arm/board/sgm775/sgm775_trusted_boot.c b/plat/arm/board/sgm775/sgm775_trusted_boot.c
index c271f7f..4592b8f 100644
--- a/plat/arm/board/sgm775/sgm775_trusted_boot.c
+++ b/plat/arm/board/sgm775/sgm775_trusted_boot.c
@@ -22,5 +22,5 @@
 int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
 			unsigned int *flags)
 {
-	return arm_get_rotpk_info(key_ptr, key_len, flags);
+	return arm_get_rotpk_info(cookie, key_ptr, key_len, flags);
 }
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index 4fb85fb..65f6bf3 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -297,6 +297,8 @@
     # Include the selected chain of trust sources.
     ifeq (${COT},tbbr)
         AUTH_SOURCES	+=	drivers/auth/tbbr/tbbr_cot.c
+    else ifeq (${COT},dualroot)
+        AUTH_SOURCES	+=	drivers/auth/dualroot/cot.c
     else
         $(error Unknown chain of trust ${COT})
     endif
diff --git a/plat/arm/css/sgi/sgi-common.mk b/plat/arm/css/sgi/sgi-common.mk
index 40a7fd8..ea5a563 100644
--- a/plat/arm/css/sgi/sgi-common.mk
+++ b/plat/arm/css/sgi/sgi-common.mk
@@ -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
 #
@@ -25,6 +25,8 @@
 ENT_GIC_SOURCES		:=	drivers/arm/gic/common/gic_common.c	\
 				drivers/arm/gic/v3/gicv3_main.c		\
 				drivers/arm/gic/v3/gicv3_helpers.c	\
+				drivers/arm/gic/v3/gicdv3_helpers.c	\
+				drivers/arm/gic/v3/gicrv3_helpers.c	\
 				plat/common/plat_gicv3.c		\
 				plat/arm/common/arm_gicv3.c		\
 				drivers/arm/gic/v3/gic600.c
diff --git a/plat/arm/css/sgm/sgm-common.mk b/plat/arm/css/sgm/sgm-common.mk
index ac34450..49fc717 100644
--- a/plat/arm/css/sgm/sgm-common.mk
+++ b/plat/arm/css/sgm/sgm-common.mk
@@ -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
 #
@@ -25,6 +25,8 @@
 SGM_GIC_SOURCES		:=	drivers/arm/gic/common/gic_common.c	\
 				drivers/arm/gic/v3/gicv3_main.c		\
 				drivers/arm/gic/v3/gicv3_helpers.c	\
+				drivers/arm/gic/v3/gicdv3_helpers.c	\
+				drivers/arm/gic/v3/gicrv3_helpers.c	\
 				plat/common/plat_gicv3.c		\
 				plat/arm/common/arm_gicv3.c		\
 				drivers/arm/gic/v3/gic600.c		\
diff --git a/plat/common/aarch64/plat_common.c b/plat/common/aarch64/plat_common.c
index f8d3129..63871d9 100644
--- a/plat/common/aarch64/plat_common.c
+++ b/plat/common/aarch64/plat_common.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
  */
@@ -64,6 +64,18 @@
 }
 #endif
 
+#if !ENABLE_BACKTRACE
+static const char *get_el_str(unsigned int el)
+{
+	if (el == MODE_EL3) {
+		return "EL3";
+	} else if (el == MODE_EL2) {
+		return "EL2";
+	}
+	return "S-EL1";
+}
+#endif /* !ENABLE_BACKTRACE */
+
 /* RAS functions common to AArch64 ARM platforms */
 void plat_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie,
 		void *handle, uint64_t flags)
@@ -74,9 +86,17 @@
 	if (handled != 0)
 		return;
 #endif
+	unsigned int level = (unsigned int)GET_EL(read_spsr_el3());
 
-	ERROR("Unhandled External Abort received on 0x%lx at EL3!\n",
-			read_mpidr_el1());
-	ERROR(" exception reason=%u syndrome=0x%llx\n", ea_reason, syndrome);
+	ERROR("Unhandled External Abort received on 0x%lx from %s\n",
+		read_mpidr_el1(), get_el_str(level));
+	ERROR("exception reason=%u syndrome=0x%llx\n", ea_reason, syndrome);
+#if HANDLE_EA_EL3_FIRST
+	/* Skip backtrace for lower EL */
+	if (level != MODE_EL3) {
+		(void)console_flush();
+		do_panic();
+	}
+#endif
 	panic();
 }
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/hisilicon/hikey960/hikey960_bl31_setup.c b/plat/hisilicon/hikey960/hikey960_bl31_setup.c
index d3b4e4f..f5f8ffe 100644
--- a/plat/hisilicon/hikey960/hikey960_bl31_setup.c
+++ b/plat/hisilicon/hikey960/hikey960_bl31_setup.c
@@ -166,6 +166,7 @@
 
 	hikey960_edma_init();
 	hikey960_iomcu_dma_init();
+	hikey960_gpio_init();
 
 	hisi_ipc_init();
 }
diff --git a/plat/hisilicon/hikey960/hikey960_bl_common.c b/plat/hisilicon/hikey960/hikey960_bl_common.c
index 89adccb..3c4a164 100644
--- a/plat/hisilicon/hikey960/hikey960_bl_common.c
+++ b/plat/hisilicon/hikey960/hikey960_bl_common.c
@@ -466,6 +466,13 @@
 	pl061_gpio_register(GPIO19_BASE, 19);
 	pl061_gpio_register(GPIO20_BASE, 20);
 	pl061_gpio_register(GPIO21_BASE, 21);
+	pl061_gpio_register(GPIO22_BASE, 22);
+	pl061_gpio_register(GPIO23_BASE, 23);
+	pl061_gpio_register(GPIO24_BASE, 24);
+	pl061_gpio_register(GPIO25_BASE, 25);
+	pl061_gpio_register(GPIO26_BASE, 26);
+	pl061_gpio_register(GPIO27_BASE, 27);
+	pl061_gpio_register(GPIO28_BASE, 28);
 
 	/* PCIE_PERST_N output low */
 	gpio_set_direction(89, GPIO_DIR_OUT);
diff --git a/plat/hisilicon/hikey960/hikey960_pm.c b/plat/hisilicon/hikey960/hikey960_pm.c
index 9f96fc3..f836508 100644
--- a/plat/hisilicon/hikey960/hikey960_pm.c
+++ b/plat/hisilicon/hikey960/hikey960_pm.c
@@ -11,6 +11,7 @@
 #include <drivers/arm/cci.h>
 #include <drivers/arm/gicv2.h>
 #include <drivers/arm/pl011.h>
+#include <drivers/arm/pl061_gpio.h>
 #include <drivers/delay_timer.h>
 #include <lib/mmio.h>
 #include <lib/psci/psci.h>
@@ -116,6 +117,13 @@
 	}
 }
 
+static void __dead2 hikey960_system_off(void)
+{
+	gpio_set_direction(176, GPIO_DIR_OUT);
+	gpio_set_value(176, GPIO_LEVEL_LOW);
+	panic();
+}
+
 static void __dead2 hikey960_system_reset(void)
 {
 	dsb();
@@ -293,7 +301,7 @@
 	.pwr_domain_off			= hikey960_pwr_domain_off,
 	.pwr_domain_suspend		= hikey960_pwr_domain_suspend,
 	.pwr_domain_suspend_finish	= hikey960_pwr_domain_suspend_finish,
-	.system_off			= NULL,
+	.system_off			= hikey960_system_off,
 	.system_reset			= hikey960_system_reset,
 	.validate_power_state		= hikey960_validate_power_state,
 	.validate_ns_entrypoint		= hikey960_validate_ns_entrypoint,
diff --git a/plat/hisilicon/hikey960/include/hi3660.h b/plat/hisilicon/hikey960/include/hi3660.h
index 7cc1ee0..17b495f 100644
--- a/plat/hisilicon/hikey960/include/hi3660.h
+++ b/plat/hisilicon/hikey960/include/hi3660.h
@@ -260,6 +260,13 @@
 #define GPIO17_BASE			UL(0xE8A1C000)
 #define GPIO20_BASE			UL(0xE8A1F000)
 #define GPIO21_BASE			UL(0xE8A20000)
+#define GPIO22_BASE			UL(0xFFF0B000)
+#define GPIO23_BASE			UL(0xFFF0C000)
+#define GPIO24_BASE			UL(0xFFF0D000)
+#define GPIO25_BASE			UL(0xFFF0E000)
+#define GPIO26_BASE			UL(0xFFF0F000)
+#define GPIO27_BASE			UL(0xFFF10000)
+#define GPIO28_BASE			UL(0xFFF1D000)
 
 #define TZC_REG_BASE			0xE8A21000
 #define TZC_STAT0_REG			(TZC_REG_BASE + 0x800)
diff --git a/plat/hisilicon/hikey960/platform.mk b/plat/hisilicon/hikey960/platform.mk
index 6cb53c7..8ebabeb 100644
--- a/plat/hisilicon/hikey960/platform.mk
+++ b/plat/hisilicon/hikey960/platform.mk
@@ -19,7 +19,7 @@
 
 CRASH_CONSOLE_BASE		:=	PL011_UART6_BASE
 COLD_BOOT_SINGLE_CPU		:=	1
-PLAT_PL061_MAX_GPIOS		:=	176
+PLAT_PL061_MAX_GPIOS		:=	232
 PROGRAMMABLE_RESET_ADDRESS	:=	1
 ENABLE_SVE_FOR_NS		:=	0
 PLAT_PARTITION_BLOCK_SIZE	:=	4096
@@ -95,12 +95,15 @@
 endif
 
 BL31_SOURCES		+=	drivers/arm/cci/cci.c			\
+				drivers/arm/pl061/pl061_gpio.c		\
+				drivers/gpio/gpio.c			\
 				lib/cpus/aarch64/cortex_a53.S           \
 				lib/cpus/aarch64/cortex_a72.S		\
 				lib/cpus/aarch64/cortex_a73.S		\
 				plat/common/plat_psci_common.c  \
 				plat/hisilicon/hikey960/aarch64/hikey960_helpers.S \
 				plat/hisilicon/hikey960/hikey960_bl31_setup.c \
+				plat/hisilicon/hikey960/hikey960_bl_common.c \
 				plat/hisilicon/hikey960/hikey960_pm.c	\
 				plat/hisilicon/hikey960/hikey960_topology.c \
 				plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.c \
diff --git a/plat/imx/imx8m/imx8mm/include/platform_def.h b/plat/imx/imx8m/imx8mm/include/platform_def.h
index 56caab7..f25ceb0 100644
--- a/plat/imx/imx8m/imx8mm/include/platform_def.h
+++ b/plat/imx/imx8m/imx8mm/include/platform_def.h
@@ -47,7 +47,6 @@
 
 #define HAB_RVT_BASE			U(0x00000900) /* HAB_RVT for i.MX8MM */
 
-#define IMX_BOOT_UART_BASE		U(0x30890000)
 #define IMX_BOOT_UART_CLK_IN_HZ		24000000 /* Select 24MHz oscillator */
 
 #define PLAT_CRASH_UART_BASE		IMX_BOOT_UART_BASE
diff --git a/plat/imx/imx8m/imx8mm/platform.mk b/plat/imx/imx8m/imx8mm/platform.mk
index c0cb6c2..5fa3003 100644
--- a/plat/imx/imx8m/imx8mm/platform.mk
+++ b/plat/imx/imx8m/imx8mm/platform.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -9,6 +9,8 @@
 				-Iplat/imx/imx8m/imx8mm/include
 
 IMX_GIC_SOURCES		:=	drivers/arm/gic/v3/gicv3_helpers.c	\
+				drivers/arm/gic/v3/gicdv3_helpers.c	\
+				drivers/arm/gic/v3/gicrv3_helpers.c	\
 				drivers/arm/gic/v3/arm_gicv3_common.c   \
 				drivers/arm/gic/v3/gic500.c             \
 				drivers/arm/gic/v3/gicv3_main.c		\
@@ -51,3 +53,6 @@
 
 BL32_SIZE		?=	0x2000000
 $(eval $(call add_define,BL32_SIZE))
+
+IMX_BOOT_UART_BASE	?=	0x30890000
+$(eval $(call add_define,IMX_BOOT_UART_BASE))
diff --git a/plat/imx/imx8m/imx8mq/platform.mk b/plat/imx/imx8m/imx8mq/platform.mk
index 80ebe40..e419f05 100644
--- a/plat/imx/imx8m/imx8mq/platform.mk
+++ b/plat/imx/imx8m/imx8mq/platform.mk
@@ -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
 #
@@ -9,6 +9,8 @@
 				-Iplat/imx/imx8m/imx8mq/include
 
 IMX_GIC_SOURCES		:=	drivers/arm/gic/v3/gicv3_helpers.c	\
+				drivers/arm/gic/v3/gicdv3_helpers.c	\
+				drivers/arm/gic/v3/gicrv3_helpers.c	\
 				drivers/arm/gic/v3/arm_gicv3_common.c   \
 				drivers/arm/gic/v3/gic500.c             \
 				drivers/arm/gic/v3/gicv3_main.c		\
diff --git a/plat/imx/imx8qm/platform.mk b/plat/imx/imx8qm/platform.mk
index 3a772e5..5ba9c3f 100644
--- a/plat/imx/imx8qm/platform.mk
+++ b/plat/imx/imx8qm/platform.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -8,6 +8,8 @@
 				-Iplat/imx/common/include		\
 
 IMX_GIC_SOURCES	:=		drivers/arm/gic/v3/gicv3_helpers.c	\
+				drivers/arm/gic/v3/gicdv3_helpers.c	\
+				drivers/arm/gic/v3/gicrv3_helpers.c	\
 				drivers/arm/gic/v3/arm_gicv3_common.c   \
 				drivers/arm/gic/v3/gic500.c             \
 				drivers/arm/gic/v3/gicv3_main.c		\
diff --git a/plat/imx/imx8qx/platform.mk b/plat/imx/imx8qx/platform.mk
index d5629d1..5e8ba06 100644
--- a/plat/imx/imx8qx/platform.mk
+++ b/plat/imx/imx8qx/platform.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -8,6 +8,8 @@
 				-Iplat/imx/common/include		\
 
 IMX_GIC_SOURCES	:=		drivers/arm/gic/v3/gicv3_helpers.c	\
+				drivers/arm/gic/v3/gicdv3_helpers.c	\
+				drivers/arm/gic/v3/gicrv3_helpers.c	\
 				drivers/arm/gic/v3/arm_gicv3_common.c	\
 				drivers/arm/gic/v3/gic500.c		\
 				drivers/arm/gic/v3/gicv3_main.c		\
diff --git a/plat/marvell/a3700/common/a3700_common.mk b/plat/marvell/a3700/common/a3700_common.mk
index 1e27567..fd2b7ed 100644
--- a/plat/marvell/a3700/common/a3700_common.mk
+++ b/plat/marvell/a3700/common/a3700_common.mk
@@ -81,6 +81,8 @@
 MARVELL_GIC_SOURCES	:=	drivers/arm/gic/common/gic_common.c	\
 				drivers/arm/gic/v3/gicv3_main.c		\
 				drivers/arm/gic/v3/gicv3_helpers.c	\
+				drivers/arm/gic/v3/gicdv3_helpers.c	\
+				drivers/arm/gic/v3/gicrv3_helpers.c	\
 				drivers/arm/gic/v3/arm_gicv3_common.c	\
 				plat/common/plat_gicv3.c		\
 				drivers/arm/gic/v3/gic500.c
diff --git a/plat/mediatek/mt6795/bl31.ld.S b/plat/mediatek/mt6795/bl31.ld.S
index cf68b71..0fd3866 100644
--- a/plat/mediatek/mt6795/bl31.ld.S
+++ b/plat/mediatek/mt6795/bl31.ld.S
@@ -1,9 +1,10 @@
 /*
- * 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
  */
 
+#include <common/bl_common.ld.h>
 #include <lib/xlat_tables/xlat_tables_defs.h>
 #include <platform_def.h>
 
@@ -131,15 +132,7 @@
 
     ASSERT(. <= BL31_LIMIT, "BL3-1 image has exceeded its limit.")
 
-    /*
-     * The xlat_table section is for full, aligned page tables (4K).
-     * Removing them from .bss avoids forcing 4K alignment on
-     * the .bss section. The tables are initialized to zero by the translation
-     * tables library.
-     */
-    xlat_table (NOLOAD) : {
-        *(xlat_table)
-    } >RAM2
+    XLAT_TABLE_SECTION >RAM2
 
 #if USE_COHERENT_MEM
     /*
diff --git a/plat/mediatek/mt8183/platform.mk b/plat/mediatek/mt8183/platform.mk
index 597e18b..59ffe5d 100644
--- a/plat/mediatek/mt8183/platform.mk
+++ b/plat/mediatek/mt8183/platform.mk
@@ -31,6 +31,8 @@
                    drivers/arm/gic/common/gic_common.c                   \
                    drivers/arm/gic/v3/arm_gicv3_common.c                 \
                    drivers/arm/gic/v3/gicv3_helpers.c                    \
+                   drivers/arm/gic/v3/gicdv3_helpers.c			 \
+                   drivers/arm/gic/v3/gicrv3_helpers.c			 \
                    drivers/arm/gic/v3/gic500.c                           \
                    drivers/arm/gic/v3/gicv3_main.c                       \
                    drivers/delay_timer/delay_timer.c                     \
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/memctrl/memctrl_v2.c b/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c
index c2ef981..a53f660 100644
--- a/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c
+++ b/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c
@@ -21,6 +21,7 @@
 #include <smmu.h>
 #include <tegra_def.h>
 #include <tegra_platform.h>
+#include <tegra_private.h>
 
 /* Video Memory base and size (live values) */
 static uint64_t video_mem_base;
@@ -223,6 +224,58 @@
 	mce_update_gsc_tzram();
 }
 
+/*
+ * Save MC settings before "System Suspend" to TZDRAM
+ */
+void tegra_mc_save_context(uint64_t mc_ctx_addr)
+{
+	const tegra_mc_settings_t *plat_mc_settings = tegra_get_mc_settings();
+	uint32_t i, num_entries = 0;
+	mc_regs_t *mc_ctx_regs;
+	const plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params();
+	uint64_t tzdram_base = params_from_bl2->tzdram_base;
+	uint64_t tzdram_end = tzdram_base + params_from_bl2->tzdram_size;
+
+	assert((mc_ctx_addr >= tzdram_base) && (mc_ctx_addr <= tzdram_end));
+
+	/* get MC context table */
+	mc_ctx_regs = plat_mc_settings->get_mc_system_suspend_ctx();
+	assert(mc_ctx_regs != NULL);
+
+	/*
+	 * mc_ctx_regs[0].val contains the size of the context table minus
+	 * the last entry. Sanity check the table size before we start with
+	 * the context save operation.
+	 */
+	while (mc_ctx_regs[num_entries].reg != 0xFFFFFFFFU) {
+		num_entries++;
+	}
+
+	/* panic if the sizes do not match */
+	if (num_entries != mc_ctx_regs[0].val) {
+		ERROR("MC context size mismatch!");
+		panic();
+	}
+
+	/* save MC register values */
+	for (i = 1U; i < num_entries; i++) {
+		mc_ctx_regs[i].val = mmio_read_32(mc_ctx_regs[i].reg);
+	}
+
+	/* increment by 1 to take care of the last entry */
+	num_entries++;
+
+	/* Save MC config settings */
+	(void)memcpy((void *)mc_ctx_addr, mc_ctx_regs,
+			sizeof(mc_regs_t) * num_entries);
+
+	/* save the MC table address */
+	mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_MC_TABLE_ADDR_LO,
+		(uint32_t)mc_ctx_addr);
+	mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_MC_TABLE_ADDR_HI,
+		(uint32_t)(mc_ctx_addr >> 32));
+}
+
 static void tegra_lock_videomem_nonoverlap(uint64_t phys_base,
 					   uint64_t size_in_bytes)
 {
diff --git a/plat/nvidia/tegra/common/drivers/smmu/smmu.c b/plat/nvidia/tegra/common/drivers/smmu/smmu.c
index 8c1b899..a4a4354 100644
--- a/plat/nvidia/tegra/common/drivers/smmu/smmu.c
+++ b/plat/nvidia/tegra/common/drivers/smmu/smmu.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -17,121 +18,8 @@
 
 extern void memcpy16(void *dest, const void *src, unsigned int length);
 
-/* SMMU IDs currently supported by the driver */
-enum {
-	TEGRA_SMMU0 = 0U,
-	TEGRA_SMMU1,
-	TEGRA_SMMU2
-};
-
-static uint32_t tegra_smmu_read_32(uint32_t smmu_id, uint32_t off)
-{
-	uint32_t ret = 0U;
-
-#if defined(TEGRA_SMMU0_BASE)
-	if (smmu_id == TEGRA_SMMU0) {
-		ret = mmio_read_32(TEGRA_SMMU0_BASE + (uint64_t)off);
-	}
-#endif
-
-#if defined(TEGRA_SMMU1_BASE)
-	if (smmu_id == TEGRA_SMMU1) {
-		ret = mmio_read_32(TEGRA_SMMU1_BASE + (uint64_t)off);
-	}
-#endif
-
-#if defined(TEGRA_SMMU2_BASE)
-	if (smmu_id == TEGRA_SMMU2) {
-		ret = mmio_read_32(TEGRA_SMMU2_BASE + (uint64_t)off);
-	}
-#endif
-
-	return ret;
-}
-
-static void tegra_smmu_write_32(uint32_t smmu_id,
-			uint32_t off, uint32_t val)
-{
-#if defined(TEGRA_SMMU0_BASE)
-	if (smmu_id == TEGRA_SMMU0) {
-		mmio_write_32(TEGRA_SMMU0_BASE + (uint64_t)off, val);
-	}
-#endif
-
-#if defined(TEGRA_SMMU1_BASE)
-	if (smmu_id == TEGRA_SMMU1) {
-		mmio_write_32(TEGRA_SMMU1_BASE + (uint64_t)off, val);
-	}
-#endif
-
-#if defined(TEGRA_SMMU2_BASE)
-	if (smmu_id == TEGRA_SMMU2) {
-		mmio_write_32(TEGRA_SMMU2_BASE + (uint64_t)off, val);
-	}
-#endif
-}
-
-/*
- * Save SMMU settings before "System Suspend" to TZDRAM
- */
-void tegra_smmu_save_context(uint64_t smmu_ctx_addr)
-{
-	uint32_t i, num_entries = 0;
-	smmu_regs_t *smmu_ctx_regs;
-	const plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params();
-	uint64_t tzdram_base = params_from_bl2->tzdram_base;
-	uint64_t tzdram_end = tzdram_base + params_from_bl2->tzdram_size;
-	uint32_t reg_id1, pgshift, cb_size;
-
-	/* sanity check SMMU settings c*/
-	reg_id1 = mmio_read_32((TEGRA_SMMU0_BASE + SMMU_GNSR0_IDR1));
-	pgshift = ((reg_id1 & ID1_PAGESIZE) != 0U) ? 16U : 12U;
-	cb_size = ((uint32_t)2 << pgshift) * \
-	((uint32_t)1 << (((reg_id1 >> ID1_NUMPAGENDXB_SHIFT) & ID1_NUMPAGENDXB_MASK) + 1U));
-
-	assert(!((pgshift != PGSHIFT) || (cb_size != CB_SIZE)));
-	assert((smmu_ctx_addr >= tzdram_base) && (smmu_ctx_addr <= tzdram_end));
-
-	/* get SMMU context table */
-	smmu_ctx_regs = plat_get_smmu_ctx();
-	assert(smmu_ctx_regs != NULL);
-
-	/*
-	 * smmu_ctx_regs[0].val contains the size of the context table minus
-	 * the last entry. Sanity check the table size before we start with
-	 * the context save operation.
-	 */
-	while ((smmu_ctx_regs[num_entries].reg != 0xFFFFFFFFU)) {
-		num_entries++;
-	}
-
-	/* panic if the sizes do not match */
-	if (num_entries != smmu_ctx_regs[0].val) {
-		ERROR("SMMU context size mismatch!");
-		panic();
-	}
-
-	/* save SMMU register values */
-	for (i = 1U; i < num_entries; i++) {
-		smmu_ctx_regs[i].val = mmio_read_32(smmu_ctx_regs[i].reg);
-	}
-
-	/* increment by 1 to take care of the last entry */
-	num_entries++;
-
-	/* Save SMMU config settings */
-	(void)memcpy16((uint8_t *)smmu_ctx_addr, (uint8_t *)smmu_ctx_regs,
-			(sizeof(smmu_regs_t) * num_entries));
-
-	/* save the SMMU table address */
-	mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_SMMU_TABLE_ADDR_LO,
-		(uint32_t)smmu_ctx_addr);
-	mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_SMMU_TABLE_ADDR_HI,
-		(uint32_t)(smmu_ctx_addr >> 32));
-}
-
-#define SMMU_NUM_CONTEXTS		64
-#define SMMU_CONTEXT_BANK_MAX_IDX	64
+#define SMMU_NUM_CONTEXTS		64U
+#define SMMU_CONTEXT_BANK_MAX_IDX	64U
 
 /*
  * Init SMMU during boot or "System Suspend" exit
diff --git a/plat/nvidia/tegra/common/tegra_fiq_glue.c b/plat/nvidia/tegra/common/tegra_fiq_glue.c
index 8e198ae..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-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;
 }
 
diff --git a/plat/nvidia/tegra/include/drivers/bpmp_ipc.h b/plat/nvidia/tegra/include/drivers/bpmp_ipc.h
index a0d02c9..401a07a 100644
--- a/plat/nvidia/tegra/include/drivers/bpmp_ipc.h
+++ b/plat/nvidia/tegra/include/drivers/bpmp_ipc.h
@@ -19,11 +19,6 @@
 #define TEGRA_RESET_ID_GPCDMA		U(70)
 
 /**
- * Clock identifier for the SE device
- */
-#define TEGRA_CLK_SE        U(124)
-
-/**
  * Function to initialise the IPC with the bpmp
  */
 int32_t tegra_bpmp_ipc_init(void);
diff --git a/plat/nvidia/tegra/include/drivers/memctrl_v2.h b/plat/nvidia/tegra/include/drivers/memctrl_v2.h
index a4085e2..509fe32 100644
--- a/plat/nvidia/tegra/include/drivers/memctrl_v2.h
+++ b/plat/nvidia/tegra/include/drivers/memctrl_v2.h
@@ -84,6 +84,41 @@
 		.override_enable = OVERRIDE_ ## access \
 	}
 
+typedef struct mc_regs {
+	uint32_t reg;
+	uint32_t val;
+} mc_regs_t;
+
+#define mc_make_sid_override_cfg(name) \
+	{ \
+		.reg = TEGRA_MC_STREAMID_BASE + MC_STREAMID_OVERRIDE_CFG_ ## name, \
+		.val = 0x00000000U, \
+	}
+
+#define mc_make_sid_security_cfg(name) \
+	{ \
+		.reg = TEGRA_MC_STREAMID_BASE + MC_STREAMID_OVERRIDE_TO_SECURITY_CFG(MC_STREAMID_OVERRIDE_CFG_ ## name), \
+		.val = 0x00000000U, \
+	}
+
+#define mc_smmu_bypass_cfg \
+	{ \
+		.reg = TEGRA_MC_BASE + MC_SMMU_BYPASS_CONFIG, \
+		.val = 0x00000000U, \
+	}
+
+#define _START_OF_TABLE_ \
+	{ \
+		.reg = 0xCAFE05C7U, \
+		.val = 0x00000000U, \
+	}
+
+#define _END_OF_TABLE_ \
+	{ \
+		.reg = 0xFFFFFFFFU, \
+		.val = 0xFFFFFFFFU, \
+	}
+
 /*******************************************************************************
  * Structure to hold Memory Controller's Configuration settings
  ******************************************************************************/
@@ -96,6 +131,7 @@
 	uint32_t num_txn_override_cfgs;
 	void (*reconfig_mss_clients)(void);
 	void (*set_txn_overrides)(void);
+	mc_regs_t* (*get_mc_system_suspend_ctx)(void);
 } tegra_mc_settings_t;
 
 static inline uint32_t tegra_mc_read_32(uint32_t off)
@@ -166,6 +202,13 @@
 tegra_mc_settings_t *tegra_get_mc_settings(void);
 
 /*******************************************************************************
+ * Handler to save MC settings before "System Suspend" to TZDRAM
+ *
+ * Implemented by Tegra common memctrl_v2 driver under common/drivers/memctrl
+ ******************************************************************************/
+void tegra_mc_save_context(uint64_t mc_ctx_addr);
+
+/*******************************************************************************
  * Handler to program the scratch registers with TZDRAM settings for the
  * resume firmware.
  *
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/smmu.h b/plat/nvidia/tegra/include/drivers/smmu.h
index 424a91a..601864f 100644
--- a/plat/nvidia/tegra/include/drivers/smmu.h
+++ b/plat/nvidia/tegra/include/drivers/smmu.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -12,566 +13,7 @@
 #include <memctrl_v2.h>
 #include <tegra_def.h>
 
-/*******************************************************************************
- * SMMU Register constants
- ******************************************************************************/
-#define SMMU_CBn_SCTLR				(0x0U)
-#define SMMU_CBn_SCTLR_STAGE2			(0x0U)
 #define SMMU_CBn_ACTLR				(0x4U)
-#define SMMU_CBn_RESUME				(0x8U)
-#define SMMU_CBn_TCR2				(0x10U)
-#define SMMU_CBn_TTBR0_LO			(0x20U)
-#define SMMU_CBn_TTBR0_HI			(0x24U)
-#define SMMU_CBn_TTBR1_LO			(0x28U)
-#define SMMU_CBn_TTBR1_HI			(0x2cU)
-#define SMMU_CBn_TCR_LPAE			(0x30U)
-#define SMMU_CBn_TCR				(0x30U)
-#define SMMU_CBn_TCR_EAE_1			(0x30U)
-#define SMMU_CBn_TCR				(0x30U)
-#define SMMU_CBn_CONTEXTIDR			(0x34U)
-#define SMMU_CBn_CONTEXTIDR_EAE_1		(0x34U)
-#define SMMU_CBn_PRRR_MAIR0			(0x38U)
-#define SMMU_CBn_NMRR_MAIR1			(0x3cU)
-#define SMMU_CBn_SMMU_CBn_PAR			(0x50U)
-#define SMMU_CBn_SMMU_CBn_PAR0			(0x50U)
-#define SMMU_CBn_SMMU_CBn_PAR1			(0x54U)
-/*      SMMU_CBn_SMMU_CBn_PAR0_Fault		(0x50U) */
-/*      SMMU_CBn_SMMU_CBn_PAR0_Fault		(0x54U) */
-#define SMMU_CBn_FSR				(0x58U)
-#define SMMU_CBn_FSRRESTORE			(0x5cU)
-#define SMMU_CBn_FAR_LO				(0x60U)
-#define SMMU_CBn_FAR_HI				(0x64U)
-#define SMMU_CBn_FSYNR0				(0x68U)
-#define SMMU_CBn_IPAFAR_LO			(0x70U)
-#define SMMU_CBn_IPAFAR_HI			(0x74U)
-#define SMMU_CBn_TLBIVA_LO			(0x600U)
-#define SMMU_CBn_TLBIVA_HI			(0x604U)
-#define SMMU_CBn_TLBIVA_AARCH_32		(0x600U)
-#define SMMU_CBn_TLBIVAA_LO			(0x608U)
-#define SMMU_CBn_TLBIVAA_HI			(0x60cU)
-#define SMMU_CBn_TLBIVAA_AARCH_32		(0x608U)
-#define SMMU_CBn_TLBIASID			(0x610U)
-#define SMMU_CBn_TLBIALL			(0x618U)
-#define SMMU_CBn_TLBIVAL_LO			(0x620U)
-#define SMMU_CBn_TLBIVAL_HI			(0x624U)
-#define SMMU_CBn_TLBIVAL_AARCH_32		(0x618U)
-#define SMMU_CBn_TLBIVAAL_LO			(0x628U)
-#define SMMU_CBn_TLBIVAAL_HI			(0x62cU)
-#define SMMU_CBn_TLBIVAAL_AARCH_32		(0x628U)
-#define SMMU_CBn_TLBIIPAS2_LO			(0x630U)
-#define SMMU_CBn_TLBIIPAS2_HI			(0x634U)
-#define SMMU_CBn_TLBIIPAS2L_LO			(0x638U)
-#define SMMU_CBn_TLBIIPAS2L_HI			(0x63cU)
-#define SMMU_CBn_TLBSYNC			(0x7f0U)
-#define SMMU_CBn_TLBSTATUS			(0x7f4U)
-#define SMMU_CBn_ATSR				(0x800U)
-#define SMMU_CBn_PMEVCNTR0			(0xe00U)
-#define SMMU_CBn_PMEVCNTR1			(0xe04U)
-#define SMMU_CBn_PMEVCNTR2			(0xe08U)
-#define SMMU_CBn_PMEVCNTR3			(0xe0cU)
-#define SMMU_CBn_PMEVTYPER0			(0xe80U)
-#define SMMU_CBn_PMEVTYPER1			(0xe84U)
-#define SMMU_CBn_PMEVTYPER2			(0xe88U)
-#define SMMU_CBn_PMEVTYPER3			(0xe8cU)
-#define SMMU_CBn_PMCFGR				(0xf00U)
-#define SMMU_CBn_PMCR				(0xf04U)
-#define SMMU_CBn_PMCEID				(0xf20U)
-#define SMMU_CBn_PMCNTENSE			(0xf40U)
-#define SMMU_CBn_PMCNTENCLR			(0xf44U)
-#define SMMU_CBn_PMCNTENSET			(0xf48U)
-#define SMMU_CBn_PMINTENCLR			(0xf4cU)
-#define SMMU_CBn_PMOVSCLR			(0xf50U)
-#define SMMU_CBn_PMOVSSET			(0xf58U)
-#define SMMU_CBn_PMAUTHSTATUS			(0xfb8U)
-#define SMMU_GNSR0_CR0				(0x0U)
-#define SMMU_GNSR0_CR2				(0x8U)
-#define SMMU_GNSR0_ACR				(0x10U)
-#define SMMU_GNSR0_IDR0				(0x20U)
-#define SMMU_GNSR0_IDR1				(0x24U)
-#define SMMU_GNSR0_IDR2				(0x28U)
-#define SMMU_GNSR0_IDR7				(0x3cU)
-#define SMMU_GNSR0_GFAR_LO			(0x40U)
-#define SMMU_GNSR0_GFAR_HI			(0x44U)
-#define SMMU_GNSR0_GFSR				(0x48U)
-#define SMMU_GNSR0_GFSRRESTORE			(0x4cU)
-#define SMMU_GNSR0_GFSYNR0			(0x50U)
-#define SMMU_GNSR0_GFSYNR1			(0x54U)
-#define SMMU_GNSR0_GFSYNR1_v2			(0x54U)
-#define SMMU_GNSR0_TLBIVMID			(0x64U)
-#define SMMU_GNSR0_TLBIALLNSNH			(0x68U)
-#define SMMU_GNSR0_TLBIALLH			(0x6cU)
-#define SMMU_GNSR0_TLBGSYNC			(0x70U)
-#define SMMU_GNSR0_TLBGSTATUS			(0x74U)
-#define SMMU_GNSR0_TLBIVAH_LO			(0x78U)
-#define SMMU_GNSR0_TLBIVALH64_LO		(0xb0U)
-#define SMMU_GNSR0_TLBIVALH64_HI		(0xb4U)
-#define SMMU_GNSR0_TLBIVMIDS1			(0xb8U)
-#define SMMU_GNSR0_TLBIVAH64_LO			(0xc0U)
-#define SMMU_GNSR0_TLBIVAH64_HI			(0xc4U)
-#define SMMU_GNSR0_SMR0				(0x800U)
-#define SMMU_GNSR0_SMRn				(0x800U)
-#define SMMU_GNSR0_SMR1				(0x804U)
-#define SMMU_GNSR0_SMR2				(0x808U)
-#define SMMU_GNSR0_SMR3				(0x80cU)
-#define SMMU_GNSR0_SMR4				(0x810U)
-#define SMMU_GNSR0_SMR5				(0x814U)
-#define SMMU_GNSR0_SMR6				(0x818U)
-#define SMMU_GNSR0_SMR7				(0x81cU)
-#define SMMU_GNSR0_SMR8				(0x820U)
-#define SMMU_GNSR0_SMR9				(0x824U)
-#define SMMU_GNSR0_SMR10			(0x828U)
-#define SMMU_GNSR0_SMR11			(0x82cU)
-#define SMMU_GNSR0_SMR12			(0x830U)
-#define SMMU_GNSR0_SMR13			(0x834U)
-#define SMMU_GNSR0_SMR14			(0x838U)
-#define SMMU_GNSR0_SMR15			(0x83cU)
-#define SMMU_GNSR0_SMR16			(0x840U)
-#define SMMU_GNSR0_SMR17			(0x844U)
-#define SMMU_GNSR0_SMR18			(0x848U)
-#define SMMU_GNSR0_SMR19			(0x84cU)
-#define SMMU_GNSR0_SMR20			(0x850U)
-#define SMMU_GNSR0_SMR21			(0x854U)
-#define SMMU_GNSR0_SMR22			(0x858U)
-#define SMMU_GNSR0_SMR23			(0x85cU)
-#define SMMU_GNSR0_SMR24			(0x860U)
-#define SMMU_GNSR0_SMR25			(0x864U)
-#define SMMU_GNSR0_SMR26			(0x868U)
-#define SMMU_GNSR0_SMR27			(0x86cU)
-#define SMMU_GNSR0_SMR28			(0x870U)
-#define SMMU_GNSR0_SMR29			(0x874U)
-#define SMMU_GNSR0_SMR30			(0x878U)
-#define SMMU_GNSR0_SMR31			(0x87cU)
-#define SMMU_GNSR0_SMR32			(0x880U)
-#define SMMU_GNSR0_SMR33			(0x884U)
-#define SMMU_GNSR0_SMR34			(0x888U)
-#define SMMU_GNSR0_SMR35			(0x88cU)
-#define SMMU_GNSR0_SMR36			(0x890U)
-#define SMMU_GNSR0_SMR37			(0x894U)
-#define SMMU_GNSR0_SMR38			(0x898U)
-#define SMMU_GNSR0_SMR39			(0x89cU)
-#define SMMU_GNSR0_SMR40			(0x8a0U)
-#define SMMU_GNSR0_SMR41			(0x8a4U)
-#define SMMU_GNSR0_SMR42			(0x8a8U)
-#define SMMU_GNSR0_SMR43			(0x8acU)
-#define SMMU_GNSR0_SMR44			(0x8b0U)
-#define SMMU_GNSR0_SMR45			(0x8b4U)
-#define SMMU_GNSR0_SMR46			(0x8b8U)
-#define SMMU_GNSR0_SMR47			(0x8bcU)
-#define SMMU_GNSR0_SMR48			(0x8c0U)
-#define SMMU_GNSR0_SMR49			(0x8c4U)
-#define SMMU_GNSR0_SMR50			(0x8c8U)
-#define SMMU_GNSR0_SMR51			(0x8ccU)
-#define SMMU_GNSR0_SMR52			(0x8d0U)
-#define SMMU_GNSR0_SMR53			(0x8d4U)
-#define SMMU_GNSR0_SMR54			(0x8d8U)
-#define SMMU_GNSR0_SMR55			(0x8dcU)
-#define SMMU_GNSR0_SMR56			(0x8e0U)
-#define SMMU_GNSR0_SMR57			(0x8e4U)
-#define SMMU_GNSR0_SMR58			(0x8e8U)
-#define SMMU_GNSR0_SMR59			(0x8ecU)
-#define SMMU_GNSR0_SMR60			(0x8f0U)
-#define SMMU_GNSR0_SMR61			(0x8f4U)
-#define SMMU_GNSR0_SMR62			(0x8f8U)
-#define SMMU_GNSR0_SMR63			(0x8fcU)
-#define SMMU_GNSR0_SMR64			(0x900U)
-#define SMMU_GNSR0_SMR65			(0x904U)
-#define SMMU_GNSR0_SMR66			(0x908U)
-#define SMMU_GNSR0_SMR67			(0x90cU)
-#define SMMU_GNSR0_SMR68			(0x910U)
-#define SMMU_GNSR0_SMR69			(0x914U)
-#define SMMU_GNSR0_SMR70			(0x918U)
-#define SMMU_GNSR0_SMR71			(0x91cU)
-#define SMMU_GNSR0_SMR72			(0x920U)
-#define SMMU_GNSR0_SMR73			(0x924U)
-#define SMMU_GNSR0_SMR74			(0x928U)
-#define SMMU_GNSR0_SMR75			(0x92cU)
-#define SMMU_GNSR0_SMR76			(0x930U)
-#define SMMU_GNSR0_SMR77			(0x934U)
-#define SMMU_GNSR0_SMR78			(0x938U)
-#define SMMU_GNSR0_SMR79			(0x93cU)
-#define SMMU_GNSR0_SMR80			(0x940U)
-#define SMMU_GNSR0_SMR81			(0x944U)
-#define SMMU_GNSR0_SMR82			(0x948U)
-#define SMMU_GNSR0_SMR83			(0x94cU)
-#define SMMU_GNSR0_SMR84			(0x950U)
-#define SMMU_GNSR0_SMR85			(0x954U)
-#define SMMU_GNSR0_SMR86			(0x958U)
-#define SMMU_GNSR0_SMR87			(0x95cU)
-#define SMMU_GNSR0_SMR88			(0x960U)
-#define SMMU_GNSR0_SMR89			(0x964U)
-#define SMMU_GNSR0_SMR90			(0x968U)
-#define SMMU_GNSR0_SMR91			(0x96cU)
-#define SMMU_GNSR0_SMR92			(0x970U)
-#define SMMU_GNSR0_SMR93			(0x974U)
-#define SMMU_GNSR0_SMR94			(0x978U)
-#define SMMU_GNSR0_SMR95			(0x97cU)
-#define SMMU_GNSR0_SMR96			(0x980U)
-#define SMMU_GNSR0_SMR97			(0x984U)
-#define SMMU_GNSR0_SMR98			(0x988U)
-#define SMMU_GNSR0_SMR99			(0x98cU)
-#define SMMU_GNSR0_SMR100			(0x990U)
-#define SMMU_GNSR0_SMR101			(0x994U)
-#define SMMU_GNSR0_SMR102			(0x998U)
-#define SMMU_GNSR0_SMR103			(0x99cU)
-#define SMMU_GNSR0_SMR104			(0x9a0U)
-#define SMMU_GNSR0_SMR105			(0x9a4U)
-#define SMMU_GNSR0_SMR106			(0x9a8U)
-#define SMMU_GNSR0_SMR107			(0x9acU)
-#define SMMU_GNSR0_SMR108			(0x9b0U)
-#define SMMU_GNSR0_SMR109			(0x9b4U)
-#define SMMU_GNSR0_SMR110			(0x9b8U)
-#define SMMU_GNSR0_SMR111			(0x9bcU)
-#define SMMU_GNSR0_SMR112			(0x9c0U)
-#define SMMU_GNSR0_SMR113			(0x9c4U)
-#define SMMU_GNSR0_SMR114			(0x9c8U)
-#define SMMU_GNSR0_SMR115			(0x9ccU)
-#define SMMU_GNSR0_SMR116			(0x9d0U)
-#define SMMU_GNSR0_SMR117			(0x9d4U)
-#define SMMU_GNSR0_SMR118			(0x9d8U)
-#define SMMU_GNSR0_SMR119			(0x9dcU)
-#define SMMU_GNSR0_SMR120			(0x9e0U)
-#define SMMU_GNSR0_SMR121			(0x9e4U)
-#define SMMU_GNSR0_SMR122			(0x9e8U)
-#define SMMU_GNSR0_SMR123			(0x9ecU)
-#define SMMU_GNSR0_SMR124			(0x9f0U)
-#define SMMU_GNSR0_SMR125			(0x9f4U)
-#define SMMU_GNSR0_SMR126			(0x9f8U)
-#define SMMU_GNSR0_SMR127			(0x9fcU)
-#define SMMU_GNSR0_S2CR0			(0xc00U)
-#define SMMU_GNSR0_S2CRn			(0xc00U)
-#define SMMU_GNSR0_S2CRn			(0xc00U)
-#define SMMU_GNSR0_S2CR1			(0xc04U)
-#define SMMU_GNSR0_S2CR2			(0xc08U)
-#define SMMU_GNSR0_S2CR3			(0xc0cU)
-#define SMMU_GNSR0_S2CR4			(0xc10U)
-#define SMMU_GNSR0_S2CR5			(0xc14U)
-#define SMMU_GNSR0_S2CR6			(0xc18U)
-#define SMMU_GNSR0_S2CR7			(0xc1cU)
-#define SMMU_GNSR0_S2CR8			(0xc20U)
-#define SMMU_GNSR0_S2CR9			(0xc24U)
-#define SMMU_GNSR0_S2CR10			(0xc28U)
-#define SMMU_GNSR0_S2CR11			(0xc2cU)
-#define SMMU_GNSR0_S2CR12			(0xc30U)
-#define SMMU_GNSR0_S2CR13			(0xc34U)
-#define SMMU_GNSR0_S2CR14			(0xc38U)
-#define SMMU_GNSR0_S2CR15			(0xc3cU)
-#define SMMU_GNSR0_S2CR16			(0xc40U)
-#define SMMU_GNSR0_S2CR17			(0xc44U)
-#define SMMU_GNSR0_S2CR18			(0xc48U)
-#define SMMU_GNSR0_S2CR19			(0xc4cU)
-#define SMMU_GNSR0_S2CR20			(0xc50U)
-#define SMMU_GNSR0_S2CR21			(0xc54U)
-#define SMMU_GNSR0_S2CR22			(0xc58U)
-#define SMMU_GNSR0_S2CR23			(0xc5cU)
-#define SMMU_GNSR0_S2CR24			(0xc60U)
-#define SMMU_GNSR0_S2CR25			(0xc64U)
-#define SMMU_GNSR0_S2CR26			(0xc68U)
-#define SMMU_GNSR0_S2CR27			(0xc6cU)
-#define SMMU_GNSR0_S2CR28			(0xc70U)
-#define SMMU_GNSR0_S2CR29			(0xc74U)
-#define SMMU_GNSR0_S2CR30			(0xc78U)
-#define SMMU_GNSR0_S2CR31			(0xc7cU)
-#define SMMU_GNSR0_S2CR32			(0xc80U)
-#define SMMU_GNSR0_S2CR33			(0xc84U)
-#define SMMU_GNSR0_S2CR34			(0xc88U)
-#define SMMU_GNSR0_S2CR35			(0xc8cU)
-#define SMMU_GNSR0_S2CR36			(0xc90U)
-#define SMMU_GNSR0_S2CR37			(0xc94U)
-#define SMMU_GNSR0_S2CR38			(0xc98U)
-#define SMMU_GNSR0_S2CR39			(0xc9cU)
-#define SMMU_GNSR0_S2CR40			(0xca0U)
-#define SMMU_GNSR0_S2CR41			(0xca4U)
-#define SMMU_GNSR0_S2CR42			(0xca8U)
-#define SMMU_GNSR0_S2CR43			(0xcacU)
-#define SMMU_GNSR0_S2CR44			(0xcb0U)
-#define SMMU_GNSR0_S2CR45			(0xcb4U)
-#define SMMU_GNSR0_S2CR46			(0xcb8U)
-#define SMMU_GNSR0_S2CR47			(0xcbcU)
-#define SMMU_GNSR0_S2CR48			(0xcc0U)
-#define SMMU_GNSR0_S2CR49			(0xcc4U)
-#define SMMU_GNSR0_S2CR50			(0xcc8U)
-#define SMMU_GNSR0_S2CR51			(0xcccU)
-#define SMMU_GNSR0_S2CR52			(0xcd0U)
-#define SMMU_GNSR0_S2CR53			(0xcd4U)
-#define SMMU_GNSR0_S2CR54			(0xcd8U)
-#define SMMU_GNSR0_S2CR55			(0xcdcU)
-#define SMMU_GNSR0_S2CR56			(0xce0U)
-#define SMMU_GNSR0_S2CR57			(0xce4U)
-#define SMMU_GNSR0_S2CR58			(0xce8U)
-#define SMMU_GNSR0_S2CR59			(0xcecU)
-#define SMMU_GNSR0_S2CR60			(0xcf0U)
-#define SMMU_GNSR0_S2CR61			(0xcf4U)
-#define SMMU_GNSR0_S2CR62			(0xcf8U)
-#define SMMU_GNSR0_S2CR63			(0xcfcU)
-#define SMMU_GNSR0_S2CR64			(0xd00U)
-#define SMMU_GNSR0_S2CR65			(0xd04U)
-#define SMMU_GNSR0_S2CR66			(0xd08U)
-#define SMMU_GNSR0_S2CR67			(0xd0cU)
-#define SMMU_GNSR0_S2CR68			(0xd10U)
-#define SMMU_GNSR0_S2CR69			(0xd14U)
-#define SMMU_GNSR0_S2CR70			(0xd18U)
-#define SMMU_GNSR0_S2CR71			(0xd1cU)
-#define SMMU_GNSR0_S2CR72			(0xd20U)
-#define SMMU_GNSR0_S2CR73			(0xd24U)
-#define SMMU_GNSR0_S2CR74			(0xd28U)
-#define SMMU_GNSR0_S2CR75			(0xd2cU)
-#define SMMU_GNSR0_S2CR76			(0xd30U)
-#define SMMU_GNSR0_S2CR77			(0xd34U)
-#define SMMU_GNSR0_S2CR78			(0xd38U)
-#define SMMU_GNSR0_S2CR79			(0xd3cU)
-#define SMMU_GNSR0_S2CR80			(0xd40U)
-#define SMMU_GNSR0_S2CR81			(0xd44U)
-#define SMMU_GNSR0_S2CR82			(0xd48U)
-#define SMMU_GNSR0_S2CR83			(0xd4cU)
-#define SMMU_GNSR0_S2CR84			(0xd50U)
-#define SMMU_GNSR0_S2CR85			(0xd54U)
-#define SMMU_GNSR0_S2CR86			(0xd58U)
-#define SMMU_GNSR0_S2CR87			(0xd5cU)
-#define SMMU_GNSR0_S2CR88			(0xd60U)
-#define SMMU_GNSR0_S2CR89			(0xd64U)
-#define SMMU_GNSR0_S2CR90			(0xd68U)
-#define SMMU_GNSR0_S2CR91			(0xd6cU)
-#define SMMU_GNSR0_S2CR92			(0xd70U)
-#define SMMU_GNSR0_S2CR93			(0xd74U)
-#define SMMU_GNSR0_S2CR94			(0xd78U)
-#define SMMU_GNSR0_S2CR95			(0xd7cU)
-#define SMMU_GNSR0_S2CR96			(0xd80U)
-#define SMMU_GNSR0_S2CR97			(0xd84U)
-#define SMMU_GNSR0_S2CR98			(0xd88U)
-#define SMMU_GNSR0_S2CR99			(0xd8cU)
-#define SMMU_GNSR0_S2CR100			(0xd90U)
-#define SMMU_GNSR0_S2CR101			(0xd94U)
-#define SMMU_GNSR0_S2CR102			(0xd98U)
-#define SMMU_GNSR0_S2CR103			(0xd9cU)
-#define SMMU_GNSR0_S2CR104			(0xda0U)
-#define SMMU_GNSR0_S2CR105			(0xda4U)
-#define SMMU_GNSR0_S2CR106			(0xda8U)
-#define SMMU_GNSR0_S2CR107			(0xdacU)
-#define SMMU_GNSR0_S2CR108			(0xdb0U)
-#define SMMU_GNSR0_S2CR109			(0xdb4U)
-#define SMMU_GNSR0_S2CR110			(0xdb8U)
-#define SMMU_GNSR0_S2CR111			(0xdbcU)
-#define SMMU_GNSR0_S2CR112			(0xdc0U)
-#define SMMU_GNSR0_S2CR113			(0xdc4U)
-#define SMMU_GNSR0_S2CR114			(0xdc8U)
-#define SMMU_GNSR0_S2CR115			(0xdccU)
-#define SMMU_GNSR0_S2CR116			(0xdd0U)
-#define SMMU_GNSR0_S2CR117			(0xdd4U)
-#define SMMU_GNSR0_S2CR118			(0xdd8U)
-#define SMMU_GNSR0_S2CR119			(0xddcU)
-#define SMMU_GNSR0_S2CR120			(0xde0U)
-#define SMMU_GNSR0_S2CR121			(0xde4U)
-#define SMMU_GNSR0_S2CR122			(0xde8U)
-#define SMMU_GNSR0_S2CR123			(0xdecU)
-#define SMMU_GNSR0_S2CR124			(0xdf0U)
-#define SMMU_GNSR0_S2CR125			(0xdf4U)
-#define SMMU_GNSR0_S2CR126			(0xdf8U)
-#define SMMU_GNSR0_S2CR127			(0xdfcU)
-#define SMMU_GNSR0_PIDR0			(0xfe0U)
-#define SMMU_GNSR0_PIDR1			(0xfe4U)
-#define SMMU_GNSR0_PIDR2			(0xfe8U)
-#define SMMU_GNSR0_PIDR3			(0xfecU)
-#define SMMU_GNSR0_PIDR4			(0xfd0U)
-#define SMMU_GNSR0_PIDR5			(0xfd4U)
-#define SMMU_GNSR0_PIDR6			(0xfd8U)
-#define SMMU_GNSR0_PIDR7			(0xfdcU)
-#define SMMU_GNSR0_CIDR0			(0xff0U)
-#define SMMU_GNSR0_CIDR1			(0xff4U)
-#define SMMU_GNSR0_CIDR2			(0xff8U)
-#define SMMU_GNSR0_CIDR3			(0xffcU)
-#define SMMU_GNSR1_CBAR0			(0x0U)
-#define SMMU_GNSR1_CBARn			(0x0U)
-#define SMMU_GNSR1_CBFRSYNRA0			(0x400U)
-#define SMMU_GNSR1_CBA2R0			(0x800U)
-#define SMMU_GNSR1_CBAR1			(0x4U)
-#define SMMU_GNSR1_CBFRSYNRA1			(0x404U)
-#define SMMU_GNSR1_CBA2R1			(0x804U)
-#define SMMU_GNSR1_CBAR2			(0x8U)
-#define SMMU_GNSR1_CBFRSYNRA2			(0x408U)
-#define SMMU_GNSR1_CBA2R2			(0x808U)
-#define SMMU_GNSR1_CBAR3			(0xcU)
-#define SMMU_GNSR1_CBFRSYNRA3			(0x40cU)
-#define SMMU_GNSR1_CBA2R3			(0x80cU)
-#define SMMU_GNSR1_CBAR4			(0x10U)
-#define SMMU_GNSR1_CBFRSYNRA4			(0x410U)
-#define SMMU_GNSR1_CBA2R4			(0x810U)
-#define SMMU_GNSR1_CBAR5			(0x14U)
-#define SMMU_GNSR1_CBFRSYNRA5			(0x414U)
-#define SMMU_GNSR1_CBA2R5			(0x814U)
-#define SMMU_GNSR1_CBAR6			(0x18U)
-#define SMMU_GNSR1_CBFRSYNRA6			(0x418U)
-#define SMMU_GNSR1_CBA2R6			(0x818U)
-#define SMMU_GNSR1_CBAR7			(0x1cU)
-#define SMMU_GNSR1_CBFRSYNRA7			(0x41cU)
-#define SMMU_GNSR1_CBA2R7			(0x81cU)
-#define SMMU_GNSR1_CBAR8			(0x20U)
-#define SMMU_GNSR1_CBFRSYNRA8			(0x420U)
-#define SMMU_GNSR1_CBA2R8			(0x820U)
-#define SMMU_GNSR1_CBAR9			(0x24U)
-#define SMMU_GNSR1_CBFRSYNRA9			(0x424U)
-#define SMMU_GNSR1_CBA2R9			(0x824U)
-#define SMMU_GNSR1_CBAR10			(0x28U)
-#define SMMU_GNSR1_CBFRSYNRA10			(0x428U)
-#define SMMU_GNSR1_CBA2R10			(0x828U)
-#define SMMU_GNSR1_CBAR11			(0x2cU)
-#define SMMU_GNSR1_CBFRSYNRA11			(0x42cU)
-#define SMMU_GNSR1_CBA2R11			(0x82cU)
-#define SMMU_GNSR1_CBAR12			(0x30U)
-#define SMMU_GNSR1_CBFRSYNRA12			(0x430U)
-#define SMMU_GNSR1_CBA2R12			(0x830U)
-#define SMMU_GNSR1_CBAR13			(0x34U)
-#define SMMU_GNSR1_CBFRSYNRA13			(0x434U)
-#define SMMU_GNSR1_CBA2R13			(0x834U)
-#define SMMU_GNSR1_CBAR14			(0x38U)
-#define SMMU_GNSR1_CBFRSYNRA14			(0x438U)
-#define SMMU_GNSR1_CBA2R14			(0x838U)
-#define SMMU_GNSR1_CBAR15			(0x3cU)
-#define SMMU_GNSR1_CBFRSYNRA15			(0x43cU)
-#define SMMU_GNSR1_CBA2R15			(0x83cU)
-#define SMMU_GNSR1_CBAR16			(0x40U)
-#define SMMU_GNSR1_CBFRSYNRA16			(0x440U)
-#define SMMU_GNSR1_CBA2R16			(0x840U)
-#define SMMU_GNSR1_CBAR17			(0x44U)
-#define SMMU_GNSR1_CBFRSYNRA17			(0x444U)
-#define SMMU_GNSR1_CBA2R17			(0x844U)
-#define SMMU_GNSR1_CBAR18			(0x48U)
-#define SMMU_GNSR1_CBFRSYNRA18			(0x448U)
-#define SMMU_GNSR1_CBA2R18			(0x848U)
-#define SMMU_GNSR1_CBAR19			(0x4cU)
-#define SMMU_GNSR1_CBFRSYNRA19			(0x44cU)
-#define SMMU_GNSR1_CBA2R19			(0x84cU)
-#define SMMU_GNSR1_CBAR20			(0x50U)
-#define SMMU_GNSR1_CBFRSYNRA20			(0x450U)
-#define SMMU_GNSR1_CBA2R20			(0x850U)
-#define SMMU_GNSR1_CBAR21			(0x54U)
-#define SMMU_GNSR1_CBFRSYNRA21			(0x454U)
-#define SMMU_GNSR1_CBA2R21			(0x854U)
-#define SMMU_GNSR1_CBAR22			(0x58U)
-#define SMMU_GNSR1_CBFRSYNRA22			(0x458U)
-#define SMMU_GNSR1_CBA2R22			(0x858U)
-#define SMMU_GNSR1_CBAR23			(0x5cU)
-#define SMMU_GNSR1_CBFRSYNRA23			(0x45cU)
-#define SMMU_GNSR1_CBA2R23			(0x85cU)
-#define SMMU_GNSR1_CBAR24			(0x60U)
-#define SMMU_GNSR1_CBFRSYNRA24			(0x460U)
-#define SMMU_GNSR1_CBA2R24			(0x860U)
-#define SMMU_GNSR1_CBAR25			(0x64U)
-#define SMMU_GNSR1_CBFRSYNRA25			(0x464U)
-#define SMMU_GNSR1_CBA2R25			(0x864U)
-#define SMMU_GNSR1_CBAR26			(0x68U)
-#define SMMU_GNSR1_CBFRSYNRA26			(0x468U)
-#define SMMU_GNSR1_CBA2R26			(0x868U)
-#define SMMU_GNSR1_CBAR27			(0x6cU)
-#define SMMU_GNSR1_CBFRSYNRA27			(0x46cU)
-#define SMMU_GNSR1_CBA2R27			(0x86cU)
-#define SMMU_GNSR1_CBAR28			(0x70U)
-#define SMMU_GNSR1_CBFRSYNRA28			(0x470U)
-#define SMMU_GNSR1_CBA2R28			(0x870U)
-#define SMMU_GNSR1_CBAR29			(0x74U)
-#define SMMU_GNSR1_CBFRSYNRA29			(0x474U)
-#define SMMU_GNSR1_CBA2R29			(0x874U)
-#define SMMU_GNSR1_CBAR30			(0x78U)
-#define SMMU_GNSR1_CBFRSYNRA30			(0x478U)
-#define SMMU_GNSR1_CBA2R30			(0x878U)
-#define SMMU_GNSR1_CBAR31			(0x7cU)
-#define SMMU_GNSR1_CBFRSYNRA31			(0x47cU)
-#define SMMU_GNSR1_CBA2R31			(0x87cU)
-#define SMMU_GNSR1_CBAR32			(0x80U)
-#define SMMU_GNSR1_CBFRSYNRA32			(0x480U)
-#define SMMU_GNSR1_CBA2R32			(0x880U)
-#define SMMU_GNSR1_CBAR33			(0x84U)
-#define SMMU_GNSR1_CBFRSYNRA33			(0x484U)
-#define SMMU_GNSR1_CBA2R33			(0x884U)
-#define SMMU_GNSR1_CBAR34			(0x88U)
-#define SMMU_GNSR1_CBFRSYNRA34			(0x488U)
-#define SMMU_GNSR1_CBA2R34			(0x888U)
-#define SMMU_GNSR1_CBAR35			(0x8cU)
-#define SMMU_GNSR1_CBFRSYNRA35			(0x48cU)
-#define SMMU_GNSR1_CBA2R35			(0x88cU)
-#define SMMU_GNSR1_CBAR36			(0x90U)
-#define SMMU_GNSR1_CBFRSYNRA36			(0x490U)
-#define SMMU_GNSR1_CBA2R36			(0x890U)
-#define SMMU_GNSR1_CBAR37			(0x94U)
-#define SMMU_GNSR1_CBFRSYNRA37			(0x494U)
-#define SMMU_GNSR1_CBA2R37			(0x894U)
-#define SMMU_GNSR1_CBAR38			(0x98U)
-#define SMMU_GNSR1_CBFRSYNRA38			(0x498U)
-#define SMMU_GNSR1_CBA2R38			(0x898U)
-#define SMMU_GNSR1_CBAR39			(0x9cU)
-#define SMMU_GNSR1_CBFRSYNRA39			(0x49cU)
-#define SMMU_GNSR1_CBA2R39			(0x89cU)
-#define SMMU_GNSR1_CBAR40			(0xa0U)
-#define SMMU_GNSR1_CBFRSYNRA40			(0x4a0U)
-#define SMMU_GNSR1_CBA2R40			(0x8a0U)
-#define SMMU_GNSR1_CBAR41			(0xa4U)
-#define SMMU_GNSR1_CBFRSYNRA41			(0x4a4U)
-#define SMMU_GNSR1_CBA2R41			(0x8a4U)
-#define SMMU_GNSR1_CBAR42			(0xa8U)
-#define SMMU_GNSR1_CBFRSYNRA42			(0x4a8U)
-#define SMMU_GNSR1_CBA2R42			(0x8a8U)
-#define SMMU_GNSR1_CBAR43			(0xacU)
-#define SMMU_GNSR1_CBFRSYNRA43			(0x4acU)
-#define SMMU_GNSR1_CBA2R43			(0x8acU)
-#define SMMU_GNSR1_CBAR44			(0xb0U)
-#define SMMU_GNSR1_CBFRSYNRA44			(0x4b0U)
-#define SMMU_GNSR1_CBA2R44			(0x8b0U)
-#define SMMU_GNSR1_CBAR45			(0xb4U)
-#define SMMU_GNSR1_CBFRSYNRA45			(0x4b4U)
-#define SMMU_GNSR1_CBA2R45			(0x8b4U)
-#define SMMU_GNSR1_CBAR46			(0xb8U)
-#define SMMU_GNSR1_CBFRSYNRA46			(0x4b8U)
-#define SMMU_GNSR1_CBA2R46			(0x8b8U)
-#define SMMU_GNSR1_CBAR47			(0xbcU)
-#define SMMU_GNSR1_CBFRSYNRA47			(0x4bcU)
-#define SMMU_GNSR1_CBA2R47			(0x8bcU)
-#define SMMU_GNSR1_CBAR48			(0xc0U)
-#define SMMU_GNSR1_CBFRSYNRA48			(0x4c0U)
-#define SMMU_GNSR1_CBA2R48			(0x8c0U)
-#define SMMU_GNSR1_CBAR49			(0xc4U)
-#define SMMU_GNSR1_CBFRSYNRA49			(0x4c4U)
-#define SMMU_GNSR1_CBA2R49			(0x8c4U)
-#define SMMU_GNSR1_CBAR50			(0xc8U)
-#define SMMU_GNSR1_CBFRSYNRA50			(0x4c8U)
-#define SMMU_GNSR1_CBA2R50			(0x8c8U)
-#define SMMU_GNSR1_CBAR51			(0xccU)
-#define SMMU_GNSR1_CBFRSYNRA51			(0x4ccU)
-#define SMMU_GNSR1_CBA2R51			(0x8ccU)
-#define SMMU_GNSR1_CBAR52			(0xd0U)
-#define SMMU_GNSR1_CBFRSYNRA52			(0x4d0U)
-#define SMMU_GNSR1_CBA2R52			(0x8d0U)
-#define SMMU_GNSR1_CBAR53			(0xd4U)
-#define SMMU_GNSR1_CBFRSYNRA53			(0x4d4U)
-#define SMMU_GNSR1_CBA2R53			(0x8d4U)
-#define SMMU_GNSR1_CBAR54			(0xd8U)
-#define SMMU_GNSR1_CBFRSYNRA54			(0x4d8U)
-#define SMMU_GNSR1_CBA2R54			(0x8d8U)
-#define SMMU_GNSR1_CBAR55			(0xdcU)
-#define SMMU_GNSR1_CBFRSYNRA55			(0x4dcU)
-#define SMMU_GNSR1_CBA2R55			(0x8dcU)
-#define SMMU_GNSR1_CBAR56			(0xe0U)
-#define SMMU_GNSR1_CBFRSYNRA56			(0x4e0U)
-#define SMMU_GNSR1_CBA2R56			(0x8e0U)
-#define SMMU_GNSR1_CBAR57			(0xe4U)
-#define SMMU_GNSR1_CBFRSYNRA57			(0x4e4U)
-#define SMMU_GNSR1_CBA2R57			(0x8e4U)
-#define SMMU_GNSR1_CBAR58			(0xe8U)
-#define SMMU_GNSR1_CBFRSYNRA58			(0x4e8U)
-#define SMMU_GNSR1_CBA2R58			(0x8e8U)
-#define SMMU_GNSR1_CBAR59			(0xecU)
-#define SMMU_GNSR1_CBFRSYNRA59			(0x4ecU)
-#define SMMU_GNSR1_CBA2R59			(0x8ecU)
-#define SMMU_GNSR1_CBAR60			(0xf0U)
-#define SMMU_GNSR1_CBFRSYNRA60			(0x4f0U)
-#define SMMU_GNSR1_CBA2R60			(0x8f0U)
-#define SMMU_GNSR1_CBAR61			(0xf4U)
-#define SMMU_GNSR1_CBFRSYNRA61			(0x4f4U)
-#define SMMU_GNSR1_CBA2R61			(0x8f4U)
-#define SMMU_GNSR1_CBAR62			(0xf8U)
-#define SMMU_GNSR1_CBFRSYNRA62			(0x4f8U)
-#define SMMU_GNSR1_CBA2R62			(0x8f8U)
-#define SMMU_GNSR1_CBAR63			(0xfcU)
-#define SMMU_GNSR1_CBFRSYNRA63			(0x4fcU)
-#define SMMU_GNSR1_CBA2R63			(0x8fcU)
 
 /*******************************************************************************
  * SMMU Global Secure Aux. Configuration Register
@@ -581,269 +23,69 @@
 #define SMMU_GSR0_PGSIZE_SHIFT			16U
 #define SMMU_GSR0_PGSIZE_4K			(0U << SMMU_GSR0_PGSIZE_SHIFT)
 #define SMMU_GSR0_PGSIZE_64K			(1U << SMMU_GSR0_PGSIZE_SHIFT)
-#define SMMU_ACR_CACHE_LOCK_ENABLE_BIT		(1U << 26)
+#define SMMU_ACR_CACHE_LOCK_ENABLE_BIT		(1ULL << 26U)
+#define SMMU_GSR0_PER				(0x20200U)
 
 /*******************************************************************************
  * SMMU Global Aux. Control Register
  ******************************************************************************/
 #define SMMU_CBn_ACTLR_CPRE_BIT			(1ULL << 1U)
 
-/*******************************************************************************
- * SMMU configuration constants
- ******************************************************************************/
-#define ID1_PAGESIZE				(1U << 31U)
-#define ID1_NUMPAGENDXB_SHIFT			28U
-#define ID1_NUMPAGENDXB_MASK			7U
-#define ID1_NUMS2CB_SHIFT			16U
-#define ID1_NUMS2CB_MASK			0xffU
-#define ID1_NUMCB_SHIFT				0U
-#define ID1_NUMCB_MASK				0xffU
-#define PGSHIFT					16U
-#define CB_SIZE					0x800000U
+/* SMMU IDs currently supported by the driver */
+enum {
+	TEGRA_SMMU0 = 0U,
+	TEGRA_SMMU1 = 1U,
+	TEGRA_SMMU2 = 2U
+};
 
-typedef struct smmu_regs {
-	uint32_t reg;
-	uint32_t val;
-} smmu_regs_t;
+static inline uint32_t tegra_smmu_read_32(uint32_t smmu_id, uint32_t off)
+{
+	uint32_t ret = 0U;
 
-#define mc_make_sid_override_cfg(name) \
-	{ \
-		.reg = TEGRA_MC_STREAMID_BASE + MC_STREAMID_OVERRIDE_CFG_ ## name, \
-		.val = 0x00000000U, \
+#if defined(TEGRA_SMMU0_BASE)
+	if (smmu_id == TEGRA_SMMU0) {
+		ret = mmio_read_32(TEGRA_SMMU0_BASE + (uint64_t)off);
 	}
+#endif
 
-#define mc_make_sid_security_cfg(name) \
-	{ \
-		.reg = TEGRA_MC_STREAMID_BASE + MC_STREAMID_OVERRIDE_TO_SECURITY_CFG(MC_STREAMID_OVERRIDE_CFG_ ## name), \
-		.val = 0x00000000U, \
+#if defined(TEGRA_SMMU1_BASE)
+	if (smmu_id == TEGRA_SMMU1) {
+		ret = mmio_read_32(TEGRA_SMMU1_BASE + (uint64_t)off);
 	}
+#endif
 
-#define smmu_make_gnsr0_sec_cfg(base_addr, name) \
-	{ \
-		.reg = base_addr + SMMU_GNSR0_ ## name, \
-		.val = 0x00000000U, \
+#if defined(TEGRA_SMMU2_BASE)
+	if (smmu_id == TEGRA_SMMU2) {
+		ret = mmio_read_32(TEGRA_SMMU2_BASE + (uint64_t)off);
 	}
+#endif
 
-/*
- * On ARM-SMMU, conditional offset to access secure aliases of non-secure registers
- * is 0x400. So, add it to register address
- */
-#define smmu_make_gnsr0_nsec_cfg(base_addr, name) \
-	{ \
-		.reg = base_addr + 0x400U + SMMU_GNSR0_ ## name, \
-		.val = 0x00000000U, \
+	return ret;
+}
+
+static inline void tegra_smmu_write_32(uint32_t smmu_id,
+			uint32_t off, uint32_t val)
+{
+#if defined(TEGRA_SMMU0_BASE)
+	if (smmu_id == TEGRA_SMMU0) {
+		mmio_write_32(TEGRA_SMMU0_BASE + (uint64_t)off, val);
 	}
+#endif
 
-#define smmu_make_gnsr0_smr_cfg(base_addr, n) \
-	{ \
-		.reg = base_addr + SMMU_GNSR0_SMR ## n, \
-		.val = 0x00000000U, \
+#if defined(TEGRA_SMMU1_BASE)
+	if (smmu_id == TEGRA_SMMU1) {
+		mmio_write_32(TEGRA_SMMU1_BASE + (uint64_t)off, val);
 	}
+#endif
 
-#define smmu_make_gnsr0_s2cr_cfg(base_addr, n) \
-	{ \
-		.reg = base_addr + SMMU_GNSR0_S2CR ## n, \
-		.val = 0x00000000U, \
+#if defined(TEGRA_SMMU2_BASE)
+	if (smmu_id == TEGRA_SMMU2) {
+		mmio_write_32(TEGRA_SMMU2_BASE + (uint64_t)off, val);
 	}
-
-#define smmu_make_gnsr1_cbar_cfg(base_addr, n) \
-	{ \
-		.reg = base_addr + (1U << PGSHIFT) + SMMU_GNSR1_CBAR ## n, \
-		.val = 0x00000000U, \
-	}
-
-#define smmu_make_gnsr1_cba2r_cfg(base_addr, n) \
-	{ \
-		.reg = base_addr + (1U << PGSHIFT) + SMMU_GNSR1_CBA2R ## n, \
-		.val = 0x00000000U, \
-	}
-
-#define smmu_make_cb_cfg(base_addr, name, n) \
-	{ \
-		.reg = base_addr + (CB_SIZE >> 1) + (n * (1 << PGSHIFT)) \
-			+ SMMU_CBn_ ## name, \
-		.val = 0x00000000U, \
-	}
-
-#define smmu_make_smrg_group(base_addr, n)	\
-	smmu_make_gnsr0_smr_cfg(base_addr, n),	\
-	smmu_make_gnsr0_s2cr_cfg(base_addr, n),	\
-	smmu_make_gnsr1_cbar_cfg(base_addr, n),	\
-	smmu_make_gnsr1_cba2r_cfg(base_addr, n)	/* don't put "," here. */
-
-#define smmu_make_cb_group(base_addr, n)		\
-	smmu_make_cb_cfg(base_addr, SCTLR, n),	\
-	smmu_make_cb_cfg(base_addr, TCR2, n),	\
-	smmu_make_cb_cfg(base_addr, TTBR0_LO, n),	\
-	smmu_make_cb_cfg(base_addr, TTBR0_HI, n),	\
-	smmu_make_cb_cfg(base_addr, TCR, n),	\
-	smmu_make_cb_cfg(base_addr, PRRR_MAIR0, n),\
-	smmu_make_cb_cfg(base_addr, FSR, n),	\
-	smmu_make_cb_cfg(base_addr, FAR_LO, n),	\
-	smmu_make_cb_cfg(base_addr, FAR_HI, n),	\
-	smmu_make_cb_cfg(base_addr, FSYNR0, n)	/* don't put "," here. */
-
-#define smmu_make_cfg(base_addr)			\
-	smmu_make_gnsr0_nsec_cfg(base_addr, CR0),	\
-	smmu_make_gnsr0_sec_cfg(base_addr, IDR0),	\
-	smmu_make_gnsr0_sec_cfg(base_addr, IDR1),	\
-	smmu_make_gnsr0_sec_cfg(base_addr, IDR2),	\
-	smmu_make_gnsr0_nsec_cfg(base_addr, GFSR),	\
-	smmu_make_gnsr0_nsec_cfg(base_addr, GFSYNR0),	\
-	smmu_make_gnsr0_nsec_cfg(base_addr, GFSYNR1),	\
-	smmu_make_gnsr0_nsec_cfg(base_addr, TLBGSTATUS),\
-	smmu_make_gnsr0_nsec_cfg(base_addr, PIDR2),	\
-	smmu_make_smrg_group(base_addr, 0),		\
-	smmu_make_smrg_group(base_addr, 1),		\
-	smmu_make_smrg_group(base_addr, 2),		\
-	smmu_make_smrg_group(base_addr, 3),		\
-	smmu_make_smrg_group(base_addr, 4),		\
-	smmu_make_smrg_group(base_addr, 5),		\
-	smmu_make_smrg_group(base_addr, 6),		\
-	smmu_make_smrg_group(base_addr, 7),		\
-	smmu_make_smrg_group(base_addr, 8),		\
-	smmu_make_smrg_group(base_addr, 9),		\
-	smmu_make_smrg_group(base_addr, 10),		\
-	smmu_make_smrg_group(base_addr, 11),		\
-	smmu_make_smrg_group(base_addr, 12),		\
-	smmu_make_smrg_group(base_addr, 13),		\
-	smmu_make_smrg_group(base_addr, 14),		\
-	smmu_make_smrg_group(base_addr, 15),		\
-	smmu_make_smrg_group(base_addr, 16),		\
-	smmu_make_smrg_group(base_addr, 17),		\
-	smmu_make_smrg_group(base_addr, 18),		\
-	smmu_make_smrg_group(base_addr, 19),		\
-	smmu_make_smrg_group(base_addr, 20),		\
-	smmu_make_smrg_group(base_addr, 21),		\
-	smmu_make_smrg_group(base_addr, 22),		\
-	smmu_make_smrg_group(base_addr, 23),		\
-	smmu_make_smrg_group(base_addr, 24),		\
-	smmu_make_smrg_group(base_addr, 25),		\
-	smmu_make_smrg_group(base_addr, 26),		\
-	smmu_make_smrg_group(base_addr, 27),		\
-	smmu_make_smrg_group(base_addr, 28),		\
-	smmu_make_smrg_group(base_addr, 29),		\
-	smmu_make_smrg_group(base_addr, 30),		\
-	smmu_make_smrg_group(base_addr, 31),		\
-	smmu_make_smrg_group(base_addr, 32),		\
-	smmu_make_smrg_group(base_addr, 33),		\
-	smmu_make_smrg_group(base_addr, 34),		\
-	smmu_make_smrg_group(base_addr, 35),		\
-	smmu_make_smrg_group(base_addr, 36),		\
-	smmu_make_smrg_group(base_addr, 37),		\
-	smmu_make_smrg_group(base_addr, 38),		\
-	smmu_make_smrg_group(base_addr, 39),		\
-	smmu_make_smrg_group(base_addr, 40),		\
-	smmu_make_smrg_group(base_addr, 41),		\
-	smmu_make_smrg_group(base_addr, 42),		\
-	smmu_make_smrg_group(base_addr, 43),		\
-	smmu_make_smrg_group(base_addr, 44),		\
-	smmu_make_smrg_group(base_addr, 45),		\
-	smmu_make_smrg_group(base_addr, 46),		\
-	smmu_make_smrg_group(base_addr, 47),		\
-	smmu_make_smrg_group(base_addr, 48),		\
-	smmu_make_smrg_group(base_addr, 49),		\
-	smmu_make_smrg_group(base_addr, 50),		\
-	smmu_make_smrg_group(base_addr, 51),		\
-	smmu_make_smrg_group(base_addr, 52),		\
-	smmu_make_smrg_group(base_addr, 53),		\
-	smmu_make_smrg_group(base_addr, 54),		\
-	smmu_make_smrg_group(base_addr, 55),		\
-	smmu_make_smrg_group(base_addr, 56),		\
-	smmu_make_smrg_group(base_addr, 57),		\
-	smmu_make_smrg_group(base_addr, 58),		\
-	smmu_make_smrg_group(base_addr, 59),		\
-	smmu_make_smrg_group(base_addr, 60),		\
-	smmu_make_smrg_group(base_addr, 61),		\
-	smmu_make_smrg_group(base_addr, 62),		\
-	smmu_make_smrg_group(base_addr, 63),		\
-	smmu_make_cb_group(base_addr, 0),		\
-	smmu_make_cb_group(base_addr, 1),		\
-	smmu_make_cb_group(base_addr, 2),		\
-	smmu_make_cb_group(base_addr, 3),		\
-	smmu_make_cb_group(base_addr, 4),		\
-	smmu_make_cb_group(base_addr, 5),		\
-	smmu_make_cb_group(base_addr, 6),		\
-	smmu_make_cb_group(base_addr, 7),		\
-	smmu_make_cb_group(base_addr, 8),		\
-	smmu_make_cb_group(base_addr, 9),		\
-	smmu_make_cb_group(base_addr, 10),		\
-	smmu_make_cb_group(base_addr, 11),		\
-	smmu_make_cb_group(base_addr, 12),		\
-	smmu_make_cb_group(base_addr, 13),		\
-	smmu_make_cb_group(base_addr, 14),		\
-	smmu_make_cb_group(base_addr, 15),		\
-	smmu_make_cb_group(base_addr, 16),		\
-	smmu_make_cb_group(base_addr, 17),		\
-	smmu_make_cb_group(base_addr, 18),		\
-	smmu_make_cb_group(base_addr, 19),		\
-	smmu_make_cb_group(base_addr, 20),		\
-	smmu_make_cb_group(base_addr, 21),		\
-	smmu_make_cb_group(base_addr, 22),		\
-	smmu_make_cb_group(base_addr, 23),		\
-	smmu_make_cb_group(base_addr, 24),		\
-	smmu_make_cb_group(base_addr, 25),		\
-	smmu_make_cb_group(base_addr, 26),		\
-	smmu_make_cb_group(base_addr, 27),		\
-	smmu_make_cb_group(base_addr, 28),		\
-	smmu_make_cb_group(base_addr, 29),		\
-	smmu_make_cb_group(base_addr, 30),		\
-	smmu_make_cb_group(base_addr, 31),		\
-	smmu_make_cb_group(base_addr, 32),		\
-	smmu_make_cb_group(base_addr, 33),		\
-	smmu_make_cb_group(base_addr, 34),		\
-	smmu_make_cb_group(base_addr, 35),		\
-	smmu_make_cb_group(base_addr, 36),		\
-	smmu_make_cb_group(base_addr, 37),		\
-	smmu_make_cb_group(base_addr, 38),		\
-	smmu_make_cb_group(base_addr, 39),		\
-	smmu_make_cb_group(base_addr, 40),		\
-	smmu_make_cb_group(base_addr, 41),		\
-	smmu_make_cb_group(base_addr, 42),		\
-	smmu_make_cb_group(base_addr, 43),		\
-	smmu_make_cb_group(base_addr, 44),		\
-	smmu_make_cb_group(base_addr, 45),		\
-	smmu_make_cb_group(base_addr, 46),		\
-	smmu_make_cb_group(base_addr, 47),		\
-	smmu_make_cb_group(base_addr, 48),		\
-	smmu_make_cb_group(base_addr, 49),		\
-	smmu_make_cb_group(base_addr, 50),		\
-	smmu_make_cb_group(base_addr, 51),		\
-	smmu_make_cb_group(base_addr, 52),		\
-	smmu_make_cb_group(base_addr, 53),		\
-	smmu_make_cb_group(base_addr, 54),		\
-	smmu_make_cb_group(base_addr, 55),		\
-	smmu_make_cb_group(base_addr, 56),		\
-	smmu_make_cb_group(base_addr, 57),		\
-	smmu_make_cb_group(base_addr, 58),		\
-	smmu_make_cb_group(base_addr, 59),		\
-	smmu_make_cb_group(base_addr, 60),		\
-	smmu_make_cb_group(base_addr, 61),		\
-	smmu_make_cb_group(base_addr, 62),		\
-	smmu_make_cb_group(base_addr, 63)	/* don't put "," here. */
-
-#define smmu_bypass_cfg \
-	{ \
-		.reg = TEGRA_MC_BASE + MC_SMMU_BYPASS_CONFIG, \
-		.val = 0x00000000U, \
-	}
-
-#define _START_OF_TABLE_ \
-	{ \
-		.reg = 0xCAFE05C7U, \
-		.val = 0x00000000U, \
-	}
-
-#define _END_OF_TABLE_ \
-	{ \
-		.reg = 0xFFFFFFFFU, \
-		.val = 0xFFFFFFFFU, \
-	}
-
+#endif
+}
 
 void tegra_smmu_init(void);
-void tegra_smmu_save_context(uint64_t smmu_ctx_addr);
-smmu_regs_t *plat_get_smmu_ctx(void);
 uint32_t plat_get_num_smmu_devices(void);
 
 #endif /* SMMU_H */
diff --git a/plat/nvidia/tegra/include/t186/tegra186_private.h b/plat/nvidia/tegra/include/t186/tegra186_private.h
index 9e2c02b..60174ab 100644
--- a/plat/nvidia/tegra/include/t186/tegra186_private.h
+++ b/plat/nvidia/tegra/include/t186/tegra186_private.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2017-2020, NVIDIA CORPORATION. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -10,7 +10,7 @@
 void tegra186_cpu_reset_handler(void);
 uint64_t tegra186_get_cpu_reset_handler_base(void);
 uint64_t tegra186_get_cpu_reset_handler_size(void);
-uint64_t tegra186_get_smmu_ctx_offset(void);
+uint64_t tegra186_get_mc_ctx_offset(void);
 void tegra186_set_system_suspend_entry(void);
 
 #endif /* TEGRA186_PRIVATE_H */
diff --git a/plat/nvidia/tegra/include/t186/tegra_def.h b/plat/nvidia/tegra/include/t186/tegra_def.h
index f2a2334..1da9b46 100644
--- a/plat/nvidia/tegra/include/t186/tegra_def.h
+++ b/plat/nvidia/tegra/include/t186/tegra_def.h
@@ -73,6 +73,12 @@
 #define TEGRA186_SEC_IRQ_TARGET_MASK	U(0xF3) /* 4 A57 - 2 Denver */
 
 /*******************************************************************************
+ * Clock identifier for the SE device
+ ******************************************************************************/
+#define TEGRA186_CLK_SE			U(103)
+#define TEGRA_CLK_SE			TEGRA186_CLK_SE
+
+/*******************************************************************************
  * Tegra Miscellanous register constants
  ******************************************************************************/
 #define TEGRA_MISC_BASE			U(0x00100000)
@@ -213,6 +219,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 +252,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,12 +262,21 @@
 #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
 #define SCRATCH_SECURE_BOOTP_FCFG	SECURE_SCRATCH_RSV6
-#define SCRATCH_SMMU_TABLE_ADDR_LO	SECURE_SCRATCH_RSV11_LO
-#define SCRATCH_SMMU_TABLE_ADDR_HI	SECURE_SCRATCH_RSV11_HI
+#define SCRATCH_MC_TABLE_ADDR_LO	SECURE_SCRATCH_RSV11_LO
+#define SCRATCH_MC_TABLE_ADDR_HI	SECURE_SCRATCH_RSV11_HI
 #define SCRATCH_BL31_PARAMS_ADDR	SECURE_SCRATCH_RSV53_LO
 #define SCRATCH_BL31_PLAT_PARAMS_ADDR	SECURE_SCRATCH_RSV53_HI
 #define SCRATCH_TZDRAM_ADDR_LO		SECURE_SCRATCH_RSV55_LO
@@ -281,6 +305,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/t194/tegra194_private.h b/plat/nvidia/tegra/include/t194/tegra194_private.h
index 8f1deb2..c5a51e9 100644
--- a/plat/nvidia/tegra/include/t194/tegra194_private.h
+++ b/plat/nvidia/tegra/include/t194/tegra194_private.h
@@ -10,7 +10,7 @@
 void tegra194_cpu_reset_handler(void);
 uint64_t tegra194_get_cpu_reset_handler_base(void);
 uint64_t tegra194_get_cpu_reset_handler_size(void);
-uint64_t tegra194_get_smmu_ctx_offset(void);
+uint64_t tegra194_get_mc_ctx_offset(void);
 void tegra194_set_system_suspend_entry(void);
 
 #endif /* TEGRA194_PRIVATE_H */
diff --git a/plat/nvidia/tegra/include/t194/tegra_def.h b/plat/nvidia/tegra/include/t194/tegra_def.h
index a58ae9d..dc06445 100644
--- a/plat/nvidia/tegra/include/t194/tegra_def.h
+++ b/plat/nvidia/tegra/include/t194/tegra_def.h
@@ -43,6 +43,12 @@
 #define TEGRA194_SEC_IRQ_TARGET_MASK	U(0xFF) /* 8 Carmel */
 
 /*******************************************************************************
+ * Clock identifier for the SE device
+ ******************************************************************************/
+#define TEGRA194_CLK_SE			U(124)
+#define TEGRA_CLK_SE			TEGRA194_CLK_SE
+
+/*******************************************************************************
  * Tegra Miscellanous register constants
  ******************************************************************************/
 #define TEGRA_MISC_BASE			U(0x00100000)
@@ -197,6 +203,16 @@
  * Tegra scratch registers constants
  ******************************************************************************/
 #define TEGRA_SCRATCH_BASE		U(0x0C390000)
+#define  SECURE_SCRATCH_RSV68_LO	U(0x284)
+#define  SECURE_SCRATCH_RSV68_HI	U(0x288)
+#define  SECURE_SCRATCH_RSV69_LO	U(0x28C)
+#define  SECURE_SCRATCH_RSV69_HI	U(0x290)
+#define  SECURE_SCRATCH_RSV70_LO	U(0x294)
+#define  SECURE_SCRATCH_RSV70_HI	U(0x298)
+#define  SECURE_SCRATCH_RSV71_LO	U(0x29C)
+#define  SECURE_SCRATCH_RSV71_HI	U(0x2A0)
+#define  SECURE_SCRATCH_RSV72_LO	U(0x2A4)
+#define  SECURE_SCRATCH_RSV72_HI	U(0x2A8)
 #define  SECURE_SCRATCH_RSV75   	U(0x2BC)
 #define  SECURE_SCRATCH_RSV81_LO	U(0x2EC)
 #define  SECURE_SCRATCH_RSV81_HI	U(0x2F0)
@@ -215,8 +231,8 @@
 #define  SCRATCH_BL31_PLAT_PARAMS_HI_ADDR_SHIFT U(16)
 #define SCRATCH_BL31_PLAT_PARAMS_LO_ADDR SECURE_SCRATCH_RSV81_HI
 #define SCRATCH_SECURE_BOOTP_FCFG	SECURE_SCRATCH_RSV97
-#define SCRATCH_SMMU_TABLE_ADDR_LO	SECURE_SCRATCH_RSV99_LO
-#define SCRATCH_SMMU_TABLE_ADDR_HI	SECURE_SCRATCH_RSV99_HI
+#define SCRATCH_MC_TABLE_ADDR_LO	SECURE_SCRATCH_RSV99_LO
+#define SCRATCH_MC_TABLE_ADDR_HI	SECURE_SCRATCH_RSV99_HI
 #define SCRATCH_RESET_VECTOR_LO		SECURE_SCRATCH_RSV109_LO
 #define SCRATCH_RESET_VECTOR_HI		SECURE_SCRATCH_RSV109_HI
 
diff --git a/plat/nvidia/tegra/include/t210/tegra_def.h b/plat/nvidia/tegra/include/t210/tegra_def.h
index 4a39aa1..f3013a8 100644
--- a/plat/nvidia/tegra/include/t210/tegra_def.h
+++ b/plat/nvidia/tegra/include/t210/tegra_def.h
@@ -44,6 +44,11 @@
 #define SC7ENTRY_FW_HEADER_SIZE_BYTES	U(0x400)
 
 /*******************************************************************************
+ * Counter-timer physical secure timer PPI
+ ******************************************************************************/
+#define TEGRA210_TIMER1_IRQ		32
+
+/*******************************************************************************
  * iRAM memory constants
  ******************************************************************************/
 #define TEGRA_IRAM_BASE			U(0x40000000)
@@ -144,6 +149,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/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..09377bb 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
@@ -511,6 +516,171 @@
 	}
 }
 
+
+/*******************************************************************************
+ * Array to hold MC context for Tegra186
+ ******************************************************************************/
+static __attribute__((aligned(16))) mc_regs_t tegra186_mc_context[] = {
+	_START_OF_TABLE_,
+	mc_make_sid_security_cfg(SCEW),
+	mc_make_sid_security_cfg(AFIR),
+	mc_make_sid_security_cfg(NVDISPLAYR1),
+	mc_make_sid_security_cfg(XUSB_DEVR),
+	mc_make_sid_security_cfg(VICSRD1),
+	mc_make_sid_security_cfg(NVENCSWR),
+	mc_make_sid_security_cfg(TSECSRDB),
+	mc_make_sid_security_cfg(AXISW),
+	mc_make_sid_security_cfg(SDMMCWAB),
+	mc_make_sid_security_cfg(AONDMAW),
+	mc_make_sid_security_cfg(GPUSWR2),
+	mc_make_sid_security_cfg(SATAW),
+	mc_make_sid_security_cfg(UFSHCW),
+	mc_make_sid_security_cfg(AFIW),
+	mc_make_sid_security_cfg(SDMMCR),
+	mc_make_sid_security_cfg(SCEDMAW),
+	mc_make_sid_security_cfg(UFSHCR),
+	mc_make_sid_security_cfg(SDMMCWAA),
+	mc_make_sid_security_cfg(APEDMAW),
+	mc_make_sid_security_cfg(SESWR),
+	mc_make_sid_security_cfg(MPCORER),
+	mc_make_sid_security_cfg(PTCR),
+	mc_make_sid_security_cfg(BPMPW),
+	mc_make_sid_security_cfg(ETRW),
+	mc_make_sid_security_cfg(GPUSRD),
+	mc_make_sid_security_cfg(VICSWR),
+	mc_make_sid_security_cfg(SCEDMAR),
+	mc_make_sid_security_cfg(HDAW),
+	mc_make_sid_security_cfg(ISPWA),
+	mc_make_sid_security_cfg(EQOSW),
+	mc_make_sid_security_cfg(XUSB_HOSTW),
+	mc_make_sid_security_cfg(TSECSWR),
+	mc_make_sid_security_cfg(SDMMCRAA),
+	mc_make_sid_security_cfg(APER),
+	mc_make_sid_security_cfg(VIW),
+	mc_make_sid_security_cfg(APEW),
+	mc_make_sid_security_cfg(AXISR),
+	mc_make_sid_security_cfg(SDMMCW),
+	mc_make_sid_security_cfg(BPMPDMAW),
+	mc_make_sid_security_cfg(ISPRA),
+	mc_make_sid_security_cfg(NVDECSWR),
+	mc_make_sid_security_cfg(XUSB_DEVW),
+	mc_make_sid_security_cfg(NVDECSRD),
+	mc_make_sid_security_cfg(MPCOREW),
+	mc_make_sid_security_cfg(NVDISPLAYR),
+	mc_make_sid_security_cfg(BPMPDMAR),
+	mc_make_sid_security_cfg(NVJPGSWR),
+	mc_make_sid_security_cfg(NVDECSRD1),
+	mc_make_sid_security_cfg(TSECSRD),
+	mc_make_sid_security_cfg(NVJPGSRD),
+	mc_make_sid_security_cfg(SDMMCWA),
+	mc_make_sid_security_cfg(SCER),
+	mc_make_sid_security_cfg(XUSB_HOSTR),
+	mc_make_sid_security_cfg(VICSRD),
+	mc_make_sid_security_cfg(AONDMAR),
+	mc_make_sid_security_cfg(AONW),
+	mc_make_sid_security_cfg(SDMMCRA),
+	mc_make_sid_security_cfg(HOST1XDMAR),
+	mc_make_sid_security_cfg(EQOSR),
+	mc_make_sid_security_cfg(SATAR),
+	mc_make_sid_security_cfg(BPMPR),
+	mc_make_sid_security_cfg(HDAR),
+	mc_make_sid_security_cfg(SDMMCRAB),
+	mc_make_sid_security_cfg(ETRR),
+	mc_make_sid_security_cfg(AONR),
+	mc_make_sid_security_cfg(APEDMAR),
+	mc_make_sid_security_cfg(SESRD),
+	mc_make_sid_security_cfg(NVENCSRD),
+	mc_make_sid_security_cfg(GPUSWR),
+	mc_make_sid_security_cfg(TSECSWRB),
+	mc_make_sid_security_cfg(ISPWB),
+	mc_make_sid_security_cfg(GPUSRD2),
+	mc_make_sid_override_cfg(APER),
+	mc_make_sid_override_cfg(VICSRD),
+	mc_make_sid_override_cfg(NVENCSRD),
+	mc_make_sid_override_cfg(NVJPGSWR),
+	mc_make_sid_override_cfg(AONW),
+	mc_make_sid_override_cfg(BPMPR),
+	mc_make_sid_override_cfg(BPMPW),
+	mc_make_sid_override_cfg(HDAW),
+	mc_make_sid_override_cfg(NVDISPLAYR1),
+	mc_make_sid_override_cfg(APEDMAR),
+	mc_make_sid_override_cfg(AFIR),
+	mc_make_sid_override_cfg(AXISR),
+	mc_make_sid_override_cfg(VICSRD1),
+	mc_make_sid_override_cfg(TSECSRD),
+	mc_make_sid_override_cfg(BPMPDMAW),
+	mc_make_sid_override_cfg(MPCOREW),
+	mc_make_sid_override_cfg(XUSB_HOSTR),
+	mc_make_sid_override_cfg(GPUSWR),
+	mc_make_sid_override_cfg(XUSB_DEVR),
+	mc_make_sid_override_cfg(UFSHCW),
+	mc_make_sid_override_cfg(XUSB_HOSTW),
+	mc_make_sid_override_cfg(SDMMCWAB),
+	mc_make_sid_override_cfg(SATAW),
+	mc_make_sid_override_cfg(SCEDMAR),
+	mc_make_sid_override_cfg(HOST1XDMAR),
+	mc_make_sid_override_cfg(SDMMCWA),
+	mc_make_sid_override_cfg(APEDMAW),
+	mc_make_sid_override_cfg(SESWR),
+	mc_make_sid_override_cfg(AXISW),
+	mc_make_sid_override_cfg(AONDMAW),
+	mc_make_sid_override_cfg(TSECSWRB),
+	mc_make_sid_override_cfg(MPCORER),
+	mc_make_sid_override_cfg(ISPWB),
+	mc_make_sid_override_cfg(AONR),
+	mc_make_sid_override_cfg(BPMPDMAR),
+	mc_make_sid_override_cfg(HDAR),
+	mc_make_sid_override_cfg(SDMMCRA),
+	mc_make_sid_override_cfg(ETRW),
+	mc_make_sid_override_cfg(GPUSWR2),
+	mc_make_sid_override_cfg(EQOSR),
+	mc_make_sid_override_cfg(TSECSWR),
+	mc_make_sid_override_cfg(ETRR),
+	mc_make_sid_override_cfg(NVDECSRD),
+	mc_make_sid_override_cfg(TSECSRDB),
+	mc_make_sid_override_cfg(SDMMCRAA),
+	mc_make_sid_override_cfg(NVDECSRD1),
+	mc_make_sid_override_cfg(SDMMCR),
+	mc_make_sid_override_cfg(NVJPGSRD),
+	mc_make_sid_override_cfg(SCEDMAW),
+	mc_make_sid_override_cfg(SDMMCWAA),
+	mc_make_sid_override_cfg(APEW),
+	mc_make_sid_override_cfg(AONDMAR),
+	mc_make_sid_override_cfg(PTCR),
+	mc_make_sid_override_cfg(SCER),
+	mc_make_sid_override_cfg(ISPRA),
+	mc_make_sid_override_cfg(ISPWA),
+	mc_make_sid_override_cfg(VICSWR),
+	mc_make_sid_override_cfg(SESRD),
+	mc_make_sid_override_cfg(SDMMCW),
+	mc_make_sid_override_cfg(SDMMCRAB),
+	mc_make_sid_override_cfg(EQOSW),
+	mc_make_sid_override_cfg(GPUSRD2),
+	mc_make_sid_override_cfg(SCEW),
+	mc_make_sid_override_cfg(GPUSRD),
+	mc_make_sid_override_cfg(NVDECSWR),
+	mc_make_sid_override_cfg(XUSB_DEVW),
+	mc_make_sid_override_cfg(SATAR),
+	mc_make_sid_override_cfg(NVDISPLAYR),
+	mc_make_sid_override_cfg(VIW),
+	mc_make_sid_override_cfg(UFSHCR),
+	mc_make_sid_override_cfg(NVENCSWR),
+	mc_make_sid_override_cfg(AFIW),
+	mc_smmu_bypass_cfg,	/* TBU settings */
+	_END_OF_TABLE_,
+};
+
+/*******************************************************************************
+ * Handler to return the pointer to the MC's context struct
+ ******************************************************************************/
+static mc_regs_t *tegra186_get_mc_system_suspend_ctx(void)
+{
+	/* index of _END_OF_TABLE_ */
+	tegra186_mc_context[0].val = (uint32_t)(ARRAY_SIZE(tegra186_mc_context)) - 1U;
+
+	return tegra186_mc_context;
+}
+
 /*******************************************************************************
  * Struct to hold the memory controller settings
  ******************************************************************************/
@@ -523,6 +693,7 @@
 	.num_txn_override_cfgs = (uint32_t)ARRAY_SIZE(tegra186_txn_override_cfgs),
 	.reconfig_mss_clients = tegra186_memctrl_reconfig_mss_clients,
 	.set_txn_overrides = tegra186_memctrl_set_overrides,
+	.get_mc_system_suspend_ctx = tegra186_get_mc_system_suspend_ctx,
 };
 
 /*******************************************************************************
@@ -540,6 +711,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 +747,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..179dd96 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,11 @@
 #include <lib/psci/psci.h>
 #include <plat/common/platform.h>
 
+#include <bpmp_ipc.h>
 #include <mce.h>
+#include <memctrl_v2.h>
+#include <security_engine.h>
 #include <smmu.h>
-#include <stdbool.h>
 #include <t18x_ari.h>
 #include <tegra186_private.h>
 #include <tegra_private.h>
@@ -97,7 +100,7 @@
 	uint32_t cpu = plat_my_core_pos();
 	const plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params();
 	mce_cstate_info_t cstate_info = { 0 };
-	uint64_t smmu_ctx_base;
+	uint64_t mc_ctx_base;
 	uint32_t val;
 
 	/* get the state ID */
@@ -130,10 +133,10 @@
 		val = mmio_read_32(TEGRA_MISC_BASE + MISCREG_PFCFG);
 		mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_SECURE_BOOTP_FCFG, val);
 
-		/* save SMMU context to TZDRAM */
-		smmu_ctx_base = params_from_bl2->tzdram_base +
-				tegra186_get_smmu_ctx_offset();
-		tegra_smmu_save_context((uintptr_t)smmu_ctx_base);
+		/* save MC context to TZDRAM */
+		mc_ctx_base = params_from_bl2->tzdram_base +
+				tegra186_get_mc_ctx_offset();
+		tegra_mc_save_context((uintptr_t)mc_ctx_base);
 
 		/* Prepare for system suspend */
 		cstate_info.cluster = (uint32_t)TEGRA_ARI_CLUSTER_CC7;
@@ -280,8 +283,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(TEGRA186_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 +319,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(TEGRA186_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 7028bfc..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}
 };
 
diff --git a/plat/nvidia/tegra/soc/t186/plat_smmu.c b/plat/nvidia/tegra/soc/t186/plat_smmu.c
index b4a7fe5..f1bc235 100644
--- a/plat/nvidia/tegra/soc/t186/plat_smmu.c
+++ b/plat/nvidia/tegra/soc/t186/plat_smmu.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -13,171 +14,6 @@
 #define MAX_NUM_SMMU_DEVICES	U(1)
 
 /*******************************************************************************
- * Array to hold SMMU context for Tegra186
- ******************************************************************************/
-static __attribute__((aligned(16))) smmu_regs_t tegra186_smmu_context[] = {
-	_START_OF_TABLE_,
-	mc_make_sid_security_cfg(SCEW),
-	mc_make_sid_security_cfg(AFIR),
-	mc_make_sid_security_cfg(NVDISPLAYR1),
-	mc_make_sid_security_cfg(XUSB_DEVR),
-	mc_make_sid_security_cfg(VICSRD1),
-	mc_make_sid_security_cfg(NVENCSWR),
-	mc_make_sid_security_cfg(TSECSRDB),
-	mc_make_sid_security_cfg(AXISW),
-	mc_make_sid_security_cfg(SDMMCWAB),
-	mc_make_sid_security_cfg(AONDMAW),
-	mc_make_sid_security_cfg(GPUSWR2),
-	mc_make_sid_security_cfg(SATAW),
-	mc_make_sid_security_cfg(UFSHCW),
-	mc_make_sid_security_cfg(AFIW),
-	mc_make_sid_security_cfg(SDMMCR),
-	mc_make_sid_security_cfg(SCEDMAW),
-	mc_make_sid_security_cfg(UFSHCR),
-	mc_make_sid_security_cfg(SDMMCWAA),
-	mc_make_sid_security_cfg(APEDMAW),
-	mc_make_sid_security_cfg(SESWR),
-	mc_make_sid_security_cfg(MPCORER),
-	mc_make_sid_security_cfg(PTCR),
-	mc_make_sid_security_cfg(BPMPW),
-	mc_make_sid_security_cfg(ETRW),
-	mc_make_sid_security_cfg(GPUSRD),
-	mc_make_sid_security_cfg(VICSWR),
-	mc_make_sid_security_cfg(SCEDMAR),
-	mc_make_sid_security_cfg(HDAW),
-	mc_make_sid_security_cfg(ISPWA),
-	mc_make_sid_security_cfg(EQOSW),
-	mc_make_sid_security_cfg(XUSB_HOSTW),
-	mc_make_sid_security_cfg(TSECSWR),
-	mc_make_sid_security_cfg(SDMMCRAA),
-	mc_make_sid_security_cfg(APER),
-	mc_make_sid_security_cfg(VIW),
-	mc_make_sid_security_cfg(APEW),
-	mc_make_sid_security_cfg(AXISR),
-	mc_make_sid_security_cfg(SDMMCW),
-	mc_make_sid_security_cfg(BPMPDMAW),
-	mc_make_sid_security_cfg(ISPRA),
-	mc_make_sid_security_cfg(NVDECSWR),
-	mc_make_sid_security_cfg(XUSB_DEVW),
-	mc_make_sid_security_cfg(NVDECSRD),
-	mc_make_sid_security_cfg(MPCOREW),
-	mc_make_sid_security_cfg(NVDISPLAYR),
-	mc_make_sid_security_cfg(BPMPDMAR),
-	mc_make_sid_security_cfg(NVJPGSWR),
-	mc_make_sid_security_cfg(NVDECSRD1),
-	mc_make_sid_security_cfg(TSECSRD),
-	mc_make_sid_security_cfg(NVJPGSRD),
-	mc_make_sid_security_cfg(SDMMCWA),
-	mc_make_sid_security_cfg(SCER),
-	mc_make_sid_security_cfg(XUSB_HOSTR),
-	mc_make_sid_security_cfg(VICSRD),
-	mc_make_sid_security_cfg(AONDMAR),
-	mc_make_sid_security_cfg(AONW),
-	mc_make_sid_security_cfg(SDMMCRA),
-	mc_make_sid_security_cfg(HOST1XDMAR),
-	mc_make_sid_security_cfg(EQOSR),
-	mc_make_sid_security_cfg(SATAR),
-	mc_make_sid_security_cfg(BPMPR),
-	mc_make_sid_security_cfg(HDAR),
-	mc_make_sid_security_cfg(SDMMCRAB),
-	mc_make_sid_security_cfg(ETRR),
-	mc_make_sid_security_cfg(AONR),
-	mc_make_sid_security_cfg(APEDMAR),
-	mc_make_sid_security_cfg(SESRD),
-	mc_make_sid_security_cfg(NVENCSRD),
-	mc_make_sid_security_cfg(GPUSWR),
-	mc_make_sid_security_cfg(TSECSWRB),
-	mc_make_sid_security_cfg(ISPWB),
-	mc_make_sid_security_cfg(GPUSRD2),
-	mc_make_sid_override_cfg(APER),
-	mc_make_sid_override_cfg(VICSRD),
-	mc_make_sid_override_cfg(NVENCSRD),
-	mc_make_sid_override_cfg(NVJPGSWR),
-	mc_make_sid_override_cfg(AONW),
-	mc_make_sid_override_cfg(BPMPR),
-	mc_make_sid_override_cfg(BPMPW),
-	mc_make_sid_override_cfg(HDAW),
-	mc_make_sid_override_cfg(NVDISPLAYR1),
-	mc_make_sid_override_cfg(APEDMAR),
-	mc_make_sid_override_cfg(AFIR),
-	mc_make_sid_override_cfg(AXISR),
-	mc_make_sid_override_cfg(VICSRD1),
-	mc_make_sid_override_cfg(TSECSRD),
-	mc_make_sid_override_cfg(BPMPDMAW),
-	mc_make_sid_override_cfg(MPCOREW),
-	mc_make_sid_override_cfg(XUSB_HOSTR),
-	mc_make_sid_override_cfg(GPUSWR),
-	mc_make_sid_override_cfg(XUSB_DEVR),
-	mc_make_sid_override_cfg(UFSHCW),
-	mc_make_sid_override_cfg(XUSB_HOSTW),
-	mc_make_sid_override_cfg(SDMMCWAB),
-	mc_make_sid_override_cfg(SATAW),
-	mc_make_sid_override_cfg(SCEDMAR),
-	mc_make_sid_override_cfg(HOST1XDMAR),
-	mc_make_sid_override_cfg(SDMMCWA),
-	mc_make_sid_override_cfg(APEDMAW),
-	mc_make_sid_override_cfg(SESWR),
-	mc_make_sid_override_cfg(AXISW),
-	mc_make_sid_override_cfg(AONDMAW),
-	mc_make_sid_override_cfg(TSECSWRB),
-	mc_make_sid_override_cfg(MPCORER),
-	mc_make_sid_override_cfg(ISPWB),
-	mc_make_sid_override_cfg(AONR),
-	mc_make_sid_override_cfg(BPMPDMAR),
-	mc_make_sid_override_cfg(HDAR),
-	mc_make_sid_override_cfg(SDMMCRA),
-	mc_make_sid_override_cfg(ETRW),
-	mc_make_sid_override_cfg(GPUSWR2),
-	mc_make_sid_override_cfg(EQOSR),
-	mc_make_sid_override_cfg(TSECSWR),
-	mc_make_sid_override_cfg(ETRR),
-	mc_make_sid_override_cfg(NVDECSRD),
-	mc_make_sid_override_cfg(TSECSRDB),
-	mc_make_sid_override_cfg(SDMMCRAA),
-	mc_make_sid_override_cfg(NVDECSRD1),
-	mc_make_sid_override_cfg(SDMMCR),
-	mc_make_sid_override_cfg(NVJPGSRD),
-	mc_make_sid_override_cfg(SCEDMAW),
-	mc_make_sid_override_cfg(SDMMCWAA),
-	mc_make_sid_override_cfg(APEW),
-	mc_make_sid_override_cfg(AONDMAR),
-	mc_make_sid_override_cfg(PTCR),
-	mc_make_sid_override_cfg(SCER),
-	mc_make_sid_override_cfg(ISPRA),
-	mc_make_sid_override_cfg(ISPWA),
-	mc_make_sid_override_cfg(VICSWR),
-	mc_make_sid_override_cfg(SESRD),
-	mc_make_sid_override_cfg(SDMMCW),
-	mc_make_sid_override_cfg(SDMMCRAB),
-	mc_make_sid_override_cfg(EQOSW),
-	mc_make_sid_override_cfg(GPUSRD2),
-	mc_make_sid_override_cfg(SCEW),
-	mc_make_sid_override_cfg(GPUSRD),
-	mc_make_sid_override_cfg(NVDECSWR),
-	mc_make_sid_override_cfg(XUSB_DEVW),
-	mc_make_sid_override_cfg(SATAR),
-	mc_make_sid_override_cfg(NVDISPLAYR),
-	mc_make_sid_override_cfg(VIW),
-	mc_make_sid_override_cfg(UFSHCR),
-	mc_make_sid_override_cfg(NVENCSWR),
-	mc_make_sid_override_cfg(AFIW),
-	smmu_make_cfg(TEGRA_SMMU0_BASE),
-	smmu_bypass_cfg,	/* TBU settings */
-	_END_OF_TABLE_,
-};
-
-/*******************************************************************************
- * Handler to return the pointer to the SMMU's context struct
- ******************************************************************************/
-smmu_regs_t *plat_get_smmu_ctx(void)
-{
-	/* index of _END_OF_TABLE_ */
-	tegra186_smmu_context[0].val = (uint32_t)(ARRAY_SIZE(tegra186_smmu_context)) - 1U;
-
-	return tegra186_smmu_context;
-}
-
-/*******************************************************************************
  * Handler to return the support SMMU devices number
  ******************************************************************************/
 uint32_t plat_get_num_smmu_devices(void)
diff --git a/plat/nvidia/tegra/soc/t186/plat_trampoline.S b/plat/nvidia/tegra/soc/t186/plat_trampoline.S
index db69234..818c24b 100644
--- a/plat/nvidia/tegra/soc/t186/plat_trampoline.S
+++ b/plat/nvidia/tegra/soc/t186/plat_trampoline.S
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -13,7 +14,7 @@
 
 #define TEGRA186_STATE_SYSTEM_SUSPEND	0x5C7
 #define TEGRA186_STATE_SYSTEM_RESUME	0x600D
-#define TEGRA186_SMMU_CTX_SIZE		0x420
+#define TEGRA186_MC_CTX_SIZE		0x93
 
 	.globl	tegra186_cpu_reset_handler
 
@@ -69,8 +70,8 @@
 	 *
 	 * 0x000: secure world's entrypoint
 	 * 0x008: BL31 size (RO + RW)
-	 * 0x00C: SMMU context start
-	 * 0x42C: SMMU context end
+	 * 0x00C: MC context start
+	 * 0x42C: MC context end
 	 */
 
 	.align 4
@@ -85,9 +86,9 @@
 	.quad	0
 
 	.align 4
-	.globl	__tegra186_smmu_context
-__tegra186_smmu_context:
-	.rept	TEGRA186_SMMU_CTX_SIZE
+	.globl	__tegra186_mc_context
+__tegra186_mc_context:
+	.rept	TEGRA186_MC_CTX_SIZE
 	.quad	0
 	.endr
 	.size	__tegra186_cpu_reset_handler_data, \
@@ -99,7 +100,7 @@
 
 	.globl tegra186_get_cpu_reset_handler_size
 	.globl tegra186_get_cpu_reset_handler_base
-	.globl tegra186_get_smmu_ctx_offset
+	.globl tegra186_get_mc_ctx_offset
 	.globl tegra186_set_system_suspend_entry
 
 /* return size of the CPU reset handler */
@@ -116,13 +117,13 @@
 	ret
 endfunc tegra186_get_cpu_reset_handler_base
 
-/* return the size of the SMMU context */
-func tegra186_get_smmu_ctx_offset
-	adr	x0, __tegra186_smmu_context
+/* return the size of the MC context */
+func tegra186_get_mc_ctx_offset
+	adr	x0, __tegra186_mc_context
 	adr	x1, tegra186_cpu_reset_handler
 	sub	x0, x0, x1
 	ret
-endfunc tegra186_get_smmu_ctx_offset
+endfunc tegra186_get_mc_ctx_offset
 
 /* set system suspend state before SC7 entry */
 func tegra186_set_system_suspend_entry
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/drivers/include/se.h b/plat/nvidia/tegra/soc/t194/drivers/include/se.h
index e7cf88d..7de55a7 100644
--- a/plat/nvidia/tegra/soc/t194/drivers/include/se.h
+++ b/plat/nvidia/tegra/soc/t194/drivers/include/se.h
@@ -7,6 +7,8 @@
 #ifndef SE_H
 #define SE_H
 
+int32_t tegra_se_calculate_save_sha256(uint64_t src_addr,
+						uint32_t src_len_inbyte);
 int32_t tegra_se_suspend(void);
 void tegra_se_resume(void);
 
diff --git a/plat/nvidia/tegra/soc/t194/drivers/se/se.c b/plat/nvidia/tegra/soc/t194/drivers/se/se.c
index a3b3389..ccdc94d 100644
--- a/plat/nvidia/tegra/soc/t194/drivers/se/se.c
+++ b/plat/nvidia/tegra/soc/t194/drivers/se/se.c
@@ -28,6 +28,14 @@
 #define MAX_TIMEOUT_MS		U(100)	/* Timeout in 100ms */
 #define NUM_SE_REGS_TO_SAVE	U(4)
 
+#define SE0_MAX_BUSY_TIMEOUT_MS		U(100)	/* 100ms Timeout Expired */
+#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)
+
 /*******************************************************************************
  * Data structure and global variables
  ******************************************************************************/
@@ -176,6 +184,270 @@
 }
 
 /*
+ * 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_sha256_hash_operation_complete(void)
+{
+	uint32_t val = 0U;
+
+	/* Poll the SE interrupt register to ensure H/W operation complete */
+	val = tegra_se_read_32(SE0_INT_STATUS_REG_OFFSET);
+	while (SE0_INT_OP_DONE(val) == SE0_INT_OP_DONE_CLEAR) {
+		val = tegra_se_read_32(SE0_INT_STATUS_REG_OFFSET);
+		if (SE0_INT_OP_DONE(val) != SE0_INT_OP_DONE_CLEAR) {
+			break;
+		}
+	}
+
+	/* Poll the SE status idle to ensure H/W operation complete */
+	val = tegra_se_read_32(SE0_SHA_STATUS_0);
+	while (val != SE0_SHA_STATUS_IDLE) {
+		val = tegra_se_read_32(SE0_SHA_STATUS_0);
+		if (val == SE0_SHA_STATUS_IDLE) {
+			break;
+		}
+	}
+
+	/* Ensure that no errors are thrown during operation */
+	val = tegra_se_read_32(SE0_ERR_STATUS_REG_OFFSET);
+	if (val != 0U) {
+		ERROR("%s: error during SE operation! 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)
+{
+	uint32_t val = 0U;
+	uint32_t src_in_lo;
+	uint32_t src_in_msb;
+	uint32_t src_in_hi;
+	int32_t ret = 0;
+
+	if ((src_addr == 0ULL) || (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 & MAX_SHA_ENGINE_CHUNK_SIZE));
+
+	/* 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, 0x0U);
+	}
+
+	/* 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);
+	}
+
+	return ret;
+}
+
+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 == 0ULL) {
+		return -EINVAL;
+	}
+
+	/* number of bytes per operation */
+	max_bytes = (SHA256_HASH_SIZE_BYTES * SHA256_MSG_LENGTH_ONETIME);
+
+	src_len_inbits = (uint32_t)(src_len_inbyte * 8U);
+	len_bits_msb = (uint32_t)(src_len_inbits >> 32U);
+	len_bits_lsb = (uint32_t)src_len_inbits;
+
+	/* program SE0_CONFIG for SHA256 operation */
+	val =  (uint32_t)(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;
+}
+
+static int32_t tegra_se_save_sha256_pmc_scratch(void)
+{
+	uint32_t val = 0U, hash_offset = 0U, scratch_offset = 0U;
+	int32_t ret;
+
+	/* Check SE0 operation status */
+	ret = tegra_se_sha256_hash_operation_complete();
+	if (ret != 0) {
+		ERROR("SE operation complete Failed! 0x%x", ret);
+		return ret;
+	}
+
+	for (scratch_offset = SECURE_SCRATCH_TZDRAM_SHA256_HASH_START;
+			scratch_offset <= SECURE_SCRATCH_TZDRAM_SHA256_HASH_END;
+					scratch_offset += BYTES_IN_WORD) {
+		val = tegra_se_read_32(SE0_SHA_HASH_RESULT_0 + hash_offset);
+		mmio_write_32((uint32_t)(TEGRA_SCRATCH_BASE + scratch_offset),
+									val);
+		hash_offset += BYTES_IN_WORD;
+	}
+	return 0;
+}
+
+/*
+ * Handler to generate SHA256 and save HASH-result to pmc-scratch register
+ */
+int32_t tegra_se_calculate_save_sha256(uint64_t src_addr,
+						uint32_t src_len_inbyte)
+{
+	uint32_t security;
+	int32_t val = 0;
+
+	/* 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);
+
+	/* Bootrom enable IN_ID bit in SE0_SHA_GSCID_0 register during SC7-exit, causing
+	 * SE0 ignores SE0 operation, and therefore failure of 2nd iteration of SC7 cycle.
+	 */
+	tegra_se_write_32(SE0_SHA_GSCID_0, 0x0U);
+
+	/* Calculate SHA256 of BL31 */
+	val = tegra_se_calculate_sha256_hash(src_addr, src_len_inbyte);
+	if (val != 0) {
+		ERROR("%s: SHA256 generation failed\n", __func__);
+		return val;
+	}
+
+	/*
+	 * Reset SE_SECURE to previous value.
+	 */
+	tegra_se_write_32(SE0_SECURITY, security);
+
+	/* copy sha256_dst to PMC Scratch register */
+	val = tegra_se_save_sha256_pmc_scratch();
+	if (val != 0) {
+		ERROR("%s: SE0 status Error.\n", __func__);
+	}
+
+	return val;
+}
+
+/*
  * Handler to power down the SE hardware blocks - SE, RNG1 and PKA1. This
  * needs to be called only during System Suspend.
  */
@@ -187,7 +459,7 @@
 	assert(tegra_bpmp_ipc_init() == 0);
 
 	/* Enable SE clock before SE context save */
-	ret = tegra_bpmp_ipc_enable_clock(TEGRA_CLK_SE);
+	ret = tegra_bpmp_ipc_enable_clock(TEGRA194_CLK_SE);
 	assert(ret == 0);
 
 	/* save SE registers */
@@ -203,7 +475,7 @@
 	}
 
 	/* Disable SE clock after SE context save */
-	ret = tegra_bpmp_ipc_disable_clock(TEGRA_CLK_SE);
+	ret = tegra_bpmp_ipc_disable_clock(TEGRA194_CLK_SE);
 	assert(ret == 0);
 
 	return ret;
@@ -220,7 +492,7 @@
 	assert(tegra_bpmp_ipc_init() == 0);
 
 	/* Enable SE clock before SE context restore */
-	ret = tegra_bpmp_ipc_enable_clock(TEGRA_CLK_SE);
+	ret = tegra_bpmp_ipc_enable_clock(TEGRA194_CLK_SE);
 	assert(ret == 0);
 
 	/*
@@ -235,6 +507,6 @@
 	mmio_write_32(TEGRA_PKA1_BASE + PKA1_MUTEX_WATCHDOG_NS_LIMIT, se_regs[3]);
 
 	/* Disable SE clock after SE context restore */
-	ret = tegra_bpmp_ipc_disable_clock(TEGRA_CLK_SE);
+	ret = tegra_bpmp_ipc_disable_clock(TEGRA194_CLK_SE);
 	assert(ret == 0);
 }
diff --git a/plat/nvidia/tegra/soc/t194/drivers/se/se_private.h b/plat/nvidia/tegra/soc/t194/drivers/se/se_private.h
index 577217b..fc118aa 100644
--- a/plat/nvidia/tegra/soc/t194/drivers/se/se_private.h
+++ b/plat/nvidia/tegra/soc/t194/drivers/se/se_private.h
@@ -9,6 +9,86 @@
 #define SE_PRIVATE_H
 
 #include <lib/utils_def.h>
+#include <tegra_def.h>
+
+/* SE0 security register */
+#define SE0_SECURITY				U(0x18)
+#define SE0_SECURITY_SE_SOFT_SETTING		(((uint32_t)1) << 16U)
+
+/* SE0 SHA GSCID register */
+#define SE0_SHA_GSCID_0				U(0x100)
+
+/* SE0 config register */
+#define SE0_SHA_CONFIG				U(0x104)
+#define SE0_SHA_TASK_CONFIG			U(0x108)
+#define SE0_SHA_CONFIG_HW_INIT_HASH		(((uint32_t)1) << 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_IN_ADDR				U(0x10c)
+#define SE0_IN_HI_ADDR_HI			U(0x110)
+#define SE0_IN_HI_ADDR_HI_0_MSB_SHIFT		U(24)
+
+/* 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)0U) << SE0_INT_OP_DONE_SHIFT)
+#define SE0_INT_OP_DONE(x)	\
+		((x) & (((uint32_t)0x1U) << 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)
+
+/* SE error status */
+#define SECURE_SCRATCH_TZDRAM_SHA256_HASH_START	SECURE_SCRATCH_RSV68_LO
+#define SECURE_SCRATCH_TZDRAM_SHA256_HASH_END	SECURE_SCRATCH_RSV71_HI
 
 /* SE0_INT_ENABLE_0 */
 #define SE0_INT_ENABLE				U(0x88)
@@ -20,7 +100,7 @@
 
 /* SE0_SHA_INT_STATUS_0 */
 #define SHA_INT_STATUS				U(0x184)
-#define  SHA_SE_OP_DONE				(U(1) << 4)
+#define SHA_SE_OP_DONE				(U(1) << 4)
 
 /* SE0_SHA_ERR_STATUS_0 */
 #define SHA_ERR_STATUS				U(0x18C)
diff --git a/plat/nvidia/tegra/soc/t194/plat_memctrl.c b/plat/nvidia/tegra/soc/t194/plat_memctrl.c
index 2208b85..2d5f8e3 100644
--- a/plat/nvidia/tegra/soc/t194/plat_memctrl.c
+++ b/plat/nvidia/tegra/soc/t194/plat_memctrl.c
@@ -15,12 +15,15 @@
  * Array to hold stream_id override config register offsets
  ******************************************************************************/
 const static uint32_t tegra194_streamid_override_regs[] = {
+	MC_STREAMID_OVERRIDE_CFG_PTCR,
 	MC_STREAMID_OVERRIDE_CFG_HDAR,
 	MC_STREAMID_OVERRIDE_CFG_HOST1XDMAR,
 	MC_STREAMID_OVERRIDE_CFG_NVENCSRD,
 	MC_STREAMID_OVERRIDE_CFG_SATAR,
+	MC_STREAMID_OVERRIDE_CFG_MPCORER,
 	MC_STREAMID_OVERRIDE_CFG_NVENCSWR,
 	MC_STREAMID_OVERRIDE_CFG_HDAW,
+	MC_STREAMID_OVERRIDE_CFG_MPCOREW,
 	MC_STREAMID_OVERRIDE_CFG_SATAW,
 	MC_STREAMID_OVERRIDE_CFG_ISPRA,
 	MC_STREAMID_OVERRIDE_CFG_ISPFALR,
@@ -131,6 +134,9 @@
 	MC_STREAMID_OVERRIDE_CFG_NVENC1SRD1,
 	MC_STREAMID_OVERRIDE_CFG_ISPRA1,
 	MC_STREAMID_OVERRIDE_CFG_PCIE0R1,
+	MC_STREAMID_OVERRIDE_CFG_NVDEC1SRD,
+	MC_STREAMID_OVERRIDE_CFG_NVDEC1SRD1,
+	MC_STREAMID_OVERRIDE_CFG_NVDEC1SWR,
 	MC_STREAMID_OVERRIDE_CFG_MIU0R,
 	MC_STREAMID_OVERRIDE_CFG_MIU0W,
 	MC_STREAMID_OVERRIDE_CFG_MIU1R,
@@ -138,19 +144,30 @@
 	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,
+	MC_STREAMID_OVERRIDE_CFG_MIU6R,
+	MC_STREAMID_OVERRIDE_CFG_MIU6W,
+	MC_STREAMID_OVERRIDE_CFG_MIU7R,
+	MC_STREAMID_OVERRIDE_CFG_MIU7W
 };
 
 /*******************************************************************************
  * Array to hold the security configs for stream IDs
  ******************************************************************************/
 const static mc_streamid_security_cfg_t tegra194_streamid_sec_cfgs[] = {
+	mc_make_sec_cfg(PTCR, NON_SECURE, OVERRIDE, DISABLE),
 	mc_make_sec_cfg(HDAR, NON_SECURE, OVERRIDE, DISABLE),
 	mc_make_sec_cfg(HOST1XDMAR, NON_SECURE, NO_OVERRIDE, DISABLE),
 	mc_make_sec_cfg(NVENCSRD, NON_SECURE, NO_OVERRIDE, DISABLE),
 	mc_make_sec_cfg(SATAR, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(MPCORER, NON_SECURE, OVERRIDE, DISABLE),
 	mc_make_sec_cfg(NVENCSWR, NON_SECURE, NO_OVERRIDE, DISABLE),
 	mc_make_sec_cfg(HDAW, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(MPCOREW, NON_SECURE, OVERRIDE, DISABLE),
 	mc_make_sec_cfg(SATAW, NON_SECURE, OVERRIDE, DISABLE),
 	mc_make_sec_cfg(ISPRA, NON_SECURE, NO_OVERRIDE, ENABLE),
 	mc_make_sec_cfg(ISPFALR, NON_SECURE, NO_OVERRIDE, ENABLE),
@@ -261,6 +278,9 @@
 	mc_make_sec_cfg(NVENC1SRD1, NON_SECURE, NO_OVERRIDE, DISABLE),
 	mc_make_sec_cfg(ISPRA1, NON_SECURE, NO_OVERRIDE, ENABLE),
 	mc_make_sec_cfg(PCIE0R1, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(NVDEC1SRD, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(NVDEC1SRD1, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(NVDEC1SWR, NON_SECURE, NO_OVERRIDE, DISABLE),
 	mc_make_sec_cfg(MIU0R, NON_SECURE, OVERRIDE, DISABLE),
 	mc_make_sec_cfg(MIU0W, NON_SECURE, OVERRIDE, DISABLE),
 	mc_make_sec_cfg(MIU1R, NON_SECURE, OVERRIDE, DISABLE),
@@ -268,414 +288,283 @@
 	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),
+	mc_make_sec_cfg(MIU6R, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(MIU6W, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(MIU7R, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(MIU7W, NON_SECURE, OVERRIDE, DISABLE)
 };
 
-/* To be called by common memctrl_v2.c */
-static void tegra194_memctrl_reconfig_mss_clients(void)
+/*******************************************************************************
+ * Array to hold MC context for Tegra194
+ ******************************************************************************/
+static __attribute__((aligned(16))) mc_regs_t tegra194_mc_context[] = {
+	_START_OF_TABLE_,
+	mc_make_sid_security_cfg(HDAR),
+	mc_make_sid_security_cfg(HOST1XDMAR),
+	mc_make_sid_security_cfg(NVENCSRD),
+	mc_make_sid_security_cfg(SATAR),
+	mc_make_sid_security_cfg(NVENCSWR),
+	mc_make_sid_security_cfg(HDAW),
+	mc_make_sid_security_cfg(SATAW),
+	mc_make_sid_security_cfg(ISPRA),
+	mc_make_sid_security_cfg(ISPFALR),
+	mc_make_sid_security_cfg(ISPWA),
+	mc_make_sid_security_cfg(ISPWB),
+	mc_make_sid_security_cfg(XUSB_HOSTR),
+	mc_make_sid_security_cfg(XUSB_HOSTW),
+	mc_make_sid_security_cfg(XUSB_DEVR),
+	mc_make_sid_security_cfg(XUSB_DEVW),
+	mc_make_sid_security_cfg(TSECSRD),
+	mc_make_sid_security_cfg(TSECSWR),
+	mc_make_sid_security_cfg(SDMMCRA),
+	mc_make_sid_security_cfg(SDMMCR),
+	mc_make_sid_security_cfg(SDMMCRAB),
+	mc_make_sid_security_cfg(SDMMCWA),
+	mc_make_sid_security_cfg(SDMMCW),
+	mc_make_sid_security_cfg(SDMMCWAB),
+	mc_make_sid_security_cfg(VICSRD),
+	mc_make_sid_security_cfg(VICSWR),
+	mc_make_sid_security_cfg(VIW),
+	mc_make_sid_security_cfg(NVDECSRD),
+	mc_make_sid_security_cfg(NVDECSWR),
+	mc_make_sid_security_cfg(APER),
+	mc_make_sid_security_cfg(APEW),
+	mc_make_sid_security_cfg(NVJPGSRD),
+	mc_make_sid_security_cfg(NVJPGSWR),
+	mc_make_sid_security_cfg(SESRD),
+	mc_make_sid_security_cfg(SESWR),
+	mc_make_sid_security_cfg(AXIAPR),
+	mc_make_sid_security_cfg(AXIAPW),
+	mc_make_sid_security_cfg(ETRR),
+	mc_make_sid_security_cfg(ETRW),
+	mc_make_sid_security_cfg(TSECSRDB),
+	mc_make_sid_security_cfg(TSECSWRB),
+	mc_make_sid_security_cfg(AXISR),
+	mc_make_sid_security_cfg(AXISW),
+	mc_make_sid_security_cfg(EQOSR),
+	mc_make_sid_security_cfg(EQOSW),
+	mc_make_sid_security_cfg(UFSHCR),
+	mc_make_sid_security_cfg(UFSHCW),
+	mc_make_sid_security_cfg(NVDISPLAYR),
+	mc_make_sid_security_cfg(BPMPR),
+	mc_make_sid_security_cfg(BPMPW),
+	mc_make_sid_security_cfg(BPMPDMAR),
+	mc_make_sid_security_cfg(BPMPDMAW),
+	mc_make_sid_security_cfg(AONR),
+	mc_make_sid_security_cfg(AONW),
+	mc_make_sid_security_cfg(AONDMAR),
+	mc_make_sid_security_cfg(AONDMAW),
+	mc_make_sid_security_cfg(SCER),
+	mc_make_sid_security_cfg(SCEW),
+	mc_make_sid_security_cfg(SCEDMAR),
+	mc_make_sid_security_cfg(SCEDMAW),
+	mc_make_sid_security_cfg(APEDMAR),
+	mc_make_sid_security_cfg(APEDMAW),
+	mc_make_sid_security_cfg(NVDISPLAYR1),
+	mc_make_sid_security_cfg(VICSRD1),
+	mc_make_sid_security_cfg(NVDECSRD1),
+	mc_make_sid_security_cfg(VIFALR),
+	mc_make_sid_security_cfg(VIFALW),
+	mc_make_sid_security_cfg(DLA0RDA),
+	mc_make_sid_security_cfg(DLA0FALRDB),
+	mc_make_sid_security_cfg(DLA0WRA),
+	mc_make_sid_security_cfg(DLA0FALWRB),
+	mc_make_sid_security_cfg(DLA1RDA),
+	mc_make_sid_security_cfg(DLA1FALRDB),
+	mc_make_sid_security_cfg(DLA1WRA),
+	mc_make_sid_security_cfg(DLA1FALWRB),
+	mc_make_sid_security_cfg(PVA0RDA),
+	mc_make_sid_security_cfg(PVA0RDB),
+	mc_make_sid_security_cfg(PVA0RDC),
+	mc_make_sid_security_cfg(PVA0WRA),
+	mc_make_sid_security_cfg(PVA0WRB),
+	mc_make_sid_security_cfg(PVA0WRC),
+	mc_make_sid_security_cfg(PVA1RDA),
+	mc_make_sid_security_cfg(PVA1RDB),
+	mc_make_sid_security_cfg(PVA1RDC),
+	mc_make_sid_security_cfg(PVA1WRA),
+	mc_make_sid_security_cfg(PVA1WRB),
+	mc_make_sid_security_cfg(PVA1WRC),
+	mc_make_sid_security_cfg(RCER),
+	mc_make_sid_security_cfg(RCEW),
+	mc_make_sid_security_cfg(RCEDMAR),
+	mc_make_sid_security_cfg(RCEDMAW),
+	mc_make_sid_security_cfg(NVENC1SRD),
+	mc_make_sid_security_cfg(NVENC1SWR),
+	mc_make_sid_security_cfg(PCIE0R),
+	mc_make_sid_security_cfg(PCIE0W),
+	mc_make_sid_security_cfg(PCIE1R),
+	mc_make_sid_security_cfg(PCIE1W),
+	mc_make_sid_security_cfg(PCIE2AR),
+	mc_make_sid_security_cfg(PCIE2AW),
+	mc_make_sid_security_cfg(PCIE3R),
+	mc_make_sid_security_cfg(PCIE3W),
+	mc_make_sid_security_cfg(PCIE4R),
+	mc_make_sid_security_cfg(PCIE4W),
+	mc_make_sid_security_cfg(PCIE5R),
+	mc_make_sid_security_cfg(PCIE5W),
+	mc_make_sid_security_cfg(ISPFALW),
+	mc_make_sid_security_cfg(DLA0RDA1),
+	mc_make_sid_security_cfg(DLA1RDA1),
+	mc_make_sid_security_cfg(PVA0RDA1),
+	mc_make_sid_security_cfg(PVA0RDB1),
+	mc_make_sid_security_cfg(PVA1RDA1),
+	mc_make_sid_security_cfg(PVA1RDB1),
+	mc_make_sid_security_cfg(PCIE5R1),
+	mc_make_sid_security_cfg(NVENCSRD1),
+	mc_make_sid_security_cfg(NVENC1SRD1),
+	mc_make_sid_security_cfg(ISPRA1),
+	mc_make_sid_security_cfg(PCIE0R1),
+	mc_make_sid_security_cfg(MIU0R),
+	mc_make_sid_security_cfg(MIU0W),
+	mc_make_sid_security_cfg(MIU1R),
+	mc_make_sid_security_cfg(MIU1W),
+	mc_make_sid_security_cfg(MIU2R),
+	mc_make_sid_security_cfg(MIU2W),
+	mc_make_sid_security_cfg(MIU3R),
+	mc_make_sid_security_cfg(MIU3W),
+	mc_make_sid_override_cfg(HDAR),
+	mc_make_sid_override_cfg(HOST1XDMAR),
+	mc_make_sid_override_cfg(NVENCSRD),
+	mc_make_sid_override_cfg(SATAR),
+	mc_make_sid_override_cfg(NVENCSWR),
+	mc_make_sid_override_cfg(HDAW),
+	mc_make_sid_override_cfg(SATAW),
+	mc_make_sid_override_cfg(ISPRA),
+	mc_make_sid_override_cfg(ISPFALR),
+	mc_make_sid_override_cfg(ISPWA),
+	mc_make_sid_override_cfg(ISPWB),
+	mc_make_sid_override_cfg(XUSB_HOSTR),
+	mc_make_sid_override_cfg(XUSB_HOSTW),
+	mc_make_sid_override_cfg(XUSB_DEVR),
+	mc_make_sid_override_cfg(XUSB_DEVW),
+	mc_make_sid_override_cfg(TSECSRD),
+	mc_make_sid_override_cfg(TSECSWR),
+	mc_make_sid_override_cfg(SDMMCRA),
+	mc_make_sid_override_cfg(SDMMCR),
+	mc_make_sid_override_cfg(SDMMCRAB),
+	mc_make_sid_override_cfg(SDMMCWA),
+	mc_make_sid_override_cfg(SDMMCW),
+	mc_make_sid_override_cfg(SDMMCWAB),
+	mc_make_sid_override_cfg(VICSRD),
+	mc_make_sid_override_cfg(VICSWR),
+	mc_make_sid_override_cfg(VIW),
+	mc_make_sid_override_cfg(NVDECSRD),
+	mc_make_sid_override_cfg(NVDECSWR),
+	mc_make_sid_override_cfg(APER),
+	mc_make_sid_override_cfg(APEW),
+	mc_make_sid_override_cfg(NVJPGSRD),
+	mc_make_sid_override_cfg(NVJPGSWR),
+	mc_make_sid_override_cfg(SESRD),
+	mc_make_sid_override_cfg(SESWR),
+	mc_make_sid_override_cfg(AXIAPR),
+	mc_make_sid_override_cfg(AXIAPW),
+	mc_make_sid_override_cfg(ETRR),
+	mc_make_sid_override_cfg(ETRW),
+	mc_make_sid_override_cfg(TSECSRDB),
+	mc_make_sid_override_cfg(TSECSWRB),
+	mc_make_sid_override_cfg(AXISR),
+	mc_make_sid_override_cfg(AXISW),
+	mc_make_sid_override_cfg(EQOSR),
+	mc_make_sid_override_cfg(EQOSW),
+	mc_make_sid_override_cfg(UFSHCR),
+	mc_make_sid_override_cfg(UFSHCW),
+	mc_make_sid_override_cfg(NVDISPLAYR),
+	mc_make_sid_override_cfg(BPMPR),
+	mc_make_sid_override_cfg(BPMPW),
+	mc_make_sid_override_cfg(BPMPDMAR),
+	mc_make_sid_override_cfg(BPMPDMAW),
+	mc_make_sid_override_cfg(AONR),
+	mc_make_sid_override_cfg(AONW),
+	mc_make_sid_override_cfg(AONDMAR),
+	mc_make_sid_override_cfg(AONDMAW),
+	mc_make_sid_override_cfg(SCER),
+	mc_make_sid_override_cfg(SCEW),
+	mc_make_sid_override_cfg(SCEDMAR),
+	mc_make_sid_override_cfg(SCEDMAW),
+	mc_make_sid_override_cfg(APEDMAR),
+	mc_make_sid_override_cfg(APEDMAW),
+	mc_make_sid_override_cfg(NVDISPLAYR1),
+	mc_make_sid_override_cfg(VICSRD1),
+	mc_make_sid_override_cfg(NVDECSRD1),
+	mc_make_sid_override_cfg(VIFALR),
+	mc_make_sid_override_cfg(VIFALW),
+	mc_make_sid_override_cfg(DLA0RDA),
+	mc_make_sid_override_cfg(DLA0FALRDB),
+	mc_make_sid_override_cfg(DLA0WRA),
+	mc_make_sid_override_cfg(DLA0FALWRB),
+	mc_make_sid_override_cfg(DLA1RDA),
+	mc_make_sid_override_cfg(DLA1FALRDB),
+	mc_make_sid_override_cfg(DLA1WRA),
+	mc_make_sid_override_cfg(DLA1FALWRB),
+	mc_make_sid_override_cfg(PVA0RDA),
+	mc_make_sid_override_cfg(PVA0RDB),
+	mc_make_sid_override_cfg(PVA0RDC),
+	mc_make_sid_override_cfg(PVA0WRA),
+	mc_make_sid_override_cfg(PVA0WRB),
+	mc_make_sid_override_cfg(PVA0WRC),
+	mc_make_sid_override_cfg(PVA1RDA),
+	mc_make_sid_override_cfg(PVA1RDB),
+	mc_make_sid_override_cfg(PVA1RDC),
+	mc_make_sid_override_cfg(PVA1WRA),
+	mc_make_sid_override_cfg(PVA1WRB),
+	mc_make_sid_override_cfg(PVA1WRC),
+	mc_make_sid_override_cfg(RCER),
+	mc_make_sid_override_cfg(RCEW),
+	mc_make_sid_override_cfg(RCEDMAR),
+	mc_make_sid_override_cfg(RCEDMAW),
+	mc_make_sid_override_cfg(NVENC1SRD),
+	mc_make_sid_override_cfg(NVENC1SWR),
+	mc_make_sid_override_cfg(PCIE0R),
+	mc_make_sid_override_cfg(PCIE0W),
+	mc_make_sid_override_cfg(PCIE1R),
+	mc_make_sid_override_cfg(PCIE1W),
+	mc_make_sid_override_cfg(PCIE2AR),
+	mc_make_sid_override_cfg(PCIE2AW),
+	mc_make_sid_override_cfg(PCIE3R),
+	mc_make_sid_override_cfg(PCIE3W),
+	mc_make_sid_override_cfg(PCIE4R),
+	mc_make_sid_override_cfg(PCIE4W),
+	mc_make_sid_override_cfg(PCIE5R),
+	mc_make_sid_override_cfg(PCIE5W),
+	mc_make_sid_override_cfg(ISPFALW),
+	mc_make_sid_override_cfg(DLA0RDA1),
+	mc_make_sid_override_cfg(DLA1RDA1),
+	mc_make_sid_override_cfg(PVA0RDA1),
+	mc_make_sid_override_cfg(PVA0RDB1),
+	mc_make_sid_override_cfg(PVA1RDA1),
+	mc_make_sid_override_cfg(PVA1RDB1),
+	mc_make_sid_override_cfg(PCIE5R1),
+	mc_make_sid_override_cfg(NVENCSRD1),
+	mc_make_sid_override_cfg(NVENC1SRD1),
+	mc_make_sid_override_cfg(ISPRA1),
+	mc_make_sid_override_cfg(PCIE0R1),
+	mc_make_sid_override_cfg(MIU0R),
+	mc_make_sid_override_cfg(MIU0W),
+	mc_make_sid_override_cfg(MIU1R),
+	mc_make_sid_override_cfg(MIU1W),
+	mc_make_sid_override_cfg(MIU2R),
+	mc_make_sid_override_cfg(MIU2W),
+	mc_make_sid_override_cfg(MIU3R),
+	mc_make_sid_override_cfg(MIU3W),
+	mc_smmu_bypass_cfg,	/* TBU settings */
+	_END_OF_TABLE_,
+};
+
+/*******************************************************************************
+ * Handler to return the pointer to the MC's context struct
+ ******************************************************************************/
+static mc_regs_t *tegra194_get_mc_system_suspend_ctx(void)
 {
-	uint32_t reg_val, wdata_0, wdata_1, wdata_2;
+	/* index of _END_OF_TABLE_ */
+	tegra194_mc_context[0].val = (uint32_t)ARRAY_SIZE(tegra194_mc_context) - 1U;
 
-	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);
+	return tegra194_mc_context;
 }
 
 /*******************************************************************************
@@ -686,7 +575,7 @@
 	.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
+	.get_mc_system_suspend_ctx = tegra194_get_mc_system_suspend_ctx
 };
 
 /*******************************************************************************
diff --git a/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c
index 144e418..d92025b 100644
--- a/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c
+++ b/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c
@@ -10,14 +10,17 @@
 #include <string.h>
 
 #include <arch_helpers.h>
+#include <bpmp_ipc.h>
 #include <common/bl_common.h>
 #include <common/debug.h>
 #include <context.h>
+#include <drivers/delay_timer.h>
 #include <denver.h>
 #include <lib/el3_runtime/context_mgmt.h>
 #include <lib/psci/psci.h>
 #include <mce.h>
 #include <mce_private.h>
+#include <memctrl_v2.h>
 #include <plat/common/platform.h>
 #include <se.h>
 #include <smmu.h>
@@ -116,7 +119,7 @@
 	const plat_local_state_t *pwr_domain_state;
 	uint8_t stateid_afflvl0, stateid_afflvl2;
 	plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params();
-	uint64_t smmu_ctx_base;
+	uint64_t mc_ctx_base;
 	uint32_t val;
 	mce_cstate_info_t sc7_cstate_info = {
 		.cluster = (uint32_t)TEGRA_NVG_CLUSTER_CC6,
@@ -135,7 +138,7 @@
 	stateid_afflvl2 = pwr_domain_state[PLAT_MAX_PWR_LVL] &
 		TEGRA194_STATE_ID_MASK;
 
-	if ((stateid_afflvl0 == PSTATE_ID_CORE_POWERDN)) {
+	if (stateid_afflvl0 == PSTATE_ID_CORE_POWERDN) {
 
 		/* Enter CPU powerdown */
 		(void)mce_command_handler((uint64_t)MCE_CMD_ENTER_CSTATE,
@@ -149,10 +152,10 @@
 		val = mmio_read_32(TEGRA_MISC_BASE + MISCREG_PFCFG);
 		mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_SECURE_BOOTP_FCFG, val);
 
-		/* save SMMU context */
-		smmu_ctx_base = params_from_bl2->tzdram_base +
-				tegra194_get_smmu_ctx_offset();
-		tegra_smmu_save_context((uintptr_t)smmu_ctx_base);
+		/* save MC context */
+		mc_ctx_base = params_from_bl2->tzdram_base +
+				tegra194_get_mc_ctx_offset();
+		tegra_mc_save_context((uintptr_t)mc_ctx_base);
 
 		/*
 		 * Suspend SE, RNG1 and PKA1 only on silcon and fpga,
@@ -289,9 +292,34 @@
 	plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params();
 	uint8_t stateid_afflvl2 = pwr_domain_state[PLAT_MAX_PWR_LVL] &
 		TEGRA194_STATE_ID_MASK;
+	uint64_t src_len_in_bytes = (uintptr_t)&__BL31_END__ - (uintptr_t)BL31_BASE;
 	uint64_t val;
+	int32_t ret = PSCI_E_SUCCESS;
 
 	if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) {
+		val = params_from_bl2->tzdram_base +
+		      tegra194_get_cpu_reset_handler_size();
+
+		/* initialise communication channel with BPMP */
+		ret = tegra_bpmp_ipc_init();
+		assert(ret == 0);
+
+		/* Enable SE clock before SE context save */
+		ret = tegra_bpmp_ipc_enable_clock(TEGRA194_CLK_SE);
+		assert(ret == 0);
+
+		/*
+		 * It is very unlikely that the BL31 image would be
+		 * bigger than 2^32 bytes
+		 */
+		assert(src_len_in_bytes < UINT32_MAX);
+
+		if (tegra_se_calculate_save_sha256(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
@@ -300,10 +328,14 @@
 		val = params_from_bl2->tzdram_base +
 		      tegra194_get_cpu_reset_handler_size();
 		memcpy((void *)(uintptr_t)val, (void *)(uintptr_t)BL31_BASE,
-		       (uintptr_t)&__BL31_END__ - (uintptr_t)BL31_BASE);
+		       src_len_in_bytes);
+
+		/* Disable SE clock after SE context save */
+		ret = tegra_bpmp_ipc_disable_clock(TEGRA194_CLK_SE);
+		assert(ret == 0);
 	}
 
-	return PSCI_E_SUCCESS;
+	return ret;
 }
 
 int32_t tegra_soc_pwr_domain_suspend_pwrdown_early(const psci_power_state_t *target_state)
diff --git a/plat/nvidia/tegra/soc/t194/plat_secondary.c b/plat/nvidia/tegra/soc/t194/plat_secondary.c
index c397c91..0882142 100644
--- a/plat/nvidia/tegra/soc/t194/plat_secondary.c
+++ b/plat/nvidia/tegra/soc/t194/plat_secondary.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -13,6 +13,8 @@
 #include <tegra_def.h>
 #include <tegra_private.h>
 
+extern uint64_t tegra_bl31_phys_base;
+
 #define MISCREG_AA64_RST_LOW		0x2004U
 #define MISCREG_AA64_RST_HIGH		0x2008U
 
@@ -25,10 +27,14 @@
 {
 	uint32_t addr_low, addr_high;
 	plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params();
-	uint64_t cpu_reset_handler_base, cpu_reset_handler_size;
+	uint64_t cpu_reset_handler_base, cpu_reset_handler_size, tzdram_addr;
+	uint64_t src_len_bytes = BL_END - tegra_bl31_phys_base;
 
 	INFO("Setting up secondary CPU boot\n");
 
+	tzdram_addr = params_from_bl2->tzdram_base +
+		      tegra194_get_cpu_reset_handler_size();
+
 	/*
 	 * The BL31 code resides in the TZSRAM which loses state
 	 * when we enter System Suspend. Copy the wakeup trampoline
@@ -53,4 +59,8 @@
 			addr_low);
 	mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_RESET_VECTOR_HI,
 			addr_high);
+	mmio_write_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV72_LO,
+						(uint32_t)tzdram_addr);
+	mmio_write_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV72_HI,
+						(uint32_t)src_len_bytes);
 }
diff --git a/plat/nvidia/tegra/soc/t194/plat_smmu.c b/plat/nvidia/tegra/soc/t194/plat_smmu.c
index 3b4a380..310e951 100644
--- a/plat/nvidia/tegra/soc/t194/plat_smmu.c
+++ b/plat/nvidia/tegra/soc/t194/plat_smmu.c
@@ -8,7 +8,6 @@
 #include <common/debug.h>
 #include <smmu.h>
 #include <tegra_def.h>
-#include <tegra_mc_def.h>
 
 #define BOARD_SYSTEM_FPGA_BASE		U(1)
 #define BASE_CONFIG_SMMU_DEVICES	U(2)
@@ -20,276 +19,6 @@
 }
 
 /*******************************************************************************
- * Array to hold SMMU context for Tegra194
- ******************************************************************************/
-static __attribute__((aligned(16))) smmu_regs_t tegra194_smmu_context[] = {
-	_START_OF_TABLE_,
-	mc_make_sid_security_cfg(HDAR),
-	mc_make_sid_security_cfg(HOST1XDMAR),
-	mc_make_sid_security_cfg(NVENCSRD),
-	mc_make_sid_security_cfg(SATAR),
-	mc_make_sid_security_cfg(NVENCSWR),
-	mc_make_sid_security_cfg(HDAW),
-	mc_make_sid_security_cfg(SATAW),
-	mc_make_sid_security_cfg(ISPRA),
-	mc_make_sid_security_cfg(ISPFALR),
-	mc_make_sid_security_cfg(ISPWA),
-	mc_make_sid_security_cfg(ISPWB),
-	mc_make_sid_security_cfg(XUSB_HOSTR),
-	mc_make_sid_security_cfg(XUSB_HOSTW),
-	mc_make_sid_security_cfg(XUSB_DEVR),
-	mc_make_sid_security_cfg(XUSB_DEVW),
-	mc_make_sid_security_cfg(TSECSRD),
-	mc_make_sid_security_cfg(TSECSWR),
-	mc_make_sid_security_cfg(SDMMCRA),
-	mc_make_sid_security_cfg(SDMMCR),
-	mc_make_sid_security_cfg(SDMMCRAB),
-	mc_make_sid_security_cfg(SDMMCWA),
-	mc_make_sid_security_cfg(SDMMCW),
-	mc_make_sid_security_cfg(SDMMCWAB),
-	mc_make_sid_security_cfg(VICSRD),
-	mc_make_sid_security_cfg(VICSWR),
-	mc_make_sid_security_cfg(VIW),
-	mc_make_sid_security_cfg(NVDECSRD),
-	mc_make_sid_security_cfg(NVDECSWR),
-	mc_make_sid_security_cfg(APER),
-	mc_make_sid_security_cfg(APEW),
-	mc_make_sid_security_cfg(NVJPGSRD),
-	mc_make_sid_security_cfg(NVJPGSWR),
-	mc_make_sid_security_cfg(SESRD),
-	mc_make_sid_security_cfg(SESWR),
-	mc_make_sid_security_cfg(AXIAPR),
-	mc_make_sid_security_cfg(AXIAPW),
-	mc_make_sid_security_cfg(ETRR),
-	mc_make_sid_security_cfg(ETRW),
-	mc_make_sid_security_cfg(TSECSRDB),
-	mc_make_sid_security_cfg(TSECSWRB),
-	mc_make_sid_security_cfg(AXISR),
-	mc_make_sid_security_cfg(AXISW),
-	mc_make_sid_security_cfg(EQOSR),
-	mc_make_sid_security_cfg(EQOSW),
-	mc_make_sid_security_cfg(UFSHCR),
-	mc_make_sid_security_cfg(UFSHCW),
-	mc_make_sid_security_cfg(NVDISPLAYR),
-	mc_make_sid_security_cfg(BPMPR),
-	mc_make_sid_security_cfg(BPMPW),
-	mc_make_sid_security_cfg(BPMPDMAR),
-	mc_make_sid_security_cfg(BPMPDMAW),
-	mc_make_sid_security_cfg(AONR),
-	mc_make_sid_security_cfg(AONW),
-	mc_make_sid_security_cfg(AONDMAR),
-	mc_make_sid_security_cfg(AONDMAW),
-	mc_make_sid_security_cfg(SCER),
-	mc_make_sid_security_cfg(SCEW),
-	mc_make_sid_security_cfg(SCEDMAR),
-	mc_make_sid_security_cfg(SCEDMAW),
-	mc_make_sid_security_cfg(APEDMAR),
-	mc_make_sid_security_cfg(APEDMAW),
-	mc_make_sid_security_cfg(NVDISPLAYR1),
-	mc_make_sid_security_cfg(VICSRD1),
-	mc_make_sid_security_cfg(NVDECSRD1),
-	mc_make_sid_security_cfg(VIFALR),
-	mc_make_sid_security_cfg(VIFALW),
-	mc_make_sid_security_cfg(DLA0RDA),
-	mc_make_sid_security_cfg(DLA0FALRDB),
-	mc_make_sid_security_cfg(DLA0WRA),
-	mc_make_sid_security_cfg(DLA0FALWRB),
-	mc_make_sid_security_cfg(DLA1RDA),
-	mc_make_sid_security_cfg(DLA1FALRDB),
-	mc_make_sid_security_cfg(DLA1WRA),
-	mc_make_sid_security_cfg(DLA1FALWRB),
-	mc_make_sid_security_cfg(PVA0RDA),
-	mc_make_sid_security_cfg(PVA0RDB),
-	mc_make_sid_security_cfg(PVA0RDC),
-	mc_make_sid_security_cfg(PVA0WRA),
-	mc_make_sid_security_cfg(PVA0WRB),
-	mc_make_sid_security_cfg(PVA0WRC),
-	mc_make_sid_security_cfg(PVA1RDA),
-	mc_make_sid_security_cfg(PVA1RDB),
-	mc_make_sid_security_cfg(PVA1RDC),
-	mc_make_sid_security_cfg(PVA1WRA),
-	mc_make_sid_security_cfg(PVA1WRB),
-	mc_make_sid_security_cfg(PVA1WRC),
-	mc_make_sid_security_cfg(RCER),
-	mc_make_sid_security_cfg(RCEW),
-	mc_make_sid_security_cfg(RCEDMAR),
-	mc_make_sid_security_cfg(RCEDMAW),
-	mc_make_sid_security_cfg(NVENC1SRD),
-	mc_make_sid_security_cfg(NVENC1SWR),
-	mc_make_sid_security_cfg(PCIE0R),
-	mc_make_sid_security_cfg(PCIE0W),
-	mc_make_sid_security_cfg(PCIE1R),
-	mc_make_sid_security_cfg(PCIE1W),
-	mc_make_sid_security_cfg(PCIE2AR),
-	mc_make_sid_security_cfg(PCIE2AW),
-	mc_make_sid_security_cfg(PCIE3R),
-	mc_make_sid_security_cfg(PCIE3W),
-	mc_make_sid_security_cfg(PCIE4R),
-	mc_make_sid_security_cfg(PCIE4W),
-	mc_make_sid_security_cfg(PCIE5R),
-	mc_make_sid_security_cfg(PCIE5W),
-	mc_make_sid_security_cfg(ISPFALW),
-	mc_make_sid_security_cfg(DLA0RDA1),
-	mc_make_sid_security_cfg(DLA1RDA1),
-	mc_make_sid_security_cfg(PVA0RDA1),
-	mc_make_sid_security_cfg(PVA0RDB1),
-	mc_make_sid_security_cfg(PVA1RDA1),
-	mc_make_sid_security_cfg(PVA1RDB1),
-	mc_make_sid_security_cfg(PCIE5R1),
-	mc_make_sid_security_cfg(NVENCSRD1),
-	mc_make_sid_security_cfg(NVENC1SRD1),
-	mc_make_sid_security_cfg(ISPRA1),
-	mc_make_sid_security_cfg(PCIE0R1),
-	mc_make_sid_security_cfg(MIU0R),
-	mc_make_sid_security_cfg(MIU0W),
-	mc_make_sid_security_cfg(MIU1R),
-	mc_make_sid_security_cfg(MIU1W),
-	mc_make_sid_security_cfg(MIU2R),
-	mc_make_sid_security_cfg(MIU2W),
-	mc_make_sid_security_cfg(MIU3R),
-	mc_make_sid_security_cfg(MIU3W),
-	mc_make_sid_override_cfg(HDAR),
-	mc_make_sid_override_cfg(HOST1XDMAR),
-	mc_make_sid_override_cfg(NVENCSRD),
-	mc_make_sid_override_cfg(SATAR),
-	mc_make_sid_override_cfg(NVENCSWR),
-	mc_make_sid_override_cfg(HDAW),
-	mc_make_sid_override_cfg(SATAW),
-	mc_make_sid_override_cfg(ISPRA),
-	mc_make_sid_override_cfg(ISPFALR),
-	mc_make_sid_override_cfg(ISPWA),
-	mc_make_sid_override_cfg(ISPWB),
-	mc_make_sid_override_cfg(XUSB_HOSTR),
-	mc_make_sid_override_cfg(XUSB_HOSTW),
-	mc_make_sid_override_cfg(XUSB_DEVR),
-	mc_make_sid_override_cfg(XUSB_DEVW),
-	mc_make_sid_override_cfg(TSECSRD),
-	mc_make_sid_override_cfg(TSECSWR),
-	mc_make_sid_override_cfg(SDMMCRA),
-	mc_make_sid_override_cfg(SDMMCR),
-	mc_make_sid_override_cfg(SDMMCRAB),
-	mc_make_sid_override_cfg(SDMMCWA),
-	mc_make_sid_override_cfg(SDMMCW),
-	mc_make_sid_override_cfg(SDMMCWAB),
-	mc_make_sid_override_cfg(VICSRD),
-	mc_make_sid_override_cfg(VICSWR),
-	mc_make_sid_override_cfg(VIW),
-	mc_make_sid_override_cfg(NVDECSRD),
-	mc_make_sid_override_cfg(NVDECSWR),
-	mc_make_sid_override_cfg(APER),
-	mc_make_sid_override_cfg(APEW),
-	mc_make_sid_override_cfg(NVJPGSRD),
-	mc_make_sid_override_cfg(NVJPGSWR),
-	mc_make_sid_override_cfg(SESRD),
-	mc_make_sid_override_cfg(SESWR),
-	mc_make_sid_override_cfg(AXIAPR),
-	mc_make_sid_override_cfg(AXIAPW),
-	mc_make_sid_override_cfg(ETRR),
-	mc_make_sid_override_cfg(ETRW),
-	mc_make_sid_override_cfg(TSECSRDB),
-	mc_make_sid_override_cfg(TSECSWRB),
-	mc_make_sid_override_cfg(AXISR),
-	mc_make_sid_override_cfg(AXISW),
-	mc_make_sid_override_cfg(EQOSR),
-	mc_make_sid_override_cfg(EQOSW),
-	mc_make_sid_override_cfg(UFSHCR),
-	mc_make_sid_override_cfg(UFSHCW),
-	mc_make_sid_override_cfg(NVDISPLAYR),
-	mc_make_sid_override_cfg(BPMPR),
-	mc_make_sid_override_cfg(BPMPW),
-	mc_make_sid_override_cfg(BPMPDMAR),
-	mc_make_sid_override_cfg(BPMPDMAW),
-	mc_make_sid_override_cfg(AONR),
-	mc_make_sid_override_cfg(AONW),
-	mc_make_sid_override_cfg(AONDMAR),
-	mc_make_sid_override_cfg(AONDMAW),
-	mc_make_sid_override_cfg(SCER),
-	mc_make_sid_override_cfg(SCEW),
-	mc_make_sid_override_cfg(SCEDMAR),
-	mc_make_sid_override_cfg(SCEDMAW),
-	mc_make_sid_override_cfg(APEDMAR),
-	mc_make_sid_override_cfg(APEDMAW),
-	mc_make_sid_override_cfg(NVDISPLAYR1),
-	mc_make_sid_override_cfg(VICSRD1),
-	mc_make_sid_override_cfg(NVDECSRD1),
-	mc_make_sid_override_cfg(VIFALR),
-	mc_make_sid_override_cfg(VIFALW),
-	mc_make_sid_override_cfg(DLA0RDA),
-	mc_make_sid_override_cfg(DLA0FALRDB),
-	mc_make_sid_override_cfg(DLA0WRA),
-	mc_make_sid_override_cfg(DLA0FALWRB),
-	mc_make_sid_override_cfg(DLA1RDA),
-	mc_make_sid_override_cfg(DLA1FALRDB),
-	mc_make_sid_override_cfg(DLA1WRA),
-	mc_make_sid_override_cfg(DLA1FALWRB),
-	mc_make_sid_override_cfg(PVA0RDA),
-	mc_make_sid_override_cfg(PVA0RDB),
-	mc_make_sid_override_cfg(PVA0RDC),
-	mc_make_sid_override_cfg(PVA0WRA),
-	mc_make_sid_override_cfg(PVA0WRB),
-	mc_make_sid_override_cfg(PVA0WRC),
-	mc_make_sid_override_cfg(PVA1RDA),
-	mc_make_sid_override_cfg(PVA1RDB),
-	mc_make_sid_override_cfg(PVA1RDC),
-	mc_make_sid_override_cfg(PVA1WRA),
-	mc_make_sid_override_cfg(PVA1WRB),
-	mc_make_sid_override_cfg(PVA1WRC),
-	mc_make_sid_override_cfg(RCER),
-	mc_make_sid_override_cfg(RCEW),
-	mc_make_sid_override_cfg(RCEDMAR),
-	mc_make_sid_override_cfg(RCEDMAW),
-	mc_make_sid_override_cfg(NVENC1SRD),
-	mc_make_sid_override_cfg(NVENC1SWR),
-	mc_make_sid_override_cfg(PCIE0R),
-	mc_make_sid_override_cfg(PCIE0W),
-	mc_make_sid_override_cfg(PCIE1R),
-	mc_make_sid_override_cfg(PCIE1W),
-	mc_make_sid_override_cfg(PCIE2AR),
-	mc_make_sid_override_cfg(PCIE2AW),
-	mc_make_sid_override_cfg(PCIE3R),
-	mc_make_sid_override_cfg(PCIE3W),
-	mc_make_sid_override_cfg(PCIE4R),
-	mc_make_sid_override_cfg(PCIE4W),
-	mc_make_sid_override_cfg(PCIE5R),
-	mc_make_sid_override_cfg(PCIE5W),
-	mc_make_sid_override_cfg(ISPFALW),
-	mc_make_sid_override_cfg(DLA0RDA1),
-	mc_make_sid_override_cfg(DLA1RDA1),
-	mc_make_sid_override_cfg(PVA0RDA1),
-	mc_make_sid_override_cfg(PVA0RDB1),
-	mc_make_sid_override_cfg(PVA1RDA1),
-	mc_make_sid_override_cfg(PVA1RDB1),
-	mc_make_sid_override_cfg(PCIE5R1),
-	mc_make_sid_override_cfg(NVENCSRD1),
-	mc_make_sid_override_cfg(NVENC1SRD1),
-	mc_make_sid_override_cfg(ISPRA1),
-	mc_make_sid_override_cfg(PCIE0R1),
-	mc_make_sid_override_cfg(MIU0R),
-	mc_make_sid_override_cfg(MIU0W),
-	mc_make_sid_override_cfg(MIU1R),
-	mc_make_sid_override_cfg(MIU1W),
-	mc_make_sid_override_cfg(MIU2R),
-	mc_make_sid_override_cfg(MIU2W),
-	mc_make_sid_override_cfg(MIU3R),
-	mc_make_sid_override_cfg(MIU3W),
-	smmu_make_cfg(TEGRA_SMMU0_BASE),
-	smmu_make_cfg(TEGRA_SMMU2_BASE),
-	smmu_bypass_cfg,	/* TBU settings */
-	_END_OF_TABLE_,
-};
-
-/*******************************************************************************
- * Handler to return the pointer to the SMMU's context struct
- ******************************************************************************/
-smmu_regs_t *plat_get_smmu_ctx(void)
-{
-	/* index of _END_OF_TABLE_ */
-	tegra194_smmu_context[0].val = (uint32_t)ARRAY_SIZE(tegra194_smmu_context) - 1U;
-
-	return tegra194_smmu_context;
-}
-
-/*******************************************************************************
  * Handler to return the support SMMU devices number
  ******************************************************************************/
 uint32_t plat_get_num_smmu_devices(void)
diff --git a/plat/nvidia/tegra/soc/t194/plat_trampoline.S b/plat/nvidia/tegra/soc/t194/plat_trampoline.S
index 540c201..819920f 100644
--- a/plat/nvidia/tegra/soc/t194/plat_trampoline.S
+++ b/plat/nvidia/tegra/soc/t194/plat_trampoline.S
@@ -12,7 +12,7 @@
 
 #define TEGRA194_STATE_SYSTEM_SUSPEND	0x5C7
 #define TEGRA194_STATE_SYSTEM_RESUME	0x600D
-#define TEGRA194_SMMU_CTX_SIZE		0x80D
+#define TEGRA194_MC_CTX_SIZE		0xFB
 
 	.align 4
 	.globl	tegra194_cpu_reset_handler
@@ -69,8 +69,8 @@
 	 *
 	 * 0x0000: secure world's entrypoint
 	 * 0x0008: BL31 size (RO + RW)
-	 * 0x0010: SMMU context start
-	 * 0x2490: SMMU context end
+	 * 0x0010: MC context start
+	 * 0x2490: MC context end
 	 */
 
 	.align 4
@@ -79,14 +79,13 @@
 __tegra194_cpu_reset_handler_data:
 	.quad	tegra_secure_entrypoint
 	.quad	__BL31_END__ - BL31_BASE
-
 	.globl	__tegra194_system_suspend_state
 __tegra194_system_suspend_state:
 	.quad	0
 
 	.align 4
-__tegra194_smmu_context:
-	.rept	TEGRA194_SMMU_CTX_SIZE
+__tegra194_mc_context:
+	.rept	TEGRA194_MC_CTX_SIZE
 	.quad	0
 	.endr
 	.size	__tegra194_cpu_reset_handler_data, \
@@ -98,7 +97,7 @@
 
 	.globl tegra194_get_cpu_reset_handler_size
 	.globl tegra194_get_cpu_reset_handler_base
-	.globl tegra194_get_smmu_ctx_offset
+	.globl tegra194_get_mc_ctx_offset
 	.globl tegra194_set_system_suspend_entry
 
 /* return size of the CPU reset handler */
@@ -115,13 +114,13 @@
 	ret
 endfunc tegra194_get_cpu_reset_handler_base
 
-/* return the size of the SMMU context */
-func tegra194_get_smmu_ctx_offset
-	adr	x0, __tegra194_smmu_context
+/* return the size of the MC context */
+func tegra194_get_mc_ctx_offset
+	adr	x0, __tegra194_mc_context
 	adr	x1, tegra194_cpu_reset_handler
 	sub	x0, x0, x1
 	ret
-endfunc tegra194_get_smmu_ctx_offset
+endfunc tegra194_get_mc_ctx_offset
 
 /* set system suspend state before SC7 entry */
 func tegra194_set_system_suspend_entry
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);
+		ret = tegra_se_context_save_atomic(&se_dev_2);
+		if (ret != 0) {
+			ERROR("%s: SE2 ctx save failed (%d)\n", __func__, ret);
 		}
 
-		/* Atomic context save se */
-		if (ret == 0) {
-			INFO("%s: SE1 atomic context save\n", __func__);
-			ret = tegra_se_context_save_atomic(&se_dev_1);
-		}
-
-		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 7afbe0d..6d014bf 100644
--- a/plat/nvidia/tegra/soc/t210/plat_setup.c
+++ b/plat/nvidia/tegra/soc/t210/plat_setup.c
@@ -174,13 +174,13 @@
 	}
 
 	/* Initialize security engine driver */
-	if (tegra_chipid_is_t210_b01()) {
-		tegra_se_init();
-	}
+	tegra_se_init();
 }
 
 /* Secure IRQs for Tegra186 */
 static const interrupt_prop_t tegra210_interrupt_props[] = {
+	INTR_PROP_DESC(TEGRA210_TIMER1_IRQ, GIC_HIGHEST_SEC_PRIORITY,
+			GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE),
 	INTR_PROP_DESC(TEGRA210_WDT_CPU_LEGACY_FIQ, GIC_HIGHEST_SEC_PRIORITY,
 			GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE),
 };
diff --git a/plat/nvidia/tegra/soc/t210/plat_sip_calls.c b/plat/nvidia/tegra/soc/t210/plat_sip_calls.c
index 7e0f5c1..904f8d6 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,8 @@
 		} else {
 			return -EINVAL;
 		}
-
-		break;
-
-	default:
-		ERROR("%s: unsupported function ID\n", __func__);
+	} else {
 		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_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..6aa198c 100644
--- a/plat/qemu/qemu/platform.mk
+++ b/plat/qemu/qemu/platform.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -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	\
@@ -135,6 +140,8 @@
 				${PLAT_QEMU_COMMON_PATH}/qemu_gicv2.c
 
 QEMU_GICV3_SOURCES	:=	drivers/arm/gic/v3/gicv3_helpers.c	\
+				drivers/arm/gic/v3/gicdv3_helpers.c	\
+				drivers/arm/gic/v3/gicrv3_helpers.c	\
 				drivers/arm/gic/v3/gicv3_main.c		\
 				drivers/arm/gic/common/gic_common.c	\
 				plat/common/plat_gicv3.c		\
@@ -165,11 +172,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/qemu/qemu_sbsa/platform.mk b/plat/qemu/qemu_sbsa/platform.mk
index 51832d0..6ad3d8b 100644
--- a/plat/qemu/qemu_sbsa/platform.mk
+++ b/plat/qemu/qemu_sbsa/platform.mk
@@ -63,6 +63,8 @@
 endif
 
 QEMU_GIC_SOURCES	:=	drivers/arm/gic/v3/gicv3_helpers.c		\
+				drivers/arm/gic/v3/gicdv3_helpers.c		\
+				drivers/arm/gic/v3/gicrv3_helpers.c		\
 				drivers/arm/gic/v3/gicv3_main.c			\
 				drivers/arm/gic/common/gic_common.c		\
 				plat/common/plat_gicv3.c			\
diff --git a/plat/rockchip/rk3399/platform.mk b/plat/rockchip/rk3399/platform.mk
index 5a23d3c..0dc1840 100644
--- a/plat/rockchip/rk3399/platform.mk
+++ b/plat/rockchip/rk3399/platform.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -29,6 +29,8 @@
 				drivers/arm/gic/v3/gic500.c		\
 				drivers/arm/gic/v3/gicv3_main.c		\
 				drivers/arm/gic/v3/gicv3_helpers.c	\
+				drivers/arm/gic/v3/gicdv3_helpers.c	\
+				drivers/arm/gic/v3/gicrv3_helpers.c	\
 				plat/common/plat_gicv3.c		\
 				${RK_PLAT}/common/rockchip_gicv3.c
 
diff --git a/plat/socionext/synquacer/platform.mk b/plat/socionext/synquacer/platform.mk
index ab1f69e..0d9071b 100644
--- a/plat/socionext/synquacer/platform.mk
+++ b/plat/socionext/synquacer/platform.mk
@@ -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
 #
@@ -33,6 +33,8 @@
 BL31_SOURCES		+=	drivers/arm/ccn/ccn.c			\
 				drivers/arm/gic/common/gic_common.c	\
 				drivers/arm/gic/v3/gicv3_helpers.c	\
+				drivers/arm/gic/v3/gicdv3_helpers.c	\
+				drivers/arm/gic/v3/gicrv3_helpers.c	\
 				drivers/arm/gic/v3/gicv3_main.c		\
 				lib/cpus/aarch64/cortex_a53.S		\
 				plat/common/plat_gicv3.c		\
diff --git a/plat/socionext/uniphier/platform.mk b/plat/socionext/uniphier/platform.mk
index 8e96b68..a014f52 100644
--- a/plat/socionext/uniphier/platform.mk
+++ b/plat/socionext/uniphier/platform.mk
@@ -58,6 +58,8 @@
 BL31_SOURCES		+=	drivers/arm/cci/cci.c			\
 				drivers/arm/gic/common/gic_common.c	\
 				drivers/arm/gic/v3/gicv3_helpers.c	\
+				drivers/arm/gic/v3/gicdv3_helpers.c	\
+				drivers/arm/gic/v3/gicrv3_helpers.c	\
 				drivers/arm/gic/v3/gicv3_main.c		\
 				lib/cpus/aarch64/cortex_a53.S		\
 				lib/cpus/aarch64/cortex_a72.S		\
diff --git a/plat/socionext/uniphier/uniphier_io_storage.c b/plat/socionext/uniphier/uniphier_io_storage.c
index e89c835..77d1eaf 100644
--- a/plat/socionext/uniphier/uniphier_io_storage.c
+++ b/plat/socionext/uniphier/uniphier_io_storage.c
@@ -21,7 +21,7 @@
 #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_SIZE	0x00040000ULL
 
diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk
index b86287b..bd1a16b 100644
--- a/plat/st/stm32mp1/platform.mk
+++ b/plat/st/stm32mp1/platform.mk
@@ -149,14 +149,8 @@
 
 # Macros and rules to build TF binary
 STM32_TF_ELF_LDFLAGS	:=	--hash-style=gnu --as-needed
-STM32_DT_BASENAME	:=	$(DTB_FILE_NAME:.dtb=)
-STM32_TF_STM32		:=	${BUILD_PLAT}/tf-a-${STM32_DT_BASENAME}.stm32
-STM32_TF_BINARY		:=	$(STM32_TF_STM32:.stm32=.bin)
-STM32_TF_MAPFILE	:=	$(STM32_TF_STM32:.stm32=.map)
-STM32_TF_LINKERFILE	:=	$(STM32_TF_STM32:.stm32=.ld)
-STM32_TF_ELF		:=	$(STM32_TF_STM32:.stm32=.elf)
-STM32_TF_DTBFILE	:=      ${BUILD_PLAT}/fdts/${DTB_FILE_NAME}
-STM32_TF_OBJS		:=	${BUILD_PLAT}/stm32mp1.o
+STM32_TF_STM32		:=	$(addprefix ${BUILD_PLAT}/tf-a-, $(patsubst %.dtb,%.stm32,$(DTB_FILE_NAME)))
+STM32_TF_LINKERFILE	:=	${BUILD_PLAT}/stm32mp1.ld
 
 BL2_CFLAGS	+=	-DPLAT_XLAT_TABLES_DYNAMIC=1
 
@@ -164,7 +158,7 @@
 STM32IMAGEPATH		?= tools/stm32image
 STM32IMAGE		?= ${STM32IMAGEPATH}/stm32image${BIN_EXT}
 
-.PHONY:			${STM32_TF_STM32}
+.PHONY:			check_dtc_version stm32image clean_stm32image
 .SUFFIXES:
 
 all: check_dtc_version ${STM32_TF_STM32} stm32image
@@ -192,32 +186,32 @@
 	fi
 
 
-${STM32_TF_OBJS}:	plat/st/stm32mp1/stm32mp1.S bl2 ${BL32_DEP} ${STM32_TF_DTBFILE}
-			@echo "  AS      $<"
+${BUILD_PLAT}/stm32mp1-%.o:	${BUILD_PLAT}/fdts/%.dtb plat/st/stm32mp1/stm32mp1.S bl2 ${BL32_DEP}
+			@echo "  AS      stm32mp1.S"
 			${Q}${AS} ${ASFLAGS} ${TF_CFLAGS} \
 				${BL32_PATH} \
 				-DBL2_BIN_PATH=\"${BUILD_PLAT}/bl2.bin\" \
-				-DDTB_BIN_PATH=\"${STM32_TF_DTBFILE}\" \
+				-DDTB_BIN_PATH=\"$<\" \
 				-c plat/st/stm32mp1/stm32mp1.S -o $@
 
 ${STM32_TF_LINKERFILE}:	plat/st/stm32mp1/stm32mp1.ld.S ${BUILD_PLAT}
 			@echo "  LDS     $<"
 			${Q}${AS} ${ASFLAGS} ${TF_CFLAGS} -P -E $< -o $@
 
-${STM32_TF_ELF}:	${STM32_TF_OBJS} ${STM32_TF_LINKERFILE}
+tf-a-%.elf:		stm32mp1-%.o ${STM32_TF_LINKERFILE}
 			@echo "  LDS     $<"
-			${Q}${LD} -o $@ ${STM32_TF_ELF_LDFLAGS} -Map=${STM32_TF_MAPFILE} --script ${STM32_TF_LINKERFILE} ${STM32_TF_OBJS}
+			${Q}${LD} -o $@ ${STM32_TF_ELF_LDFLAGS} -Map=$(@:.elf=.map) --script ${STM32_TF_LINKERFILE} $<
 
-${STM32_TF_BINARY}:	${STM32_TF_ELF}
-			${Q}${OC} -O binary ${STM32_TF_ELF} $@
+tf-a-%.bin:		tf-a-%.elf
+			${Q}${OC} -O binary $< $@
 			@echo
 			@echo "Built $@ successfully"
 			@echo
 
-${STM32_TF_STM32}:	stm32image ${STM32_TF_BINARY}
+tf-a-%.stm32:		tf-a-%.bin stm32image
 			@echo
 			@echo "Generated $@"
-			$(eval LOADADDR =  $(shell cat ${STM32_TF_MAPFILE} | grep RAM | awk '{print $$2}'))
-			$(eval ENTRY =  $(shell cat ${STM32_TF_MAPFILE} | grep "__BL2_IMAGE_START" | awk '{print $$1}'))
-			${STM32IMAGE} -s ${STM32_TF_BINARY} -d $@ -l $(LOADADDR) -e ${ENTRY} -v ${STM32_TF_VERSION}
+			$(eval LOADADDR =  $(shell cat $(@:.stm32=.map) | grep RAM | awk '{print $$2}'))
+			$(eval ENTRY =  $(shell cat $(@:.stm32=.map) | grep "__BL2_IMAGE_START" | awk '{print $$1}'))
+			${STM32IMAGE} -s $< -d $@ -l $(LOADADDR) -e ${ENTRY} -v ${STM32_TF_VERSION}
 			@echo
diff --git a/plat/ti/k3/common/plat_common.mk b/plat/ti/k3/common/plat_common.mk
index 7956497..587b44b 100644
--- a/plat/ti/k3/common/plat_common.mk
+++ b/plat/ti/k3/common/plat_common.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
 #
@@ -57,6 +57,8 @@
 				drivers/arm/gic/common/gic_common.c	\
 				drivers/arm/gic/v3/gicv3_main.c		\
 				drivers/arm/gic/v3/gicv3_helpers.c	\
+				drivers/arm/gic/v3/gicdv3_helpers.c	\
+				drivers/arm/gic/v3/gicrv3_helpers.c	\
 				plat/common/plat_gicv3.c		\
 				${PLAT_PATH}/common/k3_gicv3.c		\
 
diff --git a/plat/xilinx/versal/platform.mk b/plat/xilinx/versal/platform.mk
index 1e231cc..5d7fd69 100644
--- a/plat/xilinx/versal/platform.mk
+++ b/plat/xilinx/versal/platform.mk
@@ -52,6 +52,8 @@
 				drivers/arm/gic/v3/gic500.c			\
 				drivers/arm/gic/v3/gicv3_main.c			\
 				drivers/arm/gic/v3/gicv3_helpers.c		\
+				drivers/arm/gic/v3/gicdv3_helpers.c	\
+				drivers/arm/gic/v3/gicrv3_helpers.c	\
 				drivers/arm/pl011/aarch64/pl011_console.S	\
 				plat/common/aarch64/crash_console_helpers.S	\
 				plat/arm/common/arm_cci.c			\
diff --git a/services/spd/tlkd/tlkd_main.c b/services/spd/tlkd/tlkd_main.c
index 3cfc52d..32ae8ec 100644
--- a/services/spd/tlkd/tlkd_main.c
+++ b/services/spd/tlkd/tlkd_main.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
  */
@@ -14,6 +14,7 @@
  * responsible for initialising and maintaining communication with the SP.
  ******************************************************************************/
 #include <assert.h>
+#include <bl31/interrupt_mgmt.h>
 #include <errno.h>
 #include <stddef.h>
 
@@ -49,6 +50,50 @@
 static int32_t tlkd_init(void);
 
 /*******************************************************************************
+ * Secure Payload Dispatcher's timer interrupt handler
+ ******************************************************************************/
+static uint64_t tlkd_interrupt_handler(uint32_t id,
+					uint32_t flags,
+					void *handle,
+					void *cookie)
+{
+	cpu_context_t *s_cpu_context;
+	int irq = plat_ic_get_pending_interrupt_id();
+
+	/* acknowledge the interrupt and mark it complete */
+	(void)plat_ic_acknowledge_interrupt();
+	plat_ic_end_of_interrupt(irq);
+
+	/*
+	 * Disable the routing of NS interrupts from secure world to
+	 * EL3 while interrupted on this core.
+	 */
+	disable_intr_rm_local(INTR_TYPE_S_EL1, SECURE);
+
+	/* Check the security state when the exception was generated */
+	assert(get_interrupt_src_ss(flags) == NON_SECURE);
+	assert(handle == cm_get_context(NON_SECURE));
+
+	/* Save non-secure state */
+	cm_el1_sysregs_context_save(NON_SECURE);
+
+	/* Get a reference to the secure context */
+	s_cpu_context = cm_get_context(SECURE);
+	assert(s_cpu_context);
+
+	/*
+	 * Restore non-secure state. There is no need to save the
+	 * secure system register context since the SP was supposed
+	 * to preserve it during S-EL1 interrupt handling.
+	 */
+	cm_el1_sysregs_context_restore(SECURE);
+	cm_set_next_eret_context(SECURE);
+
+	/* Provide the IRQ number to the SPD */
+	SMC_RET4(s_cpu_context, (uint32_t)TLK_IRQ_FIRED, 0, (uint32_t)irq, 0);
+}
+
+/*******************************************************************************
  * Secure Payload Dispatcher setup. The SPD finds out the SP entrypoint and type
  * (aarch32/aarch64) if not already known and initialises the context for entry
  * into the SP for its initialisation.
@@ -56,6 +101,8 @@
 static int32_t tlkd_setup(void)
 {
 	entry_point_info_t *tlk_ep_info;
+	uint32_t flags;
+	int32_t ret;
 
 	/*
 	 * Get information about the Secure Payload (BL32) image. Its
@@ -86,6 +133,18 @@
 		tlk_ep_info->pc,
 		&tlk_ctx);
 
+	/* get a list of all S-EL1 IRQs from the platform */
+
+	/* register interrupt handler */
+	flags = 0;
+	set_interrupt_rm_flag(flags, NON_SECURE);
+	ret = register_interrupt_type_handler(INTR_TYPE_S_EL1,
+					      tlkd_interrupt_handler,
+					      flags);
+	if (ret != 0) {
+		ERROR("failed to register tlkd interrupt handler (%d)\n", ret);
+	}
+
 	/*
 	 * All TLK SPD initialization done. Now register our init function
 	 * with BL31 for deferred invocation
@@ -385,6 +444,34 @@
 		break;
 
 	/*
+	 * This function ID is used by SP to indicate that it has completed
+	 * handling the secure interrupt.
+	 */
+	case TLK_IRQ_DONE:
+
+		if (ns)
+			SMC_RET1(handle, SMC_UNK);
+
+		assert(handle == cm_get_context(SECURE));
+
+		/* save secure world context */
+		cm_el1_sysregs_context_save(SECURE);
+
+		/* Get a reference to the non-secure context */
+		ns_cpu_context = cm_get_context(NON_SECURE);
+		assert(ns_cpu_context);
+
+		/*
+		 * Restore non-secure state. There is no need to save the
+		 * secure system register context since the SP was supposed
+		 * to preserve it during S-EL1 interrupt handling.
+		 */
+		cm_el1_sysregs_context_restore(NON_SECURE);
+		cm_set_next_eret_context(NON_SECURE);
+
+		SMC_RET0(ns_cpu_context);
+
+	/*
 	 * Return the number of service function IDs implemented to
 	 * provide service to non-secure
 	 */
diff --git a/tools/cert_create/Makefile b/tools/cert_create/Makefile
index eff929e..19f736f 100644
--- a/tools/cert_create/Makefile
+++ b/tools/cert_create/Makefile
@@ -27,6 +27,8 @@
 # Chain of trust.
 ifeq (${COT},tbbr)
   include src/tbbr/tbbr.mk
+else ifeq (${COT},dualroot)
+  include src/dualroot/cot.mk
 else
   $(error Unknown chain of trust ${COT})
 endif
diff --git a/tools/cert_create/include/dualroot/cot.h b/tools/cert_create/include/dualroot/cot.h
new file mode 100644
index 0000000..5701206
--- /dev/null
+++ b/tools/cert_create/include/dualroot/cot.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef DUALROOT_COT_H
+#define DUALROOT_COT_H
+
+/* Certificates. */
+enum {
+	/* Certificates owned by the silicon provider. */
+	TRUSTED_BOOT_FW_CERT,
+	TRUSTED_KEY_CERT,
+	SCP_FW_KEY_CERT,
+	SCP_FW_CONTENT_CERT,
+	SOC_FW_KEY_CERT,
+	SOC_FW_CONTENT_CERT,
+	TRUSTED_OS_FW_KEY_CERT,
+	TRUSTED_OS_FW_CONTENT_CERT,
+	FWU_CERT,
+
+	/* Certificates owned by the platform owner. */
+	NON_TRUSTED_FW_CONTENT_CERT,
+};
+
+/* Certificate extensions. */
+enum {
+	/* Extensions used in certificates owned by the silicon provider. */
+	TRUSTED_FW_NVCOUNTER_EXT,
+	TRUSTED_BOOT_FW_HASH_EXT,
+	TRUSTED_BOOT_FW_CONFIG_HASH_EXT,
+	HW_CONFIG_HASH_EXT,
+	TRUSTED_WORLD_PK_EXT,
+	SCP_FW_CONTENT_CERT_PK_EXT,
+	SCP_FW_HASH_EXT,
+	SOC_FW_CONTENT_CERT_PK_EXT,
+	SOC_AP_FW_HASH_EXT,
+	SOC_FW_CONFIG_HASH_EXT,
+	TRUSTED_OS_FW_CONTENT_CERT_PK_EXT,
+	TRUSTED_OS_FW_HASH_EXT,
+	TRUSTED_OS_FW_EXTRA1_HASH_EXT,
+	TRUSTED_OS_FW_EXTRA2_HASH_EXT,
+	TRUSTED_OS_FW_CONFIG_HASH_EXT,
+	SCP_FWU_CFG_HASH_EXT,
+	AP_FWU_CFG_HASH_EXT,
+	FWU_HASH_EXT,
+
+	/* Extensions used in certificates owned by the platform owner. */
+	PROT_PK_EXT,
+	NON_TRUSTED_FW_NVCOUNTER_EXT,
+	NON_TRUSTED_FW_CONTENT_CERT_PK_EXT,
+	NON_TRUSTED_WORLD_BOOTLOADER_HASH_EXT,
+	NON_TRUSTED_FW_CONFIG_HASH_EXT,
+};
+
+/* Keys. */
+enum {
+	/* Keys owned by the silicon provider. */
+	ROT_KEY,
+	TRUSTED_WORLD_KEY,
+	SCP_FW_CONTENT_CERT_KEY,
+	SOC_FW_CONTENT_CERT_KEY,
+	TRUSTED_OS_FW_CONTENT_CERT_KEY,
+
+	/* Keys owned by the platform owner. */
+	PROT_KEY,
+};
+
+#endif /* DUALROOT_COT_H */
diff --git a/tools/cert_create/src/dualroot/cot.c b/tools/cert_create/src/dualroot/cot.c
new file mode 100644
index 0000000..8117ffc
--- /dev/null
+++ b/tools/cert_create/src/dualroot/cot.c
@@ -0,0 +1,453 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <dualroot_oid.h>
+
+#include "cert.h"
+#include "ext.h"
+#include "key.h"
+
+#include "dualroot/cot.h"
+
+/*
+ * Certificates used in the chain of trust.
+ *
+ * All certificates are self-signed so the issuer certificate field points to
+ * itself.
+ */
+static cert_t cot_certs[] = {
+	[TRUSTED_BOOT_FW_CERT] = {
+		.id = TRUSTED_BOOT_FW_CERT,
+		.opt = "tb-fw-cert",
+		.help_msg = "Trusted Boot FW Certificate (output file)",
+		.cn = "Trusted Boot FW Certificate",
+		.key = ROT_KEY,
+		.issuer = TRUSTED_BOOT_FW_CERT,
+		.ext = {
+			TRUSTED_FW_NVCOUNTER_EXT,
+			TRUSTED_BOOT_FW_HASH_EXT,
+			TRUSTED_BOOT_FW_CONFIG_HASH_EXT,
+			HW_CONFIG_HASH_EXT
+		},
+		.num_ext = 4
+	},
+
+	[TRUSTED_KEY_CERT] = {
+		.id = TRUSTED_KEY_CERT,
+		.opt = "trusted-key-cert",
+		.help_msg = "Trusted Key Certificate (output file)",
+		.cn = "Trusted Key Certificate",
+		.key = ROT_KEY,
+		.issuer = TRUSTED_KEY_CERT,
+		.ext = {
+			TRUSTED_FW_NVCOUNTER_EXT,
+			TRUSTED_WORLD_PK_EXT,
+		},
+		.num_ext = 2
+	},
+
+	[SCP_FW_KEY_CERT] = {
+		.id = SCP_FW_KEY_CERT,
+		.opt = "scp-fw-key-cert",
+		.help_msg = "SCP Firmware Key Certificate (output file)",
+		.cn = "SCP Firmware Key Certificate",
+		.key = TRUSTED_WORLD_KEY,
+		.issuer = SCP_FW_KEY_CERT,
+		.ext = {
+			TRUSTED_FW_NVCOUNTER_EXT,
+			SCP_FW_CONTENT_CERT_PK_EXT
+		},
+		.num_ext = 2
+	},
+
+	[SCP_FW_CONTENT_CERT] = {
+		.id = SCP_FW_CONTENT_CERT,
+		.opt = "scp-fw-cert",
+		.help_msg = "SCP Firmware Content Certificate (output file)",
+		.cn = "SCP Firmware Content Certificate",
+		.key = SCP_FW_CONTENT_CERT_KEY,
+		.issuer = SCP_FW_CONTENT_CERT,
+		.ext = {
+			TRUSTED_FW_NVCOUNTER_EXT,
+			SCP_FW_HASH_EXT
+		},
+		.num_ext = 2
+	},
+
+	[SOC_FW_KEY_CERT] = {
+		.id = SOC_FW_KEY_CERT,
+		.opt = "soc-fw-key-cert",
+		.help_msg = "SoC Firmware Key Certificate (output file)",
+		.cn = "SoC Firmware Key Certificate",
+		.key = TRUSTED_WORLD_KEY,
+		.issuer = SOC_FW_KEY_CERT,
+		.ext = {
+			TRUSTED_FW_NVCOUNTER_EXT,
+			SOC_FW_CONTENT_CERT_PK_EXT
+		},
+		.num_ext = 2
+	},
+
+	[SOC_FW_CONTENT_CERT] = {
+		.id = SOC_FW_CONTENT_CERT,
+		.opt = "soc-fw-cert",
+		.help_msg = "SoC Firmware Content Certificate (output file)",
+		.cn = "SoC Firmware Content Certificate",
+		.key = SOC_FW_CONTENT_CERT_KEY,
+		.issuer = SOC_FW_CONTENT_CERT,
+		.ext = {
+			TRUSTED_FW_NVCOUNTER_EXT,
+			SOC_AP_FW_HASH_EXT,
+			SOC_FW_CONFIG_HASH_EXT,
+		},
+		.num_ext = 3
+	},
+
+	[TRUSTED_OS_FW_KEY_CERT] = {
+		.id = TRUSTED_OS_FW_KEY_CERT,
+		.opt = "tos-fw-key-cert",
+		.help_msg = "Trusted OS Firmware Key Certificate (output file)",
+		.cn = "Trusted OS Firmware Key Certificate",
+		.key = TRUSTED_WORLD_KEY,
+		.issuer = TRUSTED_OS_FW_KEY_CERT,
+		.ext = {
+			TRUSTED_FW_NVCOUNTER_EXT,
+			TRUSTED_OS_FW_CONTENT_CERT_PK_EXT
+		},
+		.num_ext = 2
+	},
+
+	[TRUSTED_OS_FW_CONTENT_CERT] = {
+		.id = TRUSTED_OS_FW_CONTENT_CERT,
+		.opt = "tos-fw-cert",
+		.help_msg = "Trusted OS Firmware Content Certificate (output file)",
+		.cn = "Trusted OS Firmware Content Certificate",
+		.key = TRUSTED_OS_FW_CONTENT_CERT_KEY,
+		.issuer = TRUSTED_OS_FW_CONTENT_CERT,
+		.ext = {
+			TRUSTED_FW_NVCOUNTER_EXT,
+			TRUSTED_OS_FW_HASH_EXT,
+			TRUSTED_OS_FW_EXTRA1_HASH_EXT,
+			TRUSTED_OS_FW_EXTRA2_HASH_EXT,
+			TRUSTED_OS_FW_CONFIG_HASH_EXT,
+		},
+		.num_ext = 5
+	},
+
+	[FWU_CERT] = {
+		.id = FWU_CERT,
+		.opt = "fwu-cert",
+		.help_msg = "Firmware Update Certificate (output file)",
+		.cn = "Firmware Update Certificate",
+		.key = ROT_KEY,
+		.issuer = FWU_CERT,
+		.ext = {
+			SCP_FWU_CFG_HASH_EXT,
+			AP_FWU_CFG_HASH_EXT,
+			FWU_HASH_EXT
+		},
+		.num_ext = 3
+	},
+
+	[NON_TRUSTED_FW_CONTENT_CERT] = {
+		.id = NON_TRUSTED_FW_CONTENT_CERT,
+		.opt = "nt-fw-cert",
+		.help_msg = "Non-Trusted Firmware Content Certificate (output file)",
+		.cn = "Non-Trusted Firmware Content Certificate",
+		.key = PROT_KEY,
+		.issuer = NON_TRUSTED_FW_CONTENT_CERT,
+		.ext = {
+			NON_TRUSTED_FW_NVCOUNTER_EXT,
+			NON_TRUSTED_WORLD_BOOTLOADER_HASH_EXT,
+			NON_TRUSTED_FW_CONFIG_HASH_EXT,
+			PROT_PK_EXT,
+		},
+		.num_ext = 4
+	},
+};
+
+REGISTER_COT(cot_certs);
+
+
+/* Certificate extensions. */
+static ext_t cot_ext[] = {
+	[TRUSTED_FW_NVCOUNTER_EXT] = {
+		.oid = TRUSTED_FW_NVCOUNTER_OID,
+		.opt = "tfw-nvctr",
+		.help_msg = "Trusted Firmware Non-Volatile counter value",
+		.sn = "TrustedWorldNVCounter",
+		.ln = "Trusted World Non-Volatile counter",
+		.asn1_type = V_ASN1_INTEGER,
+		.type = EXT_TYPE_NVCOUNTER,
+		.attr.nvctr_type = NVCTR_TYPE_TFW
+	},
+
+	[TRUSTED_BOOT_FW_HASH_EXT] = {
+		.oid = TRUSTED_BOOT_FW_HASH_OID,
+		.opt = "tb-fw",
+		.help_msg = "Trusted Boot Firmware image file",
+		.sn = "TrustedBootFirmwareHash",
+		.ln = "Trusted Boot Firmware hash (SHA256)",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH
+	},
+
+	[TRUSTED_BOOT_FW_CONFIG_HASH_EXT] = {
+		.oid = TRUSTED_BOOT_FW_CONFIG_HASH_OID,
+		.opt = "tb-fw-config",
+		.help_msg = "Trusted Boot Firmware Config file",
+		.sn = "TrustedBootFirmwareConfigHash",
+		.ln = "Trusted Boot Firmware Config hash",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH,
+		.optional = 1
+	},
+
+	[HW_CONFIG_HASH_EXT] = {
+		.oid = HW_CONFIG_HASH_OID,
+		.opt = "hw-config",
+		.help_msg = "HW Config file",
+		.sn = "HWConfigHash",
+		.ln = "HW Config hash",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH,
+		.optional = 1
+	},
+
+	[TRUSTED_WORLD_PK_EXT] = {
+		.oid = TRUSTED_WORLD_PK_OID,
+		.sn = "TrustedWorldPublicKey",
+		.ln = "Trusted World Public Key",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_PKEY,
+		.attr.key = TRUSTED_WORLD_KEY
+	},
+
+	[SCP_FW_CONTENT_CERT_PK_EXT] = {
+		.oid = SCP_FW_CONTENT_CERT_PK_OID,
+		.sn = "SCPFirmwareContentCertPK",
+		.ln = "SCP Firmware content certificate public key",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_PKEY,
+		.attr.key = SCP_FW_CONTENT_CERT_KEY
+	},
+
+	[SCP_FW_HASH_EXT] = {
+		.oid = SCP_FW_HASH_OID,
+		.opt = "scp-fw",
+		.help_msg = "SCP Firmware image file",
+		.sn = "SCPFirmwareHash",
+		.ln = "SCP Firmware hash (SHA256)",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH
+	},
+
+	[SOC_FW_CONTENT_CERT_PK_EXT] = {
+		.oid = SOC_FW_CONTENT_CERT_PK_OID,
+		.sn = "SoCFirmwareContentCertPK",
+		.ln = "SoC Firmware content certificate public key",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_PKEY,
+		.attr.key = SOC_FW_CONTENT_CERT_KEY
+	},
+
+	[SOC_AP_FW_HASH_EXT] = {
+		.oid = SOC_AP_FW_HASH_OID,
+		.opt = "soc-fw",
+		.help_msg = "SoC AP Firmware image file",
+		.sn = "SoCAPFirmwareHash",
+		.ln = "SoC AP Firmware hash (SHA256)",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH
+	},
+
+	[SOC_FW_CONFIG_HASH_EXT] = {
+		.oid = SOC_FW_CONFIG_HASH_OID,
+		.opt = "soc-fw-config",
+		.help_msg = "SoC Firmware Config file",
+		.sn = "SocFirmwareConfigHash",
+		.ln = "SoC Firmware Config hash",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH,
+		.optional = 1
+	},
+
+	[TRUSTED_OS_FW_CONTENT_CERT_PK_EXT] = {
+		.oid = TRUSTED_OS_FW_CONTENT_CERT_PK_OID,
+		.sn = "TrustedOSFirmwareContentCertPK",
+		.ln = "Trusted OS Firmware content certificate public key",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_PKEY,
+		.attr.key = TRUSTED_OS_FW_CONTENT_CERT_KEY
+	},
+
+	[TRUSTED_OS_FW_HASH_EXT] = {
+		.oid = TRUSTED_OS_FW_HASH_OID,
+		.opt = "tos-fw",
+		.help_msg = "Trusted OS image file",
+		.sn = "TrustedOSHash",
+		.ln = "Trusted OS hash (SHA256)",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH
+	},
+
+	[TRUSTED_OS_FW_EXTRA1_HASH_EXT] = {
+		.oid = TRUSTED_OS_FW_EXTRA1_HASH_OID,
+		.opt = "tos-fw-extra1",
+		.help_msg = "Trusted OS Extra1 image file",
+		.sn = "TrustedOSExtra1Hash",
+		.ln = "Trusted OS Extra1 hash (SHA256)",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH,
+		.optional = 1
+	},
+
+	[TRUSTED_OS_FW_EXTRA2_HASH_EXT] = {
+		.oid = TRUSTED_OS_FW_EXTRA2_HASH_OID,
+		.opt = "tos-fw-extra2",
+		.help_msg = "Trusted OS Extra2 image file",
+		.sn = "TrustedOSExtra2Hash",
+		.ln = "Trusted OS Extra2 hash (SHA256)",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH,
+		.optional = 1
+	},
+
+	[TRUSTED_OS_FW_CONFIG_HASH_EXT] = {
+		.oid = TRUSTED_OS_FW_CONFIG_HASH_OID,
+		.opt = "tos-fw-config",
+		.help_msg = "Trusted OS Firmware Config file",
+		.sn = "TrustedOSFirmwareConfigHash",
+		.ln = "Trusted OS Firmware Config hash",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH,
+		.optional = 1
+	},
+
+	[SCP_FWU_CFG_HASH_EXT] = {
+		.oid = SCP_FWU_CFG_HASH_OID,
+		.opt = "scp-fwu-cfg",
+		.help_msg = "SCP Firmware Update Config image file",
+		.sn = "SCPFWUpdateConfig",
+		.ln = "SCP Firmware Update Config hash (SHA256)",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH,
+		.optional = 1
+	},
+
+	[AP_FWU_CFG_HASH_EXT] = {
+		.oid = AP_FWU_CFG_HASH_OID,
+		.opt = "ap-fwu-cfg",
+		.help_msg = "AP Firmware Update Config image file",
+		.sn = "APFWUpdateConfig",
+		.ln = "AP Firmware Update Config hash (SHA256)",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH,
+		.optional = 1
+	},
+
+	[FWU_HASH_EXT] = {
+		.oid = FWU_HASH_OID,
+		.opt = "fwu",
+		.help_msg = "Firmware Updater image file",
+		.sn = "FWUpdaterHash",
+		.ln = "Firmware Updater hash (SHA256)",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH,
+		.optional = 1
+	},
+
+	[PROT_PK_EXT] = {
+		.oid = PROT_PK_OID,
+		.sn = "PlatformRoTKey",
+		.ln = "Platform Root of Trust Public Key",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_PKEY,
+		.attr.key = PROT_KEY
+	},
+
+	[NON_TRUSTED_FW_NVCOUNTER_EXT] = {
+		.oid = NON_TRUSTED_FW_NVCOUNTER_OID,
+		.opt = "ntfw-nvctr",
+		.help_msg = "Non-Trusted Firmware Non-Volatile counter value",
+		.sn = "NormalWorldNVCounter",
+		.ln = "Non-Trusted Firmware Non-Volatile counter",
+		.asn1_type = V_ASN1_INTEGER,
+		.type = EXT_TYPE_NVCOUNTER,
+		.attr.nvctr_type = NVCTR_TYPE_NTFW
+	},
+
+	[NON_TRUSTED_WORLD_BOOTLOADER_HASH_EXT] = {
+		.oid = NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID,
+		.opt = "nt-fw",
+		.help_msg = "Non-Trusted World Bootloader image file",
+		.sn = "NonTrustedWorldBootloaderHash",
+		.ln = "Non-Trusted World hash (SHA256)",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH
+	},
+
+	[NON_TRUSTED_FW_CONFIG_HASH_EXT] = {
+		.oid = NON_TRUSTED_FW_CONFIG_HASH_OID,
+		.opt = "nt-fw-config",
+		.help_msg = "Non Trusted OS Firmware Config file",
+		.sn = "NonTrustedOSFirmwareConfigHash",
+		.ln = "Non-Trusted OS Firmware Config hash",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH,
+		.optional = 1
+	},
+};
+
+REGISTER_EXTENSIONS(cot_ext);
+
+
+/* Keys used to establish the chain of trust. */
+static key_t cot_keys[] = {
+	[ROT_KEY] = {
+		.id = ROT_KEY,
+		.opt = "rot-key",
+		.help_msg = "Root Of Trust key (input/output file)",
+		.desc = "Root Of Trust key"
+	},
+
+	[TRUSTED_WORLD_KEY] = {
+		.id = TRUSTED_WORLD_KEY,
+		.opt = "trusted-world-key",
+		.help_msg = "Trusted World key (input/output file)",
+		.desc = "Trusted World key"
+	},
+
+	[SCP_FW_CONTENT_CERT_KEY] = {
+		.id = SCP_FW_CONTENT_CERT_KEY,
+		.opt = "scp-fw-key",
+		.help_msg = "SCP Firmware Content Certificate key (input/output file)",
+		.desc = "SCP Firmware Content Certificate key"
+	},
+
+	[SOC_FW_CONTENT_CERT_KEY] = {
+		.id = SOC_FW_CONTENT_CERT_KEY,
+		.opt = "soc-fw-key",
+		.help_msg = "SoC Firmware Content Certificate key (input/output file)",
+		.desc = "SoC Firmware Content Certificate key"
+	},
+
+	[TRUSTED_OS_FW_CONTENT_CERT_KEY] = {
+		.id = TRUSTED_OS_FW_CONTENT_CERT_KEY,
+		.opt = "tos-fw-key",
+		.help_msg = "Trusted OS Firmware Content Certificate key (input/output file)",
+		.desc = "Trusted OS Firmware Content Certificate key"
+	},
+
+	[PROT_KEY] = {
+		.id = PROT_KEY,
+		.opt = "prot-key",
+		.help_msg = "Platform Root of Trust key",
+		.desc = "Platform Root of Trust key"
+	},
+};
+
+REGISTER_KEYS(cot_keys);
diff --git a/tools/cert_create/src/dualroot/cot.mk b/tools/cert_create/src/dualroot/cot.mk
new file mode 100644
index 0000000..a572484
--- /dev/null
+++ b/tools/cert_create/src/dualroot/cot.mk
@@ -0,0 +1,10 @@
+#
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+PLAT_MSG		:=	Dual root of trust
+PLAT_INCLUDE		:=	../../include/tools_share
+
+OBJECTS += src/dualroot/cot.o
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;
+}