diff --git a/plat/juno/bl31_plat_setup.c b/plat/juno/bl31_plat_setup.c
index eb00287b73b020f31e4e3acbb96259eb8b431e1a..19f2085d82807ab24729bc082499a2e518ecf7f7 100644
--- a/plat/juno/bl31_plat_setup.c
+++ b/plat/juno/bl31_plat_setup.c
@@ -28,6 +28,7 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <mhu.h>
 #include <platform.h>
 #include <assert.h>
 #include <arch_helpers.h>
@@ -115,6 +116,9 @@ void bl31_early_platform_setup(bl31_args *from_bl2,
 void bl31_platform_setup(void)
 {
 	unsigned int counter_base_frequency;
+
+	mhu_secure_init();
+
 	/* Initialize the gic cpu and distributor interfaces */
 	gic_setup();
 
diff --git a/plat/juno/plat_pm.c b/plat/juno/plat_pm.c
index 8c8f0181f1c37b5a975fb62b9f8241a32b626f08..4d4efec8822459bcf8b035ed8f7e02a16eb45756 100644
--- a/plat/juno/plat_pm.c
+++ b/plat/juno/plat_pm.c
@@ -28,14 +28,77 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <stdint.h>
+#include <arch_helpers.h>
+#include <cci400.h>
+#include <platform.h>
 #include <psci.h>
+#include <scpi.h>
+
+int pm_on(unsigned long mpidr,
+		   unsigned long sec_entrypoint,
+		   unsigned long ns_entrypoint,
+		   unsigned int afflvl,
+		   unsigned int state)
+{
+	/*
+	 * SCP takes care of powering up higher affinity levels so we
+	 * only need to care about level 0
+	 */
+	if (afflvl != MPIDR_AFFLVL0)
+		return PSCI_E_SUCCESS;
+
+	/*
+	 * Setup mailbox with address for CPU entrypoint when it next powers up
+	 */
+	unsigned long *mbox = (unsigned long *)(unsigned long)(
+			TRUSTED_MAILBOXES_BASE +
+			(platform_get_core_pos(mpidr) << TRUSTED_MAILBOX_SHIFT)
+			);
+	*mbox = sec_entrypoint;
+	flush_dcache_range((unsigned long)mbox, sizeof(*mbox));
+
+	scpi_set_css_power_state(mpidr, scpi_power_on, scpi_power_on,
+				 scpi_power_on);
+
+	return PSCI_E_SUCCESS;
+}
+
+int pm_on_finish(unsigned long mpidr, unsigned int afflvl, unsigned int state)
+{
+	switch (afflvl) {
+
+	case MPIDR_AFFLVL1:
+		/* Enable coherency if this cluster was off */
+		if (state == PSCI_STATE_OFF)
+			cci_enable_coherency(mpidr);
+		break;
+
+	case MPIDR_AFFLVL0:
+		/*
+		 * Ignore the state passed for a cpu. It could only have
+		 * been off if we are here.
+		 */
+
+		/* Turn on intra-cluster coherency. */
+		write_cpuectlr(read_cpuectlr() | CPUECTLR_SMP_BIT);
+
+		/* Enable the gic cpu interface */
+		gic_cpuif_setup(GICC_BASE);
+		/* Juno todo: Is this setup only needed after a cold boot? */
+		gic_pcpu_distif_setup(GICD_BASE);
+
+		break;
+	}
+
+	return PSCI_E_SUCCESS;
+}
 
 /*******************************************************************************
  * Export the platform handlers to enable psci to invoke them
  ******************************************************************************/
 static plat_pm_ops pm_ops = {
-	0
+	.affinst_on		= pm_on,
+	.affinst_on_finish	= pm_on_finish
 };
 
 /*******************************************************************************
diff --git a/plat/juno/platform.mk b/plat/juno/platform.mk
index 62a6d315f95e01755ad4984b06a3cdf31c3606bc..c1523ecec0d5e85da7238dd2534f007cb7fc0e67 100644
--- a/plat/juno/platform.mk
+++ b/plat/juno/platform.mk
@@ -77,16 +77,22 @@ BL1_SOURCES		+=	bl1_plat_setup.c			\
 				plat_common.c				\
 				cci400.c
 
-BL2_SOURCES		+=	bl2_plat_setup.c			\
+BL2_SOURCES		+=	bakery_lock.c				\
+				bl2_plat_setup.c			\
+				mhu.c					\
 				plat_helpers.S				\
-				plat_common.c
+				plat_common.c				\
+				scp_bootloader.c			\
+				scpi.c
 
 BL31_SOURCES		+=	bl31_plat_setup.c			\
+				mhu.c					\
 				plat_helpers.S				\
 				plat_common.c				\
 				plat_pm.c				\
 				plat_topology.c				\
 				plat_gic.c				\
+				scpi.c					\
 				cci400.c				\
 				gic_v2.c				\
 				gic_v3.c