diff options
author | Marc Zyngier <marc.zyngier@arm.com> | 2017-01-27 13:52:31 +0100 |
---|---|---|
committer | Marc Zyngier <marc.zyngier@arm.com> | 2017-04-07 12:22:10 +0200 |
commit | fa8d815fac96e7c9247783d5a1f8fa4685b3c543 (patch) | |
tree | 2bf8488d8d20bdcbfba0f69cd30999e96d365c35 /drivers/clocksource/arm_arch_timer.c | |
parent | arm64: arch_timer: Enable CNTVCT_EL0 trap if workaround is enabled (diff) | |
download | linux-fa8d815fac96e7c9247783d5a1f8fa4685b3c543.tar.xz linux-fa8d815fac96e7c9247783d5a1f8fa4685b3c543.zip |
arm64: arch_timer: Workaround for Cortex-A73 erratum 858921
Cortex-A73 (all versions) counter read can return a wrong value
when the counter crosses a 32bit boundary.
The workaround involves performing the read twice, and to return
one or the other depending on whether a transition has taken place.
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Diffstat (limited to 'drivers/clocksource/arm_arch_timer.c')
-rw-r--r-- | drivers/clocksource/arm_arch_timer.c | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index f8adea258cf0..8459d19a84f5 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -266,6 +266,17 @@ static u64 notrace hisi_161010101_read_cntvct_el0(void) } #endif +#ifdef CONFIG_ARM64_ERRATUM_858921 +static u64 notrace arm64_858921_read_cntvct_el0(void) +{ + u64 old, new; + + old = read_sysreg(cntvct_el0); + new = read_sysreg(cntvct_el0); + return (((old ^ new) >> 32) & 1) ? old : new; +} +#endif + #ifdef CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND DEFINE_PER_CPU(const struct arch_timer_erratum_workaround *, timer_unstable_counter_workaround); @@ -331,6 +342,14 @@ static const struct arch_timer_erratum_workaround ool_workarounds[] = { .set_next_event_virt = erratum_set_next_event_tval_virt, }, #endif +#ifdef CONFIG_ARM64_ERRATUM_858921 + { + .match_type = ate_match_local_cap_id, + .id = (void *)ARM64_WORKAROUND_858921, + .desc = "ARM erratum 858921", + .read_cntvct_el0 = arm64_858921_read_cntvct_el0, + }, +#endif }; typedef bool (*ate_match_fn_t)(const struct arch_timer_erratum_workaround *, |