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