diff options
Diffstat (limited to 'drivers/arm/gic/v2/gicv2_main.c')
-rw-r--r-- | drivers/arm/gic/v2/gicv2_main.c | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/drivers/arm/gic/v2/gicv2_main.c b/drivers/arm/gic/v2/gicv2_main.c index 4861e02d..8048c6a7 100644 --- a/drivers/arm/gic/v2/gicv2_main.c +++ b/drivers/arm/gic/v2/gicv2_main.c @@ -10,11 +10,19 @@ #include <debug.h> #include <gic_common.h> #include <gicv2.h> +#include <spinlock.h> #include "../common/gic_common_private.h" #include "gicv2_private.h" static const gicv2_driver_data_t *driver_data; +/* + * Spinlock to guard registers needing read-modify-write. APIs protected by this + * spinlock are used either at boot time (when only a single CPU is active), or + * when the system is fully coherent. + */ +spinlock_t gic_lock; + /******************************************************************************* * Enable secure interrupts and use FIQs to route them. Disable legacy bypass * and set the priority mask register to allow all interrupts to trickle in. @@ -335,3 +343,28 @@ void gicv2_set_interrupt_priority(unsigned int id, unsigned int priority) gicd_set_ipriorityr(driver_data->gicd_base, id, priority); } + +/******************************************************************************* + * This function assigns group for the interrupt identified by id. The group can + * be any of GICV2_INTR_GROUP* + ******************************************************************************/ +void gicv2_set_interrupt_type(unsigned int id, unsigned int type) +{ + assert(driver_data); + assert(driver_data->gicd_base); + assert(id <= MAX_SPI_ID); + + /* Serialize read-modify-write to Distributor registers */ + spin_lock(&gic_lock); + switch (type) { + case GICV2_INTR_GROUP1: + gicd_set_igroupr(driver_data->gicd_base, id); + break; + case GICV2_INTR_GROUP0: + gicd_clr_igroupr(driver_data->gicd_base, id); + break; + default: + assert(0); + } + spin_unlock(&gic_lock); +} |