]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - arch/arm64/include/asm/arch_timer.h
Merge tag 'powerpc-4.13-8' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc...
[mirror_ubuntu-artful-kernel.git] / arch / arm64 / include / asm / arch_timer.h
CommitLineData
1aee5d7a
MR
1/*
2 * arch/arm64/include/asm/arch_timer.h
3 *
4 * Copyright (C) 2012 ARM Ltd.
5 * Author: Marc Zyngier <marc.zyngier@arm.com>
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19#ifndef __ASM_ARCH_TIMER_H
20#define __ASM_ARCH_TIMER_H
21
22#include <asm/barrier.h>
cd5f22d7 23#include <asm/sysreg.h>
1aee5d7a 24
082471a8 25#include <linux/bug.h>
1aee5d7a 26#include <linux/init.h>
f6dc1576 27#include <linux/jump_label.h>
6acc71cc 28#include <linux/smp.h>
1aee5d7a
MR
29#include <linux/types.h>
30
31#include <clocksource/arm_arch_timer.h>
32
16d10ef2 33#if IS_ENABLED(CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND)
f6dc1576 34extern struct static_key_false arch_timer_read_ool_enabled;
16d10ef2 35#define needs_unstable_timer_counter_workaround() \
f6dc1576
SW
36 static_branch_unlikely(&arch_timer_read_ool_enabled)
37#else
16d10ef2 38#define needs_unstable_timer_counter_workaround() false
f6dc1576
SW
39#endif
40
651bb2e9
MZ
41enum arch_timer_erratum_match_type {
42 ate_match_dt,
0064030c 43 ate_match_local_cap_id,
5a38bcac 44 ate_match_acpi_oem_info,
651bb2e9 45};
f6dc1576 46
01d3e3ff
MZ
47struct clock_event_device;
48
16d10ef2 49struct arch_timer_erratum_workaround {
651bb2e9
MZ
50 enum arch_timer_erratum_match_type match_type;
51 const void *id;
52 const char *desc;
16d10ef2
DT
53 u32 (*read_cntp_tval_el0)(void);
54 u32 (*read_cntv_tval_el0)(void);
55 u64 (*read_cntvct_el0)(void);
01d3e3ff
MZ
56 int (*set_next_event_phys)(unsigned long, struct clock_event_device *);
57 int (*set_next_event_virt)(unsigned long, struct clock_event_device *);
16d10ef2
DT
58};
59
6acc71cc
MZ
60DECLARE_PER_CPU(const struct arch_timer_erratum_workaround *,
61 timer_unstable_counter_workaround);
f6dc1576 62
6acc71cc
MZ
63#define arch_timer_reg_read_stable(reg) \
64({ \
65 u64 _val; \
66 if (needs_unstable_timer_counter_workaround()) { \
67 const struct arch_timer_erratum_workaround *wa; \
adb4f11e 68 preempt_disable_notrace(); \
6acc71cc
MZ
69 wa = __this_cpu_read(timer_unstable_counter_workaround); \
70 if (wa && wa->read_##reg) \
71 _val = wa->read_##reg(); \
72 else \
73 _val = read_sysreg(reg); \
adb4f11e 74 preempt_enable_notrace(); \
6acc71cc
MZ
75 } else { \
76 _val = read_sysreg(reg); \
77 } \
78 _val; \
f6dc1576
SW
79})
80
e09f3cc0
SB
81/*
82 * These register accessors are marked inline so the compiler can
83 * nicely work out which register we want, and chuck away the rest of
84 * the code.
85 */
86static __always_inline
60faddf6 87void arch_timer_reg_write_cp15(int access, enum arch_timer_reg reg, u32 val)
1aee5d7a
MR
88{
89 if (access == ARCH_TIMER_PHYS_ACCESS) {
90 switch (reg) {
91 case ARCH_TIMER_REG_CTRL:
cd5f22d7 92 write_sysreg(val, cntp_ctl_el0);
1aee5d7a
MR
93 break;
94 case ARCH_TIMER_REG_TVAL:
cd5f22d7 95 write_sysreg(val, cntp_tval_el0);
1aee5d7a 96 break;
1aee5d7a
MR
97 }
98 } else if (access == ARCH_TIMER_VIRT_ACCESS) {
99 switch (reg) {
100 case ARCH_TIMER_REG_CTRL:
cd5f22d7 101 write_sysreg(val, cntv_ctl_el0);
1aee5d7a
MR
102 break;
103 case ARCH_TIMER_REG_TVAL:
cd5f22d7 104 write_sysreg(val, cntv_tval_el0);
1aee5d7a 105 break;
1aee5d7a 106 }
1aee5d7a
MR
107 }
108
109 isb();
110}
111
e09f3cc0 112static __always_inline
60faddf6 113u32 arch_timer_reg_read_cp15(int access, enum arch_timer_reg reg)
1aee5d7a 114{
1aee5d7a
MR
115 if (access == ARCH_TIMER_PHYS_ACCESS) {
116 switch (reg) {
117 case ARCH_TIMER_REG_CTRL:
cd5f22d7 118 return read_sysreg(cntp_ctl_el0);
1aee5d7a 119 case ARCH_TIMER_REG_TVAL:
f6dc1576 120 return arch_timer_reg_read_stable(cntp_tval_el0);
1aee5d7a
MR
121 }
122 } else if (access == ARCH_TIMER_VIRT_ACCESS) {
123 switch (reg) {
124 case ARCH_TIMER_REG_CTRL:
cd5f22d7 125 return read_sysreg(cntv_ctl_el0);
1aee5d7a 126 case ARCH_TIMER_REG_TVAL:
f6dc1576 127 return arch_timer_reg_read_stable(cntv_tval_el0);
1aee5d7a 128 }
1aee5d7a
MR
129 }
130
cd5f22d7 131 BUG();
1aee5d7a
MR
132}
133
134static inline u32 arch_timer_get_cntfrq(void)
135{
cd5f22d7 136 return read_sysreg(cntfrq_el0);
1aee5d7a
MR
137}
138
46efe547 139static inline u32 arch_timer_get_cntkctl(void)
1aee5d7a 140{
cd5f22d7 141 return read_sysreg(cntkctl_el1);
46efe547
SH
142}
143
144static inline void arch_timer_set_cntkctl(u32 cntkctl)
145{
cd5f22d7 146 write_sysreg(cntkctl, cntkctl_el1);
46efe547
SH
147}
148
0b46b8a7
SR
149static inline u64 arch_counter_get_cntpct(void)
150{
151 /*
152 * AArch64 kernel and user space mandate the use of CNTVCT.
153 */
154 BUG();
155 return 0;
156}
157
1aee5d7a
MR
158static inline u64 arch_counter_get_cntvct(void)
159{
1aee5d7a 160 isb();
f6dc1576 161 return arch_timer_reg_read_stable(cntvct_el0);
1aee5d7a
MR
162}
163
0583fe47
RH
164static inline int arch_timer_arch_init(void)
165{
166 return 0;
167}
168
1aee5d7a 169#endif