summaryrefslogtreecommitdiff
path: root/spm/scmi/include/ext/drivers/arm/gic_v2.h
diff options
context:
space:
mode:
Diffstat (limited to 'spm/scmi/include/ext/drivers/arm/gic_v2.h')
-rw-r--r--spm/scmi/include/ext/drivers/arm/gic_v2.h341
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__ */