diff options
author | Tom Rini <trini@konsulko.com> | 2018-07-03 23:09:34 -0400 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2018-07-03 23:09:34 -0400 |
commit | 4ac5df4b41ba46d7e635bdd8d500721c642b0a0d (patch) | |
tree | cc1fa4ffbda05534cee8b0add68338e6dc141455 /arch/arm/cpu | |
parent | 89c5c976195342344f4caffce016c2de7abb8802 (diff) | |
parent | be0d217952222b2bd3ed071de9bb0c66d8cc80d9 (diff) |
Merge branch 'master' of git://git.denx.de/u-boot-sunxi
Diffstat (limited to 'arch/arm/cpu')
-rw-r--r-- | arch/arm/cpu/armv8/generic_timer.c | 55 |
1 files changed, 49 insertions, 6 deletions
diff --git a/arch/arm/cpu/armv8/generic_timer.c b/arch/arm/cpu/armv8/generic_timer.c index bf07a706a0..c1706dcec1 100644 --- a/arch/arm/cpu/armv8/generic_timer.c +++ b/arch/arm/cpu/armv8/generic_timer.c @@ -20,27 +20,70 @@ unsigned long get_tbclk(void) return cntfrq; } +#ifdef CONFIG_SYS_FSL_ERRATUM_A008585 /* - * Generic timer implementation of timer_read_counter() + * FSL erratum A-008585 says that the ARM generic timer counter "has the + * potential to contain an erroneous value for a small number of core + * clock cycles every time the timer value changes". + * This sometimes leads to a consecutive counter read returning a lower + * value than the previous one, thus reporting the time to go backwards. + * The workaround is to read the counter twice and only return when the value + * was the same in both reads. + * Assumes that the CPU runs in much higher frequency than the timer. */ unsigned long timer_read_counter(void) { unsigned long cntpct; -#ifdef CONFIG_SYS_FSL_ERRATUM_A008585 - /* This erratum number needs to be confirmed to match ARM document */ unsigned long temp; -#endif + isb(); asm volatile("mrs %0, cntpct_el0" : "=r" (cntpct)); -#ifdef CONFIG_SYS_FSL_ERRATUM_A008585 asm volatile("mrs %0, cntpct_el0" : "=r" (temp)); while (temp != cntpct) { asm volatile("mrs %0, cntpct_el0" : "=r" (cntpct)); asm volatile("mrs %0, cntpct_el0" : "=r" (temp)); } -#endif + + return cntpct; +} +#elif CONFIG_SUNXI_A64_TIMER_ERRATUM +/* + * This erratum sometimes flips the lower 11 bits of the counter value + * to all 0's or all 1's, leading to jumps forwards or backwards. + * Backwards jumps might be interpreted all roll-overs and be treated as + * huge jumps forward. + * The workaround is to check whether the lower 11 bits of the counter are + * all 0 or all 1, then discard this value and read again. + * This occasionally discards valid values, but will catch all erroneous + * reads and fixes the problem reliably. Also this mostly requires only a + * single read, so does not have any significant overhead. + * The algorithm was conceived by Samuel Holland. + */ +unsigned long timer_read_counter(void) +{ + unsigned long cntpct; + + isb(); + do { + asm volatile("mrs %0, cntpct_el0" : "=r" (cntpct)); + } while (((cntpct + 1) & GENMASK(10, 0)) <= 1); + return cntpct; } +#else +/* + * timer_read_counter() using the Arm Generic Timer (aka arch timer). + */ +unsigned long timer_read_counter(void) +{ + unsigned long cntpct; + + isb(); + asm volatile("mrs %0, cntpct_el0" : "=r" (cntpct)); + + return cntpct; +} +#endif uint64_t get_ticks(void) { |