Merge pull request #439 from soby-mathew/sm/new-gic-driver

Introduce new GICv3 and GICv2 drivers
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/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 9aea2c9..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
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) \