diff options
Diffstat (limited to 'drivers/arm/gic')
-rw-r--r-- | drivers/arm/gic/v3/arm_gicv3_common.c | 105 | ||||
-rw-r--r-- | drivers/arm/gic/v3/gic500.c | 22 | ||||
-rw-r--r-- | drivers/arm/gic/v3/gic600.c | 13 | ||||
-rw-r--r-- | drivers/arm/gic/v3/gicv3_main.c | 295 | ||||
-rw-r--r-- | drivers/arm/gic/v3/gicv3_private.h | 81 |
5 files changed, 513 insertions, 3 deletions
diff --git a/drivers/arm/gic/v3/arm_gicv3_common.c b/drivers/arm/gic/v3/arm_gicv3_common.c new file mode 100644 index 00000000..8d552ca5 --- /dev/null +++ b/drivers/arm/gic/v3/arm_gicv3_common.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Driver for implementation defined features that are identical in ARM GICv3 +* implementations (GIC-500 and GIC-600 for now). This driver only overrides +* APIs that are different to those generic ones in GICv3 driver. + */ + +#include <arch_helpers.h> +#include <assert.h> +#include <gicv3.h> + +#include "gicv3_private.h" +#include "arm_gicv3_common.h" + +/* + * Flush the internal GIC cache of the LPIs pending tables to memory before + * saving the state of the Redistributor. This is required before powering off + * the GIC when the pending status must be preserved. + * `rdist_proc_num` is the processor number corresponding to the Redistributor of the + * current CPU. + */ +void arm_gicv3_distif_pre_save(unsigned int rdist_proc_num) +{ + uintptr_t gicr_base = 0; + + assert(gicv3_driver_data); + assert(gicv3_driver_data->rdistif_base_addrs); + + /* + * The GICR_WAKER.Sleep bit should be set only when both + * GICR_WAKER.ChildrenAsleep and GICR_WAKER.ProcessorSleep are set on + * all the Redistributors. + */ + for (unsigned int i = 0; i < gicv3_driver_data->rdistif_num; i++) { + gicr_base = gicv3_driver_data->rdistif_base_addrs[i]; + assert(gicr_base); + assert(gicr_read_waker(gicr_base) & WAKER_CA_BIT); + assert(gicr_read_waker(gicr_base) & WAKER_PS_BIT); + } + + gicr_base = gicv3_driver_data->rdistif_base_addrs[rdist_proc_num]; + /* + * According to the TRM, there is only one instance of the + * GICR_WAKER.Sleep and GICR_WAKER.Quiescent bits that can be accessed + * through any of the Redistributor. + */ + + /* + * Set GICR_WAKER.Sleep + * After this point, the system must be configured so that the + * wake_request signals for the right cores are asserted when a wakeup + * interrupt is detected. The GIC will not be able to do that anymore + * when the GICR_WAKER.Sleep bit is set to 1. + */ + gicr_write_waker(gicr_base, gicr_read_waker(gicr_base) | WAKER_SL_BIT); + + /* Wait until the GICR_WAKER.Quiescent bit is set */ + while (!(gicr_read_waker(gicr_base) & WAKER_QSC_BIT)) + ; +} + +/* + * Allow the LPIs pending state to be read back from the tables in memory after + * having restored the state of the GIC Redistributor. + */ +void arm_gicv3_distif_post_restore(unsigned int rdist_proc_num) +{ + uintptr_t gicr_base; + + assert(gicv3_driver_data); + assert(gicv3_driver_data->rdistif_base_addrs); + + /* + * According to the TRM, there is only one instance of the + * GICR_WAKER.Sleep and GICR_WAKER.Quiescent bits that can be accessed + * through any of the Redistributor. + */ + gicr_base = gicv3_driver_data->rdistif_base_addrs[rdist_proc_num]; + assert(gicr_base); + + /* + * Writes to GICR_WAKER.Sleep bit are ignored if GICR_WAKER.Quiescent + * bit is not set. We should be alright on power on path, therefore + * coming out of sleep and Quiescent should be set, but we assert in + * case. + */ + assert(gicr_read_waker(gicr_base) & WAKER_QSC_BIT); + + /* Clear GICR_WAKER.Sleep */ + gicr_write_waker(gicr_base, gicr_read_waker(gicr_base) & ~WAKER_SL_BIT); + + /* + * We don't know if the effects of setting GICR_WAKER.Sleep bit is + * instantaneous, so we wait until the interface is not Quiescent + * anymore. + */ + while (gicr_read_waker(gicr_base) & WAKER_QSC_BIT) + ; +} + diff --git a/drivers/arm/gic/v3/gic500.c b/drivers/arm/gic/v3/gic500.c new file mode 100644 index 00000000..f03e33f8 --- /dev/null +++ b/drivers/arm/gic/v3/gic500.c @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Driver for GIC500-specific features. This driver only overrides APIs that are + * different to those generic ones in GICv3 driver. + */ +#include "gicv3_private.h" + +void gicv3_distif_pre_save(unsigned int proc_num) +{ + arm_gicv3_distif_pre_save(proc_num); +} + +void gicv3_distif_post_restore(unsigned int proc_num) +{ + arm_gicv3_distif_post_restore(proc_num); +} + diff --git a/drivers/arm/gic/v3/gic600.c b/drivers/arm/gic/v3/gic600.c index 217c08fd..eb4fc548 100644 --- a/drivers/arm/gic/v3/gic600.c +++ b/drivers/arm/gic/v3/gic600.c @@ -32,9 +32,6 @@ #define PWRR_ON (0 << PWRR_RDPD_SHIFT) #define PWRR_OFF (1 << PWRR_RDPD_SHIFT) -/* Generic GICv3 resources */ -extern const gicv3_driver_data_t *gicv3_driver_data; - /* GIC600-specific accessor functions */ static void gicr_write_pwrr(uintptr_t base, unsigned int val) { @@ -82,6 +79,16 @@ static void gic600_pwr_off(uintptr_t base) } } +void gicv3_distif_pre_save(unsigned int proc_num) +{ + arm_gicv3_distif_pre_save(proc_num); +} + +void gicv3_distif_post_restore(unsigned int proc_num) +{ + arm_gicv3_distif_post_restore(proc_num); +} + /* * Power off GIC600 redistributor */ diff --git a/drivers/arm/gic/v3/gicv3_main.c b/drivers/arm/gic/v3/gicv3_main.c index b68d9988..83bf430f 100644 --- a/drivers/arm/gic/v3/gicv3_main.c +++ b/drivers/arm/gic/v3/gicv3_main.c @@ -21,6 +21,27 @@ static unsigned int gicv2_compat; #pragma weak gicv3_rdistif_off #pragma weak gicv3_rdistif_on + +/* Helper macros to save and restore GICD registers to and from the context */ +#define RESTORE_GICD_REGS(base, ctx, intr_num, reg, REG) \ + do { \ + for (unsigned int int_id = MIN_SPI_ID; int_id < intr_num; \ + int_id += (1 << REG##_SHIFT)) { \ + gicd_write_##reg(base, int_id, \ + ctx->gicd_##reg[(int_id - MIN_SPI_ID) >> REG##_SHIFT]); \ + } \ + } while (0) + +#define SAVE_GICD_REGS(base, ctx, intr_num, reg, REG) \ + do { \ + for (unsigned int int_id = MIN_SPI_ID; int_id < intr_num; \ + int_id += (1 << REG##_SHIFT)) { \ + ctx->gicd_##reg[(int_id - MIN_SPI_ID) >> REG##_SHIFT] =\ + gicd_read_##reg(base, int_id); \ + } \ + } while (0) + + /******************************************************************************* * This function initialises the ARM GICv3 driver in EL3 with provided platform * inputs. @@ -406,3 +427,277 @@ unsigned int gicv3_get_interrupt_type(unsigned int id, /* Else it is a Group 0 Secure interrupt */ return INTR_GROUP0; } + +/***************************************************************************** + * Function to save the GIC Redistributor register context. This function + * must be invoked after CPU interface disable and prior to Distributor save. + *****************************************************************************/ +void gicv3_rdistif_save(unsigned int proc_num, gicv3_redist_ctx_t * const rdist_ctx) +{ + uintptr_t gicr_base; + unsigned int int_id; + + assert(gicv3_driver_data); + assert(proc_num < gicv3_driver_data->rdistif_num); + assert(gicv3_driver_data->rdistif_base_addrs); + assert(IS_IN_EL3()); + assert(rdist_ctx); + + gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; + + /* + * Wait for any write to GICR_CTLR to complete before trying to save any + * state. + */ + gicr_wait_for_pending_write(gicr_base); + + rdist_ctx->gicr_ctlr = gicr_read_ctlr(gicr_base); + + rdist_ctx->gicr_propbaser = gicr_read_propbaser(gicr_base); + rdist_ctx->gicr_pendbaser = gicr_read_pendbaser(gicr_base); + + rdist_ctx->gicr_igroupr0 = gicr_read_igroupr0(gicr_base); + rdist_ctx->gicr_isenabler0 = gicr_read_isenabler0(gicr_base); + rdist_ctx->gicr_ispendr0 = gicr_read_ispendr0(gicr_base); + rdist_ctx->gicr_isactiver0 = gicr_read_isactiver0(gicr_base); + rdist_ctx->gicr_icfgr0 = gicr_read_icfgr0(gicr_base); + rdist_ctx->gicr_icfgr1 = gicr_read_icfgr1(gicr_base); + rdist_ctx->gicr_igrpmodr0 = gicr_read_igrpmodr0(gicr_base); + rdist_ctx->gicr_nsacr = gicr_read_nsacr(gicr_base); + for (int_id = MIN_SGI_ID; int_id < TOTAL_PCPU_INTR_NUM; + int_id += (1 << IPRIORITYR_SHIFT)) { + rdist_ctx->gicr_ipriorityr[(int_id - MIN_SGI_ID) >> IPRIORITYR_SHIFT] = + gicr_read_ipriorityr(gicr_base, int_id); + } + + + /* + * Call the pre-save hook that implements the IMP DEF sequence that may + * be required on some GIC implementations. As this may need to access + * the Redistributor registers, we pass it proc_num. + */ + gicv3_distif_pre_save(proc_num); +} + +/***************************************************************************** + * Function to restore the GIC Redistributor register context. We disable + * LPI and per-cpu interrupts before we start restore of the Redistributor. + * This function must be invoked after Distributor restore but prior to + * CPU interface enable. The pending and active interrupts are restored + * after the interrupts are fully configured and enabled. + *****************************************************************************/ +void gicv3_rdistif_init_restore(unsigned int proc_num, + const gicv3_redist_ctx_t * const rdist_ctx) +{ + uintptr_t gicr_base; + unsigned int int_id; + + assert(gicv3_driver_data); + assert(proc_num < gicv3_driver_data->rdistif_num); + assert(gicv3_driver_data->rdistif_base_addrs); + assert(IS_IN_EL3()); + assert(rdist_ctx); + + gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; + + /* Power on redistributor */ + gicv3_rdistif_on(proc_num); + + /* + * Call the post-restore hook that implements the IMP DEF sequence that + * may be required on some GIC implementations. As this may need to + * access the Redistributor registers, we pass it proc_num. + */ + gicv3_distif_post_restore(proc_num); + + /* + * Disable all SGIs (imp. def.)/PPIs before configuring them. This is a + * more scalable approach as it avoids clearing the enable bits in the + * GICD_CTLR + */ + gicr_write_icenabler0(gicr_base, ~0); + /* Wait for pending writes to GICR_ICENABLER */ + gicr_wait_for_pending_write(gicr_base); + + /* + * Disable the LPIs to avoid unpredictable behavior when writing to + * GICR_PROPBASER and GICR_PENDBASER. + */ + gicr_write_ctlr(gicr_base, + rdist_ctx->gicr_ctlr & ~(GICR_CTLR_EN_LPIS_BIT)); + + /* Restore registers' content */ + gicr_write_propbaser(gicr_base, rdist_ctx->gicr_propbaser); + gicr_write_pendbaser(gicr_base, rdist_ctx->gicr_pendbaser); + + gicr_write_igroupr0(gicr_base, rdist_ctx->gicr_igroupr0); + + for (int_id = MIN_SGI_ID; int_id < TOTAL_PCPU_INTR_NUM; + int_id += (1 << IPRIORITYR_SHIFT)) { + gicr_write_ipriorityr(gicr_base, int_id, + rdist_ctx->gicr_ipriorityr[ + (int_id - MIN_SGI_ID) >> IPRIORITYR_SHIFT]); + } + + gicr_write_icfgr0(gicr_base, rdist_ctx->gicr_icfgr0); + gicr_write_icfgr1(gicr_base, rdist_ctx->gicr_icfgr1); + gicr_write_igrpmodr0(gicr_base, rdist_ctx->gicr_igrpmodr0); + gicr_write_nsacr(gicr_base, rdist_ctx->gicr_nsacr); + + /* Restore after group and priorities are set */ + gicr_write_ispendr0(gicr_base, rdist_ctx->gicr_ispendr0); + gicr_write_isactiver0(gicr_base, rdist_ctx->gicr_isactiver0); + + /* + * Wait for all writes to the Distributor to complete before enabling + * the SGI and PPIs. + */ + gicr_wait_for_upstream_pending_write(gicr_base); + gicr_write_isenabler0(gicr_base, rdist_ctx->gicr_isenabler0); + + /* + * Restore GICR_CTLR.Enable_LPIs bit and wait for pending writes in case + * the first write to GICR_CTLR was still in flight (this write only + * restores GICR_CTLR.Enable_LPIs and no waiting is required for this + * bit). + */ + gicr_write_ctlr(gicr_base, rdist_ctx->gicr_ctlr); + gicr_wait_for_pending_write(gicr_base); +} + +/***************************************************************************** + * Function to save the GIC Distributor register context. This function + * must be invoked after CPU interface disable and Redistributor save. + *****************************************************************************/ +void gicv3_distif_save(gicv3_dist_ctx_t * const dist_ctx) +{ + unsigned int num_ints; + + assert(gicv3_driver_data); + assert(gicv3_driver_data->gicd_base); + assert(IS_IN_EL3()); + assert(dist_ctx); + + uintptr_t gicd_base = gicv3_driver_data->gicd_base; + + num_ints = gicd_read_typer(gicd_base); + num_ints &= TYPER_IT_LINES_NO_MASK; + num_ints = (num_ints + 1) << 5; + + assert(num_ints <= MAX_SPI_ID + 1); + + /* Wait for pending write to complete */ + gicd_wait_for_pending_write(gicd_base); + + /* Save the GICD_CTLR */ + dist_ctx->gicd_ctlr = gicd_read_ctlr(gicd_base); + + /* Save GICD_IGROUPR for INTIDs 32 - 1020 */ + SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, igroupr, IGROUPR); + + /* Save GICD_ISENABLER for INT_IDs 32 - 1020 */ + SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, isenabler, ISENABLER); + + /* Save GICD_ISPENDR for INTIDs 32 - 1020 */ + SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, ispendr, ISPENDR); + + /* Save GICD_ISACTIVER for INTIDs 32 - 1020 */ + SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, isactiver, ISACTIVER); + + /* Save GICD_IPRIORITYR for INTIDs 32 - 1020 */ + SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, ipriorityr, IPRIORITYR); + + /* Save GICD_ICFGR for INTIDs 32 - 1020 */ + SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, icfgr, ICFGR); + + /* Save GICD_IGRPMODR for INTIDs 32 - 1020 */ + SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, igrpmodr, IGRPMODR); + + /* Save GICD_NSACR for INTIDs 32 - 1020 */ + SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, nsacr, NSACR); + + /* Save GICD_IROUTER for INTIDs 32 - 1024 */ + SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, irouter, IROUTER); + + /* + * GICD_ITARGETSR<n> and GICD_SPENDSGIR<n> are RAZ/WI when + * GICD_CTLR.ARE_(S|NS) bits are set which is the case for our GICv3 + * driver. + */ +} + +/***************************************************************************** + * Function to restore the GIC Distributor register context. We disable G0, G1S + * and G1NS interrupt groups before we start restore of the Distributor. This + * function must be invoked prior to Redistributor restore and CPU interface + * enable. The pending and active interrupts are restored after the interrupts + * are fully configured and enabled. + *****************************************************************************/ +void gicv3_distif_init_restore(const gicv3_dist_ctx_t * const dist_ctx) +{ + unsigned int num_ints = 0; + + assert(gicv3_driver_data); + assert(gicv3_driver_data->gicd_base); + assert(IS_IN_EL3()); + assert(dist_ctx); + + uintptr_t gicd_base = gicv3_driver_data->gicd_base; + + /* + * Clear the "enable" bits for G0/G1S/G1NS interrupts before configuring + * the ARE_S bit. The Distributor might generate a system error + * otherwise. + */ + gicd_clr_ctlr(gicd_base, + CTLR_ENABLE_G0_BIT | + CTLR_ENABLE_G1S_BIT | + CTLR_ENABLE_G1NS_BIT, + RWP_TRUE); + + /* Set the ARE_S and ARE_NS bit now that interrupts have been disabled */ + gicd_set_ctlr(gicd_base, CTLR_ARE_S_BIT | CTLR_ARE_NS_BIT, RWP_TRUE); + + num_ints = gicd_read_typer(gicd_base); + num_ints &= TYPER_IT_LINES_NO_MASK; + num_ints = (num_ints + 1) << 5; + + assert(num_ints <= MAX_SPI_ID + 1); + + /* Restore GICD_IGROUPR for INTIDs 32 - 1020 */ + RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, igroupr, IGROUPR); + + /* Restore GICD_IPRIORITYR for INTIDs 32 - 1020 */ + RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, ipriorityr, IPRIORITYR); + + /* Restore GICD_ICFGR for INTIDs 32 - 1020 */ + RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, icfgr, ICFGR); + + /* Restore GICD_IGRPMODR for INTIDs 32 - 1020 */ + RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, igrpmodr, IGRPMODR); + + /* Restore GICD_NSACR for INTIDs 32 - 1020 */ + RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, nsacr, NSACR); + + /* Restore GICD_IROUTER for INTIDs 32 - 1020 */ + RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, irouter, IROUTER); + + /* + * Restore ISENABLER, ISPENDR and ISACTIVER after the interrupts are + * configured. + */ + + /* Restore GICD_ISENABLER for INT_IDs 32 - 1020 */ + RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, isenabler, ISENABLER); + + /* Restore GICD_ISPENDR for INTIDs 32 - 1020 */ + RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, ispendr, ISPENDR); + + /* Restore GICD_ISACTIVER for INTIDs 32 - 1020 */ + RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, isactiver, ISACTIVER); + + /* Restore the GICD_CTLR */ + gicd_write_ctlr(gicd_base, dist_ctx->gicd_ctlr); + gicd_wait_for_pending_write(gicd_base); + +} diff --git a/drivers/arm/gic/v3/gicv3_private.h b/drivers/arm/gic/v3/gicv3_private.h index da4bcbf7..7224e067 100644 --- a/drivers/arm/gic/v3/gicv3_private.h +++ b/drivers/arm/gic/v3/gicv3_private.h @@ -7,6 +7,7 @@ #ifndef __GICV3_PRIVATE_H__ #define __GICV3_PRIVATE_H__ +#include <assert.h> #include <gic_common.h> #include <gicv3.h> #include <mmio.h> @@ -43,6 +44,11 @@ #endif /******************************************************************************* + * GICv3 private global variables declarations + ******************************************************************************/ +extern const gicv3_driver_data_t *gicv3_driver_data; + +/******************************************************************************* * Private GICv3 function prototypes for accessing entire registers. * Note: The raw register values correspond to multiple interrupt IDs and * the number of interrupt IDs involved depends on the register accessed. @@ -150,6 +156,11 @@ static inline unsigned long long gicr_read_ctlr(uintptr_t base) return mmio_read_64(base + GICR_CTLR); } +static inline void gicr_write_ctlr(uintptr_t base, uint64_t val) +{ + mmio_write_64(base + GICR_CTLR, val); +} + static inline unsigned long long gicr_read_typer(uintptr_t base) { return mmio_read_64(base + GICR_TYPER); @@ -178,6 +189,16 @@ static inline void gicr_wait_for_pending_write(uintptr_t gicr_base) ; } +static inline void gicr_wait_for_upstream_pending_write(uintptr_t gicr_base) +{ + while (gicr_read_ctlr(gicr_base) & GICR_CTLR_UWP_BIT) + ; +} + +/* Private implementation of Distributor power control hooks */ +void arm_gicv3_distif_pre_save(unsigned int rdist_proc_num); +void arm_gicv3_distif_post_restore(unsigned int rdist_proc_num); + /******************************************************************************* * GIC Re-distributor functions for accessing entire registers. * Note: The raw register values correspond to multiple interrupt IDs and @@ -208,6 +229,16 @@ static inline unsigned int gicr_read_igroupr0(uintptr_t base) return mmio_read_32(base + GICR_IGROUPR0); } +static inline unsigned int gicr_read_ispendr0(uintptr_t base) +{ + return mmio_read_32(base + GICR_ISPENDR0); +} + +static inline void gicr_write_ispendr0(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICR_ISPENDR0, val); +} + static inline void gicr_write_igroupr0(uintptr_t base, unsigned int val) { mmio_write_32(base + GICR_IGROUPR0, val); @@ -223,14 +254,64 @@ static inline void gicr_write_igrpmodr0(uintptr_t base, unsigned int val) mmio_write_32(base + GICR_IGRPMODR0, val); } +static inline unsigned int gicr_read_nsacr(uintptr_t base) +{ + return mmio_read_32(base + GICR_NSACR); +} + +static inline void gicr_write_nsacr(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICR_NSACR, val); +} + +static inline unsigned int gicr_read_isactiver0(uintptr_t base) +{ + return mmio_read_32(base + GICR_ISACTIVER0); +} + +static inline void gicr_write_isactiver0(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICR_ISACTIVER0, val); +} + +static inline unsigned int gicr_read_icfgr0(uintptr_t base) +{ + return mmio_read_32(base + GICR_ICFGR0); +} + static inline unsigned int gicr_read_icfgr1(uintptr_t base) { return mmio_read_32(base + GICR_ICFGR1); } +static inline void gicr_write_icfgr0(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICR_ICFGR0, val); +} + static inline void gicr_write_icfgr1(uintptr_t base, unsigned int val) { mmio_write_32(base + GICR_ICFGR1, val); } +static inline unsigned int gicr_read_propbaser(uintptr_t base) +{ + return mmio_read_32(base + GICR_PROPBASER); +} + +static inline void gicr_write_propbaser(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICR_PROPBASER, val); +} + +static inline unsigned int gicr_read_pendbaser(uintptr_t base) +{ + return mmio_read_32(base + GICR_PENDBASER); +} + +static inline void gicr_write_pendbaser(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICR_PENDBASER, val); +} + #endif /* __GICV3_PRIVATE_H__ */ |