GIC: Add APIs to enable and disable interrupt

API documentation updated.

Change-Id: Ice7511f8df5356851001d2f7dc2a46cfe318f9ba
Co-authored-by: Yousuf A <yousuf.sait@arm.com>
Signed-off-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
This commit is contained in:
Jeenu Viswambharan 2017-09-22 08:32:09 +01:00
parent cbd3f3706d
commit 979225f4ee
10 changed files with 170 additions and 0 deletions

View 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.*

View 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();
}

View 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.

View 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();
}

View 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);

View 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__ */

View 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__ */

View 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)

View 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);
}

View 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