Merge pull request #1785 from vwadekar/tf2.0-tegra-downstream-rebase-1.25.19

Tf2.0 tegra downstream rebase 1.25.19
diff --git a/Makefile b/Makefile
index 0169f3f..34f6890 100644
--- a/Makefile
+++ b/Makefile
@@ -248,7 +248,6 @@
 # Common sources and include directories
 ################################################################################
 include lib/compiler-rt/compiler-rt.mk
-include lib/libc/libc.mk
 
 BL_COMMON_SOURCES	+=	common/bl_common.c			\
 				common/tf_log.c				\
@@ -390,6 +389,13 @@
 include ${AARCH32_SP_MAKE}
 endif
 
+endif
+
+################################################################################
+# Include libc if not overridden
+################################################################################
+ifeq (${OVERRIDE_LIBC},0)
+include lib/libc/libc.mk
 endif
 
 ################################################################################
@@ -595,6 +601,7 @@
 $(eval $(call assert_boolean,HW_ASSISTED_COHERENCY))
 $(eval $(call assert_boolean,MULTI_CONSOLE_API))
 $(eval $(call assert_boolean,NS_TIMER_SWITCH))
+$(eval $(call assert_boolean,OVERRIDE_LIBC))
 $(eval $(call assert_boolean,PL011_GENERIC_UART))
 $(eval $(call assert_boolean,PROGRAMMABLE_RESET_ADDRESS))
 $(eval $(call assert_boolean,PSCI_EXTENDED_STATE_ID))
diff --git a/docs/plat/nvidia-tegra.rst b/docs/plat/nvidia-tegra.rst
index 90d2ae1..7ed0f2c 100644
--- a/docs/plat/nvidia-tegra.rst
+++ b/docs/plat/nvidia-tegra.rst
@@ -1,6 +1,23 @@
 Tegra SoCs - Overview
 =====================
 
+-  .. rubric:: T186
+      :name: t186
+
+The NVIDIA® Parker (T186) series system-on-chip (SoC) delivers a heterogeneous
+multi-processing (HMP) solution designed to optimize performance and
+efficiency.
+
+T186 has Dual NVIDIA Denver 2 ARM® CPU cores, plus Quad ARM Cortex®-A57 cores,
+in a coherent multiprocessor configuration. The Denver 2 and Cortex-A57 cores
+support ARMv8, executing both 64-bit Aarch64 code, and 32-bit Aarch32 code
+including legacy ARMv7 applications. The Denver 2 processors each have 128 KB
+Instruction and 64 KB Data Level 1 caches; and have a 2MB shared Level 2
+unified cache. The Cortex-A57 processors each have 48 KB Instruction and 32 KB
+Data Level 1 caches; and also have a 2 MB shared Level 2 unified cache. A
+high speed coherency fabric connects these two processor complexes and allows
+heterogeneous multi-processing with all six cores if required.
+
 -  .. rubric:: T210
       :name: t210
 
@@ -49,11 +66,21 @@
 Trusted OS dispatcher
 =====================
 
+Tegra supports multiple Trusted OS'.
+
-Tegra supports multiple Trusted OS', Trusted Little Kernel (TLK) being one of
-them. In order to include the 'tlkd' dispatcher in the image, pass 'SPD=tlkd'
-on the command line while preparing a bl31 image. This allows other Trusted OS
-vendors to use the upstream code and include their dispatchers in the image
-without changing any makefiles.
+- Trusted Little Kernel (TLK): In order to include the 'tlkd' dispatcher in
+  the image, pass 'SPD=tlkd' on the command line while preparing a bl31 image.
+- Trusty: In order to include the 'trusty' dispatcher in the image, pass
+  'SPD=trusty' on the command line while preparing a bl31 image.
+
+This allows other Trusted OS vendors to use the upstream code and include
+their dispatchers in the image without changing any makefiles.
+
+These are the supported Trusted OS' by Tegra platforms.
+
+Tegra132: TLK
+Tegra210: TLK and Trusty
+Tegra186: Trusty
 
 Preparing the BL31 image to run on Tegra SoCs
 =============================================
@@ -61,7 +88,8 @@
 .. code:: shell
 
     CROSS_COMPILE=<path-to-aarch64-gcc>/bin/aarch64-none-elf- make PLAT=tegra \
-    TARGET_SOC=<target-soc e.g. t210|t132> SPD=<dispatcher e.g. tlkd> bl31
+    TARGET_SOC=<target-soc e.g. t186|t210|t132> SPD=<dispatcher e.g. trusty|tlkd>
+    bl31
 
 Platforms wanting to use different TZDRAM\_BASE, can add ``TZDRAM_BASE=<value>``
 to the build command line.
diff --git a/docs/user-guide.rst b/docs/user-guide.rst
index 320bb1d..35d44ca 100644
--- a/docs/user-guide.rst
+++ b/docs/user-guide.rst
@@ -575,6 +575,10 @@
    1 (do save and restore). 0 is the default. An SPD may set this to 1 if it
    wants the timer registers to be saved and restored.
 
+- ``OVERRIDE_LIBC``: This option allows platforms to override the default libc
+   for the BL image. It can be either 0 (include) or 1 (remove). The default
+   value is 0.
+
 -  ``PL011_GENERIC_UART``: Boolean option to indicate the PL011 driver that
    the underlying hardware is not a full PL011 UART but a minimally compliant
    generic UART, which is a subset of the PL011. The driver will not access
diff --git a/include/bl32/payloads/tlk.h b/include/bl32/payloads/tlk.h
index 2c12633..ce8e3e8 100644
--- a/include/bl32/payloads/tlk.h
+++ b/include/bl32/payloads/tlk.h
@@ -20,7 +20,9 @@
  */
 #define TLK_REGISTER_LOGBUF	TLK_TOS_YIELD_FID(0x1)
 #define TLK_REGISTER_REQBUF	TLK_TOS_YIELD_FID(0x2)
-#define TLK_REGISTER_NS_DRAM	TLK_TOS_YIELD_FID(0x4)
+#define TLK_SS_REGISTER_HANDLER	TLK_TOS_YIELD_FID(0x3)
+#define TLK_REGISTER_NS_DRAM_RANGES	TLK_TOS_YIELD_FID(0x4)
+#define TLK_SET_ROOT_OF_TRUST	TLK_TOS_YIELD_FID(0x5)
 #define TLK_RESUME_FID		TLK_TOS_YIELD_FID(0x100)
 #define TLK_SYSTEM_SUSPEND	TLK_TOS_YIELD_FID(0xE001)
 #define TLK_SYSTEM_RESUME	TLK_TOS_YIELD_FID(0xE002)
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index c1aa320..76a9fd4 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -122,6 +122,9 @@
 # NS timer register save and restore
 NS_TIMER_SWITCH			:= 0
 
+# Include lib/libc in the final image
+OVERRIDE_LIBC			:= 0
+
 # Build PL011 UART driver in minimal generic UART mode
 PL011_GENERIC_UART		:= 0
 
diff --git a/plat/nvidia/tegra/common/drivers/bpmp/bpmp.c b/plat/nvidia/tegra/common/drivers/bpmp/bpmp.c
index 1c5d2e1..29dc267 100644
--- a/plat/nvidia/tegra/common/drivers/bpmp/bpmp.c
+++ b/plat/nvidia/tegra/common/drivers/bpmp/bpmp.c
@@ -16,7 +16,7 @@
 #include <string.h>
 #include <tegra_def.h>
 
-#define BPMP_TIMEOUT	2
+#define BPMP_TIMEOUT	500 /* 500ms */
 
 static uint32_t channel_base[NR_CHANNELS];
 static uint32_t bpmp_init_state = BPMP_INIT_PENDING;
@@ -115,58 +115,117 @@
 
 int tegra_bpmp_init(void)
 {
-	uint32_t val, base;
+	uint32_t val, base, timeout = BPMP_TIMEOUT;
 	unsigned int ch;
 	int ret = 0;
 
-	if (bpmp_init_state != BPMP_INIT_COMPLETE) {
+	if (bpmp_init_state == BPMP_INIT_PENDING) {
 
 		/* check if the bpmp processor is alive. */
-		val = mmio_read_32(TEGRA_RES_SEMA_BASE + STA_OFFSET);
-		if (val != SIGN_OF_LIFE) {
-			ERROR("BPMP precessor not available\n");
-			return -ENOTSUP;
-		}
+		do {
+			val = mmio_read_32(TEGRA_RES_SEMA_BASE + STA_OFFSET);
+			if (val != SIGN_OF_LIFE) {
+				mdelay(1);
+				timeout--;
+			}
 
-		/* check if clock for the atomics block is enabled */
-		val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_CLK_ENB_V);
-		if ((val & CAR_ENABLE_ATOMICS) == 0) {
-			ERROR("Clock to the atomics block is disabled\n");
-		}
+		} while ((val != SIGN_OF_LIFE) && (timeout > 0U));
 
-		/* check if the atomics block is out of reset */
-		val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_CLR_V);
-		if ((val & CAR_ENABLE_ATOMICS) == CAR_ENABLE_ATOMICS) {
-			ERROR("Reset to the atomics block is asserted\n");
-		}
+		if (val == SIGN_OF_LIFE) {
 
-		/* base address to get the result from Atomics */
-		base = TEGRA_ATOMICS_BASE + RESULT0_REG_OFFSET;
+			/* check if clock for the atomics block is enabled */
+			val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_CLK_ENB_V);
+			if ((val & CAR_ENABLE_ATOMICS) == 0) {
+				ERROR("Clock to the atomics block is disabled\n");
+			}
+
+			/* check if the atomics block is out of reset */
+			val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_CLR_V);
+			if ((val & CAR_ENABLE_ATOMICS) == CAR_ENABLE_ATOMICS) {
+				ERROR("Reset to the atomics block is asserted\n");
+			}
 
-		/* channel area is setup by BPMP before signaling handshake */
-		for (ch = 0; ch < NR_CHANNELS; ch++) {
+			/* base address to get the result from Atomics */
+			base = TEGRA_ATOMICS_BASE + RESULT0_REG_OFFSET;
 
-			/* issue command to get the channel base address */
-			mmio_write_32(base, (ch << TRIGGER_ID_SHIFT) |
-				      ATOMIC_CMD_GET);
+			/* channel area is setup by BPMP before signaling handshake */
+			for (ch = 0; ch < NR_CHANNELS; ch++) {
 
-			/* get the base address for the channel */
-			channel_base[ch] = mmio_read_32(base);
+				/* issue command to get the channel base address */
+				mmio_write_32(base, (ch << TRIGGER_ID_SHIFT) |
+					      ATOMIC_CMD_GET);
 
-			/* increment result register offset */
-			base += 4U;
+				/* get the base address for the channel */
+				channel_base[ch] = mmio_read_32(base);
+
+				/* increment result register offset */
+				base += 4U;
+			}
+
+			/* mark state as "initialized" */
+			bpmp_init_state = BPMP_INIT_COMPLETE;
+
+			/* the channel values have to be visible across all cpus */
+			flush_dcache_range((uint64_t)channel_base,
+					   sizeof(channel_base));
+			flush_dcache_range((uint64_t)&bpmp_init_state,
+					   sizeof(bpmp_init_state));
+
+			INFO("%s: done\n", __func__);
+
+		} else {
+			ERROR("BPMP not powered on\n");
+
+			/* bpmp is not present in the system */
+			bpmp_init_state = BPMP_NOT_PRESENT;
+
+			/* communication timed out */
+			ret = -ETIMEDOUT;
 		}
+	}
 
-		/* mark state as "initialized" */
-		bpmp_init_state = BPMP_INIT_COMPLETE;
+	return ret;
+}
 
-		/* the channel values have to be visible across all cpus */
-		flush_dcache_range((uint64_t)channel_base, sizeof(channel_base));
+void tegra_bpmp_suspend(void)
+{
+	/* freeze the interface */
+	if (bpmp_init_state == BPMP_INIT_COMPLETE) {
+		bpmp_init_state = BPMP_SUSPEND_ENTRY;
 		flush_dcache_range((uint64_t)&bpmp_init_state,
 				   sizeof(bpmp_init_state));
-
-		INFO("%s: done\n", __func__);
 	}
+}
 
-	return ret;
+void tegra_bpmp_resume(void)
+{
+	uint32_t val, timeout = 0;
+
+	if (bpmp_init_state == BPMP_SUSPEND_ENTRY) {
+
+		/* check if the bpmp processor is alive. */
+		do {
+
+			val = mmio_read_32(TEGRA_RES_SEMA_BASE + STA_OFFSET);
+			if (val != SIGN_OF_LIFE) {
+				mdelay(1);
+				timeout++;
+			}
+
+		} while ((val != SIGN_OF_LIFE) && (timeout < BPMP_TIMEOUT));
+
+		if (val == SIGN_OF_LIFE) {
+
+			INFO("%s: BPMP took %d ms to resume\n", __func__, timeout);
+
+			/* mark state as "initialized" */
+			bpmp_init_state = BPMP_INIT_COMPLETE;
+
+			/* state has to be visible across all cpus */
+			flush_dcache_range((uint64_t)&bpmp_init_state,
+					   sizeof(bpmp_init_state));
+		} else {
+			ERROR("BPMP not powered on\n");
+		}
+	}
 }
diff --git a/plat/nvidia/tegra/common/drivers/bpmp_ipc/intf.c b/plat/nvidia/tegra/common/drivers/bpmp_ipc/intf.c
index 7faa2f0..2efa1bd 100644
--- a/plat/nvidia/tegra/common/drivers/bpmp_ipc/intf.c
+++ b/plat/nvidia/tegra/common/drivers/bpmp_ipc/intf.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2017-2018, NVIDIA CORPORATION. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -302,3 +302,49 @@
 
 	return ret;
 }
+
+int tegra_bpmp_ipc_enable_clock(uint32_t clk_id)
+{
+	int ret;
+	struct mrq_clk_request req;
+
+	/* only SE clocks are supported */
+	if (clk_id != TEGRA_CLK_SE) {
+		return -ENOTSUP;
+	}
+
+	/* prepare the MRQ_CLK command */
+	req.cmd_and_id = make_mrq_clk_cmd(CMD_CLK_ENABLE, clk_id);
+
+	ret = tegra_bpmp_ipc_send_req_atomic(MRQ_CLK, &req, sizeof(req),
+			NULL, 0);
+	if (ret != 0) {
+		ERROR("%s: failed for module %d with error %d\n", __func__,
+		      clk_id, ret);
+	}
+
+	return ret;
+}
+
+int tegra_bpmp_ipc_disable_clock(uint32_t clk_id)
+{
+	int ret;
+	struct mrq_clk_request req;
+
+	/* only SE clocks are supported */
+	if (clk_id != TEGRA_CLK_SE) {
+		return -ENOTSUP;
+	}
+
+	/* prepare the MRQ_CLK command */
+	req.cmd_and_id = make_mrq_clk_cmd(CMD_CLK_DISABLE, clk_id);
+
+	ret = tegra_bpmp_ipc_send_req_atomic(MRQ_CLK, &req, sizeof(req),
+			NULL, 0);
+	if (ret != 0) {
+		ERROR("%s: failed for module %d with error %d\n", __func__,
+		      clk_id, ret);
+	}
+
+	return ret;
+}
diff --git a/plat/nvidia/tegra/common/drivers/bpmp_ipc/intf.h b/plat/nvidia/tegra/common/drivers/bpmp_ipc/intf.h
index 689f8bb..7059c37 100644
--- a/plat/nvidia/tegra/common/drivers/bpmp_ipc/intf.h
+++ b/plat/nvidia/tegra/common/drivers/bpmp_ipc/intf.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2017-2018, NVIDIA CORPORATION. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -11,10 +11,10 @@
  * Flags used in IPC req
  */
 #define FLAG_DO_ACK			(U(1) << 0)
-#define FLAG_RING_DOORBELL		(U(1) << 1)
+#define FLAG_RING_DOORBELL	(U(1) << 1)
 
 /* Bit 1 is designated for CCPlex in secure world */
-#define HSP_MASTER_CCPLEX_BIT		(U(1) << 1)
+#define HSP_MASTER_CCPLEX_BIT	(U(1) << 1)
 /* Bit 19 is designated for BPMP in non-secure world */
 #define HSP_MASTER_BPMP_BIT		(U(1) << 19)
 /* Timeout to receive response from BPMP is 1 sec */
@@ -49,9 +49,10 @@
  */
 
 /**
- * MRQ code to issue a module reset command to BPMP
+ * MRQ command codes
  */
 #define MRQ_RESET			U(20)
+#define MRQ_CLK				U(22)
 
 /**
  * Reset sub-commands
@@ -71,4 +72,56 @@
 	uint32_t reset_id;
 };
 
+/**
+ * MRQ_CLK sub-commands
+ *
+ */
+enum {
+	CMD_CLK_GET_RATE = 1,
+	CMD_CLK_SET_RATE = 2,
+	CMD_CLK_ROUND_RATE = 3,
+	CMD_CLK_GET_PARENT = 4,
+	CMD_CLK_SET_PARENT = 5,
+	CMD_CLK_IS_ENABLED = 6,
+	CMD_CLK_ENABLE = 7,
+	CMD_CLK_DISABLE = 8,
+	CMD_CLK_GET_ALL_INFO = 14,
+	CMD_CLK_GET_MAX_CLK_ID = 15,
+	CMD_CLK_MAX,
+};
+
+/**
+ * Used by the sender of an #MRQ_CLK message to control clocks. The
+ * clk_request is split into several sub-commands. Some sub-commands
+ * require no additional data. Others have a sub-command specific
+ * payload
+ *
+ * |sub-command                 |payload                |
+ * |----------------------------|-----------------------|
+ * |CMD_CLK_GET_RATE            |-                      |
+ * |CMD_CLK_SET_RATE            |clk_set_rate           |
+ * |CMD_CLK_ROUND_RATE          |clk_round_rate         |
+ * |CMD_CLK_GET_PARENT          |-                      |
+ * |CMD_CLK_SET_PARENT          |clk_set_parent         |
+ * |CMD_CLK_IS_ENABLED          |-                      |
+ * |CMD_CLK_ENABLE              |-                      |
+ * |CMD_CLK_DISABLE             |-                      |
+ * |CMD_CLK_GET_ALL_INFO        |-                      |
+ * |CMD_CLK_GET_MAX_CLK_ID      |-                      |
+ *
+ */
+struct mrq_clk_request {
+	/**
+	 * sub-command and clock id concatenated to 32-bit word.
+	 * - bits[31..24] is the sub-cmd.
+	 * - bits[23..0] is the clock id
+	 */
+	uint32_t cmd_and_id;
+};
+
+/**
+ * Macro to prepare the MRQ_CLK sub-command
+ */
+#define make_mrq_clk_cmd(cmd, id)	(((cmd) << 24) | (id & 0xFFFFFF))
+
 #endif /* INTF_H */
diff --git a/plat/nvidia/tegra/common/drivers/flowctrl/flowctrl.c b/plat/nvidia/tegra/common/drivers/flowctrl/flowctrl.c
index 775ad30..bdd3ee7 100644
--- a/plat/nvidia/tegra/common/drivers/flowctrl/flowctrl.c
+++ b/plat/nvidia/tegra/common/drivers/flowctrl/flowctrl.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -15,6 +15,7 @@
 #include <flowctrl.h>
 #include <pmc.h>
 #include <tegra_def.h>
+#include <utils_def.h>
 
 #define CLK_RST_DEV_L_SET		0x300
 #define CLK_RST_DEV_L_CLR		0x304
@@ -76,6 +77,47 @@
 }
 
 /*******************************************************************************
+ * After this, no core can wake from C7 until the action is reverted.
+ * If a wake up event is asserted, the FC state machine will stall until
+ * the action is reverted.
+ ******************************************************************************/
+void tegra_fc_ccplex_pgexit_lock(void)
+{
+	unsigned int i, cpu = read_mpidr() & MPIDR_CPU_MASK;
+	uint32_t flags = tegra_fc_read_32(FLOWCTRL_FC_SEQ_INTERCEPT) & ~INTERCEPT_IRQ_PENDING;;
+	uint32_t icept_cpu_flags[] = {
+		INTERCEPT_EXIT_PG_CORE0,
+		INTERCEPT_EXIT_PG_CORE1,
+		INTERCEPT_EXIT_PG_CORE2,
+		INTERCEPT_EXIT_PG_CORE3
+	};
+
+	/* set the intercept flags */
+	for (i = 0; i < ARRAY_SIZE(icept_cpu_flags); i++) {
+
+		/* skip current CPU */
+		if (i == cpu)
+			continue;
+
+		/* enable power gate exit intercept locks */
+		flags |= icept_cpu_flags[i];
+	}
+
+	tegra_fc_write_32(FLOWCTRL_FC_SEQ_INTERCEPT, flags);
+	(void)tegra_fc_read_32(FLOWCTRL_FC_SEQ_INTERCEPT);
+}
+
+/*******************************************************************************
+ * Revert the ccplex powergate exit locks
+ ******************************************************************************/
+void tegra_fc_ccplex_pgexit_unlock(void)
+{
+	/* clear lock bits, clear pending interrupts */
+	tegra_fc_write_32(FLOWCTRL_FC_SEQ_INTERCEPT, INTERCEPT_IRQ_PENDING);
+	(void)tegra_fc_read_32(FLOWCTRL_FC_SEQ_INTERCEPT);
+}
+
+/*******************************************************************************
  * Powerdn the current CPU
  ******************************************************************************/
 void tegra_fc_cpu_powerdn(uint32_t mpidr)
@@ -129,6 +171,31 @@
 }
 
 /*******************************************************************************
+ * Check if cluster idle or power down state is allowed from this CPU
+ ******************************************************************************/
+bool tegra_fc_is_ccx_allowed(void)
+{
+	unsigned int i, cpu = read_mpidr() & MPIDR_CPU_MASK;
+	uint32_t val;
+	bool ccx_allowed = true;
+
+	for (i = 0; i < ARRAY_SIZE(flowctrl_offset_cpu_csr); i++) {
+
+		/* skip current CPU */
+		if (i == cpu)
+			continue;
+
+		/* check if all other CPUs are already halted */
+		val = mmio_read_32(flowctrl_offset_cpu_csr[i]);
+		if ((val & FLOWCTRL_CSR_HALT_MASK) == 0U) {
+			ccx_allowed = false;
+		}
+	}
+
+	return ccx_allowed;
+}
+
+/*******************************************************************************
  * Suspend the entire SoC
  ******************************************************************************/
 void tegra_fc_soc_powerdn(uint32_t mpidr)
@@ -190,22 +257,19 @@
 }
 
 /*******************************************************************************
- * Reset BPMP processor
+ * Power ON BPMP processor
  ******************************************************************************/
-void tegra_fc_reset_bpmp(void)
+void tegra_fc_bpmp_on(uint32_t entrypoint)
 {
-	uint32_t val;
-
 	/* halt BPMP */
 	tegra_fc_write_32(FLOWCTRL_HALT_BPMP_EVENTS, FLOWCTRL_WAITEVENT);
 
 	/* Assert BPMP reset */
 	mmio_write_32(TEGRA_CAR_RESET_BASE + CLK_RST_DEV_L_SET, CLK_BPMP_RST);
 
-	/* Restore reset address (stored in PMC_SCRATCH39) */
-	val = tegra_pmc_read_32(PMC_SCRATCH39);
-	mmio_write_32(TEGRA_EVP_BASE + EVP_BPMP_RESET_VECTOR, val);
-	while (val != mmio_read_32(TEGRA_EVP_BASE + EVP_BPMP_RESET_VECTOR))
+	/* Set reset address (stored in PMC_SCRATCH39) */
+	mmio_write_32(TEGRA_EVP_BASE + EVP_BPMP_RESET_VECTOR, entrypoint);
+	while (entrypoint != mmio_read_32(TEGRA_EVP_BASE + EVP_BPMP_RESET_VECTOR))
 		; /* wait till value reaches EVP_BPMP_RESET_VECTOR */
 
 	/* Wait for 2us before de-asserting the reset signal. */
@@ -217,3 +281,42 @@
 	/* Un-halt BPMP */
 	tegra_fc_write_32(FLOWCTRL_HALT_BPMP_EVENTS, 0);
 }
+
+/*******************************************************************************
+ * Power OFF BPMP processor
+ ******************************************************************************/
+void tegra_fc_bpmp_off(void)
+{
+	/* halt BPMP */
+	tegra_fc_write_32(FLOWCTRL_HALT_BPMP_EVENTS, FLOWCTRL_WAITEVENT);
+
+	/* Assert BPMP reset */
+	mmio_write_32(TEGRA_CAR_RESET_BASE + CLK_RST_DEV_L_SET, CLK_BPMP_RST);
+
+	/* Clear reset address */
+	mmio_write_32(TEGRA_EVP_BASE + EVP_BPMP_RESET_VECTOR, 0);
+	while (0 != mmio_read_32(TEGRA_EVP_BASE + EVP_BPMP_RESET_VECTOR))
+		; /* wait till value reaches EVP_BPMP_RESET_VECTOR */
+}
+
+/*******************************************************************************
+ * Route legacy FIQ to the GICD
+ ******************************************************************************/
+void tegra_fc_enable_fiq_to_ccplex_routing(void)
+{
+	uint32_t val = tegra_fc_read_32(FLOW_CTLR_FLOW_DBG_QUAL);
+
+	/* set the bit to pass FIQs to the GICD */
+	tegra_fc_write_32(FLOW_CTLR_FLOW_DBG_QUAL, val | FLOWCTRL_FIQ2CCPLEX_ENABLE);
+}
+
+/*******************************************************************************
+ * Disable routing legacy FIQ to the GICD
+ ******************************************************************************/
+void tegra_fc_disable_fiq_to_ccplex_routing(void)
+{
+	uint32_t val = tegra_fc_read_32(FLOW_CTLR_FLOW_DBG_QUAL);
+
+	/* clear the bit to pass FIQs to the GICD */
+	tegra_fc_write_32(FLOW_CTLR_FLOW_DBG_QUAL, val & ~FLOWCTRL_FIQ2CCPLEX_ENABLE);
+}
diff --git a/plat/nvidia/tegra/common/drivers/pmc/pmc.c b/plat/nvidia/tegra/common/drivers/pmc/pmc.c
index b9ff511..6c5a73b 100644
--- a/plat/nvidia/tegra/common/drivers/pmc/pmc.c
+++ b/plat/nvidia/tegra/common/drivers/pmc/pmc.c
@@ -17,7 +17,7 @@
 
 /* Module IDs used during power ungate procedure */
 static const uint32_t pmc_cpu_powergate_id[4] = {
-	0, /* CPU 0 */
+	14, /* CPU 0 */
 	9, /* CPU 1 */
 	10, /* CPU 2 */
 	11 /* CPU 3 */
@@ -98,6 +98,45 @@
 }
 
 /*******************************************************************************
+ * Find out if this is the last standing CPU
+ ******************************************************************************/
+bool tegra_pmc_is_last_on_cpu(void)
+{
+	int i, cpu = read_mpidr() & MPIDR_CPU_MASK;
+	uint32_t val = tegra_pmc_read_32(PMC_PWRGATE_STATUS);;
+	bool status = true;
+
+	/* check if this is the last standing CPU */
+	for (i = 0; i < PLATFORM_MAX_CPUS_PER_CLUSTER; i++) {
+
+		/* skip the current CPU */
+		if (i == cpu)
+			continue;
+
+		/* are other CPUs already power gated? */
+		if ((val & ((uint32_t)1 << pmc_cpu_powergate_id[i])) != 0U) {
+			status = false;
+		}
+	}
+
+	return status;
+}
+
+/*******************************************************************************
+ * Handler to be called on exiting System suspend. Right now only DPD registers
+ * are cleared.
+ ******************************************************************************/
+void tegra_pmc_resume(void)
+{
+
+	/* Clear DPD sample */
+	mmio_write_32((TEGRA_PMC_BASE + PMC_IO_DPD_SAMPLE), 0x0);
+
+	/* Clear DPD Enable */
+	mmio_write_32((TEGRA_PMC_BASE + PMC_DPD_ENABLE_0), 0x0);
+}
+
+/*******************************************************************************
  * Restart the system
  ******************************************************************************/
 __dead2 void tegra_pmc_system_reset(void)
diff --git a/plat/nvidia/tegra/common/drivers/spe/shared_console.S b/plat/nvidia/tegra/common/drivers/spe/shared_console.S
index a9f0334..c1fbc84 100644
--- a/plat/nvidia/tegra/common/drivers/spe/shared_console.S
+++ b/plat/nvidia/tegra/common/drivers/spe/shared_console.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -63,12 +63,28 @@
 	/* Check the input parameter */
 	cbz	x1, putc_error
 
+	/* Prepend '\r' to '\n' */
+	cmp	w0, #0xA
+	b.ne	2f
+
 	/* wait until spe is ready */
 1:	ldr	w2, [x1]
 	and	w2, w2, #CONSOLE_IS_BUSY
 	cbnz	w2, 1b
 
 	/* spe is ready */
+	mov	w2, #0xD		/* '\r' */
+	and	w2, w2, #0xFF
+	mov	w3, #(CONSOLE_WRITE | (1 << CONSOLE_NUM_BYTES_SHIFT))
+	orr	w2, w2, w3
+	str	w2, [x1]
+
+	/* wait until spe is ready */
+2:	ldr	w2, [x1]
+	and	w2, w2, #CONSOLE_IS_BUSY
+	cbnz	w2, 2b
+
+	/* spe is ready */
 	mov	w2, w0
 	and	w2, w2, #0xFF
 	mov	w3, #(CONSOLE_WRITE | (1 << CONSOLE_NUM_BYTES_SHIFT))
diff --git a/plat/nvidia/tegra/common/tegra_bl31_setup.c b/plat/nvidia/tegra/common/tegra_bl31_setup.c
index 908e4f2..c9beb14 100644
--- a/plat/nvidia/tegra/common/tegra_bl31_setup.c
+++ b/plat/nvidia/tegra/common/tegra_bl31_setup.c
@@ -162,13 +162,15 @@
 	}
 
 	/*
-	 * Parse platform specific parameters - TZDRAM aperture base and size
+	 * Parse platform specific parameters
 	 */
 	assert(plat_params != NULL);
 	plat_bl31_params_from_bl2.tzdram_base = plat_params->tzdram_base;
 	plat_bl31_params_from_bl2.tzdram_size = plat_params->tzdram_size;
 	plat_bl31_params_from_bl2.uart_id = plat_params->uart_id;
 	plat_bl31_params_from_bl2.l2_ecc_parity_prot_dis = plat_params->l2_ecc_parity_prot_dis;
+	plat_bl31_params_from_bl2.sc7entry_fw_size = plat_params->sc7entry_fw_size;
+	plat_bl31_params_from_bl2.sc7entry_fw_base = plat_params->sc7entry_fw_base;
 
 	/*
 	 * It is very important that we run either from TZDRAM or TZSRAM base.
@@ -404,6 +406,14 @@
 	 */
 	boot_profiler_add_record("[TF] arch setup entry");
 
+	/* add MMIO space */
+	plat_mmio_map = plat_get_mmio_map();
+	if (plat_mmio_map != NULL) {
+		mmap_add(plat_mmio_map);
+	} else {
+		WARN("MMIO map not available\n");
+	}
+
 	/* add memory regions */
 	mmap_add_region(rw_start, rw_start,
 			rw_size,
@@ -415,14 +425,6 @@
 			code_size,
 			MT_CODE | MT_SECURE);
 
-	/* map TZDRAM used by BL31 as coherent memory */
-	if (TEGRA_TZRAM_BASE == tegra_bl31_phys_base) {
-		mmap_add_region(params_from_bl2->tzdram_base,
-				params_from_bl2->tzdram_base,
-				BL31_SIZE,
-				MT_DEVICE | MT_RW | MT_SECURE);
-	}
-
 #if USE_COHERENT_MEM
 	coh_start = total_base + (BL_COHERENT_RAM_BASE - BL31_RO_BASE);
 	coh_size = BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE;
@@ -432,18 +434,12 @@
 			(uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE);
 #endif
 
-	/* map on-chip free running uS timer */
-	mmap_add_region(page_align(TEGRA_TMRUS_BASE, 0),
-			page_align(TEGRA_TMRUS_BASE, 0),
-			TEGRA_TMRUS_SIZE,
-			(uint8_t)MT_DEVICE | (uint8_t)MT_RO | (uint8_t)MT_SECURE);
-
-	/* add MMIO space */
-	plat_mmio_map = plat_get_mmio_map();
-	if (plat_mmio_map != NULL) {
-		mmap_add(plat_mmio_map);
-	} else {
-		WARN("MMIO map not available\n");
+	/* map TZDRAM used by BL31 as coherent memory */
+	if (TEGRA_TZRAM_BASE == tegra_bl31_phys_base) {
+		mmap_add_region(params_from_bl2->tzdram_base,
+				params_from_bl2->tzdram_base,
+				BL31_SIZE,
+				MT_DEVICE | MT_RW | MT_SECURE);
 	}
 
 	/* set up translation tables */
diff --git a/plat/nvidia/tegra/common/tegra_fiq_glue.c b/plat/nvidia/tegra/common/tegra_fiq_glue.c
index cab2e5e..60b5595 100644
--- a/plat/nvidia/tegra/common/tegra_fiq_glue.c
+++ b/plat/nvidia/tegra/common/tegra_fiq_glue.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -16,9 +16,15 @@
 #include <lib/el3_runtime/context_mgmt.h>
 #include <plat/common/platform.h>
 
+#if ENABLE_WDT_LEGACY_FIQ_HANDLING
+#include <flowctrl.h>
+#endif
 #include <tegra_def.h>
 #include <tegra_private.h>
 
+/* Legacy FIQ used by earlier Tegra platforms */
+#define LEGACY_FIQ_PPI_WDT		28U
+
 static DEFINE_BAKERY_LOCK(tegra_fiq_lock);
 
 /*******************************************************************************
@@ -46,33 +52,58 @@
 	(void)handle;
 	(void)cookie;
 
-	bakery_lock_get(&tegra_fiq_lock);
-
 	/*
-	 * The FIQ was generated when the execution was in the non-secure
-	 * world. Save the context registers to start with.
+	 * Read the pending interrupt ID
 	 */
-	cm_el1_sysregs_context_save(NON_SECURE);
+	irq = plat_ic_get_pending_interrupt_id();
+
+	bakery_lock_get(&tegra_fiq_lock);
 
 	/*
-	 * Save elr_el3 and spsr_el3 from the saved context, and overwrite
-	 * the context with the NS fiq_handler_addr and SPSR value.
+	 * Jump to NS world only if the NS world's FIQ handler has
+	 * been registered
 	 */
-	fiq_state[cpu].elr_el3 = read_ctx_reg((el3state_ctx), (uint32_t)(CTX_ELR_EL3));
-	fiq_state[cpu].spsr_el3 = read_ctx_reg((el3state_ctx), (uint32_t)(CTX_SPSR_EL3));
+	if (ns_fiq_handler_addr != 0U) {
+
+		/*
+		 * The FIQ was generated when the execution was in the non-secure
+		 * world. Save the context registers to start with.
+		 */
+		cm_el1_sysregs_context_save(NON_SECURE);
 
+		/*
+		 * Save elr_el3 and spsr_el3 from the saved context, and overwrite
+		 * the context with the NS fiq_handler_addr and SPSR value.
+		 */
+		fiq_state[cpu].elr_el3 = read_ctx_reg((el3state_ctx), (uint32_t)(CTX_ELR_EL3));
+		fiq_state[cpu].spsr_el3 = read_ctx_reg((el3state_ctx), (uint32_t)(CTX_SPSR_EL3));
+
+		/*
+		 * Set the new ELR to continue execution in the NS world using the
+		 * FIQ handler registered earlier.
+		 */
+		cm_set_elr_el3(NON_SECURE, ns_fiq_handler_addr);
+	}
+
+#if ENABLE_WDT_LEGACY_FIQ_HANDLING
 	/*
-	 * Set the new ELR to continue execution in the NS world using the
-	 * FIQ handler registered earlier.
+	 * Tegra platforms that use LEGACY_FIQ as the watchdog timer FIQ
+	 * need to issue an IPI to other CPUs, to allow them to handle
+	 * the "system hung" scenario. This interrupt is passed to the GICD
+	 * via the Flow Controller. So, once we receive this interrupt,
+	 * disable the routing so that we can mark it as "complete" in the
+	 * GIC later.
 	 */
-	assert(ns_fiq_handler_addr != 0ULL);
-	write_ctx_reg((el3state_ctx), (uint32_t)(CTX_ELR_EL3), (ns_fiq_handler_addr));
+	if (irq == LEGACY_FIQ_PPI_WDT) {
+		tegra_fc_disable_fiq_to_ccplex_routing();
+	}
+#endif
 
 	/*
 	 * Mark this interrupt as complete to avoid a FIQ storm.
 	 */
-	irq = plat_ic_acknowledge_interrupt();
 	if (irq < 1022U) {
+		(void)plat_ic_acknowledge_interrupt();
 		plat_ic_end_of_interrupt(irq);
 	}
 
diff --git a/plat/nvidia/tegra/common/tegra_pm.c b/plat/nvidia/tegra/common/tegra_pm.c
index 2805272..e06a116 100644
--- a/plat/nvidia/tegra/common/tegra_pm.c
+++ b/plat/nvidia/tegra/common/tegra_pm.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -41,6 +41,7 @@
  * provide typical implementations that will be overridden by a SoC.
  */
 #pragma weak tegra_soc_pwr_domain_suspend_pwrdown_early
+#pragma weak tegra_soc_cpu_standby
 #pragma weak tegra_soc_pwr_domain_suspend
 #pragma weak tegra_soc_pwr_domain_on
 #pragma weak tegra_soc_pwr_domain_off
@@ -55,6 +56,12 @@
 	return PSCI_E_NOT_SUPPORTED;
 }
 
+int32_t tegra_soc_cpu_standby(plat_local_state_t cpu_state)
+{
+	(void)cpu_state;
+	return PSCI_E_SUCCESS;
+}
+
 int32_t tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state)
 {
 	(void)target_state;
@@ -139,14 +146,37 @@
  ******************************************************************************/
 void tegra_cpu_standby(plat_local_state_t cpu_state)
 {
+	u_register_t saved_scr_el3;
+
 	(void)cpu_state;
 
+	/* Tegra SoC specific handler */
+	if (tegra_soc_cpu_standby(cpu_state) != PSCI_E_SUCCESS)
+		ERROR("%s failed\n", __func__);
+
+	saved_scr_el3 = read_scr_el3();
+
+	/*
+	 * As per ARM ARM D1.17.2, any physical IRQ interrupt received by the
+	 * PE will be treated as a wake-up event, if SCR_EL3.IRQ is set to '1',
+	 * irrespective of the value of the PSTATE.I bit value.
+	 */
+	write_scr_el3(saved_scr_el3 | SCR_IRQ_BIT);
+
 	/*
 	 * Enter standby state
-	 * dsb is good practice before using wfi to enter low power states
+	 *
+	 * dsb & isb is good practice before using wfi to enter low power states
 	 */
 	dsb();
+	isb();
 	wfi();
+
+	/*
+	 * Restore saved scr_el3 that has IRQ bit cleared as we don't want EL3
+	 * handling any further interrupts
+	 */
+	write_scr_el3(saved_scr_el3);
 }
 
 /*******************************************************************************
@@ -244,7 +274,7 @@
 	/*
 	 * Initialize the GIC cpu and distributor interfaces
 	 */
-	plat_gic_setup();
+	tegra_gic_init();
 
 	/*
 	 * Check if we are exiting from deep sleep.
diff --git a/plat/nvidia/tegra/common/tegra_sip_calls.c b/plat/nvidia/tegra/common/tegra_sip_calls.c
index 4955b2f..957300e 100644
--- a/plat/nvidia/tegra/common/tegra_sip_calls.c
+++ b/plat/nvidia/tegra/common/tegra_sip_calls.c
@@ -116,6 +116,16 @@
 			/* new video memory carveout settings */
 			tegra_memctrl_videomem_setup(x1, local_x2_32);
 
+			/*
+			 * Ensure again that GPU is still in reset after VPR resize
+			 */
+			regval = mmio_read_32(TEGRA_CAR_RESET_BASE +
+					      TEGRA_GPU_RESET_REG_OFFSET);
+			if ((regval & GPU_RESET_BIT) == 0U) {
+				mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_GPU_RESET_GPU_SET_OFFSET,
+									GPU_SET_BIT);
+			}
+
 			SMC_RET1(handle, 0);
 
 		/*
diff --git a/plat/nvidia/tegra/include/drivers/bpmp.h b/plat/nvidia/tegra/include/drivers/bpmp.h
index 03da6f6..dc3fb6b 100644
--- a/plat/nvidia/tegra/include/drivers/bpmp.h
+++ b/plat/nvidia/tegra/include/drivers/bpmp.h
@@ -27,8 +27,10 @@
 #define SIGN_OF_LIFE		0xAAAAAAAAU
 
 /* flags to indicate bpmp driver's state */
+#define BPMP_NOT_PRESENT	0xF00DBEEFU
 #define BPMP_INIT_COMPLETE	0xBEEFF00DU
 #define BPMP_INIT_PENDING	0xDEADBEEFU
+#define BPMP_SUSPEND_ENTRY	0xF00DCAFEU
 
 /* requests serviced by the bpmp */
 #define MRQ_PING		0
@@ -107,6 +109,16 @@
 int tegra_bpmp_init(void);
 
 /**
+ * Function to suspend the interface with the bpmp
+ */
+void tegra_bpmp_suspend(void);
+
+/**
+ * Function to resume the interface with the bpmp
+ */
+void tegra_bpmp_resume(void);
+
+/**
  * Handler to send a MRQ_* command to the bpmp
  */
 int32_t tegra_bpmp_send_receive_atomic(int mrq, const void *ob_data, int ob_sz,
diff --git a/plat/nvidia/tegra/include/drivers/bpmp_ipc.h b/plat/nvidia/tegra/include/drivers/bpmp_ipc.h
index 9304150..d487956 100644
--- a/plat/nvidia/tegra/include/drivers/bpmp_ipc.h
+++ b/plat/nvidia/tegra/include/drivers/bpmp_ipc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -18,6 +18,11 @@
 #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);
@@ -27,4 +32,16 @@
  */
 int32_t tegra_bpmp_ipc_reset_module(uint32_t rst_id);
 
+/**
+ * Handler to enable clock to a module. Only SE device is
+ * supported for now.
+ */
+int tegra_bpmp_ipc_enable_clock(uint32_t clk_id);
+
+/**
+ * Handler to disable clock to a module. Only SE device is
+ * supported for now.
+ */
+int tegra_bpmp_ipc_disable_clock(uint32_t clk_id);
+
 #endif /* __BPMP_IPC_H__ */
diff --git a/plat/nvidia/tegra/include/drivers/flowctrl.h b/plat/nvidia/tegra/include/drivers/flowctrl.h
index 3122181..54336b0 100644
--- a/plat/nvidia/tegra/include/drivers/flowctrl.h
+++ b/plat/nvidia/tegra/include/drivers/flowctrl.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -11,7 +11,7 @@
 
 #include <tegra_def.h>
 
-#define FLOWCTRL_HALT_CPU0_EVENTS	0x0U
+#define FLOWCTRL_HALT_CPU0_EVENTS	(0x0U)
 #define  FLOWCTRL_WAITEVENT		(2U << 29)
 #define  FLOWCTRL_WAIT_FOR_INTERRUPT	(4U << 29)
 #define  FLOWCTRL_JTAG_RESUME		(1U << 28)
@@ -20,19 +20,46 @@
 #define  FLOWCTRL_HALT_LIC_FIQ		(1U << 10)
 #define  FLOWCTRL_HALT_GIC_IRQ		(1U << 9)
 #define  FLOWCTRL_HALT_GIC_FIQ		(1U << 8)
-#define FLOWCTRL_HALT_BPMP_EVENTS	0x4U
-#define FLOWCTRL_CPU0_CSR		0x8U
-#define  FLOW_CTRL_CSR_PWR_OFF_STS	(1U << 16)
+#define FLOWCTRL_HALT_BPMP_EVENTS	(0x4U)
+#define FLOWCTRL_CPU0_CSR		(0x8U)
+#define  FLOWCTRL_CSR_HALT_MASK		(1U << 22)
+#define  FLOWCTRL_CSR_PWR_OFF_STS	(1U << 16)
 #define  FLOWCTRL_CSR_INTR_FLAG		(1U << 15)
 #define  FLOWCTRL_CSR_EVENT_FLAG	(1U << 14)
 #define  FLOWCTRL_CSR_IMMEDIATE_WAKE	(1U << 3)
 #define  FLOWCTRL_CSR_ENABLE		(1U << 0)
-#define FLOWCTRL_HALT_CPU1_EVENTS	0x14U
-#define FLOWCTRL_CPU1_CSR		0x18U
-#define FLOWCTRL_CC4_CORE0_CTRL		0x6cU
-#define FLOWCTRL_WAIT_WFI_BITMAP	0x100U
-#define FLOWCTRL_L2_FLUSH_CONTROL	0x94U
-#define FLOWCTRL_BPMP_CLUSTER_CONTROL	0x98U
+#define FLOWCTRL_HALT_CPU1_EVENTS	(0x14U)
+#define FLOWCTRL_CPU1_CSR		(0x18U)
+#define FLOW_CTLR_FLOW_DBG_QUAL		(0x50U)
+#define  FLOWCTRL_FIQ2CCPLEX_ENABLE	(1U << 28)
+#define FLOWCTRL_FC_SEQ_INTERCEPT	(0x5cU)
+#define  INTERCEPT_IRQ_PENDING		(0xffU)
+#define  INTERCEPT_HVC			(U(1) << 21)
+#define  INTERCEPT_ENTRY_CC4		(U(1) << 20)
+#define  INTERCEPT_ENTRY_PG_NONCPU	(U(1) << 19)
+#define  INTERCEPT_EXIT_PG_NONCPU	(U(1) << 18)
+#define  INTERCEPT_ENTRY_RG_CPU		(U(1) << 17)
+#define  INTERCEPT_EXIT_RG_CPU		(U(1) << 16)
+#define  INTERCEPT_ENTRY_PG_CORE0	(U(1) << 15)
+#define  INTERCEPT_EXIT_PG_CORE0	(U(1) << 14)
+#define  INTERCEPT_ENTRY_PG_CORE1	(U(1) << 13)
+#define  INTERCEPT_EXIT_PG_CORE1	(U(1) << 12)
+#define  INTERCEPT_ENTRY_PG_CORE2	(U(1) << 11)
+#define  INTERCEPT_EXIT_PG_CORE2	(U(1) << 10)
+#define  INTERCEPT_ENTRY_PG_CORE3	(U(1) << 9)
+#define  INTERCEPT_EXIT_PG_CORE3	(U(1) << 8)
+#define  INTERRUPT_PENDING_NONCPU	(U(1) << 7)
+#define  INTERRUPT_PENDING_CRAIL	(U(1) << 6)
+#define  INTERRUPT_PENDING_CORE0	(U(1) << 5)
+#define  INTERRUPT_PENDING_CORE1	(U(1) << 4)
+#define  INTERRUPT_PENDING_CORE2	(U(1) << 3)
+#define  INTERRUPT_PENDING_CORE3	(U(1) << 2)
+#define  CC4_INTERRUPT_PENDING		(U(1) << 1)
+#define  HVC_INTERRUPT_PENDING		(U(1) << 0)
+#define FLOWCTRL_CC4_CORE0_CTRL		(0x6cU)
+#define FLOWCTRL_WAIT_WFI_BITMAP	(0x100U)
+#define FLOWCTRL_L2_FLUSH_CONTROL	(0x94U)
+#define FLOWCTRL_BPMP_CLUSTER_CONTROL	(0x98U)
 #define  FLOWCTRL_BPMP_CLUSTER_PWRON_LOCK	(1U << 2)
 
 #define FLOWCTRL_ENABLE_EXT		12U
@@ -50,13 +77,19 @@
 	mmio_write_32(TEGRA_FLOWCTRL_BASE + off, val);
 }
 
+void tegra_fc_bpmp_on(uint32_t entrypoint);
+void tegra_fc_bpmp_off(void);
+void tegra_fc_ccplex_pgexit_lock(void);
+void tegra_fc_ccplex_pgexit_unlock(void);
 void tegra_fc_cluster_idle(uint32_t midr);
 void tegra_fc_cpu_powerdn(uint32_t mpidr);
 void tegra_fc_cluster_powerdn(uint32_t midr);
-void tegra_fc_soc_powerdn(uint32_t midr);
 void tegra_fc_cpu_on(int cpu);
 void tegra_fc_cpu_off(int cpu);
+void tegra_fc_disable_fiq_to_ccplex_routing(void);
+void tegra_fc_enable_fiq_to_ccplex_routing(void);
+bool tegra_fc_is_ccx_allowed(void);
 void tegra_fc_lock_active_cluster(void);
-void tegra_fc_reset_bpmp(void);
+void tegra_fc_soc_powerdn(uint32_t midr);
 
 #endif /* FLOWCTRL_H */
diff --git a/plat/nvidia/tegra/include/drivers/pmc.h b/plat/nvidia/tegra/include/drivers/pmc.h
index a01a4b6..32252a2 100644
--- a/plat/nvidia/tegra/include/drivers/pmc.h
+++ b/plat/nvidia/tegra/include/drivers/pmc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,22 +9,37 @@
 
 #include <lib/mmio.h>
 #include <lib/utils_def.h>
+#include <stdbool.h>
 
 #include <tegra_def.h>
 
 #define PMC_CONFIG				U(0x0)
+#define PMC_IO_DPD_SAMPLE			U(0x20)
+#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_CRYPTO_OP_0				U(0xf4)
 #define  PMC_TOGGLE_START			U(0x100)
 #define PMC_SCRATCH39				U(0x138)
+#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_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_WRITE34_ON		(U(1) << 20)
 #define  PMC_SECURE_DISABLE3_WRITE35_ON		(U(1) << 22)
 #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_SCRATCH201				U(0x844)
 
 static inline uint32_t tegra_pmc_read_32(uint32_t off)
 {
@@ -36,9 +51,11 @@
 	mmio_write_32(TEGRA_PMC_BASE + off, val);
 }
 
+void tegra_pmc_cpu_on(int32_t cpu);
 void tegra_pmc_cpu_setup(uint64_t reset_addr);
+bool tegra_pmc_is_last_on_cpu(void);
 void tegra_pmc_lock_cpu_vectors(void);
-void tegra_pmc_cpu_on(int32_t cpu);
+void tegra_pmc_resume(void);
 __dead2 void tegra_pmc_system_reset(void);
 
 #endif /* PMC_H */
diff --git a/plat/nvidia/tegra/include/drivers/smmu.h b/plat/nvidia/tegra/include/drivers/smmu.h
index 41b0c51..424a91a 100644
--- a/plat/nvidia/tegra/include/drivers/smmu.h
+++ b/plat/nvidia/tegra/include/drivers/smmu.h
@@ -618,9 +618,9 @@
 		.val = 0x00000000U, \
 	}
 
-#define smmu_make_gnsr0_sec_cfg(name) \
+#define smmu_make_gnsr0_sec_cfg(base_addr, name) \
 	{ \
-		.reg = TEGRA_SMMU0_BASE + SMMU_GNSR0_ ## name, \
+		.reg = base_addr + SMMU_GNSR0_ ## name, \
 		.val = 0x00000000U, \
 	}
 
@@ -628,60 +628,199 @@
  * 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(name) \
+#define smmu_make_gnsr0_nsec_cfg(base_addr, name) \
 	{ \
-		.reg = TEGRA_SMMU0_BASE + 0x400U + SMMU_GNSR0_ ## name, \
+		.reg = base_addr + 0x400U + SMMU_GNSR0_ ## name, \
 		.val = 0x00000000U, \
 	}
 
-#define smmu_make_gnsr0_smr_cfg(n) \
+#define smmu_make_gnsr0_smr_cfg(base_addr, n) \
 	{ \
-		.reg = TEGRA_SMMU0_BASE + SMMU_GNSR0_SMR ## n, \
+		.reg = base_addr + SMMU_GNSR0_SMR ## n, \
 		.val = 0x00000000U, \
 	}
 
-#define smmu_make_gnsr0_s2cr_cfg(n) \
+#define smmu_make_gnsr0_s2cr_cfg(base_addr, n) \
 	{ \
-		.reg = TEGRA_SMMU0_BASE + SMMU_GNSR0_S2CR ## n, \
+		.reg = base_addr + SMMU_GNSR0_S2CR ## n, \
 		.val = 0x00000000U, \
 	}
 
-#define smmu_make_gnsr1_cbar_cfg(n) \
+#define smmu_make_gnsr1_cbar_cfg(base_addr, n) \
 	{ \
-		.reg = TEGRA_SMMU0_BASE + (1U << PGSHIFT) + SMMU_GNSR1_CBAR ## n, \
+		.reg = base_addr + (1U << PGSHIFT) + SMMU_GNSR1_CBAR ## n, \
 		.val = 0x00000000U, \
 	}
 
-#define smmu_make_gnsr1_cba2r_cfg(n) \
+#define smmu_make_gnsr1_cba2r_cfg(base_addr, n) \
 	{ \
-		.reg = TEGRA_SMMU0_BASE + (1U << PGSHIFT) + SMMU_GNSR1_CBA2R ## n, \
+		.reg = base_addr + (1U << PGSHIFT) + SMMU_GNSR1_CBA2R ## n, \
 		.val = 0x00000000U, \
 	}
 
-#define make_smmu_cb_cfg(name, n) \
+#define smmu_make_cb_cfg(base_addr, name, n) \
 	{ \
-		.reg = TEGRA_SMMU0_BASE + (CB_SIZE >> 1) + (n * (1 << PGSHIFT)) \
+		.reg = base_addr + (CB_SIZE >> 1) + (n * (1 << PGSHIFT)) \
 			+ SMMU_CBn_ ## name, \
 		.val = 0x00000000U, \
 	}
 
-#define smmu_make_smrg_group(n)	\
-	smmu_make_gnsr0_smr_cfg(n),	\
-	smmu_make_gnsr0_s2cr_cfg(n),	\
-	smmu_make_gnsr1_cbar_cfg(n),	\
-	smmu_make_gnsr1_cba2r_cfg(n)	/* don't put "," here. */
+#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_cb_group(n)		\
-	make_smmu_cb_cfg(SCTLR, n),	\
-	make_smmu_cb_cfg(TCR2, n),	\
-	make_smmu_cb_cfg(TTBR0_LO, n),	\
-	make_smmu_cb_cfg(TTBR0_HI, n),	\
-	make_smmu_cb_cfg(TCR, n),	\
-	make_smmu_cb_cfg(PRRR_MAIR0, n),\
-	make_smmu_cb_cfg(FSR, n),	\
-	make_smmu_cb_cfg(FAR_LO, n),	\
-	make_smmu_cb_cfg(FAR_HI, n),	\
-	make_smmu_cb_cfg(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 \
 	{ \
diff --git a/plat/nvidia/tegra/include/plat_macros.S b/plat/nvidia/tegra/include/plat_macros.S
index 01ae821..2796c5d 100644
--- a/plat/nvidia/tegra/include/plat_macros.S
+++ b/plat/nvidia/tegra/include/plat_macros.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -50,7 +50,7 @@
 	bl	asm_print_hex
 	adr	x4, spacer
 	bl	asm_print_str
-	ldr	x4, [x7], #8
+	ldr	w4, [x7], #4
 	bl	asm_print_hex
 	adr	x4, newline
 	bl	asm_print_str
diff --git a/plat/nvidia/tegra/include/platform_def.h b/plat/nvidia/tegra/include/platform_def.h
index 0a0126b..334ad12 100644
--- a/plat/nvidia/tegra/include/platform_def.h
+++ b/plat/nvidia/tegra/include/platform_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -54,12 +54,6 @@
 #define BL32_LIMIT			TZDRAM_END
 
 /*******************************************************************************
- * Platform specific page table and MMU setup constants
- ******************************************************************************/
-#define PLAT_PHY_ADDR_SPACE_SIZE	(ULL(1) << 35)
-#define PLAT_VIRT_ADDR_SPACE_SIZE	(ULL(1) << 35)
-
-/*******************************************************************************
  * Some data must be aligned on the biggest cache line size in the platform.
  * This is known only to the platform as it might have a combination of
  * integrated and external caches.
diff --git a/plat/nvidia/tegra/include/t132/tegra_def.h b/plat/nvidia/tegra/include/t132/tegra_def.h
index fd75fbc..dfed2aa 100644
--- a/plat/nvidia/tegra/include/t132/tegra_def.h
+++ b/plat/nvidia/tegra/include/t132/tegra_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -25,6 +25,12 @@
 #define PLAT_MAX_OFF_STATE		(PSTATE_ID_SOC_POWERDN + U(1))
 
 /*******************************************************************************
+ * Chip specific page table and MMU setup constants
+ ******************************************************************************/
+#define PLAT_PHY_ADDR_SPACE_SIZE	(ULL(1) << 35)
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(ULL(1) << 35)
+
+/*******************************************************************************
  * GIC memory map
  ******************************************************************************/
 #define TEGRA_GICD_BASE			U(0x50041000)
@@ -41,7 +47,9 @@
  ******************************************************************************/
 #define TEGRA_CAR_RESET_BASE		U(0x60006000)
 #define TEGRA_GPU_RESET_REG_OFFSET	U(0x28C)
+#define TEGRA_GPU_RESET_GPU_SET_OFFSET	U(0x290)
 #define  GPU_RESET_BIT			(U(1) << 24)
+#define  GPU_SET_BIT			(U(1) << 24)
 
 /*******************************************************************************
  * Tegra Flow Controller constants
diff --git a/plat/nvidia/tegra/include/t186/tegra_def.h b/plat/nvidia/tegra/include/t186/tegra_def.h
index 231f93a..da050a8 100644
--- a/plat/nvidia/tegra/include/t186/tegra_def.h
+++ b/plat/nvidia/tegra/include/t186/tegra_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -58,6 +58,12 @@
 #define PLAT_MAX_OFF_STATE		U(8)
 
 /*******************************************************************************
+ * Chip specific page table and MMU setup constants
+ ******************************************************************************/
+#define PLAT_PHY_ADDR_SPACE_SIZE	(ULL(1) << 35)
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(ULL(1) << 35)
+
+/*******************************************************************************
  * Secure IRQ definitions
  ******************************************************************************/
 #define TEGRA186_TOP_WDT_IRQ		U(49)
@@ -210,7 +216,9 @@
  ******************************************************************************/
 #define TEGRA_CAR_RESET_BASE		U(0x05000000)
 #define TEGRA_GPU_RESET_REG_OFFSET	U(0x30)
+#define TEGRA_GPU_RESET_GPU_SET_OFFSET	U(0x34)
 #define  GPU_RESET_BIT			(U(1) << 0)
+#define  GPU_SET_BIT			(U(1) << 0)
 #define TEGRA_GPCDMA_RST_SET_REG_OFFSET	U(0x6A0004)
 #define TEGRA_GPCDMA_RST_CLR_REG_OFFSET	U(0x6A0008)
 
diff --git a/plat/nvidia/tegra/include/t210/tegra_def.h b/plat/nvidia/tegra/include/t210/tegra_def.h
index 75919e1..bbcfdc5 100644
--- a/plat/nvidia/tegra/include/t210/tegra_def.h
+++ b/plat/nvidia/tegra/include/t210/tegra_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -14,7 +14,6 @@
  ******************************************************************************/
 #define PSTATE_ID_CORE_POWERDN		U(7)
 #define PSTATE_ID_CLUSTER_IDLE		U(16)
-#define PSTATE_ID_CLUSTER_POWERDN	U(17)
 #define PSTATE_ID_SOC_POWERDN		U(27)
 
 /*******************************************************************************
@@ -33,9 +32,22 @@
 #define PLAT_MAX_OFF_STATE		(PSTATE_ID_SOC_POWERDN + U(1))
 
 /*******************************************************************************
+ * Chip specific page table and MMU setup constants
+ ******************************************************************************/
+#define PLAT_PHY_ADDR_SPACE_SIZE	(ULL(1) << 35)
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(ULL(1) << 35)
+
+/*******************************************************************************
+ * SC7 entry firmware's header size
+ ******************************************************************************/
+#define SC7ENTRY_FW_HEADER_SIZE_BYTES	U(0x400)
+
+/*******************************************************************************
  * iRAM memory constants
  ******************************************************************************/
-#define TEGRA_IRAM_BASE			0x40000000
+#define TEGRA_IRAM_BASE			U(0x40000000)
+#define TEGRA_IRAM_A_SIZE		U(0x10000) /* 64KB */
+#define TEGRA_IRAM_SIZE			U(40000) /* 256KB */
 
 /*******************************************************************************
  * GIC memory map
@@ -44,6 +56,11 @@
 #define TEGRA_GICC_BASE			U(0x50042000)
 
 /*******************************************************************************
+ * Secure IRQ definitions
+ ******************************************************************************/
+#define TEGRA210_WDT_CPU_LEGACY_FIQ		U(28)
+
+/*******************************************************************************
  * Tegra Memory Select Switch Controller constants
  ******************************************************************************/
 #define TEGRA_MSELECT_BASE		U(0x50060000)
@@ -84,21 +101,55 @@
  * Tegra Clock and Reset Controller constants
  ******************************************************************************/
 #define TEGRA_CAR_RESET_BASE		U(0x60006000)
+#define TEGRA_BOND_OUT_H		U(0x74)
+#define  APB_DMA_LOCK_BIT		(U(1) << 2)
+#define  AHB_DMA_LOCK_BIT		(U(1) << 1)
+#define TEGRA_BOND_OUT_U		U(0x78)
+#define  IRAM_D_LOCK_BIT		(U(1) << 23)
+#define  IRAM_C_LOCK_BIT		(U(1) << 22)
+#define  IRAM_B_LOCK_BIT		(U(1) << 21)
 #define TEGRA_GPU_RESET_REG_OFFSET	U(0x28C)
+#define TEGRA_GPU_RESET_GPU_SET_OFFSET	U(0x290)
 #define  GPU_RESET_BIT			(U(1) << 24)
+#define  GPU_SET_BIT			(U(1) << 24)
+#define TEGRA_RST_DEV_SET_Y		U(0x2a8)
+#define  NVENC_RESET_BIT		(U(1) << 27)
+#define  TSECB_RESET_BIT		(U(1) << 14)
+#define  APE_RESET_BIT			(U(1) << 6)
+#define  NVJPG_RESET_BIT		(U(1) << 3)
+#define  NVDEC_RESET_BIT		(U(1) << 2)
+#define TEGRA_RST_DEV_SET_L		U(0x300)
+#define  HOST1X_RESET_BIT		(U(1) << 28)
+#define  ISP_RESET_BIT			(U(1) << 23)
+#define  USBD_RESET_BIT			(U(1) << 22)
+#define  VI_RESET_BIT			(U(1) << 20)
+#define  SDMMC4_RESET_BIT		(U(1) << 15)
+#define  SDMMC1_RESET_BIT		(U(1) << 14)
+#define  SDMMC2_RESET_BIT		(U(1) << 9)
+#define TEGRA_RST_DEV_SET_H		U(0x308)
+#define  USB2_RESET_BIT			(U(1) << 26)
+#define  APBDMA_RESET_BIT		(U(1) << 2)
+#define  AHBDMA_RESET_BIT		(U(1) << 1)
+#define TEGRA_RST_DEV_SET_U		U(0x310)
+#define  XUSB_DEV_RESET_BIT		(U(1) << 31)
+#define  XUSB_HOST_RESET_BIT		(U(1) << 25)
+#define  TSEC_RESET_BIT			(U(1) << 19)
+#define  PCIE_RESET_BIT			(U(1) << 6)
+#define  SDMMC3_RESET_BIT		(U(1) << 5)
+#define TEGRA_RST_DEVICES_V		U(0x358)
+#define TEGRA_RST_DEVICES_W		U(0x35C)
+#define  ENTROPY_CLK_ENB_BIT		(U(1) << 21)
+#define TEGRA_CLK_OUT_ENB_V		U(0x360)
+#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_RST_DEV_SET_V		U(0x430)
+#define  SE_RESET_BIT			(U(1) << 31)
+#define  HDA_RESET_BIT			(U(1) << 29)
+#define  SATA_RESET_BIT			(U(1) << 28)
 #define TEGRA_RST_DEV_CLR_V		U(0x434)
 #define TEGRA_CLK_ENB_V			U(0x440)
 
-/* SE Clock Offsets */
-#define TEGRA_RST_DEVICES_V		0x358UL
-#define  SE_RESET_BIT 			(0x1UL << 31)
-#define TEGRA_RST_DEVICES_W		 0x35CUL
-#define  ENTROPY_CLK_ENB_BIT		(0x1UL << 21)
-#define TEGRA_CLK_OUT_ENB_V		0x360UL
-#define  SE_CLK_ENB_BIT			(0x1UL << 31)
-#define TEGRA_CLK_OUT_ENB_W		0x364UL
-#define  ENTROPY_RESET_BIT 		(0x1UL << 21)
-
 /*******************************************************************************
  * Tegra Flow Controller constants
  ******************************************************************************/
@@ -124,6 +175,10 @@
  ******************************************************************************/
 #define TEGRA_MISC_BASE			U(0x70000000)
 #define  HARDWARE_REVISION_OFFSET	U(0x804)
+#define  APB_SLAVE_SECURITY_ENABLE	U(0xC00)
+#define  PMC_SECURITY_EN_BIT		(U(1) << 13)
+#define  PINMUX_AUX_DVFS_PWM		U(0x3184)
+#define  PINMUX_PWM_TRISTATE		(U(1) << 4)
 
 /*******************************************************************************
  * Tegra UART controller base addresses
@@ -148,6 +203,7 @@
  * Tegra Power Mgmt Controller constants
  ******************************************************************************/
 #define TEGRA_PMC_BASE			U(0x7000E400)
+#define TEGRA_PMC_SIZE			U(0xC00) /* 3k */
 
 /*******************************************************************************
  * Tegra Atomics constants
@@ -181,6 +237,17 @@
 #define  PPCS_SMMU_ENABLE		(0x1U << 31)
 
 /*******************************************************************************
+ * Tegra CLDVFS constants
+ ******************************************************************************/
+#define TEGRA_CL_DVFS_BASE		U(0x70110000)
+#define DVFS_DFLL_CTRL			U(0x00)
+#define  ENABLE_OPEN_LOOP		U(1)
+#define  ENABLE_CLOSED_LOOP		U(2)
+#define DVFS_DFLL_OUTPUT_CFG		U(0x20)
+#define  DFLL_OUTPUT_CFG_I2C_EN_BIT	(U(1) << 30)
+#define  DFLL_OUTPUT_CFG_CLK_EN_BIT	(U(1) << 6)
+
+/*******************************************************************************
  * Tegra SE constants
  ******************************************************************************/
 #define TEGRA_SE1_BASE			U(0x70012000)
diff --git a/plat/nvidia/tegra/include/tegra_private.h b/plat/nvidia/tegra/include/tegra_private.h
index 68b4624..cdd9e08 100644
--- a/plat/nvidia/tegra/include/tegra_private.h
+++ b/plat/nvidia/tegra/include/tegra_private.h
@@ -46,6 +46,10 @@
 	int32_t l2_ecc_parity_prot_dis;
 	/* SHMEM base address for storing the boot logs */
 	uint64_t boot_profiler_shmem_base;
+	/* System Suspend Entry Firmware size */
+	uint64_t sc7entry_fw_size;
+	/* System Suspend Entry Firmware base address */
+	uint64_t sc7entry_fw_base;
 } plat_params_from_bl2_t;
 
 /*******************************************************************************
@@ -97,6 +101,7 @@
 void tegra_pm_system_suspend_entry(void);
 void tegra_pm_system_suspend_exit(void);
 int32_t tegra_system_suspended(void);
+int32_t tegra_soc_cpu_standby(plat_local_state_t cpu_state);
 int32_t tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state);
 int32_t tegra_soc_pwr_domain_on(u_register_t mpidr);
 int32_t tegra_soc_pwr_domain_off(const psci_power_state_t *target_state);
diff --git a/plat/nvidia/tegra/platform.mk b/plat/nvidia/tegra/platform.mk
index 614d2a2..6ef1900 100644
--- a/plat/nvidia/tegra/platform.mk
+++ b/plat/nvidia/tegra/platform.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -34,6 +34,9 @@
 # enable D-cache early during CPU warmboot
 WARMBOOT_ENABLE_DCACHE_EARLY := 1
 
+# remove the standard libc
+OVERRIDE_LIBC		:=	1
+
 include plat/nvidia/tegra/common/tegra_common.mk
 include ${SOC_DIR}/platform_${TARGET_SOC}.mk
 
@@ -42,3 +45,17 @@
 
 # platform cflags (enable signed comparisons, disable stdlib)
 TF_CFLAGS	+= -Wsign-compare -nostdlib
+
+# override with necessary libc files for the Tegra platform
+override LIBC_SRCS :=	$(addprefix lib/libc/,		\
+			assert.c			\
+			memcpy.c			\
+			memmove.c			\
+			memset.c			\
+			printf.c			\
+			putchar.c			\
+			strlen.c			\
+			snprintf.c)
+
+INCLUDES	+=	-Iinclude/lib/libc		\
+			-Iinclude/lib/libc/$(ARCH)	\
diff --git a/plat/nvidia/tegra/soc/t132/plat_setup.c b/plat/nvidia/tegra/soc/t132/plat_setup.c
index 3f9cda9..fef5e0a 100644
--- a/plat/nvidia/tegra/soc/t132/plat_setup.c
+++ b/plat/nvidia/tegra/soc/t132/plat_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -101,4 +101,5 @@
 void plat_gic_setup(void)
 {
 	tegra_gic_setup(NULL, 0);
+	tegra_gic_init();
 }
diff --git a/plat/nvidia/tegra/soc/t186/plat_memctrl.c b/plat/nvidia/tegra/soc/t186/plat_memctrl.c
index 376ee86..df94396 100644
--- a/plat/nvidia/tegra/soc/t186/plat_memctrl.c
+++ b/plat/nvidia/tegra/soc/t186/plat_memctrl.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -94,7 +94,7 @@
  * Array to hold the security configs for stream IDs
  ******************************************************************************/
 const static mc_streamid_security_cfg_t tegra186_streamid_sec_cfgs[] = {
-	mc_make_sec_cfg(SCEW, NON_SECURE, NO_OVERRIDE, ENABLE),
+	mc_make_sec_cfg(SCEW, NON_SECURE, NO_OVERRIDE, DISABLE),
 	mc_make_sec_cfg(AFIR, NON_SECURE, OVERRIDE, ENABLE),
 	mc_make_sec_cfg(AFIW, NON_SECURE, OVERRIDE, ENABLE),
 	mc_make_sec_cfg(NVDISPLAYR1, NON_SECURE, OVERRIDE, ENABLE),
@@ -109,17 +109,17 @@
 	mc_make_sec_cfg(SATAW, NON_SECURE, OVERRIDE, ENABLE),
 	mc_make_sec_cfg(UFSHCW, NON_SECURE, OVERRIDE, ENABLE),
 	mc_make_sec_cfg(SDMMCR, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(SCEDMAW, NON_SECURE, NO_OVERRIDE, ENABLE),
+	mc_make_sec_cfg(SCEDMAW, NON_SECURE, NO_OVERRIDE, DISABLE),
 	mc_make_sec_cfg(UFSHCR, NON_SECURE, OVERRIDE, ENABLE),
 	mc_make_sec_cfg(SDMMCWAA, NON_SECURE, OVERRIDE, ENABLE),
 	mc_make_sec_cfg(SESWR, NON_SECURE, NO_OVERRIDE, ENABLE),
 	mc_make_sec_cfg(MPCORER, NON_SECURE, OVERRIDE, ENABLE),
 	mc_make_sec_cfg(PTCR, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(BPMPW, NON_SECURE, NO_OVERRIDE, ENABLE),
+	mc_make_sec_cfg(BPMPW, NON_SECURE, NO_OVERRIDE, DISABLE),
 	mc_make_sec_cfg(ETRW, NON_SECURE, OVERRIDE, ENABLE),
 	mc_make_sec_cfg(GPUSRD, SECURE, NO_OVERRIDE, DISABLE),
 	mc_make_sec_cfg(VICSWR, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(SCEDMAR, NON_SECURE, NO_OVERRIDE, ENABLE),
+	mc_make_sec_cfg(SCEDMAR, NON_SECURE, NO_OVERRIDE, DISABLE),
 	mc_make_sec_cfg(HDAW, NON_SECURE, OVERRIDE, ENABLE),
 	mc_make_sec_cfg(ISPWA, NON_SECURE, OVERRIDE, ENABLE),
 	mc_make_sec_cfg(EQOSW, NON_SECURE, OVERRIDE, ENABLE),
@@ -129,20 +129,20 @@
 	mc_make_sec_cfg(VIW, NON_SECURE, OVERRIDE, ENABLE),
 	mc_make_sec_cfg(AXISR, SECURE, NO_OVERRIDE, DISABLE),
 	mc_make_sec_cfg(SDMMCW, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(BPMPDMAW, NON_SECURE, NO_OVERRIDE, ENABLE),
+	mc_make_sec_cfg(BPMPDMAW, NON_SECURE, NO_OVERRIDE, DISABLE),
 	mc_make_sec_cfg(ISPRA, NON_SECURE, OVERRIDE, ENABLE),
 	mc_make_sec_cfg(NVDECSWR, NON_SECURE, NO_OVERRIDE, ENABLE),
 	mc_make_sec_cfg(XUSB_DEVW, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(NVDECSRD, NON_SECURE, NO_OVERRIDE, ENABLE),
+	mc_make_sec_cfg(NVDECSRD, NON_SECURE, NO_OVERRIDE, DISABLE),
 	mc_make_sec_cfg(MPCOREW, NON_SECURE, OVERRIDE, ENABLE),
 	mc_make_sec_cfg(NVDISPLAYR, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(BPMPDMAR, NON_SECURE, NO_OVERRIDE, ENABLE),
+	mc_make_sec_cfg(BPMPDMAR, NON_SECURE, NO_OVERRIDE, DISABLE),
 	mc_make_sec_cfg(NVJPGSWR, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(NVDECSRD1, NON_SECURE, NO_OVERRIDE, ENABLE),
+	mc_make_sec_cfg(NVDECSRD1, NON_SECURE, NO_OVERRIDE, DISABLE),
 	mc_make_sec_cfg(TSECSRD, NON_SECURE, NO_OVERRIDE, ENABLE),
 	mc_make_sec_cfg(NVJPGSRD, NON_SECURE, NO_OVERRIDE, ENABLE),
 	mc_make_sec_cfg(SDMMCWA, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(SCER, NON_SECURE, NO_OVERRIDE, ENABLE),
+	mc_make_sec_cfg(SCER, NON_SECURE, NO_OVERRIDE, DISABLE),
 	mc_make_sec_cfg(XUSB_HOSTR, NON_SECURE, OVERRIDE, ENABLE),
 	mc_make_sec_cfg(VICSRD, NON_SECURE, NO_OVERRIDE, ENABLE),
 	mc_make_sec_cfg(AONDMAR, NON_SECURE, NO_OVERRIDE, ENABLE),
@@ -151,7 +151,7 @@
 	mc_make_sec_cfg(HOST1XDMAR, NON_SECURE, NO_OVERRIDE, ENABLE),
 	mc_make_sec_cfg(EQOSR, NON_SECURE, OVERRIDE, ENABLE),
 	mc_make_sec_cfg(SATAR, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(BPMPR, NON_SECURE, NO_OVERRIDE, ENABLE),
+	mc_make_sec_cfg(BPMPR, NON_SECURE, NO_OVERRIDE, DISABLE),
 	mc_make_sec_cfg(HDAR, NON_SECURE, OVERRIDE, ENABLE),
 	mc_make_sec_cfg(SDMMCRAB, NON_SECURE, OVERRIDE, ENABLE),
 	mc_make_sec_cfg(ETRR, NON_SECURE, OVERRIDE, ENABLE),
@@ -162,10 +162,10 @@
 	mc_make_sec_cfg(TSECSWRB, NON_SECURE, NO_OVERRIDE, ENABLE),
 	mc_make_sec_cfg(ISPWB, NON_SECURE, OVERRIDE, ENABLE),
 	mc_make_sec_cfg(GPUSRD2, SECURE, NO_OVERRIDE, DISABLE),
-	mc_make_sec_cfg(APEDMAW, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(APER, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(APEW, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(APEDMAR, NON_SECURE, NO_OVERRIDE, ENABLE),
+	mc_make_sec_cfg(APEDMAW, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(APER, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(APEW, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(APEDMAR, NON_SECURE, NO_OVERRIDE, DISABLE),
 };
 
 /*******************************************************************************
@@ -219,9 +219,7 @@
 	assert(val == MC_CLIENT_HOTRESET_CTRL0_RESET_VAL);
 
 	wdata_0 = MC_CLIENT_HOTRESET_CTRL0_HDA_FLUSH_ENB |
-#if ENABLE_AFI_DEVICE
 		  MC_CLIENT_HOTRESET_CTRL0_AFI_FLUSH_ENB |
-#endif
 		  MC_CLIENT_HOTRESET_CTRL0_SATA_FLUSH_ENB |
 		  MC_CLIENT_HOTRESET_CTRL0_XUSB_HOST_FLUSH_ENB |
 		  MC_CLIENT_HOTRESET_CTRL0_XUSB_DEV_FLUSH_ENB;
@@ -271,9 +269,7 @@
 	 * MC clients with default SO_DEV override still enabled at TSA:
 	 * AONW, BPMPW, SCEW, APEW
 	 */
-#if ENABLE_AFI_DEVICE
 	mc_set_tsa_passthrough(AFIW);
-#endif
 	mc_set_tsa_passthrough(HDAW);
 	mc_set_tsa_passthrough(SATAW);
 	mc_set_tsa_passthrough(XUSB_HOSTW);
@@ -413,9 +409,7 @@
 	 * boot and strongly ordered MSS clients
 	 */
 	val = MC_PCFIFO_CLIENT_CONFIG1_RESET_VAL &
-#if ENABLE_AFI_DEVICE
 		mc_set_pcfifo_unordered_boot_so_mss(1, AFIW) &
-#endif
 		mc_set_pcfifo_unordered_boot_so_mss(1, HDAW) &
 		mc_set_pcfifo_unordered_boot_so_mss(1, SATAW);
 	tegra_mc_write_32(MC_PCFIFO_CLIENT_CONFIG1, val);
diff --git a/plat/nvidia/tegra/soc/t186/plat_setup.c b/plat/nvidia/tegra/soc/t186/plat_setup.c
index fd109e5..ef0ba4e 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-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -91,6 +91,8 @@
 			MT_DEVICE | MT_RW | MT_SECURE),
 	MAP_REGION_FLAT(TEGRA_PMC_BASE, 0x40000U, /* 256KB */
 			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(TEGRA_TMRUS_BASE, 0x1000U, /* 4KB */
+			MT_DEVICE | MT_RO | MT_SECURE),
 	MAP_REGION_FLAT(TEGRA_SCRATCH_BASE, 0x10000U, /* 64KB */
 			MT_DEVICE | MT_RW | MT_SECURE),
 	MAP_REGION_FLAT(TEGRA_MMCRAB_BASE, 0x60000U, /* 384KB */
@@ -194,14 +196,13 @@
 void plat_gic_setup(void)
 {
 	tegra_gic_setup(tegra186_interrupt_props, ARRAY_SIZE(tegra186_interrupt_props));
+	tegra_gic_init();
 
 	/*
 	 * Initialize the FIQ handler only if the platform supports any
 	 * FIQ interrupt sources.
 	 */
-	if (sizeof(tegra186_interrupt_props) > 0U) {
-		tegra_fiq_handler_setup();
-	}
+	tegra_fiq_handler_setup();
 }
 
 /*******************************************************************************
diff --git a/plat/nvidia/tegra/soc/t186/plat_smmu.c b/plat/nvidia/tegra/soc/t186/plat_smmu.c
index 95f6def..b4a7fe5 100644
--- a/plat/nvidia/tegra/soc/t186/plat_smmu.c
+++ b/plat/nvidia/tegra/soc/t186/plat_smmu.c
@@ -161,143 +161,7 @@
 	mc_make_sid_override_cfg(UFSHCR),
 	mc_make_sid_override_cfg(NVENCSWR),
 	mc_make_sid_override_cfg(AFIW),
-	smmu_make_gnsr0_nsec_cfg(CR0),
-	smmu_make_gnsr0_sec_cfg(IDR0),
-	smmu_make_gnsr0_sec_cfg(IDR1),
-	smmu_make_gnsr0_sec_cfg(IDR2),
-	smmu_make_gnsr0_nsec_cfg(GFSR),
-	smmu_make_gnsr0_nsec_cfg(GFSYNR0),
-	smmu_make_gnsr0_nsec_cfg(GFSYNR1),
-	smmu_make_gnsr0_nsec_cfg(TLBGSTATUS),
-	smmu_make_gnsr0_nsec_cfg(PIDR2),
-	smmu_make_smrg_group(0),
-	smmu_make_smrg_group(1),
-	smmu_make_smrg_group(2),
-	smmu_make_smrg_group(3),
-	smmu_make_smrg_group(4),
-	smmu_make_smrg_group(5),
-	smmu_make_smrg_group(6),
-	smmu_make_smrg_group(7),
-	smmu_make_smrg_group(8),
-	smmu_make_smrg_group(9),
-	smmu_make_smrg_group(10),
-	smmu_make_smrg_group(11),
-	smmu_make_smrg_group(12),
-	smmu_make_smrg_group(13),
-	smmu_make_smrg_group(14),
-	smmu_make_smrg_group(15),
-	smmu_make_smrg_group(16),
-	smmu_make_smrg_group(17),
-	smmu_make_smrg_group(18),
-	smmu_make_smrg_group(19),
-	smmu_make_smrg_group(20),
-	smmu_make_smrg_group(21),
-	smmu_make_smrg_group(22),
-	smmu_make_smrg_group(23),
-	smmu_make_smrg_group(24),
-	smmu_make_smrg_group(25),
-	smmu_make_smrg_group(26),
-	smmu_make_smrg_group(27),
-	smmu_make_smrg_group(28),
-	smmu_make_smrg_group(29),
-	smmu_make_smrg_group(30),
-	smmu_make_smrg_group(31),
-	smmu_make_smrg_group(32),
-	smmu_make_smrg_group(33),
-	smmu_make_smrg_group(34),
-	smmu_make_smrg_group(35),
-	smmu_make_smrg_group(36),
-	smmu_make_smrg_group(37),
-	smmu_make_smrg_group(38),
-	smmu_make_smrg_group(39),
-	smmu_make_smrg_group(40),
-	smmu_make_smrg_group(41),
-	smmu_make_smrg_group(42),
-	smmu_make_smrg_group(43),
-	smmu_make_smrg_group(44),
-	smmu_make_smrg_group(45),
-	smmu_make_smrg_group(46),
-	smmu_make_smrg_group(47),
-	smmu_make_smrg_group(48),
-	smmu_make_smrg_group(49),
-	smmu_make_smrg_group(50),
-	smmu_make_smrg_group(51),
-	smmu_make_smrg_group(52),
-	smmu_make_smrg_group(53),
-	smmu_make_smrg_group(54),
-	smmu_make_smrg_group(55),
-	smmu_make_smrg_group(56),
-	smmu_make_smrg_group(57),
-	smmu_make_smrg_group(58),
-	smmu_make_smrg_group(59),
-	smmu_make_smrg_group(60),
-	smmu_make_smrg_group(61),
-	smmu_make_smrg_group(62),
-	smmu_make_smrg_group(63),
-	smmu_make_cb_group(0),
-	smmu_make_cb_group(1),
-	smmu_make_cb_group(2),
-	smmu_make_cb_group(3),
-	smmu_make_cb_group(4),
-	smmu_make_cb_group(5),
-	smmu_make_cb_group(6),
-	smmu_make_cb_group(7),
-	smmu_make_cb_group(8),
-	smmu_make_cb_group(9),
-	smmu_make_cb_group(10),
-	smmu_make_cb_group(11),
-	smmu_make_cb_group(12),
-	smmu_make_cb_group(13),
-	smmu_make_cb_group(14),
-	smmu_make_cb_group(15),
-	smmu_make_cb_group(16),
-	smmu_make_cb_group(17),
-	smmu_make_cb_group(18),
-	smmu_make_cb_group(19),
-	smmu_make_cb_group(20),
-	smmu_make_cb_group(21),
-	smmu_make_cb_group(22),
-	smmu_make_cb_group(23),
-	smmu_make_cb_group(24),
-	smmu_make_cb_group(25),
-	smmu_make_cb_group(26),
-	smmu_make_cb_group(27),
-	smmu_make_cb_group(28),
-	smmu_make_cb_group(29),
-	smmu_make_cb_group(30),
-	smmu_make_cb_group(31),
-	smmu_make_cb_group(32),
-	smmu_make_cb_group(33),
-	smmu_make_cb_group(34),
-	smmu_make_cb_group(35),
-	smmu_make_cb_group(36),
-	smmu_make_cb_group(37),
-	smmu_make_cb_group(38),
-	smmu_make_cb_group(39),
-	smmu_make_cb_group(40),
-	smmu_make_cb_group(41),
-	smmu_make_cb_group(42),
-	smmu_make_cb_group(43),
-	smmu_make_cb_group(44),
-	smmu_make_cb_group(45),
-	smmu_make_cb_group(46),
-	smmu_make_cb_group(47),
-	smmu_make_cb_group(48),
-	smmu_make_cb_group(49),
-	smmu_make_cb_group(50),
-	smmu_make_cb_group(51),
-	smmu_make_cb_group(52),
-	smmu_make_cb_group(53),
-	smmu_make_cb_group(54),
-	smmu_make_cb_group(55),
-	smmu_make_cb_group(56),
-	smmu_make_cb_group(57),
-	smmu_make_cb_group(58),
-	smmu_make_cb_group(59),
-	smmu_make_cb_group(60),
-	smmu_make_cb_group(61),
-	smmu_make_cb_group(62),
-	smmu_make_cb_group(63),
+	smmu_make_cfg(TEGRA_SMMU0_BASE),
 	smmu_bypass_cfg,	/* TBU settings */
 	_END_OF_TABLE_,
 };
diff --git a/plat/nvidia/tegra/soc/t186/platform_t186.mk b/plat/nvidia/tegra/soc/t186/platform_t186.mk
index fdeb886..fe15853 100644
--- a/plat/nvidia/tegra/soc/t186/platform_t186.mk
+++ b/plat/nvidia/tegra/soc/t186/platform_t186.mk
@@ -1,13 +1,10 @@
 #
-# Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
 # platform configs
-ENABLE_AFI_DEVICE			:= 1
-$(eval $(call add_define,ENABLE_AFI_DEVICE))
-
 ENABLE_ROC_FOR_ORDERING_CLIENT_REQUESTS	:= 1
 $(eval $(call add_define,ENABLE_ROC_FOR_ORDERING_CLIENT_REQUESTS))
 
@@ -33,7 +30,7 @@
 MAX_XLAT_TABLES				:= 24
 $(eval $(call add_define,MAX_XLAT_TABLES))
 
-MAX_MMAP_REGIONS			:= 24
+MAX_MMAP_REGIONS			:= 25
 $(eval $(call add_define,MAX_MMAP_REGIONS))
 
 # platform files
diff --git a/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c
index f52d975..b7d10af 100644
--- a/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c
+++ b/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -15,12 +15,14 @@
 
 #include <bpmp.h>
 #include <flowctrl.h>
+#include <memctrl.h>
 #include <pmc.h>
 #include <platform_def.h>
 #include <security_engine.h>
 #include <tegra_def.h>
 #include <tegra_private.h>
 #include <tegra_platform.h>
+#include <utils.h>
 
 /*
  * Register used to clear CPU reset signals. Each CPU has two reset
@@ -35,11 +37,13 @@
 #define SCLK_BURST_POLICY_DEFAULT	0x10000000
 
 static int cpu_powergate_mask[PLATFORM_MAX_CPUS_PER_CLUSTER];
+static bool tegra_bpmp_available = true;
 
 int32_t tegra_soc_validate_power_state(unsigned int power_state,
 					psci_power_state_t *req_state)
 {
 	int state_id = psci_get_pstate_id(power_state);
+	const plat_params_from_bl2_t *plat_params = bl31_get_plat_params();
 
 	/* Sanity check the requested state id */
 	switch (state_id) {
@@ -52,16 +56,24 @@
 		break;
 
 	case PSTATE_ID_CLUSTER_IDLE:
-	case PSTATE_ID_CLUSTER_POWERDN:
+
 		/*
-		 * Cluster powerdown/idle request only for afflvl 1
+		 * Cluster idle request for afflvl 0
 		 */
-		req_state->pwr_domain_state[MPIDR_AFFLVL1] = state_id;
 		req_state->pwr_domain_state[MPIDR_AFFLVL0] = PSTATE_ID_CORE_POWERDN;
-
+		req_state->pwr_domain_state[MPIDR_AFFLVL1] = state_id;
 		break;
 
 	case PSTATE_ID_SOC_POWERDN:
+
+		/*
+		 * sc7entry-fw must be present in the system when the bpmp
+		 * firmware is not present, for a successful System Suspend
+		 * entry.
+		 */
+		if (!tegra_bpmp_init() && !plat_params->sc7entry_fw_base)
+			return PSCI_E_NOT_SUPPORTED;
+
 		/*
 		 * System powerdown request only for afflvl 2
 		 */
@@ -83,7 +95,7 @@
 
 /*******************************************************************************
  * Platform handler to calculate the proper target power level at the
- * specified affinity level
+ * specified affinity level.
  ******************************************************************************/
 plat_local_state_t tegra_soc_get_target_pwr_state(unsigned int lvl,
 					     const plat_local_state_t *states,
@@ -92,7 +104,7 @@
 	plat_local_state_t target = PSCI_LOCAL_STATE_RUN;
 	int cpu = plat_my_core_pos();
 	int core_pos = read_mpidr() & MPIDR_CPU_MASK;
-	uint32_t bpmp_reply, data[3];
+	uint32_t bpmp_reply, data[3], val;
 	int ret;
 
 	/* get the power state at this level */
@@ -107,40 +119,44 @@
 		ret = tegra_bpmp_init();
 		if (ret != 0U) {
 
+			/*
+			 * flag to indicate that BPMP firmware is not
+			 * available and the CPU has to handle entry/exit
+			 * for all power states
+			 */
+			tegra_bpmp_available = false;
+
 			/* Cluster idle not allowed */
 			target = PSCI_LOCAL_STATE_RUN;
-		} else {
 
-			/* Cluster idle */
-			data[0] = (uint32_t)cpu;
-			data[1] = TEGRA_PM_CC6;
-			data[2] = TEGRA_PM_SC1;
-			ret = tegra_bpmp_send_receive_atomic(MRQ_DO_IDLE,
-					(void *)&data, (int)sizeof(data),
-					(void *)&bpmp_reply,
-					(int)sizeof(bpmp_reply));
+			/*******************************************
+			 * BPMP is not present, so handle CC6 entry
+			 * from the CPU
+			 ******************************************/
 
-			/* check if cluster idle entry is allowed */
-			if ((ret != 0L) || (bpmp_reply != BPMP_CCx_ALLOWED)) {
+			/* check if cluster idle state has been enabled */
+			val = mmio_read_32(TEGRA_CL_DVFS_BASE + DVFS_DFLL_CTRL);
+			if (val == ENABLE_CLOSED_LOOP) {
+				/*
+				 * Acquire the cluster idle lock to stop
+				 * other CPUs from powering up.
+				 */
+				tegra_fc_ccplex_pgexit_lock();
 
-				/* Cluster idle not allowed */
-				target = PSCI_LOCAL_STATE_RUN;
+				/* Cluster idle only from the last standing CPU */
+				if (tegra_pmc_is_last_on_cpu() && tegra_fc_is_ccx_allowed()) {
+					/* Cluster idle allowed */
+					target = PSTATE_ID_CLUSTER_IDLE;
+				} else {
+					/* release cluster idle lock */
+					tegra_fc_ccplex_pgexit_unlock();
+				}
 			}
-		}
-
-	} else if ((lvl == MPIDR_AFFLVL1) && (target == PSTATE_ID_CLUSTER_POWERDN)) {
-
-		/* initialize the bpmp interface */
-		ret = tegra_bpmp_init();
-		if (ret != 0U) {
-
-			/* Cluster power down not allowed */
-			target = PSCI_LOCAL_STATE_RUN;
 		} else {
 
 			/* Cluster power-down */
 			data[0] = (uint32_t)cpu;
-			data[1] = TEGRA_PM_CC7;
+			data[1] = TEGRA_PM_CC6;
 			data[2] = TEGRA_PM_SC1;
 			ret = tegra_bpmp_send_receive_atomic(MRQ_DO_IDLE,
 					(void *)&data, (int)sizeof(data),
@@ -176,7 +192,9 @@
 	unsigned int stateid_afflvl2 = pwr_domain_state[MPIDR_AFFLVL2];
 	unsigned int stateid_afflvl1 = pwr_domain_state[MPIDR_AFFLVL1];
 	unsigned int stateid_afflvl0 = pwr_domain_state[MPIDR_AFFLVL0];
+	uint32_t cfg;
 	int ret = PSCI_E_SUCCESS;
+	uint32_t val;
 
 	if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) {
 
@@ -197,15 +215,42 @@
 
 		assert(stateid_afflvl0 == PSTATE_ID_CORE_POWERDN);
 
-		/* Prepare for cluster idle */
-		tegra_fc_cluster_idle(mpidr);
+		if (!tegra_bpmp_available) {
 
-	} else if (stateid_afflvl1 == PSTATE_ID_CLUSTER_POWERDN) {
+			/*
+			 * When disabled, DFLL loses its state. Enable
+			 * open loop state for the DFLL as we dont want
+			 * garbage values being written to the pmic
+			 * when we enter cluster idle state.
+			 */
+			mmio_write_32(TEGRA_CL_DVFS_BASE + DVFS_DFLL_CTRL,
+				      ENABLE_OPEN_LOOP);
 
-		assert(stateid_afflvl0 == PSTATE_ID_CORE_POWERDN);
+			/* Find if the platform uses OVR2/MAX77621 PMIC */
+			cfg = mmio_read_32(TEGRA_CL_DVFS_BASE + DVFS_DFLL_OUTPUT_CFG);
+			if (cfg & DFLL_OUTPUT_CFG_CLK_EN_BIT) {
+				/* OVR2 */
+
+				/* PWM tristate */
+				val = mmio_read_32(TEGRA_MISC_BASE + PINMUX_AUX_DVFS_PWM);
+				val |= PINMUX_PWM_TRISTATE;
+				mmio_write_32(TEGRA_MISC_BASE + PINMUX_AUX_DVFS_PWM, val);
+
+				/*
+				 * SCRATCH201[1] is being used to identify CPU
+				 * PMIC in warmboot code.
+				 * 0 : OVR2
+				 * 1 : MAX77621
+				 */
+				tegra_pmc_write_32(PMC_SCRATCH201, 0x0);
+			} else {
+				/* MAX77621 */
+				tegra_pmc_write_32(PMC_SCRATCH201, 0x2);
+			}
+		}
 
-		/* Prepare for cluster powerdn */
-		tegra_fc_cluster_powerdn(mpidr);
+		/* Prepare for cluster idle */
+		tegra_fc_cluster_idle(mpidr);
 
 	} else if (stateid_afflvl0 == PSTATE_ID_CORE_POWERDN) {
 
@@ -221,12 +266,82 @@
 	return ret;
 }
 
+static void tegra_reset_all_dma_masters(void)
+{
+	uint32_t val, mask;
+
+	/*
+	 * Reset all possible DMA masters in the system.
+	 */
+	val = GPU_RESET_BIT;
+	mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_GPU_RESET_REG_OFFSET, val);
+
+	val = NVENC_RESET_BIT | TSECB_RESET_BIT | APE_RESET_BIT |
+	      NVJPG_RESET_BIT | NVDEC_RESET_BIT;
+	mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_Y, val);
+
+	val = HOST1X_RESET_BIT | ISP_RESET_BIT | USBD_RESET_BIT |
+	      VI_RESET_BIT | SDMMC4_RESET_BIT | SDMMC1_RESET_BIT |
+	      SDMMC2_RESET_BIT;
+	mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_L, val);
+
+	val = USB2_RESET_BIT | APBDMA_RESET_BIT | AHBDMA_RESET_BIT;
+	mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_H, val);
+
+	val = XUSB_DEV_RESET_BIT | XUSB_HOST_RESET_BIT | TSEC_RESET_BIT |
+	      PCIE_RESET_BIT | SDMMC3_RESET_BIT;
+	mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_U, val);
+
+	val = SE_RESET_BIT | HDA_RESET_BIT | SATA_RESET_BIT;
+	mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_V, val);
+
+	/*
+	 * If any of the DMA masters are still alive, assume
+	 * that the system has been compromised and reboot.
+	 */
+	val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_GPU_RESET_REG_OFFSET);
+	mask = GPU_RESET_BIT;
+	if ((val & mask) != mask)
+		tegra_pmc_system_reset();
+
+	mask = NVENC_RESET_BIT | TSECB_RESET_BIT | APE_RESET_BIT |
+	      NVJPG_RESET_BIT | NVDEC_RESET_BIT;
+	val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_Y);
+	if ((val & mask) != mask)
+		tegra_pmc_system_reset();
+
+	mask = HOST1X_RESET_BIT | ISP_RESET_BIT | USBD_RESET_BIT |
+	       VI_RESET_BIT | SDMMC4_RESET_BIT | SDMMC1_RESET_BIT |
+	       SDMMC2_RESET_BIT;
+	val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_L);
+	if ((val & mask) != mask)
+		tegra_pmc_system_reset();
+
+	mask = USB2_RESET_BIT | APBDMA_RESET_BIT | AHBDMA_RESET_BIT;
+	val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_H);
+	if ((val & mask) != mask)
+		tegra_pmc_system_reset();
+
+	mask = XUSB_DEV_RESET_BIT | XUSB_HOST_RESET_BIT | TSEC_RESET_BIT |
+	       PCIE_RESET_BIT | SDMMC3_RESET_BIT;
+	val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_U);
+	if ((val & mask) != mask)
+		tegra_pmc_system_reset();
+
+	val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_V);
+	mask = SE_RESET_BIT | HDA_RESET_BIT | SATA_RESET_BIT;
+	if ((val & mask) != mask)
+		tegra_pmc_system_reset();
+}
+
 int tegra_soc_pwr_domain_power_down_wfi(const psci_power_state_t *target_state)
 {
 	u_register_t mpidr = read_mpidr();
 	const plat_local_state_t *pwr_domain_state =
 		target_state->pwr_domain_state;
 	unsigned int stateid_afflvl2 = pwr_domain_state[PLAT_MAX_PWR_LVL];
+	const plat_params_from_bl2_t *plat_params = bl31_get_plat_params();
+	uint32_t val;
 
 	if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) {
 
@@ -235,6 +350,61 @@
 			tegra_se_save_tzram();
 		}
 
+		/* de-init the interface */
+		tegra_bpmp_suspend();
+
+		/*
+		 * The CPU needs to load the System suspend entry firmware
+		 * if nothing is running on the BPMP.
+		 */
+		if (!tegra_bpmp_available) {
+
+			/*
+			 * BPMP firmware is not running on the co-processor, so
+			 * we need to explicitly load the firmware to enable
+			 * entry/exit to/from System Suspend and set the BPMP
+			 * on its way.
+			 */
+
+			/* Power off BPMP before we proceed */
+			tegra_fc_bpmp_off();
+
+			/* bond out IRAM banks B, C and D */
+			mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_BOND_OUT_U,
+				IRAM_B_LOCK_BIT | IRAM_C_LOCK_BIT |
+				IRAM_D_LOCK_BIT);
+
+			/* bond out APB/AHB DMAs */
+			mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_BOND_OUT_H,
+				APB_DMA_LOCK_BIT | AHB_DMA_LOCK_BIT);
+
+			/* Power off BPMP before we proceed */
+			tegra_fc_bpmp_off();
+
+			/*
+			 * Reset all the hardware blocks that can act as DMA
+			 * masters on the bus.
+			 */
+			tegra_reset_all_dma_masters();
+
+			/* clean up IRAM of any cruft */
+			zeromem((void *)(uintptr_t)TEGRA_IRAM_BASE,
+					TEGRA_IRAM_A_SIZE);
+
+			/* Copy the firmware to BPMP's internal RAM */
+			(void)memcpy((void *)(uintptr_t)TEGRA_IRAM_BASE,
+				(const void *)(plat_params->sc7entry_fw_base + SC7ENTRY_FW_HEADER_SIZE_BYTES),
+				plat_params->sc7entry_fw_size - SC7ENTRY_FW_HEADER_SIZE_BYTES);
+
+			/* Power on the BPMP and execute from IRAM base */
+			tegra_fc_bpmp_on(TEGRA_IRAM_BASE);
+
+			/* Wait until BPMP powers up */
+			do {
+				val = mmio_read_32(TEGRA_RES_SEMA_BASE + STA_OFFSET);
+			} while (val != SIGN_OF_LIFE);
+		}
+
 		/* enter system suspend */
 		tegra_fc_soc_powerdn(mpidr);
 	}
@@ -245,7 +415,9 @@
 int tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state)
 {
 	const plat_params_from_bl2_t *plat_params = bl31_get_plat_params();
-	uint32_t val;
+	uint32_t cfg;
+	uint32_t val, entrypoint = 0;
+	uint64_t offset;
 
 	/* platform parameter passed by the previous bootloader */
 	if (plat_params->l2_ecc_parity_prot_dis != 1) {
@@ -284,18 +456,76 @@
 
 		/*
 		 * Restore Boot and Power Management Processor (BPMP) reset
-		 * address and reset it.
+		 * address and reset it, if it is supported by the platform.
 		 */
-		tegra_fc_reset_bpmp();
+		if (!tegra_bpmp_available) {
+			tegra_fc_bpmp_off();
+		} else {
+			entrypoint = tegra_pmc_read_32(PMC_SCRATCH39);
+			tegra_fc_bpmp_on(entrypoint);
+
+			/* initialise the interface */
+			tegra_bpmp_resume();
+		}
+
+		/* sc7entry-fw is part of TZDRAM area */
+		if (plat_params->sc7entry_fw_base != 0U) {
+			offset = plat_params->tzdram_base - plat_params->sc7entry_fw_base;
+			tegra_memctrl_tzdram_setup(plat_params->sc7entry_fw_base,
+				plat_params->tzdram_size + offset);
+
+			/* restrict PMC access to secure world */
+			val = mmio_read_32(TEGRA_MISC_BASE + APB_SLAVE_SECURITY_ENABLE);
+			val |= PMC_SECURITY_EN_BIT;
+			mmio_write_32(TEGRA_MISC_BASE + APB_SLAVE_SECURITY_ENABLE, val);
+		}
 	}
 
 	/*
+	 * Check if we are exiting cluster idle state
+	 */
+	if (target_state->pwr_domain_state[MPIDR_AFFLVL1] ==
+			PSTATE_ID_CLUSTER_IDLE) {
+
+		if (!tegra_bpmp_available) {
+
+			/* PWM un-tristate */
+			cfg = mmio_read_32(TEGRA_CL_DVFS_BASE + DVFS_DFLL_OUTPUT_CFG);
+			if (cfg & DFLL_OUTPUT_CFG_CLK_EN_BIT) {
+				val = mmio_read_32(TEGRA_MISC_BASE + PINMUX_AUX_DVFS_PWM);
+				val &= ~PINMUX_PWM_TRISTATE;
+				mmio_write_32(TEGRA_MISC_BASE + PINMUX_AUX_DVFS_PWM, val);
+
+				/* make sure the setting took effect */
+				val = mmio_read_32(TEGRA_MISC_BASE + PINMUX_AUX_DVFS_PWM);
+				assert((val & PINMUX_PWM_TRISTATE) == 0U);
+			}
+
+			/*
+			 * Restore operation mode for the DFLL ring
+			 * oscillator
+			 */
+			mmio_write_32(TEGRA_CL_DVFS_BASE + DVFS_DFLL_CTRL,
+				      ENABLE_CLOSED_LOOP);
+
+			/* release cluster idle lock */
+			tegra_fc_ccplex_pgexit_unlock();
+		}
+	}
+
+	/*
 	 * T210 has a dedicated ARMv7 boot and power mgmt processor, BPMP. It's
 	 * used for power management and boot purposes. Inform the BPMP that
 	 * we have completed the cluster power up.
 	 */
 	tegra_fc_lock_active_cluster();
 
+	/*
+         * Resume PMC hardware block for Tegra210 platforms supporting sc7entry-fw
+         */
+	if (!tegra_chipid_is_t210_b01() && (plat_params->sc7entry_fw_base != 0U))
+		tegra_pmc_resume();
+
 	return PSCI_E_SUCCESS;
 }
 
diff --git a/plat/nvidia/tegra/soc/t210/plat_setup.c b/plat/nvidia/tegra/soc/t210/plat_setup.c
index 6246dde..4a42644 100644
--- a/plat/nvidia/tegra/soc/t210/plat_setup.c
+++ b/plat/nvidia/tegra/soc/t210/plat_setup.c
@@ -1,15 +1,24 @@
 /*
- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include <arch_helpers.h>
-#include <bpmp.h>
+#include <assert.h>
 #include <cortex_a57.h>
 #include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/interrupt_props.h>
 #include <drivers/console.h>
 #include <lib/xlat_tables/xlat_tables_v2.h>
+#include <drivers/arm/gic_common.h>
+#include <drivers/arm/gicv2.h>
+#include <bl31/interrupt_mgmt.h>
+
+#include <bpmp.h>
+#include <flowctrl.h>
+#include <memctrl.h>
 #include <platform.h>
 #include <security_engine.h>
 #include <tegra_def.h>
@@ -137,10 +146,76 @@
 	}
 }
 
+/* Secure IRQs for Tegra186 */
+static const interrupt_prop_t tegra210_interrupt_props[] = {
+	INTR_PROP_DESC(TEGRA210_WDT_CPU_LEGACY_FIQ, GIC_HIGHEST_SEC_PRIORITY,
+			GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE),
+};
+
+void plat_late_platform_setup(void)
+{
+	const plat_params_from_bl2_t *plat_params = bl31_get_plat_params();
+	uint64_t sc7entry_end, offset;
+	int ret;
+	uint32_t val;
+
+	/* memmap TZDRAM area containing the SC7 Entry Firmware */
+	if (plat_params->sc7entry_fw_base && plat_params->sc7entry_fw_size) {
+
+		assert(plat_params->sc7entry_fw_size <= TEGRA_IRAM_A_SIZE);
+
+		/*
+		 * Verify that the SC7 entry firmware resides inside the TZDRAM
+		 * aperture, _before_ the BL31 code and the start address is
+		 * exactly 1MB from BL31 base.
+		 */
+
+		/* sc7entry-fw must be _before_ BL31 base */
+		assert(plat_params->tzdram_base > plat_params->sc7entry_fw_base);
+
+		sc7entry_end = plat_params->sc7entry_fw_base +
+			       plat_params->sc7entry_fw_size;
+		assert(sc7entry_end < plat_params->tzdram_base);
+
+		/* sc7entry-fw start must be exactly 1MB behind BL31 base */
+		offset = plat_params->tzdram_base - plat_params->sc7entry_fw_base;
+		assert(offset == 0x100000);
+
+		/* secure TZDRAM area */
+		tegra_memctrl_tzdram_setup(plat_params->sc7entry_fw_base,
+			plat_params->tzdram_size + offset);
+
+		/* power off BPMP processor until SC7 entry */
+		tegra_fc_bpmp_off();
+
+		/* memmap SC7 entry firmware code */
+		ret = mmap_add_dynamic_region(plat_params->sc7entry_fw_base,
+				plat_params->sc7entry_fw_base,
+				plat_params->sc7entry_fw_size,
+				MT_SECURE | MT_RO_DATA);
+		assert(ret == 0);
+
+		/* restrict PMC access to secure world */
+		val = mmio_read_32(TEGRA_MISC_BASE + APB_SLAVE_SECURITY_ENABLE);
+		val |= PMC_SECURITY_EN_BIT;
+		mmio_write_32(TEGRA_MISC_BASE + APB_SLAVE_SECURITY_ENABLE, val);
+	}
+}
+
 /*******************************************************************************
  * Initialize the GIC and SGIs
  ******************************************************************************/
 void plat_gic_setup(void)
 {
-	tegra_gic_setup(NULL, 0);
+	tegra_gic_setup(tegra210_interrupt_props, ARRAY_SIZE(tegra210_interrupt_props));
+	tegra_gic_init();
+
+	/* Enable handling for FIQs */
+	tegra_fiq_handler_setup();
+
+	/*
+	 * Enable routing watchdog FIQs from the flow controller to
+	 * the GICD.
+	 */
+	tegra_fc_enable_fiq_to_ccplex_routing();
 }
diff --git a/plat/nvidia/tegra/soc/t210/plat_sip_calls.c b/plat/nvidia/tegra/soc/t210/plat_sip_calls.c
new file mode 100644
index 0000000..0e8900e
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t210/plat_sip_calls.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <assert.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <errno.h>
+#include <mmio.h>
+#include <utils_def.h>
+
+#include <memctrl.h>
+#include <pmc.h>
+#include <tegra_private.h>
+#include <tegra_platform.h>
+#include <tegra_def.h>
+
+/*******************************************************************************
+ * PMC parameters
+ ******************************************************************************/
+#define PMC_READ 			U(0xaa)
+#define PMC_WRITE 			U(0xbb)
+
+/*******************************************************************************
+ * Tegra210 SiP SMCs
+ ******************************************************************************/
+#define TEGRA_SIP_PMC_COMMANDS		U(0xC2FFFE00)
+
+/*******************************************************************************
+ * This function is responsible for handling all T210 SiP calls
+ ******************************************************************************/
+int plat_sip_handler(uint32_t smc_fid,
+		     uint64_t x1,
+		     uint64_t x2,
+		     uint64_t x3,
+		     uint64_t x4,
+		     const void *cookie,
+		     void *handle,
+		     uint64_t flags)
+{
+	uint32_t val, ns;
+
+	/* Determine which security state this SMC originated from */
+	ns = is_caller_non_secure(flags);
+	if (!ns)
+		SMC_RET1(handle, SMC_UNK);
+
+	switch (smc_fid) {
+	case 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;
+
+		/* PMC secure-only registers are not accessible */
+		if ((x2 == PMC_DPD_ENABLE_0) || (x2 == PMC_FUSE_CONTROL_0) ||
+		    (x2 == PMC_CRYPTO_OP_0))
+			return -EFAULT;
+
+		/* Perform PMC read/write */
+		if (x1 == PMC_READ) {
+			val = mmio_read_32((uint32_t)(TEGRA_PMC_BASE + x2));
+			write_ctx_reg(get_gpregs_ctx(handle), CTX_GPREG_X1, val);
+		} else if (x1 == PMC_WRITE) {
+			mmio_write_32((uint32_t)(TEGRA_PMC_BASE + x2), (uint32_t)x3);
+		} else {
+			return -EINVAL;
+		}
+
+		break;
+
+	default:
+		ERROR("%s: unsupported function ID\n", __func__);
+		return -ENOTSUP;
+	}
+
+	return 0;
+}
diff --git a/plat/nvidia/tegra/soc/t210/platform_t210.mk b/plat/nvidia/tegra/soc/t210/platform_t210.mk
index e23d7e3..a11aef4 100644
--- a/plat/nvidia/tegra/soc/t210/platform_t210.mk
+++ b/plat/nvidia/tegra/soc/t210/platform_t210.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -19,9 +19,12 @@
 MAX_XLAT_TABLES				:= 10
 $(eval $(call add_define,MAX_XLAT_TABLES))
 
-MAX_MMAP_REGIONS			:= 15
+MAX_MMAP_REGIONS			:= 16
 $(eval $(call add_define,MAX_MMAP_REGIONS))
 
+ENABLE_WDT_LEGACY_FIQ_HANDLING		:= 1
+$(eval $(call add_define,ENABLE_WDT_LEGACY_FIQ_HANDLING))
+
 PLAT_INCLUDES		+=	-I${SOC_DIR}/drivers/se
 
 BL31_SOURCES		+=	drivers/ti/uart/aarch64/16550_console.S		\
@@ -33,7 +36,8 @@
 				${SOC_DIR}/plat_psci_handlers.c			\
 				${SOC_DIR}/plat_setup.c				\
 				${SOC_DIR}/drivers/se/security_engine.c		\
-				${SOC_DIR}/plat_secondary.c
+				${SOC_DIR}/plat_secondary.c		\
+				${SOC_DIR}/plat_sip_calls.c
 
 # Enable workarounds for selected Cortex-A57 erratas.
 A57_DISABLE_NON_TEMPORAL_HINT	:=	1
@@ -48,3 +52,6 @@
 ERRATA_A53_826319		:=	1
 ERRATA_A53_836870		:=	1
 ERRATA_A53_855873		:=	1
+
+# Skip L1 $ flush when powering down Cortex-A57 CPUs
+SKIP_A57_L1_FLUSH_PWR_DWN	:=	1
diff --git a/services/spd/tlkd/tlkd_common.c b/services/spd/tlkd/tlkd_common.c
index 2f0194e..dbe6c2e 100644
--- a/services/spd/tlkd/tlkd_common.c
+++ b/services/spd/tlkd/tlkd_common.c
@@ -126,7 +126,6 @@
 
 	/* Passing a NULL context is a critical programming error */
 	assert(tlk_ctx);
-	assert(tlk_ctx->c_rt_ctx == 0);
 
 	/* Apply the Secure EL1 system register context and switch to it */
 	assert(cm_get_context(SECURE) == &tlk_ctx->cpu_ctx);
diff --git a/services/spd/tlkd/tlkd_main.c b/services/spd/tlkd/tlkd_main.c
index b1a0477..f6f2af5 100644
--- a/services/spd/tlkd/tlkd_main.c
+++ b/services/spd/tlkd/tlkd_main.c
@@ -195,14 +195,18 @@
 	 * b. register shared memory with the SP for passing args
 	 *    required for maintaining sessions with the Trusted
 	 *    Applications.
-	 * c. register non-secure world's memory map with the OS
-	 * d. open/close sessions
-	 * e. issue commands to the Trusted Apps
-	 * f. resume the preempted yielding SMC call.
+	 * c. register shared persistent buffers for secure storage
+	 * d. register NS DRAM ranges passed by Cboot
+	 * e. register Root of Trust parameters from Cboot for Verified Boot
+	 * f. open/close sessions
+	 * g. issue commands to the Trusted Apps
+	 * h. resume the preempted yielding SMC call.
 	 */
 	case TLK_REGISTER_LOGBUF:
 	case TLK_REGISTER_REQBUF:
-	case TLK_REGISTER_NS_DRAM:
+	case TLK_SS_REGISTER_HANDLER:
+	case TLK_REGISTER_NS_DRAM_RANGES:
+	case TLK_SET_ROOT_OF_TRUST:
 	case TLK_OPEN_TA_SESSION:
 	case TLK_CLOSE_TA_SESSION:
 	case TLK_TA_LAUNCH_OP:
@@ -400,6 +404,7 @@
 		SMC_RET2(handle, TLK_VERSION_MAJOR, TLK_VERSION_MINOR);
 
 	default:
+		WARN("%s: Unhandled SMC: 0x%x\n", __func__, smc_fid);
 		break;
 	}
 
diff --git a/services/spd/trusty/trusty.c b/services/spd/trusty/trusty.c
index 83c14b4..b059a43 100644
--- a/services/spd/trusty/trusty.c
+++ b/services/spd/trusty/trusty.c
@@ -7,6 +7,7 @@
 #include <assert.h>
 #include <stdbool.h>
 #include <string.h>
+#include <xlat_tables_v2.h>
 
 #include <arch_helpers.h>
 #include <bl31/bl31.h>
@@ -352,32 +353,32 @@
 	}
 }
 
-static int32_t trusty_cpu_off_handler(u_register_t unused)
+static int32_t trusty_cpu_off_handler(u_register_t max_off_lvl)
 {
-	trusty_cpu_suspend(1);
+	trusty_cpu_suspend(max_off_lvl);
 
 	return 0;
 }
 
-static void trusty_cpu_on_finish_handler(u_register_t unused)
+static void trusty_cpu_on_finish_handler(u_register_t max_off_lvl)
 {
 	struct trusty_cpu_ctx *ctx = get_trusty_ctx();
 
 	if (ctx->saved_sp == NULL) {
 		(void)trusty_init();
 	} else {
-		trusty_cpu_resume(1);
+		trusty_cpu_resume(max_off_lvl);
 	}
 }
 
-static void trusty_cpu_suspend_handler(u_register_t unused)
+static void trusty_cpu_suspend_handler(u_register_t max_off_lvl)
 {
-	trusty_cpu_suspend(0);
+	trusty_cpu_suspend(max_off_lvl);
 }
 
-static void trusty_cpu_suspend_finish_handler(u_register_t unused)
+static void trusty_cpu_suspend_finish_handler(u_register_t max_off_lvl)
 {
-	trusty_cpu_resume(0);
+	trusty_cpu_resume(max_off_lvl);
 }
 
 static const spd_pm_ops_t trusty_pm = {
@@ -412,6 +413,14 @@
 		return -1;
 	}
 
+	/* memmap first page of trusty's code memory before peeking */
+	ret = mmap_add_dynamic_region(ep_info->pc, /* PA */
+			ep_info->pc, /* VA */
+			PAGE_SIZE, /* size */
+			MT_SECURE | MT_RW_DATA); /* attrs */
+	assert(ret == 0);
+
+	/* peek into trusty's code to see if we have a 32-bit or 64-bit image */
 	instr = *(uint32_t *)ep_info->pc;
 
 	if (instr >> 24 == 0xeaU) {
@@ -424,6 +433,9 @@
 		return -1;
 	}
 
+	/* unmap trusty's memory page */
+	(void)mmap_remove_dynamic_region(ep_info->pc, PAGE_SIZE);
+
 	SET_PARAM_HEAD(ep_info, PARAM_EP, VERSION_1, SECURE | EP_ST_ENABLE);
 	if (!aarch32)
 		ep_info->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX,