GIC: Add APIs to enable and disable interrupt
authorJeenu Viswambharan <jeenu.viswambharan@arm.com>
Fri, 22 Sep 2017 07:32:09 +0000 (08:32 +0100)
committerJeenu Viswambharan <jeenu.viswambharan@arm.com>
Mon, 16 Oct 2017 15:50:01 +0000 (16:50 +0100)
API documentation updated.

Change-Id: Ice7511f8df5356851001d2f7dc2a46cfe318f9ba
Co-authored-by: Yousuf A <yousuf.sait@arm.com>
Signed-off-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
docs/platform-interrupt-controller-API.rst
drivers/arm/gic/v2/gicv2_main.c
drivers/arm/gic/v3/gicv3_helpers.c
drivers/arm/gic/v3/gicv3_main.c
drivers/arm/gic/v3/gicv3_private.h
include/drivers/arm/gicv2.h
include/drivers/arm/gicv3.h
include/plat/common/platform.h
plat/common/plat_gicv2.c
plat/common/plat_gicv3.c

index d0a2ad27690892ed95ce97727428df4d9918a4c3..bea1a64b53ca0f21eb65fcc99de399d247fc7366 100644 (file)
@@ -81,6 +81,36 @@ In case of ARM standard platforms using GIC, the implementation of the API reads
 the GIC *Set Active Register* to read and return the active status of the
 interrupt.
 
+Function: void plat_ic_enable_interrupt(unsigned int id); [optional]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+    Argument : unsigned int
+    Return   : void
+
+This API should enable the interrupt ID specified by the first parameter,
+``id``. PEs in the system are expected to receive only enabled interrupts.
+
+In case of ARM standard platforms using GIC, the implementation of the API
+inserts barrier to make memory updates visible before enabling interrupt, and
+then writes to GIC *Set Enable Register* to enable the interrupt.
+
+Function: void plat_ic_disable_interrupt(unsigned int id); [optional]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+    Argument : unsigned int
+    Return   : void
+
+This API should disable the interrupt ID specified by the first parameter,
+``id``. PEs in the system are not expected to receive disabled interrupts.
+
+In case of ARM standard platforms using GIC, the implementation of the API
+writes to GIC *Clear Enable Register* to disable the interrupt, and inserts
+barrier to make memory updates visible afterwards.
+
 ----
 
 *Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.*
index e33353a88346a07402f13f1ff50fec2f6c8858d1..e0058ad1301932d2e48495de99818b0e320e8db2 100644 (file)
@@ -288,3 +288,37 @@ unsigned int gicv2_get_interrupt_active(unsigned int id)
 
        return gicd_get_isactiver(driver_data->gicd_base, id);
 }
+
+/*******************************************************************************
+ * This function enables the interrupt identified by id.
+ ******************************************************************************/
+void gicv2_enable_interrupt(unsigned int id)
+{
+       assert(driver_data);
+       assert(driver_data->gicd_base);
+       assert(id <= MAX_SPI_ID);
+
+       /*
+        * Ensure that any shared variable updates depending on out of band
+        * interrupt trigger are observed before enabling interrupt.
+        */
+       dsbishst();
+       gicd_set_isenabler(driver_data->gicd_base, id);
+}
+
+/*******************************************************************************
+ * This function disables the interrupt identified by id.
+ ******************************************************************************/
+void gicv2_disable_interrupt(unsigned int id)
+{
+       assert(driver_data);
+       assert(driver_data->gicd_base);
+       assert(id <= MAX_SPI_ID);
+
+       /*
+        * Disable interrupt, and ensure that any shared variable updates
+        * depending on out of band interrupt trigger are observed afterwards.
+        */
+       gicd_set_icenabler(driver_data->gicd_base, id);
+       dsbishst();
+}
index 81d50ad45f4b13c7a801ba2335e1141cc89a4f31..ee874f92f77cccc6e12b5b74ff7e3cbbcb67870e 100644 (file)
@@ -171,6 +171,17 @@ void gicr_set_isenabler0(uintptr_t base, unsigned int id)
        gicr_write_isenabler0(base, (1 << bit_num));
 }
 
+/*
+ * Accessor to set the bit corresponding to interrupt ID in GIC Re-distributor
+ * ICENABLER0.
+ */
+void gicr_set_icenabler0(uintptr_t base, unsigned int id)
+{
+       unsigned bit_num = id & ((1 << ICENABLER_SHIFT) - 1);
+
+       gicr_write_icenabler0(base, (1 << bit_num));
+}
+
 /*
  * Accessor to set the bit corresponding to interrupt ID in GIC Re-distributor
  * ISACTIVER0.
index 08cf0957d08ec26f57ecf8de70390cd5e29a8924..b3231993efdd71ac14dbc2dc25b6952f2a936f12 100644 (file)
@@ -805,3 +805,67 @@ unsigned int gicv3_get_interrupt_active(unsigned int id, unsigned int proc_num)
 
        return value;
 }
+
+/*******************************************************************************
+ * This function enables the interrupt identified by id. The proc_num
+ * is used if the interrupt is SGI or PPI, and programs the corresponding
+ * Redistributor interface.
+ ******************************************************************************/
+void gicv3_enable_interrupt(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);
+       assert(id <= MAX_SPI_ID);
+
+       /*
+        * Ensure that any shared variable updates depending on out of band
+        * interrupt trigger are observed before enabling interrupt.
+        */
+       dsbishst();
+       if (id < MIN_SPI_ID) {
+               /* For SGIs and PPIs */
+               gicr_set_isenabler0(
+                               gicv3_driver_data->rdistif_base_addrs[proc_num],
+                               id);
+       } else {
+               gicd_set_isenabler(gicv3_driver_data->gicd_base, id);
+       }
+}
+
+/*******************************************************************************
+ * This function disables the interrupt identified by id. The proc_num
+ * is used if the interrupt is SGI or PPI, and programs the corresponding
+ * Redistributor interface.
+ ******************************************************************************/
+void gicv3_disable_interrupt(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);
+       assert(id <= MAX_SPI_ID);
+
+       /*
+        * Disable 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_icenabler0(
+                               gicv3_driver_data->rdistif_base_addrs[proc_num],
+                               id);
+
+               /* Write to clear enable requires waiting for pending writes */
+               gicr_wait_for_pending_write(
+                               gicv3_driver_data->rdistif_base_addrs[proc_num]);
+       } else {
+               gicd_set_icenabler(gicv3_driver_data->gicd_base, id);
+
+               /* Write to clear enable requires waiting for pending writes */
+               gicd_wait_for_pending_write(gicv3_driver_data->gicd_base);
+       }
+
+       dsbishst();
+}
index bb8ad9ae8303ded37836603a9c700f4520ad9dca..19fce2e73b9cf772c0528035252c6caa81599c62 100644 (file)
@@ -71,6 +71,7 @@ unsigned int gicr_get_isactiver0(uintptr_t base, unsigned int id);
 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_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);
index 2b461263759b48cce183b006c35de94c458c4b82..0af1a25e239446ebb6ede07bc0ebf0299f49e29f 100644 (file)
@@ -148,6 +148,8 @@ unsigned int gicv2_get_interrupt_group(unsigned int id);
 unsigned int gicv2_get_running_priority(void);
 void gicv2_set_pe_target_mask(unsigned int proc_num);
 unsigned int gicv2_get_interrupt_active(unsigned int id);
+void gicv2_enable_interrupt(unsigned int id);
+void gicv2_disable_interrupt(unsigned int id);
 
 #endif /* __ASSEMBLY__ */
 #endif /* __GICV2_H__ */
index ec272ea7c0ba87fd2828de9e43b4925ed1d79dcd..6e6a47b978d02ab92c0d62ff4db28871781cb084 100644 (file)
@@ -351,6 +351,8 @@ void gicv3_its_restore(uintptr_t gits_base, const gicv3_its_ctx_t * const its_ct
 
 unsigned int gicv3_get_running_priority(void);
 unsigned int gicv3_get_interrupt_active(unsigned int id, unsigned int proc_num);
+void gicv3_enable_interrupt(unsigned int id, unsigned int proc_num);
+void gicv3_disable_interrupt(unsigned int id, unsigned int proc_num);
 
 #endif /* __ASSEMBLY__ */
 #endif /* __GICV3_H__ */
index e4fb6a9f939b45c30e58f4b581bd8ed1099b9ec4..671aa61e8ce7138a4b1e07fa64874912f712a0d1 100644 (file)
@@ -77,6 +77,8 @@ int plat_ic_is_spi(unsigned int id);
 int plat_ic_is_ppi(unsigned int id);
 int plat_ic_is_sgi(unsigned int id);
 unsigned int plat_ic_get_interrupt_active(unsigned int id);
+void plat_ic_disable_interrupt(unsigned int id);
+void plat_ic_enable_interrupt(unsigned int id);
 
 /*******************************************************************************
  * Optional common functions (may be overridden)
index 5a92b66b942f127abd781c2c574516322b553b50..2591805de169ca6b6e38fea278748a02a0b8f5f5 100644 (file)
@@ -25,6 +25,8 @@
 #pragma weak plat_ic_is_ppi
 #pragma weak plat_ic_is_sgi
 #pragma weak plat_ic_get_interrupt_active
+#pragma weak plat_ic_enable_interrupt
+#pragma weak plat_ic_disable_interrupt
 
 /*
  * This function returns the highest priority pending interrupt at
@@ -153,3 +155,13 @@ unsigned int plat_ic_get_interrupt_active(unsigned int id)
 {
        return gicv2_get_interrupt_active(id);
 }
+
+void plat_ic_enable_interrupt(unsigned int id)
+{
+       gicv2_enable_interrupt(id);
+}
+
+void plat_ic_disable_interrupt(unsigned int id)
+{
+       gicv2_disable_interrupt(id);
+}
index abb3f1d16f2ef75149d83143831347f73b7ad3a7..2a1f0f5c5fb36b16b7496963f7e196818c58d879 100644 (file)
@@ -31,6 +31,8 @@
 #pragma weak plat_ic_is_ppi
 #pragma weak plat_ic_is_sgi
 #pragma weak plat_ic_get_interrupt_active
+#pragma weak plat_ic_enable_interrupt
+#pragma weak plat_ic_disable_interrupt
 
 CASSERT((INTR_TYPE_S_EL1 == INTR_GROUP1S) &&
        (INTR_TYPE_NS == INTR_GROUP1NS) &&
@@ -186,6 +188,16 @@ unsigned int plat_ic_get_interrupt_active(unsigned int id)
 {
        return gicv3_get_interrupt_active(id, plat_my_core_pos());
 }
+
+void plat_ic_enable_interrupt(unsigned int id)
+{
+       gicv3_enable_interrupt(id, plat_my_core_pos());
+}
+
+void plat_ic_disable_interrupt(unsigned int id)
+{
+       gicv3_disable_interrupt(id, plat_my_core_pos());
+}
 #endif
 #ifdef IMAGE_BL32