aboutsummaryrefslogtreecommitdiff
path: root/plat/fvp
diff options
context:
space:
mode:
authorAchin Gupta <achin.gupta@arm.com>2014-05-04 19:02:52 +0100
committerAchin Gupta <achin.gupta@arm.com>2014-05-22 17:47:19 +0100
commitdcc1816c91a63e959330d3a05bb085d0c77fb69a (patch)
tree33be23dba0b92d7296610664b942446c47131c59 /plat/fvp
parente1333f753f2760499ceed5c2d8f816574c3feb02 (diff)
downloadarm-trusted-firmware-dcc1816c91a63e959330d3a05bb085d0c77fb69a.tar.gz
Introduce platform api to access an ARM GIC
This patch introduces a set of functions which allow generic firmware code e.g. the interrupt management framework to access the platform interrupt controller. APIs for finding the type and id of the highest pending interrupt, acknowledging and EOIing an interrupt and finding the security state of an interrupt have been added. It is assumed that the platform interrupt controller implements the v2.0 of the ARM GIC architecture specification. Support for v3.0 of the specification for managing interrupts in EL3 and the platform port will be added in the future. Change-Id: Ib3a01c2cf3e3ab27806930f1be79db2b29f91bcf
Diffstat (limited to 'plat/fvp')
-rw-r--r--plat/fvp/plat_gic.c94
-rw-r--r--plat/fvp/platform.h9
2 files changed, 95 insertions, 8 deletions
diff --git a/plat/fvp/plat_gic.c b/plat/fvp/plat_gic.c
index dd409f5..7dec404 100644
--- a/plat/fvp/plat_gic.c
+++ b/plat/fvp/plat_gic.c
@@ -38,12 +38,6 @@
#include <platform.h>
#include <stdint.h>
-
-/*******************************************************************************
- * TODO: Revisit if priorities are being set such that no non-secure interrupt
- * can have a higher priority than a secure one as recommended in the GICv2 spec
- ******************************************************************************/
-
/*******************************************************************************
* This function does some minimal GICv3 configuration. The Firmware itself does
* not fully support GICv3 at this time and relies on GICv2 emulation as
@@ -322,3 +316,91 @@ uint32_t plat_interrupt_type_to_line(uint32_t type, uint32_t security_state)
#endif
}
+#if FVP_GIC_ARCH == 2
+/*******************************************************************************
+ * This function returns the type of the highest priority pending interrupt at
+ * the GIC cpu interface. INTR_TYPE_INVAL is returned when there is no
+ * interrupt pending.
+ ******************************************************************************/
+uint32_t ic_get_pending_interrupt_type()
+{
+ uint32_t id, gicc_base;
+
+ gicc_base = platform_get_cfgvar(CONFIG_GICC_ADDR);
+ id = gicc_read_hppir(gicc_base);
+
+ /* Assume that all secure interrupts are S-EL1 interrupts */
+ if (id < 1022)
+ return INTR_TYPE_S_EL1;
+
+ if (id == GIC_SPURIOUS_INTERRUPT)
+ return INTR_TYPE_INVAL;
+
+ return INTR_TYPE_NS;
+}
+
+/*******************************************************************************
+ * This function returns the id of the highest priority pending interrupt at
+ * the GIC cpu interface. INTR_ID_UNAVAILABLE is returned when there is no
+ * interrupt pending.
+ ******************************************************************************/
+uint32_t ic_get_pending_interrupt_id()
+{
+ uint32_t id, gicc_base;
+
+ gicc_base = platform_get_cfgvar(CONFIG_GICC_ADDR);
+ id = gicc_read_hppir(gicc_base);
+
+ if (id < 1022)
+ return id;
+
+ if (id == 1023)
+ return INTR_ID_UNAVAILABLE;
+
+ /*
+ * Find out which non-secure interrupt it is under the assumption that
+ * the GICC_CTLR.AckCtl bit is 0.
+ */
+ return gicc_read_ahppir(gicc_base);
+}
+
+/*******************************************************************************
+ * This functions reads the GIC cpu interface Interrupt Acknowledge register
+ * to start handling the pending interrupt. It returns the contents of the IAR.
+ ******************************************************************************/
+uint32_t ic_acknowledge_interrupt()
+{
+ return gicc_read_IAR(platform_get_cfgvar(CONFIG_GICC_ADDR));
+}
+
+/*******************************************************************************
+ * This functions writes the GIC cpu interface End Of Interrupt register with
+ * the passed value to finish handling the active interrupt
+ ******************************************************************************/
+void ic_end_of_interrupt(uint32_t id)
+{
+ gicc_write_EOIR(platform_get_cfgvar(CONFIG_GICC_ADDR), id);
+ return;
+}
+
+/*******************************************************************************
+ * This function returns the type of the interrupt id depending upon the group
+ * this interrupt has been configured under by the interrupt controller i.e.
+ * group0 or group1.
+ ******************************************************************************/
+uint32_t ic_get_interrupt_type(uint32_t id)
+{
+ uint32_t group;
+
+ group = gicd_get_igroupr(platform_get_cfgvar(CONFIG_GICD_ADDR), id);
+
+ /* Assume that all secure interrupts are S-EL1 interrupts */
+ if (group == GRP0)
+ return INTR_TYPE_S_EL1;
+ else
+ return INTR_TYPE_NS;
+}
+
+#else
+#error "Invalid GIC architecture version specified for FVP port"
+#endif
diff --git a/plat/fvp/platform.h b/plat/fvp/platform.h
index 814fb77..9b85b23 100644
--- a/plat/fvp/platform.h
+++ b/plat/fvp/platform.h
@@ -425,7 +425,12 @@ extern void plat_get_entry_point_info(unsigned long target_security,
extern void fvp_cci_setup(void);
-/* Declarations for fvp_gic.c */
+/* Declarations for plat_gic.c */
+extern uint32_t ic_get_pending_interrupt_id(void);
+extern uint32_t ic_get_pending_interrupt_type(void);
+extern uint32_t ic_acknowledge_interrupt(void);
+extern uint32_t ic_get_interrupt_type(uint32_t id);
+extern void ic_end_of_interrupt(uint32_t id);
extern void gic_cpuif_deactivate(unsigned int);
extern void gic_cpuif_setup(unsigned int);
extern void gic_pcpu_distif_setup(unsigned int);
@@ -433,7 +438,7 @@ extern void gic_setup(void);
extern uint32_t plat_interrupt_type_to_line(uint32_t type,
uint32_t security_state);
-/* Declarations for fvp_topology.c */
+/* Declarations for plat_topology.c */
extern int plat_setup_topology(void);
extern int plat_get_max_afflvl(void);
extern unsigned int plat_get_aff_count(unsigned int, unsigned long);