summaryrefslogtreecommitdiff
path: root/drivers/clocksource/arm_arch_timer.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2019-02-23 19:21:53 +0300
committerThomas Gleixner <tglx@linutronix.de>2019-02-23 19:21:53 +0300
commit8dd2eee2f444a7a570599bffc9da330157cca5b5 (patch)
tree400b9a2fb19e7ac5bac27750bdac77615eded541 /drivers/clocksource/arm_arch_timer.c
parent75b710af7139768fd4ba2d4e05335d2344796279 (diff)
parentf40f4fc9506d6b2b786920059b320aac3a831574 (diff)
downloadlinux-8dd2eee2f444a7a570599bffc9da330157cca5b5.tar.xz
Merge branch 'clockevents/5.1' of https://git.linaro.org/people/daniel.lezcano/linux into timers/core
Pull clockevents updates from Daniel Lezcano: - Update the binding documentation for the gpt timer (Anson Huang) - Improve checking and error handling at init time on risc timer (Atish Patra) - Update the binding documentation for r8a774c0 cmt and tmu (Biju Das) - Fail gracefully when clock rate is unavailable on sun5i (Chen-Yu Tsai) - Rename the tango-xtal, pxa and cs5535 to timer-*.c for consistency (Daniel Lezcano) - Add the support for the tegra210 timer and add the platform's Kconfig selection (Joseph Lo) - Do a cleanup in the header inclusions and remove the unused ones for the exynos_mct timer driver (Krzysztof Kozlowski) - Remove some non-of dead code and fix the error path when initializing the resources in the exynos_mct timer driver (Marek Szyprowski) - Update the DT bindings for the MT7629 (Ryder Lee) - Provide a workaround for the arm arch timer for Allwinner A64 timers (Samuel Holland) - Clear the timer interrupt at shutdown time on the exynos_mct timer driver (Stuart Menefy)
Diffstat (limited to 'drivers/clocksource/arm_arch_timer.c')
-rw-r--r--drivers/clocksource/arm_arch_timer.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 9a7d4dc00b6e..a8b20b65bd4b 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -326,6 +326,48 @@ static u64 notrace arm64_1188873_read_cntvct_el0(void)
}
#endif
+#ifdef CONFIG_SUN50I_ERRATUM_UNKNOWN1
+/*
+ * The low bits of the counter registers are indeterminate while bit 10 or
+ * greater is rolling over. Since the counter value can jump both backward
+ * (7ff -> 000 -> 800) and forward (7ff -> fff -> 800), ignore register values
+ * with all ones or all zeros in the low bits. Bound the loop by the maximum
+ * number of CPU cycles in 3 consecutive 24 MHz counter periods.
+ */
+#define __sun50i_a64_read_reg(reg) ({ \
+ u64 _val; \
+ int _retries = 150; \
+ \
+ do { \
+ _val = read_sysreg(reg); \
+ _retries--; \
+ } while (((_val + 1) & GENMASK(9, 0)) <= 1 && _retries); \
+ \
+ WARN_ON_ONCE(!_retries); \
+ _val; \
+})
+
+static u64 notrace sun50i_a64_read_cntpct_el0(void)
+{
+ return __sun50i_a64_read_reg(cntpct_el0);
+}
+
+static u64 notrace sun50i_a64_read_cntvct_el0(void)
+{
+ return __sun50i_a64_read_reg(cntvct_el0);
+}
+
+static u32 notrace sun50i_a64_read_cntp_tval_el0(void)
+{
+ return read_sysreg(cntp_cval_el0) - sun50i_a64_read_cntpct_el0();
+}
+
+static u32 notrace sun50i_a64_read_cntv_tval_el0(void)
+{
+ return read_sysreg(cntv_cval_el0) - sun50i_a64_read_cntvct_el0();
+}
+#endif
+
#ifdef CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND
DEFINE_PER_CPU(const struct arch_timer_erratum_workaround *, timer_unstable_counter_workaround);
EXPORT_SYMBOL_GPL(timer_unstable_counter_workaround);
@@ -423,6 +465,19 @@ static const struct arch_timer_erratum_workaround ool_workarounds[] = {
.read_cntvct_el0 = arm64_1188873_read_cntvct_el0,
},
#endif
+#ifdef CONFIG_SUN50I_ERRATUM_UNKNOWN1
+ {
+ .match_type = ate_match_dt,
+ .id = "allwinner,erratum-unknown1",
+ .desc = "Allwinner erratum UNKNOWN1",
+ .read_cntp_tval_el0 = sun50i_a64_read_cntp_tval_el0,
+ .read_cntv_tval_el0 = sun50i_a64_read_cntv_tval_el0,
+ .read_cntpct_el0 = sun50i_a64_read_cntpct_el0,
+ .read_cntvct_el0 = sun50i_a64_read_cntvct_el0,
+ .set_next_event_phys = erratum_set_next_event_tval_phys,
+ .set_next_event_virt = erratum_set_next_event_tval_virt,
+ },
+#endif
};
typedef bool (*ate_match_fn_t)(const struct arch_timer_erratum_workaround *,