Skip to content

Commit a08f521

Browse files
committed
1 parent 3bbf629 commit a08f521

File tree

2 files changed

+72
-83
lines changed

2 files changed

+72
-83
lines changed

arch/arm64/include/asm/arch_timer.h

Lines changed: 48 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,51 @@
2323

2424
#include <linux/init.h>
2525
#include <linux/types.h>
26+
#include <linux/stringify.h>
2627

2728
#include <clocksource/arm_arch_timer.h>
2829

30+
#define read_sysreg(r) ({ \
31+
u64 __val; \
32+
asm volatile("mrs %0, " __stringify(r) : "=r" (__val)); \
33+
__val; \
34+
})
35+
36+
#define write_sysreg(v, r) do { \
37+
u64 __val = (u64)v; \
38+
asm volatile("msr " __stringify(r) ", %x0" \
39+
: : "rZ" (__val)); \
40+
} while (0)
41+
42+
u32 __fsl_a008585_read_cntp_tval_el0(void);
43+
u32 __fsl_a008585_read_cntv_tval_el0(void);
44+
u64 __fsl_a008585_read_cntvct_el0(void);
45+
46+
/*
47+
* The number of retries is an arbitrary value well beyond the highest number
48+
* of iterations the loop has been observed to take.
49+
*/
50+
#define __fsl_a008585_read_reg(reg) ({ \
51+
u64 _old, _new; \
52+
int _retries = 200; \
53+
\
54+
do { \
55+
_old = read_sysreg(reg); \
56+
_new = read_sysreg(reg); \
57+
_retries--; \
58+
} while (unlikely(_old != _new) && _retries); \
59+
\
60+
WARN_ON_ONCE(!_retries); \
61+
_new; \
62+
})
63+
64+
#define arch_timer_reg_read_stable(reg) \
65+
({ \
66+
u64 _val; \
67+
_val = __fsl_a008585_read_##reg(); \
68+
_val; \
69+
})
70+
2971
/*
3072
* These register accessors are marked inline so the compiler can
3173
* nicely work out which register we want, and chuck away the rest of
@@ -60,29 +102,23 @@ void arch_timer_reg_write_cp15(int access, enum arch_timer_reg reg, u32 val)
60102
static __always_inline
61103
u32 arch_timer_reg_read_cp15(int access, enum arch_timer_reg reg)
62104
{
63-
u32 val;
64-
65105
if (access == ARCH_TIMER_PHYS_ACCESS) {
66106
switch (reg) {
67107
case ARCH_TIMER_REG_CTRL:
68-
asm volatile("mrs %0, cntp_ctl_el0" : "=r" (val));
69-
break;
108+
return read_sysreg(cntp_ctl_el0);
70109
case ARCH_TIMER_REG_TVAL:
71-
asm volatile("mrs %0, cntp_tval_el0" : "=r" (val));
72-
break;
110+
return arch_timer_reg_read_stable(cntp_tval_el0);
73111
}
74112
} else if (access == ARCH_TIMER_VIRT_ACCESS) {
75113
switch (reg) {
76114
case ARCH_TIMER_REG_CTRL:
77-
asm volatile("mrs %0, cntv_ctl_el0" : "=r" (val));
78-
break;
115+
return read_sysreg(cntv_ctl_el0);
79116
case ARCH_TIMER_REG_TVAL:
80-
asm volatile("mrs %0, cntv_tval_el0" : "=r" (val));
81-
break;
117+
return arch_timer_reg_read_stable(cntv_tval_el0);
82118
}
83119
}
84120

85-
return val;
121+
BUG();
86122
}
87123

88124
static inline u32 arch_timer_get_cntfrq(void)
@@ -135,48 +171,11 @@ static inline void arch_timer_evtstrm_enable(int divider)
135171
#endif
136172
}
137173

138-
#ifdef CONFIG_ARCH_SUN50I
139-
#define ARCH_VCNT_TRY_MAX_TIME (8)
140-
#define ARCH_VCNT_MAX_DELTA (8)
141-
static inline u64 arch_counter_get_cntvct(void)
142-
{
143-
u64 cval0;
144-
u64 cval1;
145-
u64 delta;
146-
u32 retry = 0;
147-
148-
/* sun50i vcnt maybe imprecise,
149-
* we should try to fix this.
150-
*/
151-
while (retry < ARCH_VCNT_TRY_MAX_TIME) {
152-
isb();
153-
asm volatile("mrs %0, cntvct_el0" : "=r" (cval0));
154-
isb();
155-
asm volatile("mrs %0, cntvct_el0" : "=r" (cval1));
156-
delta = cval1 - cval0;
157-
if ((cval1 >= cval0) && (delta < ARCH_VCNT_MAX_DELTA)) {
158-
/* read valid vcnt */
159-
return cval1;
160-
}
161-
/* vcnt value error, try again */
162-
retry++;
163-
}
164-
/* Do not warry for this, just return the last time vcnt.
165-
* arm64 have enabled CONFIG_CLOCKSOURCE_VALIDATE_LAST_CYCLE.
166-
*/
167-
return cval1;
168-
}
169-
#else
170174
static inline u64 arch_counter_get_cntvct(void)
171175
{
172-
u64 cval;
173-
174176
isb();
175-
asm volatile("mrs %0, cntvct_el0" : "=r" (cval));
176-
177-
return cval;
177+
return arch_timer_reg_read_stable(cntvct_el0);
178178
}
179-
#endif /* CONFIG_ARCH_SUN50I */
180179

181180
static inline int arch_timer_arch_init(void)
182181
{

drivers/clocksource/arm_arch_timer.c

Lines changed: 24 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,22 @@ static __always_inline void timer_set_mode(const int access, int mode,
192192
}
193193
}
194194

195+
u32 __fsl_a008585_read_cntp_tval_el0(void)
196+
{
197+
return __fsl_a008585_read_reg(cntp_tval_el0);
198+
}
199+
200+
u32 __fsl_a008585_read_cntv_tval_el0(void)
201+
{
202+
return __fsl_a008585_read_reg(cntv_tval_el0);
203+
}
204+
205+
u64 __fsl_a008585_read_cntvct_el0(void)
206+
{
207+
return __fsl_a008585_read_reg(cntvct_el0);
208+
}
209+
EXPORT_SYMBOL(__fsl_a008585_read_cntvct_el0);
210+
195211
static void arch_timer_set_mode_virt(enum clock_event_mode mode,
196212
struct clock_event_device *clk)
197213
{
@@ -215,49 +231,23 @@ static void arch_timer_set_mode_phys_mem(enum clock_event_mode mode,
215231
{
216232
timer_set_mode(ARCH_TIMER_MEM_PHYS_ACCESS, mode, clk);
217233
}
218-
#ifdef CONFIG_ARCH_SUN50I
219-
#define ARCH_TVAL_TRY_MAX_TIME (8)
220-
static __always_inline void set_next_event(const int access, unsigned long evt,
221-
struct clock_event_device *clk)
222-
{
223-
unsigned int retry = 0;
224-
unsigned long ctrl;
225-
unsigned long tval;
226234

227-
ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL, clk);
228-
ctrl |= ARCH_TIMER_CTRL_ENABLE;
229-
ctrl &= ~ARCH_TIMER_CTRL_IT_MASK;
230-
231-
/* sun50i timer maybe imprecise,
232-
* we should try to fix this.
233-
*/
234-
while (retry < ARCH_VCNT_TRY_MAX_TIME) {
235-
arch_timer_reg_write(access, ARCH_TIMER_REG_TVAL, evt, clk);
236-
tval = arch_timer_reg_read(access, ARCH_TIMER_REG_TVAL, clk);
237-
if (tval <= evt) {
238-
/* set tval succeeded, let timer running */
239-
arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk);
240-
return;
241-
}
242-
/* tval set value error, try again */
243-
retry++;
244-
}
245-
/* set tval fail, just let timer running */
246-
printk("notice: set tval failed.\n");
247-
arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk);
248-
}
249-
#else
250235
static __always_inline void set_next_event(const int access, unsigned long evt,
251236
struct clock_event_device *clk)
252237
{
253238
unsigned long ctrl;
239+
u64 cval = evt + arch_counter_get_cntvct();
254240
ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL, clk);
255241
ctrl |= ARCH_TIMER_CTRL_ENABLE;
256242
ctrl &= ~ARCH_TIMER_CTRL_IT_MASK;
257-
arch_timer_reg_write(access, ARCH_TIMER_REG_TVAL, evt, clk);
243+
244+
if (access == ARCH_TIMER_PHYS_ACCESS)
245+
write_sysreg(cval, cntp_cval_el0);
246+
else if (access == ARCH_TIMER_VIRT_ACCESS)
247+
write_sysreg(cval, cntv_cval_el0);
248+
258249
arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk);
259250
}
260-
#endif /* CONFIG_ARCH_SUN50I */
261251

262252
static int arch_timer_set_next_event_virt(unsigned long evt,
263253
struct clock_event_device *clk)
@@ -432,7 +422,7 @@ static cycle_t arch_counter_read_cc(const struct cyclecounter *cc)
432422
}
433423

434424
static struct clocksource clocksource_counter = {
435-
.name = "arch_sys_counter",
425+
.name = "arch_sys_counter_ool",
436426
.rating = 400,
437427
.read = arch_counter_read,
438428
.mask = CLOCKSOURCE_MASK(56),

0 commit comments

Comments
 (0)