summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/arm/gic/arm_gic_v2.c114
-rw-r--r--drivers/arm/gic/gic_common.c199
-rw-r--r--drivers/arm/gic/gic_v2.c302
-rw-r--r--framework/include/tftf.h6
-rw-r--r--framework/main.c4
-rw-r--r--framework/timer/timer_framework.c46
-rw-r--r--include/drivers/arm/arm_gic.h122
-rw-r--r--include/drivers/arm/gic_common.h126
-rw-r--r--include/drivers/arm/gic_v2.h216
-rw-r--r--include/lib/power_management.h4
-rw-r--r--include/lib/sgi.h4
-rw-r--r--lib/irq/irq.c120
-rw-r--r--lib/power_management/hotplug/hotplug.c15
-rw-r--r--lib/power_management/suspend/tftf_suspend.c16
-rw-r--r--lib/psci/psci.c4
-rw-r--r--plat/armstrong/armstrong_private.h6
-rw-r--r--plat/armstrong/plat_setup.c6
-rw-r--r--plat/armstrong/platform.mk6
-rw-r--r--plat/fvp/fvp_private.h6
-rw-r--r--plat/fvp/plat_setup.c6
-rw-r--r--plat/fvp/platform.mk6
-rw-r--r--plat/juno/juno_private.h6
-rw-r--r--plat/juno/plat_setup.c6
-rw-r--r--plat/juno/platform.mk6
-rw-r--r--tests/framework_validation_tests/test_validation_irq.c4
-rw-r--r--tests/framework_validation_tests/test_validation_sgi.c12
-rw-r--r--tests/runtime_services/standard_service/psci/api_tests/affinity_info/test_psci_affinity_info.c4
-rw-r--r--tests/runtime_services/standard_service/psci/api_tests/validate_power_state/test_validate_power_state.c4
-rw-r--r--tests/runtime_services/trusted_os/tsp/test_normal_int_switch.c4
29 files changed, 825 insertions, 555 deletions
diff --git a/drivers/arm/gic/arm_gic_v2.c b/drivers/arm/gic/arm_gic_v2.c
new file mode 100644
index 0000000..cbecb1c
--- /dev/null
+++ b/drivers/arm/gic/arm_gic_v2.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2016, 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_v2.h>
+
+void arm_gic_enable_interrupts_local(void)
+{
+ gicv2_enable_cpuif();
+}
+
+void arm_gic_setup_local(void)
+{
+ gicv2_probe_gic_cpu_id();
+ gicv2_setup_cpuif();
+}
+
+void arm_gic_disable_interrupts_local(void)
+{
+ gicv2_disable_cpuif();
+}
+
+void arm_gic_setup_global(void)
+{
+ gicv2_setup_distif();
+}
+
+void arm_gic_set_intr_priority(unsigned int num,
+ unsigned int priority)
+{
+ gicv2_gicd_set_ipriorityr(num, priority);
+}
+
+void arm_gic_send_sgi(unsigned int sgi_id, unsigned int core_pos)
+{
+ gicv2_send_sgi(sgi_id, core_pos);
+}
+
+void arm_gic_set_intr_target(unsigned int num, unsigned int core_pos)
+{
+ gicv2_set_itargetsr(num, core_pos);
+}
+
+void arm_gic_intr_enable(unsigned int num)
+{
+ gicv2_gicd_set_isenabler(num);
+}
+
+void arm_gic_intr_disable(unsigned int num)
+{
+ gicv2_gicd_set_icenabler(num);
+}
+
+unsigned int arm_gic_intr_ack(unsigned int *raw_iar)
+{
+ assert(raw_iar);
+
+ *raw_iar = gicv2_gicc_read_iar();
+ return get_gicc_iar_intid(*raw_iar);
+}
+
+unsigned int arm_gic_is_intr_pending(unsigned int num)
+{
+ return gicv2_gicd_get_ispendr(num);
+}
+
+void arm_gic_intr_clear(unsigned int num)
+{
+ gicv2_gicd_set_icpendr(num);
+}
+
+void arm_gic_end_of_intr(unsigned int raw_iar)
+{
+ gicv2_gicc_write_eoir(raw_iar);
+}
+
+void arm_gic_init(uintptr_t gicc_base,
+ uintptr_t gicd_base,
+ uintptr_t gicr_base)
+{
+ gicv2_init(gicc_base, gicd_base);
+ INFO("ARM GIC v2 driver initialized\n");
+}
+
diff --git a/drivers/arm/gic/gic_common.c b/drivers/arm/gic/gic_common.c
new file mode 100644
index 0000000..4dcd6c9
--- /dev/null
+++ b/drivers/arm/gic/gic_common.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2016, 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 <gic_common.h>
+#include <mmio.h>
+
+/*******************************************************************************
+ * GIC Distributor interface accessors for reading entire registers
+ ******************************************************************************/
+
+unsigned int gicd_read_isenabler(unsigned int base, unsigned int interrupt_id)
+{
+ unsigned int n = interrupt_id >> ISENABLER_SHIFT;
+ return mmio_read_32(base + GICD_ISENABLER + (n << 2));
+}
+
+unsigned int gicd_read_icenabler(unsigned int base, unsigned int interrupt_id)
+{
+ unsigned int n = interrupt_id >> ICENABLER_SHIFT;
+ return mmio_read_32(base + GICD_ICENABLER + (n << 2));
+}
+
+unsigned int gicd_read_ispendr(unsigned int base, unsigned int interrupt_id)
+{
+ unsigned int n = interrupt_id >> ISPENDR_SHIFT;
+ return mmio_read_32(base + GICD_ISPENDR + (n << 2));
+}
+
+unsigned int gicd_read_icpendr(unsigned int base, unsigned int interrupt_id)
+{
+ unsigned int n = interrupt_id >> ICPENDR_SHIFT;
+ return mmio_read_32(base + GICD_ICPENDR + (n << 2));
+}
+
+unsigned int gicd_read_isactiver(unsigned int base, unsigned int interrupt_id)
+{
+ unsigned int n = interrupt_id >> ISACTIVER_SHIFT;
+ return mmio_read_32(base + GICD_ISACTIVER + (n << 2));
+}
+
+unsigned int gicd_read_icactiver(unsigned int base, unsigned int interrupt_id)
+{
+ unsigned int n = interrupt_id >> ICACTIVER_SHIFT;
+ return mmio_read_32(base + GICD_ICACTIVER + (n << 2));
+}
+
+unsigned int gicd_read_ipriorityr(unsigned int base, unsigned int interrupt_id)
+{
+ unsigned int n = interrupt_id >> IPRIORITYR_SHIFT;
+ return mmio_read_32(base + GICD_IPRIORITYR + (n << 2));
+}
+
+unsigned int gicd_read_icfgr(unsigned int base, unsigned int interrupt_id)
+{
+ unsigned int n = interrupt_id >> ICFGR_SHIFT;
+ return mmio_read_32(base + GICD_ICFGR + (n << 2));
+}
+
+/*******************************************************************************
+ * GIC Distributor interface accessors for writing entire registers
+ ******************************************************************************/
+
+void gicd_write_isenabler(unsigned int base,
+ unsigned int interrupt_id, unsigned int val)
+{
+ unsigned int n = interrupt_id >> ISENABLER_SHIFT;
+ mmio_write_32(base + GICD_ISENABLER + (n << 2), val);
+}
+
+void gicd_write_icenabler(unsigned int base,
+ unsigned int interrupt_id, unsigned int val)
+{
+ unsigned int n = interrupt_id >> ICENABLER_SHIFT;
+ mmio_write_32(base + GICD_ICENABLER + (n << 2), val);
+}
+
+void gicd_write_ispendr(unsigned int base,
+ unsigned int interrupt_id, unsigned int val)
+{
+ unsigned int n = interrupt_id >> ISPENDR_SHIFT;
+ mmio_write_32(base + GICD_ISPENDR + (n << 2), val);
+}
+
+void gicd_write_icpendr(unsigned int base,
+ unsigned int interrupt_id, unsigned int val)
+{
+ unsigned int n = interrupt_id >> ICPENDR_SHIFT;
+ mmio_write_32(base + GICD_ICPENDR + (n << 2), val);
+}
+
+void gicd_write_isactiver(unsigned int base,
+ unsigned int interrupt_id, unsigned int val)
+{
+ unsigned int n = interrupt_id >> ISACTIVER_SHIFT;
+ mmio_write_32(base + GICD_ISACTIVER + (n << 2), val);
+}
+
+void gicd_write_icactiver(unsigned int base,
+ unsigned int interrupt_id, unsigned int val)
+{
+ unsigned int n = interrupt_id >> ICACTIVER_SHIFT;
+ mmio_write_32(base + GICD_ICACTIVER + (n << 2), val);
+}
+
+void gicd_write_ipriorityr(unsigned int base,
+ unsigned int interrupt_id, unsigned int val)
+{
+ unsigned int n = interrupt_id >> IPRIORITYR_SHIFT;
+ mmio_write_32(base + GICD_IPRIORITYR + (n << 2), val);
+}
+
+void gicd_write_icfgr(unsigned int base,
+ unsigned int interrupt_id, unsigned int val)
+{
+ unsigned int n = interrupt_id >> ICFGR_SHIFT;
+ mmio_write_32(base + GICD_ICFGR + (n << 2), val);
+}
+
+/*******************************************************************************
+ * GIC Distributor interface accessors for individual interrupt manipulation
+ ******************************************************************************/
+void gicd_set_isenabler(unsigned int base, unsigned int interrupt_id)
+{
+ unsigned int bit_num = interrupt_id & ((1 << ISENABLER_SHIFT) - 1);
+
+ gicd_write_isenabler(base, interrupt_id, (1 << bit_num));
+}
+
+void gicd_set_icenabler(unsigned int base, unsigned int interrupt_id)
+{
+ unsigned int bit_num = interrupt_id & ((1 << ICENABLER_SHIFT) - 1);
+
+ gicd_write_icenabler(base, interrupt_id, (1 << bit_num));
+}
+
+void gicd_set_ispendr(unsigned int base, unsigned int interrupt_id)
+{
+ unsigned int bit_num = interrupt_id & ((1 << ISPENDR_SHIFT) - 1);
+
+ gicd_write_ispendr(base, interrupt_id, (1 << bit_num));
+}
+
+void gicd_set_icpendr(unsigned int base, unsigned int interrupt_id)
+{
+ unsigned int bit_num = interrupt_id & ((1 << ICPENDR_SHIFT) - 1);
+
+ gicd_write_icpendr(base, interrupt_id, (1 << bit_num));
+}
+
+void gicd_set_isactiver(unsigned int base, unsigned int interrupt_id)
+{
+ unsigned int bit_num = interrupt_id & ((1 << ISACTIVER_SHIFT) - 1);
+
+ gicd_write_isactiver(base, interrupt_id, (1 << bit_num));
+}
+
+void gicd_set_icactiver(unsigned int base, unsigned int interrupt_id)
+{
+ unsigned int bit_num = interrupt_id & ((1 << ICACTIVER_SHIFT) - 1);
+
+ gicd_write_icactiver(base, interrupt_id, (1 << bit_num));
+}
+
+void gicd_set_ipriorityr(unsigned int base, unsigned int interrupt_id,
+ unsigned int priority)
+{
+ mmio_write_8(base + GICD_IPRIORITYR + interrupt_id,
+ priority & GIC_PRI_MASK);
+}
diff --git a/drivers/arm/gic/gic_v2.c b/drivers/arm/gic/gic_v2.c
index 4ab2bef..4613767 100644
--- a/drivers/arm/gic/gic_v2.c
+++ b/drivers/arm/gic/gic_v2.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2016, 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:
@@ -30,73 +30,34 @@
#include <arch.h>
#include <arch_helpers.h>
+#include <arm_gic.h>
#include <assert.h>
+#include <gic_common.h>
#include <gic_v2.h>
#include <mmio.h>
#include <platform.h>
-static uint64_t gicc_base_addr;
-static uint64_t gicd_base_addr;
-static uint64_t gicr_base_addr;
+static uintptr_t gicc_base_addr;
+static uintptr_t gicd_base_addr;
-/*******************************************************************************
- * GIC Distributor interface accessors for reading entire registers
- ******************************************************************************/
-
-unsigned int gicd_read_isenabler(unsigned int base, unsigned int interrupt_id)
-{
- unsigned n = interrupt_id >> ISENABLER_SHIFT;
- return mmio_read_32(base + GICD_ISENABLER + (n << 2));
-}
-
-unsigned int gicd_read_icenabler(unsigned int base, unsigned int interrupt_id)
-{
- unsigned n = interrupt_id >> ICENABLER_SHIFT;
- return mmio_read_32(base + GICD_ICENABLER + (n << 2));
-}
-
-unsigned int gicd_read_ispendr(unsigned int base, unsigned int interrupt_id)
-{
- unsigned n = interrupt_id >> ISPENDR_SHIFT;
- return mmio_read_32(base + GICD_ISPENDR + (n << 2));
-}
-
-unsigned int gicd_read_icpendr(unsigned int base, unsigned int interrupt_id)
-{
- unsigned n = interrupt_id >> ICPENDR_SHIFT;
- return mmio_read_32(base + GICD_ICPENDR + (n << 2));
-}
+static unsigned int gic_cpu_id[PLATFORM_CORE_COUNT] = {UINT32_MAX};
-unsigned int gicd_read_isactiver(unsigned int base, unsigned int interrupt_id)
+/* Helper function to convert core pos to gic id */
+static unsigned int core_pos_to_gic_id(unsigned int core_pos)
{
- unsigned n = interrupt_id >> ISACTIVER_SHIFT;
- return mmio_read_32(base + GICD_ISACTIVER + (n << 2));
-}
-
-unsigned int gicd_read_icactiver(unsigned int base, unsigned int interrupt_id)
-{
- unsigned n = interrupt_id >> ICACTIVER_SHIFT;
- return mmio_read_32(base + GICD_ICACTIVER + (n << 2));
-}
-
-unsigned int gicd_read_ipriorityr(unsigned int base, unsigned int interrupt_id)
-{
- unsigned n = interrupt_id >> IPRIORITYR_SHIFT;
- return mmio_read_32(base + GICD_IPRIORITYR + (n << 2));
+ assert(gic_cpu_id[core_pos] != UINT32_MAX);
+ return gic_cpu_id[core_pos];
}
+/*******************************************************************************
+ * GIC Distributor interface accessors for reading entire registers
+ ******************************************************************************/
unsigned int gicd_read_itargetsr(unsigned int base, unsigned int interrupt_id)
{
unsigned n = interrupt_id >> ITARGETSR_SHIFT;
return mmio_read_32(base + GICD_ITARGETSR + (n << 2));
}
-unsigned int gicd_read_icfgr(unsigned int base, unsigned int interrupt_id)
-{
- unsigned n = interrupt_id >> ICFGR_SHIFT;
- return mmio_read_32(base + GICD_ICFGR + (n << 2));
-}
-
unsigned int gicd_read_cpendsgir(unsigned int base, unsigned int interrupt_id)
{
unsigned n = interrupt_id >> CPENDSGIR_SHIFT;
@@ -112,56 +73,6 @@ unsigned int gicd_read_spendsgir(unsigned int base, unsigned int interrupt_id)
/*******************************************************************************
* GIC Distributor interface accessors for writing entire registers
******************************************************************************/
-
-void gicd_write_isenabler(unsigned int base,
- unsigned int interrupt_id, unsigned int val)
-{
- unsigned n = interrupt_id >> ISENABLER_SHIFT;
- mmio_write_32(base + GICD_ISENABLER + (n << 2), val);
-}
-
-void gicd_write_icenabler(unsigned int base,
- unsigned int interrupt_id, unsigned int val)
-{
- unsigned n = interrupt_id >> ICENABLER_SHIFT;
- mmio_write_32(base + GICD_ICENABLER + (n << 2), val);
-}
-
-void gicd_write_ispendr(unsigned int base,
- unsigned int interrupt_id, unsigned int val)
-{
- unsigned n = interrupt_id >> ISPENDR_SHIFT;
- mmio_write_32(base + GICD_ISPENDR + (n << 2), val);
-}
-
-void gicd_write_icpendr(unsigned int base,
- unsigned int interrupt_id, unsigned int val)
-{
- unsigned n = interrupt_id >> ICPENDR_SHIFT;
- mmio_write_32(base + GICD_ICPENDR + (n << 2), val);
-}
-
-void gicd_write_isactiver(unsigned int base,
- unsigned int interrupt_id, unsigned int val)
-{
- unsigned n = interrupt_id >> ISACTIVER_SHIFT;
- mmio_write_32(base + GICD_ISACTIVER + (n << 2), val);
-}
-
-void gicd_write_icactiver(unsigned int base,
- unsigned int interrupt_id, unsigned int val)
-{
- unsigned n = interrupt_id >> ICACTIVER_SHIFT;
- mmio_write_32(base + GICD_ICACTIVER + (n << 2), val);
-}
-
-void gicd_write_ipriorityr(unsigned int base,
- unsigned int interrupt_id, unsigned int val)
-{
- unsigned n = interrupt_id >> IPRIORITYR_SHIFT;
- mmio_write_32(base + GICD_IPRIORITYR + (n << 2), val);
-}
-
void gicd_write_itargetsr(unsigned int base,
unsigned int interrupt_id, unsigned int val)
{
@@ -169,13 +80,6 @@ void gicd_write_itargetsr(unsigned int base,
mmio_write_32(base + GICD_ITARGETSR + (n << 2), val);
}
-void gicd_write_icfgr(unsigned int base,
- unsigned int interrupt_id, unsigned int val)
-{
- unsigned n = interrupt_id >> ICFGR_SHIFT;
- mmio_write_32(base + GICD_ICFGR + (n << 2), val);
-}
-
void gicd_write_cpendsgir(unsigned int base,
unsigned int interrupt_id, unsigned int val)
{
@@ -193,100 +97,54 @@ void gicd_write_spendsgir(unsigned int base,
/*******************************************************************************
* GIC Distributor interface accessors for individual interrupt manipulation
******************************************************************************/
-void gicd_set_isenabler(unsigned int base, unsigned int interrupt_id)
-{
- unsigned bit_num = interrupt_id & ((1 << ISENABLER_SHIFT) - 1);
-
- gicd_write_isenabler(base, interrupt_id, (1 << bit_num));
-}
-
-void gicd_set_icenabler(unsigned int base, unsigned int interrupt_id)
-{
- unsigned bit_num = interrupt_id & ((1 << ICENABLER_SHIFT) - 1);
-
- gicd_write_icenabler(base, interrupt_id, (1 << bit_num));
-}
-
-void gicd_set_ispendr(unsigned int base, unsigned int interrupt_id)
+void gicd_set_itargetsr(unsigned int base,
+ unsigned int interrupt_id, unsigned int iface)
{
- unsigned bit_num = interrupt_id & ((1 << ISPENDR_SHIFT) - 1);
-
- gicd_write_ispendr(base, interrupt_id, (1 << bit_num));
+ mmio_write_8(base + GICD_ITARGETSR + interrupt_id, (1 << iface));
}
-void gicd_set_icpendr(unsigned int base, unsigned int interrupt_id)
-{
- unsigned bit_num = interrupt_id & ((1 << ICPENDR_SHIFT) - 1);
-
- gicd_write_icpendr(base, interrupt_id, (1 << bit_num));
-}
+/******************************************************************************
+ * GICv2 public driver API
+ *****************************************************************************/
-void gicd_set_isactiver(unsigned int base, unsigned int interrupt_id)
+void gicv2_enable_cpuif(void)
{
- unsigned bit_num = interrupt_id & ((1 << ISACTIVER_SHIFT) - 1);
+ unsigned int gicc_ctlr;
- gicd_write_isactiver(base, interrupt_id, (1 << bit_num));
-}
-
-void gicd_set_icactiver(unsigned int base, unsigned int interrupt_id)
-{
- unsigned bit_num = interrupt_id & ((1 << ICACTIVER_SHIFT) - 1);
+ assert(gicc_base_addr);
- gicd_write_icactiver(base, interrupt_id, (1 << bit_num));
+ /* Enable the GICC and disable bypass */
+ gicc_ctlr = GICC_CTLR_ENABLE | FIQ_BYP_DIS_GRP1
+ | IRQ_BYP_DIS_GRP1;
+ gicc_write_ctlr(gicc_base_addr, gicc_ctlr);
}
-void gicd_set_itargetsr(unsigned int base,
- unsigned int interrupt_id, unsigned int iface)
+void gicv2_probe_gic_cpu_id(void)
{
- unsigned byte_off = interrupt_id & ((1 << ITARGETSR_SHIFT) - 1);
- unsigned int reg_val = gicd_read_itargetsr(base, interrupt_id);
+ unsigned int gicd_itargets_val, core_pos;
- gicd_write_itargetsr(base, interrupt_id, reg_val |
- (1 << iface) << (byte_off << 3));
-}
+ assert(gicd_base_addr);
+ core_pos = platform_get_core_pos(read_mpidr_el1());
+ gicd_itargets_val = gicd_read_itargetsr(gicd_base_addr, 0);
-void gicd_clear_itargetsr(unsigned int base,
- unsigned int interrupt_id, unsigned int iface)
-{
- unsigned byte_off = interrupt_id & ((1 << ITARGETSR_SHIFT) - 1);
- unsigned int reg_val = gicd_read_itargetsr(base, interrupt_id);
+ assert(gicd_itargets_val);
- gicd_write_itargetsr(base, interrupt_id,
- reg_val & ~(1 << iface) << (byte_off << 3));
+ /* Convert the bit pos returned by read of ITARGETSR0 to GIC CPU ID */
+ gic_cpu_id[core_pos] = __builtin_ctz(gicd_itargets_val);
}
-/******************************************************************************
- * Enable NS interrupts and disable legacy bypass
- ******************************************************************************/
-void arm_gic_cpuif_enable_interrupts(void)
-{
- uint32_t gicc_ctlr;
-
- assert(gicc_base_addr);
- gicc_ctlr = GICC_CTLR_ENABLE | FIQ_BYP_DIS_GRP1
- | IRQ_BYP_DIS_GRP1;
- gicc_write_ctlr(gicc_base_addr, gicc_ctlr);
-}
-
-/*******************************************************************************
- * Enable NS interrupts and disable legacy bypass and set the priority mask
- * register to allow all interrupts to trickle in.
- ******************************************************************************/
-void arm_gic_cpuif_setup(void)
+void gicv2_setup_cpuif(void)
{
assert(gicc_base_addr);
+ /* Set the priority mask register to allow all interrupts to trickle in */
gicc_write_pmr(gicc_base_addr, GIC_PRI_MASK);
- arm_gic_cpuif_enable_interrupts();
+ gicv2_enable_cpuif();
}
-/*******************************************************************************
- * 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 arm_gic_cpuif_deactivate(void)
+void gicv2_disable_cpuif(void)
{
- uint32_t gicc_ctlr;
+ unsigned int gicc_ctlr;
assert(gicc_base_addr);
@@ -297,13 +155,9 @@ void arm_gic_cpuif_deactivate(void)
gicc_write_ctlr(gicc_base_addr, gicc_ctlr);
}
-/*******************************************************************************
- * Enables the forwarding of pending interrupts from Distributor to CPU
- * interface.
- ******************************************************************************/
-static void arm_gic_distif_setup(void)
+void gicv2_setup_distif(void)
{
- uint32_t gicd_ctlr;
+ unsigned int gicd_ctlr;
assert(gicd_base_addr);
@@ -313,97 +167,95 @@ static void arm_gic_distif_setup(void)
gicd_write_ctlr(gicd_base_addr, gicd_ctlr);
}
-/* Sets the priority of the interrupt */
-void arm_gicd_set_ipriorityr(unsigned int interrupt_id, uint8_t priority)
+void gicv2_gicd_set_ipriorityr(unsigned int interrupt_id,
+ unsigned int priority)
{
- uint32_t reg_val;
- uint32_t shift = (interrupt_id & 3) << 3;
+ assert(gicd_base_addr);
+ assert(IS_VALID_INTR_ID(interrupt_id));
- reg_val = gicd_read_ipriorityr(gicd_base_addr, interrupt_id);
- reg_val &= ~(GIC_PRI_MASK << shift);
- reg_val |= priority << shift;
- gicd_write_ipriorityr(gicd_base_addr, interrupt_id, reg_val);
+ gicd_set_ipriorityr(gicd_base_addr, interrupt_id, priority);
}
-void arm_gicd_write_sgir(uint32_t sgir_val)
+void gicv2_send_sgi(unsigned int sgi_id, unsigned int core_pos)
{
+ unsigned int sgir_val;
+
assert(gicd_base_addr);
+ assert(IS_SGI(sgi_id));
+
+ sgir_val = sgi_id << GICD_SGIR_INTID_SHIFT;
+ sgir_val |= (1 << core_pos_to_gic_id(core_pos)) << GICD_SGIR_CPUTL_SHIFT;
+
gicd_write_sgir(gicd_base_addr, sgir_val);
}
-void arm_gicd_set_itargetsr(unsigned int num, unsigned int linear_id)
+void gicv2_set_itargetsr(unsigned int num, unsigned int core_pos)
{
+ unsigned int gic_cpu_id;
assert(gicd_base_addr);
- gicd_set_itargetsr(gicd_base_addr, num, linear_id);
-}
+ assert(IS_SPI(num));
-void arm_gicd_clear_itargetsr(unsigned int num, unsigned int linear_id)
-{
- assert(gicd_base_addr);
- gicd_clear_itargetsr(gicd_base_addr, num, linear_id);
+ gic_cpu_id = core_pos_to_gic_id(core_pos);
+ gicd_set_itargetsr(gicd_base_addr, num, gic_cpu_id);
}
-void arm_gicd_set_isenabler(unsigned int num)
+void gicv2_gicd_set_isenabler(unsigned int num)
{
assert(gicd_base_addr);
+ assert(IS_VALID_INTR_ID(num));
+
gicd_set_isenabler(gicd_base_addr, num);
}
-void arm_gicd_set_icenabler(unsigned int num)
+void gicv2_gicd_set_icenabler(unsigned int num)
{
assert(gicd_base_addr);
+ assert(IS_VALID_INTR_ID(num));
+
gicd_set_icenabler(gicd_base_addr, num);
}
-uint32_t arm_gicc_read_iar(void)
+unsigned int gicv2_gicc_read_iar(void)
{
assert(gicc_base_addr);
return gicc_read_iar(gicc_base_addr);
}
-uint8_t arm_gicd_get_itargetsr(unsigned int interrupt_id)
-{
- assert(gicd_base_addr);
- return gicd_read_itargetsr(gicd_base_addr, interrupt_id);
-}
-
-uint32_t arm_gicd_ispend_irq(unsigned int interrupt_id)
+unsigned int gicv2_gicd_get_ispendr(unsigned int interrupt_id)
{
unsigned int ispendr;
unsigned int bit_pos;
assert(gicd_base_addr);
+ assert(IS_VALID_INTR_ID(interrupt_id));
ispendr = gicd_read_ispendr(gicd_base_addr, interrupt_id);
- bit_pos = interrupt_id % PEND_IRQS_PER_REG;
+ bit_pos = interrupt_id % (1 << ISPENDR_SHIFT);
return !!(ispendr & (1 << bit_pos));
}
-void arm_gicd_set_icpendr(unsigned int interrupt_id)
+void gicv2_gicd_set_icpendr(unsigned int interrupt_id)
{
assert(gicd_base_addr);
+ assert(IS_PPI(interrupt_id) || IS_SPI(interrupt_id));
gicd_set_icpendr(gicd_base_addr, interrupt_id);
}
-void arm_gicc_write_eoir(uint32_t val)
+void gicv2_gicc_write_eoir(unsigned int val)
{
assert(gicc_base_addr);
+
gicc_write_eoir(gicc_base_addr, val);
}
-void arm_gic_setup(void)
+void gicv2_init(uintptr_t gicc_base,
+ uintptr_t gicd_base)
{
- arm_gic_cpuif_setup();
- arm_gic_distif_setup();
-}
+ assert(gicc_base);
+ assert(gicd_base);
-void arm_gic_init(uint64_t gicc_base,
- uint64_t gicd_base,
- uint64_t gicr_base)
-{
gicc_base_addr = gicc_base;
gicd_base_addr = gicd_base;
- gicr_base_addr = gicr_base;
}
diff --git a/framework/include/tftf.h b/framework/include/tftf.h
index 829711b..1ce220b 100644
--- a/framework/include/tftf.h
+++ b/framework/include/tftf.h
@@ -1,6 +1,6 @@
/** @file
*
-* Copyright (c) 2013, ARM Limited. All rights reserved.
+* Copyright (c) 2013-2016, ARM Limited. All rights reserved.
*
* This program and the accompanying materials
* are licensed and made available under the terms and conditions of the BSD License
@@ -149,10 +149,6 @@ void tftf_report_generate(void);
void __dead2 tftf_exit(void);
void tftf_arch_setup(void);
-void tftf_register_gic_id(void);
-uint8_t tftf_get_gic_cpu_id_from_mpidr(unsigned long mpidr);
-uint8_t tftf_get_gic_cpu_id_from_core_pos(unsigned int core_pos);
-uint8_t tftf_get_cpu_id_from_gic_id(uint8_t gic_id);
/*
* This function detects the power state format used by PSCI which can
diff --git a/framework/main.c b/framework/main.c
index c64aa6d..02f37e3 100644
--- a/framework/main.c
+++ b/framework/main.c
@@ -1,6 +1,6 @@
/** @file
*
-* Copyright (c) 2013, ARM Limited. All rights reserved.
+* Copyright (c) 2013-2016, ARM Limited. All rights reserved.
*
* This program and the accompanying materials
* are licensed and made available under the terms and conditions of the BSD License
@@ -13,9 +13,9 @@
**/
#include <arch_helpers.h>
+#include <arm_gic.h>
#include <assert.h>
#include <debug.h>
-#include <gic_v2.h>
#include <irq.h>
#include <mmio.h>
#include <nvm.h>
diff --git a/framework/timer/timer_framework.c b/framework/timer/timer_framework.c
index 67668e4..51ec44a 100644
--- a/framework/timer/timer_framework.c
+++ b/framework/timer/timer_framework.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, ARM Limited. All rights reserved.
+ * Copyright (c) 2015-2016, ARM Limited. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -32,7 +32,6 @@
#include <arch_helpers.h>
#include <arm_gic.h>
#include <debug.h>
-#include <gic_v2.h>
#include <mmio.h>
#include <errno.h>
#include <irq.h>
@@ -47,7 +46,6 @@
#define TIMER_STEP_VALUE (plat_timer_info->timer_step_value)
#define TIMER_IRQ (plat_timer_info->timer_irq)
#define PROGRAM_TIMER(a) plat_timer_info->program(a)
-#define GET_GIC_ID(a) tftf_get_gic_cpu_id_from_core_pos(a)
#define INVALID_CORE UINT32_MAX
#define INVALID_TIME UINT64_MAX
#define MAX_TIME_OUT_MS 10000
@@ -113,8 +111,8 @@ int tftf_initialise_timer(void)
interrupt_req_time[i] = INVALID_TIME;
tftf_irq_register_handler(TIMER_IRQ, tftf_timer_framework_handler);
- arm_gicd_set_ipriorityr(TIMER_IRQ, GIC_HIGHEST_NS_PRIORITY);
- arm_gicd_set_isenabler(TIMER_IRQ);
+ arm_gic_set_intr_priority(TIMER_IRQ, GIC_HIGHEST_NS_PRIORITY);
+ arm_gic_intr_enable(TIMER_IRQ);
/* Save the systicks per millisecond */
systicks_per_ms = read_cntfrq_el0() / 1000;
@@ -203,14 +201,13 @@ int tftf_program_timer(unsigned long time_out_ms)
*/
if ((!get_current_prog_time()) || (interrupt_req_time[core_pos] <
(get_current_prog_time() - TIMER_STEP_VALUE))) {
- if (current_prog_core != INVALID_CORE)
- arm_gicd_clear_itargetsr(TIMER_IRQ,
- GET_GIC_ID(current_prog_core));
+
+ arm_gic_set_intr_target(TIMER_IRQ, core_pos);
+
rc = PROGRAM_TIMER(time_out_ms);
/* We don't expect timer programming to fail */
if (rc)
ERROR("%s %d: rc = %d\n", __func__, __LINE__, rc);
- arm_gicd_set_itargetsr(TIMER_IRQ, GET_GIC_ID(core_pos));
current_prog_core = core_pos;
}
@@ -258,16 +255,15 @@ int tftf_cancel_timer(void)
* cancel timer is executed, the signal remains pending. So,
* clear the Timer IRQ if it is already pending.
*/
- if (arm_gicd_ispend_irq(TIMER_IRQ))
- arm_gicd_set_icpendr(TIMER_IRQ);
+ if (arm_gic_is_intr_pending(TIMER_IRQ))
+ arm_gic_intr_clear(TIMER_IRQ);
- arm_gicd_clear_itargetsr(TIMER_IRQ, GET_GIC_ID(core_pos));
/* Get next timer consumer */
next_timer_req_core_pos = get_lowest_req_core();
if (next_timer_req_core_pos != INVALID_CORE) {
+
/* Retarget to the next_timer_req_core_pos */
- arm_gicd_set_itargetsr(TIMER_IRQ,
- GET_GIC_ID(next_timer_req_core_pos));
+ arm_gic_set_intr_target(TIMER_IRQ, next_timer_req_core_pos);
current_prog_core = next_timer_req_core_pos;
current_time = get_current_time_ms();
@@ -315,15 +311,20 @@ int tftf_timer_framework_handler(void *data)
spin_lock(&timer_lock);
current_time = get_current_time_ms();
-
/* Check if we interrupt is targeted correctly */
assert(handler_core_pos == current_prog_core);
+
interrupt_req_time[handler_core_pos] = INVALID_TIME;
/* Execute the driver handler */
if (plat_timer_info->handler)
plat_timer_info->handler();
+ if (arm_gic_is_intr_pending(TIMER_IRQ)) {
+ ERROR(" Timer IRQ still pending. Fatal error.\n");
+ panic();
+ }
+
/*
* Execute the handler requested by the core, the handlers for the
* other cores will be executed as part of handling IRQ_WAKE_SGI.
@@ -331,9 +332,6 @@ int tftf_timer_framework_handler(void *data)
if (timer_handler[handler_core_pos])
timer_handler[handler_core_pos](data);
- arm_gicd_clear_itargetsr(TIMER_IRQ,
- GET_GIC_ID(handler_core_pos));
-
/* Send interrupts to all the CPUS in the min time block */
for (int i = 0; i < PLATFORM_CORE_COUNT; i++) {
if ((interrupt_req_time[i] <=
@@ -349,11 +347,9 @@ int tftf_timer_framework_handler(void *data)
/* Check we have not exceeded the time for next core */
assert(interrupt_req_time[next_timer_req_core_pos] >
current_time);
- rc = PROGRAM_TIMER(
- interrupt_req_time[next_timer_req_core_pos]
+ arm_gic_set_intr_target(TIMER_IRQ, next_timer_req_core_pos);
+ rc = PROGRAM_TIMER(interrupt_req_time[next_timer_req_core_pos]
- current_time);
- arm_gicd_set_itargetsr(TIMER_IRQ,
- GET_GIC_ID(next_timer_req_core_pos));
}
/* Update current program core to the newer one */
current_prog_core = next_timer_req_core_pos;
@@ -442,15 +438,15 @@ void tftf_timer_gic_state_restore(void)
unsigned int core_pos = platform_get_core_pos(read_mpidr_el1());
spin_lock(&timer_lock);
- arm_gicd_set_ipriorityr(TIMER_IRQ, GIC_HIGHEST_NS_PRIORITY);
- arm_gicd_set_isenabler(TIMER_IRQ);
+ arm_gic_set_intr_priority(TIMER_IRQ, GIC_HIGHEST_NS_PRIORITY);
+ arm_gic_intr_enable(TIMER_IRQ);
/* Check if the programmed core is the woken up core */
if (interrupt_req_time[core_pos] == INVALID_TIME) {
INFO("The programmed core is not the one woken up\n");
} else {
current_prog_core = core_pos;
- arm_gicd_set_itargetsr(TIMER_IRQ, GET_GIC_ID(core_pos));
+ arm_gic_set_intr_target(TIMER_IRQ, core_pos);
}
spin_unlock(&timer_lock);
diff --git a/include/drivers/arm/arm_gic.h b/include/drivers/arm/arm_gic.h
index d82a6c0..e4930dc 100644
--- a/include/drivers/arm/arm_gic.h
+++ b/include/drivers/arm/arm_gic.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2016, 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:
@@ -33,21 +33,111 @@
#include <stdint.h>
-void arm_gic_setup(void);
-void arm_gic_cpuif_setup(void);
-void arm_gic_cpuif_deactivate(void);
-void arm_gic_cpuif_enable_interrupts(void);
-void arm_gicd_write_sgir(uint32_t sgir_val);
-void arm_gicd_set_itargetsr(unsigned int num, unsigned int linear_id);
-void arm_gicd_clear_itargetsr(unsigned int num, unsigned int linear_id);
-void arm_gicd_set_ipriorityr(unsigned int num, uint8_t priority);
-void arm_gicd_set_isenabler(unsigned int num);
-void arm_gicd_set_icenabler(unsigned int num);
-uint32_t arm_gicc_read_iar(void);
-void arm_gicc_write_eoir(uint32_t val);
-uint8_t arm_gicd_get_itargetsr(unsigned int id);
-uint32_t arm_gicd_ispend_irq(unsigned int interrupt_id);
-void arm_gicd_set_icpendr(unsigned int interrupt_id);
+/***************************************************************************
+ * Defines and prototypes for ARM GIC driver.
+ **************************************************************************/
+#define MAX_SGIS 16
+#define MIN_SGI_ID 0
+#define MAX_SGI_ID 15
+#define MIN_PPI_ID 16
+#define MAX_PPI_ID 31
+#define MIN_SPI_ID 32
+#define MAX_SPI_ID 1020
+#define IS_SGI(irq_num) \
+ (((irq_num) >= MIN_SGI_ID) && ((irq_num) <= MAX_SGI_ID))
+
+#define IS_PPI(irq_num) \
+ (((irq_num) >= MIN_PPI_ID) && ((irq_num) <= MAX_PPI_ID))
+
+#define IS_SPI(irq_num) \
+ (((irq_num) >= MIN_SPI_ID) && ((irq_num) <= MAX_SPI_ID))
+
+#define IS_VALID_INTR_ID(irq_num) \
+ (((irq_num) >= MIN_SGI_ID) && ((irq_num) <= MAX_SPI_ID))
+
+#define GIC_HIGHEST_NS_PRIORITY 0
+#define GIC_LOWEST_NS_PRIORITY 254 /* 255 would disable an interrupt */
+#define GIC_SPURIOUS_INTERRUPT 1023
+
+/******************************************************************************
+ * Setup the global GIC interface. In case of GICv2, it would be the GIC
+ * Distributor and in case of GICv3 it would be GIC Distributor and
+ * Re-distributor.
+ *****************************************************************************/
+void arm_gic_setup_global(void);
+
+/******************************************************************************
+ * Setup the GIC interface local to the CPU
+ *****************************************************************************/
+void arm_gic_setup_local(void);
+
+/******************************************************************************
+ * Disable interrupts for this local CPU
+ *****************************************************************************/
+void arm_gic_disable_interrupts_local(void);
+
+/******************************************************************************
+ * Enable interrupts for this local CPU
+ *****************************************************************************/
+void arm_gic_enable_interrupts_local(void);
+
+/******************************************************************************
+ * Send SGI with ID `sgi_id` to a core with index `core_pos`.
+ *****************************************************************************/
+void arm_gic_send_sgi(unsigned int sgi_id, unsigned int core_pos);
+
+/******************************************************************************
+ * Set the interrupt target of interrupt ID `num` to a core with index
+ * `core_pos`
+ *****************************************************************************/
+void arm_gic_set_intr_target(unsigned int num, unsigned int core_pos);
+
+/******************************************************************************
+ * Set the priority of the interrupt ID `num` to `priority`.
+ *****************************************************************************/
+void arm_gic_set_intr_priority(unsigned int num, unsigned int priority);
+
+/******************************************************************************
+ * Enable the interrupt ID `num`
+ *****************************************************************************/
+void arm_gic_intr_enable(unsigned int num);
+
+/******************************************************************************
+ * Disable the interrupt ID `num`
+ *****************************************************************************/
+void arm_gic_intr_disable(unsigned int num);
+
+/******************************************************************************
+ * Acknowledge the highest pending interrupt. Return the interrupt ID of the
+ * acknowledged interrupt. The raw interrupt acknowledge register value will
+ * be populated in `raw_iar`.
+ *****************************************************************************/
+unsigned int arm_gic_intr_ack(unsigned int *raw_iar);
+
+/******************************************************************************
+ * Signal the end of interrupt processing of a interrupt. The raw interrupt
+ * acknowledge register value returned by arm_gic_intr_ack() should be passed
+ * as argument to this function.
+ *****************************************************************************/
+void arm_gic_end_of_intr(unsigned int raw_iar);
+
+/******************************************************************************
+ * Check if the interrupt with ID `num` is pending at the GIC. Returns 1 if
+ * interrupt is pending else returns 0.
+ *****************************************************************************/
+unsigned int arm_gic_is_intr_pending(unsigned int num);
+
+/******************************************************************************
+ * Clear the pending status of the interrupt with ID `num` at the GIC.
+ *****************************************************************************/
+void arm_gic_intr_clear(unsigned int num);
+
+/******************************************************************************
+ * Initialize the GIC Driver. This function will detect the GIC Architecture
+ * present on the system and initialize the appropriate driver. The
+ * `gicr_base` argument will be ignored on GICv2 systems.
+ *****************************************************************************/
+void arm_gic_init(uintptr_t gicc_base, uintptr_t gicd_base, uintptr_t gicr_base);
#endif /* __ARM_GIC_H__ */
diff --git a/include/drivers/arm/gic_common.h b/include/drivers/arm/gic_common.h
new file mode 100644
index 0000000..c894424
--- /dev/null
+++ b/include/drivers/arm/gic_common.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2016, 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__
+
+/***************************************************************************
+ * Defines and prototypes common to GIC v2 and v3 drivers.
+ **************************************************************************/
+/* Distributor interface register offsets */
+#define GICD_CTLR 0x0
+#define GICD_TYPER 0x4
+#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
+
+/* Distributor interface register shifts */
+#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
+
+/* GICD_TYPER bit definitions */
+#define IT_LINES_NO_MASK 0x1f
+
+/* GICD Priority register mask */
+#define GIC_PRI_MASK 0xff
+
+#ifndef __ASSEMBLY__
+
+#include <mmio.h>
+
+/*******************************************************************************
+ * Private GIC Distributor function prototypes for use by GIC drivers
+ ******************************************************************************/
+unsigned int gicd_read_isenabler(unsigned int base, unsigned int interrupt_id);
+unsigned int gicd_read_icenabler(unsigned int base, unsigned int interrupt_id);
+unsigned int gicd_read_ispendr(unsigned int base, unsigned int interrupt_id);
+unsigned int gicd_read_icpendr(unsigned int base, unsigned int interrupt_id);
+unsigned int gicd_read_isactiver(unsigned int base, unsigned int interrupt_id);
+unsigned int gicd_read_icactiver(unsigned int base, unsigned int interrupt_id);
+unsigned int gicd_read_ipriorityr(unsigned int base, unsigned int interrupt_id);
+unsigned int gicd_read_icfgr(unsigned int base, unsigned int interrupt_id);
+void gicd_write_isenabler(unsigned int base, unsigned int interrupt_id,
+ unsigned int val);
+void gicd_write_icenabler(unsigned int base, unsigned int interrupt_id,
+ unsigned int val);
+void gicd_write_ispendr(unsigned int base, unsigned int interrupt_id,
+ unsigned int val);
+void gicd_write_icpendr(unsigned int base, unsigned int interrupt_id,
+ unsigned int val);
+void gicd_write_isactiver(unsigned int base, unsigned int interrupt_id,
+ unsigned int val);
+void gicd_write_icactiver(unsigned int base, unsigned int interrupt_id,
+ unsigned int val);
+void gicd_write_ipriorityr(unsigned int base, unsigned int interrupt_id,
+ unsigned int val);
+void gicd_write_icfgr(unsigned int base, unsigned int interrupt_id,
+ unsigned int val);
+void gicd_set_isenabler(unsigned int base, unsigned int interrupt_id);
+void gicd_set_icenabler(unsigned int base, unsigned int interrupt_id);
+void gicd_set_ispendr(unsigned int base, unsigned int interrupt_id);
+void gicd_set_icpendr(unsigned int base, unsigned int interrupt_id);
+void gicd_set_isactiver(unsigned int base, unsigned int interrupt_id);
+void gicd_set_icactiver(unsigned int base, unsigned int interrupt_id);
+void gicd_set_ipriorityr(unsigned int base, unsigned int interrupt_id,
+ unsigned int priority);
+
+/*******************************************************************************
+ * Private GIC Distributor interface accessors for reading and writing
+ * entire registers
+ ******************************************************************************/
+static inline unsigned int gicd_read_ctlr(unsigned int base)
+{
+ return mmio_read_32(base + GICD_CTLR);
+}
+
+static inline unsigned int gicd_read_typer(unsigned int base)
+{
+ return mmio_read_32(base + GICD_TYPER);
+}
+
+static inline void gicd_write_ctlr(unsigned int base, unsigned int val)
+{
+ mmio_write_32(base + GICD_CTLR, val);
+}
+
+
+#endif /*__ASSEMBLY__*/
+#endif /* __GIC_COMMON_H__ */
diff --git a/include/drivers/arm/gic_v2.h b/include/drivers/arm/gic_v2.h
index e375566..271538f 100644
--- a/include/drivers/arm/gic_v2.h
+++ b/include/drivers/arm/gic_v2.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2016, 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:
@@ -31,58 +31,29 @@
#ifndef __GIC_V2_H__
#define __GIC_V2_H__
-#define GIC400_NUM_SPIS 480
-#define MAX_PPIS 14
-#define MAX_SGIS 16
-#define GIC_MAX_CPU_INTERFACES 8
-
-#define MIN_SGI_ID 0
-#define MAX_SGI_ID 15
-#define MIN_PPI_ID 16
-#define MAX_PPI_ID 31
-#define MIN_SPI_ID 32
-
-#define GIC_PRI_MASK 0xff
-#define GIC_HIGHEST_NS_PRIORITY 0
-#define GIC_LOWEST_NS_PRIORITY 254 /* 255 would disable an interrupt */
-#define GIC_SPURIOUS_INTERRUPT 1023
-
-/* Distributor interface definitions */
-#define GICD_CTLR 0x0
-#define GICD_TYPER 0x4
-#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
+/***************************************************************************
+ * Defines and prototypes specific to GIC v2.
+ **************************************************************************/
+
+/* GICD_CTLR bit definitions */
+#define GICD_CTLR_ENABLE (1 << 0)
+
+/* Distributor interface register offsets */
#define GICD_ITARGETSR 0x800
-#define GICD_ICFGR 0xC00
#define GICD_SGIR 0xF00
#define GICD_CPENDSGIR 0xF10
#define GICD_SPENDSGIR 0xF20
-/* GICD_CTLR bit definitions */
-#define GICD_CTLR_ENABLE (1 << 0)
-
-#define ISENABLER_SHIFT 5
-#define ICENABLER_SHIFT ISENABLER_SHIFT
-#define ISPENDR_SHIFT 5
-#define PEND_IRQS_PER_REG 32
-#define ICPENDR_SHIFT ISPENDR_SHIFT
-#define ISACTIVER_SHIFT 5
-#define ICACTIVER_SHIFT ISACTIVER_SHIFT
-#define IPRIORITYR_SHIFT 2
+/* GIC Distributor register shifts */
#define ITARGETSR_SHIFT 2
-#define ICFGR_SHIFT 4
#define CPENDSGIR_SHIFT 2
#define SPENDSGIR_SHIFT CPENDSGIR_SHIFT
-/* GICD_TYPER bit definitions */
-#define IT_LINES_NO_MASK 0x1f
+/* GICD_SGIR bit shifts */
+#define GICD_SGIR_INTID_SHIFT 0
+#define GICD_SGIR_CPUTL_SHIFT 16
-/* Physical CPU Interface registers */
+/* Physical CPU Interface register offsets */
#define GICC_CTLR 0x0
#define GICC_PMR 0x4
#define GICC_BPR 0x8
@@ -93,7 +64,7 @@
#define GICC_AHPPIR 0x28
#define GICC_IIDR 0xFC
#define GICC_DIR 0x1000
-#define GICC_PRIODROP GICC_EOIR
+#define GICC_PRIODROP GICC_EOIR
/* GICC_IIDR bit masks and shifts */
#define GICC_IIDR_PID_SHIFT 20
@@ -106,7 +77,7 @@
#define GICC_IIDR_REV_MASK 0xf
#define GICC_IIDR_IMP_MASK 0xfff
-/* HYP view virtual CPU Interface registers */
+/* HYP view virtual CPU Interface register offsets */
#define GICH_CTL 0x0
#define GICH_VTR 0x4
#define GICH_ELRSR0 0x30
@@ -114,7 +85,7 @@
#define GICH_APR0 0xF0
#define GICH_LR_BASE 0x100
-/* Virtual CPU Interface registers */
+/* Virtual CPU Interface register offsets */
#define GICV_CTL 0x0
#define GICV_PRIMASK 0x4
#define GICV_BP 0x8
@@ -124,10 +95,6 @@
#define GICV_HIGHESTPEND 0x18
#define GICV_DEACTIVATE 0x1000
-/* GICD_SGIR bit shifts */
-#define GICD_SGIR_INTID_SHIFT 0
-#define GICD_SGIR_CPUTL_SHIFT 16
-
/* GICC_IAR bit masks and shifts */
#define GICC_IAR_INTID_SHIFT 0
#define GICC_IAR_CPUID_SHIFT 10
@@ -155,74 +122,24 @@
#include <mmio.h>
/*******************************************************************************
- * GIC Distributor function prototypes
+ * Private Interfaces for internal use by the GICv2 driver
******************************************************************************/
-unsigned int gicd_read_isenabler(unsigned int, unsigned int);
-unsigned int gicd_read_icenabler(unsigned int, unsigned int);
-unsigned int gicd_read_ispendr(unsigned int, unsigned int);
-unsigned int gicd_read_icpendr(unsigned int, unsigned int);
-unsigned int gicd_read_isactiver(unsigned int, unsigned int);
-unsigned int gicd_read_icactiver(unsigned int, unsigned int);
-unsigned int gicd_read_ipriorityr(unsigned int, unsigned int);
-unsigned int gicd_read_itargetsr(unsigned int, unsigned int);
-unsigned int gicd_read_icfgr(unsigned int, unsigned int);
-unsigned int gicd_read_cpendsgir(unsigned int, unsigned int);
-unsigned int gicd_read_spendsgir(unsigned int, unsigned int);
-void gicd_write_isenabler(unsigned int, unsigned int, unsigned int);
-void gicd_write_icenabler(unsigned int, unsigned int, unsigned int);
-void gicd_write_ispendr(unsigned int, unsigned int, unsigned int);
-void gicd_write_icpendr(unsigned int, unsigned int, unsigned int);
-void gicd_write_isactiver(unsigned int, unsigned int, unsigned int);
-void gicd_write_icactiver(unsigned int, unsigned int, unsigned int);
-void gicd_write_ipriorityr(unsigned int, unsigned int, unsigned int);
-void gicd_write_itargetsr(unsigned int, unsigned int, unsigned int);
-void gicd_write_icfgr(unsigned int, unsigned int, unsigned int);
-void gicd_write_cpendsgir(unsigned int, unsigned int, unsigned int);
-void gicd_write_spendsgir(unsigned int, unsigned int, unsigned int);
-void gicd_set_isenabler(unsigned int, unsigned int);
-void gicd_set_icenabler(unsigned int, unsigned int);
-void gicd_set_ispendr(unsigned int, unsigned int);
-void gicd_set_icpendr(unsigned int, unsigned int);
-void gicd_set_isactiver(unsigned int, unsigned int);
-void gicd_set_icactiver(unsigned int, unsigned int);
-void gicd_set_ipriorityr(unsigned int, unsigned int, unsigned int);
-void gicd_set_itargetsr(unsigned int, unsigned int, unsigned int);
-void gicd_clear_itargetsr(unsigned int, unsigned int, unsigned int);
/*******************************************************************************
- * GIC Distributor interface accessors for reading entire registers
+ * GICv2 Distributor interface accessors for reading/writing entire registers
******************************************************************************/
-static inline unsigned int gicd_read_ctlr(unsigned int base)
-{
- return mmio_read_32(base + GICD_CTLR);
-}
-
-static inline unsigned int gicd_read_typer(unsigned int base)
-{
- return mmio_read_32(base + GICD_TYPER);
-}
-
static inline unsigned int gicd_read_sgir(unsigned int base)
{
return mmio_read_32(base + GICD_SGIR);
}
-/*******************************************************************************
- * GIC Distributor interface accessors for writing entire registers
- ******************************************************************************/
-static inline void gicd_write_ctlr(unsigned int base, unsigned int val)
-{
- mmio_write_32(base + GICD_CTLR, val);
-}
-
static inline void gicd_write_sgir(unsigned int base, unsigned int val)
{
mmio_write_32(base + GICD_SGIR, val);
}
-
/*******************************************************************************
- * GIC CPU interface accessors for reading entire registers
+ * GICv2 CPU interface accessors for reading entire registers
******************************************************************************/
static inline unsigned int gicc_read_ctlr(unsigned int base)
@@ -272,7 +189,7 @@ static inline unsigned int gicc_read_iidr(unsigned int base)
/*******************************************************************************
- * GIC CPU interface accessors for writing entire registers
+ * GICv2 CPU interface accessors for writing entire registers
******************************************************************************/
static inline void gicc_write_ctlr(unsigned int base, unsigned int val)
@@ -311,12 +228,91 @@ static inline void gicc_write_dir(unsigned int base, unsigned int val)
mmio_write_32(base + GICC_DIR, val);
}
-/*******************************************************************************
- * Prototype of function to map an interrupt type to the interrupt line used to
- * signal it.
- ******************************************************************************/
-uint32_t gicv2_interrupt_type_to_line(uint32_t cpuif_base, uint32_t type);
+/******************************************************************************
+ * GICv2 public driver API
+ *****************************************************************************/
-#endif /*__ASSEMBLY__*/
+/*
+ * Initialize the GICv2 driver. The base addresses of GIC CPU interface
+ * `gicc_base` and the Distributor interface `gicd_base` must be provided
+ * as arguments.
+ */
+void gicv2_init(uintptr_t gicc_base, uintptr_t gicd_base);
+
+/*
+ * Write the GICv2 EOIR register with `val` passed as argument. `val`
+ * should be the raw value read from IAR register.
+ */
+void gicv2_gicc_write_eoir(unsigned int val);
+/*
+ * Set the bit corresponding to `interrupt_id` in the GICD ICPENDR register.
+ */
+void gicv2_gicd_set_icpendr(unsigned int interrupt_id);
+
+/*
+ * Get the bit corresponding to `interrupt_id` from the GICD ISPENDR register.
+ */
+unsigned int gicv2_gicd_get_ispendr(unsigned int interrupt_id);
+
+/*
+ * Read and return the value in GICC IAR register
+ */
+unsigned int gicv2_gicc_read_iar(void);
+
+/*
+ * Set the bit corresponding to `num` in the GICD ICENABLER register.
+ */
+void gicv2_gicd_set_icenabler(unsigned int num);
+
+/*
+ * Set the bit corresponding to `num` in the GICD ISENABLER register.
+ */
+void gicv2_gicd_set_isenabler(unsigned int num);
+
+/*
+ * Set the target of interrupt ID `num` to core with index `core_pos`.
+ */
+void gicv2_set_itargetsr(unsigned int num, unsigned int core_pos);
+
+/*
+ * Send SGI with ID `sgi_id` to core with index `core_pos`.
+ */
+void gicv2_send_sgi(unsigned int sgi_id, unsigned int core_pos);
+
+/*
+ * Set the priority of the interrupt `interrupt_id` to `priority`.
+ */
+void gicv2_gicd_set_ipriorityr(unsigned int interrupt_id, unsigned int priority);
+
+/*
+ * Setup the GIC Distributor interface.
+ */
+void gicv2_setup_distif(void);
+
+/*
+ * Disable the GIC CPU interface.
+ */
+void gicv2_disable_cpuif(void);
+
+/*
+ * Setup the GIC CPU interface.
+ */
+void gicv2_setup_cpuif(void);
+
+/*
+ * Enable the GIC CPU interface.
+ */
+void gicv2_enable_cpuif(void);
+
+/*
+ * Read the GICD ITARGETR0 to figure out the GIC ID for the current core.
+ * This function is required to be invoked on successful boot of a core.
+ * The GIC ID will be stored internally by the driver to convert core index
+ * to GIC CPU ID when required.
+ */
+void gicv2_probe_gic_cpu_id(void);
+
+
+#endif /*__ASSEMBLY__*/
#endif /* __GIC_V2_H__ */
diff --git a/include/lib/power_management.h b/include/lib/power_management.h
index d15edab..15d80ae 100644
--- a/include/lib/power_management.h
+++ b/include/lib/power_management.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2016, 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:
@@ -175,6 +175,8 @@ void tftf_set_cpu_offline(void);
*/
unsigned int tftf_is_cpu_online(unsigned int mpid);
+unsigned int tftf_is_core_pos_online(unsigned int core_pos);
+
/* TFTF Suspend helpers */
static inline int tftf_cpu_suspend(unsigned int pwr_state)
{
diff --git a/include/lib/sgi.h b/include/lib/sgi.h
index 0b5c779..f8de472 100644
--- a/include/lib/sgi.h
+++ b/include/lib/sgi.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2016, 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:
@@ -35,8 +35,6 @@
typedef struct {
/* Interrupt ID of the signaled interrupt */
unsigned int irq_id;
- /* Identifies the processor that requested the SGI */
- unsigned int cpu_id;
} sgi_data_t;
/*
diff --git a/lib/irq/irq.c b/lib/irq/irq.c
index 31e9d4c..d6f7d80 100644
--- a/lib/irq/irq.c
+++ b/lib/irq/irq.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2016, 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:
@@ -32,7 +32,6 @@
#include <arm_gic.h>
#include <assert.h>
#include <debug.h>
-#include <gic_v2.h>
#include <irq.h>
#include <platform.h>
#include <platform_def.h>
@@ -44,29 +43,10 @@
#include <tftf.h>
#include <tftf_lib.h>
-#define IS_SGI(irq_num) \
- (((irq_num) >= MIN_SGI_ID) && ((irq_num) <= MAX_SGI_ID))
-
-#define IS_PPI(irq_num) \
- (((irq_num) >= MIN_PPI_ID) && ((irq_num) <= MAX_PPI_ID))
-
-#define IS_SPI(irq_num) \
+#define IS_PLAT_SPI(irq_num) \
(((irq_num) >= MIN_SPI_ID) && \
((irq_num) <= MIN_SPI_ID + PLAT_MAX_SPI_OFFSET_ID))
-#define GIC_CPU_INVALID_ID 0xFF
-
-static uint8_t gic_cpu_ids[GIC_MAX_CPU_INTERFACES] = {
- GIC_CPU_INVALID_ID,
- GIC_CPU_INVALID_ID,
- GIC_CPU_INVALID_ID,
- GIC_CPU_INVALID_ID,
- GIC_CPU_INVALID_ID,
- GIC_CPU_INVALID_ID,
- GIC_CPU_INVALID_ID,
- GIC_CPU_INVALID_ID
-};
-
static spi_desc spi_desc_table[PLAT_MAX_SPI_OFFSET_ID];
static ppi_desc ppi_desc_table[PLATFORM_CORE_COUNT][MAX_PPI_ID + 1];
static sgi_desc sgi_desc_table[PLATFORM_CORE_COUNT][MAX_SGI_ID + 1];
@@ -86,10 +66,6 @@ static int sgi_enabled_prio[MAX_SGI_ID - MIN_SGI_ID + 1] = {-1};
void tftf_send_sgi(unsigned int sgi_id, unsigned int core_pos)
{
- uint32_t sgir_val;
- uint8_t gic_cpu_id;
- unsigned int target_mpid;
-
assert(IS_SGI(sgi_id));
/*
@@ -101,15 +77,8 @@ void tftf_send_sgi(unsigned int sgi_id, unsigned int core_pos)
* state is observed, it is IMPLEMENTATION DEFINED how the PSCI
* implementation reacts."
*/
- target_mpid = tftf_core_pos_to_mpidr(core_pos);
- assert(tftf_is_cpu_online(target_mpid));
-
- gic_cpu_id = tftf_get_gic_cpu_id_from_mpidr(target_mpid);
-
- assert(gic_cpu_id != GIC_CPU_INVALID_ID);
- sgir_val = sgi_id << GICD_SGIR_INTID_SHIFT;
- sgir_val |= (1 << gic_cpu_id) << GICD_SGIR_CPUTL_SHIFT;
- arm_gicd_write_sgir(sgir_val);
+ assert(tftf_is_core_pos_online(core_pos));
+ arm_gic_send_sgi(sgi_id, core_pos);
}
void tftf_sgi_state_restore(void)
@@ -120,25 +89,23 @@ void tftf_sgi_state_restore(void)
if (sgi_enabled_prio[i - MIN_SGI_ID] == -1)
continue;
- arm_gicd_set_ipriorityr(MIN_SGI_ID + i, sgi_enabled_prio[i - MIN_SGI_ID]);
- arm_gicd_set_isenabler(MIN_SGI_ID + i);
+ arm_gic_set_intr_priority(MIN_SGI_ID + i, sgi_enabled_prio[i - MIN_SGI_ID]);
+ arm_gic_intr_enable(MIN_SGI_ID + i);
}
}
void tftf_irq_enable(unsigned int irq_num, uint8_t irq_priority)
{
- if (IS_SPI(irq_num)) {
+ if (IS_PLAT_SPI(irq_num)) {
/*
* Instruct the GIC Distributor to forward the interrupt to
* the calling core
*/
- uint8_t gic_cpu_id;
- gic_cpu_id = tftf_get_gic_cpu_id_from_mpidr(read_mpidr_el1());
- arm_gicd_set_itargetsr(irq_num, gic_cpu_id);
+ arm_gic_set_intr_target(irq_num, platform_get_core_pos(read_mpidr_el1()));
}
- arm_gicd_set_ipriorityr(irq_num, irq_priority);
- arm_gicd_set_isenabler(irq_num);
+ arm_gic_set_intr_priority(irq_num, irq_priority);
+ arm_gic_intr_enable(irq_num);
if (IS_SGI(irq_num))
sgi_enabled_prio[irq_num - MIN_SGI_ID] = irq_priority;
@@ -149,17 +116,7 @@ void tftf_irq_enable(unsigned int irq_num, uint8_t irq_priority)
void tftf_irq_disable(unsigned int irq_num)
{
/* Disable the interrupt */
- arm_gicd_set_icenabler(irq_num);
-
- if (IS_SPI(irq_num)) {
- /*
- * Instruct the GIC Distributor to no longer forward the
- * interrupt to the calling core
- */
- uint8_t gic_cpu_id;
- gic_cpu_id = tftf_get_gic_cpu_id_from_mpidr(read_mpidr_el1());
- arm_gicd_clear_itargetsr(irq_num, gic_cpu_id);
- }
+ arm_gic_intr_disable(irq_num);
if (IS_SGI(irq_num))
sgi_enabled_prio[irq_num - MIN_SGI_ID] = -1;
@@ -178,7 +135,7 @@ static int tftf_irq_update_handler(unsigned int irq_num,
int ret = -1;
unsigned int spi_num;
- if (IS_SPI(irq_num)) {
+ if (IS_PLAT_SPI(irq_num)) {
spi_num = irq_num - MIN_SPI_ID;
cur_handler = &spi_desc_table[spi_num].handler;
spin_lock(&spi_lock);
@@ -204,7 +161,7 @@ static int tftf_irq_update_handler(unsigned int irq_num,
ret = 0;
}
- if (IS_SPI(irq_num))
+ if (IS_PLAT_SPI(irq_num))
spin_unlock(&spi_lock);
return ret;
@@ -235,7 +192,7 @@ int tftf_irq_unregister_handler(unsigned int irq_num)
int tftf_irq_handler_dispatcher(void)
{
- uint32_t gicc_iar;
+ unsigned int raw_iar;
unsigned int irq_num;
unsigned int spi_num;
sgi_data_t sgi_data;
@@ -244,11 +201,10 @@ int tftf_irq_handler_dispatcher(void)
int rc = 0;
/* Acknowledge the interrupt */
- gicc_iar = arm_gicc_read_iar();
- irq_num = get_gicc_iar_intid(gicc_iar);
+ irq_num = arm_gic_intr_ack(&raw_iar);
/* Call the user-defined handler, if any */
- if (IS_SPI(irq_num)) {
+ if (IS_PLAT_SPI(irq_num)) {
spi_num = irq_num - MIN_SPI_ID;
handler = &spi_desc_table[spi_num].handler;
irq_data = &irq_num;
@@ -260,14 +216,10 @@ int tftf_irq_handler_dispatcher(void)
handler = &ppi_desc_table[linear_id][irq_num].handler;
irq_data = &irq_num;
} else /* SGI */ {
- uint8_t gic_cpu_id;
-
assert(IS_SGI(irq_num));
handler = &sgi_desc_table[linear_id][irq_num].handler;
- gic_cpu_id = get_gicc_iar_cpuid(gicc_iar);
sgi_data.irq_id = irq_num;
- sgi_data.cpu_id = tftf_get_cpu_id_from_gic_id(gic_cpu_id);
irq_data = &sgi_data;
}
}
@@ -275,7 +227,7 @@ int tftf_irq_handler_dispatcher(void)
rc = (*handler)(irq_data);
/* Mark the processing of the interrupt as complete */
- arm_gicc_write_eoir(gicc_iar);
+ arm_gic_end_of_intr(raw_iar);
return rc;
}
@@ -287,41 +239,3 @@ void tftf_irq_setup(void)
memset(sgi_desc_table, 0, sizeof(sgi_desc_table));
init_spinlock(&spi_lock);
}
-
-void tftf_register_gic_id(void)
-{
- int linear_id = platform_get_core_pos(read_mpidr_el1());
- uint8_t gicd_itarget_val;
-
- gicd_itarget_val = arm_gicd_get_itargetsr(0);
- assert(gicd_itarget_val);
- assert(linear_id < ARRAY_SIZE(gic_cpu_ids));
- gic_cpu_ids[linear_id] = __builtin_ctz(gicd_itarget_val);
- dsbsy();
-}
-
-uint8_t tftf_get_gic_cpu_id_from_mpidr(unsigned long mpidr)
-{
- unsigned int linear_id = platform_get_core_pos(mpidr);
- assert(linear_id < ARRAY_SIZE(gic_cpu_ids));
- return gic_cpu_ids[linear_id];
-}
-
-uint8_t tftf_get_gic_cpu_id_from_core_pos(unsigned int core_pos)
-{
- assert(core_pos < ARRAY_SIZE(gic_cpu_ids));
- return gic_cpu_ids[core_pos];
-}
-
-
-uint8_t tftf_get_cpu_id_from_gic_id(uint8_t gic_id)
-{
- assert(gic_id != GIC_CPU_INVALID_ID);
- for (uint8_t i = 0; i < GIC_MAX_CPU_INTERFACES; i++) {
- if (gic_cpu_ids[i] == gic_id)
- return i;
- }
- /* assert if none of the cpus have the requested gic_id */
- assert(0);
- return -1;
-}
diff --git a/lib/power_management/hotplug/hotplug.c b/lib/power_management/hotplug/hotplug.c
index 570083f..7c5be95 100644
--- a/lib/power_management/hotplug/hotplug.c
+++ b/lib/power_management/hotplug/hotplug.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2016, 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:
@@ -33,7 +33,6 @@
#include <assert.h>
#include <cdefs.h> /* For __dead2 */
#include <debug.h>
-#include <gic_v2.h>
#include <irq.h>
#include <platform.h>
#include <platform_def.h>
@@ -149,6 +148,11 @@ unsigned int tftf_is_cpu_online(unsigned int mpid)
return ACCESS(cpus_status_map[core_pos].state) == TFTF_AFFINITY_STATE_ON;
}
+unsigned int tftf_is_core_pos_online(unsigned int core_pos)
+{
+ return ACCESS(cpus_status_map[core_pos].state) == TFTF_AFFINITY_STATE_ON;
+}
+
int32_t tftf_cpu_on(uint64_t target_cpu,
uint64_t entrypoint,
uint64_t context_id)
@@ -244,7 +248,7 @@ static void tftf_prepare_cpu_off(void)
*/
disable_irq();
isb();
- arm_gic_cpuif_deactivate();
+ arm_gic_disable_interrupts_local();
}
/*
@@ -252,7 +256,7 @@ static void tftf_prepare_cpu_off(void)
*/
static void tftf_revert_cpu_off(void)
{
- arm_gic_cpuif_enable_interrupts();
+ arm_gic_enable_interrupts_local();
enable_irq();
isb();
}
@@ -295,8 +299,7 @@ void __dead2 tftf_warm_boot_main(void)
{
/* Initialise the CPU */
tftf_arch_setup();
- tftf_register_gic_id();
- arm_gic_cpuif_setup();
+ arm_gic_setup_local();
/* Enable the SGI used by the timer management framework */
tftf_irq_enable(IRQ_WAKE_SGI, GIC_HIGHEST_NS_PRIORITY);
diff --git a/lib/power_management/suspend/tftf_suspend.c b/lib/power_management/suspend/tftf_suspend.c
index ae607f8..1c1a216 100644
--- a/lib/power_management/suspend/tftf_suspend.c
+++ b/lib/power_management/suspend/tftf_suspend.c
@@ -1,6 +1,6 @@
/** @file
*
-* Copyright (c) 2014, ARM Limited. All rights reserved.
+* Copyright (c) 2014-2016, ARM Limited. All rights reserved.
*
* This program and the accompanying materials
* are licensed and made available under the terms and conditions of the BSD License
@@ -86,7 +86,7 @@ void tftf_restore_system_ctx(tftf_suspend_ctx_t *ctx)
INFO("Restoring system context\n");
- arm_gic_setup();
+ arm_gic_setup_global();
tftf_sgi_state_restore();
tftf_timer_gic_state_restore();
}
@@ -111,13 +111,11 @@ int tftf_suspend(const suspend_info_t *info)
rc = __tftf_suspend(info);
- if (!info->save_system_context) {
- /*
- * HACK: ARM TF is disabling Group 1 interrupts while
- * entering suspend but does not restore it
- */
- arm_gic_cpuif_setup();
- }
+ /*
+ * HACK: ARM TF is disabling Group 1 interrupts while
+ * entering suspend but does not restore it
+ */
+ arm_gic_setup_local();
/*
* DAIF flags should be restored last because it could be an issue
diff --git a/lib/psci/psci.c b/lib/psci/psci.c
index f305cb8..472afc8 100644
--- a/lib/psci/psci.c
+++ b/lib/psci/psci.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, ARM Limited. All rights reserved.
+ * Copyright (c) 2014-2016, ARM Limited. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -29,8 +29,8 @@
*/
#include <arch_helpers.h>
+#include <arm_gic.h>
#include <debug.h>
-#include <gic_v2.h>
#include <irq.h>
#include <psci.h>
#include <platform.h>
diff --git a/plat/armstrong/armstrong_private.h b/plat/armstrong/armstrong_private.h
index 3e9900c..8c0a6a9 100644
--- a/plat/armstrong/armstrong_private.h
+++ b/plat/armstrong/armstrong_private.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2016, 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:
@@ -35,10 +35,6 @@
#ifndef __ARMSTRONG_PRIVATE_H__
#define __ARMSTRONG_PRIVATE_H__
-void arm_gic_init(uint64_t gicc_base,
- uint64_t gicd_base,
- uint64_t gicr_base);
-
/*
* Initialises the flash
* Returns: IO_SUCCESS
diff --git a/plat/armstrong/plat_setup.c b/plat/armstrong/plat_setup.c
index 04807c5..d1d982a 100644
--- a/plat/armstrong/plat_setup.c
+++ b/plat/armstrong/plat_setup.c
@@ -1,6 +1,6 @@
/** @file
*
-* Copyright (c) 2014, ARM Limited. All rights reserved.
+* Copyright (c) 2014-2016, ARM Limited. All rights reserved.
*
* This program and the accompanying materials
* are licensed and made available under the terms and conditions of the BSD License
@@ -69,8 +69,8 @@ void tftf_platform_setup(void)
#endif
arm_gic_init(PLAT_ARM_GICC_BASE, PLAT_ARM_GICD_BASE,
PLAT_ARM_GICR_BASE);
- tftf_register_gic_id();
- arm_gic_setup();
+ arm_gic_setup_global();
+ arm_gic_setup_local();
}
void tftf_early_platform_setup(void)
diff --git a/plat/armstrong/platform.mk b/plat/armstrong/platform.mk
index 8980eba..0e92af1 100644
--- a/plat/armstrong/platform.mk
+++ b/plat/armstrong/platform.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2014-2016, 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:
@@ -30,7 +30,9 @@
PLAT_INCLUDES := -Iplat/armstrong/include/
-PLAT_SOURCES := drivers/arm/gic/gic_v2.c \
+PLAT_SOURCES := drivers/arm/gic/arm_gic_v2.c \
+ drivers/arm/gic/gic_common.c \
+ drivers/arm/gic/gic_v2.c \
drivers/arm/pl011/pl011_console.S \
drivers/arm/sp805/sp805.c \
drivers/arm/timer/system_timer.c \
diff --git a/plat/fvp/fvp_private.h b/plat/fvp/fvp_private.h
index 6b54c44..302e564 100644
--- a/plat/fvp/fvp_private.h
+++ b/plat/fvp/fvp_private.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2016, 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:
@@ -50,10 +50,6 @@
*/
int fvp_setup_topology(void);
-void arm_gic_init(uint64_t gicc_base,
- uint64_t gicd_base,
- uint64_t gicr_base);
-
/* Declarations for fvp_io_storage.c */
/*
diff --git a/plat/fvp/plat_setup.c b/plat/fvp/plat_setup.c
index c09ac98..9924ec6 100644
--- a/plat/fvp/plat_setup.c
+++ b/plat/fvp/plat_setup.c
@@ -1,6 +1,6 @@
/** @file
*
-* Copyright (c) 2013-2015, ARM Limited. All rights reserved.
+* Copyright (c) 2013-2016, ARM Limited. All rights reserved.
*
* This program and the accompanying materials
* are licensed and made available under the terms and conditions of the BSD License
@@ -108,8 +108,8 @@ void tftf_platform_setup(void)
* as of now
*/
arm_gic_init(BASE_GICC_BASE, BASE_GICD_BASE, BASE_GICR_BASE);
- tftf_register_gic_id();
- arm_gic_setup();
+ arm_gic_setup_global();
+ arm_gic_setup_local();
}
void tftf_early_platform_setup(void)
diff --git a/plat/fvp/platform.mk b/plat/fvp/platform.mk
index b23d3ab..9931ae0 100644
--- a/plat/fvp/platform.mk
+++ b/plat/fvp/platform.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2014-2016, 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:
@@ -30,7 +30,9 @@
PLAT_INCLUDES := -Iplat/fvp/include/
-PLAT_SOURCES := drivers/arm/gic/gic_v2.c \
+PLAT_SOURCES := drivers/arm/gic/arm_gic_v2.c \
+ drivers/arm/gic/gic_common.c \
+ drivers/arm/gic/gic_v2.c \
drivers/arm/pl011/pl011_console.S \
drivers/arm/sp805/sp805.c \
drivers/arm/timer/system_timer.c \
diff --git a/plat/juno/juno_private.h b/plat/juno/juno_private.h
index c3a382f..9252897 100644
--- a/plat/juno/juno_private.h
+++ b/plat/juno/juno_private.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2016, 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:
@@ -35,10 +35,6 @@
#ifndef __JUNO_PRIVATE_H__
#define __JUNO_PRIVATE_H__
-void arm_gic_init(uint64_t gicc_base,
- uint64_t gicd_base,
- uint64_t gicr_base);
-
/*
* Initialises the flash
* Returns: IO_SUCCESS
diff --git a/plat/juno/plat_setup.c b/plat/juno/plat_setup.c
index 9d2d7b8..eed8e66 100644
--- a/plat/juno/plat_setup.c
+++ b/plat/juno/plat_setup.c
@@ -1,6 +1,6 @@
/** @file
*
-* Copyright (c) 2014-2015, ARM Limited. All rights reserved.
+* Copyright (c) 2014-2016, ARM Limited. All rights reserved.
*
* This program and the accompanying materials
* are licensed and made available under the terms and conditions of the BSD License
@@ -117,8 +117,8 @@ void tftf_platform_setup(void)
/* Juno does not support GIC Redistributor a GICv3 feature */
arm_gic_init(GICC_BASE, GICD_BASE, 0);
- tftf_register_gic_id();
- arm_gic_setup();
+ arm_gic_setup_global();
+ arm_gic_setup_local();
/*
* The Ethernet IRQ line is high by default which prevents Juno
diff --git a/plat/juno/platform.mk b/plat/juno/platform.mk
index e501480..4c43dbc 100644
--- a/plat/juno/platform.mk
+++ b/plat/juno/platform.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2014-2016, 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:
@@ -30,7 +30,9 @@
PLAT_INCLUDES := -Iplat/juno/include/
-PLAT_SOURCES := drivers/arm/gic/gic_v2.c \
+PLAT_SOURCES := drivers/arm/gic/arm_gic_v2.c \
+ drivers/arm/gic/gic_common.c \
+ drivers/arm/gic/gic_v2.c \
drivers/arm/pl011/pl011_console.S \
drivers/arm/sp805/sp805.c \
drivers/arm/timer/sp804.c \
diff --git a/tests/framework_validation_tests/test_validation_irq.c b/tests/framework_validation_tests/test_validation_irq.c
index 31bf1cd..4545555 100644
--- a/tests/framework_validation_tests/test_validation_irq.c
+++ b/tests/framework_validation_tests/test_validation_irq.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2016, 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:
@@ -29,7 +29,7 @@
*/
#include <arch_helpers.h>
-#include <gic_v2.h>
+#include <arm_gic.h>
#include <irq.h>
#include <platform.h>
#include <sgi.h>
diff --git a/tests/framework_validation_tests/test_validation_sgi.c b/tests/framework_validation_tests/test_validation_sgi.c
index d8cc68e..3cff9ec 100644
--- a/tests/framework_validation_tests/test_validation_sgi.c
+++ b/tests/framework_validation_tests/test_validation_sgi.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2016, 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:
@@ -29,8 +29,8 @@
*/
#include <arch_helpers.h>
+#include <arm_gic.h>
#include <debug.h>
-#include <gic_v2.h>
#include <irq.h>
#include <platform.h>
#include <sgi.h>
@@ -63,8 +63,6 @@ static int sgi_handler(void *data)
* 1) Register a local IRQ handler for SGI 0.
* 2) Send SGI 0 to the calling core, i.e. the lead CPU.
* 3) Check the correctness of the data received in the IRQ handler.
- * This data comprises of the number of the interrupt and the source of the
- * SGI.
*
* TODO: Improve this test by sending SGIs to all cores in the system.
* This will ensure that IRQs are correctly configured on all cores.
@@ -103,12 +101,6 @@ test_result_t test_validation_sgi(void)
test_res = TEST_RESULT_FAIL;
}
- if (sgi_data.cpu_id != core_pos) {
- tftf_testcase_printf("Wrong CPU ID, expected %u, got %u\n",
- core_pos, sgi_data.cpu_id);
- test_res = TEST_RESULT_FAIL;
- }
-
tftf_irq_disable(sgi_id);
tftf_irq_unregister_handler(sgi_id);
diff --git a/tests/runtime_services/standard_service/psci/api_tests/affinity_info/test_psci_affinity_info.c b/tests/runtime_services/standard_service/psci/api_tests/affinity_info/test_psci_affinity_info.c
index 262c8c9..527f6bf 100644
--- a/tests/runtime_services/standard_service/psci/api_tests/affinity_info/test_psci_affinity_info.c
+++ b/tests/runtime_services/standard_service/psci/api_tests/affinity_info/test_psci_affinity_info.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2016, 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:
@@ -30,9 +30,9 @@
#include <arch.h>
#include <arch_helpers.h>
+#include <arm_gic.h>
#include <assert.h>
#include <events.h>
-#include <gic_v2.h>
#include <irq.h>
#include <plat_topology.h>
#include <platform.h>
diff --git a/tests/runtime_services/standard_service/psci/api_tests/validate_power_state/test_validate_power_state.c b/tests/runtime_services/standard_service/psci/api_tests/validate_power_state/test_validate_power_state.c
index a8dab69..20fc3c1 100644
--- a/tests/runtime_services/standard_service/psci/api_tests/validate_power_state/test_validate_power_state.c
+++ b/tests/runtime_services/standard_service/psci/api_tests/validate_power_state/test_validate_power_state.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2016, 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:
@@ -28,9 +28,9 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <arch_helpers.h>
+#include <arm_gic.h>
#include <debug.h>
#include <events.h>
-#include <gic_v2.h>
#include <irq.h>
#include <stdlib.h>
#include <platform.h>
diff --git a/tests/runtime_services/trusted_os/tsp/test_normal_int_switch.c b/tests/runtime_services/trusted_os/tsp/test_normal_int_switch.c
index 2c360ac..5b76d5e 100644
--- a/tests/runtime_services/trusted_os/tsp/test_normal_int_switch.c
+++ b/tests/runtime_services/trusted_os/tsp/test_normal_int_switch.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2016, 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:
@@ -29,9 +29,9 @@
*/
#include <arch_helpers.h>
+#include <arm_gic.h>
#include <assert.h>
#include <debug.h>
-#include <gic_v2.h>
#include <irq.h>
#include <mmio.h>
#include <platform.h>