Merge pull request #220 from soby-mathew/sm/reassign_crash_console

Use the BL3-1 runtime console as the crash console.
diff --git a/Makefile b/Makefile
index af2ddd4..9b15c21 100644
--- a/Makefile
+++ b/Makefile
@@ -138,9 +138,10 @@
 
 include plat/${PLAT}/platform.mk
 
-# By default all CPU errata workarounds are disabled. This can be
+# Include the CPU specific operations makefile. By default all CPU errata
+# workarounds and CPU specifc optimisations are disabled. This can be
 # overridden by the platform.
-include lib/cpus/cpu-errata.mk
+include lib/cpus/cpu-ops.mk
 
 ifdef BL1_SOURCES
 NEED_BL1 := yes
diff --git a/bl2/bl2_main.c b/bl2/bl2_main.c
index 51c55e0..a73946e 100644
--- a/bl2/bl2_main.c
+++ b/bl2/bl2_main.c
@@ -199,9 +199,6 @@
 	/* Perform remaining generic architectural setup in S-EL1 */
 	bl2_arch_setup();
 
-	/* Perform platform setup in BL2 */
-	bl2_platform_setup();
-
 	/*
 	 * Load the subsequent bootloader images
 	 */
@@ -211,6 +208,9 @@
 		panic();
 	}
 
+	/* Perform platform setup in BL2 after loading BL3-0 */
+	bl2_platform_setup();
+
 	/*
 	 * Get a pointer to the memory the platform has set aside to pass
 	 * information to BL3-1.
diff --git a/docs/cpu-errata-workarounds.md b/docs/cpu-errata-workarounds.md
deleted file mode 100644
index 8285d89..0000000
--- a/docs/cpu-errata-workarounds.md
+++ /dev/null
@@ -1,35 +0,0 @@
-ARM CPU Errata Workarounds
-==========================
-
-ARM Trusted Firmware exports a series of build flags which control the
-errata workarounds that are applied to each CPU by the reset handler. The
-errata details can be found in the CPU specifc errata documents published
-by ARM. The errata workarounds are implemented for a particular revision
-or a set of processor revisions. This check is done in the debug build.
-Each errata workaround is identified by its `ID` as specified in the processor's
-errata notice document. The format of the define used to enable/disable the
-errata is `ERRATA_<Processor name>_<ID>` where the `Processor name`
-is either `A57` for the `Cortex_A57` CPU or `A53` for `Cortex_A53` CPU.
-
-All workarounds are disabled by default. The platform is reponsible for
-enabling these workarounds according to its requirement by defining the
-errata workaround build flags in the platform specific makefile.
-
-In the current implementation, a platform which has more than 1 variant
-with different revisions of a processor has no runtime mechanism available
-for it to specify which errata workarounds should be enabled or not.
-
-The value of the build flags are 0 by default, that is, disabled. Any other
-value will enable it.
-
-For Cortex A57, following errata build flags are defined :
-
-*   `ERRATA_A57_806969`: This applies errata 806969 workaround to cortex a57
-     CPU. This needs to be enabled only for revision r0p0 of the CPU.
-
-*   `ERRATA_A57_813420`: This applies errata 813420 workaround to cortex a57
-     CPU. This needs to be enabled only for revision r0p0 of the CPU.
-
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-_Copyright (c) 2014, ARM Limited and Contributors. All rights reserved._
diff --git a/docs/cpu-specific-build-macros.md b/docs/cpu-specific-build-macros.md
new file mode 100644
index 0000000..246381a
--- /dev/null
+++ b/docs/cpu-specific-build-macros.md
@@ -0,0 +1,69 @@
+ARM CPU Specific Build Macros
+=============================
+
+Contents
+--------
+
+1.  Introduction
+2.  CPU Errata Workarounds
+3.  CPU Specific optimizations
+
+1.  Introduction
+----------------
+
+This document describes the various build options present in the CPU specific
+operations framework to enable errata workarounds and to enable optimizations
+for a specific CPU on a platform.
+
+2.  CPU Errata Workarounds
+--------------------------
+
+ARM Trusted Firmware exports a series of build flags which control the
+errata workarounds that are applied to each CPU by the reset handler. The
+errata details can be found in the CPU specifc errata documents published
+by ARM. The errata workarounds are implemented for a particular revision
+or a set of processor revisions. This is checked by reset handler at runtime.
+Each errata workaround is identified by its `ID` as specified in the processor's
+errata notice document. The format of the define used to enable/disable the
+errata is `ERRATA_<Processor name>_<ID>` where the `Processor name`
+is either `A57` for the `Cortex_A57` CPU or `A53` for `Cortex_A53` CPU.
+
+All workarounds are disabled by default. The platform is reponsible for
+enabling these workarounds according to its requirement by defining the
+errata workaround build flags in the platform specific makefile. In case
+these workarounds are enabled for the wrong CPU revision then the errata
+workaround is not applied. In the DEBUG build, this is indicated by
+printing a warning to the crash console.
+
+In the current implementation, a platform which has more than 1 variant
+with different revisions of a processor has no runtime mechanism available
+for it to specify which errata workarounds should be enabled or not.
+
+The value of the build flags are 0 by default, that is, disabled. Any other
+value will enable it.
+
+For Cortex-A57, following errata build flags are defined :
+
+*   `ERRATA_A57_806969`: This applies errata 806969 workaround to Cortex-A57
+     CPU. This needs to be enabled only for revision r0p0 of the CPU.
+
+*   `ERRATA_A57_813420`: This applies errata 813420 workaround to Cortex-A57
+     CPU. This needs to be enabled only for revision r0p0 of the CPU.
+
+3.  CPU Specific optimizations
+------------------------------
+
+This section describes some of the optimizations allowed by the CPU micro
+architecture that can be enabled by the platform as desired.
+
+*    `SKIP_A57_L1_FLUSH_PWR_DWN`: This flag enables an optimization in the
+     Cortex-A57 cluster power down sequence by not flushing the Level 1 data
+     cache. The L1 data cache and the L2 unified cache are inclusive. A flush
+     of the L2 by set/way flushes any dirty lines from the L1 as well. This
+     is a known safe deviation from the Cortex-A57 TRM defined power down
+     sequence. Each Cortex-A57 based platform must make its own decision on
+     whether to use the optimization.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+_Copyright (c) 2014, ARM Limited and Contributors. All rights reserved._
diff --git a/docs/firmware-design.md b/docs/firmware-design.md
index e952617..bc075da 100644
--- a/docs/firmware-design.md
+++ b/docs/firmware-design.md
@@ -982,9 +982,10 @@
 
 The CPU specific operations framework scales to accommodate a large number of
 different CPUs during power down and reset handling. The platform can specify
+any CPU optimization it wants to enable for each CPU. It can also specify
 the CPU errata workarounds to be applied for each CPU type during reset
 handling by defining CPU errata compile time macros. Details on these macros
-can be found in the [cpu-errata-workarounds.md][ERRW] file.
+can be found in the [cpu-specific-build-macros.md][CPUBM] file.
 
 The CPU specific operations framework depends on the `cpu_ops` structure which
 needs to be exported for each type of CPU in the platform. It is defined in
@@ -1199,16 +1200,12 @@
 The following list describes the memory layout on the FVP:
 
 *   A 4KB page of shared memory is used to store the entrypoint mailboxes
-    and the parameters passed between bootloaders. The shared memory can be
-    allocated either at the top of Trusted SRAM or at the base of Trusted
-    DRAM at build time. When allocated in Trusted SRAM, the amount of Trusted
-    SRAM available to load the bootloader images will be reduced by the size
-    of the shared memory.
+    and the parameters passed between bootloaders. The shared memory is located
+    at the base of the Trusted SRAM. The amount of Trusted SRAM available to
+    load the bootloader images will be reduced by the size of the shared memory.
 
 *   BL1 is originally sitting in the Trusted ROM at address `0x0`. Its
     read-write data are relocated at the top of the Trusted SRAM at runtime.
-    If the shared memory is allocated in Trusted SRAM, the BL1 read-write data
-    is relocated just below the shared memory.
 
 *   BL3-1 is loaded at the top of the Trusted SRAM, such that its NOBITS
     sections will overwrite BL1 R/W data.
@@ -1217,21 +1214,17 @@
 
 *   The TSP is loaded as the BL3-2 image at the base of either the Trusted
     SRAM or Trusted DRAM. When loaded into Trusted SRAM, its NOBITS sections
-    are allowed to overlay BL2. When loaded into Trusted DRAM, an offset
-    corresponding to the size of the shared memory is applied to avoid
-    overlap.
+    are allowed to overlay BL2.
 
 This memory layout is designed to give the BL3-2 image as much memory as
 possible when it is loaded into Trusted SRAM. Depending on the location of the
-shared memory page and the TSP, it will result in different memory maps,
-illustrated by the following diagrams.
+TSP, it will result in different memory maps, illustrated by the following
+diagrams.
 
-**Shared data & TSP in Trusted SRAM (default option):**
+**TSP in Trusted SRAM (default option):**
 
                Trusted SRAM
-    0x04040000 +----------+
-               |  Shared  |
-    0x0403F000 +----------+  loaded by BL2  ------------------
+    0x04040000 +----------+  loaded by BL2  ------------------
                | BL1 (rw) |  <<<<<<<<<<<<<  |  BL3-1 NOBITS  |
                |----------|  <<<<<<<<<<<<<  |----------------|
                |          |  <<<<<<<<<<<<<  | BL3-1 PROGBITS |
@@ -1239,7 +1232,9 @@
                |   BL2    |  <<<<<<<<<<<<<  |  BL3-2 NOBITS  |
                |----------|  <<<<<<<<<<<<<  |----------------|
                |          |  <<<<<<<<<<<<<  | BL3-2 PROGBITS |
-    0x04000000 +----------+                 ------------------
+    0x04001000 +----------+                 ------------------
+               |  Shared  |
+    0x04000000 +----------+
 
                Trusted ROM
     0x04000000 +----------+
@@ -1247,15 +1242,11 @@
     0x00000000 +----------+
 
 
-**Shared data & TSP in Trusted DRAM:**
+**TSP in Trusted DRAM:**
 
                Trusted DRAM
     0x08000000 +----------+
-               |          |
                |  BL3-2   |
-               |          |
-    0x06001000 |----------|
-               |  Shared  |
     0x06000000 +----------+
 
                Trusted SRAM
@@ -1267,6 +1258,8 @@
                |   BL2    |
                |----------|
                |          |
+    0x04001000 +----------+
+               |  Shared  |
     0x04000000 +----------+
 
                Trusted ROM
@@ -1274,37 +1267,46 @@
                | BL1 (ro) |
     0x00000000 +----------+
 
-**Shared data in Trusted DRAM, TSP in Trusted SRAM:**
+Loading the TSP image in Trusted DRAM doesn't change the memory layout of the
+other boot loader images in Trusted SRAM.
 
-               Trusted DRAM
+####  Memory layout on Juno ARM development platform
+
+**TSP in Trusted SRAM (default option):**
+
+                  Flash0
+    0x0C000000 +----------+
+               :          :
+    0x0BED0000 |----------|
+               | BL1 (ro) |
+    0x0BEC0000 |----------|
+               :          :
+               |  Bypass  |
     0x08000000 +----------+
-               |          |
-               |          |
-               |          |
-    0x06001000 |----------|
-               |  Shared  |
-    0x06000000 +----------+
 
                Trusted SRAM
-    0x04040000 +----------+  loaded by BL2  ------------------
-               | BL1 (rw) |  <<<<<<<<<<<<<  |  BL3-1 NOBITS  |
-               |----------|  <<<<<<<<<<<<<  |----------------|
-               |          |  <<<<<<<<<<<<<  | BL3-1 PROGBITS |
-               |----------|                 ------------------
-               |   BL2    |  <<<<<<<<<<<<<  |  BL3-2 NOBITS  |
-               |----------|  <<<<<<<<<<<<<  |----------------|
-               |          |  <<<<<<<<<<<<<  | BL3-2 PROGBITS |
-    0x04000000 +----------+                 ------------------
-
-               Trusted ROM
+    0x04040000 +----------+
+               |   BL2    |                 BL3-1 is loaded
+    0x04033000 |----------|                 after BL3-0 has
+               |  BL3-2   |                 been sent to SCP
+    0x04023000 |----------|                 ------------------
+               |  BL3-0   |  <<<<<<<<<<<<<  |     BL3-1      |
+    0x04009000 |----------|                 ------------------
+               | BL1 (rw) |
+    0x04001000 |----------|
+               |   MHU    |
     0x04000000 +----------+
-               | BL1 (ro) |
-    0x00000000 +----------+
 
-Loading the TSP image in Trusted DRAM doesn't change the memory layout of the
-other boot loader images in Trusted SRAM.
+**TSP in the secure region of DRAM:**
 
-####  Memory layout on Juno ARM development platform
+                   DRAM
+    0xFFE00000 +----------+
+               |  BL3-2   |
+    0xFF000000 |----------|
+               |          |
+               :          :
+               |          |
+    0x80000000 +----------+
 
                   Flash0
     0x0C000000 +----------+
@@ -1320,7 +1322,7 @@
     0x04040000 +----------+
                |   BL2    |                 BL3-1 is loaded
     0x04033000 |----------|                 after BL3-0 has
-               |  BL3-2   |                 been sent to SCP
+               |          |                 been sent to SCP
     0x04023000 |----------|                 ------------------
                |  BL3-0   |  <<<<<<<<<<<<<  |     BL3-1      |
     0x04009000 |----------|                 ------------------
@@ -1484,4 +1486,4 @@
 [User Guide]:       ./user-guide.md
 [Porting Guide]:    ./porting-guide.md
 [INTRG]:            ./interrupt-framework-design.md
-[ERRW]:             ./cpu-errata-workarounds.md
+[CPUBM]:            ./cpu-specific-build-macros.md.md
diff --git a/docs/user-guide.md b/docs/user-guide.md
index d3a92f9..0b95a1b 100644
--- a/docs/user-guide.md
+++ b/docs/user-guide.md
@@ -244,18 +244,19 @@
 
 #### FVP specific build options
 
-*   `FVP_SHARED_DATA_LOCATION`: location of the shared memory page. Available
-    options:
-    -   `tsram` (default) : top of Trusted SRAM
-    -   `tdram` : base of Trusted DRAM
-
 *   `FVP_TSP_RAM_LOCATION`: location of the TSP binary. Options:
-    -   `tsram` (default) : base of Trusted SRAM
-    -   `tdram` : Trusted DRAM (above shared data)
+    -   `tsram` (default) : Trusted SRAM
+    -   `tdram` : Trusted DRAM
 
 For a better understanding of FVP options, the FVP memory map is explained in
 the [Firmware Design].
 
+#### Juno specific build options
+
+*   `PLAT_TSP_LOCATION`: location of the TSP binary. Options:
+    -   `tsram` : Trusted SRAM (default option)
+    -   `dram`  : Secure region in DRAM (set by the TrustZone controller)
+
 ### Creating a Firmware Image Package
 
 FIPs are automatically created as part of the build instructions described in
diff --git a/drivers/arm/gic/arm_gic.c b/drivers/arm/gic/arm_gic.c
index 86aaa9a..58fbc89 100644
--- a/drivers/arm/gic/arm_gic.c
+++ b/drivers/arm/gic/arm_gic.c
@@ -40,6 +40,12 @@
 #include <platform.h>
 #include <stdint.h>
 
+/* Value used to initialize Non-Secure IRQ priorities four at a time */
+#define GICD_IPRIORITYR_DEF_VAL \
+	(GIC_HIGHEST_NS_PRIORITY | \
+	(GIC_HIGHEST_NS_PRIORITY << 8) | \
+	(GIC_HIGHEST_NS_PRIORITY << 16) | \
+	(GIC_HIGHEST_NS_PRIORITY << 24))
 
 static unsigned int g_gicc_base;
 static unsigned int g_gicd_base;
@@ -216,8 +222,16 @@
 	unsigned int index, irq_num;
 
 	assert(g_gicd_base);
+
+	/* Mark all 32 SGI+PPI interrupts as Group 1 (non-secure) */
 	gicd_write_igroupr(g_gicd_base, 0, ~0);
 
+	/* Setup PPI priorities doing four at a time */
+	for (index = 0; index < 32; index += 4) {
+		gicd_write_ipriorityr(g_gicd_base, index,
+				GICD_IPRIORITYR_DEF_VAL);
+	}
+
 	assert(g_irq_sec_ptr);
 	for (index = 0; index < g_num_irqs; index++) {
 		irq_num = g_irq_sec_ptr[index];
@@ -232,6 +246,17 @@
 }
 
 /*******************************************************************************
+ * Get the current CPU bit mask from GICD_ITARGETSR0
+ ******************************************************************************/
+static unsigned int arm_gic_get_cpuif_id(void)
+{
+	unsigned int val;
+
+	val = gicd_read_itargetsr(g_gicd_base, 0);
+	return val & GIC_TARGET_CPU_MASK;
+}
+
+/*******************************************************************************
  * 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.
@@ -239,6 +264,7 @@
 static void arm_gic_distif_setup(void)
 {
 	unsigned int num_ints, ctlr, index, irq_num;
+	uint8_t target_cpu;
 
 	/* Disable the distributor before going further */
 	assert(g_gicd_base);
@@ -247,16 +273,24 @@
 	gicd_write_ctlr(g_gicd_base, ctlr);
 
 	/*
-	 * Mark out non-secure interrupts. Calculate number of
-	 * IGROUPR registers to consider. Will be equal to the
-	 * number of IT_LINES
+	 * Mark out non-secure SPI interrupts. The number of interrupts is
+	 * calculated as 32 * (IT_LINES + 1). We do 32 at a time.
 	 */
 	num_ints = gicd_read_typer(g_gicd_base) & IT_LINES_NO_MASK;
-	num_ints++;
-	for (index = 0; index < num_ints; index++)
-		gicd_write_igroupr(g_gicd_base, index << IGROUPR_SHIFT, ~0);
+	num_ints = (num_ints + 1) << 5;
+	for (index = MIN_SPI_ID; index < num_ints; index += 32)
+		gicd_write_igroupr(g_gicd_base, index, ~0);
+
+	/* Setup SPI priorities doing four at a time */
+	for (index = MIN_SPI_ID; index < num_ints; index += 4) {
+		gicd_write_ipriorityr(g_gicd_base, index,
+				GICD_IPRIORITYR_DEF_VAL);
+	}
 
-	/* Configure secure interrupts now */
+	/* Read the target CPU mask */
+	target_cpu = arm_gic_get_cpuif_id();
+
+	/* Configure SPI secure interrupts now */
 	assert(g_irq_sec_ptr);
 	for (index = 0; index < g_num_irqs; index++) {
 		irq_num = g_irq_sec_ptr[index];
@@ -265,11 +299,16 @@
 			gicd_clr_igroupr(g_gicd_base, irq_num);
 			gicd_set_ipriorityr(g_gicd_base, irq_num,
 				GIC_HIGHEST_SEC_PRIORITY);
-			gicd_set_itargetsr(g_gicd_base, irq_num,
-					platform_get_core_pos(read_mpidr()));
+			gicd_set_itargetsr(g_gicd_base, irq_num, target_cpu);
 			gicd_set_isenabler(g_gicd_base, irq_num);
 		}
 	}
+
+	/*
+	 * Configure the SGI and PPI. This is done in a separated function
+	 * because each CPU is responsible for initializing its own private
+	 * interrupts.
+	 */
 	arm_gic_pcpu_distif_setup();
 
 	gicd_write_ctlr(g_gicd_base, ctlr | ENABLE_GRP0);
@@ -285,13 +324,22 @@
 		unsigned int num_irqs
 		)
 {
+	unsigned int val;
+
 	assert(gicc_base);
 	assert(gicd_base);
-	assert(gicr_base);
 	assert(irq_sec_ptr);
+
 	g_gicc_base = gicc_base;
 	g_gicd_base = gicd_base;
-	g_gicr_base = gicr_base;
+
+	val = gicc_read_iidr(g_gicc_base);
+
+	if (((val >> GICC_IIDR_ARCH_SHIFT) & GICC_IIDR_ARCH_MASK) >= 3) {
+		assert(gicr_base);
+		g_gicr_base = gicr_base;
+	}
+
 	g_irq_sec_ptr = irq_sec_ptr;
 	g_num_irqs = num_irqs;
 }
diff --git a/drivers/arm/gic/gic_v2.c b/drivers/arm/gic/gic_v2.c
index 27a39b9..41603a9 100644
--- a/drivers/arm/gic/gic_v2.c
+++ b/drivers/arm/gic/gic_v2.c
@@ -283,13 +283,12 @@
 	mmio_write_32(reg, reg_val);
 }
 
-void gicd_set_itargetsr(unsigned int base, unsigned int id, unsigned int iface)
+void gicd_set_itargetsr(unsigned int base, unsigned int id, unsigned int target)
 {
 	unsigned byte_off = id & ((1 << ITARGETSR_SHIFT) - 1);
 	unsigned int reg_val = gicd_read_itargetsr(base, id);
 
-	gicd_write_itargetsr(base, id, reg_val |
-			     (1 << iface) << (byte_off << 3));
+	gicd_write_itargetsr(base, id, reg_val | (target << (byte_off << 3)));
 }
 
 /*******************************************************************************
diff --git a/drivers/arm/tzc400/tzc400.c b/drivers/arm/tzc400/tzc400.c
index 3ab1f31..df52c9c 100644
--- a/drivers/arm/tzc400/tzc400.c
+++ b/drivers/arm/tzc400/tzc400.c
@@ -243,7 +243,7 @@
 
 	/* Assign the region to a filter and set secure attributes */
 	tzc_write_region_attributes(tzc.base, region,
-		(sec_attr << REGION_ATTRIBUTES_SEC_SHIFT) | filters);
+		(sec_attr << REG_ATTR_SEC_SHIFT) | filters);
 
 	/*
 	 * Specify which non-secure devices have permission to access this
diff --git a/include/drivers/arm/gic_v2.h b/include/drivers/arm/gic_v2.h
index 4c6b0dc..a2d3eee 100644
--- a/include/drivers/arm/gic_v2.h
+++ b/include/drivers/arm/gic_v2.h
@@ -48,6 +48,7 @@
 #define GIC_HIGHEST_NS_PRIORITY	128
 #define GIC_LOWEST_NS_PRIORITY	254 /* 255 would disable an interrupt */
 #define GIC_SPURIOUS_INTERRUPT	1023
+#define GIC_TARGET_CPU_MASK	0xff
 
 #define ENABLE_GRP0		(1 << 0)
 #define ENABLE_GRP1		(1 << 1)
diff --git a/include/drivers/arm/tzc400.h b/include/drivers/arm/tzc400.h
index ff8b49a..d62e67b 100644
--- a/include/drivers/arm/tzc400.h
+++ b/include/drivers/arm/tzc400.h
@@ -126,9 +126,12 @@
 #define FAIL_ID_ID_SHIFT		0
 
 /* Used along with 'tzc_region_attributes_t' below */
-#define REGION_ATTRIBUTES_SEC_SHIFT	30
-#define REGION_ATTRIBUTES_F_EN_SHIFT	0
-#define REGION_ATTRIBUTES_F_EN_MASK	0xf
+#define REG_ATTR_SEC_SHIFT		30
+#define REG_ATTR_F_EN_SHIFT		0
+#define REG_ATTR_F_EN_MASK		0xf
+#define REG_ATTR_FILTER_BIT(x)		((1 << x) << REG_ATTR_F_EN_SHIFT)
+#define REG_ATTR_FILTER_BIT_ALL		(REG_ATTR_F_EN_MASK << \
+					REG_ATTR_F_EN_SHIFT)
 
 #define REGION_ID_ACCESS_NSAID_WR_EN_SHIFT	16
 #define REGION_ID_ACCESS_NSAID_RD_EN_SHIFT	0
diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h
index e5b2bf8..476c9c5 100644
--- a/include/lib/aarch64/arch.h
+++ b/include/lib/aarch64/arch.h
@@ -38,7 +38,9 @@
 #define MIDR_IMPL_MASK		0xff
 #define MIDR_IMPL_SHIFT		0x18
 #define MIDR_VAR_SHIFT		20
+#define MIDR_VAR_BITS		4
 #define MIDR_REV_SHIFT		0
+#define MIDR_REV_BITS		4
 #define MIDR_PN_MASK		0xfff
 #define MIDR_PN_SHIFT		0x4
 
diff --git a/lib/aarch64/cache_helpers.S b/lib/aarch64/cache_helpers.S
index 1c80550..dc60102 100644
--- a/lib/aarch64/cache_helpers.S
+++ b/lib/aarch64/cache_helpers.S
@@ -35,6 +35,9 @@
 	.globl	inv_dcache_range
 	.globl	dcsw_op_louis
 	.globl	dcsw_op_all
+	.globl	dcsw_op_level1
+	.globl	dcsw_op_level2
+	.globl	dcsw_op_level3
 
 	/* ------------------------------------------
 	 * Clean+Invalidate from base address till
@@ -81,6 +84,7 @@
 	 * x0: The operation type (0-2), as defined in arch.h
 	 * x3: The last cache level to operate on
 	 * x9: clidr_el1
+	 * x10: The cache level to begin operation from
 	 * and will carry out the operation on each data cache from level 0
 	 * to the level in x3 in sequence
 	 *
@@ -93,12 +97,12 @@
 	mrs	x9, clidr_el1
 	ubfx	x3, x9, \shift, \fw
 	lsl	x3, x3, \ls
+	mov	x10, xzr
 	b	do_dcsw_op
 	.endm
 
 func do_dcsw_op
 	cbz	x3, exit
-	mov	x10, xzr
 	adr	x14, dcsw_loop_table	// compute inner loop address
 	add	x14, x14, x0, lsl #5	// inner loop is 8x32-bit instructions
 	mov	x0, x9
@@ -163,3 +167,45 @@
 
 func dcsw_op_all
 	dcsw_op #LOC_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT
+
+	/* ---------------------------------------------------------------
+	 *  Helper macro for data cache operations by set/way for the
+	 *  level specified
+	 * ---------------------------------------------------------------
+	 */
+	.macro dcsw_op_level level
+	mrs	x9, clidr_el1
+	mov	x3, \level
+	sub	x10, x3, #2
+	b	do_dcsw_op
+	.endm
+
+	/* ---------------------------------------------------------------
+	 * Data cache operations by set/way for level 1 cache
+	 *
+	 * The main function, do_dcsw_op requires:
+	 * x0: The operation type (0-2), as defined in arch.h
+	 * ---------------------------------------------------------------
+	 */
+func dcsw_op_level1
+	dcsw_op_level #(1 << LEVEL_SHIFT)
+
+	/* ---------------------------------------------------------------
+	 * Data cache operations by set/way for level 2 cache
+	 *
+	 * The main function, do_dcsw_op requires:
+	 * x0: The operation type (0-2), as defined in arch.h
+	 * ---------------------------------------------------------------
+	 */
+func dcsw_op_level2
+	dcsw_op_level #(2 << LEVEL_SHIFT)
+
+	/* ---------------------------------------------------------------
+	 * Data cache operations by set/way for level 3 cache
+	 *
+	 * The main function, do_dcsw_op requires:
+	 * x0: The operation type (0-2), as defined in arch.h
+	 * ---------------------------------------------------------------
+	 */
+func dcsw_op_level3
+	dcsw_op_level #(3 << LEVEL_SHIFT)
diff --git a/lib/cpus/aarch64/cortex_a53.S b/lib/cpus/aarch64/cortex_a53.S
index 722ce7a..ec18464 100644
--- a/lib/cpus/aarch64/cortex_a53.S
+++ b/lib/cpus/aarch64/cortex_a53.S
@@ -77,11 +77,11 @@
 	bl	cortex_a53_disable_dcache
 
 	/* ---------------------------------------------
-	 * Flush L1 cache to PoU.
+	 * Flush L1 caches.
 	 * ---------------------------------------------
 	 */
 	mov	x0, #DCCISW
-	bl	dcsw_op_louis
+	bl	dcsw_op_level1
 
 	/* ---------------------------------------------
 	 * Come out of intra cluster coherency
@@ -100,17 +100,24 @@
 	bl	cortex_a53_disable_dcache
 
 	/* ---------------------------------------------
+	 * Flush L1 caches.
+	 * ---------------------------------------------
+	 */
+	mov	x0, #DCCISW
+	bl	dcsw_op_level1
+
+	/* ---------------------------------------------
 	 * Disable the optional ACP.
 	 * ---------------------------------------------
 	 */
 	bl	plat_disable_acp
 
 	/* ---------------------------------------------
-	 * Flush L1 and L2 caches to PoC.
+	 * Flush L2 caches.
 	 * ---------------------------------------------
 	 */
 	mov	x0, #DCCISW
-	bl	dcsw_op_all
+	bl	dcsw_op_level2
 
 	/* ---------------------------------------------
 	 * Come out of intra cluster coherency
diff --git a/lib/cpus/aarch64/cortex_a57.S b/lib/cpus/aarch64/cortex_a57.S
index eed1bbb..dab16d7 100644
--- a/lib/cpus/aarch64/cortex_a57.S
+++ b/lib/cpus/aarch64/cortex_a57.S
@@ -57,7 +57,7 @@
 	bic	x0, x0, x1
 	msr	CPUECTLR_EL1, x0
 	isb
-	dsb	sy
+	dsb	ish
 	ret
 
 	/* ---------------------------------------------
@@ -81,33 +81,79 @@
 	dsb	sy
 	ret
 
-func cortex_a57_reset_func
-#if ERRATA_A57_806969 || ERRATA_A57_813420
-	/* ---------------------------------------------
-	 * Ensure that the following errata is only
-	 * applied on r0p0 parts.
-	 * ---------------------------------------------
+	/* --------------------------------------------------
+	 * Errata Workaround for Cortex A57 Errata #806969.
+	 * This applies only to revision r0p0 of Cortex A57.
+	 * Inputs:
+	 * x0: variant[4:7] and revision[0:3] of current cpu.
+	 * --------------------------------------------------
 	 */
-#if ASM_ASSERTION
-	mrs	x0, midr_el1
-	ubfx	x1, x0, #MIDR_VAR_SHIFT, #4
-	ubfx	x2, x0, #MIDR_REV_SHIFT, #4
-	orr	x0, x1, x2
-	cmp	x0, #0
-	ASM_ASSERT(eq)
+func errata_a57_806969_wa
+	/*
+	 * Compare x0 against revision r0p0
+	 */
+	cbz	x0, apply_806969
+#if DEBUG
+	b	print_revision_warning
+#else
+	ret
 #endif
-	mov	x1, xzr
-#if ERRATA_A57_806969
+apply_806969:
+	mrs	x1, CPUACTLR_EL1
 	orr	x1, x1, #CPUACTLR_NO_ALLOC_WBWA
+	msr	CPUACTLR_EL1, x1
+	ret
+
+
+	/* ---------------------------------------------------
+	 * Errata Workaround for Cortex A57 Errata #813420.
+	 * This applies only to revision r0p0 of Cortex A57.
+	 * Inputs:
+	 * x0: variant[4:7] and revision[0:3] of current cpu.
+	 * ---------------------------------------------------
+	 */
+func errata_a57_813420_wa
+	/*
+	 * Compare x0 against revision r0p0
+	 */
+	cbz	x0, apply_813420
+#if DEBUG
+	b	print_revision_warning
+#else
+	ret
 #endif
-#if ERRATA_A57_813420
+apply_813420:
+	mrs	x1, CPUACTLR_EL1
 	orr	x1, x1, #CPUACTLR_DCC_AS_DCCI
-#endif
-	mrs	x0, CPUACTLR_EL1
-	orr	x0, x0, x1
-	msr	CPUACTLR_EL1, x0
+	msr	CPUACTLR_EL1, x1
+	ret
+
+	/* -------------------------------------------------
+	 * The CPU Ops reset function for Cortex-A57.
+	 * -------------------------------------------------
+	 */
+func cortex_a57_reset_func
+	mov	x19, x30
+	mrs	x0, midr_el1
+
+	/*
+	 * Extract the variant[20:23] and revision[0:3] from x0
+	 * and pack it in x20[0:7] as variant[4:7] and revision[0:3].
+	 * First extract x0[16:23] to x20[0:7] and zero fill the rest.
+	 * Then extract x0[0:3] into x20[0:3] retaining other bits.
+	 */
+	ubfx	x20, x0, #(MIDR_VAR_SHIFT - MIDR_REV_BITS), #(MIDR_REV_BITS + MIDR_VAR_BITS)
+	bfxil	x20, x0, #MIDR_REV_SHIFT, #MIDR_REV_BITS
+
+#if ERRATA_A57_806969
+	mov	x0, x20
+	bl	errata_a57_806969_wa
 #endif
 
+#if ERRATA_A57_813420
+	mov	x0, x20
+	bl	errata_a57_813420_wa
+#endif
 	/* ---------------------------------------------
 	 * As a bare minimum enable the SMP bit.
 	 * ---------------------------------------------
@@ -116,8 +162,12 @@
 	orr	x0, x0, #CPUECTLR_SMP_BIT
 	msr	CPUECTLR_EL1, x0
 	isb
-	ret
+	ret	x19
 
+	/* ----------------------------------------------------
+	 * The CPU Ops core power down function for Cortex-A57.
+	 * ----------------------------------------------------
+	 */
 func cortex_a57_core_pwr_dwn
 	mov	x18, x30
 
@@ -134,11 +184,11 @@
 	bl	cortex_a57_disable_l2_prefetch
 
 	/* ---------------------------------------------
-	 * Flush L1 cache to PoU.
+	 * Flush L1 caches.
 	 * ---------------------------------------------
 	 */
 	mov	x0, #DCCISW
-	bl	dcsw_op_louis
+	bl	dcsw_op_level1
 
 	/* ---------------------------------------------
 	 * Come out of intra cluster coherency
@@ -153,6 +203,10 @@
 	mov	x30, x18
 	b	cortex_a57_disable_ext_debug
 
+	/* -------------------------------------------------------
+	 * The CPU Ops cluster power down function for Cortex-A57.
+	 * -------------------------------------------------------
+	 */
 func cortex_a57_cluster_pwr_dwn
 	mov	x18, x30
 
@@ -168,18 +222,26 @@
 	 */
 	bl	cortex_a57_disable_l2_prefetch
 
+#if !SKIP_A57_L1_FLUSH_PWR_DWN
+	/* -------------------------------------------------
+	 * Flush the L1 caches.
+	 * -------------------------------------------------
+	 */
+	mov	x0, #DCCISW
+	bl	dcsw_op_level1
+#endif
 	/* ---------------------------------------------
 	 * Disable the optional ACP.
 	 * ---------------------------------------------
 	 */
 	bl	plat_disable_acp
 
-	/* ---------------------------------------------
-	 * Flush L1 and L2 caches to PoC.
-	 * ---------------------------------------------
+	/* -------------------------------------------------
+	 * Flush the L2 caches.
+	 * -------------------------------------------------
 	 */
 	mov	x0, #DCCISW
-	bl	dcsw_op_all
+	bl	dcsw_op_level2
 
 	/* ---------------------------------------------
 	 * Come out of intra cluster coherency
diff --git a/lib/cpus/aarch64/cpu_helpers.S b/lib/cpus/aarch64/cpu_helpers.S
index 46584b3..f053d44 100644
--- a/lib/cpus/aarch64/cpu_helpers.S
+++ b/lib/cpus/aarch64/cpu_helpers.S
@@ -45,7 +45,7 @@
 	 */
 	.globl	reset_handler
 func reset_handler
-	mov	x10, x30
+	mov	x19, x30
 
 	bl	plat_reset_handler
 
@@ -58,10 +58,11 @@
 
 	/* Get the cpu_ops reset handler */
 	ldr	x2, [x0, #CPU_RESET_FUNC]
+	mov	x30, x19
 	cbz	x2, 1f
-	blr	x2
+	br	x2
 1:
-	ret	x10
+	ret
 
 #endif /* IMAGE_BL1 || (IMAGE_BL31 && RESET_TO_BL31) */
 
@@ -191,3 +192,29 @@
 	sub	x0, x4, #(CPU_OPS_SIZE + CPU_MIDR)
 error_exit:
 	ret
+
+#if DEBUG
+	/*
+	 * This function prints a warning message to the crash console
+	 * if the CPU revision/part number does not match the errata
+	 * workaround enabled in the build.
+	 * Clobber: x30, x0 - x5
+	 */
+.section .rodata.rev_warn_str, "aS"
+rev_warn_str:
+	.asciz "Warning: Skipping Errata workaround for non matching CPU revision number.\n"
+
+	.globl	print_revision_warning
+func print_revision_warning
+	mov	x5, x30
+	/* Ensure the console is initialized */
+	bl	plat_crash_console_init
+	/* Check if the console is initialized */
+	cbz	x0, 1f
+	/* The console is initialized */
+	adr	x4, rev_warn_str
+	bl	asm_print_str
+1:
+	ret	x5
+#endif
+
diff --git a/lib/cpus/cpu-errata.mk b/lib/cpus/cpu-ops.mk
similarity index 88%
rename from lib/cpus/cpu-errata.mk
rename to lib/cpus/cpu-ops.mk
index 79f0156..1c5512e 100644
--- a/lib/cpus/cpu-errata.mk
+++ b/lib/cpus/cpu-ops.mk
@@ -28,6 +28,15 @@
 # POSSIBILITY OF SUCH DAMAGE.
 #
 
+# Cortex A57 specific optimisation to skip L1 cache flush when
+# cluster is powered down.
+SKIP_A57_L1_FLUSH_PWR_DWN	?=0
+
+# Process SKIP_A57_L1_FLUSH_PWR_DWN flag
+$(eval $(call assert_boolean,SKIP_A57_L1_FLUSH_PWR_DWN))
+$(eval $(call add_define,SKIP_A57_L1_FLUSH_PWR_DWN))
+
+
 # CPU Errata Build flags. These should be enabled by the
 # platform if the errata needs to be applied.
 
diff --git a/lib/locks/bakery/bakery_lock.c b/lib/locks/bakery/bakery_lock.c
index 877f526..7e71dec 100644
--- a/lib/locks/bakery/bakery_lock.c
+++ b/lib/locks/bakery/bakery_lock.c
@@ -107,6 +107,7 @@
 	++my_ticket;
 	bakery->number[me] = my_ticket;
 	bakery->entering[me] = 0;
+	dsb();
 	sev();
 
 	return my_ticket;
@@ -189,5 +190,6 @@
 	 */
 	bakery->owner = NO_OWNER;
 	bakery->number[me] = 0;
+	dsb();
 	sev();
 }
diff --git a/plat/fvp/aarch64/fvp_common.c b/plat/fvp/aarch64/fvp_common.c
index e393ced..987f48f 100644
--- a/plat/fvp/aarch64/fvp_common.c
+++ b/plat/fvp/aarch64/fvp_common.c
@@ -50,8 +50,8 @@
  ******************************************************************************/
 plat_config_t plat_config;
 
-#define MAP_SHARED_RAM	MAP_REGION_FLAT(FVP_SHARED_RAM_BASE,		\
-					FVP_SHARED_RAM_SIZE,		\
+#define MAP_SHARED_RAM	MAP_REGION_FLAT(FVP_SHARED_MEM_BASE,		\
+					FVP_SHARED_MEM_SIZE,		\
 					MT_MEMORY | MT_RW | MT_SECURE)
 
 #define MAP_FLASH0	MAP_REGION_FLAT(FLASH0_BASE,			\
diff --git a/plat/fvp/bl2_fvp_setup.c b/plat/fvp/bl2_fvp_setup.c
index 2c26d97..67f89bc 100644
--- a/plat/fvp/bl2_fvp_setup.c
+++ b/plat/fvp/bl2_fvp_setup.c
@@ -74,7 +74,7 @@
 
 /* Assert that BL3-1 parameters fit in shared memory */
 CASSERT((PARAMS_BASE + sizeof(bl2_to_bl31_params_mem_t)) <
-	(FVP_SHARED_RAM_BASE + FVP_SHARED_RAM_SIZE),
+	(FVP_SHARED_MEM_BASE + FVP_SHARED_MEM_SIZE),
 	assert_bl31_params_do_not_fit_in_shared_memory);
 
 /*******************************************************************************
diff --git a/plat/fvp/fvp_def.h b/plat/fvp/fvp_def.h
index 9914f69..99c23d8 100644
--- a/plat/fvp/fvp_def.h
+++ b/plat/fvp/fvp_def.h
@@ -35,7 +35,7 @@
 #define FIP_IMAGE_NAME			"fip.bin"
 #define FVP_PRIMARY_CPU			0x0
 
-/* Memory location options for Shared data and TSP in FVP */
+/* Memory location options for TSP */
 #define FVP_IN_TRUSTED_SRAM		0
 #define FVP_IN_TRUSTED_DRAM		1
 
@@ -46,8 +46,13 @@
 #define FVP_TRUSTED_ROM_BASE	0x00000000
 #define FVP_TRUSTED_ROM_SIZE	0x04000000	/* 64 MB */
 
-#define FVP_TRUSTED_SRAM_BASE	0x04000000
-#define FVP_TRUSTED_SRAM_SIZE	0x00040000	/* 256 KB */
+/* The first 4KB of Trusted SRAM are used as shared memory */
+#define FVP_SHARED_MEM_BASE	0x04000000
+#define FVP_SHARED_MEM_SIZE	0x00001000	/* 4 KB */
+
+/* The remaining Trusted SRAM is used to load the BL images */
+#define FVP_TRUSTED_SRAM_BASE	0x04001000
+#define FVP_TRUSTED_SRAM_SIZE	0x0003F000	/* 252 KB */
 
 #define FVP_TRUSTED_DRAM_BASE	0x06000000
 #define FVP_TRUSTED_DRAM_SIZE	0x02000000	/* 32 MB */
@@ -74,28 +79,6 @@
 #define NSRAM_BASE		0x2e000000
 #define NSRAM_SIZE		0x10000
 
-/* 4KB shared memory */
-#define FVP_SHARED_RAM_SIZE	0x1000
-
-/* Location of shared memory */
-#if (FVP_SHARED_DATA_LOCATION_ID == FVP_IN_TRUSTED_DRAM)
-/* Shared memory at the base of Trusted DRAM */
-# define FVP_SHARED_RAM_BASE		FVP_TRUSTED_DRAM_BASE
-# define FVP_TRUSTED_SRAM_LIMIT		(FVP_TRUSTED_SRAM_BASE \
-					+ FVP_TRUSTED_SRAM_SIZE)
-#elif (FVP_SHARED_DATA_LOCATION_ID == FVP_IN_TRUSTED_SRAM)
-# if (FVP_TSP_RAM_LOCATION_ID == FVP_IN_TRUSTED_DRAM)
-#  error "Shared data in Trusted SRAM and TSP in Trusted DRAM is not supported"
-# endif
-/* Shared memory at the top of the Trusted SRAM */
-# define FVP_SHARED_RAM_BASE		(FVP_TRUSTED_SRAM_BASE \
-					+ FVP_TRUSTED_SRAM_SIZE \
-					- FVP_SHARED_RAM_SIZE)
-# define FVP_TRUSTED_SRAM_LIMIT		FVP_SHARED_RAM_BASE
-#else
-# error "Unsupported FVP_SHARED_DATA_LOCATION_ID value"
-#endif
-
 #define DRAM1_BASE		0x80000000ull
 #define DRAM1_SIZE		0x80000000ull
 #define DRAM1_END		(DRAM1_BASE + DRAM1_SIZE - 1)
@@ -268,7 +251,7 @@
  ******************************************************************************/
 
 /* Entrypoint mailboxes */
-#define MBOX_BASE		FVP_SHARED_RAM_BASE
+#define MBOX_BASE		FVP_SHARED_MEM_BASE
 #define MBOX_SIZE		0x200
 
 /* Base address where parameters to BL31 are stored */
diff --git a/plat/fvp/include/platform_def.h b/plat/fvp/include/platform_def.h
index 32f070f..5364a3d 100644
--- a/plat/fvp/include/platform_def.h
+++ b/plat/fvp/include/platform_def.h
@@ -93,12 +93,13 @@
 #define BL1_RO_LIMIT			(FVP_TRUSTED_ROM_BASE \
 					+ FVP_TRUSTED_ROM_SIZE)
 /*
- * Put BL1 RW at the top of the Trusted SRAM (just below the shared memory, if
- * present). BL1_RW_BASE is calculated using the current BL1 RW debug size plus
- * a little space for growth.
+ * Put BL1 RW at the top of the Trusted SRAM. BL1_RW_BASE is calculated using
+ * the current BL1 RW debug size plus a little space for growth.
  */
-#define BL1_RW_BASE			(FVP_TRUSTED_SRAM_LIMIT - 0x6000)
-#define BL1_RW_LIMIT			FVP_TRUSTED_SRAM_LIMIT
+#define BL1_RW_BASE			(FVP_TRUSTED_SRAM_BASE \
+					+ FVP_TRUSTED_SRAM_SIZE - 0x6000)
+#define BL1_RW_LIMIT			(FVP_TRUSTED_SRAM_BASE \
+					+ FVP_TRUSTED_SRAM_SIZE)
 
 /*******************************************************************************
  * BL2 specific defines.
@@ -114,13 +115,14 @@
  * BL31 specific defines.
  ******************************************************************************/
 /*
- * Put BL3-1 at the top of the Trusted SRAM (just below the shared memory, if
- * present). BL31_BASE is calculated using the current BL3-1 debug size plus a
- * little space for growth.
+ * Put BL3-1 at the top of the Trusted SRAM. BL31_BASE is calculated using the
+ * current BL3-1 debug size plus a little space for growth.
  */
-#define BL31_BASE			(FVP_TRUSTED_SRAM_LIMIT - 0x1D000)
+#define BL31_BASE			(FVP_TRUSTED_SRAM_BASE \
+					+ FVP_TRUSTED_SRAM_SIZE - 0x1D000)
 #define BL31_PROGBITS_LIMIT		BL1_RW_BASE
-#define BL31_LIMIT			FVP_TRUSTED_SRAM_LIMIT
+#define BL31_LIMIT			(FVP_TRUSTED_SRAM_BASE \
+					+ FVP_TRUSTED_SRAM_SIZE)
 
 /*******************************************************************************
  * BL32 specific defines.
@@ -137,8 +139,7 @@
 #elif FVP_TSP_RAM_LOCATION_ID == FVP_IN_TRUSTED_DRAM
 # define TSP_SEC_MEM_BASE		FVP_TRUSTED_DRAM_BASE
 # define TSP_SEC_MEM_SIZE		FVP_TRUSTED_DRAM_SIZE
-# define BL32_BASE			(FVP_TRUSTED_DRAM_BASE \
-					+ FVP_SHARED_RAM_SIZE)
+# define BL32_BASE			FVP_TRUSTED_DRAM_BASE
 # define BL32_LIMIT			(FVP_TRUSTED_DRAM_BASE + (1 << 21))
 #else
 # error "Unsupported FVP_TSP_RAM_LOCATION_ID value"
diff --git a/plat/fvp/platform.mk b/plat/fvp/platform.mk
index e7c06a8..fdcee50 100644
--- a/plat/fvp/platform.mk
+++ b/plat/fvp/platform.mk
@@ -28,17 +28,6 @@
 # POSSIBILITY OF SUCH DAMAGE.
 #
 
-# Shared memory may be allocated at the top of Trusted SRAM (tsram) or at the
-# base of Trusted SRAM (tdram)
-FVP_SHARED_DATA_LOCATION	:=	tsram
-ifeq (${FVP_SHARED_DATA_LOCATION}, tsram)
-  FVP_SHARED_DATA_LOCATION_ID := FVP_IN_TRUSTED_SRAM
-else ifeq (${FVP_SHARED_DATA_LOCATION}, tdram)
-  FVP_SHARED_DATA_LOCATION_ID := FVP_IN_TRUSTED_DRAM
-else
-  $(error "Unsupported FVP_SHARED_DATA_LOCATION value")
-endif
-
 # On FVP, the TSP can execute either from Trusted SRAM or Trusted DRAM.
 # Trusted SRAM is the default.
 FVP_TSP_RAM_LOCATION	:=	tsram
@@ -50,14 +39,7 @@
   $(error "Unsupported FVP_TSP_RAM_LOCATION value")
 endif
 
-ifeq (${FVP_SHARED_DATA_LOCATION}, tsram)
-  ifeq (${FVP_TSP_RAM_LOCATION}, tdram)
-    $(error Shared data in Trusted SRAM and TSP in Trusted DRAM is not supported)
-  endif
-endif
-
 # Process flags
-$(eval $(call add_define,FVP_SHARED_DATA_LOCATION_ID))
 $(eval $(call add_define,FVP_TSP_RAM_LOCATION_ID))
 
 PLAT_INCLUDES		:=	-Iplat/fvp/include/
diff --git a/plat/juno/aarch64/juno_common.c b/plat/juno/aarch64/juno_common.c
index 401f5fe..8129b05 100644
--- a/plat/juno/aarch64/juno_common.c
+++ b/plat/juno/aarch64/juno_common.c
@@ -29,6 +29,7 @@
  */
 
 #include <arch_helpers.h>
+#include <arm_gic.h>
 #include <assert.h>
 #include <bl_common.h>
 #include <debug.h>
@@ -60,9 +61,14 @@
 					DEVICE1_SIZE,			\
 					MT_DEVICE | MT_RW | MT_SECURE)
 
-#define MAP_DRAM	MAP_REGION_FLAT(DRAM_BASE,			\
-					DRAM_SIZE,			\
+#define MAP_NS_DRAM	MAP_REGION_FLAT(DRAM_NS_BASE,			\
+					DRAM_NS_SIZE,			\
 					MT_MEMORY | MT_RW | MT_NS)
+
+#define MAP_TSP_MEM	MAP_REGION_FLAT(TSP_SEC_MEM_BASE, 		\
+					TSP_SEC_MEM_SIZE,		\
+					MT_MEMORY | MT_RW | MT_SECURE)
+
 /*
  * Table of regions for different BL stages to map using the MMU.
  * This doesn't include Trusted RAM as the 'mem_layout' argument passed to
@@ -85,7 +91,8 @@
 	MAP_IOFPGA,
 	MAP_DEVICE0,
 	MAP_DEVICE1,
-	MAP_DRAM,
+	MAP_NS_DRAM,
+	MAP_TSP_MEM,
 	{0}
 };
 #endif
@@ -107,6 +114,28 @@
 };
 #endif
 
+/* Array of secure interrupts to be configured by the gic driver */
+const unsigned int irq_sec_array[] = {
+	IRQ_MHU,
+	IRQ_GPU_SMMU_0,
+	IRQ_GPU_SMMU_1,
+	IRQ_ETR_SMMU,
+	IRQ_TZC400,
+	IRQ_TZ_WDOG,
+	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
+};
+
+const unsigned int num_sec_irqs = sizeof(irq_sec_array) /
+	sizeof(irq_sec_array[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
@@ -157,3 +186,8 @@
 
 	return counter_base_frequency;
 }
+
+void plat_gic_init(void)
+{
+	arm_gic_init(GICC_BASE, GICD_BASE, 0, irq_sec_array, num_sec_irqs);
+}
diff --git a/plat/juno/bl1_plat_setup.c b/plat/juno/bl1_plat_setup.c
index 5804682..e27e394 100644
--- a/plat/juno/bl1_plat_setup.c
+++ b/plat/juno/bl1_plat_setup.c
@@ -37,7 +37,6 @@
 #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"
@@ -150,36 +149,6 @@
 }
 
 
-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 */
 
@@ -200,7 +169,6 @@
 void bl1_platform_setup(void)
 {
 	init_nic400();
-	init_tzc400();
 	init_pcie();
 
 	/* Initialise the IO layer and register platform IO devices */
diff --git a/plat/juno/bl2_plat_setup.c b/plat/juno/bl2_plat_setup.c
index 717cfbb..900a587 100644
--- a/plat/juno/bl2_plat_setup.c
+++ b/plat/juno/bl2_plat_setup.c
@@ -162,6 +162,9 @@
 
 	/* Setup the BL2 memory layout */
 	bl2_tzram_layout = *mem_layout;
+
+	/* Initialise the IO layer and register platform IO devices */
+	io_setup();
 }
 
 /*******************************************************************************
@@ -171,8 +174,8 @@
  ******************************************************************************/
 void bl2_platform_setup(void)
 {
-	/* Initialise the IO layer and register platform IO devices */
-	io_setup();
+	/* Initialize the secure environment */
+	plat_security_setup();
 }
 
 /* Flush the TF params and the TF plat params */
@@ -309,8 +312,8 @@
  ******************************************************************************/
 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;
+	bl33_meminfo->total_base = DRAM_NS_BASE;
+	bl33_meminfo->total_size = DRAM_NS_SIZE;
+	bl33_meminfo->free_base = DRAM_NS_BASE;
+	bl33_meminfo->free_size = DRAM_NS_SIZE;
 }
diff --git a/plat/juno/bl31_plat_setup.c b/plat/juno/bl31_plat_setup.c
index 4a92d44..c450462 100644
--- a/plat/juno/bl31_plat_setup.c
+++ b/plat/juno/bl31_plat_setup.c
@@ -29,6 +29,7 @@
  */
 
 #include <arch.h>
+#include <arm_gic.h>
 #include <assert.h>
 #include <bl31.h>
 #include <bl_common.h>
@@ -151,7 +152,8 @@
 	mhu_secure_init();
 
 	/* Initialize the gic cpu and distributor interfaces */
-	gic_setup();
+	plat_gic_init();
+	arm_gic_setup();
 
 	/* Enable and initialize the System level generic timer */
 	mmio_write_32(SYS_CNTCTL_BASE + CNTCR_OFF, CNTCR_FCREQ(0) | CNTCR_EN);
diff --git a/plat/juno/include/platform_def.h b/plat/juno/include/platform_def.h
index 6d9d0fb..e746d02 100644
--- a/plat/juno/include/platform_def.h
+++ b/plat/juno/include/platform_def.h
@@ -125,10 +125,20 @@
 /*******************************************************************************
  * 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
+#if (PLAT_TSP_LOCATION_ID == PLAT_TRUSTED_SRAM_ID)
+# 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
+#elif (PLAT_TSP_LOCATION_ID == PLAT_DRAM_ID)
+# define TSP_SEC_MEM_BASE		DRAM_SEC_BASE
+# define TSP_SEC_MEM_SIZE		(DRAM_SEC_SIZE - DRAM_SCP_SIZE)
+# define BL32_BASE			DRAM_SEC_BASE
+# define BL32_LIMIT			(DRAM_SEC_BASE + DRAM_SEC_SIZE - \
+					DRAM_SCP_SIZE)
+#else
+# error "Unsupported PLAT_TSP_LOCATION_ID value"
+#endif
 
 /*******************************************************************************
  * Load address of BL3-3 in the Juno port
@@ -139,7 +149,15 @@
  * Platform specific page table and MMU setup constants
  ******************************************************************************/
 #define ADDR_SPACE_SIZE			(1ull << 32)
-#define MAX_XLAT_TABLES			2
+
+#if IMAGE_BL1 || IMAGE_BL31
+# define MAX_XLAT_TABLES		2
+#endif
+
+#if IMAGE_BL2 || IMAGE_BL32
+# define MAX_XLAT_TABLES		3
+#endif
+
 #define MAX_MMAP_REGIONS		16
 
 /*******************************************************************************
diff --git a/plat/juno/juno_def.h b/plat/juno/juno_def.h
index 15296ed..88e35b0 100644
--- a/plat/juno/juno_def.h
+++ b/plat/juno/juno_def.h
@@ -37,6 +37,9 @@
 /*******************************************************************************
  * Juno memory map related constants
  ******************************************************************************/
+#define PLAT_TRUSTED_SRAM_ID	0
+#define PLAT_DRAM_ID		1
+
 #define MHU_SECURE_BASE		0x04000000
 #define MHU_SECURE_SIZE		0x00001000
 
@@ -73,6 +76,26 @@
 #define DRAM_BASE		0x80000000
 #define DRAM_SIZE		0x80000000
 
+/*
+ * DRAM at 0x8000_0000 is divided in two regions:
+ *   - Secure DRAM (default is the top 16MB except for the last 2MB, which are
+ *     used by the SCP for DDR retraining)
+ *   - Non-Secure DRAM (remaining DRAM starting at DRAM_BASE)
+ */
+
+#define DRAM_SCP_SIZE		0x00200000
+#define DRAM_SCP_BASE		(DRAM_BASE + DRAM_SIZE - DRAM_SCP_SIZE)
+
+#define DRAM_SEC_SIZE		0x00E00000
+#define DRAM_SEC_BASE		(DRAM_SCP_BASE - DRAM_SEC_SIZE)
+
+#define DRAM_NS_BASE		DRAM_BASE
+#define DRAM_NS_SIZE		(DRAM_SIZE - DRAM_SCP_SIZE - DRAM_SEC_SIZE)
+
+/* Second region of DRAM */
+#define DRAM2_BASE		0x880000000
+#define DRAM2_SIZE		0x180000000
+
 /* Memory mapped Generic timer interfaces  */
 #define SYS_CNTCTL_BASE		0x2a430000
 #define SYS_CNTREAD_BASE	0x2a800000
diff --git a/plat/juno/juno_private.h b/plat/juno/juno_private.h
index 0dac03a..14d7af4 100644
--- a/plat/juno/juno_private.h
+++ b/plat/juno/juno_private.h
@@ -83,18 +83,7 @@
 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);
+void plat_gic_init(void);
 
 /* Declarations for plat_topology.c */
 int plat_setup_topology(void);
@@ -108,6 +97,9 @@
 			  uintptr_t *dev_handle,
 			  uintptr_t *image_spec);
 
+/* Declarations for security.c */
+void plat_security_setup(void);
+
 /*
  * 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
diff --git a/plat/juno/plat_gic.c b/plat/juno/plat_gic.c
deleted file mode 100644
index 9001519..0000000
--- a/plat/juno/plat_gic.c
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * 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_pm.c b/plat/juno/plat_pm.c
index 74ce89f..adf599f 100644
--- a/plat/juno/plat_pm.c
+++ b/plat/juno/plat_pm.c
@@ -30,6 +30,7 @@
 
 #include <assert.h>
 #include <arch_helpers.h>
+#include <arm_gic.h>
 #include <debug.h>
 #include <cci400.h>
 #include <errno.h>
@@ -133,10 +134,10 @@
 
 
 	/* Enable the gic cpu interface */
-	gic_cpuif_setup(GICC_BASE);
+	arm_gic_cpuif_setup();
 
 	/* Juno todo: Is this setup only needed after a cold boot? */
-	gic_pcpu_distif_setup(GICD_BASE);
+	arm_gic_pcpu_distif_setup();
 
 	/* Clear the mailbox for this cpu. */
 	juno_program_mailbox(mpidr, 0);
@@ -155,7 +156,7 @@
 	uint32_t cluster_state = scpi_power_on;
 
 	/* Prevent interrupts from spuriously waking up this cpu */
-	gic_cpuif_deactivate(GICC_BASE);
+	arm_gic_cpuif_deactivate();
 
 	/* Cluster is to be turned off, so disable coherency */
 	if (afflvl > MPIDR_AFFLVL0) {
@@ -275,12 +276,47 @@
 }
 
 /*******************************************************************************
+ * Handler called when an affinity instance is about to enter standby.
+ ******************************************************************************/
+int32_t juno_affinst_standby(unsigned int power_state)
+{
+	unsigned int target_afflvl;
+	unsigned int scr;
+
+	/* Sanity check the requested state */
+	target_afflvl = psci_get_pstate_afflvl(power_state);
+
+	/*
+	 * It's possible to enter standby only on affinity level 0 i.e. a cpu
+	 * on the Juno. Ignore any other affinity level.
+	 */
+	if (target_afflvl != MPIDR_AFFLVL0)
+		return PSCI_E_INVALID_PARAMS;
+
+	scr = read_scr_el3();
+	/* Enable PhysicalIRQ bit for NS world to wake the CPU */
+	write_scr_el3(scr | SCR_IRQ_BIT);
+	isb();
+	dsb();
+	wfi();
+
+	/*
+	 * Restore SCR to the original value, synchronisation of scr_el3 is
+	 * done by eret while el3_exit to save some execution cycles.
+	 */
+	write_scr_el3(scr);
+
+	return PSCI_E_SUCCESS;
+}
+
+/*******************************************************************************
  * 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_standby	= juno_affinst_standby,
 	.affinst_suspend	= juno_affinst_suspend,
 	.affinst_suspend_finish	= juno_affinst_suspend_finish,
 	.system_off		= juno_system_off,
diff --git a/plat/juno/plat_security.c b/plat/juno/plat_security.c
new file mode 100644
index 0000000..64e493f
--- /dev/null
+++ b/plat/juno/plat_security.c
@@ -0,0 +1,104 @@
+/*
+ * 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 <debug.h>
+#include <tzc400.h>
+#include "juno_def.h"
+
+/*******************************************************************************
+ * Initialize the TrustZone Controller. Configure Region 0 with Secure RW access
+ * and allow Non-Secure masters full access
+ ******************************************************************************/
+static void init_tzc400(void)
+{
+	tzc_init(TZC400_BASE);
+
+	/* Disable filters. */
+	tzc_disable_filters();
+
+	/* Region 1 set to cover Non-Secure DRAM at 0x8000_0000. Apply the
+	 * same configuration to all filters in the TZC. */
+	tzc_configure_region(REG_ATTR_FILTER_BIT_ALL, 1,
+			DRAM_NS_BASE, DRAM_NS_BASE + DRAM_NS_SIZE - 1,
+			TZC_REGION_S_NONE,
+			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_CORESIGHT));
+
+	/* Region 2 set to cover Secure DRAM */
+	tzc_configure_region(REG_ATTR_FILTER_BIT_ALL, 2,
+			DRAM_SEC_BASE, DRAM_SEC_BASE + DRAM_SEC_SIZE - 1,
+			TZC_REGION_S_RDWR,
+			0);
+
+	/* Region 3 set to cover DRAM used by SCP for DDR retraining */
+	tzc_configure_region(REG_ATTR_FILTER_BIT_ALL, 3,
+			DRAM_SCP_BASE, DRAM_SCP_BASE + DRAM_SCP_SIZE - 1,
+			TZC_REGION_S_NONE,
+			TZC_REGION_ACCESS_RDWR(TZC400_NSAID_SCP));
+
+	/* Region 4 set to cover Non-Secure DRAM at 0x8_8000_0000 */
+	tzc_configure_region(REG_ATTR_FILTER_BIT_ALL, 4,
+			DRAM2_BASE, DRAM2_BASE + DRAM2_SIZE - 1,
+			TZC_REGION_S_NONE,
+			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_CORESIGHT));
+
+	/* Raise an exception if a NS device tries to access secure memory */
+	tzc_set_action(TZC_ACTION_ERR);
+
+	/* Enable filters. */
+	tzc_enable_filters();
+}
+
+/*******************************************************************************
+ * Initialize the secure environment. At this moment only the TrustZone
+ * Controller is initialized.
+ ******************************************************************************/
+void plat_security_setup(void)
+{
+	/* Initialize the TrustZone Controller */
+	init_tzc400();
+}
diff --git a/plat/juno/platform.mk b/plat/juno/platform.mk
index 4746536..6ca219d 100644
--- a/plat/juno/platform.mk
+++ b/plat/juno/platform.mk
@@ -28,6 +28,23 @@
 # POSSIBILITY OF SUCH DAMAGE.
 #
 
+# On Juno, the Secure Payload can be loaded either in Trusted SRAM (default) or
+# Secure DRAM allocated by the TrustZone Controller.
+
+PLAT_TSP_LOCATION	:=	tsram
+
+ifeq (${PLAT_TSP_LOCATION}, tsram)
+  PLAT_TSP_LOCATION_ID := PLAT_TRUSTED_SRAM_ID
+else ifeq (${PLAT_TSP_LOCATION}, dram)
+  PLAT_TSP_LOCATION_ID := PLAT_DRAM_ID
+else
+  $(error "Unsupported PLAT_TSP_LOCATION value")
+endif
+
+# Process flags
+$(eval $(call add_define,PLAT_TSP_LOCATION_ID))
+
+
 PLAT_INCLUDES		:=	-Iplat/juno/include/
 
 PLAT_BL_COMMON_SOURCES	:=	drivers/arm/pl011/pl011_console.S	\
@@ -36,6 +53,7 @@
 				drivers/io/io_storage.c			\
 				lib/aarch64/xlat_tables.c		\
 				plat/common/aarch64/plat_common.c	\
+				plat/common/plat_gic.c			\
 				plat/juno/plat_io_storage.c
 
 BL1_SOURCES		+=	drivers/arm/cci400/cci400.c		\
@@ -47,17 +65,21 @@
 				plat/juno/aarch64/plat_helpers.S	\
 				plat/juno/aarch64/juno_common.c
 
-BL2_SOURCES		+=	lib/locks/bakery/bakery_lock.c		\
+BL2_SOURCES		+=	drivers/arm/tzc400/tzc400.c		\
+				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/plat_security.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/arm_gic.c		\
 				drivers/arm/gic/gic_v2.c		\
+				drivers/arm/gic/gic_v3.c		\
 				lib/cpus/aarch64/cortex_a53.S		\
 				lib/cpus/aarch64/cortex_a57.S		\
 				plat/common/aarch64/platform_mp_stack.S	\
@@ -67,7 +89,6 @@
 				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)
@@ -80,3 +101,7 @@
 # Enable workarounds for selected Cortex-A57 erratas.
 ERRATA_A57_806969	:=	1
 ERRATA_A57_813420	:=	1
+
+# Enable option to skip L1 data cache flush during the Cortex-A57 cluster
+# power down sequence
+SKIP_A57_L1_FLUSH_PWR_DWN	:=	 1
diff --git a/plat/juno/tsp/tsp-juno.mk b/plat/juno/tsp/tsp-juno.mk
index d0d29d7..4d56ea2 100644
--- a/plat/juno/tsp/tsp-juno.mk
+++ b/plat/juno/tsp/tsp-juno.mk
@@ -29,9 +29,9 @@
 #
 
 # TSP source files specific to Juno platform
-BL32_SOURCES		+=	drivers/arm/gic/gic_v2.c		\
+BL32_SOURCES		+=	drivers/arm/gic/arm_gic.c		\
+				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
+				plat/juno/tsp/tsp_plat_setup.c
diff --git a/plat/juno/tsp/tsp_plat_setup.c b/plat/juno/tsp/tsp_plat_setup.c
index 2d4ab81..0a9d4cb 100644
--- a/plat/juno/tsp/tsp_plat_setup.c
+++ b/plat/juno/tsp/tsp_plat_setup.c
@@ -80,6 +80,7 @@
  ******************************************************************************/
 void tsp_platform_setup(void)
 {
+	plat_gic_init();
 }
 
 /*******************************************************************************