diff --git a/plat/nvidia/tegra/include/t186/tegra_def.h b/plat/nvidia/tegra/include/t186/tegra_def.h
index 0732993d903aaa5af1602cc5e76be1a9fd1e4f9d..f3fbb891e4f730137692d3108233fa42dc9bf5df 100644
--- a/plat/nvidia/tegra/include/t186/tegra_def.h
+++ b/plat/nvidia/tegra/include/t186/tegra_def.h
@@ -81,6 +81,7 @@
 #define  HARDWARE_MINOR_REVISION_MASK	0xf0000
 #define  HARDWARE_MINOR_REVISION_SHIFT	0x10
 #define  HARDWARE_REVISION_A01		1
+#define  MISCREG_PFCFG			0x200C
 
 /*******************************************************************************
  * Tegra Memory Controller constants
@@ -105,6 +106,16 @@
 #define TEGRA_GICD_BASE			0x03881000
 #define TEGRA_GICC_BASE			0x03882000
 
+/*******************************************************************************
+ * Security Engine related constants
+ ******************************************************************************/
+#define TEGRA_SE0_BASE			0x03AC0000
+#define  SE_MUTEX_WATCHDOG_NS_LIMIT	0x6C
+#define TEGRA_PKA1_BASE			0x03AD0000
+#define  PKA_MUTEX_WATCHDOG_NS_LIMIT	0x8144
+#define TEGRA_RNG1_BASE			0x03AE0000
+#define  RNG_MUTEX_WATCHDOG_NS_LIMIT	0xFE0
+
 /*******************************************************************************
  * Tegra Clock and Reset Controller constants
  ******************************************************************************/
@@ -124,6 +135,9 @@
  * Tegra scratch registers constants
  ******************************************************************************/
 #define TEGRA_SCRATCH_BASE		0x0C390000
+#define  SECURE_SCRATCH_RSV6		0x680
+#define  SECURE_SCRATCH_RSV11_LO	0x6A8
+#define  SECURE_SCRATCH_RSV11_HI	0x6AC
 
 /*******************************************************************************
  * Tegra Memory Mapped Control Register Access Bus constants
diff --git a/plat/nvidia/tegra/soc/t186/drivers/mce/mce.c b/plat/nvidia/tegra/soc/t186/drivers/mce/mce.c
index 98151070848141271d2f59924e94f7f2113b85fb..745b6f4e563c1dca0216b7c558ae900b6ebd70c8 100644
--- a/plat/nvidia/tegra/soc/t186/drivers/mce/mce.c
+++ b/plat/nvidia/tegra/soc/t186/drivers/mce/mce.c
@@ -262,7 +262,6 @@ int mce_command_handler(mce_cmd_t cmd, uint64_t arg0, uint64_t arg1,
 		/* update context to return SC7 status value */
 		write_ctx_reg(gp_regs, CTX_GPREG_X1, ret);
 		write_ctx_reg(gp_regs, CTX_GPREG_X3, ret);
-		ret = 0;
 
 		break;
 
diff --git a/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c
index 20c0f4c12151ae77043444a9e3ffce0cc06b1961..7e35cc6b29070dcf92c4c6cf7e43852fede59476 100644
--- a/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c
+++ b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c
@@ -38,6 +38,7 @@
 #include <denver.h>
 #include <mce.h>
 #include <psci.h>
+#include <smmu.h>
 #include <t18x_ari.h>
 #include <tegra_private.h>
 
@@ -48,7 +49,10 @@ extern void prepare_cpu_pwr_dwn(void);
 /* constants to get power state's wake time */
 #define TEGRA186_WAKE_TIME_MASK		0xFFFFFF
 #define TEGRA186_WAKE_TIME_SHIFT	4
+/* context size to save during system suspend */
+#define TEGRA186_SE_CONTEXT_SIZE		3
 
+static uint32_t se_regs[TEGRA186_SE_CONTEXT_SIZE];
 static unsigned int wake_time[PLATFORM_CORE_COUNT];
 
 /* System power down state */
@@ -89,9 +93,15 @@ int32_t tegra_soc_validate_power_state(unsigned int power_state,
 int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state)
 {
 	const plat_local_state_t *pwr_domain_state;
-	unsigned int stateid_afflvl0;
+	unsigned int stateid_afflvl0, stateid_afflvl2;
 	int cpu = read_mpidr() & MPIDR_CPU_MASK;
 	int impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK;
+	cpu_context_t *ctx = cm_get_context(NON_SECURE);
+	gp_regs_t *gp_regs = get_gpregs_ctx(ctx);
+	uint32_t val;
+
+	assert(ctx);
+	assert(gp_regs);
 
 	if (impl == DENVER_IMPL)
 		cpu |= 0x4;
@@ -100,6 +110,8 @@ int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state)
 	pwr_domain_state = target_state->pwr_domain_state;
 	stateid_afflvl0 = pwr_domain_state[MPIDR_AFFLVL0] &
 		TEGRA186_STATE_ID_MASK;
+	stateid_afflvl2 = pwr_domain_state[PLAT_MAX_PWR_LVL] &
+		TEGRA186_STATE_ID_MASK;
 
 	if (stateid_afflvl0 == PSTATE_ID_CORE_IDLE) {
 
@@ -113,6 +125,42 @@ int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state)
 		(void)mce_command_handler(MCE_CMD_ENTER_CSTATE,
 			TEGRA_ARI_CORE_C7, wake_time[cpu], 0);
 
+	} else if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) {
+
+		/* loop until SC7 is allowed */
+		do {
+			val = mce_command_handler(MCE_CMD_IS_SC7_ALLOWED,
+					TEGRA_ARI_CORE_C7,
+					MCE_CORE_SLEEP_TIME_INFINITE,
+					0);
+		} while (val == 0);
+
+		/* save SE registers */
+		se_regs[0] = mmio_read_32(TEGRA_SE0_BASE +
+				SE_MUTEX_WATCHDOG_NS_LIMIT);
+		se_regs[1] = mmio_read_32(TEGRA_RNG1_BASE +
+				RNG_MUTEX_WATCHDOG_NS_LIMIT);
+		se_regs[2] = mmio_read_32(TEGRA_PKA1_BASE +
+				PKA_MUTEX_WATCHDOG_NS_LIMIT);
+
+		/* save 'Secure Boot' Processor Feature Config Register */
+		val = mmio_read_32(TEGRA_MISC_BASE + MISCREG_PFCFG);
+		mmio_write_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV6, val);
+
+		/* save SMMU context */
+		tegra_smmu_save_context();
+
+		/* Prepare for system suspend */
+		write_ctx_reg(gp_regs, CTX_GPREG_X4, 1);
+		write_ctx_reg(gp_regs, CTX_GPREG_X5, 0);
+		write_ctx_reg(gp_regs, CTX_GPREG_X6, 1);
+		(void)mce_command_handler(MCE_CMD_UPDATE_CSTATE_INFO,
+			TEGRA_ARI_CLUSTER_CC7, 0, TEGRA_ARI_SYSTEM_SC7);
+
+		/* Enter system suspend state */
+		(void)mce_command_handler(MCE_CMD_ENTER_CSTATE,
+			TEGRA_ARI_CORE_C7, MCE_CORE_SLEEP_TIME_INFINITE, 0);
+
 	} else {
 		ERROR("%s: Unknown state id\n", __func__);
 		return PSCI_E_NOT_SUPPORTED;
@@ -140,6 +188,29 @@ int tegra_soc_pwr_domain_on(u_register_t mpidr)
 	return PSCI_E_SUCCESS;
 }
 
+int tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+	int state_id = target_state->pwr_domain_state[PLAT_MAX_PWR_LVL];
+
+	/*
+	 * Check if we are exiting from deep sleep and restore SE
+	 * context if we are.
+	 */
+	if (state_id == PSTATE_ID_SOC_POWERDN) {
+		mmio_write_32(TEGRA_SE0_BASE + SE_MUTEX_WATCHDOG_NS_LIMIT,
+			se_regs[0]);
+		mmio_write_32(TEGRA_RNG1_BASE + RNG_MUTEX_WATCHDOG_NS_LIMIT,
+			se_regs[1]);
+		mmio_write_32(TEGRA_PKA1_BASE + PKA_MUTEX_WATCHDOG_NS_LIMIT,
+			se_regs[2]);
+
+		/* Init SMMU */
+		tegra_smmu_init();
+	}
+
+	return PSCI_E_SUCCESS;
+}
+
 int tegra_soc_pwr_domain_off(const psci_power_state_t *target_state)
 {
 	cpu_context_t *ctx = cm_get_context(NON_SECURE);
diff --git a/plat/nvidia/tegra/soc/t186/plat_setup.c b/plat/nvidia/tegra/soc/t186/plat_setup.c
index 44faefef076ac4a62ffbcee3e3d35ddc8bf5f3c4..d6b8bc3f8b8c88ded92165d416a66bc2c07d1a0b 100644
--- a/plat/nvidia/tegra/soc/t186/plat_setup.c
+++ b/plat/nvidia/tegra/soc/t186/plat_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -73,13 +73,21 @@ static const mmap_region_t tegra_mmap[] = {
 			MT_DEVICE | MT_RW | MT_SECURE),
 	MAP_REGION_FLAT(TEGRA_GICD_BASE, 0x20000, /* 128KB */
 			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(TEGRA_SE0_BASE, 0x10000, /* 64KB */
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(TEGRA_PKA1_BASE, 0x10000, /* 64KB */
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(TEGRA_RNG1_BASE, 0x10000, /* 64KB */
+			MT_DEVICE | MT_RW | MT_SECURE),
 	MAP_REGION_FLAT(TEGRA_CAR_RESET_BASE, 0x10000, /* 64KB */
 			MT_DEVICE | MT_RW | MT_SECURE),
 	MAP_REGION_FLAT(TEGRA_PMC_BASE, 0x40000, /* 256KB */
 			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(TEGRA_SCRATCH_BASE, 0x10000, /* 64KB */
+			MT_DEVICE | MT_RW | MT_SECURE),
 	MAP_REGION_FLAT(TEGRA_MMCRAB_BASE, 0x60000, /* 384KB */
 			MT_DEVICE | MT_RW | MT_SECURE),
-	MAP_REGION_FLAT(TEGRA_SMMU_BASE, 0x10000, /* 64KB */
+	MAP_REGION_FLAT(TEGRA_SMMU_BASE, 0x1000000, /* 64KB */
 			MT_DEVICE | MT_RW | MT_SECURE),
 	{0}
 };
diff --git a/plat/nvidia/tegra/soc/t186/platform_t186.mk b/plat/nvidia/tegra/soc/t186/platform_t186.mk
index 272074c55f13f933f39b5918d552c913423b0335..adc4a9ee9c45df36f36aa7aed6d5cc83feff5077 100644
--- a/plat/nvidia/tegra/soc/t186/platform_t186.mk
+++ b/plat/nvidia/tegra/soc/t186/platform_t186.mk
@@ -42,10 +42,10 @@ $(eval $(call add_define,PLATFORM_CLUSTER_COUNT))
 PLATFORM_MAX_CPUS_PER_CLUSTER		:= 4
 $(eval $(call add_define,PLATFORM_MAX_CPUS_PER_CLUSTER))
 
-MAX_XLAT_TABLES				:= 12
+MAX_XLAT_TABLES				:= 15
 $(eval $(call add_define,MAX_XLAT_TABLES))
 
-MAX_MMAP_REGIONS			:= 12
+MAX_MMAP_REGIONS			:= 15
 $(eval $(call add_define,MAX_MMAP_REGIONS))
 
 # platform files