generic_timer: force timer to de-assert irq
Generic Timer IRQs are level-sensitive, when the CNT_TVAL is updated the trigger condition is de-asserted and the change is propagated to the GIC in a finite time to clear the pending state. However, we have to make sure the timer deasserts before EOIR/DIR, otherwise the interrupt happens again. Therefore, we need an isb() to cause the timer to de-assert before EOIR/DIR. There is also a chance of spurious IRQ. A spurious IRQ can be generated, in the case we have a level-sensitive IRQ, and its pending state is cleared at device-level but not yet propagated to the GIC. In between the IRQ deactivation and IRQ ack of the new interrupt if the requested change from the timer gets propagated then it causes a spurious IRQ. Signed-off-by: JorgeMVP <jorgepereira89@gmail.com>
This commit is contained in:
parent
8c9cf6c7db
commit
62c8148268
1 changed files with 10 additions and 0 deletions
|
|
@ -32,6 +32,11 @@ static inline void ackDeadlineIRQ(void)
|
|||
{
|
||||
ticks_t deadline = UINT64_MAX;
|
||||
setDeadline(deadline);
|
||||
/* Ensure that the timer deasserts the IRQ before GIC EOIR/DIR.
|
||||
* This is sufficient to remove the pending state from the GICR
|
||||
* and avoid the interrupt happening twice because of the level
|
||||
* sensitive configuration. */
|
||||
isb();
|
||||
}
|
||||
#else /* CONFIG_KERNEL_MCS */
|
||||
#include <arch/machine/timer.h>
|
||||
|
|
@ -39,6 +44,11 @@ static inline void resetTimer(void)
|
|||
{
|
||||
SYSTEM_WRITE_WORD(CNT_TVAL, TIMER_RELOAD);
|
||||
SYSTEM_WRITE_WORD(CNT_CTL, BIT(0));
|
||||
/* Ensure that the timer deasserts the IRQ before GIC EOIR/DIR.
|
||||
* This is sufficient to remove the pending state from the GICR
|
||||
* and avoid the interrupt happening twice because of the level
|
||||
* sensitive configuration. */
|
||||
isb();
|
||||
}
|
||||
#endif /* !CONFIG_KERNEL_MCS */
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue