diff options
author | Jeenu Viswambharan <jeenu.viswambharan@arm.com> | 2017-09-22 08:32:09 +0100 |
---|---|---|
committer | Jeenu Viswambharan <jeenu.viswambharan@arm.com> | 2017-10-16 16:50:02 +0100 |
commit | a2816a16440d9eb1223ba505bc30faf6cd31b0ee (patch) | |
tree | 608060349061283ee78f0f9c2438e365b393bd1d /drivers/arm | |
parent | fc529fee720de5fef8388c52bfefcb807ac764b0 (diff) |
GIC: Add API to set/clear interrupt pending
API documentation updated.
Change-Id: I14e33cfc7dfa93257c82d76fae186b17a1b6d266
Co-authored-by: Yousuf A <yousuf.sait@arm.com>
Signed-off-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
Diffstat (limited to 'drivers/arm')
-rw-r--r-- | drivers/arm/gic/v2/gicv2_main.c | 38 | ||||
-rw-r--r-- | drivers/arm/gic/v3/gicv3_helpers.c | 22 | ||||
-rw-r--r-- | drivers/arm/gic/v3/gicv3_main.c | 52 | ||||
-rw-r--r-- | drivers/arm/gic/v3/gicv3_private.h | 7 |
4 files changed, 119 insertions, 0 deletions
diff --git a/drivers/arm/gic/v2/gicv2_main.c b/drivers/arm/gic/v2/gicv2_main.c index f0b902cf..eab4c3bf 100644 --- a/drivers/arm/gic/v2/gicv2_main.c +++ b/drivers/arm/gic/v2/gicv2_main.c @@ -438,3 +438,41 @@ void gicv2_set_spi_routing(unsigned int id, int proc_num) gicd_set_itargetsr(driver_data->gicd_base, id, target); } + +/******************************************************************************* + * This function clears the pending status of an interrupt identified by id. + ******************************************************************************/ +void gicv2_clear_interrupt_pending(unsigned int id) +{ + assert(driver_data); + assert(driver_data->gicd_base); + + /* SGIs can't be cleared pending */ + assert(id >= MIN_PPI_ID); + + /* + * Clear pending interrupt, and ensure that any shared variable updates + * depending on out of band interrupt trigger are observed afterwards. + */ + gicd_set_icpendr(driver_data->gicd_base, id); + dsbishst(); +} + +/******************************************************************************* + * This function sets the pending status of an interrupt identified by id. + ******************************************************************************/ +void gicv2_set_interrupt_pending(unsigned int id) +{ + assert(driver_data); + assert(driver_data->gicd_base); + + /* SGIs can't be cleared pending */ + assert(id >= MIN_PPI_ID); + + /* + * Ensure that any shared variable updates depending on out of band + * interrupt trigger are observed before setting interrupt pending. + */ + dsbishst(); + gicd_set_ispendr(driver_data->gicd_base, id); +} diff --git a/drivers/arm/gic/v3/gicv3_helpers.c b/drivers/arm/gic/v3/gicv3_helpers.c index ee874f92..3abc6a5c 100644 --- a/drivers/arm/gic/v3/gicv3_helpers.c +++ b/drivers/arm/gic/v3/gicv3_helpers.c @@ -195,6 +195,28 @@ unsigned int gicr_get_isactiver0(uintptr_t base, unsigned int id) } /* + * Accessor to clear the bit corresponding to interrupt ID in GIC Re-distributor + * ICPENDRR0. + */ +void gicr_set_icpendr0(uintptr_t base, unsigned int id) +{ + unsigned bit_num = id & ((1 << ICPENDR_SHIFT) - 1); + + gicr_write_icpendr0(base, (1 << bit_num)); +} + +/* + * Accessor to set the bit corresponding to interrupt ID in GIC Re-distributor + * ISPENDR0. + */ +void gicr_set_ispendr0(uintptr_t base, unsigned int id) +{ + unsigned bit_num = id & ((1 << ISPENDR_SHIFT) - 1); + + gicr_write_ispendr0(base, (1 << bit_num)); +} + +/* * Accessor to set the byte corresponding to interrupt ID * in GIC Re-distributor IPRIORITYR. */ diff --git a/drivers/arm/gic/v3/gicv3_main.c b/drivers/arm/gic/v3/gicv3_main.c index c81ba950..43dd77f1 100644 --- a/drivers/arm/gic/v3/gicv3_main.c +++ b/drivers/arm/gic/v3/gicv3_main.c @@ -1037,3 +1037,55 @@ void gicv3_set_spi_routing(unsigned int id, unsigned int irm, u_register_t mpidr } } } + +/******************************************************************************* + * This function clears the pending status of an interrupt identified by id. + * The proc_num is used if the interrupt is SGI or PPI, and programs the + * corresponding Redistributor interface. + ******************************************************************************/ +void gicv3_clear_interrupt_pending(unsigned int id, unsigned int proc_num) +{ + assert(gicv3_driver_data); + assert(gicv3_driver_data->gicd_base); + assert(proc_num < gicv3_driver_data->rdistif_num); + assert(gicv3_driver_data->rdistif_base_addrs); + + /* + * Clear pending interrupt, and ensure that any shared variable updates + * depending on out of band interrupt trigger are observed afterwards. + */ + if (id < MIN_SPI_ID) { + /* For SGIs and PPIs */ + gicr_set_icpendr0(gicv3_driver_data->rdistif_base_addrs[proc_num], + id); + } else { + gicd_set_icpendr(gicv3_driver_data->gicd_base, id); + } + dsbishst(); +} + +/******************************************************************************* + * This function sets the pending status of an interrupt identified by id. + * The proc_num is used if the interrupt is SGI or PPI and programs the + * corresponding Redistributor interface. + ******************************************************************************/ +void gicv3_set_interrupt_pending(unsigned int id, unsigned int proc_num) +{ + assert(gicv3_driver_data); + assert(gicv3_driver_data->gicd_base); + assert(proc_num < gicv3_driver_data->rdistif_num); + assert(gicv3_driver_data->rdistif_base_addrs); + + /* + * Ensure that any shared variable updates depending on out of band + * interrupt trigger are observed before setting interrupt pending. + */ + dsbishst(); + if (id < MIN_SPI_ID) { + /* For SGIs and PPIs */ + gicr_set_ispendr0(gicv3_driver_data->rdistif_base_addrs[proc_num], + id); + } else { + gicd_set_ispendr(gicv3_driver_data->gicd_base, id); + } +} diff --git a/drivers/arm/gic/v3/gicv3_private.h b/drivers/arm/gic/v3/gicv3_private.h index 19fce2e7..43529c5a 100644 --- a/drivers/arm/gic/v3/gicv3_private.h +++ b/drivers/arm/gic/v3/gicv3_private.h @@ -72,6 +72,8 @@ void gicd_set_igrpmodr(uintptr_t base, unsigned int id); void gicr_set_igrpmodr0(uintptr_t base, unsigned int id); void gicr_set_isenabler0(uintptr_t base, unsigned int id); void gicr_set_icenabler0(uintptr_t base, unsigned int id); +void gicr_set_ispendr0(uintptr_t base, unsigned int id); +void gicr_set_icpendr0(uintptr_t base, unsigned int id); void gicr_set_igroupr0(uintptr_t base, unsigned int id); void gicd_clr_igrpmodr(uintptr_t base, unsigned int id); void gicr_clr_igrpmodr0(uintptr_t base, unsigned int id); @@ -221,6 +223,11 @@ static inline unsigned int gicr_read_isenabler0(uintptr_t base) return mmio_read_32(base + GICR_ISENABLER0); } +static inline void gicr_write_icpendr0(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICR_ICPENDR0, val); +} + static inline void gicr_write_isenabler0(uintptr_t base, unsigned int val) { mmio_write_32(base + GICR_ISENABLER0, val); |