Tegra194: base commit for the platform

This patch creates the base commit for the Tegra194 platform, from
Tegra186 code base.

Change-Id: I1c77e4984f7ff39655f3fb79633d13d533707ede
Signed-off-by: Varun Wadekar <vwadekar@nvidia.com>
diff --git a/plat/nvidia/tegra/include/t194/tegra_def.h b/plat/nvidia/tegra/include/t194/tegra_def.h
new file mode 100644
index 0000000..8e7b28c
--- /dev/null
+++ b/plat/nvidia/tegra/include/t194/tegra_def.h
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __TEGRA_DEF_H__
+#define __TEGRA_DEF_H__
+
+#include <lib/utils_def.h>
+
+/*******************************************************************************
+ * These values are used by the PSCI implementation during the `CPU_SUSPEND`
+ * and `SYSTEM_SUSPEND` calls as the `state-id` field in the 'power state'
+ * parameter.
+ ******************************************************************************/
+#define PSTATE_ID_CORE_IDLE		6
+#define PSTATE_ID_CORE_POWERDN		7
+#define PSTATE_ID_SOC_POWERDN		2
+
+/*******************************************************************************
+ * Platform power states (used by PSCI framework)
+ *
+ * - PLAT_MAX_RET_STATE should be less than lowest PSTATE_ID
+ * - PLAT_MAX_OFF_STATE should be greater than the highest PSTATE_ID
+ ******************************************************************************/
+#define PLAT_MAX_RET_STATE		1
+#define PLAT_MAX_OFF_STATE		8
+
+/*******************************************************************************
+ * Implementation defined ACTLR_EL3 bit definitions
+ ******************************************************************************/
+#define ACTLR_EL3_L2ACTLR_BIT		(1 << 6)
+#define ACTLR_EL3_L2ECTLR_BIT		(1 << 5)
+#define ACTLR_EL3_L2CTLR_BIT		(1 << 4)
+#define ACTLR_EL3_CPUECTLR_BIT		(1 << 1)
+#define ACTLR_EL3_CPUACTLR_BIT		(1 << 0)
+#define ACTLR_EL3_ENABLE_ALL_ACCESS	(ACTLR_EL3_L2ACTLR_BIT | \
+					 ACTLR_EL3_L2ECTLR_BIT | \
+					 ACTLR_EL3_L2CTLR_BIT | \
+					 ACTLR_EL3_CPUECTLR_BIT | \
+					 ACTLR_EL3_CPUACTLR_BIT)
+
+/*******************************************************************************
+ * Secure IRQ definitions
+ ******************************************************************************/
+#define TEGRA186_MAX_SEC_IRQS		5
+#define TEGRA186_BPMP_WDT_IRQ		46
+#define TEGRA186_SPE_WDT_IRQ		47
+#define TEGRA186_SCE_WDT_IRQ		48
+#define TEGRA186_TOP_WDT_IRQ		49
+#define TEGRA186_AON_WDT_IRQ		50
+
+#define TEGRA186_SEC_IRQ_TARGET_MASK	0xFF /* 8 Carmel */
+
+/*******************************************************************************
+ * Tegra Miscellanous register constants
+ ******************************************************************************/
+#define TEGRA_MISC_BASE			0x00100000
+#define  HARDWARE_REVISION_OFFSET	0x4
+
+#define  MISCREG_PFCFG			0x200C
+
+/*******************************************************************************
+ * Tegra TSA Controller constants
+ ******************************************************************************/
+#define TEGRA_TSA_BASE			0x02000000
+
+#define TSA_CONFIG_STATIC0_CSW_SESWR		0x1010
+#define  TSA_CONFIG_STATIC0_CSW_SESWR_RESET	0x1100
+#define TSA_CONFIG_STATIC0_CSW_ETRW		0xD034
+#define  TSA_CONFIG_STATIC0_CSW_ETRW_RESET	0x1100
+#define TSA_CONFIG_STATIC0_CSW_SDMMCWAB		0x3020
+#define  TSA_CONFIG_STATIC0_CSW_SDMMCWAB_RESET	0x1100
+#define TSA_CONFIG_STATIC0_CSW_AXISW		0x8008
+#define  TSA_CONFIG_STATIC0_CSW_AXISW_RESET	0x1100
+#define TSA_CONFIG_STATIC0_CSW_HDAW		0xD008
+#define  TSA_CONFIG_STATIC0_CSW_HDAW_RESET	0x1100
+#define TSA_CONFIG_STATIC0_CSW_AONDMAW		0xE018
+#define  TSA_CONFIG_STATIC0_CSW_AONDMAW_RESET	0x1100
+#define TSA_CONFIG_STATIC0_CSW_SCEDMAW		0x9008
+#define  TSA_CONFIG_STATIC0_CSW_SCEDMAW_RESET	0x1100
+#define TSA_CONFIG_STATIC0_CSW_BPMPDMAW		0x9028
+#define  TSA_CONFIG_STATIC0_CSW_BPMPDMAW_RESET	0x1100
+#define TSA_CONFIG_STATIC0_CSW_APEDMAW		0xB008
+#define  TSA_CONFIG_STATIC0_CSW_APEDMAW_RESET	0x1100
+#define TSA_CONFIG_STATIC0_CSW_UFSHCW		0x6008
+#define  TSA_CONFIG_STATIC0_CSW_UFSHCW_RESET	0x1100
+#define TSA_CONFIG_STATIC0_CSW_AFIW		0xF008
+#define  TSA_CONFIG_STATIC0_CSW_AFIW_RESET	0x1100
+#define TSA_CONFIG_STATIC0_CSW_SATAW		0x4008
+#define  TSA_CONFIG_STATIC0_CSW_SATAW_RESET	0x1100
+#define TSA_CONFIG_STATIC0_CSW_EQOSW		0x3038
+#define  TSA_CONFIG_STATIC0_CSW_EQOSW_RESET	0x1100
+#define TSA_CONFIG_STATIC0_CSW_XUSB_DEVW	0x6018
+#define  TSA_CONFIG_STATIC0_CSW_XUSB_DEVW_RESET	0x1100
+#define TSA_CONFIG_STATIC0_CSW_XUSB_HOSTW	0x6028
+#define  TSA_CONFIG_STATIC0_CSW_XUSB_HOSTW_RESET 0x1100
+
+#define TSA_CONFIG_CSW_MEMTYPE_OVERRIDE_MASK	(0x3 << 11)
+#define TSA_CONFIG_CSW_MEMTYPE_OVERRIDE_PASTHRU	(0 << 11)
+
+/*******************************************************************************
+ * Tegra Memory Controller constants
+ ******************************************************************************/
+#define TEGRA_MC_STREAMID_BASE		0x02C00000
+#define TEGRA_MC_BASE			0x02C10000
+
+/* TZDRAM carveout configuration registers */
+#define MC_SECURITY_CFG0_0		0x70
+#define MC_SECURITY_CFG1_0		0x74
+#define MC_SECURITY_CFG3_0		0x9BC
+
+/* Video Memory carveout configuration registers */
+#define MC_VIDEO_PROTECT_BASE_HI	0x978
+#define MC_VIDEO_PROTECT_BASE_LO	0x648
+#define MC_VIDEO_PROTECT_SIZE_MB	0x64c
+
+/* TZRAM carveout (MC_SECURITY_CARVEOUT11) configuration registers */
+#define MC_TZRAM_BASE_LO		0x2194
+#define  TZRAM_BASE_LO_SHIFT		12
+#define  TZRAM_BASE_LO_MASK		0xFFFFF
+#define MC_TZRAM_BASE_HI		0x2198
+#define  TZRAM_BASE_HI_SHIFT		0
+#define  TZRAM_BASE_HI_MASK		3
+#define MC_TZRAM_SIZE			0x219C
+#define  TZRAM_SIZE_RANGE_4KB_SHIFT	27
+
+#define MC_TZRAM_CARVEOUT_CFG			0x2190
+#define  TZRAM_LOCK_CFG_SETTINGS_BIT		(1 << 1)
+#define  TZRAM_ENABLE_TZ_LOCK_BIT		(1 << 0)
+#define MC_TZRAM_CARVEOUT_CLIENT_ACCESS_CFG0	0x21A0
+#define MC_TZRAM_CARVEOUT_CLIENT_ACCESS_CFG1	0x21A4
+#define  TZRAM_CARVEOUT_CPU_WRITE_ACCESS_BIT	(1 << 25)
+#define  TZRAM_CARVEOUT_CPU_READ_ACCESS_BIT	(1 << 7)
+#define MC_TZRAM_CARVEOUT_CLIENT_ACCESS_CFG2	0x21A8
+#define MC_TZRAM_CARVEOUT_CLIENT_ACCESS_CFG3	0x21AC
+#define MC_TZRAM_CARVEOUT_CLIENT_ACCESS_CFG4	0x21B0
+#define MC_TZRAM_CARVEOUT_CLIENT_ACCESS_CFG5	0x21B4
+
+#define MC_TZRAM_CARVEOUT_FORCE_INTERNAL_ACCESS0	0x21C0
+#define MC_TZRAM_CARVEOUT_FORCE_INTERNAL_ACCESS1	0x21C4
+#define MC_TZRAM_CARVEOUT_FORCE_INTERNAL_ACCESS2	0x21C8
+#define MC_TZRAM_CARVEOUT_FORCE_INTERNAL_ACCESS3	0x21CC
+#define MC_TZRAM_CARVEOUT_FORCE_INTERNAL_ACCESS4	0x21D0
+#define MC_TZRAM_CARVEOUT_FORCE_INTERNAL_ACCESS5	0x21D4
+
+/* Memory Controller Reset Control registers */
+#define  MC_CLIENT_HOTRESET_CTRL1_VIFAL_FLUSH_ENB	(1 << 27)
+#define  MC_CLIENT_HOTRESET_CTRL1_DLAA_FLUSH_ENB	(1 << 28)
+#define  MC_CLIENT_HOTRESET_CTRL1_DLA1A_FLUSH_ENB	(1 << 29)
+#define  MC_CLIENT_HOTRESET_CTRL1_PVA0A_FLUSH_ENB	(1 << 30)
+#define  MC_CLIENT_HOTRESET_CTRL1_PVA1A_FLUSH_ENB	(1 << 31)
+
+/*******************************************************************************
+ * Tegra UART Controller constants
+ ******************************************************************************/
+#define TEGRA_UARTA_BASE		0x03100000
+#define TEGRA_UARTB_BASE		0x03110000
+#define TEGRA_UARTC_BASE		0x0C280000
+#define TEGRA_UARTD_BASE		0x03130000
+#define TEGRA_UARTE_BASE		0x03140000
+#define TEGRA_UARTF_BASE		0x03150000
+#define TEGRA_UARTG_BASE		0x0C290000
+
+/*******************************************************************************
+ * Tegra Fuse Controller related constants
+ ******************************************************************************/
+#define TEGRA_FUSE_BASE			0x03820000
+#define  OPT_SUBREVISION		0x248
+#define  SUBREVISION_MASK		0xF
+
+/*******************************************************************************
+ * GICv2 & interrupt handling related constants
+ ******************************************************************************/
+#define TEGRA_GICD_BASE			0x03881000
+#define TEGRA_GICC_BASE			0x03882000
+
+/*******************************************************************************
+ * Security Engine related constants
+ ******************************************************************************/
+#define TEGRA_SE0_BASE			0x03AC0000
+#define  SE_MUTEX_WATCHDOG_NS_LIMIT	0x6C
+#define TEGRA_PKA1_BASE			0x03AD0000
+#define  PKA_MUTEX_WATCHDOG_NS_LIMIT	0x8144
+#define TEGRA_RNG1_BASE			0x03AE0000
+#define  RNG_MUTEX_WATCHDOG_NS_LIMIT	0xFE0
+
+/*******************************************************************************
+ * Tegra micro-seconds timer constants
+ ******************************************************************************/
+#define TEGRA_TMRUS_BASE		0x0C2E0000
+
+/*******************************************************************************
+ * Tegra Power Mgmt Controller constants
+ ******************************************************************************/
+#define TEGRA_PMC_BASE			0x0C360000
+
+/*******************************************************************************
+ * Tegra scratch registers constants
+ ******************************************************************************/
+#define TEGRA_SCRATCH_BASE		0x0C390000
+#define  SECURE_SCRATCH_RSV1_LO		0x06C
+#define  SECURE_SCRATCH_RSV1_HI		0x070
+#define  SECURE_SCRATCH_RSV6		0x094
+#define  SECURE_SCRATCH_RSV11_LO	0x0BC
+#define  SECURE_SCRATCH_RSV11_HI	0x0C0
+#define  SECURE_SCRATCH_RSV53_LO	0x20C
+#define  SECURE_SCRATCH_RSV53_HI	0x210
+#define  SECURE_SCRATCH_RSV54_HI	0x218
+#define  SECURE_SCRATCH_RSV55_LO	0x21C
+#define  SECURE_SCRATCH_RSV55_HI	0x220
+
+/*******************************************************************************
+ * Tegra Memory Mapped Control Register Access Bus constants
+ ******************************************************************************/
+#define TEGRA_MMCRAB_BASE		0x0E000000
+
+/*******************************************************************************
+ * Tegra SMMU Controller constants
+ ******************************************************************************/
+#define TEGRA_SMMU_BASE			0x10000000
+
+/*******************************************************************************
+ * Tegra TZRAM constants
+ ******************************************************************************/
+#define TEGRA_TZRAM_BASE		0x40000000
+#define TEGRA_TZRAM_SIZE		0x40000
+
+/*******************************************************************************
+ * Tegra Clock and Reset Controller constants
+ ******************************************************************************/
+#define TEGRA_CAR_RESET_BASE		0x200000000
+
+#endif /* __TEGRA_DEF_H__ */
diff --git a/plat/nvidia/tegra/soc/t194/drivers/include/mce_private.h b/plat/nvidia/tegra/soc/t194/drivers/include/mce_private.h
new file mode 100644
index 0000000..4735404
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t194/drivers/include/mce_private.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __MCE_PRIVATE_H__
+#define __MCE_PRIVATE_H__
+
+#include <mmio.h>
+#include <tegra_def.h>
+
+/*******************************************************************************
+ * Macros to prepare CSTATE info request
+ ******************************************************************************/
+/* Description of the parameters for UPDATE_CSTATE_INFO request */
+#define CLUSTER_CSTATE_MASK			0x7
+#define CLUSTER_CSTATE_SHIFT			0
+#define CLUSTER_CSTATE_UPDATE_BIT		(1 << 7)
+#define CCPLEX_CSTATE_MASK			0x3
+#define CCPLEX_CSTATE_SHIFT			8
+#define CCPLEX_CSTATE_UPDATE_BIT		(1 << 15)
+#define SYSTEM_CSTATE_MASK			0xF
+#define SYSTEM_CSTATE_SHIFT			16
+#define SYSTEM_CSTATE_FORCE_UPDATE_SHIFT	22
+#define SYSTEM_CSTATE_FORCE_UPDATE_BIT		(1 << 22)
+#define SYSTEM_CSTATE_UPDATE_BIT		(1 << 23)
+#define CSTATE_WAKE_MASK_UPDATE_BIT		(1 << 31)
+#define CSTATE_WAKE_MASK_SHIFT			32
+#define CSTATE_WAKE_MASK_CLEAR			0xFFFFFFFF
+
+/*******************************************************************************
+ * Auto-CC3 control macros
+ ******************************************************************************/
+#define MCE_AUTO_CC3_FREQ_MASK			0x1FF
+#define MCE_AUTO_CC3_FREQ_SHIFT			0
+#define MCE_AUTO_CC3_VTG_MASK			0x7F
+#define MCE_AUTO_CC3_VTG_SHIFT			16
+#define MCE_AUTO_CC3_ENABLE_BIT			(1 << 31)
+
+/*******************************************************************************
+ * Macros for the 'IS_SC7_ALLOWED' command
+ ******************************************************************************/
+#define MCE_SC7_ALLOWED_MASK			0x7
+#define MCE_SC7_WAKE_TIME_SHIFT			32
+
+/*******************************************************************************
+ * Macros for 'read/write ctats' commands
+ ******************************************************************************/
+#define MCE_CSTATE_STATS_TYPE_SHIFT		32
+#define MCE_CSTATE_WRITE_DATA_LO_MASK		0xF
+
+/*******************************************************************************
+ * Macros for 'update crossover threshold' command
+ ******************************************************************************/
+#define MCE_CROSSOVER_THRESHOLD_TIME_SHIFT	32
+
+/*******************************************************************************
+ * Timeout value used to powerdown a core
+ ******************************************************************************/
+#define MCE_CORE_SLEEP_TIME_INFINITE		0xFFFFFFFF
+
+/*******************************************************************************
+ * MCA command struct
+ ******************************************************************************/
+typedef union mca_cmd {
+	struct command {
+		uint8_t cmd;
+		uint8_t idx;
+		uint8_t subidx;
+	} command;
+	struct input {
+		uint32_t low;
+		uint32_t high;
+	} input;
+	uint64_t data;
+} mca_cmd_t;
+
+/*******************************************************************************
+ * MCA argument struct
+ ******************************************************************************/
+typedef union mca_arg {
+	struct err {
+		uint64_t error:8;
+		uint64_t unused:48;
+		uint64_t finish:8;
+	} err;
+	struct arg {
+		uint32_t low;
+		uint32_t high;
+	} arg;
+	uint64_t data;
+} mca_arg_t;
+
+/*******************************************************************************
+ * Uncore PERFMON ARI struct
+ ******************************************************************************/
+typedef union uncore_perfmon_req {
+	struct perfmon_command {
+		/*
+		 * Commands: 0 = READ, 1 = WRITE
+		 */
+		uint64_t cmd:8;
+		/*
+		 * The unit group: L2=0, L3=1, ROC=2, MC=3, IOB=4
+		 */
+		uint64_t grp:4;
+		/*
+		 * Unit selector: Selects the unit instance, with 0 = Unit
+		 * = (number of units in group) - 1.
+		 */
+		uint64_t unit:4;
+		/*
+		 * Selects the uncore perfmon register to access
+		 */
+		uint64_t reg:8;
+		/*
+		 * Counter number. Selects which counter to use for
+		 * registers NV_PMEVCNTR and NV_PMEVTYPER.
+		 */
+		uint64_t counter:8;
+	} perfmon_command;
+	struct perfmon_status {
+		/*
+		 * Resulting command status
+		 */
+		uint64_t val:8;
+		uint64_t unused:24;
+	} perfmon_status;
+	uint64_t data;
+} uncore_perfmon_req_t;
+
+#define UNCORE_PERFMON_CMD_READ			0
+#define UNCORE_PERFMON_CMD_WRITE		1
+
+#define UNCORE_PERFMON_CMD_MASK			0xFF
+#define UNCORE_PERFMON_UNIT_GRP_MASK		0xF
+#define UNCORE_PERFMON_SELECTOR_MASK		0xF
+#define UNCORE_PERFMON_REG_MASK			0xFF
+#define UNCORE_PERFMON_CTR_MASK			0xFF
+#define UNCORE_PERFMON_RESP_STATUS_MASK		0xFF
+
+/* declarations for NVG handler functions */
+int nvg_enter_cstate(uint32_t ari_base, uint32_t state, uint32_t wake_time);
+int nvg_update_cstate_info(uint32_t ari_base, uint32_t cluster, uint32_t ccplex,
+		uint32_t system, uint8_t sys_state_force, uint32_t wake_mask,
+		uint8_t update_wake_mask);
+int nvg_update_crossover_time(uint32_t ari_base, uint32_t type, uint32_t time);
+uint64_t nvg_read_cstate_stats(uint32_t ari_base, uint32_t state);
+int nvg_write_cstate_stats(uint32_t ari_base, uint32_t state, uint32_t val);
+int nvg_is_ccx_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time);
+int nvg_is_sc7_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time);
+int nvg_online_core(uint32_t ari_base, uint32_t core);
+int nvg_cc3_ctrl(uint32_t ari_base, uint32_t freq, uint32_t volt, uint8_t enable);
+
+#endif /* __MCE_PRIVATE_H__ */
diff --git a/plat/nvidia/tegra/soc/t194/drivers/mce/aarch64/nvg_helpers.S b/plat/nvidia/tegra/soc/t194/drivers/mce/aarch64/nvg_helpers.S
new file mode 100644
index 0000000..e6a6a99
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t194/drivers/mce/aarch64/nvg_helpers.S
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+
+	.globl	nvg_set_request_data
+	.globl	nvg_set_request
+	.globl	nvg_get_result
+
+/* void nvg_set_request_data(uint64_t req, uint64_t data) */
+func nvg_set_request_data
+	msr	s3_0_c15_c1_2, x0
+	msr	s3_0_c15_c1_3, x1
+	ret
+endfunc nvg_set_request_data
+
+/* void nvg_set_request(uint64_t req) */
+func nvg_set_request
+	msr	s3_0_c15_c1_2, x0
+	ret
+endfunc nvg_set_request
+
+/* uint64_t nvg_get_result(void) */
+func nvg_get_result
+	mrs	x0, s3_0_c15_c1_3
+	ret
+endfunc nvg_get_result
diff --git a/plat/nvidia/tegra/soc/t194/drivers/mce/mce.c b/plat/nvidia/tegra/soc/t194/drivers/mce/mce.c
new file mode 100644
index 0000000..3a2e262
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t194/drivers/mce/mce.c
@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 2019, NVIDIA CORPORATION. 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 <context.h>
+#include <lib/el3_runtime/context_mgmt.h>
+#include <common/debug.h>
+#include <denver.h>
+#include <mce.h>
+#include <mce_private.h>
+#include <mmio.h>
+#include <string.h>
+#include <errno.h>
+#include <tegra_def.h>
+#include <tegra_platform.h>
+
+/*******************************************************************************
+ * Common handler for all MCE commands
+ ******************************************************************************/
+int mce_command_handler(mce_cmd_t cmd, uint64_t arg0, uint64_t arg1,
+			uint64_t arg2)
+{
+	uint64_t ret64 = 0, arg3, arg4, arg5;
+	int ret = 0;
+	mca_cmd_t mca_cmd;
+	uncore_perfmon_req_t req;
+	cpu_context_t *ctx = cm_get_context(NON_SECURE);
+	gp_regs_t *gp_regs = get_gpregs_ctx(ctx);
+
+	assert(ctx);
+	assert(gp_regs);
+
+	switch (cmd) {
+	case MCE_CMD_ENTER_CSTATE:
+		/* NVG */
+		break;
+
+	case MCE_CMD_UPDATE_CSTATE_INFO:
+		/*
+		 * get the parameters required for the update cstate info
+		 * command
+		 */
+		arg3 = read_ctx_reg(gp_regs, CTX_GPREG_X4);
+		arg4 = read_ctx_reg(gp_regs, CTX_GPREG_X5);
+		arg5 = read_ctx_reg(gp_regs, CTX_GPREG_X6);
+
+		/* NVG */
+
+		write_ctx_reg(gp_regs, CTX_GPREG_X4, arg3);
+		write_ctx_reg(gp_regs, CTX_GPREG_X5, arg4);
+		write_ctx_reg(gp_regs, CTX_GPREG_X6, arg5);
+
+		break;
+
+	case MCE_CMD_UPDATE_CROSSOVER_TIME:
+		/* NVG */
+
+		break;
+
+	case MCE_CMD_READ_CSTATE_STATS:
+		/* NVG */
+
+		/* update context to return cstate stats value */
+		write_ctx_reg(gp_regs, CTX_GPREG_X1, ret64);
+		write_ctx_reg(gp_regs, CTX_GPREG_X2, ret64);
+
+		break;
+
+	case MCE_CMD_WRITE_CSTATE_STATS:
+		/* NVG */
+
+		break;
+
+	case MCE_CMD_IS_CCX_ALLOWED:
+		/* NVG */
+
+		/* update context to return CCx status value */
+		write_ctx_reg(gp_regs, CTX_GPREG_X1, ret);
+
+		break;
+
+	case MCE_CMD_IS_SC7_ALLOWED:
+		/* NVG */
+
+		/* update context to return SC7 status value */
+		write_ctx_reg(gp_regs, CTX_GPREG_X1, ret);
+		write_ctx_reg(gp_regs, CTX_GPREG_X3, ret);
+
+		break;
+
+	case MCE_CMD_ONLINE_CORE:
+		/* NVG */
+
+		break;
+
+	case MCE_CMD_CC3_CTRL:
+		/* NVG */
+
+		break;
+
+	case MCE_CMD_ECHO_DATA:
+		/* issue NVG to echo data */
+
+		/* update context to return if echo'd data matched source */
+		write_ctx_reg(gp_regs, CTX_GPREG_X1, ret64 == arg0);
+		write_ctx_reg(gp_regs, CTX_GPREG_X2, ret64 == arg0);
+
+		break;
+
+	case MCE_CMD_READ_VERSIONS:
+		/* get the MCE firmware version */
+
+		/*
+		 * version = minor(63:32) | major(31:0). Update context
+		 * to return major and minor version number.
+		 */
+		write_ctx_reg(gp_regs, CTX_GPREG_X1, (uint32_t)ret64);
+		write_ctx_reg(gp_regs, CTX_GPREG_X2, (uint32_t)(ret64 >> 32));
+
+		break;
+
+	case MCE_CMD_ENUM_FEATURES:
+		break;
+
+	case MCE_CMD_ROC_FLUSH_CACHE_TRBITS:
+		/* NVG */
+
+		break;
+
+	case MCE_CMD_ROC_FLUSH_CACHE:
+		/* NVG */
+
+		break;
+
+	case MCE_CMD_ROC_CLEAN_CACHE:
+		/* NVG */
+
+		break;
+
+	case MCE_CMD_ENUM_READ_MCA:
+		memcpy(&mca_cmd, &arg0, sizeof(arg0));
+
+		/* NVG */
+
+		/* update context to return MCA data/error */
+		write_ctx_reg(gp_regs, CTX_GPREG_X1, ret64);
+		write_ctx_reg(gp_regs, CTX_GPREG_X2, arg1);
+		write_ctx_reg(gp_regs, CTX_GPREG_X3, ret64);
+
+		break;
+
+	case MCE_CMD_ENUM_WRITE_MCA:
+		memcpy(&mca_cmd, &arg0, sizeof(arg0));
+
+		/* NVG */
+
+		/* update context to return MCA error */
+		write_ctx_reg(gp_regs, CTX_GPREG_X1, ret64);
+		write_ctx_reg(gp_regs, CTX_GPREG_X3, ret64);
+
+		break;
+
+	case MCE_CMD_ENABLE_LATIC:
+		/*
+		 * This call is not for production use. The constant value,
+		 * 0xFFFF0000, is specific to allowing for enabling LATIC on
+		 * pre-production parts for the chip verification harness.
+		 *
+		 * Enabling LATIC allows S/W to read the MINI ISPs in the
+		 * CCPLEX. The ISMs are used for various measurements relevant
+		 * to particular locations in the Silicon. They are small
+		 * counters which can be polled to determine how fast a
+		 * particular location in the Silicon is.
+		 */
+		/* NVG */
+
+		break;
+
+	case MCE_CMD_UNCORE_PERFMON_REQ:
+		memcpy(&req, &arg0, sizeof(arg0));
+		/* NVG */
+
+		/* update context to return data */
+		write_ctx_reg(gp_regs, CTX_GPREG_X1, arg1);
+		break;
+
+	case MCE_CMD_MISC_CCPLEX:
+		/* NVG */
+
+		break;
+
+	default:
+		ERROR("unknown MCE command (%lld)\n", cmd);
+		return EINVAL;
+	}
+
+	return ret;
+}
+
+/*******************************************************************************
+ * Handler to update the reset vector for CPUs
+ ******************************************************************************/
+int mce_update_reset_vector(void)
+{
+	return 0;
+}
+
+static int mce_update_ccplex_gsc(/* GSC ID */)
+{
+	return 0;
+}
+
+/*******************************************************************************
+ * Handler to update carveout values for Video Memory Carveout region
+ ******************************************************************************/
+int mce_update_gsc_videomem(void)
+{
+	return mce_update_ccplex_gsc();
+}
+
+/*******************************************************************************
+ * Handler to update carveout values for TZDRAM aperture
+ ******************************************************************************/
+int mce_update_gsc_tzdram(void)
+{
+	return mce_update_ccplex_gsc();
+}
+
+/*******************************************************************************
+ * Handler to update carveout values for TZ SysRAM aperture
+ ******************************************************************************/
+int mce_update_gsc_tzram(void)
+{
+	return mce_update_ccplex_gsc();
+}
+
+/*******************************************************************************
+ * Handler to shutdown/reset the entire system
+ ******************************************************************************/
+__dead2 void mce_enter_ccplex_state(uint32_t state_idx)
+{
+	/* sanity check state value */
+
+	/* enter ccplex power state */
+
+	/* wait till the CCPLEX powers down */
+	for (;;)
+		;
+
+	panic();
+}
+
+/*******************************************************************************
+ * Handler to issue the UPDATE_CSTATE_INFO request
+ ******************************************************************************/
+void mce_update_cstate_info(mce_cstate_info_t *cstate)
+{
+	/* issue the UPDATE_CSTATE_INFO request */
+	/* NVG */
+}
+
+/*******************************************************************************
+ * Handler to read the MCE firmware version and check if it is compatible
+ * with interface header the BL3-1 was compiled against
+ ******************************************************************************/
+void mce_verify_firmware_version(void)
+{
+	uint64_t version;
+	uint32_t major, minor;
+
+	/*
+	 * MCE firmware is not running on simulation platforms.
+	 */
+	if (tegra_platform_is_linsim() || tegra_platform_is_virt_dev_kit())
+		return;
+
+	/* get a pointer to the CPU's arch_mce_ops_t struct */
+
+	/*
+	 * Read the MCE firmware version and extract the major and minor
+	 * version fields
+	 */
+	version = 0;
+	major = (uint32_t)version;
+	minor = (uint32_t)(version >> 32);
+
+	INFO("MCE Version - HW=%d:%d, SW=%d:%d\n", major, minor,
+		0, 0);
+
+	/*
+	 * Verify that the MCE firmware version and the interface header
+	 * match
+	 */
+	if (major != 0) {
+		ERROR("MCE major version mismatch\n");
+		panic();
+	}
+
+	if (minor < 0) {
+		ERROR("MCE minor version mismatch\n");
+		panic();
+	}
+}
diff --git a/plat/nvidia/tegra/soc/t194/drivers/mce/nvg.c b/plat/nvidia/tegra/soc/t194/drivers/mce/nvg.c
new file mode 100644
index 0000000..36b3aab
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t194/drivers/mce/nvg.c
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <denver.h>
+#include <lib/mmio.h>
+#include <mce_private.h>
+#include <errno.h>
+
+extern void nvg_set_request_data(uint64_t req, uint64_t data);
+extern void nvg_set_request(uint64_t req);
+extern uint64_t nvg_get_result(void);
+
+int nvg_enter_cstate(uint32_t ari_base, uint32_t state, uint32_t wake_time)
+{
+	/* check for allowed power state */
+	if (state != TEGRA_ARI_CORE_C0 && state != TEGRA_ARI_CORE_C1 &&
+	    state != TEGRA_ARI_CORE_C6 && state != TEGRA_ARI_CORE_C7) {
+		ERROR("%s: unknown cstate (%d)\n", __func__, state);
+		return EINVAL;
+	}
+
+	/* time (TSC ticks) until the core is expected to get a wake event */
+	nvg_set_request_data(TEGRA_NVG_CHANNEL_WAKE_TIME, wake_time);
+
+	/* set the core cstate */
+	write_actlr_el1(state);
+
+	return 0;
+}
+
+/*
+ * This request allows updating of CLUSTER_CSTATE, CCPLEX_CSTATE and
+ * SYSTEM_CSTATE values.
+ */
+int nvg_update_cstate_info(uint32_t ari_base, uint32_t cluster, uint32_t ccplex,
+		uint32_t system, uint8_t sys_state_force, uint32_t wake_mask,
+		uint8_t update_wake_mask)
+{
+	uint64_t val = 0;
+
+	/* update CLUSTER_CSTATE? */
+	if (cluster)
+		val |= (cluster & CLUSTER_CSTATE_MASK) |
+			CLUSTER_CSTATE_UPDATE_BIT;
+
+	/* update CCPLEX_CSTATE? */
+	if (ccplex)
+		val |= (ccplex & CCPLEX_CSTATE_MASK) << CCPLEX_CSTATE_SHIFT |
+			CCPLEX_CSTATE_UPDATE_BIT;
+
+	/* update SYSTEM_CSTATE? */
+	if (system)
+		val |= ((system & SYSTEM_CSTATE_MASK) << SYSTEM_CSTATE_SHIFT) |
+		       ((sys_state_force << SYSTEM_CSTATE_FORCE_UPDATE_SHIFT) |
+			SYSTEM_CSTATE_UPDATE_BIT);
+
+	/* update wake mask value? */
+	if (update_wake_mask)
+		val |= CSTATE_WAKE_MASK_UPDATE_BIT;
+
+	/* set the wake mask */
+	val &= CSTATE_WAKE_MASK_CLEAR;
+	val |= ((uint64_t)wake_mask << CSTATE_WAKE_MASK_SHIFT);
+
+	/* set the updated cstate info */
+	nvg_set_request_data(TEGRA_NVG_CHANNEL_CSTATE_INFO, val);
+
+	return 0;
+}
+
+int nvg_update_crossover_time(uint32_t ari_base, uint32_t type, uint32_t time)
+{
+	/* sanity check crossover type */
+	if (type > TEGRA_ARI_CROSSOVER_CCP3_SC1)
+		return EINVAL;
+
+	/*
+	 * The crossover threshold limit types start from
+	 * TEGRA_CROSSOVER_TYPE_C1_C6 to TEGRA_CROSSOVER_TYPE_CCP3_SC7. The
+	 * command indices for updating the threshold can be generated
+	 * by adding the type to the NVG_SET_THRESHOLD_CROSSOVER_C1_C6
+	 * command index.
+	 */
+	nvg_set_request_data(TEGRA_NVG_CHANNEL_CROSSOVER_C1_C6 + type,
+		(uint64_t)time);
+
+	return 0;
+}
+
+uint64_t nvg_read_cstate_stats(uint32_t ari_base, uint32_t state)
+{
+	/* sanity check state */
+	if (state == 0)
+		return EINVAL;
+
+	/*
+	 * The cstate types start from NVG_READ_CSTATE_STATS_SC7_ENTRIES
+	 * to NVG_GET_LAST_CSTATE_ENTRY_A57_3. The command indices for
+	 * reading the threshold can be generated by adding the type to
+	 * the NVG_CLEAR_CSTATE_STATS command index.
+	 */
+	nvg_set_request(TEGRA_NVG_CHANNEL_CSTATE_STATS_CLEAR + state);
+
+	return (int64_t)nvg_get_result();
+}
+
+int nvg_write_cstate_stats(uint32_t ari_base, uint32_t state, uint32_t stats)
+{
+	uint64_t val;
+
+	/*
+	 * The only difference between a CSTATE_STATS_WRITE and
+	 * CSTATE_STATS_READ is the usage of the 63:32 in the request.
+	 * 63:32 are set to '0' for a read, while a write contains the
+	 * actual stats value to be written.
+	 */
+	val = ((uint64_t)stats << MCE_CSTATE_STATS_TYPE_SHIFT) | state;
+
+	/*
+	 * The cstate types start from NVG_READ_CSTATE_STATS_SC7_ENTRIES
+	 * to NVG_GET_LAST_CSTATE_ENTRY_A57_3. The command indices for
+	 * reading the threshold can be generated by adding the type to
+	 * the NVG_CLEAR_CSTATE_STATS command index.
+	 */
+	nvg_set_request_data(TEGRA_NVG_CHANNEL_CSTATE_STATS_CLEAR + state, val);
+
+	return 0;
+}
+
+int nvg_is_ccx_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time)
+{
+	/* This does not apply to the Denver cluster */
+	return 0;
+}
+
+int nvg_is_sc7_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time)
+{
+	uint64_t val;
+
+	/* check for allowed power state */
+	if (state != TEGRA_ARI_CORE_C0 && state != TEGRA_ARI_CORE_C1 &&
+	    state != TEGRA_ARI_CORE_C6 && state != TEGRA_ARI_CORE_C7) {
+		ERROR("%s: unknown cstate (%d)\n", __func__, state);
+		return EINVAL;
+	}
+
+	/*
+	 * Request format -
+	 * 63:32 = wake time
+	 * 31:0 = C-state for this core
+	 */
+	val = ((uint64_t)wake_time << MCE_SC7_WAKE_TIME_SHIFT) |
+			(state & MCE_SC7_ALLOWED_MASK);
+
+	/* issue command to check if SC7 is allowed */
+	nvg_set_request_data(TEGRA_NVG_CHANNEL_IS_SC7_ALLOWED, val);
+
+	/* 1 = SC7 allowed, 0 = SC7 not allowed */
+	return !!nvg_get_result();
+}
+
+int nvg_online_core(uint32_t ari_base, uint32_t core)
+{
+	int cpu = read_mpidr() & MPIDR_CPU_MASK;
+	int impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK;
+
+	/* sanity check code id */
+	if ((core >= MCE_CORE_ID_MAX) || (cpu == core)) {
+		ERROR("%s: unsupported core id (%d)\n", __func__, core);
+		return EINVAL;
+	}
+
+	/*
+	 * The Denver cluster has 2 CPUs only - 0, 1.
+	 */
+	if (impl == DENVER_IMPL && ((core == 2) || (core == 3))) {
+		ERROR("%s: unknown core id (%d)\n", __func__, core);
+		return EINVAL;
+	}
+
+	/* get a core online */
+	nvg_set_request_data(TEGRA_NVG_CHANNEL_ONLINE_CORE, core & MCE_CORE_ID_MASK);
+
+	return 0;
+}
+
+int nvg_cc3_ctrl(uint32_t ari_base, uint32_t freq, uint32_t volt, uint8_t enable)
+{
+	int val;
+
+	/*
+	 * If the enable bit is cleared, Auto-CC3 will be disabled by setting
+	 * the SW visible voltage/frequency request registers for all non
+	 * floorswept cores valid independent of StandbyWFI and disabling
+	 * the IDLE voltage/frequency request register. If set, Auto-CC3
+	 * will be enabled by setting the ARM SW visible voltage/frequency
+	 * request registers for all non floorswept cores to be enabled by
+	 * StandbyWFI or the equivalent signal, and always keeping the IDLE
+	 * voltage/frequency request register enabled.
+	 */
+	val = (((freq & MCE_AUTO_CC3_FREQ_MASK) << MCE_AUTO_CC3_FREQ_SHIFT) |\
+		((volt & MCE_AUTO_CC3_VTG_MASK) << MCE_AUTO_CC3_VTG_SHIFT) |\
+		(enable ? MCE_AUTO_CC3_ENABLE_BIT : 0));
+
+	nvg_set_request_data(TEGRA_NVG_CHANNEL_CC3_CTRL, val);
+
+	return 0;
+}
diff --git a/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c
new file mode 100644
index 0000000..fb33c13
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c
@@ -0,0 +1,306 @@
+/*
+ * Copyright (c) 2019, NVIDIA CORPORATION. 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 <context.h>
+#include <lib/el3_runtime/context_mgmt.h>
+#include <common/debug.h>
+#include <denver.h>
+#include <mce.h>
+#include <plat/common/platform.h>
+#include <lib/psci/psci.h>
+#include <smmu.h>
+#include <string.h>
+#include <tegra_private.h>
+
+extern void prepare_core_pwr_dwn(void);
+
+#if ENABLE_SYSTEM_SUSPEND_CTX_SAVE_TZDRAM
+extern void tegra186_cpu_reset_handler(void);
+extern uint32_t __tegra186_cpu_reset_handler_data,
+		__tegra186_cpu_reset_handler_end;
+
+/* TZDRAM offset for saving SMMU context */
+#define TEGRA186_SMMU_CTX_OFFSET	16
+#endif
+
+/* state id mask */
+#define TEGRA186_STATE_ID_MASK		0xF
+/* constants to get power state's wake time */
+#define TEGRA186_WAKE_TIME_MASK		0x0FFFFFF0
+#define TEGRA186_WAKE_TIME_SHIFT	4
+/* default core wake mask for CPU_SUSPEND */
+#define TEGRA186_CORE_WAKE_MASK		0x180c
+/* context size to save during system suspend */
+#define TEGRA186_SE_CONTEXT_SIZE	3
+
+static uint32_t se_regs[TEGRA186_SE_CONTEXT_SIZE];
+static struct t18x_psci_percpu_data {
+	unsigned int wake_time;
+} __aligned(CACHE_WRITEBACK_GRANULE) percpu_data[PLATFORM_CORE_COUNT];
+
+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) & TEGRA186_STATE_ID_MASK;
+	int cpu = plat_my_core_pos();
+
+	/* save the core wake time (in TSC ticks)*/
+	percpu_data[cpu].wake_time = (power_state & TEGRA186_WAKE_TIME_MASK)
+			<< TEGRA186_WAKE_TIME_SHIFT;
+
+	/*
+	 * Clean percpu_data[cpu] to DRAM. This needs to be done to ensure that
+	 * the correct value is read in tegra_soc_pwr_domain_suspend(), which
+	 * is called with caches disabled. It is possible to read a stale value
+	 * from DRAM in that function, because the L2 cache is not flushed
+	 * unless the cluster is entering CC6/CC7.
+	 */
+	clean_dcache_range((uint64_t)&percpu_data[cpu],
+			sizeof(percpu_data[cpu]));
+
+	/* Sanity check the requested state id */
+	switch (state_id) {
+	case PSTATE_ID_CORE_IDLE:
+	case PSTATE_ID_CORE_POWERDN:
+
+		/* Core powerdown request */
+		req_state->pwr_domain_state[MPIDR_AFFLVL0] = state_id;
+		req_state->pwr_domain_state[MPIDR_AFFLVL1] = state_id;
+
+		break;
+
+	default:
+		ERROR("%s: unsupported state id (%d)\n", __func__, state_id);
+		return PSCI_E_INVALID_PARAMS;
+	}
+
+	return PSCI_E_SUCCESS;
+}
+
+int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state)
+{
+	const plat_local_state_t *pwr_domain_state;
+	unsigned int stateid_afflvl0, stateid_afflvl2;
+#if ENABLE_SYSTEM_SUSPEND_CTX_SAVE_TZDRAM
+	plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params();
+	uint64_t smmu_ctx_base;
+#endif
+	uint32_t val;
+
+	/* get the state ID */
+	pwr_domain_state = target_state->pwr_domain_state;
+	stateid_afflvl0 = pwr_domain_state[MPIDR_AFFLVL0] &
+		TEGRA186_STATE_ID_MASK;
+	stateid_afflvl2 = pwr_domain_state[PLAT_MAX_PWR_LVL] &
+		TEGRA186_STATE_ID_MASK;
+
+	if ((stateid_afflvl0 == PSTATE_ID_CORE_IDLE) ||
+	    (stateid_afflvl0 == PSTATE_ID_CORE_POWERDN)) {
+
+		/* Enter CPU idle/powerdown */
+
+	} else if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) {
+
+		/* save SE registers */
+		se_regs[0] = mmio_read_32(TEGRA_SE0_BASE +
+				SE_MUTEX_WATCHDOG_NS_LIMIT);
+		se_regs[1] = mmio_read_32(TEGRA_RNG1_BASE +
+				RNG_MUTEX_WATCHDOG_NS_LIMIT);
+		se_regs[2] = mmio_read_32(TEGRA_PKA1_BASE +
+				PKA_MUTEX_WATCHDOG_NS_LIMIT);
+
+		/* save 'Secure Boot' Processor Feature Config Register */
+		val = mmio_read_32(TEGRA_MISC_BASE + MISCREG_PFCFG);
+		mmio_write_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV6, val);
+
+#if ENABLE_SYSTEM_SUSPEND_CTX_SAVE_TZDRAM
+		/* save SMMU context */
+		smmu_ctx_base = params_from_bl2->tzdram_base +
+			((uintptr_t)&__tegra186_cpu_reset_handler_data -
+			 (uintptr_t)tegra186_cpu_reset_handler) +
+			TEGRA186_SMMU_CTX_OFFSET;
+		tegra_smmu_save_context((uintptr_t)smmu_ctx_base);
+#else
+		tegra_smmu_save_context(0);
+#endif
+
+		/* Instruct the MCE to enter system suspend state */
+	}
+
+	return PSCI_E_SUCCESS;
+}
+
+/*******************************************************************************
+ * Platform handler to calculate the proper target power level at the
+ * specified affinity level
+ ******************************************************************************/
+plat_local_state_t tegra_soc_get_target_pwr_state(unsigned int lvl,
+					     const plat_local_state_t *states,
+					     unsigned int ncpu)
+{
+	plat_local_state_t target = *states;
+	int cluster_powerdn = 1;
+	int core_pos = read_mpidr() & MPIDR_CPU_MASK;
+
+	/* get the current core's power state */
+	target = *(states + core_pos);
+
+	/* CPU suspend */
+	if (lvl == MPIDR_AFFLVL1 && target == PSTATE_ID_CORE_POWERDN) {
+
+		/* Program default wake mask */
+
+		/* Check if CCx state is allowed. */
+	}
+
+	/* CPU off */
+	if (lvl == MPIDR_AFFLVL1 && target == PLAT_MAX_OFF_STATE) {
+
+		/* find out the number of ON cpus in the cluster */
+		do {
+			target = *states++;
+			if (target != PLAT_MAX_OFF_STATE)
+				cluster_powerdn = 0;
+		} while (--ncpu);
+
+		/* Enable cluster powerdn from last CPU in the cluster */
+		if (cluster_powerdn) {
+
+			/* Enable CC7 state and turn off wake mask */
+
+		} else {
+
+			/* Turn off wake_mask */
+		}
+	}
+
+	/* System Suspend */
+	if ((lvl == MPIDR_AFFLVL2) || (target == PSTATE_ID_SOC_POWERDN))
+		return PSTATE_ID_SOC_POWERDN;
+
+	/* default state */
+	return PSCI_LOCAL_STATE_RUN;
+}
+
+#if ENABLE_SYSTEM_SUSPEND_CTX_SAVE_TZDRAM
+int tegra_soc_pwr_domain_power_down_wfi(const psci_power_state_t *target_state)
+{
+	const plat_local_state_t *pwr_domain_state =
+		target_state->pwr_domain_state;
+	plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params();
+	unsigned int stateid_afflvl2 = pwr_domain_state[PLAT_MAX_PWR_LVL] &
+		TEGRA186_STATE_ID_MASK;
+	uint32_t val;
+
+	if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) {
+		/*
+		 * The TZRAM loses power when we enter system suspend. To
+		 * allow graceful exit from system suspend, we need to copy
+		 * BL3-1 over to TZDRAM.
+		 */
+		val = params_from_bl2->tzdram_base +
+			((uintptr_t)&__tegra186_cpu_reset_handler_end -
+			 (uintptr_t)tegra186_cpu_reset_handler);
+		memcpy((void *)(uintptr_t)val, (void *)(uintptr_t)BL31_BASE,
+		       (uintptr_t)&__BL31_END__ - (uintptr_t)BL31_BASE);
+	}
+
+	return PSCI_E_SUCCESS;
+}
+#endif
+
+int tegra_soc_pwr_domain_on(u_register_t mpidr)
+{
+	int target_cpu = mpidr & MPIDR_CPU_MASK;
+	int target_cluster = (mpidr & MPIDR_CLUSTER_MASK) >>
+			MPIDR_AFFINITY_BITS;
+
+	if (target_cluster > MPIDR_AFFLVL1) {
+		ERROR("%s: unsupported CPU (0x%lx)\n", __func__ , mpidr);
+		return PSCI_E_NOT_PRESENT;
+	}
+
+	/* construct the target CPU # */
+	target_cpu |= (target_cluster << 2);
+
+	mce_command_handler(MCE_CMD_ONLINE_CORE, target_cpu, 0, 0);
+
+	return PSCI_E_SUCCESS;
+}
+
+int tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+	int stateid_afflvl2 = target_state->pwr_domain_state[PLAT_MAX_PWR_LVL];
+
+	/*
+	 * Reset power state info for CPUs when onlining, we set
+	 * deepest power when offlining a core but that may not be
+	 * requested by non-secure sw which controls idle states. It
+	 * will re-init this info from non-secure software when the
+	 * core come online.
+	 */
+
+	/*
+	 * Check if we are exiting from deep sleep and restore SE
+	 * context if we are.
+	 */
+	if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) {
+
+		mmio_write_32(TEGRA_SE0_BASE + SE_MUTEX_WATCHDOG_NS_LIMIT,
+			se_regs[0]);
+		mmio_write_32(TEGRA_RNG1_BASE + RNG_MUTEX_WATCHDOG_NS_LIMIT,
+			se_regs[1]);
+		mmio_write_32(TEGRA_PKA1_BASE + PKA_MUTEX_WATCHDOG_NS_LIMIT,
+			se_regs[2]);
+
+		/* Init SMMU */
+
+		/*
+		 * Reset power state info for the last core doing SC7
+		 * entry and exit, we set deepest power state as CC7
+		 * and SC7 for SC7 entry which may not be requested by
+		 * non-secure SW which controls idle states.
+		 */
+	}
+
+	return PSCI_E_SUCCESS;
+}
+
+int tegra_soc_pwr_domain_off(const psci_power_state_t *target_state)
+{
+	int impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK;
+
+	/* Disable Denver's DCO operations */
+	if (impl == DENVER_IMPL)
+		denver_disable_dco();
+
+	/* Turn off CPU */
+
+	return PSCI_E_SUCCESS;
+}
+
+__dead2 void tegra_soc_prepare_system_off(void)
+{
+	/* System power off */
+
+	/* SC8 */
+
+	wfi();
+
+	/* wait for the system to power down */
+	for (;;) {
+		;
+	}
+}
+
+int tegra_soc_prepare_system_reset(void)
+{
+	return PSCI_E_SUCCESS;
+}
diff --git a/plat/nvidia/tegra/soc/t194/plat_secondary.c b/plat/nvidia/tegra/soc/t194/plat_secondary.c
new file mode 100644
index 0000000..33c8e1b
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t194/plat_secondary.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <mce.h>
+#include <string.h>
+#include <tegra_def.h>
+#include <tegra_private.h>
+
+#define MISCREG_CPU_RESET_VECTOR	0x2000
+#define MISCREG_AA64_RST_LOW		0x2004
+#define MISCREG_AA64_RST_HIGH		0x2008
+
+#define CPU_RESET_MODE_AA64		1
+
+extern void tegra_secure_entrypoint(void);
+
+#if ENABLE_SYSTEM_SUSPEND_CTX_SAVE_TZDRAM
+extern void tegra186_cpu_reset_handler(void);
+extern uint64_t __tegra186_smmu_ctx_start;
+#endif
+
+/*******************************************************************************
+ * Setup secondary CPU vectors
+ ******************************************************************************/
+void plat_secondary_setup(void)
+{
+	uint32_t addr_low, addr_high;
+#if ENABLE_SYSTEM_SUSPEND_CTX_SAVE_TZDRAM
+	plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params();
+	uint64_t cpu_reset_handler_base = params_from_bl2->tzdram_base;
+#else
+	uint64_t cpu_reset_handler_base = (uintptr_t)tegra_secure_entrypoint;
+#endif
+
+	INFO("Setting up secondary CPU boot\n");
+
+#if ENABLE_SYSTEM_SUSPEND_CTX_SAVE_TZDRAM
+	memcpy((void *)((uintptr_t)cpu_reset_handler_base),
+		 (void *)(uintptr_t)tegra186_cpu_reset_handler,
+		 (uintptr_t)&__tegra186_smmu_ctx_start -
+		 (uintptr_t)tegra186_cpu_reset_handler);
+#endif
+
+	addr_low = (uint32_t)cpu_reset_handler_base | CPU_RESET_MODE_AA64;
+	addr_high = (uint32_t)((cpu_reset_handler_base >> 32) & 0x7ff);
+
+	/* write lower 32 bits first, then the upper 11 bits */
+	mmio_write_32(TEGRA_MISC_BASE + MISCREG_AA64_RST_LOW, addr_low);
+	mmio_write_32(TEGRA_MISC_BASE + MISCREG_AA64_RST_HIGH, addr_high);
+
+	/* save reset vector to be used during SYSTEM_SUSPEND exit */
+	mmio_write_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV1_LO,
+			addr_low);
+	mmio_write_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV1_HI,
+			addr_high);
+
+	/* update reset vector address to the CCPLEX */
+	mce_update_reset_vector();
+}
diff --git a/plat/nvidia/tegra/soc/t194/plat_setup.c b/plat/nvidia/tegra/soc/t194/plat_setup.c
new file mode 100644
index 0000000..aab884e
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t194/plat_setup.c
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl31/bl31.h>
+#include <common/bl_common.h>
+#include <common/interrupt_props.h>
+#include <drivers/console.h>
+#include <context.h>
+#include <lib/el3_runtime/context_mgmt.h>
+#include <cortex_a57.h>
+#include <common/debug.h>
+#include <denver.h>
+#include <drivers/arm/gic_common.h>
+#include <drivers/arm/gicv2.h>
+#include <bl31/interrupt_mgmt.h>
+#include <mce.h>
+#include <plat/common/platform.h>
+#include <tegra_def.h>
+#include <tegra_platform.h>
+#include <tegra_private.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+
+DEFINE_RENAME_SYSREG_RW_FUNCS(l2ctlr_el1, L2CTLR_EL1)
+extern uint64_t tegra_enable_l2_ecc_parity_prot;
+
+/*******************************************************************************
+ * The Tegra power domain tree has a single system level power domain i.e. a
+ * single root node. The first entry in the power domain descriptor specifies
+ * the number of power domains at the highest power level.
+ *******************************************************************************
+ */
+const unsigned char tegra_power_domain_tree_desc[] = {
+	/* No of root nodes */
+	1,
+	/* No of clusters */
+	PLATFORM_CLUSTER_COUNT,
+	/* No of CPU cores - cluster0 */
+	PLATFORM_MAX_CPUS_PER_CLUSTER,
+	/* No of CPU cores - cluster1 */
+	PLATFORM_MAX_CPUS_PER_CLUSTER
+};
+
+/*
+ * Table of regions to map using the MMU.
+ */
+static const mmap_region_t tegra_mmap[] = {
+	MAP_REGION_FLAT(TEGRA_MISC_BASE, 0x10000, /* 64KB */
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(TEGRA_TSA_BASE, 0x20000, /* 128KB */
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(TEGRA_MC_STREAMID_BASE, 0x10000, /* 64KB */
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(TEGRA_MC_BASE, 0x10000, /* 64KB */
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(TEGRA_UARTA_BASE, 0x20000, /* 128KB - UART A, B*/
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(TEGRA_UARTC_BASE, 0x20000, /* 128KB - UART C, G */
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(TEGRA_UARTD_BASE, 0x30000, /* 192KB - UART D, E, F */
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(TEGRA_FUSE_BASE, 0x10000, /* 64KB */
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(TEGRA_GICD_BASE, 0x20000, /* 128KB */
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(TEGRA_SE0_BASE, 0x10000, /* 64KB */
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(TEGRA_PKA1_BASE, 0x10000, /* 64KB */
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(TEGRA_RNG1_BASE, 0x10000, /* 64KB */
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(TEGRA_CAR_RESET_BASE, 0x10000, /* 64KB */
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(TEGRA_PMC_BASE, 0x40000, /* 256KB */
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(TEGRA_SCRATCH_BASE, 0x10000, /* 64KB */
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(TEGRA_MMCRAB_BASE, 0x60000, /* 384KB */
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(TEGRA_SMMU_BASE, 0x1000000, /* 64KB */
+			MT_DEVICE | MT_RW | MT_SECURE),
+	{0}
+};
+
+/*******************************************************************************
+ * Set up the pagetables as per the platform memory map & initialize the MMU
+ ******************************************************************************/
+const mmap_region_t *plat_get_mmio_map(void)
+{
+	/* MMIO space */
+	return tegra_mmap;
+}
+
+/*******************************************************************************
+ * Handler to get the System Counter Frequency
+ ******************************************************************************/
+unsigned int plat_get_syscnt_freq2(void)
+{
+	return 31250000;
+}
+
+/*******************************************************************************
+ * Maximum supported UART controllers
+ ******************************************************************************/
+#define TEGRA186_MAX_UART_PORTS		7
+
+/*******************************************************************************
+ * This variable holds the UART port base addresses
+ ******************************************************************************/
+static uint32_t tegra186_uart_addresses[TEGRA186_MAX_UART_PORTS + 1] = {
+	0,	/* undefined - treated as an error case */
+	TEGRA_UARTA_BASE,
+	TEGRA_UARTB_BASE,
+	TEGRA_UARTC_BASE,
+	TEGRA_UARTD_BASE,
+	TEGRA_UARTE_BASE,
+	TEGRA_UARTF_BASE,
+	TEGRA_UARTG_BASE,
+};
+
+/*******************************************************************************
+ * Retrieve the UART controller base to be used as the console
+ ******************************************************************************/
+uint32_t plat_get_console_from_id(int id)
+{
+	if (id > TEGRA186_MAX_UART_PORTS)
+		return 0;
+
+	return tegra186_uart_addresses[id];
+}
+
+/* represent chip-version as concatenation of major (15:12), minor (11:8) and subrev (7:0) */
+#define TEGRA186_VER_A02P	0x1201
+
+/*******************************************************************************
+ * Handler for early platform setup
+ ******************************************************************************/
+void plat_early_platform_setup(void)
+{
+	int impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK;
+	uint32_t chip_subrev, val;
+
+	/* sanity check MCE firmware compatibility */
+	mce_verify_firmware_version();
+
+	/*
+	 * Enable ECC and Parity Protection for Cortex-A57 CPUs
+	 * for Tegra A02p SKUs
+	 */
+	if (impl != DENVER_IMPL) {
+
+		/* get the major, minor and sub-version values */
+		chip_subrev = mmio_read_32(TEGRA_FUSE_BASE + OPT_SUBREVISION) &
+			      SUBREVISION_MASK;
+
+		/* prepare chip version number */
+		val = (tegra_get_chipid_major() << 12) |
+		      (tegra_get_chipid_minor() << 8) |
+		       chip_subrev;
+
+		/* enable L2 ECC for Tegra186 A02P and beyond */
+		if (val >= TEGRA186_VER_A02P) {
+
+			val = read_l2ctlr_el1();
+			val |= L2_ECC_PARITY_PROTECTION_BIT;
+			write_l2ctlr_el1(val);
+
+			/*
+			 * Set the flag to enable ECC/Parity Protection
+			 * when we exit System Suspend or Cluster Powerdn
+			 */
+			tegra_enable_l2_ecc_parity_prot = 1;
+		}
+	}
+}
+
+/* Secure IRQs for Tegra186 */
+static const irq_sec_cfg_t tegra186_sec_irqs[] = {
+	[0] = {
+		TEGRA186_BPMP_WDT_IRQ,
+		TEGRA186_SEC_IRQ_TARGET_MASK,
+		INTR_TYPE_EL3,
+	},
+	[1] = {
+		TEGRA186_BPMP_WDT_IRQ,
+		TEGRA186_SEC_IRQ_TARGET_MASK,
+		INTR_TYPE_EL3,
+	},
+	[2] = {
+		TEGRA186_SPE_WDT_IRQ,
+		TEGRA186_SEC_IRQ_TARGET_MASK,
+		INTR_TYPE_EL3,
+	},
+	[3] = {
+		TEGRA186_SCE_WDT_IRQ,
+		TEGRA186_SEC_IRQ_TARGET_MASK,
+		INTR_TYPE_EL3,
+	},
+	[4] = {
+		TEGRA186_TOP_WDT_IRQ,
+		TEGRA186_SEC_IRQ_TARGET_MASK,
+		INTR_TYPE_EL3,
+	},
+	[5] = {
+		TEGRA186_AON_WDT_IRQ,
+		TEGRA186_SEC_IRQ_TARGET_MASK,
+		INTR_TYPE_EL3,
+	},
+};
+
+/*******************************************************************************
+ * Initialize the GIC and SGIs
+ ******************************************************************************/
+void plat_gic_setup(void)
+{
+	tegra_gic_setup(tegra186_sec_irqs,
+		sizeof(tegra186_sec_irqs) / sizeof(tegra186_sec_irqs[0]));
+
+	/*
+	 * Initialize the FIQ handler only if the platform supports any
+	 * FIQ interrupt sources.
+	 */
+	if (sizeof(tegra186_sec_irqs) > 0)
+		tegra_fiq_handler_setup();
+}
+
+/*******************************************************************************
+ * Return pointer to the BL31 params from previous bootloader
+ ******************************************************************************/
+struct tegra_bl31_params *plat_get_bl31_params(void)
+{
+	uint32_t val;
+
+	val = mmio_read_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV53_LO);
+
+	return (struct tegra_bl31_params *)(uintptr_t)val;
+}
+
+/*******************************************************************************
+ * Return pointer to the BL31 platform params from previous bootloader
+ ******************************************************************************/
+plat_params_from_bl2_t *plat_get_bl31_plat_params(void)
+{
+	uint32_t val;
+
+	val = mmio_read_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV53_HI);
+
+	return (plat_params_from_bl2_t *)(uintptr_t)val;
+}
diff --git a/plat/nvidia/tegra/soc/t194/plat_sip_calls.c b/plat/nvidia/tegra/soc/t194/plat_sip_calls.c
new file mode 100644
index 0000000..12b4b77
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t194/plat_sip_calls.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2019, NVIDIA CORPORATION. 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 <lib/el3_runtime/context_mgmt.h>
+#include <common/debug.h>
+#include <errno.h>
+#include <mce.h>
+#include <memctrl.h>
+#include <common/runtime_svc.h>
+#include <tegra_private.h>
+
+extern uint32_t tegra186_system_powerdn_state;
+
+/*******************************************************************************
+ * Tegra186 SiP SMCs
+ ******************************************************************************/
+#define TEGRA_SIP_NEW_VIDEOMEM_REGION			0x82000003
+#define TEGRA_SIP_SYSTEM_SHUTDOWN_STATE			0x82FFFE01
+#define TEGRA_SIP_MCE_CMD_ENTER_CSTATE			0x82FFFF00
+#define TEGRA_SIP_MCE_CMD_UPDATE_CSTATE_INFO		0x82FFFF01
+#define TEGRA_SIP_MCE_CMD_UPDATE_CROSSOVER_TIME		0x82FFFF02
+#define TEGRA_SIP_MCE_CMD_READ_CSTATE_STATS		0x82FFFF03
+#define TEGRA_SIP_MCE_CMD_WRITE_CSTATE_STATS		0x82FFFF04
+#define TEGRA_SIP_MCE_CMD_IS_SC7_ALLOWED		0x82FFFF05
+#define TEGRA_SIP_MCE_CMD_ONLINE_CORE			0x82FFFF06
+#define TEGRA_SIP_MCE_CMD_CC3_CTRL			0x82FFFF07
+#define TEGRA_SIP_MCE_CMD_ECHO_DATA			0x82FFFF08
+#define TEGRA_SIP_MCE_CMD_READ_VERSIONS			0x82FFFF09
+#define TEGRA_SIP_MCE_CMD_ENUM_FEATURES			0x82FFFF0A
+#define TEGRA_SIP_MCE_CMD_ROC_FLUSH_CACHE_TRBITS	0x82FFFF0B
+#define TEGRA_SIP_MCE_CMD_ENUM_READ_MCA			0x82FFFF0C
+#define TEGRA_SIP_MCE_CMD_ENUM_WRITE_MCA		0x82FFFF0D
+#define TEGRA_SIP_MCE_CMD_ROC_FLUSH_CACHE		0x82FFFF0E
+#define TEGRA_SIP_MCE_CMD_ROC_CLEAN_CACHE		0x82FFFF0F
+#define TEGRA_SIP_MCE_CMD_ENABLE_LATIC			0x82FFFF10
+#define TEGRA_SIP_MCE_CMD_UNCORE_PERFMON_REQ		0x82FFFF11
+#define TEGRA_SIP_MCE_CMD_MISC_CCPLEX			0x82FFFF12
+
+/*******************************************************************************
+ * This function is responsible for handling all T186 SiP calls
+ ******************************************************************************/
+int plat_sip_handler(uint32_t smc_fid,
+		     uint64_t x1,
+		     uint64_t x2,
+		     uint64_t x3,
+		     uint64_t x4,
+		     void *cookie,
+		     void *handle,
+		     uint64_t flags)
+{
+	int mce_ret;
+
+	switch (smc_fid) {
+
+	/*
+	 * Micro Coded Engine (MCE) commands reside in the 0x82FFFF00 -
+	 * 0x82FFFFFF SiP SMC space
+	 */
+	case TEGRA_SIP_MCE_CMD_ENTER_CSTATE:
+	case TEGRA_SIP_MCE_CMD_UPDATE_CSTATE_INFO:
+	case TEGRA_SIP_MCE_CMD_UPDATE_CROSSOVER_TIME:
+	case TEGRA_SIP_MCE_CMD_READ_CSTATE_STATS:
+	case TEGRA_SIP_MCE_CMD_WRITE_CSTATE_STATS:
+	case TEGRA_SIP_MCE_CMD_IS_SC7_ALLOWED:
+	case TEGRA_SIP_MCE_CMD_CC3_CTRL:
+	case TEGRA_SIP_MCE_CMD_ECHO_DATA:
+	case TEGRA_SIP_MCE_CMD_READ_VERSIONS:
+	case TEGRA_SIP_MCE_CMD_ENUM_FEATURES:
+	case TEGRA_SIP_MCE_CMD_ROC_FLUSH_CACHE_TRBITS:
+	case TEGRA_SIP_MCE_CMD_ENUM_READ_MCA:
+	case TEGRA_SIP_MCE_CMD_ENUM_WRITE_MCA:
+	case TEGRA_SIP_MCE_CMD_ROC_FLUSH_CACHE:
+	case TEGRA_SIP_MCE_CMD_ROC_CLEAN_CACHE:
+	case TEGRA_SIP_MCE_CMD_ENABLE_LATIC:
+	case TEGRA_SIP_MCE_CMD_UNCORE_PERFMON_REQ:
+	case TEGRA_SIP_MCE_CMD_MISC_CCPLEX:
+
+		/* clean up the high bits */
+		smc_fid &= MCE_CMD_MASK;
+
+		/* execute the command and store the result */
+		mce_ret = mce_command_handler(smc_fid, x1, x2, x3);
+		write_ctx_reg(get_gpregs_ctx(handle), CTX_GPREG_X0, mce_ret);
+
+		return 0;
+
+	case TEGRA_SIP_SYSTEM_SHUTDOWN_STATE:
+
+		/* clean up the high bits */
+		x1 = (uint32_t)x1;
+
+		/*
+		 * SC8 is a special Tegra186 system state where the CPUs and
+		 * DRAM are powered down but the other subsystem is still
+		 * alive.
+		 */
+
+		return 0;
+
+	default:
+		break;
+	}
+
+	return -ENOTSUP;
+}
diff --git a/plat/nvidia/tegra/soc/t194/plat_trampoline.S b/plat/nvidia/tegra/soc/t194/plat_trampoline.S
new file mode 100644
index 0000000..cf76507
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t194/plat_trampoline.S
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <plat/common/common_def.h>
+#include <memctrl_v2.h>
+#include <tegra_def.h>
+
+#define TEGRA186_SMMU_CTX_SIZE		0x420
+
+	.align 4
+	.globl	tegra186_cpu_reset_handler
+
+/* CPU reset handler routine */
+func tegra186_cpu_reset_handler
+	/*
+	 * The TZRAM loses state during System Suspend. We use this
+	 * information to decide if the reset handler is running after a
+	 * System Suspend. Resume from system suspend requires restoring
+	 * the entire state from TZDRAM to TZRAM.
+	 */
+	mov	x0, #BL31_BASE
+	ldr	x0, [x0]
+	cbnz	x0, boot_cpu
+
+	/* resume from system suspend */
+	mov	x0, #BL31_BASE
+	adr	x1, __tegra186_cpu_reset_handler_end
+	adr	x2, __tegra186_cpu_reset_handler_data
+	ldr	x2, [x2, #8]
+
+	/* memcpy16 */
+m_loop16:
+	cmp	x2, #16
+	b.lt	m_loop1
+	ldp	x3, x4, [x1], #16
+	stp	x3, x4, [x0], #16
+	sub	x2, x2, #16
+	b	m_loop16
+	/* copy byte per byte */
+m_loop1:
+	cbz	x2, boot_cpu
+	ldrb	w3, [x1], #1
+	strb	w3, [x0], #1
+	subs	x2, x2, #1
+	b.ne	m_loop1
+
+boot_cpu:
+	adr	x0, __tegra186_cpu_reset_handler_data
+	ldr	x0, [x0]
+	br	x0
+endfunc tegra186_cpu_reset_handler
+
+	/*
+	 * Tegra186 reset data (offset 0x0 - 0x430)
+	 *
+	 * 0x000: secure world's entrypoint
+	 * 0x008: BL31 size (RO + RW)
+	 * 0x00C: SMMU context start
+	 * 0x42C: SMMU context end
+	 */
+
+	.align 4
+	.type	__tegra186_cpu_reset_handler_data, %object
+	.globl	__tegra186_cpu_reset_handler_data
+__tegra186_cpu_reset_handler_data:
+	.quad	tegra_secure_entrypoint
+	.quad	__BL31_END__ - BL31_BASE
+	.globl	__tegra186_smmu_ctx_start
+__tegra186_smmu_ctx_start:
+	.rept	TEGRA186_SMMU_CTX_SIZE
+	.quad	0
+	.endr
+	.size	__tegra186_cpu_reset_handler_data, \
+		. - __tegra186_cpu_reset_handler_data
+
+	.align 4
+	.globl	__tegra186_cpu_reset_handler_end
+__tegra186_cpu_reset_handler_end:
diff --git a/plat/nvidia/tegra/soc/t194/platform_t194.mk b/plat/nvidia/tegra/soc/t194/platform_t194.mk
new file mode 100644
index 0000000..54bc941
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t194/platform_t194.mk
@@ -0,0 +1,62 @@
+#
+# Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# platform configs
+ENABLE_AFI_DEVICE			:= 0
+$(eval $(call add_define,ENABLE_AFI_DEVICE))
+
+ENABLE_ROC_FOR_ORDERING_CLIENT_REQUESTS	:= 0
+$(eval $(call add_define,ENABLE_ROC_FOR_ORDERING_CLIENT_REQUESTS))
+
+ENABLE_SYSTEM_SUSPEND_CTX_SAVE_TZDRAM	:= 1
+$(eval $(call add_define,ENABLE_SYSTEM_SUSPEND_CTX_SAVE_TZDRAM))
+
+RELOCATE_TO_BL31_BASE			:= 1
+$(eval $(call add_define,RELOCATE_TO_BL31_BASE))
+
+ENABLE_CHIP_VERIFICATION_HARNESS	:= 0
+$(eval $(call add_define,ENABLE_CHIP_VERIFICATION_HARNESS))
+
+ENABLE_SMMU_DEVICE			:= 0
+$(eval $(call add_define,ENABLE_SMMU_DEVICE))
+
+RESET_TO_BL31				:= 1
+
+PROGRAMMABLE_RESET_ADDRESS		:= 1
+
+COLD_BOOT_SINGLE_CPU			:= 1
+
+# platform settings
+TZDRAM_BASE				:= 0x40000000
+$(eval $(call add_define,TZDRAM_BASE))
+
+PLATFORM_CLUSTER_COUNT			:= 2
+$(eval $(call add_define,PLATFORM_CLUSTER_COUNT))
+
+PLATFORM_MAX_CPUS_PER_CLUSTER		:= 4
+$(eval $(call add_define,PLATFORM_MAX_CPUS_PER_CLUSTER))
+
+MAX_XLAT_TABLES				:= 24
+$(eval $(call add_define,MAX_XLAT_TABLES))
+
+MAX_MMAP_REGIONS			:= 24
+$(eval $(call add_define,MAX_MMAP_REGIONS))
+
+# platform files
+PLAT_INCLUDES		+=	-I${SOC_DIR}/drivers/include
+
+BL31_SOURCES		+=	lib/cpus/aarch64/denver.S		\
+				${COMMON_DIR}/drivers/memctrl/memctrl_v2.c	\
+				${COMMON_DIR}/drivers/smmu/smmu.c	\
+				${SOC_DIR}/drivers/mce/mce.c		\
+				${SOC_DIR}/plat_psci_handlers.c		\
+				${SOC_DIR}/plat_setup.c			\
+				${SOC_DIR}/plat_secondary.c		\
+				${SOC_DIR}/plat_sip_calls.c
+
+ifeq (${ENABLE_SYSTEM_SUSPEND_CTX_SAVE_TZDRAM}, 1)
+BL31_SOURCES		+=	${SOC_DIR}/plat_trampoline.S
+endif