drivers: timer: arm_arch_timer: Workaround for Cortex-A9 erratum 740657
Modification of the ARM architected timer driver and its configuration data in order to address an erratum which exists at least in the Cor- tex-A9 CPU, and which can also be observed in the QEMU implementation of the Cortex-A9. Comp.: ARM Cortex-A9 processors Software Developer Errata Notice ARM document ID032315 Erratum 740657 This erratum causes a spurious interrupt pending indication with the interrupt controller if no new compare value is written within the timer ISR before the interrupt is cleared. This is usually the case in tickless mode. If the spurious interrupt is not prevented, the timer ISR will be called twice, but on second execution, the pending flag is not set within the timer's register space. Not handling this issue will lead to erratic tick announcements to the kernel. Signed-off-by: Immo Birnbaum <Immo.Birnbaum@weidmueller.com>
This commit is contained in:
parent
a69cd66b6e
commit
315ad1d6e6
3 changed files with 76 additions and 0 deletions
|
@ -35,6 +35,8 @@ extern "C" {
|
|||
#define TIMER_COMP_ENABLE BIT(1)
|
||||
#define TIMER_ENABLE BIT(0)
|
||||
|
||||
#define TIMER_ISR_EVENT_FLAG BIT(0)
|
||||
|
||||
DEVICE_MMIO_TOPLEVEL_STATIC(timer_regs, ARM_TIMER_NODE);
|
||||
|
||||
#define TIMER_REG_GET(offs) (DEVICE_MMIO_TOPLEVEL_GET(timer_regs) + offs)
|
||||
|
@ -63,6 +65,30 @@ static ALWAYS_INLINE void arm_arch_timer_set_compare(uint64_t val)
|
|||
sys_write32(ctrl, TIMER_REG_GET(TIMER_CTRL));
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ARM_ARCH_TIMER_ERRATUM_740657)
|
||||
|
||||
/*
|
||||
* R/W access to the event flag register is required for the timer errata
|
||||
* 740657 workaround -> comp. ISR implementation in arm_arch_timer.c.
|
||||
* This functionality is not present in the aarch64 implementation of the
|
||||
* ARM global timer access functions.
|
||||
*
|
||||
* comp. ARM Cortex-A9 processors Software Developers Errata Notice,
|
||||
* ARM document ID032315.
|
||||
*/
|
||||
|
||||
static ALWAYS_INLINE uint8_t arm_arch_timer_get_int_status(void)
|
||||
{
|
||||
return (uint8_t)(sys_read32(TIMER_REG_GET(TIMER_ISR)) & TIMER_ISR_EVENT_FLAG);
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE void arm_arch_timer_clear_int_status(void)
|
||||
{
|
||||
sys_write32(TIMER_ISR_EVENT_FLAG, TIMER_REG_GET(TIMER_ISR));
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ARM_ARCH_TIMER_ERRATUM_740657 */
|
||||
|
||||
static ALWAYS_INLINE void arm_arch_timer_enable(bool enable)
|
||||
{
|
||||
uint32_t ctrl;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue