Merge pull request #196 from soby-mathew/sm/tf_juno_support

Add support for Juno in Trusted Firmware
diff --git a/bl32/tsp/tsp_timer.c b/bl32/tsp/tsp_timer.c
index d9460b6..f196021 100644
--- a/bl32/tsp/tsp_timer.c
+++ b/bl32/tsp/tsp_timer.c
@@ -68,9 +68,14 @@
 	/* Ensure that the timer did assert the interrupt */
 	assert(get_cntp_ctl_istatus(read_cntps_ctl_el1()));
 
-	/* Disable the timer and reprogram it */
+	/*
+	 * Disable the timer and reprogram it. The barriers ensure that there is
+	 * no reordering of instructions around the reprogramming code.
+	 */
+	isb();
 	write_cntps_ctl_el1(0);
 	tsp_generic_timer_start();
+	isb();
 }
 
 /*******************************************************************************
diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h
index b2aac2f..4056260 100644
--- a/include/lib/aarch64/arch.h
+++ b/include/lib/aarch64/arch.h
@@ -166,6 +166,10 @@
 #define EL0VTEN_BIT		(1 << 8)
 #define EL0PCTEN_BIT		(1 << 0)
 #define EL0VCTEN_BIT		(1 << 1)
+#define EVNTEN_BIT		(1 << 2)
+#define EVNTDIR_BIT		(1 << 3)
+#define EVNTI_SHIFT		4
+#define EVNTI_MASK		0xf
 
 /* CPTR_EL3 definitions */
 #define TCPAC_BIT		(1 << 31)
diff --git a/include/lib/cpus/aarch64/cortex_a57.h b/include/lib/cpus/aarch64/cortex_a57.h
index 9cf8780..6128b16 100644
--- a/include/lib/cpus/aarch64/cortex_a57.h
+++ b/include/lib/cpus/aarch64/cortex_a57.h
@@ -52,4 +52,15 @@
 #define CPUACTLR_NO_ALLOC_WBWA         (1 << 49)
 #define CPUACTLR_DCC_AS_DCCI           (1 << 44)
 
+/*******************************************************************************
+ * L2 Control register specific definitions.
+ ******************************************************************************/
+#define L2CTLR_EL1			S3_1_C11_C0_2	/* Instruction def. */
+
+#define L2CTLR_DATA_RAM_LATENCY_SHIFT	0
+#define L2CTLR_TAG_RAM_LATENCY_SHIFT	6
+
+#define L2_DATA_RAM_LATENCY_3_CYCLES	0x2
+#define L2_TAG_RAM_LATENCY_3_CYCLES	0x2
+
 #endif /* __CORTEX_A57_H__ */
diff --git a/plat/juno/aarch64/bl1_plat_helpers.S b/plat/juno/aarch64/bl1_plat_helpers.S
new file mode 100644
index 0000000..3054eab
--- /dev/null
+++ b/plat/juno/aarch64/bl1_plat_helpers.S
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include "../juno_def.h"
+
+	.globl	platform_is_primary_cpu
+	.globl	platform_get_entrypoint
+	.globl	platform_cold_boot_init
+	.globl	plat_secondary_cold_boot_setup
+
+	/* -----------------------------------------------------
+	 * unsigned int platform_is_primary_cpu (unsigned int mpid);
+	 *
+	 * Given the mpidr say whether this cpu is the primary
+	 * cpu (applicable ony after a cold boot)
+	 * -----------------------------------------------------
+	 */
+func platform_is_primary_cpu
+	mov	x9, x30
+	bl	platform_get_core_pos
+	ldr	x1, =SCP_BOOT_CFG_ADDR
+	ldr	x1, [x1]
+	ubfx	x1, x1, #PRIMARY_CPU_SHIFT, #PRIMARY_CPU_MASK
+	cmp	x0, x1
+	cset	x0, eq
+	ret	x9
+
+	/* -----------------------------------------------------
+	 * void plat_secondary_cold_boot_setup (void);
+	 *
+	 * This function performs any platform specific actions
+	 * needed for a secondary cpu after a cold reset e.g
+	 * mark the cpu's presence, mechanism to place it in a
+	 * holding pen etc.
+	 * -----------------------------------------------------
+	 */
+func plat_secondary_cold_boot_setup
+	/* Juno todo: Implement secondary CPU cold boot setup on Juno */
+cb_panic:
+	b	cb_panic
+
+
+	/* -----------------------------------------------------
+	 * void platform_get_entrypoint (unsigned int mpid);
+	 *
+	 * Main job of this routine is to distinguish between
+	 * a cold and warm boot.
+	 * On a cold boot the secondaries first wait for the
+	 * platform to be initialized after which they are
+	 * hotplugged in. The primary proceeds to perform the
+	 * platform initialization.
+	 * On a warm boot, each cpu jumps to the address in its
+	 * mailbox.
+	 *
+	 * TODO: Not a good idea to save lr in a temp reg
+	 * -----------------------------------------------------
+	 */
+func platform_get_entrypoint
+	mov	x9, x30 // lr
+	bl	platform_get_core_pos
+	ldr	x1, =TRUSTED_MAILBOXES_BASE
+	lsl	x0, x0, #TRUSTED_MAILBOX_SHIFT
+	ldr	x0, [x1, x0]
+	ret	x9
+
+
+	/* -----------------------------------------------------
+	 * void platform_cold_boot_init (bl1_main function);
+	 *
+	 * Routine called only by the primary cpu after a cold
+	 * boot to perform early platform initialization
+	 * -----------------------------------------------------
+	 */
+func platform_cold_boot_init
+	mov	x20, x0
+
+	/* ---------------------------------------------
+	 * Give ourselves a small coherent stack to
+	 * ease the pain of initializing the MMU and
+	 * CCI in assembler
+	 * ---------------------------------------------
+	 */
+	mrs	x0, mpidr_el1
+	bl	platform_set_coherent_stack
+
+	/* ---------------------------------------------
+	 * Architectural init. can be generic e.g.
+	 * enabling stack alignment and platform spec-
+	 * ific e.g. MMU & page table setup as per the
+	 * platform memory map. Perform the latter here
+	 * and the former in bl1_main.
+	 * ---------------------------------------------
+	 */
+	bl	bl1_early_platform_setup
+	bl	bl1_plat_arch_setup
+
+	/* ---------------------------------------------
+	 * Give ourselves a stack allocated in Normal
+	 * -IS-WBWA memory
+	 * ---------------------------------------------
+	 */
+	mrs	x0, mpidr_el1
+	bl	platform_set_stack
+
+	/* ---------------------------------------------
+	 * Jump to the main function. Returning from it
+	 * is a terminal error.
+	 * ---------------------------------------------
+	 */
+	blr	x20
+
+cb_init_panic:
+	b	cb_init_panic
diff --git a/plat/juno/aarch64/juno_common.c b/plat/juno/aarch64/juno_common.c
new file mode 100644
index 0000000..5ba38c1
--- /dev/null
+++ b/plat/juno/aarch64/juno_common.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <debug.h>
+#include <mmio.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <xlat_tables.h>
+#include "../juno_def.h"
+
+/*
+ * Table of regions to map using the MMU.
+ * This doesn't include Trusted RAM as the 'mem_layout' argument passed to
+ * configure_mmu_elx() will give the available subset of that,
+ */
+static const mmap_region_t juno_mmap[] = {
+	{ TZROM_BASE,		TZROM_BASE,		TZROM_SIZE,		MT_MEMORY | MT_RO | MT_SECURE },
+	{ MHU_SECURE_BASE,	MHU_SECURE_BASE,	MHU_SECURE_SIZE,	(MHU_PAYLOAD_CACHED ? MT_MEMORY : MT_DEVICE) | MT_RW | MT_SECURE },
+	{ FLASH_BASE,		FLASH_BASE,		FLASH_SIZE,		MT_MEMORY | MT_RO | MT_SECURE },
+	{ EMMC_BASE,		EMMC_BASE,		EMMC_SIZE,		MT_MEMORY | MT_RO | MT_SECURE },
+	{ PSRAM_BASE,		PSRAM_BASE,		PSRAM_SIZE,		MT_MEMORY | MT_RW | MT_SECURE }, /* Used for 'TZDRAM' */
+	{ IOFPGA_BASE,		IOFPGA_BASE,		IOFPGA_SIZE,		MT_DEVICE | MT_RW | MT_SECURE },
+	{ DEVICE0_BASE,		DEVICE0_BASE,		DEVICE0_SIZE,		MT_DEVICE | MT_RW | MT_SECURE },
+	{ DEVICE1_BASE,		DEVICE1_BASE,		DEVICE1_SIZE,		MT_DEVICE | MT_RW | MT_SECURE },
+	{ DRAM_BASE,		DRAM_BASE,		DRAM_SIZE,		MT_MEMORY | MT_RW | MT_NS },
+	{0}
+};
+
+/*******************************************************************************
+ * Macro generating the code for the function setting up the pagetables as per
+ * the platform memory map & initialize the mmu, for the given exception level
+ ******************************************************************************/
+#define DEFINE_CONFIGURE_MMU_EL(_el)				\
+	void configure_mmu_el##_el(unsigned long total_base,	\
+				  unsigned long total_size,	\
+				  unsigned long ro_start,	\
+				  unsigned long ro_limit,	\
+				  unsigned long coh_start,	\
+				  unsigned long coh_limit)	\
+	{							\
+	       mmap_add_region(total_base, total_base,		\
+			       total_size,			\
+			       MT_MEMORY | MT_RW | MT_SECURE);	\
+	       mmap_add_region(ro_start, ro_start,		\
+			       ro_limit - ro_start,		\
+			       MT_MEMORY | MT_RO | MT_SECURE);	\
+	       mmap_add_region(coh_start, coh_start,		\
+			       coh_limit - coh_start,		\
+			       MT_DEVICE | MT_RW | MT_SECURE);	\
+	       mmap_add(juno_mmap);				\
+	       init_xlat_tables();				\
+								\
+	       enable_mmu_el##_el(0);				\
+	}
+
+/* Define EL1 and EL3 variants of the function initialising the MMU */
+DEFINE_CONFIGURE_MMU_EL(1)
+DEFINE_CONFIGURE_MMU_EL(3)
+
+
+unsigned long plat_get_ns_image_entrypoint(void)
+{
+	return NS_IMAGE_OFFSET;
+}
+
+uint64_t plat_get_syscnt_freq(void)
+{
+	uint64_t counter_base_frequency;
+
+	/* Read the frequency from Frequency modes table */
+	counter_base_frequency = mmio_read_32(SYS_CNTCTL_BASE + CNTFID_OFF);
+
+	/* The first entry of the frequency modes table must not be 0 */
+	if (counter_base_frequency == 0)
+		panic();
+
+	return counter_base_frequency;
+}
diff --git a/plat/juno/aarch64/plat_helpers.S b/plat/juno/aarch64/plat_helpers.S
new file mode 100644
index 0000000..1721a0a
--- /dev/null
+++ b/plat/juno/aarch64/plat_helpers.S
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <bl_common.h>
+#include <cortex_a57.h>
+#include <cpu_macros.S>
+#include <platform_def.h>
+#include "../juno_def.h"
+
+	.globl	plat_crash_console_init
+	.globl	plat_crash_console_putc
+	.globl	plat_report_exception
+	.globl	plat_reset_handler
+	.globl	platform_get_core_pos
+	.globl	platform_mem_init
+
+	/* Define a crash console for the plaform */
+#define JUNO_CRASH_CONSOLE_BASE		PL011_UART0_BASE
+
+	/* ---------------------------------------------
+	 * int plat_crash_console_init(void)
+	 * Function to initialize the crash console
+	 * without a C Runtime to print crash report.
+	 * Clobber list : x0, x1, x2
+	 * ---------------------------------------------
+	 */
+func plat_crash_console_init
+	mov_imm	x0, JUNO_CRASH_CONSOLE_BASE
+	mov_imm	x1, PL011_UART0_CLK_IN_HZ
+	mov_imm	x2, PL011_BAUDRATE
+	b	console_core_init
+
+	/* ---------------------------------------------
+	 * int plat_crash_console_putc(int c)
+	 * Function to print a character on the crash
+	 * console without a C Runtime.
+	 * Clobber list : x1, x2
+	 * ---------------------------------------------
+	 */
+func plat_crash_console_putc
+	mov_imm	x1, JUNO_CRASH_CONSOLE_BASE
+	b	console_core_putc
+
+	/* ---------------------------------------------
+	 * void plat_report_exception(unsigned int type)
+	 * Function to report an unhandled exception
+	 * with platform-specific means.
+	 * On Juno platform, it updates the LEDs
+	 * to indicate where we are
+	 * ---------------------------------------------
+	 */
+func plat_report_exception
+	mrs	x1, CurrentEl
+	lsr	x1, x1, #MODE_EL_SHIFT
+	lsl	x1, x1, #SYS_LED_EL_SHIFT
+	lsl	x0, x0, #SYS_LED_EC_SHIFT
+	mov	x2, #(SECURE << SYS_LED_SS_SHIFT)
+	orr	x0, x0, x2
+	orr	x0, x0, x1
+	mov	x1, #VE_SYSREGS_BASE
+	add	x1, x1, #V2M_SYS_LED
+	str	w0, [x1]
+	ret
+
+	/*
+	 * Return 0 to 3 for the A53s and 4 or 5 for the A57s
+	 */
+func platform_get_core_pos
+	and	x1, x0, #MPIDR_CPU_MASK
+	and	x0, x0, #MPIDR_CLUSTER_MASK
+	eor	x0, x0, #(1 << MPIDR_AFFINITY_BITS)  // swap A53/A57 order
+	add	x0, x1, x0, LSR #6
+	ret
+
+
+	/* -----------------------------------------------------
+	 * void platform_mem_init(void);
+	 *
+	 * We don't need to carry out any memory initialization
+	 * on Juno. The Secure RAM is accessible straight away.
+	 * -----------------------------------------------------
+	 */
+func platform_mem_init
+	ret
+
+	/* -----------------------------------------------------
+	 * void plat_reset_handler(void);
+	 *
+	 * Implement workaround for defect id 831273 by enabling
+	 * an event stream every 65536 cycles and set the L2 RAM
+	 * latencies for Cortex-A57.
+	 * -----------------------------------------------------
+	 */
+func plat_reset_handler
+	/* Read the MIDR_EL1 */
+	mrs	x0, midr_el1
+	ubfx	x1, x0, MIDR_PN_SHIFT, #12
+	cmp     w1, #((CORTEX_A57_MIDR >> MIDR_PN_SHIFT) & MIDR_PN_MASK)
+	b.ne    1f
+
+	/* Change the L2 Data and Tag Ram latency to 3 cycles */
+	mov	x0, #(L2_DATA_RAM_LATENCY_3_CYCLES |    \
+			(L2_TAG_RAM_LATENCY_3_CYCLES << \
+			 L2CTLR_TAG_RAM_LATENCY_SHIFT))
+	msr     L2CTLR_EL1, x0
+
+1:
+	/* ---------------------------------------------
+	* Enable the event stream every 65536 cycles
+	* ---------------------------------------------
+	*/
+	mov     x0, #(0xf << EVNTI_SHIFT)
+	orr     x0, x0, #EVNTEN_BIT
+	msr     CNTKCTL_EL1, x0
+	isb
+	ret
diff --git a/plat/juno/bl1_plat_setup.c b/plat/juno/bl1_plat_setup.c
new file mode 100644
index 0000000..d2f2ab4
--- /dev/null
+++ b/plat/juno/bl1_plat_setup.c
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <cci400.h>
+#include <console.h>
+#include <debug.h>
+#include <mmio.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <tzc400.h>
+#include "../../bl1/bl1_private.h"
+#include "juno_def.h"
+#include "juno_private.h"
+
+/*******************************************************************************
+ * Declarations of linker defined symbols which will help us find the layout
+ * of trusted RAM
+ ******************************************************************************/
+extern unsigned long __COHERENT_RAM_START__;
+extern unsigned long __COHERENT_RAM_END__;
+
+/*
+ * The next 2 constants identify the extents of the coherent memory region.
+ * These addresses are used by the MMU setup code and therefore they must be
+ * page-aligned.  It is the responsibility of the linker script to ensure that
+ * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols refer to
+ * page-aligned addresses.
+ */
+#define BL1_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__)
+#define BL1_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__)
+
+/* Data structure which holds the extents of the trusted RAM for BL1 */
+static meminfo_t bl1_tzram_layout;
+
+meminfo_t *bl1_plat_sec_mem_layout(void)
+{
+	return &bl1_tzram_layout;
+}
+
+/*******************************************************************************
+ * Perform any BL1 specific platform actions.
+ ******************************************************************************/
+void bl1_early_platform_setup(void)
+{
+	const size_t bl1_size = BL1_RAM_LIMIT - BL1_RAM_BASE;
+
+	/* Initialize the console to provide early debug support */
+	console_init(PL011_UART0_BASE, PL011_UART0_CLK_IN_HZ, PL011_BAUDRATE);
+
+	/*
+	 * Enable CCI-400 for this cluster. No need for locks as no other cpu is
+	 * active at the moment
+	 */
+	cci_init(CCI400_BASE,
+		 CCI400_SL_IFACE3_CLUSTER_IX,
+		 CCI400_SL_IFACE4_CLUSTER_IX);
+	cci_enable_cluster_coherency(read_mpidr());
+
+	/* Allow BL1 to see the whole Trusted RAM */
+	bl1_tzram_layout.total_base = TZRAM_BASE;
+	bl1_tzram_layout.total_size = TZRAM_SIZE;
+
+	/* Calculate how much RAM BL1 is using and how much remains free */
+	bl1_tzram_layout.free_base = TZRAM_BASE;
+	bl1_tzram_layout.free_size = TZRAM_SIZE;
+	reserve_mem(&bl1_tzram_layout.free_base,
+		    &bl1_tzram_layout.free_size,
+		    BL1_RAM_BASE,
+		    bl1_size);
+
+	INFO("BL1: 0x%lx - 0x%lx [size = %u]\n", BL1_RAM_BASE, BL1_RAM_LIMIT,
+	     bl1_size);
+}
+
+
+/*
+ * Address of slave 'n' security setting in the NIC-400 address region
+ * control
+ * TODO: Ideally this macro should be moved in a "nic-400.h" header file but
+ * it would be the only thing in there so it's not worth it at the moment.
+ */
+#define NIC400_ADDR_CTRL_SECURITY_REG(n)	(0x8 + (n) * 4)
+
+static void init_nic400(void)
+{
+	/*
+	 * NIC-400 Access Control Initialization
+	 *
+	 * Define access privileges by setting each corresponding bit to:
+	 *   0 = Secure access only
+	 *   1 = Non-secure access allowed
+	 */
+
+	/*
+	 * Allow non-secure access to some SOC regions, excluding UART1, which
+	 * remains secure.
+	 * Note: This is the NIC-400 device on the SOC
+	 */
+	mmio_write_32(SOC_NIC400_BASE +
+		      NIC400_ADDR_CTRL_SECURITY_REG(SOC_NIC400_USB_EHCI), ~0);
+	mmio_write_32(SOC_NIC400_BASE +
+		      NIC400_ADDR_CTRL_SECURITY_REG(SOC_NIC400_TLX_MASTER), ~0);
+	mmio_write_32(SOC_NIC400_BASE +
+		      NIC400_ADDR_CTRL_SECURITY_REG(SOC_NIC400_USB_OHCI), ~0);
+	mmio_write_32(SOC_NIC400_BASE +
+		      NIC400_ADDR_CTRL_SECURITY_REG(SOC_NIC400_PL354_SMC), ~0);
+	mmio_write_32(SOC_NIC400_BASE +
+		      NIC400_ADDR_CTRL_SECURITY_REG(SOC_NIC400_APB4_BRIDGE), ~0);
+	mmio_write_32(SOC_NIC400_BASE +
+		      NIC400_ADDR_CTRL_SECURITY_REG(SOC_NIC400_BOOTSEC_BRIDGE),
+		      ~SOC_NIC400_BOOTSEC_BRIDGE_UART1);
+
+	/*
+	 * Allow non-secure access to some CSS regions.
+	 * Note: This is the NIC-400 device on the CSS
+	 */
+	mmio_write_32(CSS_NIC400_BASE +
+		      NIC400_ADDR_CTRL_SECURITY_REG(CSS_NIC400_SLAVE_BOOTSECURE),
+		      ~0);
+}
+
+
+static void init_tzc400(void)
+{
+	/* Enable all filter units available */
+	mmio_write_32(TZC400_BASE + GATE_KEEPER_OFF, 0x0000000f);
+
+	/*
+	 * Secure read and write are enabled for region 0, and the background
+	 * region (region 0) is enabled for all four filter units
+	 */
+	mmio_write_32(TZC400_BASE + REGION_ATTRIBUTES_OFF, 0xc0000000);
+
+	/*
+	 * Enable Non-secure read/write accesses for the Soc Devices from the
+	 * Non-Secure World
+	 */
+	mmio_write_32(TZC400_BASE + REGION_ID_ACCESS_OFF,
+		TZC_REGION_ACCESS_RDWR(TZC400_NSAID_CCI400)	|
+		TZC_REGION_ACCESS_RDWR(TZC400_NSAID_PCIE)	|
+		TZC_REGION_ACCESS_RDWR(TZC400_NSAID_HDLCD0)	|
+		TZC_REGION_ACCESS_RDWR(TZC400_NSAID_HDLCD1)	|
+		TZC_REGION_ACCESS_RDWR(TZC400_NSAID_USB)	|
+		TZC_REGION_ACCESS_RDWR(TZC400_NSAID_DMA330)	|
+		TZC_REGION_ACCESS_RDWR(TZC400_NSAID_THINLINKS)	|
+		TZC_REGION_ACCESS_RDWR(TZC400_NSAID_AP)		|
+		TZC_REGION_ACCESS_RDWR(TZC400_NSAID_GPU)	|
+		TZC_REGION_ACCESS_RDWR(TZC400_NSAID_SCP)	|
+		TZC_REGION_ACCESS_RDWR(TZC400_NSAID_CORESIGHT)
+		);
+}
+
+#define PCIE_SECURE_REG		0x3000
+#define PCIE_SEC_ACCESS_MASK	((1 << 0) | (1 << 1)) /* REG and MEM access bits */
+
+static void init_pcie(void)
+{
+	/*
+	 * PCIE Root Complex Security settings to enable non-secure
+	 * access to config registers.
+	 */
+	mmio_write_32(PCIE_CONTROL_BASE + PCIE_SECURE_REG, PCIE_SEC_ACCESS_MASK);
+}
+
+
+/*******************************************************************************
+ * Function which will perform any remaining platform-specific setup that can
+ * occur after the MMU and data cache have been enabled.
+ ******************************************************************************/
+void bl1_platform_setup(void)
+{
+	init_nic400();
+	init_tzc400();
+	init_pcie();
+
+	/* Initialise the IO layer and register platform IO devices */
+	io_setup();
+
+	/* Enable and initialize the System level generic timer */
+	mmio_write_32(SYS_CNTCTL_BASE + CNTCR_OFF, CNTCR_FCREQ(0) | CNTCR_EN);
+}
+
+
+/*******************************************************************************
+ * Perform the very early platform specific architecture setup here. At the
+ * moment this only does basic initialization. Later architectural setup
+ * (bl1_arch_setup()) does not do anything platform specific.
+ ******************************************************************************/
+void bl1_plat_arch_setup(void)
+{
+	configure_mmu_el3(bl1_tzram_layout.total_base,
+			  bl1_tzram_layout.total_size,
+			  TZROM_BASE,
+			  TZROM_BASE + TZROM_SIZE,
+			  BL1_COHERENT_RAM_BASE,
+			  BL1_COHERENT_RAM_LIMIT);
+}
+
+/*******************************************************************************
+ * Before calling this function BL2 is loaded in memory and its entrypoint
+ * is set by load_image. This is a placeholder for the platform to change
+ * the entrypoint of BL2 and set SPSR and security state.
+ * On Juno we are only setting the security state, entrypoint
+ ******************************************************************************/
+void bl1_plat_set_bl2_ep_info(image_info_t *bl2_image,
+			      entry_point_info_t *bl2_ep)
+{
+	SET_SECURITY_STATE(bl2_ep->h.attr, SECURE);
+	bl2_ep->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+}
diff --git a/plat/juno/bl2_plat_setup.c b/plat/juno/bl2_plat_setup.c
new file mode 100644
index 0000000..5dec2d7
--- /dev/null
+++ b/plat/juno/bl2_plat_setup.c
@@ -0,0 +1,316 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <console.h>
+#include <debug.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <string.h>
+#include "juno_def.h"
+#include "juno_private.h"
+#include "scp_bootloader.h"
+
+/*******************************************************************************
+ * Declarations of linker defined symbols which will help us find the layout
+ * of trusted RAM
+ ******************************************************************************/
+extern unsigned long __RO_START__;
+extern unsigned long __RO_END__;
+
+extern unsigned long __COHERENT_RAM_START__;
+extern unsigned long __COHERENT_RAM_END__;
+
+/*
+ * The next 2 constants identify the extents of the code & RO data region.
+ * These addresses are used by the MMU setup code and therefore they must be
+ * page-aligned.  It is the responsibility of the linker script to ensure that
+ * __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses.
+ */
+#define BL2_RO_BASE (unsigned long)(&__RO_START__)
+#define BL2_RO_LIMIT (unsigned long)(&__RO_END__)
+
+/*
+ * The next 2 constants identify the extents of the coherent memory region.
+ * These addresses are used by the MMU setup code and therefore they must be
+ * page-aligned.  It is the responsibility of the linker script to ensure that
+ * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols refer to
+ * page-aligned addresses.
+ */
+#define BL2_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__)
+#define BL2_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__)
+
+/* Data structure which holds the extents of the trusted RAM for BL2 */
+static meminfo_t bl2_tzram_layout
+__attribute__ ((aligned(PLATFORM_CACHE_LINE_SIZE),
+		section("tzfw_coherent_mem")));
+
+/*******************************************************************************
+ * Structure which holds the arguments which need to be passed to BL3-1
+ ******************************************************************************/
+static bl2_to_bl31_params_mem_t bl31_params_mem;
+
+meminfo_t *bl2_plat_sec_mem_layout(void)
+{
+	return &bl2_tzram_layout;
+}
+
+/*******************************************************************************
+ * This function assigns a pointer to the memory that the platform has kept
+ * aside to pass platform specific and trusted firmware related information
+ * to BL31. This memory is allocated by allocating memory to
+ * bl2_to_bl31_params_mem_t structure which is a superset of all the
+ * structure whose information is passed to BL31
+ * NOTE: This function should be called only once and should be done
+ * before generating params to BL31
+ ******************************************************************************/
+bl31_params_t *bl2_plat_get_bl31_params(void)
+{
+	bl31_params_t *bl2_to_bl31_params;
+
+	/*
+	 * Initialise the memory for all the arguments that needs to
+	 * be passed to BL3-1
+	 */
+	memset(&bl31_params_mem, 0, sizeof(bl2_to_bl31_params_mem_t));
+
+	/* Assign memory for TF related information */
+	bl2_to_bl31_params = &bl31_params_mem.bl31_params;
+	SET_PARAM_HEAD(bl2_to_bl31_params, PARAM_BL31, VERSION_1, 0);
+
+	/* Fill BL3-1 related information */
+	bl2_to_bl31_params->bl31_image_info = &bl31_params_mem.bl31_image_info;
+	SET_PARAM_HEAD(bl2_to_bl31_params->bl31_image_info, PARAM_IMAGE_BINARY,
+		VERSION_1, 0);
+
+	/* Fill BL3-2 related information if it exists */
+#if BL32_BASE
+	bl2_to_bl31_params->bl32_ep_info = &bl31_params_mem.bl32_ep_info;
+	SET_PARAM_HEAD(bl2_to_bl31_params->bl32_ep_info, PARAM_EP,
+		VERSION_1, 0);
+	bl2_to_bl31_params->bl32_image_info = &bl31_params_mem.bl32_image_info;
+	SET_PARAM_HEAD(bl2_to_bl31_params->bl32_image_info, PARAM_IMAGE_BINARY,
+		VERSION_1, 0);
+#endif
+
+	/* Fill BL3-3 related information */
+	bl2_to_bl31_params->bl33_ep_info = &bl31_params_mem.bl33_ep_info;
+	SET_PARAM_HEAD(bl2_to_bl31_params->bl33_ep_info,
+		PARAM_EP, VERSION_1, 0);
+
+	/* BL3-3 expects to receive the primary CPU MPID (through x0) */
+	bl2_to_bl31_params->bl33_ep_info->args.arg0 = 0xffff & read_mpidr();
+
+	bl2_to_bl31_params->bl33_image_info = &bl31_params_mem.bl33_image_info;
+	SET_PARAM_HEAD(bl2_to_bl31_params->bl33_image_info, PARAM_IMAGE_BINARY,
+		VERSION_1, 0);
+
+	return bl2_to_bl31_params;
+}
+
+/*******************************************************************************
+ * This function returns a pointer to the shared memory that the platform
+ * has kept to point to entry point information of BL31 to BL2
+ ******************************************************************************/
+struct entry_point_info *bl2_plat_get_bl31_ep_info(void)
+{
+#if DEBUG
+	bl31_params_mem.bl31_ep_info.args.arg1 = JUNO_BL31_PLAT_PARAM_VAL;
+#endif
+
+	return &bl31_params_mem.bl31_ep_info;
+}
+
+/*******************************************************************************
+ * BL1 has passed the extents of the trusted RAM that should be visible to BL2
+ * in x0. This memory layout is sitting at the base of the free trusted RAM.
+ * Copy it to a safe loaction before its reclaimed by later BL2 functionality.
+ ******************************************************************************/
+void bl2_early_platform_setup(meminfo_t *mem_layout)
+{
+	/* Initialize the console to provide early debug support */
+	console_init(PL011_UART0_BASE, PL011_UART0_CLK_IN_HZ, PL011_BAUDRATE);
+
+	/* Setup the BL2 memory layout */
+	bl2_tzram_layout = *mem_layout;
+}
+
+/*******************************************************************************
+ * Perform platform specific setup, i.e. initialize the IO layer, load BL3-0
+ * image and initialise the memory location to use for passing arguments to
+ * BL3-1.
+ ******************************************************************************/
+void bl2_platform_setup(void)
+{
+	/* Initialise the IO layer and register platform IO devices */
+	io_setup();
+}
+
+/* Flush the TF params and the TF plat params */
+void bl2_plat_flush_bl31_params(void)
+{
+	flush_dcache_range((unsigned long)&bl31_params_mem,
+			sizeof(bl2_to_bl31_params_mem_t));
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only intializes the mmu in a quick and dirty way.
+ ******************************************************************************/
+void bl2_plat_arch_setup(void)
+{
+	configure_mmu_el1(bl2_tzram_layout.total_base,
+			  bl2_tzram_layout.total_size,
+			  BL2_RO_BASE,
+			  BL2_RO_LIMIT,
+			  BL2_COHERENT_RAM_BASE,
+			  BL2_COHERENT_RAM_LIMIT);
+}
+
+/*******************************************************************************
+ * Populate the extents of memory available for loading BL3-0, i.e. anywhere
+ * in trusted RAM as long as it doesn't overwrite BL2.
+ ******************************************************************************/
+void bl2_plat_get_bl30_meminfo(meminfo_t *bl30_meminfo)
+{
+	*bl30_meminfo = bl2_tzram_layout;
+}
+
+/*******************************************************************************
+ * Transfer BL3-0 from Trusted RAM using the SCP Download protocol.
+ * Return 0 on success, -1 otherwise.
+ ******************************************************************************/
+int bl2_plat_handle_bl30(image_info_t *bl30_image_info)
+{
+	int ret;
+
+	ret = scp_bootloader_transfer((void *)bl30_image_info->image_base,
+		bl30_image_info->image_size);
+
+	if (ret == 0)
+		INFO("BL2: BL3-0 transferred to SCP\n\r");
+	else
+		ERROR("BL2: BL3-0 transfer failure\n\r");
+
+	return ret;
+}
+
+/*******************************************************************************
+ * Before calling this function BL31 is loaded in memory and its entrypoint
+ * is set by load_image. This is a placeholder for the platform to change
+ * the entrypoint of BL31 and set SPSR and security state.
+ * On Juno we are only setting the security state, entrypoint
+ ******************************************************************************/
+void bl2_plat_set_bl31_ep_info(image_info_t *bl31_image_info,
+			       entry_point_info_t *bl31_ep_info)
+{
+	SET_SECURITY_STATE(bl31_ep_info->h.attr, SECURE);
+	bl31_ep_info->spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+				       DISABLE_ALL_EXCEPTIONS);
+}
+
+
+/*******************************************************************************
+ * Before calling this function BL32 is loaded in memory and its entrypoint
+ * is set by load_image. This is a placeholder for the platform to change
+ * the entrypoint of BL32 and set SPSR and security state.
+ * On Juno we are only setting the security state, entrypoint
+ ******************************************************************************/
+void bl2_plat_set_bl32_ep_info(image_info_t *bl32_image_info,
+			       entry_point_info_t *bl32_ep_info)
+{
+	SET_SECURITY_STATE(bl32_ep_info->h.attr, SECURE);
+	/*
+	* The Secure Payload Dispatcher service is responsible for
+	* setting the SPSR prior to entry into the BL32 image.
+	*/
+	bl32_ep_info->spsr = 0;
+}
+
+/*******************************************************************************
+ * Before calling this function BL33 is loaded in memory and its entrypoint
+ * is set by load_image. This is a placeholder for the platform to change
+ * the entrypoint of BL33 and set SPSR and security state.
+ * On Juno we are only setting the security state, entrypoint
+ ******************************************************************************/
+void bl2_plat_set_bl33_ep_info(image_info_t *image,
+				       entry_point_info_t *bl33_ep_info)
+{
+	unsigned long el_status;
+	unsigned int mode;
+
+	/* Figure out what mode we enter the non-secure world in */
+	el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT;
+	el_status &= ID_AA64PFR0_ELX_MASK;
+
+	if (el_status)
+		mode = MODE_EL2;
+	else
+		mode = MODE_EL1;
+
+	/*
+	 * TODO: Consider the possibility of specifying the SPSR in
+	 * the FIP ToC and allowing the platform to have a say as
+	 * well.
+	 */
+	bl33_ep_info->spsr = SPSR_64(mode, MODE_SP_ELX,
+				       DISABLE_ALL_EXCEPTIONS);
+	SET_SECURITY_STATE(bl33_ep_info->h.attr, NON_SECURE);
+}
+
+/*******************************************************************************
+ * Populate the extents of memory available for loading BL3-2
+ ******************************************************************************/
+void bl2_plat_get_bl32_meminfo(meminfo_t *bl32_meminfo)
+{
+	/*
+	 * Populate the extents of memory available for loading BL3-2.
+	 */
+	bl32_meminfo->total_base = BL32_BASE;
+	bl32_meminfo->free_base = BL32_BASE;
+	bl32_meminfo->total_size =
+		       (TSP_SEC_MEM_BASE + TSP_SEC_MEM_SIZE) - BL32_BASE;
+	bl32_meminfo->free_size =
+		       (TSP_SEC_MEM_BASE + TSP_SEC_MEM_SIZE) - BL32_BASE;
+}
+
+
+/*******************************************************************************
+ * Populate the extents of memory available for loading BL3-3
+ ******************************************************************************/
+void bl2_plat_get_bl33_meminfo(meminfo_t *bl33_meminfo)
+{
+	bl33_meminfo->total_base = DRAM_BASE;
+	bl33_meminfo->total_size = DRAM_SIZE;
+	bl33_meminfo->free_base = DRAM_BASE;
+	bl33_meminfo->free_size = DRAM_SIZE;
+}
diff --git a/plat/juno/bl31_plat_setup.c b/plat/juno/bl31_plat_setup.c
new file mode 100644
index 0000000..131a1b1
--- /dev/null
+++ b/plat/juno/bl31_plat_setup.c
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <assert.h>
+#include <bl31.h>
+#include <bl_common.h>
+#include <cci400.h>
+#include <console.h>
+#include <mmio.h>
+#include <platform.h>
+#include <stddef.h>
+#include "juno_def.h"
+#include "juno_private.h"
+#include "mhu.h"
+
+/*******************************************************************************
+ * Declarations of linker defined symbols which will help us find the layout
+ * of trusted RAM
+ ******************************************************************************/
+extern unsigned long __RO_START__;
+extern unsigned long __RO_END__;
+
+extern unsigned long __COHERENT_RAM_START__;
+extern unsigned long __COHERENT_RAM_END__;
+
+/*
+ * The next 2 constants identify the extents of the code & RO data region.
+ * These addresses are used by the MMU setup code and therefore they must be
+ * page-aligned.  It is the responsibility of the linker script to ensure that
+ * __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses.
+ */
+#define BL31_RO_BASE (unsigned long)(&__RO_START__)
+#define BL31_RO_LIMIT (unsigned long)(&__RO_END__)
+
+/*
+ * The next 2 constants identify the extents of the coherent memory region.
+ * These addresses are used by the MMU setup code and therefore they must be
+ * page-aligned.  It is the responsibility of the linker script to ensure that
+ * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols
+ * refer to page-aligned addresses.
+ */
+#define BL31_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__)
+#define BL31_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__)
+
+/******************************************************************************
+ * Placeholder variables for copying the arguments that have been passed to
+ * BL3-1 from BL2.
+ ******************************************************************************/
+static entry_point_info_t bl32_ep_info;
+static entry_point_info_t bl33_ep_info;
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image for
+ * the security state specified. BL3-3 corresponds to the non-secure image type
+ * while BL3-2 corresponds to the secure image type. A NULL pointer is returned
+ * if the image does not exist.
+ ******************************************************************************/
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+	entry_point_info_t *next_image_info;
+
+	next_image_info = (type == NON_SECURE) ? &bl33_ep_info : &bl32_ep_info;
+
+	/* None of the images on this platform can have 0x0 as the entrypoint */
+	if (next_image_info->pc)
+		return next_image_info;
+	else
+		return NULL;
+}
+
+/*******************************************************************************
+ * Perform any BL3-1 specific platform actions. Here is an opportunity to copy
+ * parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before they
+ * are lost (potentially). This needs to be done before the MMU is initialized
+ * so that the memory layout can be used while creating page tables. Also, BL2
+ * has flushed this information to memory, so we are guaranteed to pick up good
+ * data
+ ******************************************************************************/
+void bl31_early_platform_setup(bl31_params_t *from_bl2,
+			       void *plat_params_from_bl2)
+{
+	/* Initialize the console to provide early debug support */
+	console_init(PL011_UART0_BASE, PL011_UART0_CLK_IN_HZ, PL011_BAUDRATE);
+
+	/*
+	 * Initialise the CCI-400 driver for BL31 so that it is accessible after
+	 * a warm boot. BL1 should have already enabled CCI coherency for this
+	 * cluster during cold boot.
+	 */
+	cci_init(CCI400_BASE,
+		 CCI400_SL_IFACE3_CLUSTER_IX,
+		 CCI400_SL_IFACE4_CLUSTER_IX);
+
+	/*
+	 * Check params passed from BL2 should not be NULL,
+	 */
+	assert(from_bl2 != NULL);
+	assert(from_bl2->h.type == PARAM_BL31);
+	assert(from_bl2->h.version >= VERSION_1);
+	/*
+	 * In debug builds, we pass a special value in 'plat_params_from_bl2'
+	 * to verify platform parameters from BL2 to BL3-1.
+	 * In release builds, it's not used.
+	 */
+	assert(((unsigned long long)plat_params_from_bl2) ==
+		JUNO_BL31_PLAT_PARAM_VAL);
+
+	/*
+	 * Copy BL3-2 and BL3-3 entry point information.
+	 * They are stored in Secure RAM, in BL2's address space.
+	 */
+	bl32_ep_info = *from_bl2->bl32_ep_info;
+	bl33_ep_info = *from_bl2->bl33_ep_info;
+}
+
+/*******************************************************************************
+ * Initialize the MHU and the GIC.
+ ******************************************************************************/
+void bl31_platform_setup(void)
+{
+	unsigned int reg_val;
+
+	mhu_secure_init();
+
+	/* Initialize the gic cpu and distributor interfaces */
+	gic_setup();
+
+	/* Enable and initialize the System level generic timer */
+	mmio_write_32(SYS_CNTCTL_BASE + CNTCR_OFF, CNTCR_FCREQ(0) | CNTCR_EN);
+
+	/* Allow access to the System counter timer module */
+	reg_val = (1 << CNTACR_RPCT_SHIFT) | (1 << CNTACR_RVCT_SHIFT);
+	reg_val |= (1 << CNTACR_RFRQ_SHIFT) | (1 << CNTACR_RVOFF_SHIFT);
+	reg_val |= (1 << CNTACR_RWVT_SHIFT) | (1 << CNTACR_RWPT_SHIFT);
+	mmio_write_32(SYS_TIMCTL_BASE + CNTACR_BASE(1), reg_val);
+
+	reg_val = (1 << CNTNSAR_NS_SHIFT(1));
+	mmio_write_32(SYS_TIMCTL_BASE + CNTNSAR, reg_val);
+
+	/* Topologies are best known to the platform. */
+	plat_setup_topology();
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only intializes the mmu in a quick and dirty way.
+ ******************************************************************************/
+void bl31_plat_arch_setup()
+{
+	configure_mmu_el3(BL31_RO_BASE,
+			  BL31_COHERENT_RAM_LIMIT - BL31_RO_BASE,
+			  BL31_RO_BASE,
+			  BL31_RO_LIMIT,
+			  BL31_COHERENT_RAM_BASE,
+			  BL31_COHERENT_RAM_LIMIT);
+}
diff --git a/plat/juno/include/plat_macros.S b/plat/juno/include/plat_macros.S
new file mode 100644
index 0000000..0e08834
--- /dev/null
+++ b/plat/juno/include/plat_macros.S
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <cci400.h>
+#include <gic_v2.h>
+#include "platform_def.h"
+#include "../juno_def.h"
+
+.section .rodata.gic_reg_name, "aS"
+gic_regs:
+	.asciz "gic_hppir", "gic_ahppir", "gic_ctlr", ""
+gicd_pend_reg:
+	.asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n Offset:\t\t\tvalue\n"
+newline:
+	.asciz "\n"
+spacer:
+	.asciz ":\t\t0x"
+
+
+	/* ---------------------------------------------
+	 * The below macro prints out relevant GIC
+	 * registers whenever an unhandled exception is
+	 * taken in BL3-1.
+	 * Clobbers: x0 - x10, x16, sp
+	 * ---------------------------------------------
+	 */
+	.macro plat_print_gic_regs
+	ldr	x16, =GICC_BASE
+	/* Load the gic reg list to x6 */
+	adr	x6, gic_regs
+	/* Load the gic regs to gp regs used by str_in_crash_buf_print */
+	ldr	w8, [x16, #GICC_HPPIR]
+	ldr	w9, [x16, #GICC_AHPPIR]
+	ldr	w10, [x16, #GICC_CTLR]
+	/* Store to the crash buf and print to console */
+	bl	str_in_crash_buf_print
+
+	/* Print the GICD_ISPENDR regs */
+	add	x7, x16, #GICD_ISPENDR
+	adr	x4, gicd_pend_reg
+	bl	asm_print_str
+gicd_ispendr_loop:
+	sub	x4, x7, x16
+	cmp	x4, #0x280
+	b.eq	exit_print_gic_regs
+	bl	asm_print_hex
+
+	adr	x4, spacer
+	bl	asm_print_str
+
+	ldr	x4, [x7], #8
+	bl	asm_print_hex
+
+	adr	x4, newline
+	bl	asm_print_str
+	b	gicd_ispendr_loop
+exit_print_gic_regs:
+	.endm
+
+.section .rodata.cci_reg_name, "aS"
+cci_iface_regs:
+	.asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , ""
+
+	/* ------------------------------------------------
+	 * The below macro prints out relevant interconnect
+	 * registers whenever an unhandled exception is
+	 * taken in BL3-1.
+	 * Clobbers: x0 - x9, sp
+	 * ------------------------------------------------
+	 */
+	.macro plat_print_interconnect_regs
+	adr	x6, cci_iface_regs
+	/* Store in x7 the base address of the first interface */
+	mov_imm	x7, (CCI400_BASE + SLAVE_IFACE3_OFFSET)
+	ldr	w8, [x7, #SNOOP_CTRL_REG]
+	/* Store in x7 the base address of the second interface */
+	mov_imm	x7, (CCI400_BASE + SLAVE_IFACE4_OFFSET)
+	ldr	w9, [x7, #SNOOP_CTRL_REG]
+	/* Store to the crash buf and print to console */
+	bl	str_in_crash_buf_print
+	.endm
diff --git a/plat/juno/include/platform_def.h b/plat/juno/include/platform_def.h
new file mode 100644
index 0000000..6d9d0fb
--- /dev/null
+++ b/plat/juno/include/platform_def.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __PLATFORM_DEF_H__
+#define __PLATFORM_DEF_H__
+
+#include <arch.h>
+#include "../juno_def.h"
+
+/*******************************************************************************
+ * Platform binary types for linking
+ ******************************************************************************/
+#define PLATFORM_LINKER_FORMAT          "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH            aarch64
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+
+/* Size of cacheable stacks */
+#define PLATFORM_STACK_SIZE    0x800
+
+#define FIRMWARE_WELCOME_STR		"Booting Trusted Firmware\n"
+
+/* Trusted Boot Firmware BL2 */
+#define BL2_IMAGE_NAME			"bl2.bin"
+
+/* EL3 Runtime Firmware BL3-1 */
+#define BL31_IMAGE_NAME			"bl31.bin"
+
+/* SCP Firmware BL3-0 */
+#define BL30_IMAGE_NAME			"bl30.bin"
+
+/* Secure Payload BL3-2 (Trusted OS) */
+#define BL32_IMAGE_NAME			"bl32.bin"
+
+/* Non-Trusted Firmware BL3-3 */
+#define BL33_IMAGE_NAME			"bl33.bin" /* e.g. UEFI */
+
+/* Firmware Image Package */
+#define FIP_IMAGE_NAME			"fip.bin"
+
+#define PLATFORM_CACHE_LINE_SIZE	64
+#define PLATFORM_CLUSTER_COUNT		2
+#define PLATFORM_CORE_COUNT             6
+#define PLATFORM_NUM_AFFS		(PLATFORM_CLUSTER_COUNT + \
+					 PLATFORM_CORE_COUNT)
+#define MAX_IO_DEVICES			3
+#define MAX_IO_HANDLES			4
+
+/*******************************************************************************
+ * Platform memory map related constants
+ ******************************************************************************/
+#define FLASH_BASE		0x08000000
+#define FLASH_SIZE		0x04000000
+
+/* Bypass offset from start of NOR flash */
+#define BL1_ROM_BYPASS_OFFSET	0x03EC0000
+
+#ifndef TZROM_BASE
+/* Use the bypass address */
+#define TZROM_BASE		FLASH_BASE + BL1_ROM_BYPASS_OFFSET
+#endif
+#define TZROM_SIZE		0x00010000
+
+#define TZRAM_BASE		0x04001000
+#define TZRAM_SIZE		0x0003F000
+
+/*******************************************************************************
+ * BL1 specific defines.
+ * BL1 RW data is relocated from ROM to RAM at runtime so we need 2 base
+ * addresses.
+ ******************************************************************************/
+#define BL1_RO_BASE			TZROM_BASE
+#define BL1_RO_LIMIT			(TZROM_BASE + TZROM_SIZE)
+#define BL1_RW_BASE			TZRAM_BASE
+#define BL1_RW_LIMIT			BL31_BASE
+
+/*******************************************************************************
+ * BL2 specific defines.
+ ******************************************************************************/
+#define BL2_BASE			(TZRAM_BASE + TZRAM_SIZE - 0xd000)
+#define BL2_LIMIT			(TZRAM_BASE + TZRAM_SIZE)
+
+/*******************************************************************************
+ * Load address of BL3-0 in the Juno port
+ * BL3-0 is loaded to the same place as BL3-1.  Once BL3-0 is transferred to the
+ * SCP, it is discarded and BL3-1 is loaded over the top.
+ ******************************************************************************/
+#define BL30_BASE			BL31_BASE
+
+/*******************************************************************************
+ * BL3-1 specific defines.
+ ******************************************************************************/
+#define BL31_BASE			(TZRAM_BASE + 0x8000)
+#define BL31_LIMIT			BL32_BASE
+
+/*******************************************************************************
+ * BL3-2 specific defines.
+ ******************************************************************************/
+#define TSP_SEC_MEM_BASE		TZRAM_BASE
+#define TSP_SEC_MEM_SIZE		TZRAM_SIZE
+#define BL32_BASE			(TZRAM_BASE + TZRAM_SIZE - 0x1d000)
+#define BL32_LIMIT			BL2_BASE
+
+/*******************************************************************************
+ * Load address of BL3-3 in the Juno port
+ ******************************************************************************/
+#define NS_IMAGE_OFFSET			0xE0000000
+
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+#define ADDR_SPACE_SIZE			(1ull << 32)
+#define MAX_XLAT_TABLES			2
+#define MAX_MMAP_REGIONS		16
+
+/*******************************************************************************
+ * ID of the secure physical generic timer interrupt used by the TSP
+ ******************************************************************************/
+#define TSP_IRQ_SEC_PHY_TIMER		IRQ_SEC_PHY_TIMER
+
+/*******************************************************************************
+ * Declarations and constants to access the mailboxes safely. Each mailbox is
+ * aligned on the biggest cache line size in the platform. This is known only
+ * to the platform as it might have a combination of integrated and external
+ * caches. Such alignment ensures that two maiboxes do not sit on the same cache
+ * line at any cache level. They could belong to different cpus/clusters &
+ * get written while being protected by different locks causing corruption of
+ * a valid mailbox address.
+ ******************************************************************************/
+#define CACHE_WRITEBACK_SHIFT   6
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
+
+#endif /* __PLATFORM_DEF_H__ */
diff --git a/plat/juno/juno_def.h b/plat/juno/juno_def.h
new file mode 100644
index 0000000..1eae65d
--- /dev/null
+++ b/plat/juno/juno_def.h
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __JUNO_DEF_H__
+#define __JUNO_DEF_H__
+
+/* Special value used to verify platform parameters from BL2 to BL3-1 */
+#define JUNO_BL31_PLAT_PARAM_VAL	0x0f1e2d3c4b5a6978ULL
+
+/*******************************************************************************
+ * Juno memory map related constants
+ ******************************************************************************/
+#define MHU_SECURE_BASE		0x04000000
+#define MHU_SECURE_SIZE		0x00001000
+
+#define MHU_PAYLOAD_CACHED	0
+
+#define TRUSTED_MAILBOXES_BASE	MHU_SECURE_BASE
+#define TRUSTED_MAILBOX_SHIFT	4
+
+#define EMMC_BASE		0x0c000000
+#define EMMC_SIZE		0x04000000
+
+#define PSRAM_BASE		0x14000000
+#define PSRAM_SIZE		0x02000000
+
+#define IOFPGA_BASE		0x1c000000
+#define IOFPGA_SIZE		0x03000000
+
+#define NSROM_BASE		0x1f000000
+#define NSROM_SIZE		0x00001000
+
+/* Following covers Columbus Peripherals excluding NSROM and NSRAM  */
+#define DEVICE0_BASE		0x20000000
+#define DEVICE0_SIZE		0x0e000000
+#define MHU_BASE		0x2b1f0000
+
+#define NSRAM_BASE		0x2e000000
+#define NSRAM_SIZE		0x00008000
+
+/* Following covers Juno Peripherals and PCIe expansion area */
+#define DEVICE1_BASE		0x40000000
+#define DEVICE1_SIZE		0x40000000
+#define PCIE_CONTROL_BASE	0x7ff20000
+
+#define DRAM_BASE		0x80000000
+#define DRAM_SIZE		0x80000000
+
+/* Memory mapped Generic timer interfaces  */
+#define SYS_CNTCTL_BASE		0x2a430000
+#define SYS_CNTREAD_BASE	0x2a800000
+#define SYS_TIMCTL_BASE		0x2a810000
+
+/* V2M motherboard system registers & offsets */
+#define VE_SYSREGS_BASE		0x1c010000
+#define V2M_SYS_LED		0x8
+
+/*
+ * V2M sysled bit definitions. The values written to this
+ * register are defined in arch.h & runtime_svc.h. Only
+ * used by the primary cpu to diagnose any cold boot issues.
+ *
+ * SYS_LED[0]   - Security state (S=0/NS=1)
+ * SYS_LED[2:1] - Exception Level (EL3-EL0)
+ * SYS_LED[7:3] - Exception Class (Sync/Async & origin)
+ *
+ */
+#define SYS_LED_SS_SHIFT		0x0
+#define SYS_LED_EL_SHIFT		0x1
+#define SYS_LED_EC_SHIFT		0x3
+
+/*******************************************************************************
+ * GIC-400 & interrupt handling related constants
+ ******************************************************************************/
+#define GICD_BASE			0x2c010000
+#define GICC_BASE			0x2c02f000
+#define GICH_BASE			0x2c04f000
+#define GICV_BASE			0x2c06f000
+
+#define IRQ_MHU			69
+#define IRQ_GPU_SMMU_0		71
+#define IRQ_GPU_SMMU_1		73
+#define IRQ_ETR_SMMU		75
+#define IRQ_TZC400		80
+#define IRQ_TZ_WDOG		86
+
+#define IRQ_SEC_PHY_TIMER		29
+#define IRQ_SEC_SGI_0			8
+#define IRQ_SEC_SGI_1			9
+#define IRQ_SEC_SGI_2			10
+#define IRQ_SEC_SGI_3			11
+#define IRQ_SEC_SGI_4			12
+#define IRQ_SEC_SGI_5			13
+#define IRQ_SEC_SGI_6			14
+#define IRQ_SEC_SGI_7			15
+#define IRQ_SEC_SGI_8			16
+
+/*******************************************************************************
+ * PL011 related constants
+ ******************************************************************************/
+/* FPGA UART0 */
+#define PL011_UART0_BASE		0x1c090000
+/* FPGA UART1 */
+#define PL011_UART1_BASE		0x1c0a0000
+/* SoC UART0 */
+#define PL011_UART2_BASE		0x7ff80000
+/* SoC UART1 */
+#define PL011_UART3_BASE		0x7ff70000
+
+#define PL011_BAUDRATE			115200
+
+#define PL011_UART0_CLK_IN_HZ		24000000
+#define PL011_UART1_CLK_IN_HZ		24000000
+
+/*******************************************************************************
+ * NIC-400 related constants
+ ******************************************************************************/
+
+/* CSS NIC-400 Global Programmers View (GPV) */
+#define CSS_NIC400_BASE		0x2a000000
+
+/* The slave_bootsecure controls access to GPU, DMC and CS. */
+#define CSS_NIC400_SLAVE_BOOTSECURE		8
+
+/* SoC NIC-400 Global Programmers View (GPV) */
+#define SOC_NIC400_BASE		0x7fd00000
+
+#define SOC_NIC400_USB_EHCI	0
+#define SOC_NIC400_TLX_MASTER	1
+#define SOC_NIC400_USB_OHCI	2
+#define SOC_NIC400_PL354_SMC	3
+/*
+ * The apb4_bridge controls access to:
+ *   - the PCIe configuration registers
+ *   - the MMU units for USB, HDLCD and DMA
+ */
+#define SOC_NIC400_APB4_BRIDGE	4
+/*
+ * The bootsec_bridge controls access to a bunch of peripherals, e.g. the UARTs.
+ */
+#define SOC_NIC400_BOOTSEC_BRIDGE		5
+#define SOC_NIC400_BOOTSEC_BRIDGE_UART1         (1 << 12)
+
+/*******************************************************************************
+ * TZC-400 related constants
+ ******************************************************************************/
+#define TZC400_BASE		0x2a4a0000
+
+#define TZC400_NSAID_CCI400	0  /* Note: Same as default NSAID!! */
+#define TZC400_NSAID_PCIE	1
+#define TZC400_NSAID_HDLCD0	2
+#define TZC400_NSAID_HDLCD1	3
+#define TZC400_NSAID_USB	4
+#define TZC400_NSAID_DMA330	5
+#define TZC400_NSAID_THINLINKS	6
+#define TZC400_NSAID_AP		9
+#define TZC400_NSAID_GPU	10
+#define TZC400_NSAID_SCP	11
+#define TZC400_NSAID_CORESIGHT	12
+
+/*******************************************************************************
+ * CCI-400 related constants
+ ******************************************************************************/
+#define CCI400_BASE			0x2c090000
+#define CCI400_SL_IFACE3_CLUSTER_IX	1
+#define CCI400_SL_IFACE4_CLUSTER_IX	0
+
+/*******************************************************************************
+ * SCP <=> AP boot configuration
+ ******************************************************************************/
+#define SCP_BOOT_CFG_ADDR	0x04000080
+#define PRIMARY_CPU_SHIFT	8
+#define PRIMARY_CPU_MASK	0xf
+
+#endif /* __JUNO_DEF_H__ */
diff --git a/plat/juno/juno_private.h b/plat/juno/juno_private.h
new file mode 100644
index 0000000..0dac03a
--- /dev/null
+++ b/plat/juno/juno_private.h
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __JUNO_PRIVATE_H__
+#define __JUNO_PRIVATE_H__
+
+#include <bl_common.h>
+#include <platform_def.h>
+#include <stdint.h>
+
+/*******************************************************************************
+ * Forward declarations
+ ******************************************************************************/
+struct plat_pm_ops;
+struct meminfo;
+struct bl31_params;
+struct image_info;
+struct entry_point_info;
+
+/*******************************************************************************
+ * This structure represents the superset of information that is passed to
+ * BL3-1 e.g. while passing control to it from BL2 which is bl31_params
+ * and other platform specific params
+ ******************************************************************************/
+typedef struct bl2_to_bl31_params_mem {
+	struct bl31_params bl31_params;
+	struct image_info bl31_image_info;
+	struct image_info bl32_image_info;
+	struct image_info bl33_image_info;
+	struct entry_point_info bl33_ep_info;
+	struct entry_point_info bl32_ep_info;
+	struct entry_point_info bl31_ep_info;
+} bl2_to_bl31_params_mem_t;
+
+/*******************************************************************************
+ * Function and variable prototypes
+ ******************************************************************************/
+void bl1_plat_arch_setup(void);
+void bl2_plat_arch_setup(void);
+void bl31_plat_arch_setup(void);
+int platform_setup_pm(const struct plat_pm_ops **plat_ops);
+unsigned int platform_get_core_pos(unsigned long mpidr);
+void configure_mmu_el1(unsigned long total_base,
+		       unsigned long total_size,
+		       unsigned long ro_start,
+		       unsigned long ro_limit,
+		       unsigned long coh_start,
+		       unsigned long coh_limit);
+void configure_mmu_el3(unsigned long total_base,
+		       unsigned long total_size,
+		       unsigned long ro_start,
+		       unsigned long ro_limit,
+		       unsigned long coh_start,
+		       unsigned long coh_limit);
+void plat_report_exception(unsigned long type);
+unsigned long plat_get_ns_image_entrypoint(void);
+unsigned long platform_get_stack(unsigned long mpidr);
+uint64_t plat_get_syscnt_freq(void);
+
+/* Declarations for plat_gic.c */
+uint32_t ic_get_pending_interrupt_id(void);
+uint32_t ic_get_pending_interrupt_type(void);
+uint32_t ic_acknowledge_interrupt(void);
+uint32_t ic_get_interrupt_type(uint32_t id);
+void ic_end_of_interrupt(uint32_t id);
+void gic_cpuif_deactivate(unsigned int gicc_base);
+void gic_cpuif_setup(unsigned int gicc_base);
+void gic_pcpu_distif_setup(unsigned int gicd_base);
+void gic_setup(void);
+uint32_t plat_interrupt_type_to_line(uint32_t type, uint32_t security_state);
+
+/* Declarations for plat_topology.c */
+int plat_setup_topology(void);
+int plat_get_max_afflvl(void);
+unsigned int plat_get_aff_count(unsigned int aff_lvl, unsigned long mpidr);
+unsigned int plat_get_aff_state(unsigned int aff_lvl, unsigned long mpidr);
+
+/* Declarations for plat_io_storage.c */
+void io_setup(void);
+int plat_get_image_source(const char *image_name,
+			  uintptr_t *dev_handle,
+			  uintptr_t *image_spec);
+
+/*
+ * Before calling this function BL2 is loaded in memory and its entrypoint
+ * is set by load_image. This is a placeholder for the platform to change
+ * the entrypoint of BL2 and set SPSR and security state.
+ * On Juno we are only setting the security state, entrypoint
+ */
+void bl1_plat_set_bl2_ep_info(struct image_info *image,
+			      struct entry_point_info *ep);
+
+/*
+ * Before calling this function BL3-1 is loaded in memory and its entrypoint
+ * is set by load_image. This is a placeholder for the platform to change
+ * the entrypoint of BL3-1 and set SPSR and security state.
+ * On Juno we are only setting the security state, entrypoint
+ */
+void bl2_plat_set_bl31_ep_info(struct image_info *image,
+			       struct entry_point_info *ep);
+
+/*
+ * Before calling this function BL3-2 is loaded in memory and its entrypoint
+ * is set by load_image. This is a placeholder for the platform to change
+ * the entrypoint of BL3-2 and set SPSR and security state.
+ * On Juno we are only setting the security state, entrypoint
+ */
+void bl2_plat_set_bl32_ep_info(struct image_info *image,
+			       struct entry_point_info *ep);
+
+/*
+ * Before calling this function BL3-3 is loaded in memory and its entrypoint
+ * is set by load_image. This is a placeholder for the platform to change
+ * the entrypoint of BL3-3 and set SPSR and security state.
+ * On Juno we are only setting the security state, entrypoint
+ */
+void bl2_plat_set_bl33_ep_info(struct image_info *image,
+			       struct entry_point_info *ep);
+
+/* Gets the memory layout for BL3-2 */
+void bl2_plat_get_bl32_meminfo(struct meminfo *mem_info);
+
+/* Gets the memory layout for BL3-3 */
+void bl2_plat_get_bl33_meminfo(struct meminfo *mem_info);
+
+#endif /* __JUNO_PRIVATE_H__ */
diff --git a/plat/juno/mhu.c b/plat/juno/mhu.c
new file mode 100644
index 0000000..b6541a8
--- /dev/null
+++ b/plat/juno/mhu.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <bakery_lock.h>
+#include <mmio.h>
+#include "juno_def.h"
+#include "mhu.h"
+
+/* SCP MHU secure channel registers */
+#define SCP_INTR_S_STAT		0x200
+#define SCP_INTR_S_SET		0x208
+#define SCP_INTR_S_CLEAR	0x210
+
+/* CPU MHU secure channel registers */
+#define CPU_INTR_S_STAT		0x300
+#define CPU_INTR_S_SET		0x308
+#define CPU_INTR_S_CLEAR	0x310
+
+
+static bakery_lock_t mhu_secure_lock __attribute__ ((section("tzfw_coherent_mem")));
+
+
+void mhu_secure_message_start(void)
+{
+	bakery_lock_get(&mhu_secure_lock);
+
+	/* Make sure any previous command has finished */
+	while (mmio_read_32(MHU_BASE + CPU_INTR_S_STAT) != 0)
+		;
+}
+
+void mhu_secure_message_send(uint32_t command)
+{
+	/* Send command to SCP and wait for it to pick it up */
+	mmio_write_32(MHU_BASE + CPU_INTR_S_SET, command);
+	while (mmio_read_32(MHU_BASE + CPU_INTR_S_STAT) != 0)
+		;
+}
+
+uint32_t mhu_secure_message_wait(void)
+{
+	/* Wait for response from SCP */
+	uint32_t response;
+	while (!(response = mmio_read_32(MHU_BASE + SCP_INTR_S_STAT)))
+		;
+
+	return response;
+}
+
+void mhu_secure_message_end(void)
+{
+	/* Clear any response we got by writing all ones to the CLEAR register */
+	mmio_write_32(MHU_BASE + SCP_INTR_S_CLEAR, 0xffffffffu);
+
+	bakery_lock_release(&mhu_secure_lock);
+}
+
+void mhu_secure_init(void)
+{
+	bakery_lock_init(&mhu_secure_lock);
+
+	/*
+	 * Clear the CPU's INTR register to make sure we don't see a stale
+	 * or garbage value and think it's a message we've already sent.
+	 */
+	mmio_write_32(MHU_BASE + CPU_INTR_S_CLEAR, 0xffffffffu);
+}
diff --git a/plat/juno/mhu.h b/plat/juno/mhu.h
new file mode 100644
index 0000000..5149c82
--- /dev/null
+++ b/plat/juno/mhu.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MHU_H__
+#define __MHU_H__
+
+#include <stdint.h>
+
+extern void mhu_secure_message_start(void);
+extern void mhu_secure_message_send(uint32_t command);
+extern uint32_t mhu_secure_message_wait(void);
+extern void mhu_secure_message_end(void);
+
+extern void mhu_secure_init(void);
+
+#endif	/* __MHU_H__ */
diff --git a/plat/juno/plat-tsp.ld.S b/plat/juno/plat-tsp.ld.S
new file mode 100644
index 0000000..16d6c17
--- /dev/null
+++ b/plat/juno/plat-tsp.ld.S
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+    ASSERT(__BL32_END__ <= BL2_BASE, "BL3-2 image overlaps BL2 image.")
diff --git a/plat/juno/plat_gic.c b/plat/juno/plat_gic.c
new file mode 100644
index 0000000..9001519
--- /dev/null
+++ b/plat/juno/plat_gic.c
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <gic_v2.h>
+#include <interrupt_mgmt.h>
+#include <platform.h>
+#include "juno_def.h"
+#include "juno_private.h"
+
+
+/* Value used to initialise Non-Secure irq priorities four at a time */
+#define DEFAULT_NS_PRIORITY_X4 \
+	(GIC_HIGHEST_NS_PRIORITY | \
+	(GIC_HIGHEST_NS_PRIORITY << 8) | \
+	(GIC_HIGHEST_NS_PRIORITY << 16) | \
+	(GIC_HIGHEST_NS_PRIORITY << 24))
+
+
+/*******************************************************************************
+ * Enable secure interrupts and use FIQs to route them. Disable legacy bypass
+ * and set the priority mask register to allow all interrupts to trickle in.
+ ******************************************************************************/
+void gic_cpuif_setup(unsigned int gicc_base)
+{
+	unsigned int val;
+
+	gicc_write_pmr(gicc_base, GIC_PRI_MASK);
+
+	val = ENABLE_GRP0 | FIQ_EN;
+	val |= FIQ_BYP_DIS_GRP0 | IRQ_BYP_DIS_GRP0;
+	val |= FIQ_BYP_DIS_GRP1 | IRQ_BYP_DIS_GRP1;
+	gicc_write_ctlr(gicc_base, val);
+}
+
+/*******************************************************************************
+ * Place the cpu interface in a state where it can never make a cpu exit wfi as
+ * as result of an asserted interrupt. This is critical for powering down a cpu
+ ******************************************************************************/
+void gic_cpuif_deactivate(unsigned int gicc_base)
+{
+	unsigned int val;
+
+	/* Disable secure, non-secure interrupts and disable their bypass */
+	val = gicc_read_ctlr(gicc_base);
+	val &= ~(ENABLE_GRP0 | ENABLE_GRP1);
+	val |= FIQ_BYP_DIS_GRP1 | FIQ_BYP_DIS_GRP0;
+	val |= IRQ_BYP_DIS_GRP0 | IRQ_BYP_DIS_GRP1;
+	gicc_write_ctlr(gicc_base, val);
+}
+
+static void gic_set_secure(unsigned int gicd_base, unsigned id)
+{
+	/* Set interrupt as Group 0 */
+	gicd_clr_igroupr(gicd_base, id);
+
+	/* Set priority to max */
+	gicd_set_ipriorityr(gicd_base, id, GIC_HIGHEST_SEC_PRIORITY);
+}
+
+/*******************************************************************************
+ * Per cpu gic distributor setup which will be done by all cpus after a cold
+ * boot/hotplug. This marks out the secure interrupts & enables them.
+ ******************************************************************************/
+void gic_pcpu_distif_setup(unsigned int gicd_base)
+{
+	unsigned i;
+
+	/* Mark all 32 PPI interrupts as Group 1 (non-secure) */
+	mmio_write_32(gicd_base + GICD_IGROUPR, 0xffffffffu);
+
+	/* Setup PPI priorities doing four at a time */
+	for (i = 0; i < 32; i += 4)
+		mmio_write_32(gicd_base + GICD_IPRIORITYR + i, DEFAULT_NS_PRIORITY_X4);
+
+	/* Configure those PPIs we want as secure, and enable them. */
+	static const char sec_irq[] = {
+		IRQ_SEC_PHY_TIMER,
+		IRQ_SEC_SGI_0,
+		IRQ_SEC_SGI_1,
+		IRQ_SEC_SGI_2,
+		IRQ_SEC_SGI_3,
+		IRQ_SEC_SGI_4,
+		IRQ_SEC_SGI_5,
+		IRQ_SEC_SGI_6,
+		IRQ_SEC_SGI_7
+	};
+	for (i = 0; i < sizeof(sec_irq) / sizeof(sec_irq[0]); i++) {
+		gic_set_secure(gicd_base, sec_irq[i]);
+		gicd_set_isenabler(gicd_base, sec_irq[i]);
+	}
+}
+
+/*******************************************************************************
+ * Global gic distributor setup which will be done by the primary cpu after a
+ * cold boot. It marks out the secure SPIs, PPIs & SGIs and enables them. It
+ * then enables the secure GIC distributor interface.
+ ******************************************************************************/
+static void gic_distif_setup(unsigned int gicd_base)
+{
+	unsigned int i, ctlr;
+	const unsigned int ITLinesNumber =
+				gicd_read_typer(gicd_base) & IT_LINES_NO_MASK;
+
+	/* Disable the distributor before going further */
+	ctlr = gicd_read_ctlr(gicd_base);
+	ctlr &= ~(ENABLE_GRP0 | ENABLE_GRP1);
+	gicd_write_ctlr(gicd_base, ctlr);
+
+	/* Mark all lines of SPIs as Group 1 (non-secure) */
+	for (i = 0; i < ITLinesNumber; i++)
+		mmio_write_32(gicd_base + GICD_IGROUPR + 4 + i * 4, 0xffffffffu);
+
+	/* Setup SPI priorities doing four at a time */
+	for (i = 0; i < ITLinesNumber * 32; i += 4)
+		mmio_write_32(gicd_base + GICD_IPRIORITYR + 32 + i, DEFAULT_NS_PRIORITY_X4);
+
+	/* Configure the SPIs we want as secure */
+	static const char sec_irq[] = {
+		IRQ_MHU,
+		IRQ_GPU_SMMU_0,
+		IRQ_GPU_SMMU_1,
+		IRQ_ETR_SMMU,
+		IRQ_TZC400,
+		IRQ_TZ_WDOG
+	};
+	for (i = 0; i < sizeof(sec_irq) / sizeof(sec_irq[0]); i++)
+		gic_set_secure(gicd_base, sec_irq[i]);
+
+	/* Route watchdog interrupt to this CPU and enable it. */
+	gicd_set_itargetsr(gicd_base, IRQ_TZ_WDOG,
+			   platform_get_core_pos(read_mpidr()));
+	gicd_set_isenabler(gicd_base, IRQ_TZ_WDOG);
+
+	/* Now setup the PPIs */
+	gic_pcpu_distif_setup(gicd_base);
+
+	/* Enable Group 0 (secure) interrupts */
+	gicd_write_ctlr(gicd_base, ctlr | ENABLE_GRP0);
+}
+
+void gic_setup(void)
+{
+	gic_cpuif_setup(GICC_BASE);
+	gic_distif_setup(GICD_BASE);
+}
+
+/*******************************************************************************
+ * An ARM processor signals interrupt exceptions through the IRQ and FIQ pins.
+ * The interrupt controller knows which pin/line it uses to signal a type of
+ * interrupt. The platform knows which interrupt controller type is being used
+ * in a particular security state e.g. with an ARM GIC, normal world could use
+ * the GICv2 features while the secure world could use GICv3 features and vice
+ * versa.
+ * This function is exported by the platform to let the interrupt management
+ * framework determine for a type of interrupt and security state, which line
+ * should be used in the SCR_EL3 to control its routing to EL3. The interrupt
+ * line is represented as the bit position of the IRQ or FIQ bit in the SCR_EL3.
+ ******************************************************************************/
+uint32_t plat_interrupt_type_to_line(uint32_t type, uint32_t security_state)
+{
+	assert(type == INTR_TYPE_S_EL1 ||
+	       type == INTR_TYPE_EL3 ||
+	       type == INTR_TYPE_NS);
+
+	assert(sec_state_is_valid(security_state));
+
+	/*
+	 * We ignore the security state parameter because Juno is GICv2 only
+	 * so both normal and secure worlds are using ARM GICv2.
+	 */
+	return gicv2_interrupt_type_to_line(GICC_BASE, type);
+}
+
+/*******************************************************************************
+ * This function returns the type of the highest priority pending interrupt at
+ * the GIC cpu interface. INTR_TYPE_INVAL is returned when there is no
+ * interrupt pending.
+ ******************************************************************************/
+uint32_t plat_ic_get_pending_interrupt_type(void)
+{
+	uint32_t id;
+
+	id = gicc_read_hppir(GICC_BASE);
+
+	/* Assume that all secure interrupts are S-EL1 interrupts */
+	if (id < 1022)
+		return INTR_TYPE_S_EL1;
+
+	if (id == GIC_SPURIOUS_INTERRUPT)
+		return INTR_TYPE_INVAL;
+
+	return INTR_TYPE_NS;
+}
+
+/*******************************************************************************
+ * This function returns the id of the highest priority pending interrupt at
+ * the GIC cpu interface. INTR_ID_UNAVAILABLE is returned when there is no
+ * interrupt pending.
+ ******************************************************************************/
+uint32_t plat_ic_get_pending_interrupt_id(void)
+{
+	uint32_t id;
+
+	id = gicc_read_hppir(GICC_BASE);
+
+	if (id < 1022)
+		return id;
+
+	if (id == 1023)
+		return INTR_ID_UNAVAILABLE;
+
+	/*
+	 * Find out which non-secure interrupt it is under the assumption that
+	 * the GICC_CTLR.AckCtl bit is 0.
+	 */
+	return gicc_read_ahppir(GICC_BASE);
+}
+
+/*******************************************************************************
+ * This functions reads the GIC cpu interface Interrupt Acknowledge register
+ * to start handling the pending interrupt. It returns the contents of the IAR.
+ ******************************************************************************/
+uint32_t plat_ic_acknowledge_interrupt(void)
+{
+	return gicc_read_IAR(GICC_BASE);
+}
+
+/*******************************************************************************
+ * This functions writes the GIC cpu interface End Of Interrupt register with
+ * the passed value to finish handling the active interrupt
+ ******************************************************************************/
+void plat_ic_end_of_interrupt(uint32_t id)
+{
+	gicc_write_EOIR(GICC_BASE, id);
+}
+
+/*******************************************************************************
+ * This function returns the type of the interrupt id depending upon the group
+ * this interrupt has been configured under by the interrupt controller i.e.
+ * group0 or group1.
+ ******************************************************************************/
+uint32_t plat_ic_get_interrupt_type(uint32_t id)
+{
+	uint32_t group;
+
+	group = gicd_get_igroupr(GICD_BASE, id);
+
+	/* Assume that all secure interrupts are S-EL1 interrupts */
+	if (group == GRP0)
+		return INTR_TYPE_S_EL1;
+	else
+		return INTR_TYPE_NS;
+}
diff --git a/plat/juno/plat_io_storage.c b/plat/juno/plat_io_storage.c
new file mode 100644
index 0000000..83d7e43
--- /dev/null
+++ b/plat/juno/plat_io_storage.c
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <debug.h>
+#include <io_driver.h>
+#include <io_fip.h>
+#include <io_memmap.h>
+#include <io_storage.h>
+#include <platform_def.h>
+#include <semihosting.h>	/* For FOPEN_MODE_... */
+#include <string.h>
+
+/* IO devices */
+static const io_dev_connector_t *fip_dev_con;
+static uintptr_t fip_dev_spec;
+static uintptr_t fip_dev_handle;
+static const io_dev_connector_t *memmap_dev_con;
+static uintptr_t memmap_dev_spec;
+static uintptr_t memmap_init_params;
+static uintptr_t memmap_dev_handle;
+
+static const io_block_spec_t fip_block_spec = {
+	.offset = FLASH_BASE,
+	.length = FLASH_SIZE
+};
+
+static const io_file_spec_t bl2_file_spec = {
+	.path = BL2_IMAGE_NAME,
+	.mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl30_file_spec = {
+	.path = BL30_IMAGE_NAME,
+	.mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl31_file_spec = {
+	.path = BL31_IMAGE_NAME,
+	.mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl32_file_spec = {
+	.path = BL32_IMAGE_NAME,
+	.mode = FOPEN_MODE_RB
+};
+
+static const io_file_spec_t bl33_file_spec = {
+	.path = BL33_IMAGE_NAME,
+	.mode = FOPEN_MODE_RB
+};
+
+static int open_fip(const uintptr_t spec);
+static int open_memmap(const uintptr_t spec);
+
+struct plat_io_policy {
+	const char *image_name;
+	uintptr_t *dev_handle;
+	uintptr_t image_spec;
+	int (*check)(const uintptr_t spec);
+};
+
+static const struct plat_io_policy policies[] = {
+	{
+		FIP_IMAGE_NAME,
+		&memmap_dev_handle,
+		(uintptr_t)&fip_block_spec,
+		open_memmap
+	}, {
+		BL2_IMAGE_NAME,
+		&fip_dev_handle,
+		(uintptr_t)&bl2_file_spec,
+		open_fip
+	}, {
+		BL30_IMAGE_NAME,
+		&fip_dev_handle,
+		(uintptr_t)&bl30_file_spec,
+		open_fip
+	}, {
+		BL31_IMAGE_NAME,
+		&fip_dev_handle,
+		(uintptr_t)&bl31_file_spec,
+		open_fip
+	}, {
+		BL32_IMAGE_NAME,
+		&fip_dev_handle,
+		(uintptr_t)&bl32_file_spec,
+		open_fip
+	}, {
+		BL33_IMAGE_NAME,
+		&fip_dev_handle,
+		(uintptr_t)&bl33_file_spec,
+		open_fip
+	}, {
+		0, 0, 0
+	}
+};
+
+
+static int open_fip(const uintptr_t spec)
+{
+	int result = IO_FAIL;
+
+	/* See if a Firmware Image Package is available */
+	result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_NAME);
+	if (result == IO_SUCCESS) {
+		INFO("Using FIP\n");
+		/*TODO: Check image defined in spec is present in FIP. */
+	}
+	return result;
+}
+
+
+static int open_memmap(const uintptr_t spec)
+{
+	int result = IO_FAIL;
+	uintptr_t local_image_handle;
+
+	result = io_dev_init(memmap_dev_handle, memmap_init_params);
+	if (result == IO_SUCCESS) {
+		result = io_open(memmap_dev_handle, spec, &local_image_handle);
+		if (result == IO_SUCCESS) {
+			/* INFO("Using Memmap IO\n"); */
+			io_close(local_image_handle);
+		}
+	}
+	return result;
+}
+
+void io_setup(void)
+{
+	int io_result = IO_FAIL;
+
+	/* Register the IO devices on this platform */
+	io_result = register_io_dev_fip(&fip_dev_con);
+	assert(io_result == IO_SUCCESS);
+
+	io_result = register_io_dev_memmap(&memmap_dev_con);
+	assert(io_result == IO_SUCCESS);
+
+	/* Open connections to devices and cache the handles */
+	io_result = io_dev_open(fip_dev_con, fip_dev_spec, &fip_dev_handle);
+	assert(io_result == IO_SUCCESS);
+
+	io_result = io_dev_open(memmap_dev_con, memmap_dev_spec,
+				&memmap_dev_handle);
+	assert(io_result == IO_SUCCESS);
+
+	/* Ignore improbable errors in release builds */
+	(void)io_result;
+}
+
+
+/* Return an IO device handle and specification which can be used to access
+ * an image. Use this to enforce platform load policy */
+int plat_get_image_source(const char *image_name, uintptr_t *dev_handle,
+			  uintptr_t *image_spec)
+{
+	int result = IO_FAIL;
+	const struct plat_io_policy *policy;
+
+	if ((image_name != NULL) && (dev_handle != NULL) &&
+	    (image_spec != NULL)) {
+		policy = policies;
+		while (policy->image_name != NULL) {
+			if (strcmp(policy->image_name, image_name) == 0) {
+				result = policy->check(policy->image_spec);
+				if (result == IO_SUCCESS) {
+					*image_spec = policy->image_spec;
+					*dev_handle = *(policy->dev_handle);
+					break;
+				}
+			}
+			policy++;
+		}
+	} else {
+		result = IO_FAIL;
+	}
+	return result;
+}
diff --git a/plat/juno/plat_pm.c b/plat/juno/plat_pm.c
new file mode 100644
index 0000000..74ce89f
--- /dev/null
+++ b/plat/juno/plat_pm.c
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 2013, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <arch_helpers.h>
+#include <debug.h>
+#include <cci400.h>
+#include <errno.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <psci.h>
+#include "juno_def.h"
+#include "juno_private.h"
+#include "scpi.h"
+
+/*******************************************************************************
+ * Private Juno function to program the mailbox for a cpu before it is released
+ * from reset.
+ ******************************************************************************/
+static void juno_program_mailbox(uint64_t mpidr, uint64_t address)
+{
+	uint64_t linear_id;
+	uint64_t mbox;
+
+	linear_id = platform_get_core_pos(mpidr);
+	mbox = TRUSTED_MAILBOXES_BASE +	(linear_id << TRUSTED_MAILBOX_SHIFT);
+	*((uint64_t *) mbox) = address;
+	flush_dcache_range(mbox, sizeof(mbox));
+}
+
+/*******************************************************************************
+ * Private Juno function which is used to determine if any platform actions
+ * should be performed for the specified affinity instance given its
+ * state. Nothing needs to be done if the 'state' is not off or if this is not
+ * the highest affinity level which will enter the 'state'.
+ ******************************************************************************/
+static int32_t juno_do_plat_actions(uint32_t afflvl, uint32_t state)
+{
+	uint32_t max_phys_off_afflvl;
+
+	assert(afflvl <= MPIDR_AFFLVL1);
+
+	if (state != PSCI_STATE_OFF)
+		return -EAGAIN;
+
+	/*
+	 * Find the highest affinity level which will be suspended and postpone
+	 * all the platform specific actions until that level is hit.
+	 */
+	max_phys_off_afflvl = psci_get_max_phys_off_afflvl();
+	assert(max_phys_off_afflvl != PSCI_INVALID_DATA);
+	assert(psci_get_suspend_afflvl() >= max_phys_off_afflvl);
+	if (afflvl != max_phys_off_afflvl)
+		return -EAGAIN;
+
+	return 0;
+}
+
+/*******************************************************************************
+ * Juno handler called when an affinity instance is about to be turned on. The
+ * level and mpidr determine the affinity instance.
+ ******************************************************************************/
+int32_t juno_affinst_on(uint64_t mpidr,
+			uint64_t sec_entrypoint,
+			uint64_t ns_entrypoint,
+			uint32_t afflvl,
+			uint32_t 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
+	 */
+	juno_program_mailbox(mpidr, sec_entrypoint);
+
+	scpi_set_css_power_state(mpidr, scpi_power_on, scpi_power_on,
+				 scpi_power_on);
+
+	return PSCI_E_SUCCESS;
+}
+
+/*******************************************************************************
+ * Juno handler called when an affinity instance has just been powered on after
+ * being turned off earlier. The level and mpidr determine the affinity
+ * instance. The 'state' arg. allows the platform to decide whether the cluster
+ * was turned off prior to wakeup and do what's necessary to setup it up
+ * correctly.
+ ******************************************************************************/
+int32_t juno_affinst_on_finish(uint64_t mpidr, uint32_t afflvl, uint32_t state)
+{
+	/* Determine if any platform actions need to be executed. */
+	if (juno_do_plat_actions(afflvl, state) == -EAGAIN)
+		return PSCI_E_SUCCESS;
+
+	/*
+	 * Perform the common cluster specific operations i.e enable coherency
+	 * if this cluster was off.
+	 */
+	if (afflvl != MPIDR_AFFLVL0)
+		cci_enable_cluster_coherency(mpidr);
+
+
+	/* 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);
+
+	/* Clear the mailbox for this cpu. */
+	juno_program_mailbox(mpidr, 0);
+
+	return PSCI_E_SUCCESS;
+}
+
+/*******************************************************************************
+ * Common function called while turning a cpu off or suspending it. It is called
+ * from juno_off() or juno_suspend() when these functions in turn are called for
+ * the highest affinity level which will be powered down. It performs the
+ * actions common to the OFF and SUSPEND calls.
+ ******************************************************************************/
+static int32_t juno_power_down_common(uint32_t afflvl)
+{
+	uint32_t cluster_state = scpi_power_on;
+
+	/* Prevent interrupts from spuriously waking up this cpu */
+	gic_cpuif_deactivate(GICC_BASE);
+
+	/* Cluster is to be turned off, so disable coherency */
+	if (afflvl > MPIDR_AFFLVL0) {
+		cci_disable_cluster_coherency(read_mpidr_el1());
+		cluster_state = scpi_power_off;
+	}
+
+	/*
+	 * Ask the SCP to power down the appropriate components depending upon
+	 * their state.
+	 */
+	scpi_set_css_power_state(read_mpidr_el1(),
+				 scpi_power_off,
+				 cluster_state,
+				 scpi_power_on);
+
+	return PSCI_E_SUCCESS;
+}
+
+/*******************************************************************************
+ * Handler called when an affinity instance is about to be turned off. The
+ * level and mpidr determine the affinity instance. The 'state' arg. allows the
+ * platform to decide whether the cluster is being turned off and take
+ * appropriate actions.
+ *
+ * CAUTION: There is no guarantee that caches will remain turned on across calls
+ * to this function as each affinity level is dealt with. So do not write & read
+ * global variables across calls. It will be wise to do flush a write to the
+ * global to prevent unpredictable results.
+ ******************************************************************************/
+static int32_t juno_affinst_off(uint64_t mpidr, uint32_t afflvl, uint32_t state)
+{
+	/* Determine if any platform actions need to be executed */
+	if (juno_do_plat_actions(afflvl, state) == -EAGAIN)
+		return PSCI_E_SUCCESS;
+
+	return juno_power_down_common(afflvl);
+}
+
+/*******************************************************************************
+ * Handler called when an affinity instance is about to be suspended. The
+ * level and mpidr determine the affinity instance. The 'state' arg. allows the
+ * platform to decide whether the cluster is being turned off and take apt
+ * actions. The 'sec_entrypoint' determines the address in BL3-1 from where
+ * execution should resume.
+ *
+ * CAUTION: There is no guarantee that caches will remain turned on across calls
+ * to this function as each affinity level is dealt with. So do not write & read
+ * global variables across calls. It will be wise to do flush a write to the
+ * global to prevent unpredictable results.
+ ******************************************************************************/
+static int32_t juno_affinst_suspend(uint64_t mpidr,
+				    uint64_t sec_entrypoint,
+				    uint64_t ns_entrypoint,
+				    uint32_t afflvl,
+				    uint32_t state)
+{
+	/* Determine if any platform actions need to be executed */
+	if (juno_do_plat_actions(afflvl, state) == -EAGAIN)
+		return PSCI_E_SUCCESS;
+
+	/*
+	 * Setup mailbox with address for CPU entrypoint when it next powers up.
+	 */
+	juno_program_mailbox(mpidr, sec_entrypoint);
+
+	return juno_power_down_common(afflvl);
+}
+
+/*******************************************************************************
+ * Juno handler called when an affinity instance has just been powered on after
+ * having been suspended earlier. The level and mpidr determine the affinity
+ * instance.
+ * TODO: At the moment we reuse the on finisher and reinitialize the secure
+ * context. Need to implement a separate suspend finisher.
+ ******************************************************************************/
+static int32_t juno_affinst_suspend_finish(uint64_t mpidr,
+					   uint32_t afflvl,
+					   uint32_t state)
+{
+	return juno_affinst_on_finish(mpidr, afflvl, state);
+}
+
+/*******************************************************************************
+ * Juno handlers to shutdown/reboot the system
+ ******************************************************************************/
+static void __dead2 juno_system_off(void)
+{
+	uint32_t response;
+
+	/* Send the power down request to the SCP */
+	response = scpi_sys_power_state(scpi_system_shutdown);
+
+	if (response != SCP_OK) {
+		ERROR("Juno System Off: SCP error %u.\n", response);
+		panic();
+	}
+	wfi();
+	ERROR("Juno System Off: operation not handled.\n");
+	panic();
+}
+
+static void __dead2 juno_system_reset(void)
+{
+	uint32_t response;
+
+	/* Send the system reset request to the SCP */
+	response = scpi_sys_power_state(scpi_system_reboot);
+
+	if (response != SCP_OK) {
+		ERROR("Juno System Reset: SCP error %u.\n", response);
+		panic();
+	}
+	wfi();
+	ERROR("Juno System Reset: operation not handled.\n");
+	panic();
+}
+
+/*******************************************************************************
+ * Export the platform handlers to enable psci to invoke them
+ ******************************************************************************/
+static const plat_pm_ops_t juno_ops = {
+	.affinst_on		= juno_affinst_on,
+	.affinst_on_finish	= juno_affinst_on_finish,
+	.affinst_off		= juno_affinst_off,
+	.affinst_suspend	= juno_affinst_suspend,
+	.affinst_suspend_finish	= juno_affinst_suspend_finish,
+	.system_off		= juno_system_off,
+	.system_reset		= juno_system_reset
+};
+
+/*******************************************************************************
+ * Export the platform specific power ops.
+ ******************************************************************************/
+int32_t platform_setup_pm(const plat_pm_ops_t **plat_ops)
+{
+	*plat_ops = &juno_ops;
+	return 0;
+}
diff --git a/plat/juno/plat_topology.c b/plat/juno/plat_topology.c
new file mode 100644
index 0000000..39d4dab
--- /dev/null
+++ b/plat/juno/plat_topology.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <platform_def.h>
+#include <psci.h>
+
+unsigned int plat_get_aff_count(unsigned int aff_lvl, unsigned long mpidr)
+{
+	/* Report 1 (absent) instance at levels higher that the cluster level */
+	if (aff_lvl > MPIDR_AFFLVL1)
+		return 1;
+
+	if (aff_lvl == MPIDR_AFFLVL1)
+		return 2; /* We have two clusters */
+
+	return mpidr & 0x100 ? 4 : 2; /* 4 cpus in cluster 1, 2 in cluster 0 */
+}
+
+unsigned int plat_get_aff_state(unsigned int aff_lvl, unsigned long mpidr)
+{
+	return aff_lvl <= MPIDR_AFFLVL1 ? PSCI_AFF_PRESENT : PSCI_AFF_ABSENT;
+}
+
+int plat_get_max_afflvl()
+{
+	return MPIDR_AFFLVL1;
+}
+
+int plat_setup_topology()
+{
+	/* Juno todo: Make topology configurable via SCC */
+	return 0;
+}
diff --git a/plat/juno/platform.mk b/plat/juno/platform.mk
new file mode 100644
index 0000000..4746536
--- /dev/null
+++ b/plat/juno/platform.mk
@@ -0,0 +1,82 @@
+#
+# Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# Neither the name of ARM nor the names of its contributors may be used
+# to endorse or promote products derived from this software without specific
+# prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+PLAT_INCLUDES		:=	-Iplat/juno/include/
+
+PLAT_BL_COMMON_SOURCES	:=	drivers/arm/pl011/pl011_console.S	\
+				drivers/io/io_fip.c			\
+				drivers/io/io_memmap.c			\
+				drivers/io/io_storage.c			\
+				lib/aarch64/xlat_tables.c		\
+				plat/common/aarch64/plat_common.c	\
+				plat/juno/plat_io_storage.c
+
+BL1_SOURCES		+=	drivers/arm/cci400/cci400.c		\
+				lib/cpus/aarch64/cortex_a53.S		\
+				lib/cpus/aarch64/cortex_a57.S		\
+				plat/common/aarch64/platform_up_stack.S	\
+				plat/juno/bl1_plat_setup.c		\
+				plat/juno/aarch64/bl1_plat_helpers.S	\
+				plat/juno/aarch64/plat_helpers.S	\
+				plat/juno/aarch64/juno_common.c
+
+BL2_SOURCES		+=	lib/locks/bakery/bakery_lock.c		\
+				plat/common/aarch64/platform_up_stack.S	\
+				plat/juno/bl2_plat_setup.c		\
+				plat/juno/mhu.c				\
+				plat/juno/aarch64/plat_helpers.S	\
+				plat/juno/aarch64/juno_common.c		\
+				plat/juno/scp_bootloader.c		\
+				plat/juno/scpi.c
+
+BL31_SOURCES		+=	drivers/arm/cci400/cci400.c		\
+				drivers/arm/gic/gic_v2.c		\
+				lib/cpus/aarch64/cortex_a53.S		\
+				lib/cpus/aarch64/cortex_a57.S		\
+				plat/common/aarch64/platform_mp_stack.S	\
+				plat/juno/bl31_plat_setup.c		\
+				plat/juno/mhu.c				\
+				plat/juno/aarch64/plat_helpers.S	\
+				plat/juno/aarch64/juno_common.c		\
+				plat/juno/plat_pm.c			\
+				plat/juno/plat_topology.c		\
+				plat/juno/plat_gic.c			\
+				plat/juno/scpi.c
+
+ifneq (${RESET_TO_BL31},0)
+  $(error "Using BL3-1 as the reset vector is not supported on Juno. \
+  Please set RESET_TO_BL31 to 0.")
+endif
+
+NEED_BL30		:=	yes
+
+# Enable workarounds for selected Cortex-A57 erratas.
+ERRATA_A57_806969	:=	1
+ERRATA_A57_813420	:=	1
diff --git a/plat/juno/scp_bootloader.c b/plat/juno/scp_bootloader.c
new file mode 100644
index 0000000..a6d25d4
--- /dev/null
+++ b/plat/juno/scp_bootloader.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <platform.h>
+#include "juno_def.h"
+#include "mhu.h"
+#include "scp_bootloader.h"
+#include "scpi.h"
+
+/* Boot commands sent from AP -> SCP */
+#define BOOT_CMD_START	0x01
+#define BOOT_CMD_DATA	0x02
+
+typedef struct {
+	uint32_t image_size;
+} cmd_start_payload;
+
+typedef struct {
+	uint32_t sequence_num;
+	uint32_t offset;
+	uint32_t size;
+} cmd_data_payload;
+
+#define BOOT_DATA_MAX_SIZE  0x1000
+
+/* Boot commands sent from SCP -> AP */
+#define BOOT_CMD_ACK	0x03
+#define BOOT_CMD_NACK	0x04
+
+typedef struct {
+	uint32_t sequence_num;
+} cmd_ack_payload;
+
+/*
+ * Unlike the runtime protocol, the boot protocol uses the same memory region
+ * for both AP -> SCP and SCP -> AP transfers; define the address of this...
+ */
+static void * const cmd_payload = (void *)(MHU_SECURE_BASE + 0x0080);
+
+static void *scp_boot_message_start(void)
+{
+	mhu_secure_message_start();
+
+	return cmd_payload;
+}
+
+static void scp_boot_message_send(unsigned command, size_t size)
+{
+	/* Make sure payload can be seen by SCP */
+	if (MHU_PAYLOAD_CACHED)
+		flush_dcache_range((unsigned long)cmd_payload, size);
+
+	/* Send command to SCP */
+	mhu_secure_message_send(command | (size << 8));
+}
+
+static uint32_t scp_boot_message_wait(size_t size)
+{
+	uint32_t response =  mhu_secure_message_wait();
+
+	/* Make sure we see the reply from the SCP and not any stale data */
+	if (MHU_PAYLOAD_CACHED)
+		inv_dcache_range((unsigned long)cmd_payload, size);
+
+	return response & 0xff;
+}
+
+static void scp_boot_message_end(void)
+{
+	mhu_secure_message_end();
+}
+
+static int transfer_block(uint32_t sequence_num, uint32_t offset, uint32_t size)
+{
+	cmd_data_payload *cmd_data = scp_boot_message_start();
+	cmd_data->sequence_num = sequence_num;
+	cmd_data->offset = offset;
+	cmd_data->size = size;
+
+	scp_boot_message_send(BOOT_CMD_DATA, sizeof(*cmd_data));
+
+	cmd_ack_payload *cmd_ack = cmd_payload;
+	int ok = scp_boot_message_wait(sizeof(*cmd_ack)) == BOOT_CMD_ACK
+		 && cmd_ack->sequence_num == sequence_num;
+
+	scp_boot_message_end();
+
+	return ok;
+}
+
+int scp_bootloader_transfer(void *image, unsigned int image_size)
+{
+	uintptr_t offset = (uintptr_t)image - MHU_SECURE_BASE;
+	uintptr_t end = offset + image_size;
+	uint32_t response;
+
+	mhu_secure_init();
+
+	/* Initiate communications with SCP */
+	do {
+		cmd_start_payload *cmd_start = scp_boot_message_start();
+		cmd_start->image_size = image_size;
+
+		scp_boot_message_send(BOOT_CMD_START, sizeof(*cmd_start));
+
+		response = scp_boot_message_wait(0);
+
+		scp_boot_message_end();
+	} while (response != BOOT_CMD_ACK);
+
+	/* Transfer image to SCP a block at a time */
+	uint32_t sequence_num = 1;
+	size_t size;
+	while ((size = end - offset) != 0) {
+		if (size > BOOT_DATA_MAX_SIZE)
+			size = BOOT_DATA_MAX_SIZE;
+		while (!transfer_block(sequence_num, offset, size))
+			; /* Retry forever */
+		offset += size;
+		sequence_num++;
+	}
+
+	/* Wait for SCP to signal it's ready */
+	return scpi_wait_ready();
+}
diff --git a/plat/juno/scp_bootloader.h b/plat/juno/scp_bootloader.h
new file mode 100644
index 0000000..e872513
--- /dev/null
+++ b/plat/juno/scp_bootloader.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __SCP_BOOTLOADER_H__
+#define __SCP_BOOTLOADER_H__
+
+int scp_bootloader_transfer(void *image, unsigned int image_size);
+
+#endif
diff --git a/plat/juno/scpi.c b/plat/juno/scpi.c
new file mode 100644
index 0000000..950c00b
--- /dev/null
+++ b/plat/juno/scpi.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch_helpers.h>
+#include <platform.h>
+#include "juno_def.h"
+#include "mhu.h"
+#include "scpi.h"
+
+#define MHU_SECURE_SCP_TO_AP_PAYLOAD	(MHU_SECURE_BASE+0x0080)
+#define MHU_SECURE_AP_TO_SCP_PAYLOAD	(MHU_SECURE_BASE+0x0280)
+
+#define SIZE_SHIFT	20	/* Bit position for size value in MHU header */
+#define SIZE_MASK	0x1ff	/* Mask to extract size value in MHU header*/
+
+
+void *scpi_secure_message_start(void)
+{
+	mhu_secure_message_start();
+
+	/* Return address of payload area. */
+	return (void *)MHU_SECURE_AP_TO_SCP_PAYLOAD;
+}
+
+void scpi_secure_message_send(unsigned command, size_t size)
+{
+	/* Make sure payload can be seen by SCP */
+	if (MHU_PAYLOAD_CACHED)
+		flush_dcache_range(MHU_SECURE_AP_TO_SCP_PAYLOAD, size);
+
+	mhu_secure_message_send(command | (size << SIZE_SHIFT));
+}
+
+unsigned scpi_secure_message_receive(void **message_out, size_t *size_out)
+{
+	uint32_t response =  mhu_secure_message_wait();
+
+	/* Get size of payload */
+	size_t size = (response >> SIZE_SHIFT) & SIZE_MASK;
+
+	/* Clear size from response */
+	response &= ~(SIZE_MASK << SIZE_SHIFT);
+
+	/* Make sure we don't read stale data */
+	if (MHU_PAYLOAD_CACHED)
+		inv_dcache_range(MHU_SECURE_SCP_TO_AP_PAYLOAD, size);
+
+	if (size_out)
+		*size_out = size;
+
+	if (message_out)
+		*message_out = (void *)MHU_SECURE_SCP_TO_AP_PAYLOAD;
+
+	return response;
+}
+
+void scpi_secure_message_end(void)
+{
+	mhu_secure_message_end();
+}
+
+static void scpi_secure_send32(unsigned command, uint32_t message)
+{
+	*(__typeof__(message) *)scpi_secure_message_start() = message;
+	scpi_secure_message_send(command, sizeof(message));
+	scpi_secure_message_end();
+}
+
+int scpi_wait_ready(void)
+{
+	/* Get a message from the SCP */
+	scpi_secure_message_start();
+	size_t size;
+	unsigned command = scpi_secure_message_receive(NULL, &size);
+	scpi_secure_message_end();
+
+	/* We are expecting 'SCP Ready', produce correct error if it's not */
+	scpi_status_t response = SCP_OK;
+	if (command != SCPI_CMD_SCP_READY)
+		response = SCP_E_SUPPORT;
+	else if (size != 0)
+		response = SCP_E_SIZE;
+
+	/* Send our response back to SCP */
+	scpi_secure_send32(command, response);
+
+	return response == SCP_OK ? 0 : -1;
+}
+
+void scpi_set_css_power_state(unsigned mpidr, scpi_power_state_t cpu_state,
+		scpi_power_state_t cluster_state, scpi_power_state_t css_state)
+{
+	uint32_t state = mpidr & 0x0f;	/* CPU ID */
+	state |= (mpidr & 0xf00) >> 4;	/* Cluster ID */
+	state |= cpu_state << 8;
+	state |= cluster_state << 12;
+	state |= css_state << 16;
+	scpi_secure_send32(SCPI_CMD_SET_CSS_POWER_STATE, state);
+}
+
+uint32_t scpi_sys_power_state(scpi_system_state_t system_state)
+{
+	uint32_t *response;
+	size_t size;
+	uint8_t state = system_state & 0xff;
+
+	/* Send the command */
+	*(__typeof__(state) *)scpi_secure_message_start() = state;
+	scpi_secure_message_send(SCPI_CMD_SYS_POWER_STATE, sizeof(state));
+	scpi_secure_message_receive((void *)&response, &size);
+	scpi_secure_message_end();
+	return *response;
+}
diff --git a/plat/juno/scpi.h b/plat/juno/scpi.h
new file mode 100644
index 0000000..8a5ef65
--- /dev/null
+++ b/plat/juno/scpi.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __SCPI_H__
+#define __SCPI_H__
+
+#include <stddef.h>
+#include <stdint.h>
+
+extern void *scpi_secure_message_start(void);
+extern void scpi_secure_message_send(unsigned command, size_t size);
+extern unsigned scpi_secure_message_receive(void **message_out, size_t *size_out);
+extern void scpi_secure_message_end(void);
+
+
+enum {
+	SCP_OK = 0,	/* Success */
+	SCP_E_PARAM,	/* Invalid parameter(s) */
+	SCP_E_ALIGN,	/* Invalid alignment */
+	SCP_E_SIZE,	/* Invalid size */
+	SCP_E_HANDLER,	/* Invalid handler or callback */
+	SCP_E_ACCESS,	/* Invalid access or permission denied */
+	SCP_E_RANGE,	/* Value out of range */
+	SCP_E_TIMEOUT,	/* Time out has ocurred */
+	SCP_E_NOMEM,	/* Invalid memory area or pointer */
+	SCP_E_PWRSTATE,	/* Invalid power state */
+	SCP_E_SUPPORT,	/* Feature not supported or disabled */
+};
+
+typedef uint32_t scpi_status_t;
+
+typedef enum {
+	SCPI_CMD_SCP_READY = 0x01,
+	SCPI_CMD_SET_CSS_POWER_STATE = 0x04,
+	SCPI_CMD_SYS_POWER_STATE = 0x08
+} scpi_command_t;
+
+typedef enum {
+	scpi_power_on = 0,
+	scpi_power_retention = 1,
+	scpi_power_off = 3,
+} scpi_power_state_t;
+
+typedef enum {
+	scpi_system_shutdown = 0,
+	scpi_system_reboot = 1,
+	scpi_system_reset = 2
+} scpi_system_state_t;
+
+extern int scpi_wait_ready(void);
+extern void scpi_set_css_power_state(unsigned mpidr, scpi_power_state_t cpu_state,
+		scpi_power_state_t cluster_state, scpi_power_state_t css_state);
+uint32_t scpi_sys_power_state(scpi_system_state_t system_state);
+
+#endif	/* __SCPI_H__ */
diff --git a/plat/juno/tsp/tsp-juno.mk b/plat/juno/tsp/tsp-juno.mk
new file mode 100644
index 0000000..d0d29d7
--- /dev/null
+++ b/plat/juno/tsp/tsp-juno.mk
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# Neither the name of ARM nor the names of its contributors may be used
+# to endorse or promote products derived from this software without specific
+# prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+# TSP source files specific to Juno platform
+BL32_SOURCES		+=	drivers/arm/gic/gic_v2.c		\
+				plat/common/aarch64/platform_mp_stack.S	\
+				plat/juno/aarch64/juno_common.c		\
+				plat/juno/aarch64/plat_helpers.S	\
+				plat/juno/tsp/tsp_plat_setup.c		\
+				plat/juno/plat_gic.c
diff --git a/plat/juno/tsp/tsp_plat_setup.c b/plat/juno/tsp/tsp_plat_setup.c
new file mode 100644
index 0000000..b999df1
--- /dev/null
+++ b/plat/juno/tsp/tsp_plat_setup.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <bl_common.h>
+#include <console.h>
+#include <platform_tsp.h>
+#include "../juno_def.h"
+#include "../juno_private.h"
+
+/*******************************************************************************
+ * Declarations of linker defined symbols which will help us find the layout
+ * of trusted SRAM
+ ******************************************************************************/
+extern unsigned long __RO_START__;
+extern unsigned long __RO_END__;
+
+extern unsigned long __COHERENT_RAM_START__;
+extern unsigned long __COHERENT_RAM_END__;
+
+/*
+ * The next 2 constants identify the extents of the code & RO data region.
+ * These addresses are used by the MMU setup code and therefore they must be
+ * page-aligned.  It is the responsibility of the linker script to ensure that
+ * __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses.
+ */
+#define BL32_RO_BASE (unsigned long)(&__RO_START__)
+#define BL32_RO_LIMIT (unsigned long)(&__RO_END__)
+
+/*
+ * The next 2 constants identify the extents of the coherent memory region.
+ * These addresses are used by the MMU setup code and therefore they must be
+ * page-aligned.  It is the responsibility of the linker script to ensure that
+ * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols refer to
+ * page-aligned addresses.
+ */
+#define BL32_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__)
+#define BL32_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__)
+
+/*******************************************************************************
+ * Initialize the UART
+ ******************************************************************************/
+void tsp_early_platform_setup(void)
+{
+	/*
+	 * Initialize a different console than already in use to display
+	 * messages from TSP
+	 */
+	console_init(PL011_UART1_BASE, PL011_UART1_CLK_IN_HZ, PL011_BAUDRATE);
+}
+
+/*******************************************************************************
+ * Perform platform specific setup placeholder
+ ******************************************************************************/
+void tsp_platform_setup(void)
+{
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this only intializes the MMU
+ ******************************************************************************/
+void tsp_plat_arch_setup(void)
+{
+	configure_mmu_el1(BL32_RO_BASE,
+			  BL32_COHERENT_RAM_LIMIT - BL32_RO_BASE,
+			  BL32_RO_BASE,
+			  BL32_RO_LIMIT,
+			  BL32_COHERENT_RAM_BASE,
+			  BL32_COHERENT_RAM_LIMIT);
+}