diff options
Diffstat (limited to 'drivers/clocksource')
| -rw-r--r-- | drivers/clocksource/Kconfig | 9 | ||||
| -rw-r--r-- | drivers/clocksource/arm_arch_timer.c | 38 |
2 files changed, 31 insertions, 16 deletions
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 50f512629afd..64b8158675b5 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -158,6 +158,15 @@ config ARM_ARCH_TIMER_EVTSTREAM This must be disabled for hardware validation purposes to detect any hardware anomalies of missing events. +config MSM_TIMER_LEAP + bool "ARCH TIMER counter rollover" + default n + depends on ARM_ARCH_TIMER && ARM64 + help + This option enables a check for least significant 32 bits of + counter rollover. On every counter read if least significant + 32 bits are set, reread counter. + config ARM_ARCH_TIMER_VCT_ACCESS bool "Support for ARM architected timer virtual counter access in userspace" default !ARM64 diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index e2d743336305..78da251a5f5d 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -25,6 +25,7 @@ #include <linux/acpi.h> #include <asm/arch_timer.h> +#include <asm/traps.h> #include <asm/virt.h> #include <clocksource/arm_arch_timer.h> @@ -83,20 +84,20 @@ void arch_timer_reg_write(int access, enum arch_timer_reg reg, u32 val, struct arch_timer *timer = to_arch_timer(clk); switch (reg) { case ARCH_TIMER_REG_CTRL: - writel_relaxed(val, timer->base + CNTP_CTL); + writel_relaxed_no_log(val, timer->base + CNTP_CTL); break; case ARCH_TIMER_REG_TVAL: - writel_relaxed(val, timer->base + CNTP_TVAL); + writel_relaxed_no_log(val, timer->base + CNTP_TVAL); break; } } else if (access == ARCH_TIMER_MEM_VIRT_ACCESS) { struct arch_timer *timer = to_arch_timer(clk); switch (reg) { case ARCH_TIMER_REG_CTRL: - writel_relaxed(val, timer->base + CNTV_CTL); + writel_relaxed_no_log(val, timer->base + CNTV_CTL); break; case ARCH_TIMER_REG_TVAL: - writel_relaxed(val, timer->base + CNTV_TVAL); + writel_relaxed_no_log(val, timer->base + CNTV_TVAL); break; } } else { @@ -114,20 +115,20 @@ u32 arch_timer_reg_read(int access, enum arch_timer_reg reg, struct arch_timer *timer = to_arch_timer(clk); switch (reg) { case ARCH_TIMER_REG_CTRL: - val = readl_relaxed(timer->base + CNTP_CTL); + val = readl_relaxed_no_log(timer->base + CNTP_CTL); break; case ARCH_TIMER_REG_TVAL: - val = readl_relaxed(timer->base + CNTP_TVAL); + val = readl_relaxed_no_log(timer->base + CNTP_TVAL); break; } } else if (access == ARCH_TIMER_MEM_VIRT_ACCESS) { struct arch_timer *timer = to_arch_timer(clk); switch (reg) { case ARCH_TIMER_REG_CTRL: - val = readl_relaxed(timer->base + CNTV_CTL); + val = readl_relaxed_no_log(timer->base + CNTV_CTL); break; case ARCH_TIMER_REG_TVAL: - val = readl_relaxed(timer->base + CNTV_TVAL); + val = readl_relaxed_no_log(timer->base + CNTV_TVAL); break; } } else { @@ -337,11 +338,12 @@ static void arch_counter_set_user_access(void) /* Disable user access to the timers and the physical counter */ /* Also disable virtual event stream */ cntkctl &= ~(ARCH_TIMER_USR_PT_ACCESS_EN - | ARCH_TIMER_USR_VT_ACCESS_EN | ARCH_TIMER_VIRT_EVT_EN | ARCH_TIMER_USR_PCT_ACCESS_EN); /* Enable user access to the virtual counter */ + cntkctl |= ARCH_TIMER_USR_VT_ACCESS_EN; + if (IS_ENABLED(CONFIG_ARM_ARCH_TIMER_VCT_ACCESS)) cntkctl |= ARCH_TIMER_USR_VCT_ACCESS_EN; else @@ -383,7 +385,8 @@ arch_timer_detect_rate(void __iomem *cntbase, struct device_node *np) if (!acpi_disabled || of_property_read_u32(np, "clock-frequency", &arch_timer_rate)) { if (cntbase) - arch_timer_rate = readl_relaxed(cntbase + CNTFRQ); + arch_timer_rate = readl_relaxed_no_log(cntbase + + CNTFRQ); else arch_timer_rate = arch_timer_get_cntfrq(); } @@ -420,9 +423,9 @@ static u64 arch_counter_get_cntvct_mem(void) u32 vct_lo, vct_hi, tmp_hi; do { - vct_hi = readl_relaxed(arch_counter_base + CNTVCT_HI); - vct_lo = readl_relaxed(arch_counter_base + CNTVCT_LO); - tmp_hi = readl_relaxed(arch_counter_base + CNTVCT_HI); + vct_hi = readl_relaxed_no_log(arch_counter_base + CNTVCT_HI); + vct_lo = readl_relaxed_no_log(arch_counter_base + CNTVCT_LO); + tmp_hi = readl_relaxed_no_log(arch_counter_base + CNTVCT_HI); } while (vct_hi != tmp_hi); return ((u64) vct_hi << 32) | vct_lo; @@ -698,6 +701,7 @@ static void __init arch_timer_common_init(void) arch_timer_banner(arch_timers_present); arch_counter_register(arch_timers_present); arch_timer_arch_init(); + clocksource_select_force(); } static void __init arch_timer_init(void) @@ -757,7 +761,7 @@ CLOCKSOURCE_OF_DECLARE(armv8_arch_timer, "arm,armv8-timer", arch_timer_of_init); static void __init arch_timer_mem_init(struct device_node *np) { struct device_node *frame, *best_frame = NULL; - void __iomem *cntctlbase, *base; + void __iomem *cntctlbase, *base = NULL; unsigned int irq; u32 cnttidr; @@ -768,7 +772,7 @@ static void __init arch_timer_mem_init(struct device_node *np) return; } - cnttidr = readl_relaxed(cntctlbase + CNTTIDR); + cnttidr = readl_relaxed_no_log(cntctlbase + CNTTIDR); iounmap(cntctlbase); /* @@ -795,7 +799,8 @@ static void __init arch_timer_mem_init(struct device_node *np) best_frame = of_node_get(frame); } - base = arch_counter_base = of_iomap(best_frame, 0); + if (best_frame) + base = arch_counter_base = of_iomap(best_frame, 0); if (!base) { pr_err("arch_timer: Can't map frame's registers\n"); of_node_put(best_frame); @@ -816,6 +821,7 @@ static void __init arch_timer_mem_init(struct device_node *np) arch_timer_detect_rate(base, np); arch_timer_mem_register(base, irq); arch_timer_common_init(); + get_pct_hook_init(); } CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem", arch_timer_mem_init); |
