Skip to content

Commit 8b82c4f

Browse files
Marc Zyngierdlezcano
authored andcommitted
clocksource/drivers/arm_arch_timer: Move MMIO timer programming over to CVAL
Similarily to the sysreg-based timer, move the MMIO over to using the CVAL registers instead of TVAL. Note that there is no warranty that the 64bit MMIO access will be atomic, but the timer is always disabled at the point where we program CVAL. Signed-off-by: Marc Zyngier <maz@kernel.org> Link: https://lore.kernel.org/r/20211017124225.3018098-8-maz@kernel.org Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
1 parent 72f47a3 commit 8b82c4f

File tree

2 files changed

+39
-12
lines changed

2 files changed

+39
-12
lines changed

arch/arm/include/asm/arch_timer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <asm/hwcap.h>
88
#include <linux/clocksource.h>
99
#include <linux/init.h>
10+
#include <linux/io-64-nonatomic-lo-hi.h>
1011
#include <linux/types.h>
1112

1213
#include <clocksource/arm_arch_timer.h>

drivers/clocksource/arm_arch_timer.c

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,13 @@
4444
#define CNTACR_RWVT BIT(4)
4545
#define CNTACR_RWPT BIT(5)
4646

47-
#define CNTVCT_LO 0x08
48-
#define CNTVCT_HI 0x0c
47+
#define CNTVCT_LO 0x00
48+
#define CNTPCT_LO 0x08
4949
#define CNTFRQ 0x10
50+
#define CNTP_CVAL_LO 0x20
5051
#define CNTP_TVAL 0x28
5152
#define CNTP_CTL 0x2c
53+
#define CNTV_CVAL_LO 0x30
5254
#define CNTV_TVAL 0x38
5355
#define CNTV_CTL 0x3c
5456

@@ -112,6 +114,13 @@ void arch_timer_reg_write(int access, enum arch_timer_reg reg, u64 val,
112114
case ARCH_TIMER_REG_TVAL:
113115
writel_relaxed((u32)val, timer->base + CNTP_TVAL);
114116
break;
117+
case ARCH_TIMER_REG_CVAL:
118+
/*
119+
* Not guaranteed to be atomic, so the timer
120+
* must be disabled at this point.
121+
*/
122+
writeq_relaxed(val, timer->base + CNTP_CVAL_LO);
123+
break;
115124
default:
116125
BUILD_BUG();
117126
}
@@ -124,6 +133,10 @@ void arch_timer_reg_write(int access, enum arch_timer_reg reg, u64 val,
124133
case ARCH_TIMER_REG_TVAL:
125134
writel_relaxed((u32)val, timer->base + CNTV_TVAL);
126135
break;
136+
case ARCH_TIMER_REG_CVAL:
137+
/* Same restriction as above */
138+
writeq_relaxed(val, timer->base + CNTV_CVAL_LO);
139+
break;
127140
default:
128141
BUILD_BUG();
129142
}
@@ -720,15 +733,36 @@ static int arch_timer_set_next_event_phys(unsigned long evt,
720733
return 0;
721734
}
722735

736+
static u64 arch_counter_get_cnt_mem(struct arch_timer *t, int offset_lo)
737+
{
738+
u32 cnt_lo, cnt_hi, tmp_hi;
739+
740+
do {
741+
cnt_hi = readl_relaxed(t->base + offset_lo + 4);
742+
cnt_lo = readl_relaxed(t->base + offset_lo);
743+
tmp_hi = readl_relaxed(t->base + offset_lo + 4);
744+
} while (cnt_hi != tmp_hi);
745+
746+
return ((u64) cnt_hi << 32) | cnt_lo;
747+
}
748+
723749
static __always_inline void set_next_event_mem(const int access, unsigned long evt,
724750
struct clock_event_device *clk)
725751
{
752+
struct arch_timer *timer = to_arch_timer(clk);
726753
unsigned long ctrl;
754+
u64 cnt;
755+
727756
ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL, clk);
728757
ctrl |= ARCH_TIMER_CTRL_ENABLE;
729758
ctrl &= ~ARCH_TIMER_CTRL_IT_MASK;
730759

731-
arch_timer_reg_write(access, ARCH_TIMER_REG_TVAL, evt, clk);
760+
if (access == ARCH_TIMER_MEM_VIRT_ACCESS)
761+
cnt = arch_counter_get_cnt_mem(timer, CNTVCT_LO);
762+
else
763+
cnt = arch_counter_get_cnt_mem(timer, CNTPCT_LO);
764+
765+
arch_timer_reg_write(access, ARCH_TIMER_REG_CVAL, evt + cnt, clk);
732766
arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk);
733767
}
734768

@@ -970,15 +1004,7 @@ bool arch_timer_evtstrm_available(void)
9701004

9711005
static u64 arch_counter_get_cntvct_mem(void)
9721006
{
973-
u32 vct_lo, vct_hi, tmp_hi;
974-
975-
do {
976-
vct_hi = readl_relaxed(arch_timer_mem->base + CNTVCT_HI);
977-
vct_lo = readl_relaxed(arch_timer_mem->base + CNTVCT_LO);
978-
tmp_hi = readl_relaxed(arch_timer_mem->base + CNTVCT_HI);
979-
} while (vct_hi != tmp_hi);
980-
981-
return ((u64) vct_hi << 32) | vct_lo;
1007+
return arch_counter_get_cnt_mem(arch_timer_mem, CNTVCT_LO);
9821008
}
9831009

9841010
static struct arch_timer_kvm_info arch_timer_kvm_info;

0 commit comments

Comments
 (0)