diff --git a/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c
index 1a77c5bf2d1983e5a073933456cae3d2fd722f64..20c0f4c12151ae77043444a9e3ffce0cc06b1961 100644
--- a/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c
+++ b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c
@@ -41,6 +41,8 @@
 #include <t18x_ari.h>
 #include <tegra_private.h>
 
+extern void prepare_cpu_pwr_dwn(void);
+
 /* state id mask */
 #define TEGRA186_STATE_ID_MASK		0xF
 /* constants to get power state's wake time */
@@ -49,6 +51,9 @@
 
 static unsigned int wake_time[PLATFORM_CORE_COUNT];
 
+/* System power down state */
+uint32_t tegra186_system_powerdn_state = TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF;
+
 int32_t tegra_soc_validate_power_state(unsigned int power_state,
 					psci_power_state_t *req_state)
 {
@@ -162,7 +167,53 @@ int tegra_soc_pwr_domain_off(const psci_power_state_t *target_state)
 
 __dead2 void tegra_soc_prepare_system_off(void)
 {
-	mce_enter_ccplex_state(TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF);
+	cpu_context_t *ctx = cm_get_context(NON_SECURE);
+	gp_regs_t *gp_regs = get_gpregs_ctx(ctx);
+	uint32_t val;
+
+	if (tegra186_system_powerdn_state == TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF) {
+
+		/* power off the entire system */
+		mce_enter_ccplex_state(tegra186_system_powerdn_state);
+
+	} else if (tegra186_system_powerdn_state == TEGRA_ARI_SYSTEM_SC8) {
+
+		/* loop until other CPUs power down */
+		do {
+			val = mce_command_handler(MCE_CMD_IS_SC7_ALLOWED,
+					TEGRA_ARI_CORE_C7,
+					MCE_CORE_SLEEP_TIME_INFINITE,
+					0);
+		} while (val == 0);
+
+		/* Prepare for quasi power down */
+		write_ctx_reg(gp_regs, CTX_GPREG_X4, 1);
+		write_ctx_reg(gp_regs, CTX_GPREG_X5, 0);
+		write_ctx_reg(gp_regs, CTX_GPREG_X6, 1);
+		(void)mce_command_handler(MCE_CMD_UPDATE_CSTATE_INFO,
+			TEGRA_ARI_CLUSTER_CC7, 0, TEGRA_ARI_SYSTEM_SC8);
+
+		/* Enter quasi power down state */
+		(void)mce_command_handler(MCE_CMD_ENTER_CSTATE,
+			TEGRA_ARI_CORE_C7, MCE_CORE_SLEEP_TIME_INFINITE, 0);
+
+		/* disable GICC */
+		tegra_gic_cpuif_deactivate();
+
+		/* power down core */
+		prepare_cpu_pwr_dwn();
+
+	} else {
+		ERROR("%s: unsupported power down state (%d)\n", __func__,
+			tegra186_system_powerdn_state);
+	}
+
+	wfi();
+
+	/* wait for the system to power down */
+	for (;;) {
+		;
+	}
 }
 
 int tegra_soc_prepare_system_reset(void)
diff --git a/plat/nvidia/tegra/soc/t186/plat_sip_calls.c b/plat/nvidia/tegra/soc/t186/plat_sip_calls.c
index 8b340a19075a0709a282c82b187610eb4f093e37..fabab0185ddc665ba1308fa5e2f8ce11f5eb086a 100644
--- a/plat/nvidia/tegra/soc/t186/plat_sip_calls.c
+++ b/plat/nvidia/tegra/soc/t186/plat_sip_calls.c
@@ -41,10 +41,13 @@
 #include <t18x_ari.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
@@ -133,6 +136,33 @@ int plat_sip_handler(uint32_t smc_fid,
 
 		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.
+		 */
+		if ((x1 == TEGRA_ARI_SYSTEM_SC8) ||
+		    (x1 == TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF)) {
+
+			tegra186_system_powerdn_state = x1;
+			flush_dcache_range(
+				(uintptr_t)&tegra186_system_powerdn_state,
+				sizeof(tegra186_system_powerdn_state));
+
+		} else {
+
+			ERROR("%s: unhandled powerdn state (%d)\n", __func__,
+				(uint32_t)x1);
+			return -ENOTSUP;
+		}
+
+		return 0;
+
 	default:
 		break;
 	}