diff --git a/plat/nvidia/tegra/common/drivers/flowctrl/flowctrl.c b/plat/nvidia/tegra/common/drivers/flowctrl/flowctrl.c
index 4f89cf4689a104bd389b30101cb4dea3add3af4a..bdd3ee763133890575121c4970e2b49e28f223a7 100644
--- a/plat/nvidia/tegra/common/drivers/flowctrl/flowctrl.c
+++ b/plat/nvidia/tegra/common/drivers/flowctrl/flowctrl.c
@@ -257,22 +257,19 @@ void tegra_fc_lock_active_cluster(void)
 }
 
 /*******************************************************************************
- * Reset BPMP processor
+ * Power ON BPMP processor
  ******************************************************************************/
-void tegra_fc_reset_bpmp(void)
+void tegra_fc_bpmp_on(uint32_t entrypoint)
 {
-	uint32_t val;
-
 	/* halt BPMP */
 	tegra_fc_write_32(FLOWCTRL_HALT_BPMP_EVENTS, FLOWCTRL_WAITEVENT);
 
 	/* Assert BPMP reset */
 	mmio_write_32(TEGRA_CAR_RESET_BASE + CLK_RST_DEV_L_SET, CLK_BPMP_RST);
 
-	/* Restore reset address (stored in PMC_SCRATCH39) */
-	val = tegra_pmc_read_32(PMC_SCRATCH39);
-	mmio_write_32(TEGRA_EVP_BASE + EVP_BPMP_RESET_VECTOR, val);
-	while (val != mmio_read_32(TEGRA_EVP_BASE + EVP_BPMP_RESET_VECTOR))
+	/* Set reset address (stored in PMC_SCRATCH39) */
+	mmio_write_32(TEGRA_EVP_BASE + EVP_BPMP_RESET_VECTOR, entrypoint);
+	while (entrypoint != mmio_read_32(TEGRA_EVP_BASE + EVP_BPMP_RESET_VECTOR))
 		; /* wait till value reaches EVP_BPMP_RESET_VECTOR */
 
 	/* Wait for 2us before de-asserting the reset signal. */
@@ -285,6 +282,23 @@ void tegra_fc_reset_bpmp(void)
 	tegra_fc_write_32(FLOWCTRL_HALT_BPMP_EVENTS, 0);
 }
 
+/*******************************************************************************
+ * Power OFF BPMP processor
+ ******************************************************************************/
+void tegra_fc_bpmp_off(void)
+{
+	/* halt BPMP */
+	tegra_fc_write_32(FLOWCTRL_HALT_BPMP_EVENTS, FLOWCTRL_WAITEVENT);
+
+	/* Assert BPMP reset */
+	mmio_write_32(TEGRA_CAR_RESET_BASE + CLK_RST_DEV_L_SET, CLK_BPMP_RST);
+
+	/* Clear reset address */
+	mmio_write_32(TEGRA_EVP_BASE + EVP_BPMP_RESET_VECTOR, 0);
+	while (0 != mmio_read_32(TEGRA_EVP_BASE + EVP_BPMP_RESET_VECTOR))
+		; /* wait till value reaches EVP_BPMP_RESET_VECTOR */
+}
+
 /*******************************************************************************
  * Route legacy FIQ to the GICD
  ******************************************************************************/
diff --git a/plat/nvidia/tegra/common/tegra_bl31_setup.c b/plat/nvidia/tegra/common/tegra_bl31_setup.c
index 0d0bc7406e68739aeabf1390a433f55fa9c5e47b..c9beb142672f669caf2f5da3930168024b40af6c 100644
--- a/plat/nvidia/tegra/common/tegra_bl31_setup.c
+++ b/plat/nvidia/tegra/common/tegra_bl31_setup.c
@@ -162,13 +162,15 @@ void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
 	}
 
 	/*
-	 * Parse platform specific parameters - TZDRAM aperture base and size
+	 * Parse platform specific parameters
 	 */
 	assert(plat_params != NULL);
 	plat_bl31_params_from_bl2.tzdram_base = plat_params->tzdram_base;
 	plat_bl31_params_from_bl2.tzdram_size = plat_params->tzdram_size;
 	plat_bl31_params_from_bl2.uart_id = plat_params->uart_id;
 	plat_bl31_params_from_bl2.l2_ecc_parity_prot_dis = plat_params->l2_ecc_parity_prot_dis;
+	plat_bl31_params_from_bl2.sc7entry_fw_size = plat_params->sc7entry_fw_size;
+	plat_bl31_params_from_bl2.sc7entry_fw_base = plat_params->sc7entry_fw_base;
 
 	/*
 	 * It is very important that we run either from TZDRAM or TZSRAM base.
diff --git a/plat/nvidia/tegra/include/drivers/flowctrl.h b/plat/nvidia/tegra/include/drivers/flowctrl.h
index bf7e82fba0343a0eb0b35c781a0272f3961fb74a..54336b044f7cc860fd1aac75e430ac20a9fa0080 100644
--- a/plat/nvidia/tegra/include/drivers/flowctrl.h
+++ b/plat/nvidia/tegra/include/drivers/flowctrl.h
@@ -77,6 +77,8 @@ static inline void tegra_fc_write_32(uint32_t off, uint32_t val)
 	mmio_write_32(TEGRA_FLOWCTRL_BASE + off, val);
 }
 
+void tegra_fc_bpmp_on(uint32_t entrypoint);
+void tegra_fc_bpmp_off(void);
 void tegra_fc_ccplex_pgexit_lock(void);
 void tegra_fc_ccplex_pgexit_unlock(void);
 void tegra_fc_cluster_idle(uint32_t midr);
@@ -88,7 +90,6 @@ void tegra_fc_disable_fiq_to_ccplex_routing(void);
 void tegra_fc_enable_fiq_to_ccplex_routing(void);
 bool tegra_fc_is_ccx_allowed(void);
 void tegra_fc_lock_active_cluster(void);
-void tegra_fc_reset_bpmp(void);
 void tegra_fc_soc_powerdn(uint32_t midr);
 
 #endif /* FLOWCTRL_H */
diff --git a/plat/nvidia/tegra/include/drivers/pmc.h b/plat/nvidia/tegra/include/drivers/pmc.h
index b9090b4a5090ddea63212b78ecdc1a31b201382d..53317de1ef28cde6bc65f715397a2dd82d7a3bec 100644
--- a/plat/nvidia/tegra/include/drivers/pmc.h
+++ b/plat/nvidia/tegra/include/drivers/pmc.h
@@ -26,6 +26,7 @@
 #define  PMC_SECURE_DISABLE3_WRITE35_ON		(U(1) << 22)
 #define PMC_SECURE_SCRATCH34			U(0x368)
 #define PMC_SECURE_SCRATCH35			U(0x36c)
+#define PMC_SCRATCH201				U(0x844)
 
 static inline uint32_t tegra_pmc_read_32(uint32_t off)
 {
diff --git a/plat/nvidia/tegra/include/t210/tegra_def.h b/plat/nvidia/tegra/include/t210/tegra_def.h
index c4ce7670c01fe123ad0527771503dd2b1bdebe57..02c5f135e01d0b3bed711858b1991316f7d2a019 100644
--- a/plat/nvidia/tegra/include/t210/tegra_def.h
+++ b/plat/nvidia/tegra/include/t210/tegra_def.h
@@ -40,7 +40,8 @@
 /*******************************************************************************
  * iRAM memory constants
  ******************************************************************************/
-#define TEGRA_IRAM_BASE			0x40000000
+#define TEGRA_IRAM_BASE			U(0x40000000)
+#define TEGRA_IRAM_SIZE			U(40000) /* 256KB */
 
 /*******************************************************************************
  * GIC memory map
diff --git a/plat/nvidia/tegra/include/tegra_private.h b/plat/nvidia/tegra/include/tegra_private.h
index 40aeaf85f1ac7208aaeca825f09dcb4fb88d0d5e..cdd9e08c179cfd5dc8bc2c7df0c9ce754a7d6213 100644
--- a/plat/nvidia/tegra/include/tegra_private.h
+++ b/plat/nvidia/tegra/include/tegra_private.h
@@ -46,6 +46,10 @@ typedef struct plat_params_from_bl2 {
 	int32_t l2_ecc_parity_prot_dis;
 	/* SHMEM base address for storing the boot logs */
 	uint64_t boot_profiler_shmem_base;
+	/* System Suspend Entry Firmware size */
+	uint64_t sc7entry_fw_size;
+	/* System Suspend Entry Firmware base address */
+	uint64_t sc7entry_fw_base;
 } plat_params_from_bl2_t;
 
 /*******************************************************************************
diff --git a/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c
index bb3b8fec7bebc77cd240f8b49d0a9bfcff6820ad..4c49386bbfae414160cdba7dac2ccc8ee21fea1a 100644
--- a/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c
+++ b/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c
@@ -41,6 +41,7 @@ int32_t tegra_soc_validate_power_state(unsigned int power_state,
 					psci_power_state_t *req_state)
 {
 	int state_id = psci_get_pstate_id(power_state);
+	const plat_params_from_bl2_t *plat_params = bl31_get_plat_params();
 
 	/* Sanity check the requested state id */
 	switch (state_id) {
@@ -62,6 +63,15 @@ int32_t tegra_soc_validate_power_state(unsigned int power_state,
 		break;
 
 	case PSTATE_ID_SOC_POWERDN:
+
+		/*
+		 * sc7entry-fw must be present in the system when the bpmp
+		 * firmware is not present, for a successful System Suspend
+		 * entry.
+		 */
+		if (!tegra_bpmp_init() && !plat_params->sc7entry_fw_base)
+			return PSCI_E_NOT_SUPPORTED;
+
 		/*
 		 * System powerdown request only for afflvl 2
 		 */
@@ -205,12 +215,26 @@ int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state)
 
 		if (!tegra_bpmp_available) {
 
-			/* PWM tristate */
+			/* Find if the platform uses OVR2/MAX77621 PMIC */
 			cfg = mmio_read_32(TEGRA_CL_DVFS_BASE + DVFS_DFLL_OUTPUT_CFG);
 			if (cfg & DFLL_OUTPUT_CFG_CLK_EN_BIT) {
+				/* OVR2 */
+
+				/* PWM tristate */
 				val = mmio_read_32(TEGRA_MISC_BASE + PINMUX_AUX_DVFS_PWM);
 				val |= PINMUX_PWM_TRISTATE;
 				mmio_write_32(TEGRA_MISC_BASE + PINMUX_AUX_DVFS_PWM, val);
+
+				/*
+				 * SCRATCH201[1] is being used to identify CPU
+				 * PMIC in warmboot code.
+				 * 0 : OVR2
+				 * 1 : MAX77621
+				 */
+				tegra_pmc_write_32(PMC_SCRATCH201, 0x0);
+			} else {
+				/* MAX77621 */
+				tegra_pmc_write_32(PMC_SCRATCH201, 0x2);
 			}
 		}
 
@@ -237,6 +261,8 @@ 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;
 	unsigned int stateid_afflvl2 = pwr_domain_state[PLAT_MAX_PWR_LVL];
+	const plat_params_from_bl2_t *plat_params = bl31_get_plat_params();
+	uint32_t val;
 
 	if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) {
 
@@ -245,6 +271,36 @@ int tegra_soc_pwr_domain_power_down_wfi(const psci_power_state_t *target_state)
 			tegra_se_save_tzram();
 		}
 
+		/*
+		 * The CPU needs to load the System suspend entry firmware
+		 * if nothing is running on the BPMP.
+		 */
+		if (!tegra_bpmp_available) {
+
+			/*
+			 * BPMP firmware is not running on the co-processor, so
+			 * we need to explicitly load the firmware to enable
+			 * entry/exit to/from System Suspend and set the BPMP
+			 * on its way.
+			 */
+
+			/* Power off BPMP before we proceed */
+			tegra_fc_bpmp_off();
+
+			/* Copy the firmware to BPMP's internal RAM */
+			(void)memcpy((void *)(uintptr_t)TEGRA_IRAM_BASE,
+				(const void *)plat_params->sc7entry_fw_base,
+				plat_params->sc7entry_fw_size);
+
+			/* Power on the BPMP and execute from IRAM base */
+			tegra_fc_bpmp_on(TEGRA_IRAM_BASE);
+
+			/* Wait until BPMP powers up */
+			do {
+				val = mmio_read_32(TEGRA_RES_SEMA_BASE + STA_OFFSET);
+			} while (val != SIGN_OF_LIFE);
+		}
+
 		/* enter system suspend */
 		tegra_fc_soc_powerdn(mpidr);
 	}
@@ -256,7 +312,7 @@ int tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state)
 {
 	const plat_params_from_bl2_t *plat_params = bl31_get_plat_params();
 	uint32_t cfg;
-	uint32_t val;
+	uint32_t val, entrypoint = 0;
 
 	/* platform parameter passed by the previous bootloader */
 	if (plat_params->l2_ecc_parity_prot_dis != 1) {
@@ -295,10 +351,14 @@ int tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state)
 
 		/*
 		 * Restore Boot and Power Management Processor (BPMP) reset
-		 * address and reset it.
+		 * address and reset it, if it is supported by the platform.
 		 */
-		if (tegra_bpmp_available)
-			tegra_fc_reset_bpmp();
+		if (!tegra_bpmp_available) {
+			tegra_fc_bpmp_off();
+		} else {
+			entrypoint = tegra_pmc_read_32(PMC_SCRATCH39);
+			tegra_fc_bpmp_on(entrypoint);
+		}
 	}
 
 	/*
diff --git a/plat/nvidia/tegra/soc/t210/plat_setup.c b/plat/nvidia/tegra/soc/t210/plat_setup.c
index 25105ba13e3273e6648e2fe4a4d9147b089a4b20..4fdd5a8ad8e9c69508f23a7da38282e04570ac51 100644
--- a/plat/nvidia/tegra/soc/t210/plat_setup.c
+++ b/plat/nvidia/tegra/soc/t210/plat_setup.c
@@ -5,6 +5,7 @@
  */
 
 #include <arch_helpers.h>
+#include <assert.h>
 #include <cortex_a57.h>
 #include <common/bl_common.h>
 #include <common/debug.h>
@@ -150,6 +151,42 @@ static const interrupt_prop_t tegra210_interrupt_props[] = {
 			GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE),
 };
 
+void plat_late_platform_setup(void)
+{
+	const plat_params_from_bl2_t *plat_params = bl31_get_plat_params();
+	uint64_t tzdram_start, tzdram_end, sc7entry_end;
+	int ret;
+
+	/* memmap TZDRAM area containing the SC7 Entry Firmware */
+	if (plat_params->sc7entry_fw_base && plat_params->sc7entry_fw_size) {
+
+		assert(plat_params->sc7entry_fw_size <= TEGRA_IRAM_SIZE);
+
+		/*
+		 * Verify that the SC7 entry firmware resides inside the TZDRAM
+		 * aperture, _after_ the BL31 code.
+		 */
+		tzdram_start = plat_params->tzdram_base;
+		tzdram_end = plat_params->tzdram_base + plat_params->tzdram_size;
+		sc7entry_end = plat_params->sc7entry_fw_base +
+			       plat_params->sc7entry_fw_size;
+		if ((plat_params->sc7entry_fw_base < (tzdram_start + BL31_SIZE)) ||
+		    (sc7entry_end > tzdram_end)) {
+			panic();
+		}
+
+		/* power off BPMP processor until SC7 entry */
+		tegra_fc_bpmp_off();
+
+		/* memmap SC7 entry firmware code */
+		ret = mmap_add_dynamic_region(plat_params->sc7entry_fw_base,
+				plat_params->sc7entry_fw_base,
+				plat_params->sc7entry_fw_size,
+				MT_NS | MT_RO | MT_EXECUTE_NEVER);
+		assert(ret == 0);
+	}
+}
+
 /*******************************************************************************
  * Initialize the GIC and SGIs
  ******************************************************************************/