diff --git a/docs/platform-migration-guide.rst b/docs/platform-migration-guide.rst
index 5e8eeba18c7902d6d65b0df83b5b4b22005b75a6..638033e440f6fc072f772abb2dfdbbf6bbdb2e9b 100644
--- a/docs/platform-migration-guide.rst
+++ b/docs/platform-migration-guide.rst
@@ -146,6 +146,7 @@ for the ``plat_psci_ops`` structure which is declared as :
         void (*cpu_standby)(plat_local_state_t cpu_state);
         int (*pwr_domain_on)(u_register_t mpidr);
         void (*pwr_domain_off)(const psci_power_state_t *target_state);
+        void (*pwr_domain_suspend_early)(const psci_power_state_t *target_state);
         void (*pwr_domain_suspend)(const psci_power_state_t *target_state);
         void (*pwr_domain_on_finish)(const psci_power_state_t *target_state);
         void (*pwr_domain_suspend_finish)(
@@ -170,12 +171,12 @@ convert the power-state parameter (possibly encoding a composite power state)
 passed in a PSCI ``CPU_SUSPEND`` to the ``psci_power_state`` format. This handler
 is now mandatory for PSCI ``CPU_SUSPEND`` support.
 
-The ``plat_psci_ops`` handlers, ``pwr_domain_off`` and ``pwr_domain_suspend``, are
-passed the target local state for each affected power domain. The platform
-must execute operations specific to these target states. Similarly,
-``pwr_domain_on_finish`` and ``pwr_domain_suspend_finish`` are passed the local
-states of the affected power domains before wakeup. The platform
-must execute actions to restore these power domains from these specific
+The ``plat_psci_ops`` handlers, ``pwr_domain_off``, ``pwr_domain_suspend_early``
+and ``pwr_domain_suspend``, are passed the target local state for each affected
+power domain. The platform must execute operations specific to these target
+states. Similarly, ``pwr_domain_on_finish`` and ``pwr_domain_suspend_finish``
+are passed the local states of the affected power domains before wakeup. The
+platform must execute actions to restore these power domains from these specific
 local states.
 
 -  Difference in invocation
diff --git a/docs/porting-guide.rst b/docs/porting-guide.rst
index 4d4cdcd6e77c6f214a48f3cd6a07ab5fd0d8ae8b..bf8dea7b4f627aa29bb1987c09035e7c0f7dc16a 100644
--- a/docs/porting-guide.rst
+++ b/docs/porting-guide.rst
@@ -2060,6 +2060,23 @@ power down state where as it could be either power down, retention or run state
 for the higher power domain levels depending on the result of state
 coordination. The generic code expects the handler to succeed.
 
+plat\_psci\_ops.pwr\_domain\_suspend\_pwrdown\_early() [optional]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This optional function may be used as a performance optimization to replace
+or complement pwr_domain_suspend() on some platforms. Its calling semantics
+are identical to pwr_domain_suspend(), except the PSCI implementation only
+calls this function when suspending to a power down state, and it guarantees
+that data caches are enabled.
+
+When HW_ASSISTED_COHERENCY = 0, the PSCI implementation disables data caches
+before calling pwr_domain_suspend(). If the target_state corresponds to a
+power down state and it is safe to perform some or all of the platform
+specific actions in that function with data caches enabled, it may be more
+efficient to move those actions to this function. When HW_ASSISTED_COHERENCY
+= 1, data caches remain enabled throughout, and so there is no advantage to
+moving platform specific actions to this function.
+
 plat\_psci\_ops.pwr\_domain\_suspend()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
diff --git a/include/lib/psci/psci.h b/include/lib/psci/psci.h
index fee6a24fb3b65a2e58b494992487796eb92ceafd..0ed39c9acd83a85c73fae120b71453965f2f0159 100644
--- a/include/lib/psci/psci.h
+++ b/include/lib/psci/psci.h
@@ -267,6 +267,8 @@ typedef struct plat_psci_ops {
 	void (*cpu_standby)(plat_local_state_t cpu_state);
 	int (*pwr_domain_on)(u_register_t mpidr);
 	void (*pwr_domain_off)(const psci_power_state_t *target_state);
+	void (*pwr_domain_suspend_pwrdown_early)(
+				const psci_power_state_t *target_state);
 	void (*pwr_domain_suspend)(const psci_power_state_t *target_state);
 	void (*pwr_domain_on_finish)(const psci_power_state_t *target_state);
 	void (*pwr_domain_suspend_finish)(
diff --git a/lib/psci/psci_suspend.c b/lib/psci/psci_suspend.c
index 0d1589ee0a0df7c8eb4eff01483229c106075cb1..40ecdeea99654c7ef2b83463c0496645ddfe7b8d 100644
--- a/lib/psci/psci_suspend.c
+++ b/lib/psci/psci_suspend.c
@@ -80,6 +80,17 @@ static void psci_suspend_to_pwrdown_start(unsigned int end_pwrlvl,
 	if (psci_spd_pm && psci_spd_pm->svc_suspend)
 		psci_spd_pm->svc_suspend(max_off_lvl);
 
+#if !HW_ASSISTED_COHERENCY
+	/*
+	 * Plat. management: Allow the platform to perform any early
+	 * actions required to power down the CPU. This might be useful for
+	 * HW_ASSISTED_COHERENCY = 0 platforms that can safely perform these
+	 * actions with data caches enabled.
+	 */
+	if (psci_plat_pm_ops->pwr_domain_suspend_pwrdown_early)
+		psci_plat_pm_ops->pwr_domain_suspend_pwrdown_early(state_info);
+#endif
+
 	/*
 	 * Store the re-entry information for the non-secure world.
 	 */
diff --git a/plat/nvidia/tegra/common/tegra_pm.c b/plat/nvidia/tegra/common/tegra_pm.c
index 0c25934c3101f4bf9eb92c47d39f9a0586c59548..86021ba94ff422371626209b38db400faa78849f 100644
--- a/plat/nvidia/tegra/common/tegra_pm.c
+++ b/plat/nvidia/tegra/common/tegra_pm.c
@@ -36,6 +36,7 @@ uint8_t tegra_fake_system_suspend;
  * The following platform setup functions are weakly defined. They
  * provide typical implementations that will be overridden by a SoC.
  */
+#pragma weak tegra_soc_pwr_domain_suspend_pwrdown_early
 #pragma weak tegra_soc_pwr_domain_suspend
 #pragma weak tegra_soc_pwr_domain_on
 #pragma weak tegra_soc_pwr_domain_off
@@ -45,6 +46,11 @@ uint8_t tegra_fake_system_suspend;
 #pragma weak tegra_soc_prepare_system_off
 #pragma weak tegra_soc_get_target_pwr_state
 
+int tegra_soc_pwr_domain_suspend_pwrdown_early(const psci_power_state_t *target_state)
+{
+	return PSCI_E_NOT_SUPPORTED;
+}
+
 int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state)
 {
 	return PSCI_E_NOT_SUPPORTED;
@@ -142,6 +148,17 @@ void tegra_pwr_domain_off(const psci_power_state_t *target_state)
 	tegra_soc_pwr_domain_off(target_state);
 }
 
+/*******************************************************************************
+ * Handler called when a power domain is about to be suspended. The
+ * target_state encodes the power state that each level should transition to.
+ * This handler is called with SMP and data cache enabled, when
+ * HW_ASSISTED_COHERENCY = 0
+ ******************************************************************************/
+void tegra_pwr_domain_suspend_pwrdown_early(const psci_power_state_t *target_state)
+{
+	tegra_soc_pwr_domain_suspend_pwrdown_early(target_state);
+}
+
 /*******************************************************************************
  * Handler called when a power domain is about to be suspended. The
  * target_state encodes the power state that each level should transition to.
@@ -315,6 +332,7 @@ static const plat_psci_ops_t tegra_plat_psci_ops = {
 	.cpu_standby			= tegra_cpu_standby,
 	.pwr_domain_on			= tegra_pwr_domain_on,
 	.pwr_domain_off			= tegra_pwr_domain_off,
+	.pwr_domain_suspend_pwrdown_early = tegra_pwr_domain_suspend_pwrdown_early,
 	.pwr_domain_suspend		= tegra_pwr_domain_suspend,
 	.pwr_domain_on_finish		= tegra_pwr_domain_on_finish,
 	.pwr_domain_suspend_finish	= tegra_pwr_domain_suspend_finish,