diff options
Diffstat (limited to 'spm/scmi/include/ext/drivers/arm/gic_v2.h')
-rw-r--r-- | spm/scmi/include/ext/drivers/arm/gic_v2.h | 341 |
1 files changed, 341 insertions, 0 deletions
diff --git a/spm/scmi/include/ext/drivers/arm/gic_v2.h b/spm/scmi/include/ext/drivers/arm/gic_v2.h new file mode 100644 index 0000000..6e7b764 --- /dev/null +++ b/spm/scmi/include/ext/drivers/arm/gic_v2.h @@ -0,0 +1,341 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __GIC_V2_H__ +#define __GIC_V2_H__ + +/*************************************************************************** + * 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_SGIR 0xF00 +#define GICD_CPENDSGIR 0xF10 +#define GICD_SPENDSGIR 0xF20 + +/* GIC Distributor register shifts */ +#define ITARGETSR_SHIFT 2 +#define CPENDSGIR_SHIFT 2 +#define SPENDSGIR_SHIFT CPENDSGIR_SHIFT + +/* GICD_SGIR bit shifts */ +#define GICD_SGIR_INTID_SHIFT 0 +#define GICD_SGIR_CPUTL_SHIFT 16 + +/* Physical CPU Interface register offsets */ +#define GICC_CTLR 0x0 +#define GICC_PMR 0x4 +#define GICC_BPR 0x8 +#define GICC_IAR 0xC +#define GICC_EOIR 0x10 +#define GICC_RPR 0x14 +#define GICC_HPPIR 0x18 +#define GICC_AHPPIR 0x28 +#define GICC_IIDR 0xFC +#define GICC_DIR 0x1000 +#define GICC_PRIODROP GICC_EOIR + +/* GICC_IIDR bit masks and shifts */ +#define GICC_IIDR_PID_SHIFT 20 +#define GICC_IIDR_ARCH_SHIFT 16 +#define GICC_IIDR_REV_SHIFT 12 +#define GICC_IIDR_IMP_SHIFT 0 + +#define GICC_IIDR_PID_MASK 0xfff +#define GICC_IIDR_ARCH_MASK 0xf +#define GICC_IIDR_REV_MASK 0xf +#define GICC_IIDR_IMP_MASK 0xfff + +/* HYP view virtual CPU Interface register offsets */ +#define GICH_CTL 0x0 +#define GICH_VTR 0x4 +#define GICH_ELRSR0 0x30 +#define GICH_ELRSR1 0x34 +#define GICH_APR0 0xF0 +#define GICH_LR_BASE 0x100 + +/* Virtual CPU Interface register offsets */ +#define GICV_CTL 0x0 +#define GICV_PRIMASK 0x4 +#define GICV_BP 0x8 +#define GICV_INTACK 0xC +#define GICV_EOI 0x10 +#define GICV_RUNNINGPRI 0x14 +#define GICV_HIGHESTPEND 0x18 +#define GICV_DEACTIVATE 0x1000 + +/* GICC_IAR bit masks and shifts */ +#define GICC_IAR_INTID_SHIFT 0 +#define GICC_IAR_CPUID_SHIFT 10 + +#define GICC_IAR_INTID_MASK 0x3ff +#define GICC_IAR_CPUID_MASK 0x7 + +#define get_gicc_iar_intid(val) (((val) >> GICC_IAR_INTID_SHIFT) \ + & GICC_IAR_INTID_MASK) +#define get_gicc_iar_cpuid(val) (((val) >> GICC_IAR_CPUID_SHIFT) \ + & GICC_IAR_CPUID_MASK) + +/* + * GICC_CTLR is banked to provide Secure and Non-secure copies and the register + * bit assignments are different in the Secure and Non-secure copies. + * These are the bit assignments for the Non-secure copy. + */ +#define GICC_CTLR_ENABLE (1 << 0) +#define FIQ_BYP_DIS_GRP1 (1 << 5) +#define IRQ_BYP_DIS_GRP1 (1 << 6) +#define EOI_MODE_NS (1 << 9) + +#ifndef __ASSEMBLY__ + +#include <mmio.h> + +/******************************************************************************* + * Private Interfaces for internal use by the GICv2 driver + ******************************************************************************/ + +/******************************************************************************* + * GICv2 Distributor interface accessors for reading/writing entire registers + ******************************************************************************/ +static inline unsigned int gicd_read_sgir(unsigned int base) +{ + return mmio_read_32(base + GICD_SGIR); +} + +static inline void gicd_write_sgir(unsigned int base, unsigned int val) +{ + mmio_write_32(base + GICD_SGIR, val); +} + +/******************************************************************************* + * GICv2 CPU interface accessors for reading entire registers + ******************************************************************************/ + +static inline unsigned int gicc_read_ctlr(unsigned int base) +{ + return mmio_read_32(base + GICC_CTLR); +} + +static inline unsigned int gicc_read_pmr(unsigned int base) +{ + return mmio_read_32(base + GICC_PMR); +} + +static inline unsigned int gicc_read_bpr(unsigned int base) +{ + return mmio_read_32(base + GICC_BPR); +} + +static inline unsigned int gicc_read_iar(unsigned int base) +{ + return mmio_read_32(base + GICC_IAR); +} + +static inline unsigned int gicc_read_eoir(unsigned int base) +{ + return mmio_read_32(base + GICC_EOIR); +} + +static inline unsigned int gicc_read_hppir(unsigned int base) +{ + return mmio_read_32(base + GICC_HPPIR); +} + +static inline unsigned int gicc_read_ahppir(unsigned int base) +{ + return mmio_read_32(base + GICC_AHPPIR); +} + +static inline unsigned int gicc_read_dir(unsigned int base) +{ + return mmio_read_32(base + GICC_DIR); +} + +static inline unsigned int gicc_read_iidr(unsigned int base) +{ + return mmio_read_32(base + GICC_IIDR); +} + + +/******************************************************************************* + * GICv2 CPU interface accessors for writing entire registers + ******************************************************************************/ + +static inline void gicc_write_ctlr(unsigned int base, unsigned int val) +{ + mmio_write_32(base + GICC_CTLR, val); +} + +static inline void gicc_write_pmr(unsigned int base, unsigned int val) +{ + mmio_write_32(base + GICC_PMR, val); +} + +static inline void gicc_write_bpr(unsigned int base, unsigned int val) +{ + mmio_write_32(base + GICC_BPR, val); +} + + +static inline void gicc_write_iar(unsigned int base, unsigned int val) +{ + mmio_write_32(base + GICC_IAR, val); +} + +static inline void gicc_write_eoir(unsigned int base, unsigned int val) +{ + mmio_write_32(base + GICC_EOIR, val); +} + +static inline void gicc_write_hppir(unsigned int base, unsigned int val) +{ + mmio_write_32(base + GICC_HPPIR, val); +} + +static inline void gicc_write_dir(unsigned int base, unsigned int val) +{ + mmio_write_32(base + GICC_DIR, val); +} + +/****************************************************************************** + * GICv2 public driver API + *****************************************************************************/ + +/* + * 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 ISPENDR register. + */ +void gicv2_gicd_set_ispendr(unsigned int interrupt_id); + +/* + * 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); + +/* + * Read and return the target core mask of interrupt ID `num`. + */ +uint8_t gicv2_read_itargetsr_value(unsigned int num); + +/* + * Set the bit corresponding to `num` in the GICD ICENABLER register. + */ +void gicv2_gicd_set_icenabler(unsigned int num); + +/* + * Get the bit corresponding to `num` in the GICD ISENABLER register. + */ +unsigned int gicv2_gicd_get_isenabler(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); + +/* + * Set the target of interrupt ID `num` to the desired core mask. + */ +void gicv2_set_itargetsr_value(unsigned int num, unsigned int val); + +/* + * Send SGI with ID `sgi_id` to core with index `core_pos`. + */ +void gicv2_send_sgi(unsigned int sgi_id, unsigned int core_pos); + +/* + * Get the priority of the interrupt `interrupt_id`. + */ +unsigned int gicv2_gicd_get_ipriorityr(unsigned int interrupt_id); + +/* + * 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); + +/* + * Save the GICv2 SGI and PPI context prior to powering down the + * GIC Distributor. + */ +void gicv2_save_sgi_ppi_context(void); + +/* + * Restore the GICv2 SGI and PPI context after powering up the + * GIC Distributor. + */ +void gicv2_restore_sgi_ppi_context(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); + +/* + * Save the GICv2 CPU interface prior to powering down the CPU interface. + */ +void gicv2_save_cpuif_context(void); + +/* + * Restore the GICv2 CPU interface after powering up the CPU interface. + */ +void gicv2_restore_cpuif_context(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__ */ |