Merge pull request #445 from jcastillo-arm/jc/tf-issues/320

Add NULL pointer check before reading BL32 entry point information
diff --git a/Makefile b/Makefile
index 6c062b2..7a4be44 100644
--- a/Makefile
+++ b/Makefile
@@ -87,8 +87,8 @@
 # By default, consider that the platform's reset address is not programmable.
 # The platform Makefile is free to override this value.
 PROGRAMMABLE_RESET_ADDRESS	:= 0
-# Build flag to warn about usage of deprecated platform and framework APIs
-WARN_DEPRECATED			:= 0
+# Build flag to treat usage of deprecated platform and framework APIs as error.
+ERROR_DEPRECATED		:= 0
 
 
 ################################################################################
@@ -167,7 +167,8 @@
 				${DEFINES} ${INCLUDES}
 CFLAGS			+= 	-nostdinc -ffreestanding -Wall			\
 				-Werror -Wmissing-include-dirs			\
-				-mgeneral-regs-only -std=c99 -c -Os		\
+				-mgeneral-regs-only -mstrict-align		\
+				-std=c99 -c -Os					\
 				${DEFINES} ${INCLUDES}
 CFLAGS			+=	-ffunction-sections -fdata-sections
 
@@ -240,10 +241,15 @@
         $(info Including ${SPD_MAKE})
         include ${SPD_MAKE}
 
-        # If there's BL3-2 companion for the chosen SPD, and the SPD wants to build the
-        # BL3-2 from source, we expect that the SPD's Makefile would set NEED_BL32
-        # variable to "yes". In case the BL3-2 is a binary which needs to be included in
-        # fip, then the NEED_BL32 needs to be set and BL3-2 would need to point to the bin.
+        # If there's BL32 companion for the chosen SPD, we expect that the SPD's
+        # Makefile would set NEED_BL32 to "yes". In this case, the build system
+        # supports two mutually exclusive options:
+        # * BL32 is built from source: then BL32_SOURCES must contain the list
+        #   of source files to build BL32
+        # * BL32 is a prebuilt binary: then BL32 must point to the image file
+        #   that will be included in the FIP
+        # If both BL32_SOURCES and BL32 are defined, the binary takes precedence
+        # over the sources.
 endif
 
 
@@ -340,7 +346,7 @@
 $(eval $(call assert_boolean,TRUSTED_BOARD_BOOT))
 $(eval $(call assert_boolean,PROGRAMMABLE_RESET_ADDRESS))
 $(eval $(call assert_boolean,PSCI_EXTENDED_STATE_ID))
-$(eval $(call assert_boolean,WARN_DEPRECATED))
+$(eval $(call assert_boolean,ERROR_DEPRECATED))
 $(eval $(call assert_boolean,ENABLE_PLAT_COMPAT))
 
 
@@ -362,7 +368,7 @@
 $(eval $(call add_define,TRUSTED_BOARD_BOOT))
 $(eval $(call add_define,PROGRAMMABLE_RESET_ADDRESS))
 $(eval $(call add_define,PSCI_EXTENDED_STATE_ID))
-$(eval $(call add_define,WARN_DEPRECATED))
+$(eval $(call add_define,ERROR_DEPRECATED))
 $(eval $(call add_define,ENABLE_PLAT_COMPAT))
 
 
@@ -398,6 +404,11 @@
 msg_start:
 	@echo "Building ${PLAT}"
 
+# Check if deprecated declarations should be treated as error or not.
+ifeq (${ERROR_DEPRECATED},0)
+    CFLAGS		+= 	-Wno-error=deprecated-declarations
+endif
+
 # Expand build macros for the different images
 ifeq (${NEED_BL1},yes)
 $(eval $(call MAKE_BL,1))
@@ -414,9 +425,13 @@
 	$(eval $(call MAKE_BL,31,in_fip)))
 endif
 
+# If a BL32 image is needed but neither BL32 nor BL32_SOURCES is defined, the
+# build system will call FIP_ADD_IMG to print a warning message and abort the
+# process. Note that the dependency on BL32 applies to the FIP only.
 ifeq (${NEED_BL32},yes)
 $(if ${BL32}, $(eval $(call MAKE_TOOL_ARGS,32,${BL32},in_fip)),\
-	$(eval $(call MAKE_BL,32,in_fip)))
+	$(if ${BL32_SOURCES}, $(eval $(call MAKE_BL,32,in_fip)),\
+		$(eval $(call FIP_ADD_IMG,BL32,--bl32))))
 endif
 
 # Add the BL33 image if required by the platform
diff --git a/bl31/aarch64/runtime_exceptions.S b/bl31/aarch64/runtime_exceptions.S
index bbc7f1b..2835320 100644
--- a/bl31/aarch64/runtime_exceptions.S
+++ b/bl31/aarch64/runtime_exceptions.S
@@ -130,16 +130,6 @@
 	mov	x21, x0
 
 	mov	x0, #INTR_ID_UNAVAILABLE
-#if IMF_READ_INTERRUPT_ID
-	/*
-	 * Read the id of the highest priority pending interrupt. If
-	 * no interrupt is asserted then return to where we came from.
-	 */
-	mov	x19,  #INTR_ID_UNAVAILABLE
-	bl	plat_ic_get_pending_interrupt_id
-	cmp	x19, x0
-	b.eq	interrupt_exit_\label
-#endif
 
 	/* Set the current security state in the 'flags' parameter */
 	mrs	x2, scr_el3
diff --git a/bl31/bl31.mk b/bl31/bl31.mk
index 04e1542..a31c1f4 100644
--- a/bl31/bl31.mk
+++ b/bl31/bl31.mk
@@ -60,13 +60,6 @@
 
 BL31_LINKERFILE		:=	bl31/bl31.ld.S
 
-# Flag used by the generic interrupt management framework to  determine if
-# upon the assertion of an interrupt, it should pass the interrupt id or not
-IMF_READ_INTERRUPT_ID	:=	0
-
-$(eval $(call assert_boolean,IMF_READ_INTERRUPT_ID))
-$(eval $(call add_define,IMF_READ_INTERRUPT_ID))
-
 # Flag used to inidicate if Crash reporting via console should be included
 # in BL3-1. This defaults to being present in DEBUG builds only
 ifndef CRASH_REPORTING
diff --git a/bl31/context_mgmt.c b/bl31/context_mgmt.c
index a0fd1b6..6d40534 100644
--- a/bl31/context_mgmt.c
+++ b/bl31/context_mgmt.c
@@ -90,6 +90,14 @@
 	set_cpu_data_by_index(cpu_idx, cpu_context[security_state], context);
 }
 
+#if !ERROR_DEPRECATED
+/*
+ * These context management helpers are deprecated but are maintained for use
+ * by SPDs which have not migrated to the new API. If ERROR_DEPRECATED
+ * is enabled, these are excluded from the build so as to force users to
+ * migrate to the new API.
+ */
+
 /*******************************************************************************
  * This function returns a pointer to the most recent 'cpu_context' structure
  * for the CPU identified by MPIDR that was set as the context for the specified
@@ -113,6 +121,21 @@
 	cm_set_context_by_index(platform_get_core_pos(mpidr),
 						 context, security_state);
 }
+
+/*******************************************************************************
+ * The following function provides a compatibility function for SPDs using the
+ * existing cm library routines. This function is expected to be invoked for
+ * initializing the cpu_context for the CPU specified by MPIDR for first use.
+ ******************************************************************************/
+void cm_init_context(unsigned long mpidr, const entry_point_info_t *ep)
+{
+	if ((mpidr & MPIDR_AFFINITY_MASK) ==
+			(read_mpidr_el1() & MPIDR_AFFINITY_MASK))
+		cm_init_my_context(ep);
+	else
+		cm_init_context_by_index(platform_get_core_pos(mpidr), ep);
+}
+#endif
 
 /*******************************************************************************
  * This function is used to program the context that's used for exception
@@ -261,20 +284,6 @@
 }
 
 /*******************************************************************************
- * The following function provides a compatibility function for SPDs using the
- * existing cm library routines. This function is expected to be invoked for
- * initializing the cpu_context for the CPU specified by MPIDR for first use.
- ******************************************************************************/
-void cm_init_context(unsigned long mpidr, const entry_point_info_t *ep)
-{
-	if ((mpidr & MPIDR_AFFINITY_MASK) ==
-			(read_mpidr_el1() & MPIDR_AFFINITY_MASK))
-		cm_init_my_context(ep);
-	else
-		cm_init_context_by_index(platform_get_core_pos(mpidr), ep);
-}
-
-/*******************************************************************************
  * Prepare the CPU system registers for first entry into secure or normal world
  *
  * If execution is requested to EL2 or hyp mode, SCTLR_EL2 is initialized
diff --git a/bl31/interrupt_mgmt.c b/bl31/interrupt_mgmt.c
index 5478902..206578b 100644
--- a/bl31/interrupt_mgmt.c
+++ b/bl31/interrupt_mgmt.c
@@ -129,7 +129,12 @@
 	flag = get_interrupt_rm_flag(interrupt_type_flags, security_state);
 	bit_pos = plat_interrupt_type_to_line(type, security_state);
 	intr_type_descs[type].scr_el3[security_state] = flag << bit_pos;
-	cm_write_scr_el3_bit(security_state, bit_pos, flag);
+
+	/* Update scr_el3 only if there is a context available. If not, it
+	 * will be updated later during context initialization which will obtain
+	 * the scr_el3 value to be used via get_scr_el3_from_routing_model() */
+	if (cm_get_context(security_state))
+		cm_write_scr_el3_bit(security_state, bit_pos, flag);
 }
 
 /*******************************************************************************
diff --git a/docs/interrupt-framework-design.md b/docs/interrupt-framework-design.md
index cee29a3..53707ae 100644
--- a/docs/interrupt-framework-design.md
+++ b/docs/interrupt-framework-design.md
@@ -293,11 +293,9 @@
 					     void *handle,
 					     void *cookie);
 
-The value of the `id` parameter depends upon the definition of the
-`IMF_READ_INTERRUPT_ID` build time flag. When the flag is defined, `id` contains
-the number of the highest priority pending interrupt of the type that this
-handler was registered for. When the flag is not defined `id` contains
-`INTR_ID_UNAVAILABLE`.
+The `id` is parameter is reserved and could be used in the future for passing
+the interrupt id of the highest pending interrupt only if there is a foolproof
+way of determining the id. Currently it contains `INTR_ID_UNAVAILABLE`.
 
 The `flags` parameter contains miscellaneous information as follows.
 
@@ -583,11 +581,10 @@
     irrecoverable error condition.
 
 6.  Calling the registered handler function for the interrupt type generated.
-    The firmware also determines the interrupt id if the IMF_READ_INTERRUPT_ID
-    build time flag is set. The id is set to `INTR_ID_UNAVAILABLE` if the flag
-    is not set. The id along with the current security state and a reference to
-    the `cpu_context_t` structure for the current security state are passed to
-    the handler function as its arguments.
+    The `id` parameter is set to `INTR_ID_UNAVAILABLE` currently. The id along
+    with the current security state and a reference to the `cpu_context_t`
+    structure for the current security state are passed to the handler function
+    as its arguments.
 
     The handler function returns a reference to the per-cpu `cpu_context_t`
     structure for the target security state.
diff --git a/docs/porting-guide.md b/docs/porting-guide.md
index 6e71025..8c0d7b7 100644
--- a/docs/porting-guide.md
+++ b/docs/porting-guide.md
@@ -1473,9 +1473,8 @@
     Return   : uint32_t
 
 This API returns the id of the highest priority pending interrupt at the
-platform IC. The IMF passes the id returned by this API to the registered
-handler for the pending interrupt if the `IMF_READ_INTERRUPT_ID` build time flag
-is set. INTR_ID_UNAVAILABLE is returned when there is no interrupt pending.
+platform IC. INTR_ID_UNAVAILABLE is returned when there is no interrupt
+pending.
 
 ARM standard platforms read the _Highest Priority Pending Interrupt
 Register_ (`GICC_HPPIR`) to determine the id of the pending interrupt. The id
diff --git a/docs/user-guide.md b/docs/user-guide.md
index 7987d10..b7b152e 100644
--- a/docs/user-guide.md
+++ b/docs/user-guide.md
@@ -250,11 +250,6 @@
     is used to determine the number of valid slave interfaces available in the
     ARM CCI driver. Default is 400 (that is, CCI-400).
 
-*   `IMF_READ_INTERRUPT_ID`: Boolean flag used by the interrupt management
-    framework to enable passing of the interrupt id to its handler. The id is
-    read using a platform GIC API. `INTR_ID_UNAVAILABLE` is passed instead if
-    this option set to 0. Default is 0.
-
 *   `RESET_TO_BL31`: Enable BL3-1 entrypoint as the CPU reset vector instead
     of the BL1 entrypoint. It can take the value 0 (CPU reset to BL1
     entrypoint) or 1 (CPU reset to BL3-1 entrypoint).
@@ -367,10 +362,10 @@
     and it governs the return value of PSCI_FEATURES API for CPU_SUSPEND
     smc function id.
 
-*   `WARN_DEPRECATED`: This option decides whether to warn the usage of
-    deprecated platform APIs and context management helpers within Trusted
-    Firmware. It can take the value 1 (warn the use of deprecated APIs) or
-    0. The default is 0.
+*   `ERROR_DEPRECATED`: This option decides whether to treat the usage of
+    deprecated platform APIs, helper functions or drivers within Trusted
+    Firmware as error. It can take the value 1 (flag the use of deprecated
+    APIs as error) or 0. The default is 0.
 
 #### ARM development platform specific build options
 
diff --git a/drivers/arm/gic/common/gic_common.c b/drivers/arm/gic/common/gic_common.c
new file mode 100644
index 0000000..17be61d
--- /dev/null
+++ b/drivers/arm/gic/common/gic_common.c
@@ -0,0 +1,308 @@
+/*
+ * Copyright (c) 2015, 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 <gic_common.h>
+#include <mmio.h>
+
+/*******************************************************************************
+ * GIC Distributor interface accessors for reading entire registers
+ ******************************************************************************/
+/*
+ * Accessor to read the GIC Distributor IGROUPR corresponding to the interrupt
+ * `id`, 32 interrupt ids at a time.
+ */
+unsigned int gicd_read_igroupr(uintptr_t base, unsigned int id)
+{
+	unsigned n = id >> IGROUPR_SHIFT;
+	return mmio_read_32(base + GICD_IGROUPR + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor ISENABLER corresponding to the
+ * interrupt `id`, 32 interrupt ids at a time.
+ */
+unsigned int gicd_read_isenabler(uintptr_t base, unsigned int id)
+{
+	unsigned n = id >> ISENABLER_SHIFT;
+	return mmio_read_32(base + GICD_ISENABLER + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor ICENABLER corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+unsigned int gicd_read_icenabler(uintptr_t base, unsigned int id)
+{
+	unsigned n = id >> ICENABLER_SHIFT;
+	return mmio_read_32(base + GICD_ICENABLER + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor ISPENDR corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+unsigned int gicd_read_ispendr(uintptr_t base, unsigned int id)
+{
+	unsigned n = id >> ISPENDR_SHIFT;
+	return mmio_read_32(base + GICD_ISPENDR + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor ICPENDR corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+unsigned int gicd_read_icpendr(uintptr_t base, unsigned int id)
+{
+	unsigned n = id >> ICPENDR_SHIFT;
+	return mmio_read_32(base + GICD_ICPENDR + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor ISACTIVER corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+unsigned int gicd_read_isactiver(uintptr_t base, unsigned int id)
+{
+	unsigned n = id >> ISACTIVER_SHIFT;
+	return mmio_read_32(base + GICD_ISACTIVER + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor ICACTIVER corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+unsigned int gicd_read_icactiver(uintptr_t base, unsigned int id)
+{
+	unsigned n = id >> ICACTIVER_SHIFT;
+	return mmio_read_32(base + GICD_ICACTIVER + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor IPRIORITYR corresponding to the
+ * interrupt `id`, 4 interrupt IDs at a time.
+ */
+unsigned int gicd_read_ipriorityr(uintptr_t base, unsigned int id)
+{
+	unsigned n = id >> IPRIORITYR_SHIFT;
+	return mmio_read_32(base + GICD_IPRIORITYR + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor ICGFR corresponding to the
+ * interrupt `id`, 16 interrupt IDs at a time.
+ */
+unsigned int gicd_read_icfgr(uintptr_t base, unsigned int id)
+{
+	unsigned n = id >> ICFGR_SHIFT;
+	return mmio_read_32(base + GICD_ICFGR + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor NSACR corresponding to the
+ * interrupt `id`, 16 interrupt IDs at a time.
+ */
+unsigned int gicd_read_nsacr(uintptr_t base, unsigned int id)
+{
+	unsigned n = id >> NSACR_SHIFT;
+	return mmio_read_32(base + GICD_NSACR + (n << 2));
+}
+
+/*******************************************************************************
+ * GIC Distributor interface accessors for writing entire registers
+ ******************************************************************************/
+/*
+ * Accessor to write the GIC Distributor IGROUPR corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+void gicd_write_igroupr(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned n = id >> IGROUPR_SHIFT;
+	mmio_write_32(base + GICD_IGROUPR + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor ISENABLER corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+void gicd_write_isenabler(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned n = id >> ISENABLER_SHIFT;
+	mmio_write_32(base + GICD_ISENABLER + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor ICENABLER corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+void gicd_write_icenabler(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned n = id >> ICENABLER_SHIFT;
+	mmio_write_32(base + GICD_ICENABLER + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor ISPENDR corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+void gicd_write_ispendr(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned n = id >> ISPENDR_SHIFT;
+	mmio_write_32(base + GICD_ISPENDR + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor ICPENDR corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+void gicd_write_icpendr(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned n = id >> ICPENDR_SHIFT;
+	mmio_write_32(base + GICD_ICPENDR + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor ISACTIVER corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+void gicd_write_isactiver(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned n = id >> ISACTIVER_SHIFT;
+	mmio_write_32(base + GICD_ISACTIVER + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor ICACTIVER corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+void gicd_write_icactiver(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned n = id >> ICACTIVER_SHIFT;
+	mmio_write_32(base + GICD_ICACTIVER + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor IPRIORITYR corresponding to the
+ * interrupt `id`, 4 interrupt IDs at a time.
+ */
+void gicd_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned n = id >> IPRIORITYR_SHIFT;
+	mmio_write_32(base + GICD_IPRIORITYR + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor ICFGR corresponding to the
+ * interrupt `id`, 16 interrupt IDs at a time.
+ */
+void gicd_write_icfgr(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned n = id >> ICFGR_SHIFT;
+	mmio_write_32(base + GICD_ICFGR + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor NSACR corresponding to the
+ * interrupt `id`, 16 interrupt IDs at a time.
+ */
+void gicd_write_nsacr(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned n = id >> NSACR_SHIFT;
+	mmio_write_32(base + GICD_NSACR + (n << 2), val);
+}
+
+/*******************************************************************************
+ * GIC Distributor interface accessors for individual interrupt manipulation
+ ******************************************************************************/
+unsigned int gicd_get_igroupr(uintptr_t base, unsigned int id)
+{
+	unsigned bit_num = id & ((1 << IGROUPR_SHIFT) - 1);
+	unsigned int reg_val = gicd_read_igroupr(base, id);
+
+	return (reg_val >> bit_num) & 0x1;
+}
+
+void gicd_set_igroupr(uintptr_t base, unsigned int id)
+{
+	unsigned bit_num = id & ((1 << IGROUPR_SHIFT) - 1);
+	unsigned int reg_val = gicd_read_igroupr(base, id);
+
+	gicd_write_igroupr(base, id, reg_val | (1 << bit_num));
+}
+
+void gicd_clr_igroupr(uintptr_t base, unsigned int id)
+{
+	unsigned bit_num = id & ((1 << IGROUPR_SHIFT) - 1);
+	unsigned int reg_val = gicd_read_igroupr(base, id);
+
+	gicd_write_igroupr(base, id, reg_val & ~(1 << bit_num));
+}
+
+void gicd_set_isenabler(uintptr_t base, unsigned int id)
+{
+	unsigned bit_num = id & ((1 << ISENABLER_SHIFT) - 1);
+
+	gicd_write_isenabler(base, id, (1 << bit_num));
+}
+
+void gicd_set_icenabler(uintptr_t base, unsigned int id)
+{
+	unsigned bit_num = id & ((1 << ICENABLER_SHIFT) - 1);
+
+	gicd_write_icenabler(base, id, (1 << bit_num));
+}
+
+void gicd_set_ispendr(uintptr_t base, unsigned int id)
+{
+	unsigned bit_num = id & ((1 << ISPENDR_SHIFT) - 1);
+
+	gicd_write_ispendr(base, id, (1 << bit_num));
+}
+
+void gicd_set_icpendr(uintptr_t base, unsigned int id)
+{
+	unsigned bit_num = id & ((1 << ICPENDR_SHIFT) - 1);
+
+	gicd_write_icpendr(base, id, (1 << bit_num));
+}
+
+void gicd_set_isactiver(uintptr_t base, unsigned int id)
+{
+	unsigned bit_num = id & ((1 << ISACTIVER_SHIFT) - 1);
+
+	gicd_write_isactiver(base, id, (1 << bit_num));
+}
+
+void gicd_set_icactiver(uintptr_t base, unsigned int id)
+{
+	unsigned bit_num = id & ((1 << ICACTIVER_SHIFT) - 1);
+
+	gicd_write_icactiver(base, id, (1 << bit_num));
+}
diff --git a/drivers/arm/gic/v2/gicv2_helpers.c b/drivers/arm/gic/v2/gicv2_helpers.c
new file mode 100644
index 0000000..1f904c5
--- /dev/null
+++ b/drivers/arm/gic/v2/gicv2_helpers.c
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2015, 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 <arch_helpers.h>
+#include <assert.h>
+#include <debug.h>
+#include <gic_common.h>
+#include "gicv2_private.h"
+
+/*
+ * Accessor to read the GIC Distributor ITARGETSR corresponding to the
+ * interrupt `id`, 4 interrupt IDs at a time.
+ */
+unsigned int gicd_read_itargetsr(uintptr_t base, unsigned int id)
+{
+	unsigned n = id >> ITARGETSR_SHIFT;
+	return mmio_read_32(base + GICD_ITARGETSR + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor CPENDSGIR corresponding to the
+ * interrupt `id`, 4 interrupt IDs at a time.
+ */
+unsigned int gicd_read_cpendsgir(uintptr_t base, unsigned int id)
+{
+	unsigned n = id >> CPENDSGIR_SHIFT;
+	return mmio_read_32(base + GICD_CPENDSGIR + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor SPENDSGIR corresponding to the
+ * interrupt `id`, 4 interrupt IDs at a time.
+ */
+unsigned int gicd_read_spendsgir(uintptr_t base, unsigned int id)
+{
+	unsigned n = id >> SPENDSGIR_SHIFT;
+	return mmio_read_32(base + GICD_SPENDSGIR + (n << 2));
+}
+
+/*
+ * Accessor to write the GIC Distributor ITARGETSR corresponding to the
+ * interrupt `id`, 4 interrupt IDs at a time.
+ */
+void gicd_write_itargetsr(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned n = id >> ITARGETSR_SHIFT;
+	mmio_write_32(base + GICD_ITARGETSR + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor CPENDSGIR corresponding to the
+ * interrupt `id`, 4 interrupt IDs at a time.
+ */
+void gicd_write_cpendsgir(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned n = id >> CPENDSGIR_SHIFT;
+	mmio_write_32(base + GICD_CPENDSGIR + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor SPENDSGIR corresponding to the
+ * interrupt `id`, 4 interrupt IDs at a time.
+ */
+void gicd_write_spendsgir(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned n = id >> SPENDSGIR_SHIFT;
+	mmio_write_32(base + GICD_SPENDSGIR + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor ITARGETSR corresponding to the
+ * interrupt `id`.
+ */
+void gicd_set_itargetsr(uintptr_t 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 | (target << (byte_off << 3)));
+}
+
+/*******************************************************************************
+ * Get the current CPU bit mask from GICD_ITARGETSR0
+ ******************************************************************************/
+unsigned int gicv2_get_cpuif_id(uintptr_t base)
+{
+	unsigned int val;
+
+	val = gicd_read_itargetsr(base, 0);
+	return val & GIC_TARGET_CPU_MASK;
+}
+
+/*******************************************************************************
+ * Helper function to configure the default attributes of SPIs.
+ ******************************************************************************/
+void gicv2_spis_configure_defaults(uintptr_t gicd_base)
+{
+	unsigned int index, num_ints;
+
+	num_ints = gicd_read_typer(gicd_base);
+	num_ints &= TYPER_IT_LINES_NO_MASK;
+	num_ints = (num_ints + 1) << 5;
+
+	/*
+	 * Treat all SPIs as G1NS by default. The number of interrupts is
+	 * calculated as 32 * (IT_LINES + 1). We do 32 at a time.
+	 */
+	for (index = MIN_SPI_ID; index < num_ints; index += 32)
+		gicd_write_igroupr(gicd_base, index, ~0U);
+
+	/* Setup the default SPI priorities doing four at a time */
+	for (index = MIN_SPI_ID; index < num_ints; index += 4)
+		gicd_write_ipriorityr(gicd_base,
+				      index,
+				      GICD_IPRIORITYR_DEF_VAL);
+
+	/* Treat all SPIs as level triggered by default, 16 at a time */
+	for (index = MIN_SPI_ID; index < num_ints; index += 16)
+		gicd_write_icfgr(gicd_base, index, 0);
+}
+
+/*******************************************************************************
+ * Helper function to configure secure G0 SPIs.
+ ******************************************************************************/
+void gicv2_secure_spis_configure(uintptr_t gicd_base,
+				     unsigned int num_ints,
+				     const unsigned int *sec_intr_list)
+{
+	unsigned int index, irq_num;
+
+	/* If `num_ints` is not 0, ensure that `sec_intr_list` is not NULL */
+	assert(num_ints ? (uintptr_t)sec_intr_list : 1);
+
+	for (index = 0; index < num_ints; index++) {
+		irq_num = sec_intr_list[index];
+		if (irq_num >= MIN_SPI_ID) {
+			/* Configure this interrupt as a secure interrupt */
+			gicd_clr_igroupr(gicd_base, irq_num);
+
+			/* Set the priority of this interrupt */
+			gicd_write_ipriorityr(gicd_base,
+					      irq_num,
+					      GIC_HIGHEST_SEC_PRIORITY);
+
+			/* Target the secure interrupts to primary CPU */
+			gicd_set_itargetsr(gicd_base, irq_num,
+					gicv2_get_cpuif_id(gicd_base));
+
+			/* Enable this interrupt */
+			gicd_set_isenabler(gicd_base, irq_num);
+		}
+	}
+
+}
+
+/*******************************************************************************
+ * Helper function to configure secure G0 SGIs and PPIs.
+ ******************************************************************************/
+void gicv2_secure_ppi_sgi_setup(uintptr_t gicd_base,
+					unsigned int num_ints,
+					const unsigned int *sec_intr_list)
+{
+	unsigned int index, irq_num, sec_ppi_sgi_mask = 0;
+
+	/* If `num_ints` is not 0, ensure that `sec_intr_list` is not NULL */
+	assert(num_ints ? (uintptr_t)sec_intr_list : 1);
+
+	/*
+	 * Disable all SGIs (imp. def.)/PPIs before configuring them. This is a
+	 * more scalable approach as it avoids clearing the enable bits in the
+	 * GICD_CTLR.
+	 */
+	gicd_write_icenabler(gicd_base, 0, ~0);
+
+	/* Setup the default PPI/SGI priorities doing four at a time */
+	for (index = 0; index < MIN_SPI_ID; index += 4)
+		gicd_write_ipriorityr(gicd_base,
+				      index,
+				      GICD_IPRIORITYR_DEF_VAL);
+
+	for (index = 0; index < num_ints; index++) {
+		irq_num = sec_intr_list[index];
+		if (irq_num < MIN_SPI_ID) {
+			/* We have an SGI or a PPI. They are Group0 at reset */
+			sec_ppi_sgi_mask |= 1U << irq_num;
+
+			/* Set the priority of this interrupt */
+			gicd_write_ipriorityr(gicd_base,
+					    irq_num,
+					    GIC_HIGHEST_SEC_PRIORITY);
+		}
+	}
+
+	/*
+	 * Invert the bitmask to create a mask for non-secure PPIs and
+	 * SGIs. Program the GICD_IGROUPR0 with this bit mask.
+	 */
+	gicd_write_igroupr(gicd_base, 0, ~sec_ppi_sgi_mask);
+
+	/* Enable the Group 0 SGIs and PPIs */
+	gicd_write_isenabler(gicd_base, 0, sec_ppi_sgi_mask);
+}
diff --git a/drivers/arm/gic/v2/gicv2_main.c b/drivers/arm/gic/v2/gicv2_main.c
new file mode 100644
index 0000000..cf93926
--- /dev/null
+++ b/drivers/arm/gic/v2/gicv2_main.c
@@ -0,0 +1,254 @@
+/*
+ * Copyright (c) 2015, 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 <arch_helpers.h>
+#include <assert.h>
+#include <debug.h>
+#include <gic_common.h>
+#include <gicv2.h>
+#include "gicv2_private.h"
+
+static const gicv2_driver_data_t *driver_data;
+
+/*******************************************************************************
+ * 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 gicv2_cpuif_enable(void)
+{
+	unsigned int val;
+
+	assert(driver_data);
+	assert(driver_data->gicc_base);
+
+	/*
+	 * Enable the Group 0 interrupts, FIQEn and disable Group 0/1
+	 * bypass.
+	 */
+	val = CTLR_ENABLE_G0_BIT | FIQ_EN_BIT | FIQ_BYP_DIS_GRP0;
+	val |= IRQ_BYP_DIS_GRP0 | FIQ_BYP_DIS_GRP1 | IRQ_BYP_DIS_GRP1;
+
+	/* Program the idle priority in the PMR */
+	gicc_write_pmr(driver_data->gicc_base, GIC_PRI_MASK);
+	gicc_write_ctlr(driver_data->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 gicv2_cpuif_disable(void)
+{
+	unsigned int val;
+
+	assert(driver_data);
+	assert(driver_data->gicc_base);
+
+	/* Disable secure, non-secure interrupts and disable their bypass */
+	val = gicc_read_ctlr(driver_data->gicc_base);
+	val &= ~(CTLR_ENABLE_G0_BIT | CTLR_ENABLE_G1_BIT);
+	val |= FIQ_BYP_DIS_GRP1 | FIQ_BYP_DIS_GRP0;
+	val |= IRQ_BYP_DIS_GRP0 | IRQ_BYP_DIS_GRP1;
+	gicc_write_ctlr(driver_data->gicc_base, val);
+}
+
+/*******************************************************************************
+ * Per cpu gic distributor setup which will be done by all cpus after a cold
+ * boot/hotplug. This marks out the secure SPIs and PPIs & enables them.
+ ******************************************************************************/
+void gicv2_pcpu_distif_init(void)
+{
+	assert(driver_data);
+	assert(driver_data->gicd_base);
+	assert(driver_data->g0_interrupt_array);
+
+	gicv2_secure_ppi_sgi_setup(driver_data->gicd_base,
+					driver_data->g0_interrupt_num,
+					driver_data->g0_interrupt_array);
+}
+
+/*******************************************************************************
+ * Global gic distributor init 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.
+ ******************************************************************************/
+void gicv2_distif_init(void)
+{
+	unsigned int ctlr;
+
+	assert(driver_data);
+	assert(driver_data->gicd_base);
+	assert(driver_data->g0_interrupt_array);
+
+	/* Disable the distributor before going further */
+	ctlr = gicd_read_ctlr(driver_data->gicd_base);
+	gicd_write_ctlr(driver_data->gicd_base,
+			ctlr & ~(CTLR_ENABLE_G0_BIT | CTLR_ENABLE_G1_BIT));
+
+	/* Set the default attribute of all SPIs */
+	gicv2_spis_configure_defaults(driver_data->gicd_base);
+
+	/* Configure the G0 SPIs */
+	gicv2_secure_spis_configure(driver_data->gicd_base,
+					driver_data->g0_interrupt_num,
+					driver_data->g0_interrupt_array);
+
+	/* Re-enable the secure SPIs now that they have been configured */
+	gicd_write_ctlr(driver_data->gicd_base, ctlr | CTLR_ENABLE_G0_BIT);
+}
+
+/*******************************************************************************
+ * Initialize the ARM GICv2 driver with the provided platform inputs
+ ******************************************************************************/
+void gicv2_driver_init(const gicv2_driver_data_t *plat_driver_data)
+{
+	unsigned int gic_version;
+	assert(plat_driver_data);
+	assert(plat_driver_data->gicd_base);
+	assert(plat_driver_data->gicc_base);
+
+	/*
+	 * The platform should provide a list of atleast one type of
+	 * interrupts
+	 */
+	assert(plat_driver_data->g0_interrupt_array);
+
+	/*
+	 * If there are no interrupts of a particular type, then the number of
+	 * interrupts of that type should be 0 and vice-versa.
+	 */
+	assert(plat_driver_data->g0_interrupt_array ?
+	       plat_driver_data->g0_interrupt_num :
+	       plat_driver_data->g0_interrupt_num == 0);
+
+	/* Ensure that this is a GICv2 system */
+	gic_version = gicd_read_pidr2(plat_driver_data->gicd_base);
+	gic_version = (gic_version >> PIDR2_ARCH_REV_SHIFT)
+					& PIDR2_ARCH_REV_MASK;
+	assert(gic_version == ARCH_REV_GICV2);
+
+	driver_data = plat_driver_data;
+
+	INFO("ARM GICv2 driver initialized\n");
+}
+
+/******************************************************************************
+ * This function returns whether FIQ is enabled in the GIC CPU interface.
+ *****************************************************************************/
+unsigned int gicv2_is_fiq_enabled(void)
+{
+	unsigned int gicc_ctlr;
+
+	assert(driver_data);
+	assert(driver_data->gicc_base);
+
+	gicc_ctlr = gicc_read_ctlr(driver_data->gicc_base);
+	return (gicc_ctlr >> FIQ_EN_SHIFT) & 0x1;
+}
+
+/*******************************************************************************
+ * This function returns the type of the highest priority pending interrupt at
+ * the GIC cpu interface. The return values can be one of the following :
+ *   PENDING_G1_INTID   : The interrupt type is non secure Group 1.
+ *   0 - 1019           : The interrupt type is secure Group 0.
+ *   GIC_SPURIOUS_INTERRUPT : there is no pending interrupt with
+ *                            sufficient priority to be signaled
+ ******************************************************************************/
+unsigned int gicv2_get_pending_interrupt_type(void)
+{
+	assert(driver_data);
+	assert(driver_data->gicc_base);
+
+	return gicc_read_hppir(driver_data->gicc_base) & INT_ID_MASK;
+}
+
+/*******************************************************************************
+ * This function returns the id of the highest priority pending interrupt at
+ * the GIC cpu interface. GIC_SPURIOUS_INTERRUPT is returned when there is no
+ * interrupt pending.
+ ******************************************************************************/
+unsigned int gicv2_get_pending_interrupt_id(void)
+{
+	unsigned int id;
+
+	assert(driver_data);
+	assert(driver_data->gicc_base);
+
+	id = gicc_read_hppir(driver_data->gicc_base) & INT_ID_MASK;
+
+	/*
+	 * Find out which non-secure interrupt it is under the assumption that
+	 * the GICC_CTLR.AckCtl bit is 0.
+	 */
+	if (id == PENDING_G1_INTID)
+		id = gicc_read_ahppir(driver_data->gicc_base) & INT_ID_MASK;
+
+	return id;
+}
+
+/*******************************************************************************
+ * This functions reads the GIC cpu interface Interrupt Acknowledge register
+ * to start handling the pending secure 0 interrupt. It returns the
+ * contents of the IAR.
+ ******************************************************************************/
+unsigned int gicv2_acknowledge_interrupt(void)
+{
+	assert(driver_data);
+	assert(driver_data->gicc_base);
+
+	return gicc_read_IAR(driver_data->gicc_base);
+}
+
+/*******************************************************************************
+ * This functions writes the GIC cpu interface End Of Interrupt register with
+ * the passed value to finish handling the active secure group 0 interrupt.
+ ******************************************************************************/
+void gicv2_end_of_interrupt(unsigned int id)
+{
+	assert(driver_data);
+	assert(driver_data->gicc_base);
+
+	gicc_write_EOIR(driver_data->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 secure or group1 non secure. It returns zero for Group 0 secure and
+ * one for Group 1 non secure interrupt.
+ ******************************************************************************/
+unsigned int gicv2_get_interrupt_group(unsigned int id)
+{
+	assert(driver_data);
+	assert(driver_data->gicd_base);
+
+	return gicd_get_igroupr(driver_data->gicd_base, id);
+}
diff --git a/drivers/arm/gic/v2/gicv2_private.h b/drivers/arm/gic/v2/gicv2_private.h
new file mode 100644
index 0000000..6a1ec82
--- /dev/null
+++ b/drivers/arm/gic/v2/gicv2_private.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2015, 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 __GICV2_PRIVATE_H__
+#define __GICV2_PRIVATE_H__
+
+#include <gicv2.h>
+#include <mmio.h>
+#include <stdint.h>
+
+/*******************************************************************************
+ * Private function prototypes
+ ******************************************************************************/
+void gicv2_spis_configure_defaults(uintptr_t gicd_base);
+void gicv2_secure_spis_configure(uintptr_t gicd_base,
+				     unsigned int num_ints,
+				     const unsigned int *sec_intr_list);
+void gicv2_secure_ppi_sgi_setup(uintptr_t gicd_base,
+					unsigned int num_ints,
+					const unsigned int *sec_intr_list);
+unsigned int gicv2_get_cpuif_id(uintptr_t base);
+
+/*******************************************************************************
+ * GIC Distributor interface accessors for reading entire registers
+ ******************************************************************************/
+static inline unsigned int gicd_read_pidr2(uintptr_t base)
+{
+	return mmio_read_32(base + GICD_PIDR2_GICV2);
+}
+
+/*******************************************************************************
+ * GIC CPU interface accessors for reading entire registers
+ ******************************************************************************/
+
+static inline unsigned int gicc_read_ctlr(uintptr_t base)
+{
+	return mmio_read_32(base + GICC_CTLR);
+}
+
+static inline unsigned int gicc_read_pmr(uintptr_t base)
+{
+	return mmio_read_32(base + GICC_PMR);
+}
+
+static inline unsigned int gicc_read_BPR(uintptr_t base)
+{
+	return mmio_read_32(base + GICC_BPR);
+}
+
+static inline unsigned int gicc_read_IAR(uintptr_t base)
+{
+	return mmio_read_32(base + GICC_IAR);
+}
+
+static inline unsigned int gicc_read_EOIR(uintptr_t base)
+{
+	return mmio_read_32(base + GICC_EOIR);
+}
+
+static inline unsigned int gicc_read_hppir(uintptr_t base)
+{
+	return mmio_read_32(base + GICC_HPPIR);
+}
+
+static inline unsigned int gicc_read_ahppir(uintptr_t base)
+{
+	return mmio_read_32(base + GICC_AHPPIR);
+}
+
+static inline unsigned int gicc_read_dir(uintptr_t base)
+{
+	return mmio_read_32(base + GICC_DIR);
+}
+
+static inline unsigned int gicc_read_iidr(uintptr_t base)
+{
+	return mmio_read_32(base + GICC_IIDR);
+}
+
+/*******************************************************************************
+ * GIC CPU interface accessors for writing entire registers
+ ******************************************************************************/
+
+static inline void gicc_write_ctlr(uintptr_t base, unsigned int val)
+{
+	mmio_write_32(base + GICC_CTLR, val);
+}
+
+static inline void gicc_write_pmr(uintptr_t base, unsigned int val)
+{
+	mmio_write_32(base + GICC_PMR, val);
+}
+
+static inline void gicc_write_BPR(uintptr_t base, unsigned int val)
+{
+	mmio_write_32(base + GICC_BPR, val);
+}
+
+
+static inline void gicc_write_IAR(uintptr_t base, unsigned int val)
+{
+	mmio_write_32(base + GICC_IAR, val);
+}
+
+static inline void gicc_write_EOIR(uintptr_t base, unsigned int val)
+{
+	mmio_write_32(base + GICC_EOIR, val);
+}
+
+static inline void gicc_write_hppir(uintptr_t base, unsigned int val)
+{
+	mmio_write_32(base + GICC_HPPIR, val);
+}
+
+static inline void gicc_write_dir(uintptr_t base, unsigned int val)
+{
+	mmio_write_32(base + GICC_DIR, val);
+}
+
+#endif /* __GICV2_PRIVATE_H__ */
diff --git a/drivers/arm/gic/v3/gicv3_helpers.c b/drivers/arm/gic/v3/gicv3_helpers.c
new file mode 100644
index 0000000..6e8251d
--- /dev/null
+++ b/drivers/arm/gic/v3/gicv3_helpers.c
@@ -0,0 +1,415 @@
+/*
+ * Copyright (c) 2015, 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 <arch_helpers.h>
+#include <assert.h>
+#include <debug.h>
+#include <gic_common.h>
+#include "gicv3_private.h"
+
+/*
+ * Accessor to read the GIC Distributor IGRPMODR corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+unsigned int gicd_read_igrpmodr(uintptr_t base, unsigned int id)
+{
+	unsigned n = id >> IGRPMODR_SHIFT;
+	return mmio_read_32(base + GICD_IGRPMODR + (n << 2));
+}
+
+/*
+ * Accessor to write the GIC Distributor IGRPMODR corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+void gicd_write_igrpmodr(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned n = id >> IGRPMODR_SHIFT;
+	mmio_write_32(base + GICD_IGRPMODR + (n << 2), val);
+}
+
+/*
+ * Accessor to get the bit corresponding to interrupt ID
+ * in GIC Distributor IGRPMODR.
+ */
+unsigned int gicd_get_igrpmodr(uintptr_t base, unsigned int id)
+{
+	unsigned bit_num = id & ((1 << IGRPMODR_SHIFT) - 1);
+	unsigned int reg_val = gicd_read_igrpmodr(base, id);
+
+	return (reg_val >> bit_num) & 0x1;
+}
+
+/*
+ * Accessor to set the bit corresponding to interrupt ID
+ * in GIC Distributor IGRPMODR.
+ */
+void gicd_set_igrpmodr(uintptr_t base, unsigned int id)
+{
+	unsigned bit_num = id & ((1 << IGRPMODR_SHIFT) - 1);
+	unsigned int reg_val = gicd_read_igrpmodr(base, id);
+
+	gicd_write_igrpmodr(base, id, reg_val | (1 << bit_num));
+}
+
+/*
+ * Accessor to clear the bit corresponding to interrupt ID
+ * in GIC Distributor IGRPMODR.
+ */
+void gicd_clr_igrpmodr(uintptr_t base, unsigned int id)
+{
+	unsigned bit_num = id & ((1 << IGRPMODR_SHIFT) - 1);
+	unsigned int reg_val = gicd_read_igrpmodr(base, id);
+
+	gicd_write_igrpmodr(base, id, reg_val & ~(1 << bit_num));
+}
+
+/*
+ * Accessor to read the GIC Re-distributor IPRIORITYR corresponding to the
+ * interrupt `id`, 4 interrupts IDs at a time.
+ */
+unsigned int gicr_read_ipriorityr(uintptr_t base, unsigned int id)
+{
+	unsigned n = id >> IPRIORITYR_SHIFT;
+	return mmio_read_32(base + GICR_IPRIORITYR + (n << 2));
+}
+
+/*
+ * Accessor to write the GIC Re-distributor IPRIORITYR corresponding to the
+ * interrupt `id`, 4 interrupts IDs at a time.
+ */
+void gicr_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned n = id >> IPRIORITYR_SHIFT;
+	mmio_write_32(base + GICR_IPRIORITYR + (n << 2), val);
+}
+
+/*
+ * Accessor to get the bit corresponding to interrupt ID
+ * from GIC Re-distributor IGROUPR0.
+ */
+unsigned int gicr_get_igroupr0(uintptr_t base, unsigned int id)
+{
+	unsigned bit_num = id & ((1 << IGROUPR_SHIFT) - 1);
+	unsigned int reg_val = gicr_read_igroupr0(base);
+
+	return (reg_val >> bit_num) & 0x1;
+}
+
+/*
+ * Accessor to set the bit corresponding to interrupt ID
+ * in GIC Re-distributor IGROUPR0.
+ */
+void gicr_set_igroupr0(uintptr_t base, unsigned int id)
+{
+	unsigned bit_num = id & ((1 << IGROUPR_SHIFT) - 1);
+	unsigned int reg_val = gicr_read_igroupr0(base);
+
+	gicr_write_igroupr0(base, reg_val | (1 << bit_num));
+}
+
+/*
+ * Accessor to clear the bit corresponding to interrupt ID
+ * in GIC Re-distributor IGROUPR0.
+ */
+void gicr_clr_igroupr0(uintptr_t base, unsigned int id)
+{
+	unsigned bit_num = id & ((1 << IGROUPR_SHIFT) - 1);
+	unsigned int reg_val = gicr_read_igroupr0(base);
+
+	gicr_write_igroupr0(base, reg_val & ~(1 << bit_num));
+}
+
+/*
+ * Accessor to get the bit corresponding to interrupt ID
+ * from GIC Re-distributor IGRPMODR0.
+ */
+unsigned int gicr_get_igrpmodr0(uintptr_t base, unsigned int id)
+{
+	unsigned bit_num = id & ((1 << IGRPMODR_SHIFT) - 1);
+	unsigned int reg_val = gicr_read_igrpmodr0(base);
+
+	return (reg_val >> bit_num) & 0x1;
+}
+
+/*
+ * Accessor to set the bit corresponding to interrupt ID
+ * in GIC Re-distributor IGRPMODR0.
+ */
+void gicr_set_igrpmodr0(uintptr_t base, unsigned int id)
+{
+	unsigned bit_num = id & ((1 << IGRPMODR_SHIFT) - 1);
+	unsigned int reg_val = gicr_read_igrpmodr0(base);
+
+	gicr_write_igrpmodr0(base, reg_val | (1 << bit_num));
+}
+
+/*
+ * Accessor to clear the bit corresponding to interrupt ID
+ * in GIC Re-distributor IGRPMODR0.
+ */
+void gicr_clr_igrpmodr0(uintptr_t base, unsigned int id)
+{
+	unsigned bit_num = id & ((1 << IGRPMODR_SHIFT) - 1);
+	unsigned int reg_val = gicr_read_igrpmodr0(base);
+
+	gicr_write_igrpmodr0(base, reg_val & ~(1 << bit_num));
+}
+
+/*
+ * Accessor to set the bit corresponding to interrupt ID
+ * in GIC Re-distributor ISENABLER0.
+ */
+void gicr_set_isenabler0(uintptr_t base, unsigned int id)
+{
+	unsigned bit_num = id & ((1 << ISENABLER_SHIFT) - 1);
+
+	gicr_write_isenabler0(base, (1 << bit_num));
+}
+
+/******************************************************************************
+ * This function marks the core as awake in the re-distributor and
+ * ensures that the interface is active.
+ *****************************************************************************/
+void gicv3_rdistif_mark_core_awake(uintptr_t gicr_base)
+{
+	/*
+	 * The WAKER_PS_BIT should be changed to 0
+	 * only when WAKER_CA_BIT is 1.
+	 */
+	assert(gicr_read_waker(gicr_base) & WAKER_CA_BIT);
+
+	/* Mark the connected core as awake */
+	gicr_write_waker(gicr_base, gicr_read_waker(gicr_base) & ~WAKER_PS_BIT);
+
+	/* Wait till the WAKER_CA_BIT changes to 0 */
+	while (gicr_read_waker(gicr_base) & WAKER_CA_BIT)
+		;
+}
+
+
+/******************************************************************************
+ * This function marks the core as asleep in the re-distributor and ensures
+ * that the interface is quiescent.
+ *****************************************************************************/
+void gicv3_rdistif_mark_core_asleep(uintptr_t gicr_base)
+{
+	/* Mark the connected core as asleep */
+	gicr_write_waker(gicr_base, gicr_read_waker(gicr_base) | WAKER_PS_BIT);
+
+	/* Wait till the WAKER_CA_BIT changes to 1 */
+	while (!(gicr_read_waker(gicr_base) & WAKER_CA_BIT))
+		;
+}
+
+
+/*******************************************************************************
+ * This function probes the Redistributor frames when the driver is initialised
+ * and saves their base addresses. These base addresses are used later to
+ * initialise each Redistributor interface.
+ ******************************************************************************/
+void gicv3_rdistif_base_addrs_probe(uintptr_t *rdistif_base_addrs,
+					unsigned int rdistif_num,
+					uintptr_t gicr_base,
+					mpidr_hash_fn mpidr_to_core_pos)
+{
+	unsigned long mpidr;
+	unsigned int proc_num;
+	unsigned long long typer_val;
+	uintptr_t rdistif_base = gicr_base;
+
+	assert(rdistif_base_addrs);
+
+	/*
+	 * Iterate over the Redistributor frames. Store the base address of each
+	 * frame in the platform provided array. Use the "Processor Number"
+	 * field to index into the array if the platform has not provided a hash
+	 * function to convert an MPIDR (obtained from the "Affinity Value"
+	 * field into a linear index.
+	 */
+	do {
+		typer_val = gicr_read_typer(rdistif_base);
+		if (mpidr_to_core_pos) {
+			mpidr = mpidr_from_gicr_typer(typer_val);
+			proc_num = mpidr_to_core_pos(mpidr);
+		} else {
+			proc_num = (typer_val >> TYPER_PROC_NUM_SHIFT) &
+				TYPER_PROC_NUM_MASK;
+		}
+		assert(proc_num < rdistif_num);
+		rdistif_base_addrs[proc_num] = rdistif_base;
+		rdistif_base += (1 << GICR_PCPUBASE_SHIFT);
+	} while (!(typer_val & TYPER_LAST_BIT));
+}
+
+/*******************************************************************************
+ * Helper function to configure the default attributes of SPIs.
+ ******************************************************************************/
+void gicv3_spis_configure_defaults(uintptr_t gicd_base)
+{
+	unsigned int index, num_ints;
+
+	num_ints = gicd_read_typer(gicd_base);
+	num_ints &= TYPER_IT_LINES_NO_MASK;
+	num_ints = (num_ints + 1) << 5;
+
+	/*
+	 * Treat all SPIs as G1NS by default. The number of interrupts is
+	 * calculated as 32 * (IT_LINES + 1). We do 32 at a time.
+	 */
+	for (index = MIN_SPI_ID; index < num_ints; index += 32)
+		gicd_write_igroupr(gicd_base, index, ~0U);
+
+	/* Setup the default SPI priorities doing four at a time */
+	for (index = MIN_SPI_ID; index < num_ints; index += 4)
+		gicd_write_ipriorityr(gicd_base,
+				      index,
+				      GICD_IPRIORITYR_DEF_VAL);
+
+	/*
+	 * Treat all SPIs as level triggered by default, write 16 at
+	 * a time
+	 */
+	for (index = MIN_SPI_ID; index < num_ints; index += 16)
+		gicd_write_icfgr(gicd_base, index, 0);
+}
+
+/*******************************************************************************
+ * Helper function to configure secure G0 and G1S SPIs.
+ ******************************************************************************/
+void gicv3_secure_spis_configure(uintptr_t gicd_base,
+				     unsigned int num_ints,
+				     const unsigned int *sec_intr_list,
+				     unsigned int int_grp)
+{
+	unsigned int index, irq_num;
+	uint64_t gic_affinity_val;
+
+	assert((int_grp == INT_TYPE_G1S) || (int_grp == INT_TYPE_G0));
+	/* If `num_ints` is not 0, ensure that `sec_intr_list` is not NULL */
+	assert(num_ints ? (uintptr_t)sec_intr_list : 1);
+
+	for (index = 0; index < num_ints; index++) {
+		irq_num = sec_intr_list[index];
+		if (irq_num >= MIN_SPI_ID) {
+
+			/* Configure this interrupt as a secure interrupt */
+			gicd_clr_igroupr(gicd_base, irq_num);
+
+			/* Configure this interrupt as G0 or a G1S interrupt */
+			if (int_grp == INT_TYPE_G1S)
+				gicd_set_igrpmodr(gicd_base, irq_num);
+			else
+				gicd_clr_igrpmodr(gicd_base, irq_num);
+
+			/* Set the priority of this interrupt */
+			gicd_write_ipriorityr(gicd_base,
+					      irq_num,
+					      GIC_HIGHEST_SEC_PRIORITY);
+
+			/* Target SPIs to the primary CPU */
+			gic_affinity_val =
+				gicd_irouter_val_from_mpidr(read_mpidr(), 0);
+			gicd_write_irouter(gicd_base,
+					   irq_num,
+					   gic_affinity_val);
+
+			/* Enable this interrupt */
+			gicd_set_isenabler(gicd_base, irq_num);
+		}
+	}
+
+}
+
+/*******************************************************************************
+ * Helper function to configure the default attributes of SPIs.
+ ******************************************************************************/
+void gicv3_ppi_sgi_configure_defaults(uintptr_t gicr_base)
+{
+	unsigned int index;
+
+	/*
+	 * Disable all SGIs (imp. def.)/PPIs before configuring them. This is a
+	 * more scalable approach as it avoids clearing the enable bits in the
+	 * GICD_CTLR
+	 */
+	gicr_write_icenabler0(gicr_base, ~0);
+	gicr_wait_for_pending_write(gicr_base);
+
+	/* Treat all SGIs/PPIs as G1NS by default. */
+	gicr_write_igroupr0(gicr_base, ~0U);
+
+	/* Setup the default PPI/SGI priorities doing four at a time */
+	for (index = 0; index < MIN_SPI_ID; index += 4)
+		gicr_write_ipriorityr(gicr_base,
+				      index,
+				      GICD_IPRIORITYR_DEF_VAL);
+
+	/* Configure all PPIs as level triggered by default */
+	gicr_write_icfgr1(gicr_base, 0);
+}
+
+/*******************************************************************************
+ * Helper function to configure secure G0 and G1S SPIs.
+ ******************************************************************************/
+void gicv3_secure_ppi_sgi_configure(uintptr_t gicr_base,
+					unsigned int num_ints,
+					const unsigned int *sec_intr_list,
+					unsigned int int_grp)
+{
+	unsigned int index, irq_num;
+
+	assert((int_grp == INT_TYPE_G1S) || (int_grp == INT_TYPE_G0));
+	/* If `num_ints` is not 0, ensure that `sec_intr_list` is not NULL */
+	assert(num_ints ? (uintptr_t)sec_intr_list : 1);
+
+	for (index = 0; index < num_ints; index++) {
+		irq_num = sec_intr_list[index];
+		if (irq_num < MIN_SPI_ID) {
+
+			/* Configure this interrupt as a secure interrupt */
+			gicr_clr_igroupr0(gicr_base, irq_num);
+
+			/* Configure this interrupt as G0 or a G1S interrupt */
+			if (int_grp == INT_TYPE_G1S)
+				gicr_set_igrpmodr0(gicr_base, irq_num);
+			else
+				gicr_clr_igrpmodr0(gicr_base, irq_num);
+
+			/* Set the priority of this interrupt */
+			gicr_write_ipriorityr(gicr_base,
+					    irq_num,
+					    GIC_HIGHEST_SEC_PRIORITY);
+
+			/* Enable this interrupt */
+			gicr_set_isenabler0(gicr_base, irq_num);
+		}
+	}
+}
diff --git a/drivers/arm/gic/v3/gicv3_main.c b/drivers/arm/gic/v3/gicv3_main.c
new file mode 100644
index 0000000..06311e3
--- /dev/null
+++ b/drivers/arm/gic/v3/gicv3_main.c
@@ -0,0 +1,381 @@
+/*
+ * Copyright (c) 2015, 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 <arch_helpers.h>
+#include <assert.h>
+#include <debug.h>
+#include <gic_common.h>
+#include <gicv3.h>
+#include "gicv3_private.h"
+
+static const gicv3_driver_data_t *driver_data;
+static unsigned int gicv2_compat;
+
+/*******************************************************************************
+ * This function initialises the ARM GICv3 driver in EL3 with provided platform
+ * inputs.
+ ******************************************************************************/
+void gicv3_driver_init(const gicv3_driver_data_t *plat_driver_data)
+{
+	unsigned int gic_version;
+
+	assert(plat_driver_data);
+	assert(plat_driver_data->gicd_base);
+	assert(plat_driver_data->gicr_base);
+	assert(plat_driver_data->rdistif_num);
+	assert(plat_driver_data->rdistif_base_addrs);
+
+	assert(IS_IN_EL3());
+
+	/*
+	 * The platform should provide a list of at least one type of
+	 * interrupts
+	 */
+	assert(plat_driver_data->g0_interrupt_array ||
+	       plat_driver_data->g1s_interrupt_array);
+
+	/*
+	 * If there are no interrupts of a particular type, then the number of
+	 * interrupts of that type should be 0 and vice-versa.
+	 */
+	assert(plat_driver_data->g0_interrupt_array ?
+	       plat_driver_data->g0_interrupt_num :
+	       plat_driver_data->g0_interrupt_num == 0);
+	assert(plat_driver_data->g1s_interrupt_array ?
+	       plat_driver_data->g1s_interrupt_num :
+	       plat_driver_data->g1s_interrupt_num == 0);
+
+	/* Check for system register support */
+	assert(read_id_aa64pfr0_el1() &
+			(ID_AA64PFR0_GIC_MASK << ID_AA64PFR0_GIC_SHIFT));
+
+	/* The GIC version should be 3.0 */
+	gic_version = gicd_read_pidr2(plat_driver_data->gicd_base);
+	gic_version >>=	PIDR2_ARCH_REV_SHIFT;
+	gic_version &= PIDR2_ARCH_REV_MASK;
+	assert(gic_version == ARCH_REV_GICV3);
+
+	/*
+	 * Find out whether the GIC supports the GICv2 compatibility mode. The
+	 * ARE_S bit resets to 0 if supported
+	 */
+	gicv2_compat = gicd_read_ctlr(plat_driver_data->gicd_base);
+	gicv2_compat >>= CTLR_ARE_S_SHIFT;
+	gicv2_compat = !(gicv2_compat & CTLR_ARE_S_MASK);
+
+	/*
+	 * Find the base address of each implemented Redistributor interface.
+	 * The number of interfaces should be equal to the number of CPUs in the
+	 * system. The memory for saving these addresses has to be allocated by
+	 * the platform port
+	 */
+	gicv3_rdistif_base_addrs_probe(plat_driver_data->rdistif_base_addrs,
+					   plat_driver_data->rdistif_num,
+					   plat_driver_data->gicr_base,
+					   plat_driver_data->mpidr_to_core_pos);
+
+	driver_data = plat_driver_data;
+
+	INFO("GICv3 %s legacy support detected."
+			" ARM GICV3 driver initialized in EL3\n",
+			gicv2_compat ? "with" : "without");
+}
+
+/*******************************************************************************
+ * This function initialises the GIC distributor interface based upon the data
+ * provided by the platform while initialising the driver.
+ ******************************************************************************/
+void gicv3_distif_init(void)
+{
+	assert(driver_data);
+	assert(driver_data->gicd_base);
+	assert(driver_data->g1s_interrupt_array);
+	assert(driver_data->g0_interrupt_array);
+
+	assert(IS_IN_EL3());
+
+	/*
+	 * Clear the "enable" bits for G0/G1S/G1NS interrupts before configuring
+	 * the ARE_S bit. The Distributor might generate a system error
+	 * otherwise.
+	 */
+	gicd_clr_ctlr(driver_data->gicd_base,
+		      CTLR_ENABLE_G0_BIT |
+		      CTLR_ENABLE_G1S_BIT |
+		      CTLR_ENABLE_G1NS_BIT,
+		      RWP_TRUE);
+
+	/* Set the ARE_S and ARE_NS bit now that interrupts have been disabled */
+	gicd_set_ctlr(driver_data->gicd_base,
+			CTLR_ARE_S_BIT | CTLR_ARE_NS_BIT, RWP_TRUE);
+
+	/* Set the default attribute of all SPIs */
+	gicv3_spis_configure_defaults(driver_data->gicd_base);
+
+	/* Configure the G1S SPIs */
+	gicv3_secure_spis_configure(driver_data->gicd_base,
+					driver_data->g1s_interrupt_num,
+					driver_data->g1s_interrupt_array,
+					INT_TYPE_G1S);
+
+	/* Configure the G0 SPIs */
+	gicv3_secure_spis_configure(driver_data->gicd_base,
+					driver_data->g0_interrupt_num,
+					driver_data->g0_interrupt_array,
+					INT_TYPE_G0);
+
+	/* Enable the secure SPIs now that they have been configured */
+	gicd_set_ctlr(driver_data->gicd_base,
+		      CTLR_ENABLE_G1S_BIT | CTLR_ENABLE_G0_BIT,
+		      RWP_TRUE);
+}
+
+/*******************************************************************************
+ * This function initialises the GIC Redistributor interface of the calling CPU
+ * (identified by the 'proc_num' parameter) based upon the data provided by the
+ * platform while initialising the driver.
+ ******************************************************************************/
+void gicv3_rdistif_init(unsigned int proc_num)
+{
+	uintptr_t gicr_base;
+
+	assert(driver_data);
+	assert(proc_num < driver_data->rdistif_num);
+	assert(driver_data->rdistif_base_addrs);
+	assert(driver_data->gicd_base);
+	assert(gicd_read_ctlr(driver_data->gicd_base) & CTLR_ARE_S_BIT);
+	assert(driver_data->g1s_interrupt_array);
+	assert(driver_data->g0_interrupt_array);
+
+	assert(IS_IN_EL3());
+
+	gicr_base = driver_data->rdistif_base_addrs[proc_num];
+
+	/* Set the default attribute of all SGIs and PPIs */
+	gicv3_ppi_sgi_configure_defaults(gicr_base);
+
+	/* Configure the G1S SGIs/PPIs */
+	gicv3_secure_ppi_sgi_configure(gicr_base,
+					   driver_data->g1s_interrupt_num,
+					   driver_data->g1s_interrupt_array,
+					   INT_TYPE_G1S);
+
+	/* Configure the G0 SGIs/PPIs */
+	gicv3_secure_ppi_sgi_configure(gicr_base,
+					   driver_data->g0_interrupt_num,
+					   driver_data->g0_interrupt_array,
+					   INT_TYPE_G0);
+}
+
+/*******************************************************************************
+ * This function enables the GIC CPU interface of the calling CPU using only
+ * system register accesses.
+ ******************************************************************************/
+void gicv3_cpuif_enable(unsigned int proc_num)
+{
+	uintptr_t gicr_base;
+	unsigned int scr_el3;
+	unsigned int icc_sre_el3;
+
+	assert(driver_data);
+	assert(proc_num < driver_data->rdistif_num);
+	assert(driver_data->rdistif_base_addrs);
+	assert(IS_IN_EL3());
+
+	/* Mark the connected core as awake */
+	gicr_base = driver_data->rdistif_base_addrs[proc_num];
+	gicv3_rdistif_mark_core_awake(gicr_base);
+
+	/* Disable the legacy interrupt bypass */
+	icc_sre_el3 = ICC_SRE_DIB_BIT | ICC_SRE_DFB_BIT;
+
+	/*
+	 * Enable system register access for EL3 and allow lower exception
+	 * levels to configure the same for themselves. If the legacy mode is
+	 * not supported, the SRE bit is RAO/WI
+	 */
+	icc_sre_el3 |= (ICC_SRE_EN_BIT | ICC_SRE_SRE_BIT);
+	write_icc_sre_el3(read_icc_sre_el3() | icc_sre_el3);
+
+	scr_el3 = read_scr_el3();
+
+	/*
+	 * Switch to NS state to write Non secure ICC_SRE_EL1 and
+	 * ICC_SRE_EL2 registers.
+	 */
+	write_scr_el3(scr_el3 | SCR_NS_BIT);
+	isb();
+
+	write_icc_sre_el2(read_icc_sre_el2() | icc_sre_el3);
+	write_icc_sre_el1(ICC_SRE_SRE_BIT);
+	isb();
+
+	/* Switch to secure state. */
+	write_scr_el3(scr_el3 & (~SCR_NS_BIT));
+	isb();
+
+	/* Program the idle priority in the PMR */
+	write_icc_pmr_el1(GIC_PRI_MASK);
+
+	/* Enable Group0 interrupts */
+	write_icc_igrpen0_el1(IGRPEN1_EL1_ENABLE_G0_BIT);
+
+	/* Enable Group1 Secure interrupts */
+	write_icc_igrpen1_el3(read_icc_igrpen1_el3() |
+				IGRPEN1_EL3_ENABLE_G1S_BIT);
+
+	/* Write the secure ICC_SRE_EL1 register */
+	write_icc_sre_el1(ICC_SRE_SRE_BIT);
+	isb();
+}
+
+/*******************************************************************************
+ * This function disables the GIC CPU interface of the calling CPU using
+ * only system register accesses.
+ ******************************************************************************/
+void gicv3_cpuif_disable(unsigned int proc_num)
+{
+	uintptr_t gicr_base;
+
+	assert(driver_data);
+	assert(proc_num < driver_data->rdistif_num);
+	assert(driver_data->rdistif_base_addrs);
+
+	assert(IS_IN_EL3());
+
+	/* Disable legacy interrupt bypass */
+	write_icc_sre_el3(read_icc_sre_el3() |
+			  (ICC_SRE_DIB_BIT | ICC_SRE_DFB_BIT));
+
+	/* Disable Group0 interrupts */
+	write_icc_igrpen0_el1(read_icc_igrpen0_el1() &
+			      ~IGRPEN1_EL1_ENABLE_G0_BIT);
+
+	/* Disable Group1 Secure interrupts */
+	write_icc_igrpen1_el3(read_icc_igrpen1_el3() &
+			      ~IGRPEN1_EL3_ENABLE_G1S_BIT);
+
+	/* Synchronise accesses to group enable registers */
+	isb();
+
+	/* Mark the connected core as asleep */
+	gicr_base = driver_data->rdistif_base_addrs[proc_num];
+	gicv3_rdistif_mark_core_asleep(gicr_base);
+}
+
+/*******************************************************************************
+ * This function returns the id of the highest priority pending interrupt at
+ * the GIC cpu interface.
+ ******************************************************************************/
+unsigned int gicv3_get_pending_interrupt_id(void)
+{
+	unsigned int id;
+
+	assert(IS_IN_EL3());
+	id = read_icc_hppir0_el1() & HPPIR0_EL1_INTID_MASK;
+
+	/*
+	 * If the ID is special identifier corresponding to G1S or G1NS
+	 * interrupt, then read the highest pending group 1 interrupt.
+	 */
+	if ((id == PENDING_G1S_INTID) || (id == PENDING_G1NS_INTID))
+		return read_icc_hppir1_el1() & HPPIR1_EL1_INTID_MASK;
+
+	return id;
+}
+
+/*******************************************************************************
+ * This function returns the type of the highest priority pending interrupt at
+ * the GIC cpu interface. The return values can be one of the following :
+ *   PENDING_G1S_INTID  : The interrupt type is secure Group 1.
+ *   PENDING_G1NS_INTID : The interrupt type is non secure Group 1.
+ *   0 - 1019           : The interrupt type is secure Group 0.
+ *   GIC_SPURIOUS_INTERRUPT : there is no pending interrupt with
+ *                            sufficient priority to be signaled
+ ******************************************************************************/
+unsigned int gicv3_get_pending_interrupt_type(void)
+{
+	assert(IS_IN_EL3());
+	return read_icc_hppir0_el1() & HPPIR0_EL1_INTID_MASK;
+}
+
+/*******************************************************************************
+ * 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 Secure / Non Secure. The return value can be one of the
+ * following :
+ *    INT_TYPE_G0  : The interrupt type is a Secure Group 0 interrupt
+ *    INT_TYPE_G1S : The interrupt type is a Secure Group 1 secure interrupt
+ *    INT_TYPE_G1NS: The interrupt type is a Secure Group 1 non secure
+ *                   interrupt.
+ ******************************************************************************/
+unsigned int gicv3_get_interrupt_type(unsigned int id,
+					  unsigned int proc_num)
+{
+	unsigned int igroup, grpmodr;
+	uintptr_t gicr_base;
+
+	assert(IS_IN_EL3());
+	assert(driver_data);
+
+	/* Ensure the parameters are valid */
+	assert(id < PENDING_G1S_INTID || id >= MIN_LPI_ID);
+	assert(proc_num < driver_data->rdistif_num);
+
+	/* All LPI interrupts are Group 1 non secure */
+	if (id >= MIN_LPI_ID)
+		return INT_TYPE_G1NS;
+
+	if (id < MIN_SPI_ID) {
+		assert(driver_data->rdistif_base_addrs);
+		gicr_base = driver_data->rdistif_base_addrs[proc_num];
+		igroup = gicr_get_igroupr0(gicr_base, id);
+		grpmodr = gicr_get_igrpmodr0(gicr_base, id);
+	} else {
+		assert(driver_data->gicd_base);
+		igroup = gicd_get_igroupr(driver_data->gicd_base, id);
+		grpmodr = gicd_get_igrpmodr(driver_data->gicd_base, id);
+	}
+
+	/*
+	 * If the IGROUP bit is set, then it is a Group 1 Non secure
+	 * interrupt
+	 */
+	if (igroup)
+		return INT_TYPE_G1NS;
+
+	/* If the GRPMOD bit is set, then it is a Group 1 Secure interrupt */
+	if (grpmodr)
+		return INT_TYPE_G1S;
+
+	/* Else it is a Group 0 Secure interrupt */
+	return INT_TYPE_G0;
+}
diff --git a/drivers/arm/gic/v3/gicv3_private.h b/drivers/arm/gic/v3/gicv3_private.h
new file mode 100644
index 0000000..c8b311a
--- /dev/null
+++ b/drivers/arm/gic/v3/gicv3_private.h
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2015, 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 __GICV3_PRIVATE_H__
+#define __GICV3_PRIVATE_H__
+
+#include <gicv3.h>
+#include <mmio.h>
+#include <stdint.h>
+
+/*******************************************************************************
+ * GICv3 private macro definitions
+ ******************************************************************************/
+
+/* Constants to indicate the status of the RWP bit */
+#define RWP_TRUE		1
+#define RWP_FALSE		0
+
+/*
+ * Macro to wait for updates to :
+ * GICD_CTLR[2:0] - the Group Enables
+ * GICD_CTLR[5:4] - the ARE bits
+ * GICD_ICENABLERn - the clearing of enable state for SPIs
+ */
+#define gicd_wait_for_pending_write(gicd_base)			\
+	do {							\
+		;						\
+	} while (gicd_read_ctlr(gicd_base) & GICD_CTLR_RWP_BIT)
+
+/*
+ * Macro to convert an mpidr to a value suitable for programming into a
+ * GICD_IROUTER. Bits[31:24] in the MPIDR are cleared as they are not relevant
+ * to GICv3.
+ */
+#define gicd_irouter_val_from_mpidr(mpidr, irm)		\
+	((mpidr & ~(0xff << 24)) |			\
+	 (irm & IROUTER_IRM_MASK) << IROUTER_IRM_SHIFT)
+
+/*
+ * Macro to wait for updates to :
+ * GICR_ICENABLER0
+ * GICR_CTLR.DPG1S
+ * GICR_CTLR.DPG1NS
+ * GICR_CTLR.DPG0
+ */
+#define gicr_wait_for_pending_write(gicr_base)			\
+	do {							\
+		;						\
+	} while (gicr_read_ctlr(gicr_base) & GICR_CTLR_RWP_BIT)
+
+/*
+ * Macro to convert a GICR_TYPER affinity value into a MPIDR value. Bits[31:24]
+ * are zeroes.
+ */
+#define mpidr_from_gicr_typer(typer_val)				 \
+	((((typer_val >> 56) & MPIDR_AFFLVL_MASK) << MPIDR_AFF3_SHIFT) | \
+	 ((typer_val >> 32) & 0xffffff))
+
+/*******************************************************************************
+ * Private function prototypes
+ ******************************************************************************/
+unsigned int gicd_read_igrpmodr(uintptr_t base, unsigned int id);
+unsigned int gicr_read_ipriorityr(uintptr_t base, unsigned int id);
+unsigned int gicd_get_igrpmodr(uintptr_t base, unsigned int id);
+unsigned int gicr_get_igrpmodr0(uintptr_t base, unsigned int id);
+unsigned int gicr_get_igroupr0(uintptr_t base, unsigned int id);
+unsigned int gicv3_get_pending_grp1_interrupt_id(unsigned int pending_grp);
+void gicd_write_igrpmodr(uintptr_t base, unsigned int id, unsigned int val);
+void gicr_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val);
+void gicd_set_igrpmodr(uintptr_t base, unsigned int id);
+void gicr_set_igrpmodr0(uintptr_t base, unsigned int id);
+void gicr_set_isenabler0(uintptr_t base, unsigned int id);
+void gicr_set_igroupr0(uintptr_t base, unsigned int id);
+void gicd_clr_igrpmodr(uintptr_t base, unsigned int id);
+void gicr_clr_igrpmodr0(uintptr_t base, unsigned int id);
+void gicr_clr_igroupr0(uintptr_t base, unsigned int id);
+void gicv3_spis_configure_defaults(uintptr_t gicd_base);
+void gicv3_ppi_sgi_configure_defaults(uintptr_t gicr_base);
+void gicv3_secure_spis_configure(uintptr_t gicd_base,
+				     unsigned int num_ints,
+				     const unsigned int *sec_intr_list,
+				     unsigned int int_grp);
+void gicv3_secure_ppi_sgi_configure(uintptr_t gicr_base,
+					unsigned int num_ints,
+					const unsigned int *sec_intr_list,
+					unsigned int int_grp);
+void gicv3_rdistif_base_addrs_probe(uintptr_t *rdistif_base_addrs,
+					unsigned int rdistif_num,
+					uintptr_t gicr_base,
+					mpidr_hash_fn mpidr_to_core_pos);
+void gicv3_rdistif_mark_core_awake(uintptr_t gicr_base);
+void gicv3_rdistif_mark_core_asleep(uintptr_t gicr_base);
+
+/*******************************************************************************
+ * GIC Distributor interface accessors
+ ******************************************************************************/
+static inline unsigned int gicd_read_pidr2(uintptr_t base)
+{
+	return mmio_read_32(base + GICD_PIDR2_GICV3);
+}
+
+static inline unsigned long long gicd_read_irouter(uintptr_t base, unsigned int id)
+{
+	return mmio_read_64(base + GICD_IROUTER + (id << 3));
+}
+
+static inline void gicd_write_irouter(uintptr_t base,
+				      unsigned int id,
+				      unsigned long long affinity)
+{
+	mmio_write_64(base + GICD_IROUTER + (id << 3), affinity);
+}
+
+static inline void gicd_clr_ctlr(uintptr_t base,
+				 unsigned int bitmap,
+				 unsigned int rwp)
+{
+	gicd_write_ctlr(base, gicd_read_ctlr(base) & ~bitmap);
+	if (rwp)
+		gicd_wait_for_pending_write(base);
+}
+
+static inline void gicd_set_ctlr(uintptr_t base,
+				 unsigned int bitmap,
+				 unsigned int rwp)
+{
+	gicd_write_ctlr(base, gicd_read_ctlr(base) | bitmap);
+	if (rwp)
+		gicd_wait_for_pending_write(base);
+}
+
+/*******************************************************************************
+ * GIC Redistributor interface accessors
+ ******************************************************************************/
+static inline unsigned long long gicr_read_ctlr(uintptr_t base)
+{
+	return mmio_read_64(base + GICR_CTLR);
+}
+
+static inline unsigned long long gicr_read_typer(uintptr_t base)
+{
+	return mmio_read_64(base + GICR_TYPER);
+}
+
+static inline unsigned int gicr_read_waker(uintptr_t base)
+{
+	return mmio_read_32(base + GICR_WAKER);
+}
+
+static inline void gicr_write_waker(uintptr_t base, unsigned int val)
+{
+	mmio_write_32(base + GICR_WAKER, val);
+}
+
+static inline unsigned int gicr_read_icenabler0(uintptr_t base)
+{
+	return mmio_read_32(base + GICR_ICENABLER0);
+}
+
+static inline void gicr_write_icenabler0(uintptr_t base, unsigned int val)
+{
+	mmio_write_32(base + GICR_ICENABLER0, val);
+}
+
+static inline unsigned int gicr_read_isenabler0(uintptr_t base)
+{
+	return mmio_read_32(base + GICR_ISENABLER0);
+}
+
+static inline void gicr_write_isenabler0(uintptr_t base, unsigned int val)
+{
+	mmio_write_32(base + GICR_ISENABLER0, val);
+}
+
+static inline unsigned int gicr_read_igroupr0(uintptr_t base)
+{
+	return mmio_read_32(base + GICR_IGROUPR0);
+}
+
+static inline void gicr_write_igroupr0(uintptr_t base, unsigned int val)
+{
+	mmio_write_32(base + GICR_IGROUPR0, val);
+}
+
+static inline unsigned int gicr_read_igrpmodr0(uintptr_t base)
+{
+	return mmio_read_32(base + GICR_IGRPMODR0);
+}
+
+static inline void gicr_write_igrpmodr0(uintptr_t base, unsigned int val)
+{
+	mmio_write_32(base + GICR_IGRPMODR0, val);
+}
+
+static inline unsigned int gicr_read_icfgr1(uintptr_t base)
+{
+	return mmio_read_32(base + GICR_ICFGR1);
+}
+
+static inline void gicr_write_icfgr1(uintptr_t base, unsigned int val)
+{
+	mmio_write_32(base + GICR_ICFGR1, val);
+}
+
+#endif /* __GICV3_PRIVATE_H__ */
diff --git a/include/common/asm_macros.S b/include/common/asm_macros.S
index 128259f..a331c05 100644
--- a/include/common/asm_macros.S
+++ b/include/common/asm_macros.S
@@ -101,10 +101,10 @@
 
 	/*
 	 * Theses macros are used to create function labels for deprecated
-	 * APIs. If WARN_DEPRECATED is non zero, the callers of these APIs
+	 * APIs. If ERROR_DEPRECATED is non zero, the callers of these APIs
 	 * will fail to link and cause build failure.
 	 */
-#if WARN_DEPRECATED
+#if ERROR_DEPRECATED
 	.macro func_deprecated _name
 	func deprecated\_name
 	.endm
diff --git a/include/drivers/arm/arm_gic.h b/include/drivers/arm/arm_gic.h
index 5752d8f..8c1f03f 100644
--- a/include/drivers/arm/arm_gic.h
+++ b/include/drivers/arm/arm_gic.h
@@ -31,6 +31,7 @@
 #ifndef __ARM_GIC_H__
 #define __ARM_GIC_H__
 
+#include <common_def.h>
 #include <stdint.h>
 
 /*******************************************************************************
@@ -40,18 +41,18 @@
 		  uintptr_t gicd_base,
 		  uintptr_t gicr_base,
 		  const unsigned int *irq_sec_ptr,
-		  unsigned int num_irqs);
-void arm_gic_setup(void);
-void arm_gic_cpuif_deactivate(void);
-void arm_gic_cpuif_setup(void);
-void arm_gic_pcpu_distif_setup(void);
+		  unsigned int num_irqs) __warn_deprecated;
+void arm_gic_setup(void) __warn_deprecated;
+void arm_gic_cpuif_deactivate(void) __warn_deprecated;
+void arm_gic_cpuif_setup(void) __warn_deprecated;
+void arm_gic_pcpu_distif_setup(void) __warn_deprecated;
 
 uint32_t arm_gic_interrupt_type_to_line(uint32_t type,
-				uint32_t security_state);
-uint32_t arm_gic_get_pending_interrupt_type(void);
-uint32_t arm_gic_get_pending_interrupt_id(void);
-uint32_t arm_gic_acknowledge_interrupt(void);
-void arm_gic_end_of_interrupt(uint32_t id);
-uint32_t arm_gic_get_interrupt_type(uint32_t id);
+				uint32_t security_state) __warn_deprecated;
+uint32_t arm_gic_get_pending_interrupt_type(void) __warn_deprecated;
+uint32_t arm_gic_get_pending_interrupt_id(void) __warn_deprecated;
+uint32_t arm_gic_acknowledge_interrupt(void) __warn_deprecated;
+void arm_gic_end_of_interrupt(uint32_t id) __warn_deprecated;
+uint32_t arm_gic_get_interrupt_type(uint32_t id) __warn_deprecated;
 
 #endif /* __GIC_H__ */
diff --git a/include/drivers/arm/gic_common.h b/include/drivers/arm/gic_common.h
new file mode 100644
index 0000000..6a322a2
--- /dev/null
+++ b/include/drivers/arm/gic_common.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2015, 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 __GIC_COMMON_H__
+#define __GIC_COMMON_H__
+
+/*******************************************************************************
+ * GIC Distributor interface general definitions
+ ******************************************************************************/
+/* Constants to categorise interrupts */
+#define MIN_SGI_ID		0
+#define MIN_PPI_ID		16
+#define MIN_SPI_ID		32
+
+/* Mask for the priority field common to all GIC interfaces */
+#define GIC_PRI_MASK			0xff
+
+/* Constant to indicate a spurious interrupt in all GIC versions */
+#define GIC_SPURIOUS_INTERRUPT		1023
+
+/* Constants to categorise priorities */
+#define GIC_HIGHEST_SEC_PRIORITY	0
+#define GIC_LOWEST_SEC_PRIORITY		127
+#define GIC_HIGHEST_NS_PRIORITY		128
+#define GIC_LOWEST_NS_PRIORITY		254 /* 255 would disable an interrupt */
+
+/*******************************************************************************
+ * GIC Distributor interface register offsets that are common to GICv3 & GICv2
+ ******************************************************************************/
+#define GICD_CTLR		0x0
+#define GICD_TYPER		0x4
+#define GICD_IIDR		0x8
+#define GICD_IGROUPR		0x80
+#define GICD_ISENABLER		0x100
+#define GICD_ICENABLER		0x180
+#define GICD_ISPENDR		0x200
+#define GICD_ICPENDR		0x280
+#define GICD_ISACTIVER		0x300
+#define GICD_ICACTIVER		0x380
+#define GICD_IPRIORITYR		0x400
+#define GICD_ICFGR		0xc00
+#define GICD_NSACR		0xe00
+
+/* GICD_CTLR bit definitions */
+#define CTLR_ENABLE_G0_SHIFT		0
+#define CTLR_ENABLE_G0_MASK		0x1
+#define CTLR_ENABLE_G0_BIT		(1 << CTLR_ENABLE_G0_SHIFT)
+
+
+/*******************************************************************************
+ * GIC Distributor interface register constants that are common to GICv3 & GICv2
+ ******************************************************************************/
+#define PIDR2_ARCH_REV_SHIFT	4
+#define PIDR2_ARCH_REV_MASK	0xf
+
+/* GICv3 revision as reported by the PIDR2 register */
+#define ARCH_REV_GICV3		0x3
+/* GICv2 revision as reported by the PIDR2 register */
+#define ARCH_REV_GICV2		0x2
+
+#define IGROUPR_SHIFT		5
+#define ISENABLER_SHIFT		5
+#define ICENABLER_SHIFT		ISENABLER_SHIFT
+#define ISPENDR_SHIFT		5
+#define ICPENDR_SHIFT		ISPENDR_SHIFT
+#define ISACTIVER_SHIFT		5
+#define ICACTIVER_SHIFT		ISACTIVER_SHIFT
+#define IPRIORITYR_SHIFT	2
+#define ICFGR_SHIFT		4
+#define NSACR_SHIFT		4
+
+/* GICD_TYPER shifts and masks */
+#define TYPER_IT_LINES_NO_SHIFT	0
+#define TYPER_IT_LINES_NO_MASK	0x1f
+
+/* Value used to initialize Normal world interrupt 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))
+
+#ifndef __ASSEMBLY__
+
+#include <mmio.h>
+#include <stdint.h>
+
+/*******************************************************************************
+ * GIC Distributor interface register accessors that are common to GICv3 & GICv2
+ ******************************************************************************/
+static inline unsigned int gicd_read_ctlr(uintptr_t base)
+{
+	return mmio_read_32(base + GICD_CTLR);
+}
+
+static inline unsigned int gicd_read_typer(uintptr_t base)
+{
+	return mmio_read_32(base + GICD_TYPER);
+}
+
+static inline unsigned int gicd_read_iidr(uintptr_t base)
+{
+	return mmio_read_32(base + GICD_IIDR);
+}
+
+static inline void gicd_write_ctlr(uintptr_t base, unsigned int val)
+{
+	mmio_write_32(base + GICD_CTLR, val);
+}
+
+/*******************************************************************************
+ * GIC Distributor function prototypes
+ ******************************************************************************/
+unsigned int gicd_read_igroupr(uintptr_t base, unsigned int id);
+unsigned int gicd_read_isenabler(uintptr_t base, unsigned int id);
+unsigned int gicd_read_icenabler(uintptr_t base, unsigned int id);
+unsigned int gicd_read_ispendr(uintptr_t base, unsigned int id);
+unsigned int gicd_read_icpendr(uintptr_t base, unsigned int id);
+unsigned int gicd_read_isactiver(uintptr_t base, unsigned int id);
+unsigned int gicd_read_icactiver(uintptr_t base, unsigned int id);
+unsigned int gicd_read_ipriorityr(uintptr_t base, unsigned int id);
+unsigned int gicd_read_icfgr(uintptr_t base, unsigned int id);
+unsigned int gicd_read_nsacr(uintptr_t base, unsigned int id);
+void gicd_write_igroupr(uintptr_t base, unsigned int id, unsigned int val);
+void gicd_write_isenabler(uintptr_t base, unsigned int id, unsigned int val);
+void gicd_write_icenabler(uintptr_t base, unsigned int id, unsigned int val);
+void gicd_write_ispendr(uintptr_t base, unsigned int id, unsigned int val);
+void gicd_write_icpendr(uintptr_t base, unsigned int id, unsigned int val);
+void gicd_write_isactiver(uintptr_t base, unsigned int id, unsigned int val);
+void gicd_write_icactiver(uintptr_t base, unsigned int id, unsigned int val);
+void gicd_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val);
+void gicd_write_icfgr(uintptr_t base, unsigned int id, unsigned int val);
+void gicd_write_nsacr(uintptr_t base, unsigned int id, unsigned int val);
+unsigned int gicd_get_igroupr(uintptr_t base, unsigned int id);
+void gicd_set_igroupr(uintptr_t base, unsigned int id);
+void gicd_clr_igroupr(uintptr_t base, unsigned int id);
+void gicd_set_isenabler(uintptr_t base, unsigned int id);
+void gicd_set_icenabler(uintptr_t base, unsigned int id);
+void gicd_set_ispendr(uintptr_t base, unsigned int id);
+void gicd_set_icpendr(uintptr_t base, unsigned int id);
+void gicd_set_isactiver(uintptr_t base, unsigned int id);
+void gicd_set_icactiver(uintptr_t base, unsigned int id);
+
+
+#endif /* __ASSEMBLY__ */
+#endif /* __GIC_COMMON_H__ */
diff --git a/include/drivers/arm/gic_v2.h b/include/drivers/arm/gic_v2.h
index ce9311e..594ce49 100644
--- a/include/drivers/arm/gic_v2.h
+++ b/include/drivers/arm/gic_v2.h
@@ -31,6 +31,13 @@
 #ifndef __GIC_V2_H__
 #define __GIC_V2_H__
 
+/******************************************************************************
+ * THIS DRIVER IS DEPRECATED. For GICv2 systems, use the driver in gicv2.h
+ * and for GICv3 systems, use the driver in gicv3.h.
+ *****************************************************************************/
+#if ERROR_DEPRECATED
+#error " The legacy ARM GIC driver is deprecated."
+#endif
 
 #define GIC400_NUM_SPIS		480
 #define MAX_PPIS		14
diff --git a/include/drivers/arm/gic_v3.h b/include/drivers/arm/gic_v3.h
index c410626..a1b6f1b 100644
--- a/include/drivers/arm/gic_v3.h
+++ b/include/drivers/arm/gic_v3.h
@@ -31,6 +31,14 @@
 #ifndef __GIC_V3_H__
 #define __GIC_V3_H__
 
+/******************************************************************************
+ * THIS DRIVER IS DEPRECATED. For GICv2 systems, use the driver in gicv2.h
+ * and for GICv3 systems, use the driver in gicv3.h.
+ *****************************************************************************/
+#if ERROR_DEPRECATED
+#error " The legacy ARM GIC driver is deprecated."
+#endif
+
 #include <mmio.h>
 #include <stdint.h>
 
diff --git a/include/drivers/arm/gicv2.h b/include/drivers/arm/gicv2.h
new file mode 100644
index 0000000..88dc015
--- /dev/null
+++ b/include/drivers/arm/gicv2.h
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2015, 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 __GICV2_H__
+#define __GICV2_H__
+
+/*******************************************************************************
+ * GICv2 miscellaneous definitions
+ ******************************************************************************/
+/* Interrupt IDs reported by the HPPIR and IAR registers */
+#define PENDING_G1_INTID	1022
+
+/*******************************************************************************
+ * GICv2 specific Distributor interface register offsets and constants.
+ ******************************************************************************/
+#define GICD_ITARGETSR		0x800
+#define GICD_SGIR		0xF00
+#define GICD_CPENDSGIR		0xF10
+#define GICD_SPENDSGIR		0xF20
+#define GICD_PIDR2_GICV2	0xFE8
+
+#define ITARGETSR_SHIFT		2
+#define GIC_TARGET_CPU_MASK	0xff
+
+#define CPENDSGIR_SHIFT		2
+#define SPENDSGIR_SHIFT		CPENDSGIR_SHIFT
+
+/*******************************************************************************
+ * GICv2 specific CPU interface register offsets and constants.
+ ******************************************************************************/
+/* Physical CPU Interface registers */
+#define GICC_CTLR		0x0
+#define GICC_PMR		0x4
+#define GICC_BPR		0x8
+#define GICC_IAR		0xC
+#define GICC_EOIR		0x10
+#define GICC_RPR		0x14
+#define GICC_HPPIR		0x18
+#define GICC_AHPPIR		0x28
+#define GICC_IIDR		0xFC
+#define GICC_DIR		0x1000
+#define GICC_PRIODROP		GICC_EOIR
+
+/* GICC_CTLR bit definitions */
+#define EOI_MODE_NS		(1 << 10)
+#define EOI_MODE_S		(1 << 9)
+#define IRQ_BYP_DIS_GRP1	(1 << 8)
+#define FIQ_BYP_DIS_GRP1	(1 << 7)
+#define IRQ_BYP_DIS_GRP0	(1 << 6)
+#define FIQ_BYP_DIS_GRP0	(1 << 5)
+#define CBPR			(1 << 4)
+#define FIQ_EN_SHIFT		3
+#define FIQ_EN_BIT		(1 << FIQ_EN_SHIFT)
+#define ACK_CTL			(1 << 2)
+
+/* GICC_IIDR bit masks and shifts */
+#define GICC_IIDR_PID_SHIFT	20
+#define GICC_IIDR_ARCH_SHIFT	16
+#define GICC_IIDR_REV_SHIFT	12
+#define GICC_IIDR_IMP_SHIFT	0
+
+#define GICC_IIDR_PID_MASK	0xfff
+#define GICC_IIDR_ARCH_MASK	0xf
+#define GICC_IIDR_REV_MASK	0xf
+#define GICC_IIDR_IMP_MASK	0xfff
+
+/* HYP view virtual CPU Interface registers */
+#define GICH_CTL		0x0
+#define GICH_VTR		0x4
+#define GICH_ELRSR0		0x30
+#define GICH_ELRSR1		0x34
+#define GICH_APR0		0xF0
+#define GICH_LR_BASE		0x100
+
+/* Virtual CPU Interface registers */
+#define GICV_CTL		0x0
+#define GICV_PRIMASK		0x4
+#define GICV_BP			0x8
+#define GICV_INTACK		0xC
+#define GICV_EOI		0x10
+#define GICV_RUNNINGPRI		0x14
+#define GICV_HIGHESTPEND	0x18
+#define GICV_DEACTIVATE		0x1000
+
+/* GICD_CTLR bit definitions */
+#define CTLR_ENABLE_G1_SHIFT		1
+#define CTLR_ENABLE_G1_MASK		0x1
+#define CTLR_ENABLE_G1_BIT		(1 << CTLR_ENABLE_G1_SHIFT)
+
+/* Interrupt ID mask for HPPIR, AHPPIR, IAR and AIAR CPU Interface registers */
+#define INT_ID_MASK		0x3ff
+
+#ifndef __ASSEMBLY__
+
+#include <stdint.h>
+
+/*******************************************************************************
+ * This structure describes some of the implementation defined attributes of
+ * the GICv2 IP. It is used by the platform port to specify these attributes
+ * in order to initialize the GICv2 driver. The attributes are described
+ * below.
+ *
+ * 1. The 'gicd_base' field contains the base address of the Distributor
+ *    interface programmer's view.
+ *
+ * 2. The 'gicc_base' field contains the base address of the CPU Interface
+ *    programmer's view.
+ *
+ * 3. The 'g0_interrupt_array' field is a pointer to an array in which each
+ *    entry corresponds to an ID of a Group 0 interrupt.
+ *
+ * 4. The 'g0_interrupt_num' field contains the number of entries in the
+ *    'g0_interrupt_array'.
+ ******************************************************************************/
+typedef struct gicv2_driver_data {
+	uintptr_t gicd_base;
+	uintptr_t gicc_base;
+	unsigned int g0_interrupt_num;
+	const unsigned int *g0_interrupt_array;
+} gicv2_driver_data_t;
+
+/*******************************************************************************
+ * Function prototypes
+ ******************************************************************************/
+void gicv2_driver_init(const gicv2_driver_data_t *plat_driver_data);
+void gicv2_distif_init(void);
+void gicv2_pcpu_distif_init(void);
+void gicv2_cpuif_enable(void);
+void gicv2_cpuif_disable(void);
+unsigned int gicv2_is_fiq_enabled(void);
+unsigned int gicv2_get_pending_interrupt_type(void);
+unsigned int gicv2_get_pending_interrupt_id(void);
+unsigned int gicv2_acknowledge_interrupt(void);
+void gicv2_end_of_interrupt(unsigned int id);
+unsigned int gicv2_get_interrupt_group(unsigned int id);
+
+#endif /* __ASSEMBLY__ */
+#endif /* __GICV2_H__ */
diff --git a/include/drivers/arm/gicv3.h b/include/drivers/arm/gicv3.h
new file mode 100644
index 0000000..e874f5c
--- /dev/null
+++ b/include/drivers/arm/gicv3.h
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 2015, 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 __GICV3_H__
+#define __GICV3_H__
+
+/*******************************************************************************
+ * GICv3 miscellaneous definitions
+ ******************************************************************************/
+/* Interrupt group definitions */
+#define INT_TYPE_G1S		0
+#define INT_TYPE_G0		1
+#define INT_TYPE_G1NS		2
+
+/* Interrupt IDs reported by the HPPIR and IAR registers */
+#define PENDING_G1S_INTID	1020
+#define PENDING_G1NS_INTID	1021
+
+/* Constant to categorize LPI interrupt */
+#define MIN_LPI_ID		8192
+
+/*******************************************************************************
+ * GICv3 specific Distributor interface register offsets and constants.
+ ******************************************************************************/
+#define GICD_STATUSR		0x10
+#define GICD_SETSPI_NSR		0x40
+#define GICD_CLRSPI_NSR		0x48
+#define GICD_SETSPI_SR		0x50
+#define GICD_CLRSPI_SR		0x50
+#define GICD_IGRPMODR		0xd00
+#define GICD_IROUTER		0x6100
+#define GICD_PIDR2_GICV3	0xffe8
+
+#define IGRPMODR_SHIFT		5
+
+/* GICD_CTLR bit definitions */
+#define CTLR_ENABLE_G1NS_SHIFT		1
+#define CTLR_ENABLE_G1S_SHIFT		2
+#define CTLR_ARE_S_SHIFT		4
+#define CTLR_ARE_NS_SHIFT		5
+#define CTLR_DS_SHIFT			6
+#define CTLR_E1NWF_SHIFT		7
+#define GICD_CTLR_RWP_SHIFT		31
+
+#define CTLR_ENABLE_G1NS_MASK		0x1
+#define CTLR_ENABLE_G1S_MASK		0x1
+#define CTLR_ARE_S_MASK			0x1
+#define CTLR_ARE_NS_MASK		0x1
+#define CTLR_DS_MASK			0x1
+#define CTLR_E1NWF_MASK			0x1
+#define GICD_CTLR_RWP_MASK		0x1
+
+#define CTLR_ENABLE_G1NS_BIT		(1 << CTLR_ENABLE_G1NS_SHIFT)
+#define CTLR_ENABLE_G1S_BIT		(1 << CTLR_ENABLE_G1S_SHIFT)
+#define CTLR_ARE_S_BIT			(1 << CTLR_ARE_S_SHIFT)
+#define CTLR_ARE_NS_BIT			(1 << CTLR_ARE_NS_SHIFT)
+#define CTLR_DS_BIT			(1 << CTLR_DS_SHIFT)
+#define CTLR_E1NWF_BIT			(1 << CTLR_E1NWF_SHIFT)
+#define GICD_CTLR_RWP_BIT		(1 << GICD_CTLR_RWP_SHIFT)
+
+/* GICD_IROUTER shifts and masks */
+#define IROUTER_IRM_SHIFT	31
+#define IROUTER_IRM_MASK	0x1
+
+/*******************************************************************************
+ * GICv3 Re-distributor interface registers & constants
+ ******************************************************************************/
+#define GICR_PCPUBASE_SHIFT	0x11
+#define GICR_SGIBASE_OFFSET	(1 << 0x10)	/* 64 KB */
+#define GICR_CTLR		0x0
+#define GICR_TYPER		0x08
+#define GICR_WAKER		0x14
+#define GICR_IGROUPR0		(GICR_SGIBASE_OFFSET + 0x80)
+#define GICR_ISENABLER0		(GICR_SGIBASE_OFFSET + 0x100)
+#define GICR_ICENABLER0		(GICR_SGIBASE_OFFSET + 0x180)
+#define GICR_IPRIORITYR		(GICR_SGIBASE_OFFSET + 0x400)
+#define GICR_ICFGR0		(GICR_SGIBASE_OFFSET + 0xc00)
+#define GICR_ICFGR1		(GICR_SGIBASE_OFFSET + 0xc04)
+#define GICR_IGRPMODR0		(GICR_SGIBASE_OFFSET + 0xd00)
+
+/* GICR_CTLR bit definitions */
+#define GICR_CTLR_RWP_SHIFT	3
+#define GICR_CTLR_RWP_MASK	0x1
+#define GICR_CTLR_RWP_BIT	(1 << GICR_CTLR_RWP_SHIFT)
+
+/* GICR_WAKER bit definitions */
+#define WAKER_CA_SHIFT		2
+#define WAKER_PS_SHIFT		1
+
+#define WAKER_CA_MASK		0x1
+#define WAKER_PS_MASK		0x1
+
+#define WAKER_CA_BIT		(1 << WAKER_CA_SHIFT)
+#define WAKER_PS_BIT		(1 << WAKER_PS_SHIFT)
+
+/* GICR_TYPER bit definitions */
+#define TYPER_AFF_VAL_SHIFT	32
+#define TYPER_PROC_NUM_SHIFT	8
+#define TYPER_LAST_SHIFT	4
+
+#define TYPER_AFF_VAL_MASK	0xffffffff
+#define TYPER_PROC_NUM_MASK	0xffff
+#define TYPER_LAST_MASK		0x1
+
+#define TYPER_LAST_BIT		(1 << TYPER_LAST_SHIFT)
+
+/*******************************************************************************
+ * GICv3 CPU interface registers & constants
+ ******************************************************************************/
+/* ICC_SRE bit definitions*/
+#define ICC_SRE_EN_BIT		(1 << 3)
+#define ICC_SRE_DIB_BIT		(1 << 2)
+#define ICC_SRE_DFB_BIT		(1 << 1)
+#define ICC_SRE_SRE_BIT		(1 << 0)
+
+/* ICC_IGRPEN1_EL3 bit definitions */
+#define IGRPEN1_EL3_ENABLE_G1NS_SHIFT	0
+#define IGRPEN1_EL3_ENABLE_G1S_SHIFT	1
+
+#define IGRPEN1_EL3_ENABLE_G1NS_BIT	(1 << IGRPEN1_EL3_ENABLE_G1NS_SHIFT)
+#define IGRPEN1_EL3_ENABLE_G1S_BIT	(1 << IGRPEN1_EL3_ENABLE_G1S_SHIFT)
+
+/* ICC_IGRPEN0_EL1 bit definitions */
+#define IGRPEN1_EL1_ENABLE_G0_SHIFT	0
+#define IGRPEN1_EL1_ENABLE_G0_BIT	(1 << IGRPEN1_EL1_ENABLE_G0_SHIFT)
+
+/* ICC_HPPIR0_EL1 bit definitions */
+#define HPPIR0_EL1_INTID_SHIFT		0
+#define HPPIR0_EL1_INTID_MASK		0xffffff
+
+/* ICC_HPPIR1_EL1 bit definitions */
+#define HPPIR1_EL1_INTID_SHIFT		0
+#define HPPIR1_EL1_INTID_MASK		0xffffff
+
+/* ICC_IAR0_EL1 bit definitions */
+#define IAR0_EL1_INTID_SHIFT		0
+#define IAR0_EL1_INTID_MASK		0xffffff
+
+/* ICC_IAR1_EL1 bit definitions */
+#define IAR1_EL1_INTID_SHIFT		0
+#define IAR1_EL1_INTID_MASK		0xffffff
+
+#ifndef __ASSEMBLY__
+
+#include <stdint.h>
+
+#define gicv3_is_intr_id_special_identifier(id)	\
+	(((id) >= PENDING_G1S_INTID) && ((id) <= GIC_SPURIOUS_INTERRUPT))
+
+/*******************************************************************************
+ * Helper GICv3 macros for SEL1
+ ******************************************************************************/
+#define gicv3_acknowledge_interrupt_sel1()	read_icc_iar1_el1() &\
+							IAR1_EL1_INTID_MASK
+#define gicv3_get_pending_interrupt_id_sel1()	read_icc_hppir1_el1() &\
+							HPPIR1_EL1_INTID_MASK
+#define gicv3_end_of_interrupt_sel1(id)		write_icc_eoir1_el1(id)
+
+
+/*******************************************************************************
+ * Helper GICv3 macros for EL3
+ ******************************************************************************/
+#define gicv3_acknowledge_interrupt()		read_icc_iar0_el1() &\
+							IAR0_EL1_INTID_MASK
+#define gicv3_end_of_interrupt(id)		write_icc_eoir0_el1(id)
+
+/*******************************************************************************
+ * This structure describes some of the implementation defined attributes of the
+ * GICv3 IP. It is used by the platform port to specify these attributes in order
+ * to initialise the GICV3 driver. The attributes are described below.
+ *
+ * 1. The 'gicd_base' field contains the base address of the Distributor
+ *    interface programmer's view.
+ *
+ * 2. The 'gicr_base' field contains the base address of the Re-distributor
+ *    interface programmer's view.
+ *
+ * 3. The 'g0_interrupt_array' field is a ponter to an array in which each
+ *    entry corresponds to an ID of a Group 0 interrupt.
+ *
+ * 4. The 'g0_interrupt_num' field contains the number of entries in the
+ *    'g0_interrupt_array'.
+ *
+ * 5. The 'g1s_interrupt_array' field is a ponter to an array in which each
+ *    entry corresponds to an ID of a Group 1 interrupt.
+ *
+ * 6. The 'g1s_interrupt_num' field contains the number of entries in the
+ *    'g1s_interrupt_array'.
+ *
+ * 7. The 'rdistif_num' field contains the number of Redistributor interfaces
+ *    the GIC implements. This is equal to the number of CPUs or CPU interfaces
+ *    instantiated in the GIC.
+ *
+ * 8. The 'rdistif_base_addrs' field is a pointer to an array that has an entry
+ *    for storing the base address of the Redistributor interface frame of each
+ *    CPU in the system. The size of the array = 'rdistif_num'. The base
+ *    addresses are detected during driver initialisation.
+ *
+ * 9. The 'mpidr_to_core_pos' field is a pointer to a hash function which the
+ *    driver will use to convert an MPIDR value to a linear core index. This
+ *    index will be used for accessing the 'rdistif_base_addrs' array. This is
+ *    an optional field. A GICv3 implementation maps each MPIDR to a linear core
+ *    index as well. This mapping can be found by reading the "Affinity Value"
+ *    and "Processor Number" fields in the GICR_TYPER. It is IMP. DEF. if the
+ *    "Processor Numbers" are suitable to index into an array to access core
+ *    specific information. If this not the case, the platform port must provide
+ *    a hash function. Otherwise, the "Processor Number" field will be used to
+ *    access the array elements.
+ ******************************************************************************/
+typedef unsigned int (*mpidr_hash_fn)(unsigned long mpidr);
+
+typedef struct gicv3_driver_data {
+	uintptr_t gicd_base;
+	uintptr_t gicr_base;
+	unsigned int g0_interrupt_num;
+	unsigned int g1s_interrupt_num;
+	const unsigned int *g0_interrupt_array;
+	const unsigned int *g1s_interrupt_array;
+	unsigned int rdistif_num;
+	uintptr_t *rdistif_base_addrs;
+	mpidr_hash_fn mpidr_to_core_pos;
+} gicv3_driver_data_t;
+
+/*******************************************************************************
+ * GICv3 EL3 driver API
+ ******************************************************************************/
+void gicv3_driver_init(const gicv3_driver_data_t *plat_driver_data);
+void gicv3_distif_init(void);
+void gicv3_rdistif_init(unsigned int proc_num);
+void gicv3_cpuif_enable(unsigned int proc_num);
+void gicv3_cpuif_disable(unsigned int proc_num);
+unsigned int gicv3_get_pending_interrupt_type(void);
+unsigned int gicv3_get_pending_interrupt_id(void);
+unsigned int gicv3_get_interrupt_type(unsigned int id,
+					  unsigned int proc_num);
+
+
+#endif /* __ASSEMBLY__ */
+#endif /* __GICV3_H__ */
diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h
index 912643d..49efafc 100644
--- a/include/lib/aarch64/arch.h
+++ b/include/lib/aarch64/arch.h
@@ -88,6 +88,14 @@
 #define ICC_CTLR_EL1    S3_0_C12_C12_4
 #define ICC_CTLR_EL3    S3_6_C12_C12_4
 #define ICC_PMR_EL1     S3_0_C4_C6_0
+#define ICC_IGRPEN1_EL3 S3_6_c12_c12_7
+#define ICC_IGRPEN0_EL1 S3_0_c12_c12_6
+#define ICC_HPPIR0_EL1  S3_0_c12_c8_2
+#define ICC_HPPIR1_EL1  S3_0_c12_c12_2
+#define ICC_IAR0_EL1    S3_0_c12_c8_0
+#define ICC_IAR1_EL1    S3_0_c12_c12_0
+#define ICC_EOIR0_EL1   S3_0_c12_c8_1
+#define ICC_EOIR1_EL1   S3_0_c12_c12_1
 
 /*******************************************************************************
  * Generic timer memory mapped registers & offsets
@@ -122,6 +130,10 @@
 #define ID_AA64PFR0_EL3_SHIFT	12
 #define ID_AA64PFR0_ELX_MASK	0xf
 
+#define ID_AA64PFR0_GIC_SHIFT	24
+#define ID_AA64PFR0_GIC_WIDTH	4
+#define ID_AA64PFR0_GIC_MASK	((1 << ID_AA64PFR0_GIC_WIDTH) - 1)
+
 /* ID_PFR1_EL1 definitions */
 #define ID_PFR1_VIRTEXT_SHIFT	12
 #define ID_PFR1_VIRTEXT_MASK	0xf
@@ -134,7 +146,7 @@
 			(1 << 4))
 
 #define SCTLR_EL1_RES1  ((1 << 29) | (1 << 28) | (1 << 23) | (1 << 22) | \
-			(1 << 11))
+			(1 << 20) | (1 << 11))
 #define SCTLR_AARCH32_EL1_RES1 \
 			((1 << 23) | (1 << 22) | (1 << 11) | (1 << 4) | \
 			(1 << 3))
diff --git a/include/lib/aarch64/arch_helpers.h b/include/lib/aarch64/arch_helpers.h
index d01ea31..43c6917 100644
--- a/include/lib/aarch64/arch_helpers.h
+++ b/include/lib/aarch64/arch_helpers.h
@@ -74,6 +74,14 @@
 	_DEFINE_SYSREG_READ_FUNC(_name, _reg_name)	\
 	_DEFINE_SYSREG_WRITE_FUNC(_name, _reg_name)
 
+/* Define read function for renamed system register */
+#define DEFINE_RENAME_SYSREG_READ_FUNC(_name, _reg_name)	\
+	_DEFINE_SYSREG_READ_FUNC(_name, _reg_name)
+
+/* Define write function for renamed system register */
+#define DEFINE_RENAME_SYSREG_WRITE_FUNC(_name, _reg_name)	\
+	_DEFINE_SYSREG_WRITE_FUNC(_name, _reg_name)
+
 /* Define write function for special system registers */
 #define DEFINE_SYSREG_WRITE_CONST_FUNC(_name)		\
 	_DEFINE_SYSREG_WRITE_CONST_FUNC(_name, _name)
@@ -284,12 +292,18 @@
 
 DEFINE_SYSREG_READ_FUNC(ctr_el0)
 
-/* GICv3 System Registers */
-
 DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sre_el1, ICC_SRE_EL1)
 DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sre_el2, ICC_SRE_EL2)
 DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sre_el3, ICC_SRE_EL3)
 DEFINE_RENAME_SYSREG_RW_FUNCS(icc_pmr_el1, ICC_PMR_EL1)
+DEFINE_RENAME_SYSREG_RW_FUNCS(icc_igrpen1_el3, ICC_IGRPEN1_EL3)
+DEFINE_RENAME_SYSREG_RW_FUNCS(icc_igrpen0_el1, ICC_IGRPEN0_EL1)
+DEFINE_RENAME_SYSREG_READ_FUNC(icc_hppir0_el1, ICC_HPPIR0_EL1)
+DEFINE_RENAME_SYSREG_READ_FUNC(icc_hppir1_el1, ICC_HPPIR1_EL1)
+DEFINE_RENAME_SYSREG_READ_FUNC(icc_iar0_el1, ICC_IAR0_EL1)
+DEFINE_RENAME_SYSREG_READ_FUNC(icc_iar1_el1, ICC_IAR1_EL1)
+DEFINE_RENAME_SYSREG_WRITE_FUNC(icc_eoir0_el1, ICC_EOIR0_EL1)
+DEFINE_RENAME_SYSREG_WRITE_FUNC(icc_eoir1_el1, ICC_EOIR1_EL1)
 
 
 #define IS_IN_EL(x) \
diff --git a/include/lib/cpus/aarch64/cortex_a72.h b/include/lib/cpus/aarch64/cortex_a72.h
index bb32f9b..fa10ca9 100644
--- a/include/lib/cpus/aarch64/cortex_a72.h
+++ b/include/lib/cpus/aarch64/cortex_a72.h
@@ -62,6 +62,7 @@
 #define L2CTLR_TAG_RAM_LATENCY_SHIFT	6
 
 #define L2_DATA_RAM_LATENCY_3_CYCLES	0x2
+#define L2_TAG_RAM_LATENCY_2_CYCLES	0x1
 #define L2_TAG_RAM_LATENCY_3_CYCLES	0x2
 
 #endif /* __CORTEX_A72_H__ */
diff --git a/include/plat/common/common_def.h b/include/plat/common/common_def.h
index 077080d..43c69cc 100644
--- a/include/plat/common/common_def.h
+++ b/include/plat/common/common_def.h
@@ -69,15 +69,10 @@
 
 /*
  * Macros to wrap declarations of deprecated APIs within Trusted Firmware.
- * The callers of these APIs will continue to compile as long as the build
- * flag WARN_DEPRECATED is zero. Else the compiler will emit a warning
- * when the callers of these APIs are compiled.
+ * The callers of these APIs will continue to compile with a warning as long
+ * as the build flag ERROR_DEPRECATED is zero.
  */
-#if WARN_DEPRECATED
 #define __warn_deprecated	__attribute__ ((deprecated))
-#else
-#define __warn_deprecated
-#endif
 
 #endif /* __COMMON_DEF_H__ */
 
diff --git a/make_helpers/tbbr/tbbr_tools.mk b/make_helpers/tbbr/tbbr_tools.mk
index 58c84d2..2ec72b9 100644
--- a/make_helpers/tbbr/tbbr_tools.mk
+++ b/make_helpers/tbbr/tbbr_tools.mk
@@ -97,7 +97,7 @@
 # Add the BL32 CoT (key cert + img cert + image)
 ifeq (${NEED_BL32},yes)
     $(if ${BL32},$(eval $(call CERT_ADD_CMD_OPT,${BL32},--bl32,true)),\
-                 $(eval $(call CERT_ADD_CMD_OPT,$(call IMG_BIN,32),--bl32,true)))
+                 $(if ${BL32_SOURCES},$(eval $(call CERT_ADD_CMD_OPT,$(call IMG_BIN,32),--bl32,true))))
     $(if ${BL32_KEY},$(eval $(call CERT_ADD_CMD_OPT,${BL32_KEY},--bl32-key)))
     $(eval $(call CERT_ADD_CMD_OPT,${BUILD_PLAT}/bl32.crt,--bl32-cert))
     $(eval $(call CERT_ADD_CMD_OPT,${BUILD_PLAT}/bl32_key.crt,--bl32-key-cert))
diff --git a/plat/arm/board/juno/aarch64/juno_helpers.S b/plat/arm/board/juno/aarch64/juno_helpers.S
index 263a980..1931535 100644
--- a/plat/arm/board/juno/aarch64/juno_helpers.S
+++ b/plat/arm/board/juno/aarch64/juno_helpers.S
@@ -31,7 +31,9 @@
 #include <arch.h>
 #include <asm_macros.S>
 #include <bl_common.h>
+#include <cortex_a53.h>
 #include <cortex_a57.h>
+#include <cortex_a72.h>
 #include <v2m_def.h>
 #include "../juno_def.h"
 
@@ -39,52 +41,99 @@
 	.globl	plat_reset_handler
 	.globl	plat_arm_calc_core_pos
 
+#define JUNO_REVISION(rev)	REV_JUNO_R##rev
+#define JUNO_HANDLER(rev)	plat_reset_handler_juno_r##rev
+#define JUMP_TO_HANDLER_IF_JUNO_R(revision)	\
+	jump_to_handler JUNO_REVISION(revision), JUNO_HANDLER(revision)
+
 	/* --------------------------------------------------------------------
-	 * void plat_reset_handler(void);
+	 * Helper macro to jump to the given handler if the board revision
+	 * matches.
+	 * Expects the Juno board revision in x0.
+	 * --------------------------------------------------------------------
+	 */
+	.macro jump_to_handler _revision, _handler
+	cmp	x0, #\_revision
+	b.eq	\_handler
+	.endm
+
+	/* --------------------------------------------------------------------
+	 * Helper macro that reads the part number of the current CPU and jumps
+	 * to the given label if it matches the CPU MIDR provided.
+	 *
+	 * Clobbers x0.
+	 * --------------------------------------------------------------------
+	 */
+	.macro  jump_if_cpu_midr _cpu_midr, _label
+	mrs	x0, midr_el1
+	ubfx	x0, x0, MIDR_PN_SHIFT, #12
+	cmp     w0, #((\_cpu_midr >> MIDR_PN_SHIFT) & MIDR_PN_MASK)
+	b.eq	\_label
+	.endm
+
+	/* --------------------------------------------------------------------
+	 * Platform reset handler for Juno R0.
+	 *
+	 * Juno R0 has the following topology:
+	 * - Quad core Cortex-A53 processor cluster;
+	 * - Dual core Cortex-A57 processor cluster.
 	 *
-	 * For Juno r0:
+	 * This handler does the following:
 	 * - Implement workaround for defect id 831273 by enabling an event
 	 *   stream every 65536 cycles.
 	 * - Set the L2 Data RAM latency to 2 (i.e. 3 cycles) for Cortex-A57
 	 * - Set the L2 Tag RAM latency to 2 (i.e. 3 cycles) for Cortex-A57
-	 *
-	 * For Juno r1:
-	 * - Set the L2 Data RAM latency to 2 (i.e. 3 cycles) for Cortex-A57
-	 * Note that:
-	 * - The default value for the L2 Tag RAM latency for Cortex-A57 is
-	 *   suitable.
-	 * - Defect #831273 doesn't affect Juno r1.
 	 * --------------------------------------------------------------------
 	 */
-func plat_reset_handler
+func JUNO_HANDLER(0)
 	/* --------------------------------------------------------------------
-	 * Determine whether this code is running on Juno r0 or Juno r1.
-	 * Keep this information in x2.
+	 * Enable the event stream every 65536 cycles
 	 * --------------------------------------------------------------------
 	 */
-	/* Read the V2M SYS_ID register */
-	mov_imm	x0, (V2M_SYSREGS_BASE + V2M_SYS_ID)
-	ldr	w1, [x0]
-	/* Extract board revision from the SYS_ID */
-	ubfx	x1, x1, #V2M_SYS_ID_REV_SHIFT, #4
-	/*
-	 * On Juno R0:  x2 := REV_JUNO_R0 - 1 = 0
-	 * On Juno R1:  x2 := REV_JUNO_R1 - 1 = 1
+	mov     x0, #(0xf << EVNTI_SHIFT)
+	orr     x0, x0, #EVNTEN_BIT
+	msr     CNTKCTL_EL1, x0
+
+	/* --------------------------------------------------------------------
+	 * Nothing else to do on Cortex-A53.
+	 * --------------------------------------------------------------------
 	 */
-	sub	x2, x1, #1
+	jump_if_cpu_midr CORTEX_A53_MIDR, 1f
 
 	/* --------------------------------------------------------------------
-	 * Determine whether this code is executed on a Cortex-A53 or on a
-	 * Cortex-A57 core.
+	 * Cortex-A57 specific settings
 	 * --------------------------------------------------------------------
 	 */
-	mrs	x0, midr_el1
-	ubfx	x1, x0, MIDR_PN_SHIFT, #12
-	cmp     w1, #((CORTEX_A57_MIDR >> MIDR_PN_SHIFT) & MIDR_PN_MASK)
-	b.eq	A57
+	mov	x0, #((L2_DATA_RAM_LATENCY_3_CYCLES << L2CTLR_DATA_RAM_LATENCY_SHIFT) |	\
+		      (L2_TAG_RAM_LATENCY_3_CYCLES << L2CTLR_TAG_RAM_LATENCY_SHIFT))
+	msr     L2CTLR_EL1, x0
+1:
+	isb
+	ret
+endfunc JUNO_HANDLER(0)
 
-	/* Nothing needs to be done for the Cortex-A53 on Juno r1 */
-	cbz	x2, apply_831273
+	/* --------------------------------------------------------------------
+	 * Platform reset handler for Juno R1.
+	 *
+	 * Juno R1 has the following topology:
+	 * - Quad core Cortex-A53 processor cluster;
+	 * - Dual core Cortex-A57 processor cluster.
+	 *
+	 * This handler does the following:
+	 * - Set the L2 Data RAM latency to 2 (i.e. 3 cycles) for Cortex-A57
+	 *
+	 * Note that:
+	 * - The default value for the L2 Tag RAM latency for Cortex-A57 is
+	 *   suitable.
+	 * - Defect #831273 doesn't affect Juno R1.
+	 * --------------------------------------------------------------------
+	 */
+func JUNO_HANDLER(1)
+	/* --------------------------------------------------------------------
+	 * Nothing to do on Cortex-A53.
+	 * --------------------------------------------------------------------
+	 */
+	jump_if_cpu_midr CORTEX_A57_MIDR, A57
 	ret
 
 A57:
@@ -92,30 +141,69 @@
 	 * Cortex-A57 specific settings
 	 * --------------------------------------------------------------------
 	 */
-
-	/* Change the L2 Data RAM latency to 3 cycles */
-	mov	x0, #L2_DATA_RAM_LATENCY_3_CYCLES
-	cbnz	x2, apply_l2_ram_latencies
-	/* On Juno r0, also change the L2 Tag RAM latency to 3 cycles */
-	orr	x0, x0, #(L2_TAG_RAM_LATENCY_3_CYCLES << 		\
-				L2CTLR_TAG_RAM_LATENCY_SHIFT)
-apply_l2_ram_latencies:
+	mov	x0, #(L2_DATA_RAM_LATENCY_3_CYCLES << L2CTLR_DATA_RAM_LATENCY_SHIFT)
 	msr     L2CTLR_EL1, x0
+	isb
+	ret
+endfunc JUNO_HANDLER(1)
 
-	/* Juno r1 doesn't suffer from defect #831273 */
-	cbnz	x2, ret
+	/* --------------------------------------------------------------------
+	 * Platform reset handler for Juno R2.
+	 *
+	 * Juno R2 has the following topology:
+	 * - Quad core Cortex-A53 processor cluster;
+	 * - Dual core Cortex-A72 processor cluster.
+	 *
+	 * This handler does the following:
+	 * - Set the L2 Data RAM latency to 2 (i.e. 3 cycles) for Cortex-A72
+	 * - Set the L2 Tag RAM latency to 1 (i.e. 2 cycles) for Cortex-A72
+	 *
+	 * Note that:
+	 * - Defect #831273 doesn't affect Juno R2.
+	 * --------------------------------------------------------------------
+	 */
+func JUNO_HANDLER(2)
+	/* --------------------------------------------------------------------
+	 * Nothing to do on Cortex-A53.
+	 * --------------------------------------------------------------------
+	 */
+	jump_if_cpu_midr CORTEX_A72_MIDR, A72
+	ret
 
-apply_831273:
+A72:
 	/* --------------------------------------------------------------------
-	 * On Juno r0, enable the event stream every 65536 cycles
+	 * Cortex-A72 specific settings
 	 * --------------------------------------------------------------------
 	 */
-	mov     x0, #(0xf << EVNTI_SHIFT)
-	orr     x0, x0, #EVNTEN_BIT
-	msr     CNTKCTL_EL1, x0
-ret:
+	mov	x0, #((L2_DATA_RAM_LATENCY_3_CYCLES << L2CTLR_DATA_RAM_LATENCY_SHIFT) |	\
+		      (L2_TAG_RAM_LATENCY_2_CYCLES << L2CTLR_TAG_RAM_LATENCY_SHIFT))
+	msr     L2CTLR_EL1, x0
 	isb
 	ret
+endfunc JUNO_HANDLER(2)
+
+	/* --------------------------------------------------------------------
+	 * void plat_reset_handler(void);
+	 *
+	 * Determine the Juno board revision and call the appropriate reset
+	 * handler.
+	 * --------------------------------------------------------------------
+	 */
+func plat_reset_handler
+	/* Read the V2M SYS_ID register */
+	mov_imm	x0, (V2M_SYSREGS_BASE + V2M_SYS_ID)
+	ldr	w1, [x0]
+	/* Extract board revision from the SYS_ID */
+	ubfx	x0, x1, #V2M_SYS_ID_REV_SHIFT, #4
+
+	JUMP_TO_HANDLER_IF_JUNO_R(0)
+	JUMP_TO_HANDLER_IF_JUNO_R(1)
+	JUMP_TO_HANDLER_IF_JUNO_R(2)
+
+	/* Board revision is not supported */
+not_supported:
+	b	not_supported
+
 endfunc plat_reset_handler
 
 	/* -----------------------------------------------------
diff --git a/plat/arm/board/juno/juno_def.h b/plat/arm/board/juno/juno_def.h
index 143cf00..1f367f2 100644
--- a/plat/arm/board/juno/juno_def.h
+++ b/plat/arm/board/juno/juno_def.h
@@ -39,6 +39,7 @@
 /* Board revisions */
 #define REV_JUNO_R0			0x1	/* Rev B */
 #define REV_JUNO_R1			0x2	/* Rev C */
+#define REV_JUNO_R2			0x3	/* Rev D */
 
 /* Bypass offset from start of NOR flash */
 #define BL1_ROM_BYPASS_OFFSET		0x03EC0000
diff --git a/plat/nvidia/tegra/common/tegra_pm.c b/plat/nvidia/tegra/common/tegra_pm.c
index 87f7240..c2c73f6 100644
--- a/plat/nvidia/tegra/common/tegra_pm.c
+++ b/plat/nvidia/tegra/common/tegra_pm.c
@@ -55,6 +55,7 @@
 #pragma weak tegra_soc_prepare_cpu_on
 #pragma weak tegra_soc_prepare_cpu_off
 #pragma weak tegra_soc_prepare_cpu_on_finish
+#pragma weak tegra_soc_prepare_system_reset
 
 int tegra_soc_prepare_cpu_suspend(unsigned int id, unsigned int afflvl)
 {
@@ -76,6 +77,11 @@
 	return PSCI_E_SUCCESS;
 }
 
+int tegra_soc_prepare_system_reset(void)
+{
+	return PSCI_E_SUCCESS;
+}
+
 /*******************************************************************************
  * Track system suspend entry.
  ******************************************************************************/
@@ -298,6 +304,9 @@
  ******************************************************************************/
 __dead2 void tegra_system_reset(void)
 {
+	/* per-SoC system reset handler */
+	tegra_soc_prepare_system_reset();
+
 	/*
 	 * Program the PMC in order to restart the system.
 	 */
diff --git a/plat/nvidia/tegra/soc/t132/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t132/plat_psci_handlers.c
index 79e9f1c..46e5940 100644
--- a/plat/nvidia/tegra/soc/t132/plat_psci_handlers.c
+++ b/plat/nvidia/tegra/soc/t132/plat_psci_handlers.c
@@ -33,6 +33,7 @@
 #include <assert.h>
 #include <denver.h>
 #include <debug.h>
+#include <delay_timer.h>
 #include <flowctrl.h>
 #include <mmio.h>
 #include <platform_def.h>
@@ -48,6 +49,11 @@
 #define CPU_CMPLX_RESET_CLR		0x344
 #define CPU_CORE_RESET_MASK		0x10001
 
+/* Clock and Reset controller registers for system clock's settings */
+#define SCLK_RATE			0x30
+#define SCLK_BURST_POLICY		0x28
+#define SCLK_BURST_POLICY_DEFAULT	0x10000000
+
 static int cpu_powergate_mask[PLATFORM_MAX_CPUS_PER_CLUSTER];
 
 int32_t tegra_soc_validate_power_state(unsigned int power_state)
@@ -121,3 +127,19 @@
 
 	return PSCI_E_SUCCESS;
 }
+
+int tegra_soc_prepare_system_reset(void)
+{
+	/*
+	 * Set System Clock (SCLK) to POR default so that the clock source
+	 * for the PMC APB clock would not be changed due to system reset.
+	 */
+	mmio_write_32((uintptr_t)TEGRA_CAR_RESET_BASE + SCLK_BURST_POLICY,
+		       SCLK_BURST_POLICY_DEFAULT);
+	mmio_write_32((uintptr_t)TEGRA_CAR_RESET_BASE + SCLK_RATE, 0);
+
+	/* Wait 1 ms to make sure clock source/device logic is stabilized. */
+	mdelay(1);
+
+	return PSCI_E_SUCCESS;
+}
diff --git a/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c
index 57be347..73358d4 100644
--- a/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c
+++ b/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c
@@ -31,6 +31,7 @@
 #include <arch_helpers.h>
 #include <assert.h>
 #include <debug.h>
+#include <delay_timer.h>
 #include <mmio.h>
 #include <platform.h>
 #include <platform_def.h>
@@ -47,6 +48,11 @@
 #define CPU_CMPLX_RESET_CLR		0x454
 #define CPU_CORE_RESET_MASK		0x10001
 
+/* Clock and Reset controller registers for system clock's settings */
+#define SCLK_RATE			0x30
+#define SCLK_BURST_POLICY		0x28
+#define SCLK_BURST_POLICY_DEFAULT	0x10000000
+
 static int cpu_powergate_mask[PLATFORM_MAX_CPUS_PER_CLUSTER];
 
 int32_t tegra_soc_validate_power_state(unsigned int power_state)
@@ -183,3 +189,19 @@
 	tegra_fc_cpu_off(mpidr & MPIDR_CPU_MASK);
 	return PSCI_E_SUCCESS;
 }
+
+int tegra_soc_prepare_system_reset(void)
+{
+	/*
+	 * Set System Clock (SCLK) to POR default so that the clock source
+	 * for the PMC APB clock would not be changed due to system reset.
+	 */
+	mmio_write_32((uintptr_t)TEGRA_CAR_RESET_BASE + SCLK_BURST_POLICY,
+		       SCLK_BURST_POLICY_DEFAULT);
+	mmio_write_32((uintptr_t)TEGRA_CAR_RESET_BASE + SCLK_RATE, 0);
+
+	/* Wait 1 ms to make sure clock source/device logic is stabilized. */
+	mdelay(1);
+
+	return PSCI_E_SUCCESS;
+}
diff --git a/services/spd/opteed/opteed_main.c b/services/spd/opteed/opteed_main.c
index fefc8a7..7796fc4 100644
--- a/services/spd/opteed/opteed_main.c
+++ b/services/spd/opteed/opteed_main.c
@@ -85,11 +85,6 @@
 	/* Check the security state when the exception was generated */
 	assert(get_interrupt_src_ss(flags) == NON_SECURE);
 
-#if IMF_READ_INTERRUPT_ID
-	/* Check the security status of the interrupt */
-	assert(plat_ic_get_interrupt_type(id) == INTR_TYPE_S_EL1);
-#endif
-
 	/* Sanity check the pointer to this cpu's context */
 	assert(handle == cm_get_context(NON_SECURE));
 
diff --git a/services/spd/tspd/tspd_main.c b/services/spd/tspd/tspd_main.c
index b8b67fa..6223160 100644
--- a/services/spd/tspd/tspd_main.c
+++ b/services/spd/tspd/tspd_main.c
@@ -106,11 +106,6 @@
 	/* Check the security state when the exception was generated */
 	assert(get_interrupt_src_ss(flags) == NON_SECURE);
 
-#if IMF_READ_INTERRUPT_ID
-	/* Check the security status of the interrupt */
-	assert(plat_ic_get_interrupt_type(id) == INTR_TYPE_S_EL1);
-#endif
-
 	/* Sanity check the pointer to this cpu's context */
 	assert(handle == cm_get_context(NON_SECURE));
 
@@ -173,10 +168,6 @@
 	/* Check the security state when the exception was generated */
 	assert(get_interrupt_src_ss(flags) == SECURE);
 
-#if IMF_READ_INTERRUPT_ID
-	/* Check the security status of the interrupt */
-	assert(plat_ic_get_interrupt_type(id) == INTR_TYPE_NS);
-#endif
 	/*
 	 * Disable the routing of NS interrupts from secure world to EL3 while
 	 * interrupted on this core.