drivers: interrupt_controller: GIC barrier before EOI
It is desired to have the peripheral writes completed to clear the interrupt condition and de-assert the interrupt request to GIC before EOI write. Failing which spurious interrupt will occur. A barrier is needed to ensure peripheral register write transfers are complete before EOI is done. GICv2 memory mapped DEVICE nGnR(n)E writes are ordered from core point of view. However these writes may pass over different interconnects, bridges, buffers leaving some rare chances for the actual write to complete out of order. GICv3 ICC EOI system register writes have no ordering against nGnR(n)E memory writes as they are over different interfaces. Hence a dsb can ensure from core no writes are issued before the previous writes are *complete*. Signed-off-by: Sandeep Tripathy <sandeep.tripathy@broadcom.com>
This commit is contained in:
parent
9b6ab5b6ab
commit
ccb4b1ec47
2 changed files with 23 additions and 0 deletions
|
@ -79,6 +79,16 @@ unsigned int arm_gic_get_active(void)
|
|||
|
||||
void arm_gic_eoi(unsigned int irq)
|
||||
{
|
||||
/*
|
||||
* Ensure the write to peripheral registers are *complete* before the write
|
||||
* to GIC_EOIR.
|
||||
*
|
||||
* Note: The completion gurantee depends on various factors of system design
|
||||
* and the barrier is the best core can do by which execution of further
|
||||
* instructions waits till the barrier is alive.
|
||||
*/
|
||||
__DSB();
|
||||
|
||||
/* set to inactive */
|
||||
sys_write32(irq, GICC_EOIR);
|
||||
}
|
||||
|
|
|
@ -106,6 +106,19 @@ unsigned int arm_gic_get_active(void)
|
|||
|
||||
void arm_gic_eoi(unsigned int intid)
|
||||
{
|
||||
/*
|
||||
* Interrupt request deassertion from peripheral to GIC happens
|
||||
* by clearing interrupt condition by a write to the peripheral
|
||||
* register. It is desired that the write transfer is complete
|
||||
* before the core tries to change GIC state from 'AP/Active' to
|
||||
* a new state on seeing 'EOI write'.
|
||||
* Since ICC interface writes are not ordered against Device
|
||||
* memory writes, a barrier is required to ensure the ordering.
|
||||
* The dsb will also ensure *completion* of previous writes with
|
||||
* DEVICE nGnRnE attribute.
|
||||
*/
|
||||
__DSB();
|
||||
|
||||
/* (AP -> Pending) Or (Active -> Inactive) or (AP to AP) nested case */
|
||||
write_sysreg(intid, ICC_EOIR1_EL1);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue