mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-20 19:44:23 +00:00
GIC: Add API to set/clear interrupt pending
API documentation updated. Change-Id: I14e33cfc7dfa93257c82d76fae186b17a1b6d266 Co-authored-by: Yousuf A <yousuf.sait@arm.com> Signed-off-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
This commit is contained in:
parent
fc529fee72
commit
a2816a1644
10 changed files with 182 additions and 0 deletions
|
@ -243,6 +243,37 @@ In case of ARM standard platforms using GIC, the implementation of the API
|
||||||
writes to the GIC *Target Register* (GICv2) or *Route Register* (GICv3) to set
|
writes to the GIC *Target Register* (GICv2) or *Route Register* (GICv3) to set
|
||||||
the routing.
|
the routing.
|
||||||
|
|
||||||
|
Function: void plat_ic_set_interrupt_pending(unsigned int id); [optional]
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
Argument : unsigned int
|
||||||
|
Return : void
|
||||||
|
|
||||||
|
This API should set the interrupt specified by first parameter ``id`` to
|
||||||
|
*Pending*.
|
||||||
|
|
||||||
|
In case of ARM standard platforms using GIC, the implementation of the API
|
||||||
|
inserts barrier to make memory updates visible before setting interrupt pending,
|
||||||
|
and writes to the GIC *Set Pending Register* to set the interrupt pending
|
||||||
|
status.
|
||||||
|
|
||||||
|
Function: void plat_ic_clear_interrupt_pending(unsigned int id); [optional]
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
Argument : unsigned int
|
||||||
|
Return : void
|
||||||
|
|
||||||
|
This API should clear the *Pending* status of the interrupt specified by first
|
||||||
|
parameter ``id``.
|
||||||
|
|
||||||
|
In case of ARM standard platforms using GIC, the implementation of the API
|
||||||
|
writes to the GIC *Clear Pending Register* to clear the interrupt pending
|
||||||
|
status, 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.*
|
||||||
|
|
|
@ -438,3 +438,41 @@ void gicv2_set_spi_routing(unsigned int id, int proc_num)
|
||||||
|
|
||||||
gicd_set_itargetsr(driver_data->gicd_base, id, target);
|
gicd_set_itargetsr(driver_data->gicd_base, id, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* This function clears the pending status of an interrupt identified by id.
|
||||||
|
******************************************************************************/
|
||||||
|
void gicv2_clear_interrupt_pending(unsigned int id)
|
||||||
|
{
|
||||||
|
assert(driver_data);
|
||||||
|
assert(driver_data->gicd_base);
|
||||||
|
|
||||||
|
/* SGIs can't be cleared pending */
|
||||||
|
assert(id >= MIN_PPI_ID);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clear pending interrupt, and ensure that any shared variable updates
|
||||||
|
* depending on out of band interrupt trigger are observed afterwards.
|
||||||
|
*/
|
||||||
|
gicd_set_icpendr(driver_data->gicd_base, id);
|
||||||
|
dsbishst();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* This function sets the pending status of an interrupt identified by id.
|
||||||
|
******************************************************************************/
|
||||||
|
void gicv2_set_interrupt_pending(unsigned int id)
|
||||||
|
{
|
||||||
|
assert(driver_data);
|
||||||
|
assert(driver_data->gicd_base);
|
||||||
|
|
||||||
|
/* SGIs can't be cleared pending */
|
||||||
|
assert(id >= MIN_PPI_ID);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ensure that any shared variable updates depending on out of band
|
||||||
|
* interrupt trigger are observed before setting interrupt pending.
|
||||||
|
*/
|
||||||
|
dsbishst();
|
||||||
|
gicd_set_ispendr(driver_data->gicd_base, id);
|
||||||
|
}
|
||||||
|
|
|
@ -194,6 +194,28 @@ unsigned int gicr_get_isactiver0(uintptr_t base, unsigned int id)
|
||||||
return (reg_val >> bit_num) & 0x1;
|
return (reg_val >> bit_num) & 0x1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Accessor to clear the bit corresponding to interrupt ID in GIC Re-distributor
|
||||||
|
* ICPENDRR0.
|
||||||
|
*/
|
||||||
|
void gicr_set_icpendr0(uintptr_t base, unsigned int id)
|
||||||
|
{
|
||||||
|
unsigned bit_num = id & ((1 << ICPENDR_SHIFT) - 1);
|
||||||
|
|
||||||
|
gicr_write_icpendr0(base, (1 << bit_num));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Accessor to set the bit corresponding to interrupt ID in GIC Re-distributor
|
||||||
|
* ISPENDR0.
|
||||||
|
*/
|
||||||
|
void gicr_set_ispendr0(uintptr_t base, unsigned int id)
|
||||||
|
{
|
||||||
|
unsigned bit_num = id & ((1 << ISPENDR_SHIFT) - 1);
|
||||||
|
|
||||||
|
gicr_write_ispendr0(base, (1 << bit_num));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Accessor to set the byte corresponding to interrupt ID
|
* Accessor to set the byte corresponding to interrupt ID
|
||||||
* in GIC Re-distributor IPRIORITYR.
|
* in GIC Re-distributor IPRIORITYR.
|
||||||
|
|
|
@ -1037,3 +1037,55 @@ void gicv3_set_spi_routing(unsigned int id, unsigned int irm, u_register_t mpidr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* This function clears the pending status of an interrupt identified by id.
|
||||||
|
* The proc_num is used if the interrupt is SGI or PPI, and programs the
|
||||||
|
* corresponding Redistributor interface.
|
||||||
|
******************************************************************************/
|
||||||
|
void gicv3_clear_interrupt_pending(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);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clear pending 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_icpendr0(gicv3_driver_data->rdistif_base_addrs[proc_num],
|
||||||
|
id);
|
||||||
|
} else {
|
||||||
|
gicd_set_icpendr(gicv3_driver_data->gicd_base, id);
|
||||||
|
}
|
||||||
|
dsbishst();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* This function sets the pending status of an interrupt identified by id.
|
||||||
|
* The proc_num is used if the interrupt is SGI or PPI and programs the
|
||||||
|
* corresponding Redistributor interface.
|
||||||
|
******************************************************************************/
|
||||||
|
void gicv3_set_interrupt_pending(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);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ensure that any shared variable updates depending on out of band
|
||||||
|
* interrupt trigger are observed before setting interrupt pending.
|
||||||
|
*/
|
||||||
|
dsbishst();
|
||||||
|
if (id < MIN_SPI_ID) {
|
||||||
|
/* For SGIs and PPIs */
|
||||||
|
gicr_set_ispendr0(gicv3_driver_data->rdistif_base_addrs[proc_num],
|
||||||
|
id);
|
||||||
|
} else {
|
||||||
|
gicd_set_ispendr(gicv3_driver_data->gicd_base, id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -72,6 +72,8 @@ 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_icenabler0(uintptr_t base, unsigned int id);
|
||||||
|
void gicr_set_ispendr0(uintptr_t base, unsigned int id);
|
||||||
|
void gicr_set_icpendr0(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);
|
||||||
|
@ -221,6 +223,11 @@ static inline unsigned int gicr_read_isenabler0(uintptr_t base)
|
||||||
return mmio_read_32(base + GICR_ISENABLER0);
|
return mmio_read_32(base + GICR_ISENABLER0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void gicr_write_icpendr0(uintptr_t base, unsigned int val)
|
||||||
|
{
|
||||||
|
mmio_write_32(base + GICR_ICPENDR0, val);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void gicr_write_isenabler0(uintptr_t base, unsigned int val)
|
static inline void gicr_write_isenabler0(uintptr_t base, unsigned int val)
|
||||||
{
|
{
|
||||||
mmio_write_32(base + GICR_ISENABLER0, val);
|
mmio_write_32(base + GICR_ISENABLER0, val);
|
||||||
|
|
|
@ -172,6 +172,8 @@ void gicv2_set_interrupt_priority(unsigned int id, unsigned int priority);
|
||||||
void gicv2_set_interrupt_type(unsigned int id, unsigned int type);
|
void gicv2_set_interrupt_type(unsigned int id, unsigned int type);
|
||||||
void gicv2_raise_sgi(int sgi_num, int proc_num);
|
void gicv2_raise_sgi(int sgi_num, int proc_num);
|
||||||
void gicv2_set_spi_routing(unsigned int id, int proc_num);
|
void gicv2_set_spi_routing(unsigned int id, int proc_num);
|
||||||
|
void gicv2_set_interrupt_pending(unsigned int id);
|
||||||
|
void gicv2_clear_interrupt_pending(unsigned int id);
|
||||||
|
|
||||||
#endif /* __ASSEMBLY__ */
|
#endif /* __ASSEMBLY__ */
|
||||||
#endif /* __GICV2_H__ */
|
#endif /* __GICV2_H__ */
|
||||||
|
|
|
@ -387,6 +387,8 @@ void gicv3_set_interrupt_type(unsigned int id, unsigned int proc_num,
|
||||||
void gicv3_raise_secure_g0_sgi(int sgi_num, u_register_t target);
|
void gicv3_raise_secure_g0_sgi(int sgi_num, u_register_t target);
|
||||||
void gicv3_set_spi_routing(unsigned int id, unsigned int irm,
|
void gicv3_set_spi_routing(unsigned int id, unsigned int irm,
|
||||||
u_register_t mpidr);
|
u_register_t mpidr);
|
||||||
|
void gicv3_set_interrupt_pending(unsigned int id, unsigned int proc_num);
|
||||||
|
void gicv3_clear_interrupt_pending(unsigned int id, unsigned int proc_num);
|
||||||
|
|
||||||
#endif /* __ASSEMBLY__ */
|
#endif /* __ASSEMBLY__ */
|
||||||
#endif /* __GICV3_H__ */
|
#endif /* __GICV3_H__ */
|
||||||
|
|
|
@ -85,6 +85,8 @@ void plat_ic_set_interrupt_priority(unsigned int id, unsigned int priority);
|
||||||
void plat_ic_raise_el3_sgi(int sgi_num, u_register_t target);
|
void plat_ic_raise_el3_sgi(int sgi_num, u_register_t target);
|
||||||
void plat_ic_set_spi_routing(unsigned int id, unsigned int routing_mode,
|
void plat_ic_set_spi_routing(unsigned int id, unsigned int routing_mode,
|
||||||
u_register_t mpidr);
|
u_register_t mpidr);
|
||||||
|
void plat_ic_set_interrupt_pending(unsigned int id);
|
||||||
|
void plat_ic_clear_interrupt_pending(unsigned int id);
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Optional common functions (may be overridden)
|
* Optional common functions (may be overridden)
|
||||||
|
|
|
@ -262,3 +262,13 @@ void plat_ic_set_spi_routing(unsigned int id, unsigned int routing_mode,
|
||||||
|
|
||||||
gicv2_set_spi_routing(id, proc_num);
|
gicv2_set_spi_routing(id, proc_num);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void plat_ic_set_interrupt_pending(unsigned int id)
|
||||||
|
{
|
||||||
|
gicv2_set_interrupt_pending(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void plat_ic_clear_interrupt_pending(unsigned int id)
|
||||||
|
{
|
||||||
|
gicv2_clear_interrupt_pending(id);
|
||||||
|
}
|
||||||
|
|
|
@ -37,6 +37,8 @@
|
||||||
#pragma weak plat_ic_set_interrupt_type
|
#pragma weak plat_ic_set_interrupt_type
|
||||||
#pragma weak plat_ic_raise_el3_sgi
|
#pragma weak plat_ic_raise_el3_sgi
|
||||||
#pragma weak plat_ic_set_spi_routing
|
#pragma weak plat_ic_set_spi_routing
|
||||||
|
#pragma weak plat_ic_set_interrupt_pending
|
||||||
|
#pragma weak plat_ic_clear_interrupt_pending
|
||||||
|
|
||||||
CASSERT((INTR_TYPE_S_EL1 == INTR_GROUP1S) &&
|
CASSERT((INTR_TYPE_S_EL1 == INTR_GROUP1S) &&
|
||||||
(INTR_TYPE_NS == INTR_GROUP1NS) &&
|
(INTR_TYPE_NS == INTR_GROUP1NS) &&
|
||||||
|
@ -250,6 +252,20 @@ void plat_ic_set_spi_routing(unsigned int id, unsigned int routing_mode,
|
||||||
|
|
||||||
gicv3_set_spi_routing(id, irm, mpidr);
|
gicv3_set_spi_routing(id, irm, mpidr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void plat_ic_set_interrupt_pending(unsigned int id)
|
||||||
|
{
|
||||||
|
/* Disallow setting SGIs pending */
|
||||||
|
assert(id >= MIN_PPI_ID);
|
||||||
|
gicv3_set_interrupt_pending(id, plat_my_core_pos());
|
||||||
|
}
|
||||||
|
|
||||||
|
void plat_ic_clear_interrupt_pending(unsigned int id)
|
||||||
|
{
|
||||||
|
/* Disallow setting SGIs pending */
|
||||||
|
assert(id >= MIN_PPI_ID);
|
||||||
|
gicv3_clear_interrupt_pending(id, plat_my_core_pos());
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef IMAGE_BL32
|
#ifdef IMAGE_BL32
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue