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:
parent
cbd3f3706d
commit
979225f4ee
|
@ -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
|
the GIC *Set Active Register* to read and return the active status of the
|
||||||
interrupt.
|
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.*
|
*Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.*
|
||||||
|
|
|
@ -288,3 +288,37 @@ unsigned int gicv2_get_interrupt_active(unsigned int id)
|
||||||
|
|
||||||
return gicd_get_isactiver(driver_data->gicd_base, 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();
|
||||||
|
}
|
||||||
|
|
|
@ -171,6 +171,17 @@ void gicr_set_isenabler0(uintptr_t base, unsigned int id)
|
||||||
gicr_write_isenabler0(base, (1 << bit_num));
|
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
|
* Accessor to set the bit corresponding to interrupt ID in GIC Re-distributor
|
||||||
* ISACTIVER0.
|
* ISACTIVER0.
|
||||||
|
|
|
@ -805,3 +805,67 @@ unsigned int gicv3_get_interrupt_active(unsigned int id, unsigned int proc_num)
|
||||||
|
|
||||||
return value;
|
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();
|
||||||
|
}
|
||||||
|
|
|
@ -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 gicd_set_igrpmodr(uintptr_t base, unsigned int id);
|
||||||
void gicr_set_igrpmodr0(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_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 gicr_set_igroupr0(uintptr_t base, unsigned int id);
|
||||||
void gicd_clr_igrpmodr(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);
|
void gicr_clr_igrpmodr0(uintptr_t base, unsigned int id);
|
||||||
|
|
|
@ -148,6 +148,8 @@ unsigned int gicv2_get_interrupt_group(unsigned int id);
|
||||||
unsigned int gicv2_get_running_priority(void);
|
unsigned int gicv2_get_running_priority(void);
|
||||||
void gicv2_set_pe_target_mask(unsigned int proc_num);
|
void gicv2_set_pe_target_mask(unsigned int proc_num);
|
||||||
unsigned int gicv2_get_interrupt_active(unsigned int id);
|
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 /* __ASSEMBLY__ */
|
||||||
#endif /* __GICV2_H__ */
|
#endif /* __GICV2_H__ */
|
||||||
|
|
|
@ -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_running_priority(void);
|
||||||
unsigned int gicv3_get_interrupt_active(unsigned int id, unsigned int proc_num);
|
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 /* __ASSEMBLY__ */
|
||||||
#endif /* __GICV3_H__ */
|
#endif /* __GICV3_H__ */
|
||||||
|
|
|
@ -77,6 +77,8 @@ int plat_ic_is_spi(unsigned int id);
|
||||||
int plat_ic_is_ppi(unsigned int id);
|
int plat_ic_is_ppi(unsigned int id);
|
||||||
int plat_ic_is_sgi(unsigned int id);
|
int plat_ic_is_sgi(unsigned int id);
|
||||||
unsigned int plat_ic_get_interrupt_active(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)
|
* Optional common functions (may be overridden)
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
#pragma weak plat_ic_is_ppi
|
#pragma weak plat_ic_is_ppi
|
||||||
#pragma weak plat_ic_is_sgi
|
#pragma weak plat_ic_is_sgi
|
||||||
#pragma weak plat_ic_get_interrupt_active
|
#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
|
* 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);
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -31,6 +31,8 @@
|
||||||
#pragma weak plat_ic_is_ppi
|
#pragma weak plat_ic_is_ppi
|
||||||
#pragma weak plat_ic_is_sgi
|
#pragma weak plat_ic_is_sgi
|
||||||
#pragma weak plat_ic_get_interrupt_active
|
#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) &&
|
CASSERT((INTR_TYPE_S_EL1 == INTR_GROUP1S) &&
|
||||||
(INTR_TYPE_NS == INTR_GROUP1NS) &&
|
(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());
|
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
|
#endif
|
||||||
#ifdef IMAGE_BL32
|
#ifdef IMAGE_BL32
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue