clocksource/drivers/arm_arch_timer: Move system register timer programming over to...
[linux-2.6-block.git] / arch / arm64 / include / asm / arch_timer.h
CommitLineData
caab277b 1/* SPDX-License-Identifier: GPL-2.0-only */
1aee5d7a
MR
2/*
3 * arch/arm64/include/asm/arch_timer.h
4 *
5 * Copyright (C) 2012 ARM Ltd.
6 * Author: Marc Zyngier <marc.zyngier@arm.com>
1aee5d7a
MR
7 */
8#ifndef __ASM_ARCH_TIMER_H
9#define __ASM_ARCH_TIMER_H
10
11#include <asm/barrier.h>
5a354412 12#include <asm/hwcap.h>
cd5f22d7 13#include <asm/sysreg.h>
1aee5d7a 14
082471a8 15#include <linux/bug.h>
1aee5d7a 16#include <linux/init.h>
f6dc1576 17#include <linux/jump_label.h>
6acc71cc 18#include <linux/smp.h>
1aee5d7a
MR
19#include <linux/types.h>
20
21#include <clocksource/arm_arch_timer.h>
22
16d10ef2 23#if IS_ENABLED(CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND)
5ef19a16
MZ
24#define has_erratum_handler(h) \
25 ({ \
26 const struct arch_timer_erratum_workaround *__wa; \
27 __wa = __this_cpu_read(timer_unstable_counter_workaround); \
28 (__wa && __wa->h); \
29 })
30
31#define erratum_handler(h) \
32 ({ \
33 const struct arch_timer_erratum_workaround *__wa; \
34 __wa = __this_cpu_read(timer_unstable_counter_workaround); \
35 (__wa && __wa->h) ? __wa->h : arch_timer_##h; \
36 })
37
f6dc1576 38#else
5ef19a16
MZ
39#define has_erratum_handler(h) false
40#define erratum_handler(h) (arch_timer_##h)
f6dc1576
SW
41#endif
42
651bb2e9
MZ
43enum arch_timer_erratum_match_type {
44 ate_match_dt,
0064030c 45 ate_match_local_cap_id,
5a38bcac 46 ate_match_acpi_oem_info,
651bb2e9 47};
f6dc1576 48
01d3e3ff
MZ
49struct clock_event_device;
50
16d10ef2 51struct arch_timer_erratum_workaround {
651bb2e9
MZ
52 enum arch_timer_erratum_match_type match_type;
53 const void *id;
54 const char *desc;
f2e600c1 55 u64 (*read_cntpct_el0)(void);
16d10ef2 56 u64 (*read_cntvct_el0)(void);
01d3e3ff
MZ
57 int (*set_next_event_phys)(unsigned long, struct clock_event_device *);
58 int (*set_next_event_virt)(unsigned long, struct clock_event_device *);
c1fbec4a 59 bool disable_compat_vdso;
16d10ef2
DT
60};
61
6acc71cc
MZ
62DECLARE_PER_CPU(const struct arch_timer_erratum_workaround *,
63 timer_unstable_counter_workaround);
f6dc1576 64
57f27666
MZ
65static inline notrace u64 arch_timer_read_cntpct_el0(void)
66{
67 return read_sysreg(cntpct_el0);
68}
69
70static inline notrace u64 arch_timer_read_cntvct_el0(void)
71{
72 return read_sysreg(cntvct_el0);
73}
74
6acc71cc 75#define arch_timer_reg_read_stable(reg) \
57f27666
MZ
76 ({ \
77 u64 _val; \
78 \
adb4f11e 79 preempt_disable_notrace(); \
57f27666 80 _val = erratum_handler(read_ ## reg)(); \
adb4f11e 81 preempt_enable_notrace(); \
57f27666
MZ
82 \
83 _val; \
84 })
f6dc1576 85
e09f3cc0
SB
86/*
87 * These register accessors are marked inline so the compiler can
88 * nicely work out which register we want, and chuck away the rest of
89 * the code.
90 */
91static __always_inline
1e8d9292 92void arch_timer_reg_write_cp15(int access, enum arch_timer_reg reg, u64 val)
1aee5d7a
MR
93{
94 if (access == ARCH_TIMER_PHYS_ACCESS) {
95 switch (reg) {
96 case ARCH_TIMER_REG_CTRL:
cd5f22d7 97 write_sysreg(val, cntp_ctl_el0);
1aee5d7a 98 break;
a38b71b0
MZ
99 case ARCH_TIMER_REG_CVAL:
100 write_sysreg(val, cntp_cval_el0);
1aee5d7a 101 break;
4775bc63
MZ
102 default:
103 BUILD_BUG();
1aee5d7a
MR
104 }
105 } else if (access == ARCH_TIMER_VIRT_ACCESS) {
106 switch (reg) {
107 case ARCH_TIMER_REG_CTRL:
cd5f22d7 108 write_sysreg(val, cntv_ctl_el0);
1aee5d7a 109 break;
a38b71b0
MZ
110 case ARCH_TIMER_REG_CVAL:
111 write_sysreg(val, cntv_cval_el0);
1aee5d7a 112 break;
4775bc63
MZ
113 default:
114 BUILD_BUG();
1aee5d7a 115 }
4775bc63
MZ
116 } else {
117 BUILD_BUG();
1aee5d7a
MR
118 }
119
120 isb();
121}
122
e09f3cc0 123static __always_inline
a38b71b0 124u64 arch_timer_reg_read_cp15(int access, enum arch_timer_reg reg)
1aee5d7a 125{
1aee5d7a
MR
126 if (access == ARCH_TIMER_PHYS_ACCESS) {
127 switch (reg) {
128 case ARCH_TIMER_REG_CTRL:
cd5f22d7 129 return read_sysreg(cntp_ctl_el0);
4775bc63
MZ
130 default:
131 BUILD_BUG();
1aee5d7a
MR
132 }
133 } else if (access == ARCH_TIMER_VIRT_ACCESS) {
134 switch (reg) {
135 case ARCH_TIMER_REG_CTRL:
cd5f22d7 136 return read_sysreg(cntv_ctl_el0);
4775bc63
MZ
137 default:
138 BUILD_BUG();
1aee5d7a 139 }
1aee5d7a
MR
140 }
141
4775bc63
MZ
142 BUILD_BUG();
143 unreachable();
1aee5d7a
MR
144}
145
146static inline u32 arch_timer_get_cntfrq(void)
147{
cd5f22d7 148 return read_sysreg(cntfrq_el0);
1aee5d7a
MR
149}
150
46efe547 151static inline u32 arch_timer_get_cntkctl(void)
1aee5d7a 152{
cd5f22d7 153 return read_sysreg(cntkctl_el1);
46efe547
SK
154}
155
156static inline void arch_timer_set_cntkctl(u32 cntkctl)
157{
cd5f22d7 158 write_sysreg(cntkctl, cntkctl_el1);
ec5c8e42 159 isb();
46efe547
SK
160}
161
f31e98bf 162static __always_inline u64 __arch_counter_get_cntpct_stable(void)
0b46b8a7 163{
75a19a02
WD
164 u64 cnt;
165
f2e600c1 166 isb();
75a19a02
WD
167 cnt = arch_timer_reg_read_stable(cntpct_el0);
168 arch_counter_enforce_ordering(cnt);
169 return cnt;
0b46b8a7
SR
170}
171
f31e98bf 172static __always_inline u64 __arch_counter_get_cntpct(void)
0ea41539 173{
24cf262d
WD
174 u64 cnt;
175
0ea41539 176 isb();
24cf262d
WD
177 cnt = read_sysreg(cntpct_el0);
178 arch_counter_enforce_ordering(cnt);
179 return cnt;
0ea41539
MZ
180}
181
f31e98bf 182static __always_inline u64 __arch_counter_get_cntvct_stable(void)
1aee5d7a 183{
75a19a02
WD
184 u64 cnt;
185
1aee5d7a 186 isb();
75a19a02
WD
187 cnt = arch_timer_reg_read_stable(cntvct_el0);
188 arch_counter_enforce_ordering(cnt);
189 return cnt;
1aee5d7a
MR
190}
191
f31e98bf 192static __always_inline u64 __arch_counter_get_cntvct(void)
0ea41539 193{
24cf262d
WD
194 u64 cnt;
195
0ea41539 196 isb();
24cf262d
WD
197 cnt = read_sysreg(cntvct_el0);
198 arch_counter_enforce_ordering(cnt);
199 return cnt;
0ea41539
MZ
200}
201
0583fe47
RH
202static inline int arch_timer_arch_init(void)
203{
204 return 0;
205}
206
5a354412
AM
207static inline void arch_timer_set_evtstrm_feature(void)
208{
209 cpu_set_named_feature(EVTSTRM);
210#ifdef CONFIG_COMPAT
211 compat_elf_hwcap |= COMPAT_HWCAP_EVTSTRM;
212#endif
213}
214
215static inline bool arch_timer_have_evtstrm_feature(void)
216{
217 return cpu_have_named_feature(EVTSTRM);
218}
1aee5d7a 219#endif