summaryrefslogtreecommitdiff
path: root/drivers/clocksource
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clocksource')
-rw-r--r--drivers/clocksource/Kconfig9
-rw-r--r--drivers/clocksource/arm_arch_timer.c38
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);