diff options
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> |