1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
28a4da6e3SMark Rutland /*
38a4da6e3SMark Rutland * linux/drivers/clocksource/arm_arch_timer.c
48a4da6e3SMark Rutland *
58a4da6e3SMark Rutland * Copyright (C) 2011 ARM Ltd.
68a4da6e3SMark Rutland * All Rights Reserved
78a4da6e3SMark Rutland */
8f005bd7eSMarc Zyngier
99155697eSYangtao Li #define pr_fmt(fmt) "arch_timer: " fmt
10f005bd7eSMarc Zyngier
118a4da6e3SMark Rutland #include <linux/init.h>
128a4da6e3SMark Rutland #include <linux/kernel.h>
138a4da6e3SMark Rutland #include <linux/device.h>
148a4da6e3SMark Rutland #include <linux/smp.h>
158a4da6e3SMark Rutland #include <linux/cpu.h>
16346e7480SSudeep KarkadaNagesha #include <linux/cpu_pm.h>
178a4da6e3SMark Rutland #include <linux/clockchips.h>
187c8f1e78SRichard Cochran #include <linux/clocksource.h>
19100148d0SJianyong Wu #include <linux/clocksource_ids.h>
208a4da6e3SMark Rutland #include <linux/interrupt.h>
2142385687SChristophe JAILLET #include <linux/kstrtox.h>
228a4da6e3SMark Rutland #include <linux/of_irq.h>
2322006994SStephen Boyd #include <linux/of_address.h>
248a4da6e3SMark Rutland #include <linux/io.h>
2522006994SStephen Boyd #include <linux/slab.h>
26e6017571SIngo Molnar #include <linux/sched/clock.h>
2765cd4f6cSStephen Boyd #include <linux/sched_clock.h>
28b09ca1ecSHanjun Guo #include <linux/acpi.h>
29300bb1feSJianyong Wu #include <linux/arm-smccc.h>
30300bb1feSJianyong Wu #include <linux/ptp_kvm.h>
318a4da6e3SMark Rutland
328a4da6e3SMark Rutland #include <asm/arch_timer.h>
338266891eSMarc Zyngier #include <asm/virt.h>
348a4da6e3SMark Rutland
358a4da6e3SMark Rutland #include <clocksource/arm_arch_timer.h>
368a4da6e3SMark Rutland
3722006994SStephen Boyd #define CNTTIDR 0x08
3822006994SStephen Boyd #define CNTTIDR_VIRT(n) (BIT(1) << ((n) * 4))
3922006994SStephen Boyd
40e392d603SRobin Murphy #define CNTACR(n) (0x40 + ((n) * 4))
41e392d603SRobin Murphy #define CNTACR_RPCT BIT(0)
42e392d603SRobin Murphy #define CNTACR_RVCT BIT(1)
43e392d603SRobin Murphy #define CNTACR_RFRQ BIT(2)
44e392d603SRobin Murphy #define CNTACR_RVOFF BIT(3)
45e392d603SRobin Murphy #define CNTACR_RWVT BIT(4)
46e392d603SRobin Murphy #define CNTACR_RWPT BIT(5)
47e392d603SRobin Murphy
48af246cc6SYang Guo #define CNTPCT_LO 0x00
49af246cc6SYang Guo #define CNTVCT_LO 0x08
5022006994SStephen Boyd #define CNTFRQ 0x10
518b82c4f8SMarc Zyngier #define CNTP_CVAL_LO 0x20
5222006994SStephen Boyd #define CNTP_CTL 0x2c
538b82c4f8SMarc Zyngier #define CNTV_CVAL_LO 0x30
5422006994SStephen Boyd #define CNTV_CTL 0x3c
5522006994SStephen Boyd
56c1153d52SOliver Upton /*
57c1153d52SOliver Upton * The minimum amount of time a generic counter is guaranteed to not roll over
58c1153d52SOliver Upton * (40 years)
59c1153d52SOliver Upton */
60c1153d52SOliver Upton #define MIN_ROLLOVER_SECS (40ULL * 365 * 24 * 3600)
61c1153d52SOliver Upton
6222006994SStephen Boyd static unsigned arch_timers_present __initdata;
6322006994SStephen Boyd
6422006994SStephen Boyd struct arch_timer {
6522006994SStephen Boyd void __iomem *base;
6622006994SStephen Boyd struct clock_event_device evt;
6722006994SStephen Boyd };
6822006994SStephen Boyd
6972f47a3fSMarc Zyngier static struct arch_timer *arch_timer_mem __ro_after_init;
7072f47a3fSMarc Zyngier
7122006994SStephen Boyd #define to_arch_timer(e) container_of(e, struct arch_timer, evt)
7222006994SStephen Boyd
73e2bf384dSJisheng Zhang static u32 arch_timer_rate __ro_after_init;
74e2bf384dSJisheng Zhang static int arch_timer_ppi[ARCH_TIMER_MAX_TIMER_PPI] __ro_after_init;
758a4da6e3SMark Rutland
7686332e9eSHector Martin static const char *arch_timer_ppi_names[ARCH_TIMER_MAX_TIMER_PPI] = {
7786332e9eSHector Martin [ARCH_TIMER_PHYS_SECURE_PPI] = "sec-phys",
7886332e9eSHector Martin [ARCH_TIMER_PHYS_NONSECURE_PPI] = "phys",
7986332e9eSHector Martin [ARCH_TIMER_VIRT_PPI] = "virt",
8086332e9eSHector Martin [ARCH_TIMER_HYP_PPI] = "hyp-phys",
8186332e9eSHector Martin [ARCH_TIMER_HYP_VIRT_PPI] = "hyp-virt",
8286332e9eSHector Martin };
8386332e9eSHector Martin
848a4da6e3SMark Rutland static struct clock_event_device __percpu *arch_timer_evt;
858a4da6e3SMark Rutland
86e2bf384dSJisheng Zhang static enum arch_timer_ppi_nr arch_timer_uses_ppi __ro_after_init = ARCH_TIMER_VIRT_PPI;
87e2bf384dSJisheng Zhang static bool arch_timer_c3stop __ro_after_init;
88e2bf384dSJisheng Zhang static bool arch_timer_mem_use_virtual __ro_after_init;
89e2bf384dSJisheng Zhang static bool arch_counter_suspend_stop __ro_after_init;
90a67de48bSVincenzo Frascino #ifdef CONFIG_GENERIC_GETTIMEOFDAY
915e3c6a31SThomas Gleixner static enum vdso_clock_mode vdso_default = VDSO_CLOCKMODE_ARCHTIMER;
92a67de48bSVincenzo Frascino #else
93a67de48bSVincenzo Frascino static enum vdso_clock_mode vdso_default = VDSO_CLOCKMODE_NONE;
94a67de48bSVincenzo Frascino #endif /* CONFIG_GENERIC_GETTIMEOFDAY */
958a4da6e3SMark Rutland
96ec5c8e42SJulien Thierry static cpumask_t evtstrm_available = CPU_MASK_NONE;
97e2bf384dSJisheng Zhang static bool evtstrm_enable __ro_after_init = IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM);
9846fd5c6bSWill Deacon
early_evtstrm_cfg(char * buf)9946fd5c6bSWill Deacon static int __init early_evtstrm_cfg(char *buf)
10046fd5c6bSWill Deacon {
10142385687SChristophe JAILLET return kstrtobool(buf, &evtstrm_enable);
10246fd5c6bSWill Deacon }
10346fd5c6bSWill Deacon early_param("clocksource.arm_arch_timer.evtstrm", early_evtstrm_cfg);
10446fd5c6bSWill Deacon
1058a4da6e3SMark Rutland /*
106c1153d52SOliver Upton * Makes an educated guess at a valid counter width based on the Generic Timer
107c1153d52SOliver Upton * specification. Of note:
108c1153d52SOliver Upton * 1) the system counter is at least 56 bits wide
109c1153d52SOliver Upton * 2) a roll-over time of not less than 40 years
110c1153d52SOliver Upton *
111c1153d52SOliver Upton * See 'ARM DDI 0487G.a D11.1.2 ("The system counter")' for more details.
112c1153d52SOliver Upton */
arch_counter_get_width(void)113c1153d52SOliver Upton static int arch_counter_get_width(void)
114c1153d52SOliver Upton {
115c1153d52SOliver Upton u64 min_cycles = MIN_ROLLOVER_SECS * arch_timer_rate;
116c1153d52SOliver Upton
117c1153d52SOliver Upton /* guarantee the returned width is within the valid range */
118c1153d52SOliver Upton return clamp_val(ilog2(min_cycles - 1) + 1, 56, 64);
119c1153d52SOliver Upton }
120c1153d52SOliver Upton
121c1153d52SOliver Upton /*
1228a4da6e3SMark Rutland * Architected system timer support.
1238a4da6e3SMark Rutland */
1248a4da6e3SMark Rutland
125f4e00a1aSMarc Zyngier static __always_inline
arch_timer_reg_write(int access,enum arch_timer_reg reg,u64 val,struct clock_event_device * clk)1261e8d9292SMarc Zyngier void arch_timer_reg_write(int access, enum arch_timer_reg reg, u64 val,
127f4e00a1aSMarc Zyngier struct clock_event_device *clk)
128f4e00a1aSMarc Zyngier {
129f4e00a1aSMarc Zyngier if (access == ARCH_TIMER_MEM_PHYS_ACCESS) {
130f4e00a1aSMarc Zyngier struct arch_timer *timer = to_arch_timer(clk);
131f4e00a1aSMarc Zyngier switch (reg) {
132f4e00a1aSMarc Zyngier case ARCH_TIMER_REG_CTRL:
1331e8d9292SMarc Zyngier writel_relaxed((u32)val, timer->base + CNTP_CTL);
134f4e00a1aSMarc Zyngier break;
1358b82c4f8SMarc Zyngier case ARCH_TIMER_REG_CVAL:
1368b82c4f8SMarc Zyngier /*
1378b82c4f8SMarc Zyngier * Not guaranteed to be atomic, so the timer
1388b82c4f8SMarc Zyngier * must be disabled at this point.
1398b82c4f8SMarc Zyngier */
1408b82c4f8SMarc Zyngier writeq_relaxed(val, timer->base + CNTP_CVAL_LO);
1418b82c4f8SMarc Zyngier break;
1424775bc63SMarc Zyngier default:
1434775bc63SMarc Zyngier BUILD_BUG();
144f4e00a1aSMarc Zyngier }
145f4e00a1aSMarc Zyngier } else if (access == ARCH_TIMER_MEM_VIRT_ACCESS) {
146f4e00a1aSMarc Zyngier struct arch_timer *timer = to_arch_timer(clk);
147f4e00a1aSMarc Zyngier switch (reg) {
148f4e00a1aSMarc Zyngier case ARCH_TIMER_REG_CTRL:
1491e8d9292SMarc Zyngier writel_relaxed((u32)val, timer->base + CNTV_CTL);
150f4e00a1aSMarc Zyngier break;
1518b82c4f8SMarc Zyngier case ARCH_TIMER_REG_CVAL:
1528b82c4f8SMarc Zyngier /* Same restriction as above */
1538b82c4f8SMarc Zyngier writeq_relaxed(val, timer->base + CNTV_CVAL_LO);
1548b82c4f8SMarc Zyngier break;
1554775bc63SMarc Zyngier default:
1564775bc63SMarc Zyngier BUILD_BUG();
157f4e00a1aSMarc Zyngier }
158f4e00a1aSMarc Zyngier } else {
159f4e00a1aSMarc Zyngier arch_timer_reg_write_cp15(access, reg, val);
160f4e00a1aSMarc Zyngier }
161f4e00a1aSMarc Zyngier }
162f4e00a1aSMarc Zyngier
163f4e00a1aSMarc Zyngier static __always_inline
arch_timer_reg_read(int access,enum arch_timer_reg reg,struct clock_event_device * clk)164f4e00a1aSMarc Zyngier u32 arch_timer_reg_read(int access, enum arch_timer_reg reg,
165f4e00a1aSMarc Zyngier struct clock_event_device *clk)
166f4e00a1aSMarc Zyngier {
167f4e00a1aSMarc Zyngier u32 val;
168f4e00a1aSMarc Zyngier
169f4e00a1aSMarc Zyngier if (access == ARCH_TIMER_MEM_PHYS_ACCESS) {
170f4e00a1aSMarc Zyngier struct arch_timer *timer = to_arch_timer(clk);
171f4e00a1aSMarc Zyngier switch (reg) {
172f4e00a1aSMarc Zyngier case ARCH_TIMER_REG_CTRL:
173f4e00a1aSMarc Zyngier val = readl_relaxed(timer->base + CNTP_CTL);
174f4e00a1aSMarc Zyngier break;
1754775bc63SMarc Zyngier default:
1764775bc63SMarc Zyngier BUILD_BUG();
177f4e00a1aSMarc Zyngier }
178f4e00a1aSMarc Zyngier } else if (access == ARCH_TIMER_MEM_VIRT_ACCESS) {
179f4e00a1aSMarc Zyngier struct arch_timer *timer = to_arch_timer(clk);
180f4e00a1aSMarc Zyngier switch (reg) {
181f4e00a1aSMarc Zyngier case ARCH_TIMER_REG_CTRL:
182f4e00a1aSMarc Zyngier val = readl_relaxed(timer->base + CNTV_CTL);
183f4e00a1aSMarc Zyngier break;
1844775bc63SMarc Zyngier default:
1854775bc63SMarc Zyngier BUILD_BUG();
186f4e00a1aSMarc Zyngier }
187f4e00a1aSMarc Zyngier } else {
188f4e00a1aSMarc Zyngier val = arch_timer_reg_read_cp15(access, reg);
189f4e00a1aSMarc Zyngier }
190f4e00a1aSMarc Zyngier
191f4e00a1aSMarc Zyngier return val;
192f4e00a1aSMarc Zyngier }
193f4e00a1aSMarc Zyngier
raw_counter_get_cntpct_stable(void)19424ee7607SPeter Zijlstra static noinstr u64 raw_counter_get_cntpct_stable(void)
1950ea41539SMarc Zyngier {
1960ea41539SMarc Zyngier return __arch_counter_get_cntpct_stable();
1970ea41539SMarc Zyngier }
1980ea41539SMarc Zyngier
arch_counter_get_cntpct_stable(void)19924ee7607SPeter Zijlstra static notrace u64 arch_counter_get_cntpct_stable(void)
20024ee7607SPeter Zijlstra {
20124ee7607SPeter Zijlstra u64 val;
20224ee7607SPeter Zijlstra preempt_disable_notrace();
20324ee7607SPeter Zijlstra val = __arch_counter_get_cntpct_stable();
20424ee7607SPeter Zijlstra preempt_enable_notrace();
20524ee7607SPeter Zijlstra return val;
20624ee7607SPeter Zijlstra }
20724ee7607SPeter Zijlstra
arch_counter_get_cntpct(void)20824ee7607SPeter Zijlstra static noinstr u64 arch_counter_get_cntpct(void)
2090ea41539SMarc Zyngier {
2100ea41539SMarc Zyngier return __arch_counter_get_cntpct();
2110ea41539SMarc Zyngier }
2120ea41539SMarc Zyngier
raw_counter_get_cntvct_stable(void)21324ee7607SPeter Zijlstra static noinstr u64 raw_counter_get_cntvct_stable(void)
2140ea41539SMarc Zyngier {
2150ea41539SMarc Zyngier return __arch_counter_get_cntvct_stable();
2160ea41539SMarc Zyngier }
2170ea41539SMarc Zyngier
arch_counter_get_cntvct_stable(void)21824ee7607SPeter Zijlstra static notrace u64 arch_counter_get_cntvct_stable(void)
21924ee7607SPeter Zijlstra {
22024ee7607SPeter Zijlstra u64 val;
22124ee7607SPeter Zijlstra preempt_disable_notrace();
22224ee7607SPeter Zijlstra val = __arch_counter_get_cntvct_stable();
22324ee7607SPeter Zijlstra preempt_enable_notrace();
22424ee7607SPeter Zijlstra return val;
22524ee7607SPeter Zijlstra }
22624ee7607SPeter Zijlstra
arch_counter_get_cntvct(void)22724ee7607SPeter Zijlstra static noinstr u64 arch_counter_get_cntvct(void)
2280ea41539SMarc Zyngier {
2290ea41539SMarc Zyngier return __arch_counter_get_cntvct();
2300ea41539SMarc Zyngier }
2310ea41539SMarc Zyngier
232992dd16fSMarc Zyngier /*
233992dd16fSMarc Zyngier * Default to cp15 based access because arm64 uses this function for
234992dd16fSMarc Zyngier * sched_clock() before DT is probed and the cp15 method is guaranteed
235992dd16fSMarc Zyngier * to exist on arm64. arm doesn't use this before DT is probed so even
236992dd16fSMarc Zyngier * if we don't have the cp15 accessors we won't have a problem.
237992dd16fSMarc Zyngier */
238e2bf384dSJisheng Zhang u64 (*arch_timer_read_counter)(void) __ro_after_init = arch_counter_get_cntvct;
239e6d68b00SChristoffer Dall EXPORT_SYMBOL_GPL(arch_timer_read_counter);
240992dd16fSMarc Zyngier
arch_counter_read(struct clocksource * cs)241992dd16fSMarc Zyngier static u64 arch_counter_read(struct clocksource *cs)
242992dd16fSMarc Zyngier {
243992dd16fSMarc Zyngier return arch_timer_read_counter();
244992dd16fSMarc Zyngier }
245992dd16fSMarc Zyngier
arch_counter_read_cc(const struct cyclecounter * cc)246992dd16fSMarc Zyngier static u64 arch_counter_read_cc(const struct cyclecounter *cc)
247992dd16fSMarc Zyngier {
248992dd16fSMarc Zyngier return arch_timer_read_counter();
249992dd16fSMarc Zyngier }
250992dd16fSMarc Zyngier
251992dd16fSMarc Zyngier static struct clocksource clocksource_counter = {
252992dd16fSMarc Zyngier .name = "arch_sys_counter",
253100148d0SJianyong Wu .id = CSID_ARM_ARCH_COUNTER,
254992dd16fSMarc Zyngier .rating = 400,
255992dd16fSMarc Zyngier .read = arch_counter_read,
256992dd16fSMarc Zyngier .flags = CLOCK_SOURCE_IS_CONTINUOUS,
257992dd16fSMarc Zyngier };
258992dd16fSMarc Zyngier
259992dd16fSMarc Zyngier static struct cyclecounter cyclecounter __ro_after_init = {
260992dd16fSMarc Zyngier .read = arch_counter_read_cc,
261992dd16fSMarc Zyngier };
262992dd16fSMarc Zyngier
2635a38bcacSMarc Zyngier struct ate_acpi_oem_info {
2645a38bcacSMarc Zyngier char oem_id[ACPI_OEM_ID_SIZE + 1];
2655a38bcacSMarc Zyngier char oem_table_id[ACPI_OEM_TABLE_ID_SIZE + 1];
2665a38bcacSMarc Zyngier u32 oem_revision;
2675a38bcacSMarc Zyngier };
2685a38bcacSMarc Zyngier
269f6dc1576SScott Wood #ifdef CONFIG_FSL_ERRATUM_A008585
27016d10ef2SDing Tianhong /*
27116d10ef2SDing Tianhong * The number of retries is an arbitrary value well beyond the highest number
27216d10ef2SDing Tianhong * of iterations the loop has been observed to take.
27316d10ef2SDing Tianhong */
27416d10ef2SDing Tianhong #define __fsl_a008585_read_reg(reg) ({ \
27516d10ef2SDing Tianhong u64 _old, _new; \
27616d10ef2SDing Tianhong int _retries = 200; \
27716d10ef2SDing Tianhong \
27816d10ef2SDing Tianhong do { \
27916d10ef2SDing Tianhong _old = read_sysreg(reg); \
28016d10ef2SDing Tianhong _new = read_sysreg(reg); \
28116d10ef2SDing Tianhong _retries--; \
28216d10ef2SDing Tianhong } while (unlikely(_old != _new) && _retries); \
28316d10ef2SDing Tianhong \
28416d10ef2SDing Tianhong WARN_ON_ONCE(!_retries); \
28516d10ef2SDing Tianhong _new; \
28616d10ef2SDing Tianhong })
287f6dc1576SScott Wood
fsl_a008585_read_cntpct_el0(void)288f2e600c1SChristoffer Dall static u64 notrace fsl_a008585_read_cntpct_el0(void)
289f2e600c1SChristoffer Dall {
290f2e600c1SChristoffer Dall return __fsl_a008585_read_reg(cntpct_el0);
291f2e600c1SChristoffer Dall }
292f2e600c1SChristoffer Dall
fsl_a008585_read_cntvct_el0(void)29316d10ef2SDing Tianhong static u64 notrace fsl_a008585_read_cntvct_el0(void)
294f6dc1576SScott Wood {
295f6dc1576SScott Wood return __fsl_a008585_read_reg(cntvct_el0);
296f6dc1576SScott Wood }
29716d10ef2SDing Tianhong #endif
29816d10ef2SDing Tianhong
299bb42ca47SDing Tianhong #ifdef CONFIG_HISILICON_ERRATUM_161010101
300bb42ca47SDing Tianhong /*
301bb42ca47SDing Tianhong * Verify whether the value of the second read is larger than the first by
302bb42ca47SDing Tianhong * less than 32 is the only way to confirm the value is correct, so clear the
303bb42ca47SDing Tianhong * lower 5 bits to check whether the difference is greater than 32 or not.
304bb42ca47SDing Tianhong * Theoretically the erratum should not occur more than twice in succession
305bb42ca47SDing Tianhong * when reading the system counter, but it is possible that some interrupts
306bb42ca47SDing Tianhong * may lead to more than twice read errors, triggering the warning, so setting
307bb42ca47SDing Tianhong * the number of retries far beyond the number of iterations the loop has been
308bb42ca47SDing Tianhong * observed to take.
309bb42ca47SDing Tianhong */
310bb42ca47SDing Tianhong #define __hisi_161010101_read_reg(reg) ({ \
311bb42ca47SDing Tianhong u64 _old, _new; \
312bb42ca47SDing Tianhong int _retries = 50; \
313bb42ca47SDing Tianhong \
314bb42ca47SDing Tianhong do { \
315bb42ca47SDing Tianhong _old = read_sysreg(reg); \
316bb42ca47SDing Tianhong _new = read_sysreg(reg); \
317bb42ca47SDing Tianhong _retries--; \
318bb42ca47SDing Tianhong } while (unlikely((_new - _old) >> 5) && _retries); \
319bb42ca47SDing Tianhong \
320bb42ca47SDing Tianhong WARN_ON_ONCE(!_retries); \
321bb42ca47SDing Tianhong _new; \
322bb42ca47SDing Tianhong })
323bb42ca47SDing Tianhong
hisi_161010101_read_cntpct_el0(void)324f2e600c1SChristoffer Dall static u64 notrace hisi_161010101_read_cntpct_el0(void)
325f2e600c1SChristoffer Dall {
326f2e600c1SChristoffer Dall return __hisi_161010101_read_reg(cntpct_el0);
327f2e600c1SChristoffer Dall }
328f2e600c1SChristoffer Dall
hisi_161010101_read_cntvct_el0(void)329bb42ca47SDing Tianhong static u64 notrace hisi_161010101_read_cntvct_el0(void)
330bb42ca47SDing Tianhong {
331bb42ca47SDing Tianhong return __hisi_161010101_read_reg(cntvct_el0);
332bb42ca47SDing Tianhong }
333d003d029SMarc Zyngier
3342030a7e1SStephen Boyd static const struct ate_acpi_oem_info hisi_161010101_oem_info[] = {
335d003d029SMarc Zyngier /*
336d003d029SMarc Zyngier * Note that trailing spaces are required to properly match
337d003d029SMarc Zyngier * the OEM table information.
338d003d029SMarc Zyngier */
339d003d029SMarc Zyngier {
340d003d029SMarc Zyngier .oem_id = "HISI ",
341d003d029SMarc Zyngier .oem_table_id = "HIP05 ",
342d003d029SMarc Zyngier .oem_revision = 0,
343d003d029SMarc Zyngier },
344d003d029SMarc Zyngier {
345d003d029SMarc Zyngier .oem_id = "HISI ",
346d003d029SMarc Zyngier .oem_table_id = "HIP06 ",
347d003d029SMarc Zyngier .oem_revision = 0,
348d003d029SMarc Zyngier },
349d003d029SMarc Zyngier {
350d003d029SMarc Zyngier .oem_id = "HISI ",
351d003d029SMarc Zyngier .oem_table_id = "HIP07 ",
352d003d029SMarc Zyngier .oem_revision = 0,
353d003d029SMarc Zyngier },
354d003d029SMarc Zyngier { /* Sentinel indicating the end of the OEM array */ },
355d003d029SMarc Zyngier };
356bb42ca47SDing Tianhong #endif
357bb42ca47SDing Tianhong
358fa8d815fSMarc Zyngier #ifdef CONFIG_ARM64_ERRATUM_858921
arm64_858921_read_cntpct_el0(void)359f2e600c1SChristoffer Dall static u64 notrace arm64_858921_read_cntpct_el0(void)
360f2e600c1SChristoffer Dall {
361f2e600c1SChristoffer Dall u64 old, new;
362f2e600c1SChristoffer Dall
363f2e600c1SChristoffer Dall old = read_sysreg(cntpct_el0);
364f2e600c1SChristoffer Dall new = read_sysreg(cntpct_el0);
365f2e600c1SChristoffer Dall return (((old ^ new) >> 32) & 1) ? old : new;
366f2e600c1SChristoffer Dall }
367f2e600c1SChristoffer Dall
arm64_858921_read_cntvct_el0(void)368fa8d815fSMarc Zyngier static u64 notrace arm64_858921_read_cntvct_el0(void)
369fa8d815fSMarc Zyngier {
370fa8d815fSMarc Zyngier u64 old, new;
371fa8d815fSMarc Zyngier
372fa8d815fSMarc Zyngier old = read_sysreg(cntvct_el0);
373fa8d815fSMarc Zyngier new = read_sysreg(cntvct_el0);
374fa8d815fSMarc Zyngier return (((old ^ new) >> 32) & 1) ? old : new;
375fa8d815fSMarc Zyngier }
376fa8d815fSMarc Zyngier #endif
377fa8d815fSMarc Zyngier
378c950ca8cSSamuel Holland #ifdef CONFIG_SUN50I_ERRATUM_UNKNOWN1
379c950ca8cSSamuel Holland /*
380c950ca8cSSamuel Holland * The low bits of the counter registers are indeterminate while bit 10 or
381c950ca8cSSamuel Holland * greater is rolling over. Since the counter value can jump both backward
382c950ca8cSSamuel Holland * (7ff -> 000 -> 800) and forward (7ff -> fff -> 800), ignore register values
383c950ca8cSSamuel Holland * with all ones or all zeros in the low bits. Bound the loop by the maximum
384c950ca8cSSamuel Holland * number of CPU cycles in 3 consecutive 24 MHz counter periods.
385c950ca8cSSamuel Holland */
386c950ca8cSSamuel Holland #define __sun50i_a64_read_reg(reg) ({ \
387c950ca8cSSamuel Holland u64 _val; \
388c950ca8cSSamuel Holland int _retries = 150; \
389c950ca8cSSamuel Holland \
390c950ca8cSSamuel Holland do { \
391c950ca8cSSamuel Holland _val = read_sysreg(reg); \
392c950ca8cSSamuel Holland _retries--; \
3938b33dfe0SSamuel Holland } while (((_val + 1) & GENMASK(8, 0)) <= 1 && _retries); \
394c950ca8cSSamuel Holland \
395c950ca8cSSamuel Holland WARN_ON_ONCE(!_retries); \
396c950ca8cSSamuel Holland _val; \
397c950ca8cSSamuel Holland })
398c950ca8cSSamuel Holland
sun50i_a64_read_cntpct_el0(void)399c950ca8cSSamuel Holland static u64 notrace sun50i_a64_read_cntpct_el0(void)
400c950ca8cSSamuel Holland {
401c950ca8cSSamuel Holland return __sun50i_a64_read_reg(cntpct_el0);
402c950ca8cSSamuel Holland }
403c950ca8cSSamuel Holland
sun50i_a64_read_cntvct_el0(void)404c950ca8cSSamuel Holland static u64 notrace sun50i_a64_read_cntvct_el0(void)
405c950ca8cSSamuel Holland {
406c950ca8cSSamuel Holland return __sun50i_a64_read_reg(cntvct_el0);
407c950ca8cSSamuel Holland }
408c950ca8cSSamuel Holland #endif
409c950ca8cSSamuel Holland
41016d10ef2SDing Tianhong #ifdef CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND
411a7fb4577SMark Rutland DEFINE_PER_CPU(const struct arch_timer_erratum_workaround *, timer_unstable_counter_workaround);
41216d10ef2SDing Tianhong EXPORT_SYMBOL_GPL(timer_unstable_counter_workaround);
41316d10ef2SDing Tianhong
4140ea41539SMarc Zyngier static atomic_t timer_unstable_counter_workaround_in_use = ATOMIC_INIT(0);
41516d10ef2SDing Tianhong
4161edb7e74SMarc Zyngier /*
4171edb7e74SMarc Zyngier * Force the inlining of this function so that the register accesses
4181edb7e74SMarc Zyngier * can be themselves correctly inlined.
4191edb7e74SMarc Zyngier */
4201edb7e74SMarc Zyngier static __always_inline
erratum_set_next_event_generic(const int access,unsigned long evt,struct clock_event_device * clk)4211edb7e74SMarc Zyngier void erratum_set_next_event_generic(const int access, unsigned long evt,
4228328089fSMarc Zyngier struct clock_event_device *clk)
4238328089fSMarc Zyngier {
4248328089fSMarc Zyngier unsigned long ctrl;
425e6d68b00SChristoffer Dall u64 cval;
4268328089fSMarc Zyngier
4278328089fSMarc Zyngier ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL, clk);
4288328089fSMarc Zyngier ctrl |= ARCH_TIMER_CTRL_ENABLE;
4298328089fSMarc Zyngier ctrl &= ~ARCH_TIMER_CTRL_IT_MASK;
4308328089fSMarc Zyngier
431e6d68b00SChristoffer Dall if (access == ARCH_TIMER_PHYS_ACCESS) {
432d8cc3905SKeqian Zhu cval = evt + arch_counter_get_cntpct_stable();
4338328089fSMarc Zyngier write_sysreg(cval, cntp_cval_el0);
434e6d68b00SChristoffer Dall } else {
435d8cc3905SKeqian Zhu cval = evt + arch_counter_get_cntvct_stable();
4368328089fSMarc Zyngier write_sysreg(cval, cntv_cval_el0);
437e6d68b00SChristoffer Dall }
4388328089fSMarc Zyngier
4398328089fSMarc Zyngier arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk);
4408328089fSMarc Zyngier }
4418328089fSMarc Zyngier
erratum_set_next_event_virt(unsigned long evt,struct clock_event_device * clk)442ac9ef4f2SMarc Zyngier static __maybe_unused int erratum_set_next_event_virt(unsigned long evt,
4438328089fSMarc Zyngier struct clock_event_device *clk)
4448328089fSMarc Zyngier {
445ac9ef4f2SMarc Zyngier erratum_set_next_event_generic(ARCH_TIMER_VIRT_ACCESS, evt, clk);
4468328089fSMarc Zyngier return 0;
4478328089fSMarc Zyngier }
4488328089fSMarc Zyngier
erratum_set_next_event_phys(unsigned long evt,struct clock_event_device * clk)449ac9ef4f2SMarc Zyngier static __maybe_unused int erratum_set_next_event_phys(unsigned long evt,
4508328089fSMarc Zyngier struct clock_event_device *clk)
4518328089fSMarc Zyngier {
452ac9ef4f2SMarc Zyngier erratum_set_next_event_generic(ARCH_TIMER_PHYS_ACCESS, evt, clk);
4538328089fSMarc Zyngier return 0;
4548328089fSMarc Zyngier }
4558328089fSMarc Zyngier
45616d10ef2SDing Tianhong static const struct arch_timer_erratum_workaround ool_workarounds[] = {
45716d10ef2SDing Tianhong #ifdef CONFIG_FSL_ERRATUM_A008585
45816d10ef2SDing Tianhong {
459651bb2e9SMarc Zyngier .match_type = ate_match_dt,
46016d10ef2SDing Tianhong .id = "fsl,erratum-a008585",
461651bb2e9SMarc Zyngier .desc = "Freescale erratum a005858",
462f2e600c1SChristoffer Dall .read_cntpct_el0 = fsl_a008585_read_cntpct_el0,
46316d10ef2SDing Tianhong .read_cntvct_el0 = fsl_a008585_read_cntvct_el0,
464ac9ef4f2SMarc Zyngier .set_next_event_phys = erratum_set_next_event_phys,
465ac9ef4f2SMarc Zyngier .set_next_event_virt = erratum_set_next_event_virt,
46616d10ef2SDing Tianhong },
46716d10ef2SDing Tianhong #endif
468bb42ca47SDing Tianhong #ifdef CONFIG_HISILICON_ERRATUM_161010101
469bb42ca47SDing Tianhong {
470651bb2e9SMarc Zyngier .match_type = ate_match_dt,
471bb42ca47SDing Tianhong .id = "hisilicon,erratum-161010101",
472651bb2e9SMarc Zyngier .desc = "HiSilicon erratum 161010101",
473f2e600c1SChristoffer Dall .read_cntpct_el0 = hisi_161010101_read_cntpct_el0,
474bb42ca47SDing Tianhong .read_cntvct_el0 = hisi_161010101_read_cntvct_el0,
475ac9ef4f2SMarc Zyngier .set_next_event_phys = erratum_set_next_event_phys,
476ac9ef4f2SMarc Zyngier .set_next_event_virt = erratum_set_next_event_virt,
477bb42ca47SDing Tianhong },
478d003d029SMarc Zyngier {
479d003d029SMarc Zyngier .match_type = ate_match_acpi_oem_info,
480d003d029SMarc Zyngier .id = hisi_161010101_oem_info,
481d003d029SMarc Zyngier .desc = "HiSilicon erratum 161010101",
482f2e600c1SChristoffer Dall .read_cntpct_el0 = hisi_161010101_read_cntpct_el0,
483d003d029SMarc Zyngier .read_cntvct_el0 = hisi_161010101_read_cntvct_el0,
484ac9ef4f2SMarc Zyngier .set_next_event_phys = erratum_set_next_event_phys,
485ac9ef4f2SMarc Zyngier .set_next_event_virt = erratum_set_next_event_virt,
486d003d029SMarc Zyngier },
487bb42ca47SDing Tianhong #endif
488fa8d815fSMarc Zyngier #ifdef CONFIG_ARM64_ERRATUM_858921
489fa8d815fSMarc Zyngier {
490fa8d815fSMarc Zyngier .match_type = ate_match_local_cap_id,
491fa8d815fSMarc Zyngier .id = (void *)ARM64_WORKAROUND_858921,
492fa8d815fSMarc Zyngier .desc = "ARM erratum 858921",
493f2e600c1SChristoffer Dall .read_cntpct_el0 = arm64_858921_read_cntpct_el0,
494fa8d815fSMarc Zyngier .read_cntvct_el0 = arm64_858921_read_cntvct_el0,
4956c3b62d9SKunkun Jiang .set_next_event_phys = erratum_set_next_event_phys,
4966c3b62d9SKunkun Jiang .set_next_event_virt = erratum_set_next_event_virt,
497fa8d815fSMarc Zyngier },
498fa8d815fSMarc Zyngier #endif
499c950ca8cSSamuel Holland #ifdef CONFIG_SUN50I_ERRATUM_UNKNOWN1
500c950ca8cSSamuel Holland {
501c950ca8cSSamuel Holland .match_type = ate_match_dt,
502c950ca8cSSamuel Holland .id = "allwinner,erratum-unknown1",
503c950ca8cSSamuel Holland .desc = "Allwinner erratum UNKNOWN1",
504c950ca8cSSamuel Holland .read_cntpct_el0 = sun50i_a64_read_cntpct_el0,
505c950ca8cSSamuel Holland .read_cntvct_el0 = sun50i_a64_read_cntvct_el0,
506ac9ef4f2SMarc Zyngier .set_next_event_phys = erratum_set_next_event_phys,
507ac9ef4f2SMarc Zyngier .set_next_event_virt = erratum_set_next_event_virt,
508c950ca8cSSamuel Holland },
509c950ca8cSSamuel Holland #endif
5104b661d61SMarc Zyngier #ifdef CONFIG_ARM64_ERRATUM_1418040
5114b661d61SMarc Zyngier {
5124b661d61SMarc Zyngier .match_type = ate_match_local_cap_id,
5134b661d61SMarc Zyngier .id = (void *)ARM64_WORKAROUND_1418040,
5144b661d61SMarc Zyngier .desc = "ARM erratum 1418040",
5154b661d61SMarc Zyngier .disable_compat_vdso = true,
5164b661d61SMarc Zyngier },
5174b661d61SMarc Zyngier #endif
51816d10ef2SDing Tianhong };
519651bb2e9SMarc Zyngier
520651bb2e9SMarc Zyngier typedef bool (*ate_match_fn_t)(const struct arch_timer_erratum_workaround *,
521651bb2e9SMarc Zyngier const void *);
522651bb2e9SMarc Zyngier
523651bb2e9SMarc Zyngier static
arch_timer_check_dt_erratum(const struct arch_timer_erratum_workaround * wa,const void * arg)524651bb2e9SMarc Zyngier bool arch_timer_check_dt_erratum(const struct arch_timer_erratum_workaround *wa,
525651bb2e9SMarc Zyngier const void *arg)
526651bb2e9SMarc Zyngier {
527651bb2e9SMarc Zyngier const struct device_node *np = arg;
528651bb2e9SMarc Zyngier
529651bb2e9SMarc Zyngier return of_property_read_bool(np, wa->id);
530651bb2e9SMarc Zyngier }
531651bb2e9SMarc Zyngier
5320064030cSMarc Zyngier static
arch_timer_check_local_cap_erratum(const struct arch_timer_erratum_workaround * wa,const void * arg)5330064030cSMarc Zyngier bool arch_timer_check_local_cap_erratum(const struct arch_timer_erratum_workaround *wa,
5340064030cSMarc Zyngier const void *arg)
5350064030cSMarc Zyngier {
5360064030cSMarc Zyngier return this_cpu_has_cap((uintptr_t)wa->id);
5370064030cSMarc Zyngier }
5380064030cSMarc Zyngier
5395a38bcacSMarc Zyngier
5405a38bcacSMarc Zyngier static
arch_timer_check_acpi_oem_erratum(const struct arch_timer_erratum_workaround * wa,const void * arg)5415a38bcacSMarc Zyngier bool arch_timer_check_acpi_oem_erratum(const struct arch_timer_erratum_workaround *wa,
5425a38bcacSMarc Zyngier const void *arg)
5435a38bcacSMarc Zyngier {
5445a38bcacSMarc Zyngier static const struct ate_acpi_oem_info empty_oem_info = {};
5455a38bcacSMarc Zyngier const struct ate_acpi_oem_info *info = wa->id;
5465a38bcacSMarc Zyngier const struct acpi_table_header *table = arg;
5475a38bcacSMarc Zyngier
5485a38bcacSMarc Zyngier /* Iterate over the ACPI OEM info array, looking for a match */
5495a38bcacSMarc Zyngier while (memcmp(info, &empty_oem_info, sizeof(*info))) {
5505a38bcacSMarc Zyngier if (!memcmp(info->oem_id, table->oem_id, ACPI_OEM_ID_SIZE) &&
5515a38bcacSMarc Zyngier !memcmp(info->oem_table_id, table->oem_table_id, ACPI_OEM_TABLE_ID_SIZE) &&
5525a38bcacSMarc Zyngier info->oem_revision == table->oem_revision)
5535a38bcacSMarc Zyngier return true;
5545a38bcacSMarc Zyngier
5555a38bcacSMarc Zyngier info++;
5565a38bcacSMarc Zyngier }
5575a38bcacSMarc Zyngier
5585a38bcacSMarc Zyngier return false;
5595a38bcacSMarc Zyngier }
5605a38bcacSMarc Zyngier
561651bb2e9SMarc Zyngier static const struct arch_timer_erratum_workaround *
arch_timer_iterate_errata(enum arch_timer_erratum_match_type type,ate_match_fn_t match_fn,void * arg)562651bb2e9SMarc Zyngier arch_timer_iterate_errata(enum arch_timer_erratum_match_type type,
563651bb2e9SMarc Zyngier ate_match_fn_t match_fn,
564651bb2e9SMarc Zyngier void *arg)
565651bb2e9SMarc Zyngier {
566651bb2e9SMarc Zyngier int i;
567651bb2e9SMarc Zyngier
568651bb2e9SMarc Zyngier for (i = 0; i < ARRAY_SIZE(ool_workarounds); i++) {
569651bb2e9SMarc Zyngier if (ool_workarounds[i].match_type != type)
570651bb2e9SMarc Zyngier continue;
571651bb2e9SMarc Zyngier
572651bb2e9SMarc Zyngier if (match_fn(&ool_workarounds[i], arg))
573651bb2e9SMarc Zyngier return &ool_workarounds[i];
574651bb2e9SMarc Zyngier }
575651bb2e9SMarc Zyngier
576651bb2e9SMarc Zyngier return NULL;
577651bb2e9SMarc Zyngier }
578651bb2e9SMarc Zyngier
579651bb2e9SMarc Zyngier static
arch_timer_enable_workaround(const struct arch_timer_erratum_workaround * wa,bool local)5806acc71ccSMarc Zyngier void arch_timer_enable_workaround(const struct arch_timer_erratum_workaround *wa,
5816acc71ccSMarc Zyngier bool local)
582651bb2e9SMarc Zyngier {
5836acc71ccSMarc Zyngier int i;
5846acc71ccSMarc Zyngier
5856acc71ccSMarc Zyngier if (local) {
5866acc71ccSMarc Zyngier __this_cpu_write(timer_unstable_counter_workaround, wa);
5876acc71ccSMarc Zyngier } else {
5886acc71ccSMarc Zyngier for_each_possible_cpu(i)
5896acc71ccSMarc Zyngier per_cpu(timer_unstable_counter_workaround, i) = wa;
5906acc71ccSMarc Zyngier }
5916acc71ccSMarc Zyngier
5920ea41539SMarc Zyngier if (wa->read_cntvct_el0 || wa->read_cntpct_el0)
5930ea41539SMarc Zyngier atomic_set(&timer_unstable_counter_workaround_in_use, 1);
594a86bd139SMarc Zyngier
595a86bd139SMarc Zyngier /*
596a86bd139SMarc Zyngier * Don't use the vdso fastpath if errata require using the
597a86bd139SMarc Zyngier * out-of-line counter accessor. We may change our mind pretty
598a86bd139SMarc Zyngier * late in the game (with a per-CPU erratum, for example), so
599a86bd139SMarc Zyngier * change both the default value and the vdso itself.
600a86bd139SMarc Zyngier */
601a86bd139SMarc Zyngier if (wa->read_cntvct_el0) {
6025e3c6a31SThomas Gleixner clocksource_counter.vdso_clock_mode = VDSO_CLOCKMODE_NONE;
6035e3c6a31SThomas Gleixner vdso_default = VDSO_CLOCKMODE_NONE;
604c1fbec4aSMarc Zyngier } else if (wa->disable_compat_vdso && vdso_default != VDSO_CLOCKMODE_NONE) {
605c1fbec4aSMarc Zyngier vdso_default = VDSO_CLOCKMODE_ARCHTIMER_NOCOMPAT;
606c1fbec4aSMarc Zyngier clocksource_counter.vdso_clock_mode = vdso_default;
607a86bd139SMarc Zyngier }
608651bb2e9SMarc Zyngier }
609651bb2e9SMarc Zyngier
arch_timer_check_ool_workaround(enum arch_timer_erratum_match_type type,void * arg)610651bb2e9SMarc Zyngier static void arch_timer_check_ool_workaround(enum arch_timer_erratum_match_type type,
611651bb2e9SMarc Zyngier void *arg)
612651bb2e9SMarc Zyngier {
613a862fc22SMarc Zyngier const struct arch_timer_erratum_workaround *wa, *__wa;
614651bb2e9SMarc Zyngier ate_match_fn_t match_fn = NULL;
6150064030cSMarc Zyngier bool local = false;
616651bb2e9SMarc Zyngier
617651bb2e9SMarc Zyngier switch (type) {
618651bb2e9SMarc Zyngier case ate_match_dt:
619651bb2e9SMarc Zyngier match_fn = arch_timer_check_dt_erratum;
620651bb2e9SMarc Zyngier break;
6210064030cSMarc Zyngier case ate_match_local_cap_id:
6220064030cSMarc Zyngier match_fn = arch_timer_check_local_cap_erratum;
6230064030cSMarc Zyngier local = true;
6240064030cSMarc Zyngier break;
6255a38bcacSMarc Zyngier case ate_match_acpi_oem_info:
6265a38bcacSMarc Zyngier match_fn = arch_timer_check_acpi_oem_erratum;
6275a38bcacSMarc Zyngier break;
628651bb2e9SMarc Zyngier default:
629651bb2e9SMarc Zyngier WARN_ON(1);
630651bb2e9SMarc Zyngier return;
631651bb2e9SMarc Zyngier }
632651bb2e9SMarc Zyngier
633651bb2e9SMarc Zyngier wa = arch_timer_iterate_errata(type, match_fn, arg);
634651bb2e9SMarc Zyngier if (!wa)
635651bb2e9SMarc Zyngier return;
636651bb2e9SMarc Zyngier
6376acc71ccSMarc Zyngier __wa = __this_cpu_read(timer_unstable_counter_workaround);
6386acc71ccSMarc Zyngier if (__wa && wa != __wa)
6390064030cSMarc Zyngier pr_warn("Can't enable workaround for %s (clashes with %s\n)",
6406acc71ccSMarc Zyngier wa->desc, __wa->desc);
6416acc71ccSMarc Zyngier
6426acc71ccSMarc Zyngier if (__wa)
6430064030cSMarc Zyngier return;
6440064030cSMarc Zyngier
6456acc71ccSMarc Zyngier arch_timer_enable_workaround(wa, local);
6460064030cSMarc Zyngier pr_info("Enabling %s workaround for %s\n",
6470064030cSMarc Zyngier local ? "local" : "global", wa->desc);
648651bb2e9SMarc Zyngier }
649651bb2e9SMarc Zyngier
arch_timer_this_cpu_has_cntvct_wa(void)650a86bd139SMarc Zyngier static bool arch_timer_this_cpu_has_cntvct_wa(void)
651a86bd139SMarc Zyngier {
6525ef19a16SMarc Zyngier return has_erratum_handler(read_cntvct_el0);
653a86bd139SMarc Zyngier }
6546acc71ccSMarc Zyngier
arch_timer_counter_has_wa(void)6550ea41539SMarc Zyngier static bool arch_timer_counter_has_wa(void)
6560ea41539SMarc Zyngier {
6570ea41539SMarc Zyngier return atomic_read(&timer_unstable_counter_workaround_in_use);
65801d3e3ffSMarc Zyngier }
659651bb2e9SMarc Zyngier #else
660651bb2e9SMarc Zyngier #define arch_timer_check_ool_workaround(t,a) do { } while(0)
661a86bd139SMarc Zyngier #define arch_timer_this_cpu_has_cntvct_wa() ({false;})
6620ea41539SMarc Zyngier #define arch_timer_counter_has_wa() ({false;})
66316d10ef2SDing Tianhong #endif /* CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND */
664f6dc1576SScott Wood
timer_handler(const int access,struct clock_event_device * evt)665e09f3cc0SStephen Boyd static __always_inline irqreturn_t timer_handler(const int access,
6668a4da6e3SMark Rutland struct clock_event_device *evt)
6678a4da6e3SMark Rutland {
6688a4da6e3SMark Rutland unsigned long ctrl;
669cfb6d656SThomas Gleixner
67060faddf6SStephen Boyd ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL, evt);
6718a4da6e3SMark Rutland if (ctrl & ARCH_TIMER_CTRL_IT_STAT) {
6728a4da6e3SMark Rutland ctrl |= ARCH_TIMER_CTRL_IT_MASK;
67360faddf6SStephen Boyd arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, evt);
6748a4da6e3SMark Rutland evt->event_handler(evt);
6758a4da6e3SMark Rutland return IRQ_HANDLED;
6768a4da6e3SMark Rutland }
6778a4da6e3SMark Rutland
6788a4da6e3SMark Rutland return IRQ_NONE;
6798a4da6e3SMark Rutland }
6808a4da6e3SMark Rutland
arch_timer_handler_virt(int irq,void * dev_id)6818a4da6e3SMark Rutland static irqreturn_t arch_timer_handler_virt(int irq, void *dev_id)
6828a4da6e3SMark Rutland {
6838a4da6e3SMark Rutland struct clock_event_device *evt = dev_id;
6848a4da6e3SMark Rutland
6858a4da6e3SMark Rutland return timer_handler(ARCH_TIMER_VIRT_ACCESS, evt);
6868a4da6e3SMark Rutland }
6878a4da6e3SMark Rutland
arch_timer_handler_phys(int irq,void * dev_id)6888a4da6e3SMark Rutland static irqreturn_t arch_timer_handler_phys(int irq, void *dev_id)
6898a4da6e3SMark Rutland {
6908a4da6e3SMark Rutland struct clock_event_device *evt = dev_id;
6918a4da6e3SMark Rutland
6928a4da6e3SMark Rutland return timer_handler(ARCH_TIMER_PHYS_ACCESS, evt);
6938a4da6e3SMark Rutland }
6948a4da6e3SMark Rutland
arch_timer_handler_phys_mem(int irq,void * dev_id)69522006994SStephen Boyd static irqreturn_t arch_timer_handler_phys_mem(int irq, void *dev_id)
69622006994SStephen Boyd {
69722006994SStephen Boyd struct clock_event_device *evt = dev_id;
69822006994SStephen Boyd
69922006994SStephen Boyd return timer_handler(ARCH_TIMER_MEM_PHYS_ACCESS, evt);
70022006994SStephen Boyd }
70122006994SStephen Boyd
arch_timer_handler_virt_mem(int irq,void * dev_id)70222006994SStephen Boyd static irqreturn_t arch_timer_handler_virt_mem(int irq, void *dev_id)
70322006994SStephen Boyd {
70422006994SStephen Boyd struct clock_event_device *evt = dev_id;
70522006994SStephen Boyd
70622006994SStephen Boyd return timer_handler(ARCH_TIMER_MEM_VIRT_ACCESS, evt);
70722006994SStephen Boyd }
70822006994SStephen Boyd
arch_timer_shutdown(const int access,struct clock_event_device * clk)70973737a58SSteven Rostedt (Google) static __always_inline int arch_timer_shutdown(const int access,
71060faddf6SStephen Boyd struct clock_event_device *clk)
7118a4da6e3SMark Rutland {
7128a4da6e3SMark Rutland unsigned long ctrl;
71346c5bfddSViresh Kumar
71460faddf6SStephen Boyd ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL, clk);
7158a4da6e3SMark Rutland ctrl &= ~ARCH_TIMER_CTRL_ENABLE;
71660faddf6SStephen Boyd arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk);
71746c5bfddSViresh Kumar
71846c5bfddSViresh Kumar return 0;
7198a4da6e3SMark Rutland }
7208a4da6e3SMark Rutland
arch_timer_shutdown_virt(struct clock_event_device * clk)72146c5bfddSViresh Kumar static int arch_timer_shutdown_virt(struct clock_event_device *clk)
7228a4da6e3SMark Rutland {
72373737a58SSteven Rostedt (Google) return arch_timer_shutdown(ARCH_TIMER_VIRT_ACCESS, clk);
7248a4da6e3SMark Rutland }
7258a4da6e3SMark Rutland
arch_timer_shutdown_phys(struct clock_event_device * clk)72646c5bfddSViresh Kumar static int arch_timer_shutdown_phys(struct clock_event_device *clk)
7278a4da6e3SMark Rutland {
72873737a58SSteven Rostedt (Google) return arch_timer_shutdown(ARCH_TIMER_PHYS_ACCESS, clk);
7298a4da6e3SMark Rutland }
7308a4da6e3SMark Rutland
arch_timer_shutdown_virt_mem(struct clock_event_device * clk)73146c5bfddSViresh Kumar static int arch_timer_shutdown_virt_mem(struct clock_event_device *clk)
73222006994SStephen Boyd {
73373737a58SSteven Rostedt (Google) return arch_timer_shutdown(ARCH_TIMER_MEM_VIRT_ACCESS, clk);
73422006994SStephen Boyd }
73522006994SStephen Boyd
arch_timer_shutdown_phys_mem(struct clock_event_device * clk)73646c5bfddSViresh Kumar static int arch_timer_shutdown_phys_mem(struct clock_event_device *clk)
73722006994SStephen Boyd {
73873737a58SSteven Rostedt (Google) return arch_timer_shutdown(ARCH_TIMER_MEM_PHYS_ACCESS, clk);
73922006994SStephen Boyd }
74022006994SStephen Boyd
set_next_event(const int access,unsigned long evt,struct clock_event_device * clk)74160faddf6SStephen Boyd static __always_inline void set_next_event(const int access, unsigned long evt,
74260faddf6SStephen Boyd struct clock_event_device *clk)
7438a4da6e3SMark Rutland {
7448a4da6e3SMark Rutland unsigned long ctrl;
745a38b71b0SMarc Zyngier u64 cnt;
746a38b71b0SMarc Zyngier
74760faddf6SStephen Boyd ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL, clk);
7488a4da6e3SMark Rutland ctrl |= ARCH_TIMER_CTRL_ENABLE;
7498a4da6e3SMark Rutland ctrl &= ~ARCH_TIMER_CTRL_IT_MASK;
750a38b71b0SMarc Zyngier
751a38b71b0SMarc Zyngier if (access == ARCH_TIMER_PHYS_ACCESS)
752a38b71b0SMarc Zyngier cnt = __arch_counter_get_cntpct();
753a38b71b0SMarc Zyngier else
754a38b71b0SMarc Zyngier cnt = __arch_counter_get_cntvct();
755a38b71b0SMarc Zyngier
756a38b71b0SMarc Zyngier arch_timer_reg_write(access, ARCH_TIMER_REG_CVAL, evt + cnt, clk);
75760faddf6SStephen Boyd arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk);
7588a4da6e3SMark Rutland }
7598a4da6e3SMark Rutland
arch_timer_set_next_event_virt(unsigned long evt,struct clock_event_device * clk)7608a4da6e3SMark Rutland static int arch_timer_set_next_event_virt(unsigned long evt,
76160faddf6SStephen Boyd struct clock_event_device *clk)
7628a4da6e3SMark Rutland {
76360faddf6SStephen Boyd set_next_event(ARCH_TIMER_VIRT_ACCESS, evt, clk);
7648a4da6e3SMark Rutland return 0;
7658a4da6e3SMark Rutland }
7668a4da6e3SMark Rutland
arch_timer_set_next_event_phys(unsigned long evt,struct clock_event_device * clk)7678a4da6e3SMark Rutland static int arch_timer_set_next_event_phys(unsigned long evt,
76860faddf6SStephen Boyd struct clock_event_device *clk)
7698a4da6e3SMark Rutland {
77060faddf6SStephen Boyd set_next_event(ARCH_TIMER_PHYS_ACCESS, evt, clk);
7718a4da6e3SMark Rutland return 0;
7728a4da6e3SMark Rutland }
7738a4da6e3SMark Rutland
arch_counter_get_cnt_mem(struct arch_timer * t,int offset_lo)77424ee7607SPeter Zijlstra static noinstr u64 arch_counter_get_cnt_mem(struct arch_timer *t, int offset_lo)
7758b82c4f8SMarc Zyngier {
7768b82c4f8SMarc Zyngier u32 cnt_lo, cnt_hi, tmp_hi;
7778b82c4f8SMarc Zyngier
7788b82c4f8SMarc Zyngier do {
7795416bf1cSPeter Zijlstra cnt_hi = __le32_to_cpu((__le32 __force)__raw_readl(t->base + offset_lo + 4));
7805416bf1cSPeter Zijlstra cnt_lo = __le32_to_cpu((__le32 __force)__raw_readl(t->base + offset_lo));
7815416bf1cSPeter Zijlstra tmp_hi = __le32_to_cpu((__le32 __force)__raw_readl(t->base + offset_lo + 4));
7828b82c4f8SMarc Zyngier } while (cnt_hi != tmp_hi);
7838b82c4f8SMarc Zyngier
7848b82c4f8SMarc Zyngier return ((u64) cnt_hi << 32) | cnt_lo;
7858b82c4f8SMarc Zyngier }
7868b82c4f8SMarc Zyngier
set_next_event_mem(const int access,unsigned long evt,struct clock_event_device * clk)787a38b71b0SMarc Zyngier static __always_inline void set_next_event_mem(const int access, unsigned long evt,
788a38b71b0SMarc Zyngier struct clock_event_device *clk)
789a38b71b0SMarc Zyngier {
7908b82c4f8SMarc Zyngier struct arch_timer *timer = to_arch_timer(clk);
791a38b71b0SMarc Zyngier unsigned long ctrl;
7928b82c4f8SMarc Zyngier u64 cnt;
7938b82c4f8SMarc Zyngier
794a38b71b0SMarc Zyngier ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL, clk);
795e7d65e40SWalter Chang
796e7d65e40SWalter Chang /* Timer must be disabled before programming CVAL */
797e7d65e40SWalter Chang if (ctrl & ARCH_TIMER_CTRL_ENABLE) {
798e7d65e40SWalter Chang ctrl &= ~ARCH_TIMER_CTRL_ENABLE;
799e7d65e40SWalter Chang arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk);
800e7d65e40SWalter Chang }
801e7d65e40SWalter Chang
802a38b71b0SMarc Zyngier ctrl |= ARCH_TIMER_CTRL_ENABLE;
803a38b71b0SMarc Zyngier ctrl &= ~ARCH_TIMER_CTRL_IT_MASK;
804a38b71b0SMarc Zyngier
8058b82c4f8SMarc Zyngier if (access == ARCH_TIMER_MEM_VIRT_ACCESS)
8068b82c4f8SMarc Zyngier cnt = arch_counter_get_cnt_mem(timer, CNTVCT_LO);
8078b82c4f8SMarc Zyngier else
8088b82c4f8SMarc Zyngier cnt = arch_counter_get_cnt_mem(timer, CNTPCT_LO);
8098b82c4f8SMarc Zyngier
8108b82c4f8SMarc Zyngier arch_timer_reg_write(access, ARCH_TIMER_REG_CVAL, evt + cnt, clk);
811a38b71b0SMarc Zyngier arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk);
812a38b71b0SMarc Zyngier }
813a38b71b0SMarc Zyngier
arch_timer_set_next_event_virt_mem(unsigned long evt,struct clock_event_device * clk)81422006994SStephen Boyd static int arch_timer_set_next_event_virt_mem(unsigned long evt,
81522006994SStephen Boyd struct clock_event_device *clk)
8168a4da6e3SMark Rutland {
817a38b71b0SMarc Zyngier set_next_event_mem(ARCH_TIMER_MEM_VIRT_ACCESS, evt, clk);
81822006994SStephen Boyd return 0;
81922006994SStephen Boyd }
82022006994SStephen Boyd
arch_timer_set_next_event_phys_mem(unsigned long evt,struct clock_event_device * clk)82122006994SStephen Boyd static int arch_timer_set_next_event_phys_mem(unsigned long evt,
82222006994SStephen Boyd struct clock_event_device *clk)
82322006994SStephen Boyd {
824a38b71b0SMarc Zyngier set_next_event_mem(ARCH_TIMER_MEM_PHYS_ACCESS, evt, clk);
82522006994SStephen Boyd return 0;
82622006994SStephen Boyd }
82722006994SStephen Boyd
__arch_timer_check_delta(void)828012f1885SMarc Zyngier static u64 __arch_timer_check_delta(void)
829012f1885SMarc Zyngier {
830012f1885SMarc Zyngier #ifdef CONFIG_ARM64
831012f1885SMarc Zyngier const struct midr_range broken_cval_midrs[] = {
832012f1885SMarc Zyngier /*
833012f1885SMarc Zyngier * XGene-1 implements CVAL in terms of TVAL, meaning
834012f1885SMarc Zyngier * that the maximum timer range is 32bit. Shame on them.
835839a9739SJoe Korty *
836839a9739SJoe Korty * Note that TVAL is signed, thus has only 31 of its
837839a9739SJoe Korty * 32 bits to express magnitude.
838012f1885SMarc Zyngier */
839851354cbSAndre Przywara MIDR_REV_RANGE(MIDR_CPU_MODEL(ARM_CPU_IMP_APM,
840851354cbSAndre Przywara APM_CPU_PART_XGENE),
841851354cbSAndre Przywara APM_CPU_VAR_POTENZA, 0x0, 0xf),
842012f1885SMarc Zyngier {},
843012f1885SMarc Zyngier };
844012f1885SMarc Zyngier
845*e3121298SShameer Kolothum if (is_midr_in_range_list(broken_cval_midrs)) {
846839a9739SJoe Korty pr_warn_once("Broken CNTx_CVAL_EL1, using 31 bit TVAL instead.\n");
847839a9739SJoe Korty return CLOCKSOURCE_MASK(31);
848012f1885SMarc Zyngier }
849012f1885SMarc Zyngier #endif
850c1153d52SOliver Upton return CLOCKSOURCE_MASK(arch_counter_get_width());
851012f1885SMarc Zyngier }
852012f1885SMarc Zyngier
__arch_timer_setup(unsigned type,struct clock_event_device * clk)853cfb6d656SThomas Gleixner static void __arch_timer_setup(unsigned type,
85422006994SStephen Boyd struct clock_event_device *clk)
85522006994SStephen Boyd {
856012f1885SMarc Zyngier u64 max_delta;
857012f1885SMarc Zyngier
85822006994SStephen Boyd clk->features = CLOCK_EVT_FEAT_ONESHOT;
85922006994SStephen Boyd
8608a5c21dcSFu Wei if (type == ARCH_TIMER_TYPE_CP15) {
8615ef19a16SMarc Zyngier typeof(clk->set_next_event) sne;
8625ef19a16SMarc Zyngier
8635ef19a16SMarc Zyngier arch_timer_check_ool_workaround(ate_match_local_cap_id, NULL);
8645ef19a16SMarc Zyngier
86582a56194SLorenzo Pieralisi if (arch_timer_c3stop)
86622006994SStephen Boyd clk->features |= CLOCK_EVT_FEAT_C3STOP;
8678a4da6e3SMark Rutland clk->name = "arch_sys_timer";
8688a4da6e3SMark Rutland clk->rating = 450;
86922006994SStephen Boyd clk->cpumask = cpumask_of(smp_processor_id());
870f81f03faSMarc Zyngier clk->irq = arch_timer_ppi[arch_timer_uses_ppi];
871f81f03faSMarc Zyngier switch (arch_timer_uses_ppi) {
872ee34f1e6SFu Wei case ARCH_TIMER_VIRT_PPI:
87346c5bfddSViresh Kumar clk->set_state_shutdown = arch_timer_shutdown_virt;
874cf8c5009SViresh Kumar clk->set_state_oneshot_stopped = arch_timer_shutdown_virt;
8755ef19a16SMarc Zyngier sne = erratum_handler(set_next_event_virt);
876f81f03faSMarc Zyngier break;
877ee34f1e6SFu Wei case ARCH_TIMER_PHYS_SECURE_PPI:
878ee34f1e6SFu Wei case ARCH_TIMER_PHYS_NONSECURE_PPI:
879ee34f1e6SFu Wei case ARCH_TIMER_HYP_PPI:
88046c5bfddSViresh Kumar clk->set_state_shutdown = arch_timer_shutdown_phys;
881cf8c5009SViresh Kumar clk->set_state_oneshot_stopped = arch_timer_shutdown_phys;
8825ef19a16SMarc Zyngier sne = erratum_handler(set_next_event_phys);
883f81f03faSMarc Zyngier break;
884f81f03faSMarc Zyngier default:
885f81f03faSMarc Zyngier BUG();
8868a4da6e3SMark Rutland }
887f6dc1576SScott Wood
8885ef19a16SMarc Zyngier clk->set_next_event = sne;
889012f1885SMarc Zyngier max_delta = __arch_timer_check_delta();
89022006994SStephen Boyd } else {
8917b52ad2eSStephen Boyd clk->features |= CLOCK_EVT_FEAT_DYNIRQ;
89222006994SStephen Boyd clk->name = "arch_mem_timer";
89322006994SStephen Boyd clk->rating = 400;
8945e18e412SSudeep Holla clk->cpumask = cpu_possible_mask;
89522006994SStephen Boyd if (arch_timer_mem_use_virtual) {
89646c5bfddSViresh Kumar clk->set_state_shutdown = arch_timer_shutdown_virt_mem;
897cf8c5009SViresh Kumar clk->set_state_oneshot_stopped = arch_timer_shutdown_virt_mem;
89822006994SStephen Boyd clk->set_next_event =
89922006994SStephen Boyd arch_timer_set_next_event_virt_mem;
90022006994SStephen Boyd } else {
90146c5bfddSViresh Kumar clk->set_state_shutdown = arch_timer_shutdown_phys_mem;
902cf8c5009SViresh Kumar clk->set_state_oneshot_stopped = arch_timer_shutdown_phys_mem;
90322006994SStephen Boyd clk->set_next_event =
90422006994SStephen Boyd arch_timer_set_next_event_phys_mem;
90522006994SStephen Boyd }
906012f1885SMarc Zyngier
907012f1885SMarc Zyngier max_delta = CLOCKSOURCE_MASK(56);
90822006994SStephen Boyd }
9098a4da6e3SMark Rutland
91046c5bfddSViresh Kumar clk->set_state_shutdown(clk);
9118a4da6e3SMark Rutland
912012f1885SMarc Zyngier clockevents_config_and_register(clk, arch_timer_rate, 0xf, max_delta);
91322006994SStephen Boyd }
9148a4da6e3SMark Rutland
arch_timer_evtstrm_enable(unsigned int divider)9158c4b810aSMarc Zyngier static void arch_timer_evtstrm_enable(unsigned int divider)
916e1ce5c7aSNathan Lynch {
917e1ce5c7aSNathan Lynch u32 cntkctl = arch_timer_get_cntkctl();
918e1ce5c7aSNathan Lynch
9198c4b810aSMarc Zyngier #ifdef CONFIG_ARM64
9208c4b810aSMarc Zyngier /* ECV is likely to require a large divider. Use the EVNTIS flag. */
921166b76a0SMark Rutland if (cpus_have_final_cap(ARM64_HAS_ECV) && divider > 15) {
9228c4b810aSMarc Zyngier cntkctl |= ARCH_TIMER_EVT_INTERVAL_SCALE;
9238c4b810aSMarc Zyngier divider -= 8;
9248c4b810aSMarc Zyngier }
9258c4b810aSMarc Zyngier #endif
9268c4b810aSMarc Zyngier
9278c4b810aSMarc Zyngier divider = min(divider, 15U);
928e1ce5c7aSNathan Lynch cntkctl &= ~ARCH_TIMER_EVT_TRIGGER_MASK;
929e1ce5c7aSNathan Lynch /* Set the divider and enable virtual event stream */
930e1ce5c7aSNathan Lynch cntkctl |= (divider << ARCH_TIMER_EVT_TRIGGER_SHIFT)
931e1ce5c7aSNathan Lynch | ARCH_TIMER_VIRT_EVT_EN;
932e1ce5c7aSNathan Lynch arch_timer_set_cntkctl(cntkctl);
9335a354412SAndrew Murray arch_timer_set_evtstrm_feature();
934ec5c8e42SJulien Thierry cpumask_set_cpu(smp_processor_id(), &evtstrm_available);
935e1ce5c7aSNathan Lynch }
936e1ce5c7aSNathan Lynch
arch_timer_configure_evtstream(void)937037f6377SWill Deacon static void arch_timer_configure_evtstream(void)
938037f6377SWill Deacon {
9398b7770b8SKeqian Zhu int evt_stream_div, lsb;
940037f6377SWill Deacon
9418b7770b8SKeqian Zhu /*
9428b7770b8SKeqian Zhu * As the event stream can at most be generated at half the frequency
9438b7770b8SKeqian Zhu * of the counter, use half the frequency when computing the divider.
9448b7770b8SKeqian Zhu */
9458b7770b8SKeqian Zhu evt_stream_div = arch_timer_rate / ARCH_TIMER_EVT_STREAM_FREQ / 2;
9468b7770b8SKeqian Zhu
9478b7770b8SKeqian Zhu /*
9488b7770b8SKeqian Zhu * Find the closest power of two to the divisor. If the adjacent bit
9498b7770b8SKeqian Zhu * of lsb (last set bit, starts from 0) is set, then we use (lsb + 1).
9508b7770b8SKeqian Zhu */
9518b7770b8SKeqian Zhu lsb = fls(evt_stream_div) - 1;
9528b7770b8SKeqian Zhu if (lsb > 0 && (evt_stream_div & BIT(lsb - 1)))
9538b7770b8SKeqian Zhu lsb++;
9548b7770b8SKeqian Zhu
955037f6377SWill Deacon /* enable event stream */
9568c4b810aSMarc Zyngier arch_timer_evtstrm_enable(max(0, lsb));
957037f6377SWill Deacon }
958037f6377SWill Deacon
arch_timer_evtstrm_starting_cpu(unsigned int cpu)959166b76a0SMark Rutland static int arch_timer_evtstrm_starting_cpu(unsigned int cpu)
960166b76a0SMark Rutland {
961166b76a0SMark Rutland arch_timer_configure_evtstream();
962166b76a0SMark Rutland return 0;
963166b76a0SMark Rutland }
964166b76a0SMark Rutland
arch_timer_evtstrm_dying_cpu(unsigned int cpu)965166b76a0SMark Rutland static int arch_timer_evtstrm_dying_cpu(unsigned int cpu)
966166b76a0SMark Rutland {
967166b76a0SMark Rutland cpumask_clear_cpu(smp_processor_id(), &evtstrm_available);
968166b76a0SMark Rutland return 0;
969166b76a0SMark Rutland }
970166b76a0SMark Rutland
arch_timer_evtstrm_register(void)971166b76a0SMark Rutland static int __init arch_timer_evtstrm_register(void)
972166b76a0SMark Rutland {
973166b76a0SMark Rutland if (!arch_timer_evt || !evtstrm_enable)
974166b76a0SMark Rutland return 0;
975166b76a0SMark Rutland
976166b76a0SMark Rutland return cpuhp_setup_state(CPUHP_AP_ARM_ARCH_TIMER_EVTSTRM_STARTING,
977166b76a0SMark Rutland "clockevents/arm/arch_timer_evtstrm:starting",
978166b76a0SMark Rutland arch_timer_evtstrm_starting_cpu,
979166b76a0SMark Rutland arch_timer_evtstrm_dying_cpu);
980166b76a0SMark Rutland }
981166b76a0SMark Rutland core_initcall(arch_timer_evtstrm_register);
982166b76a0SMark Rutland
arch_counter_set_user_access(void)9838b8dde00SNathan Lynch static void arch_counter_set_user_access(void)
9848b8dde00SNathan Lynch {
9858b8dde00SNathan Lynch u32 cntkctl = arch_timer_get_cntkctl();
9868b8dde00SNathan Lynch
987a86bd139SMarc Zyngier /* Disable user access to the timers and both counters */
9888b8dde00SNathan Lynch /* Also disable virtual event stream */
9898b8dde00SNathan Lynch cntkctl &= ~(ARCH_TIMER_USR_PT_ACCESS_EN
9908b8dde00SNathan Lynch | ARCH_TIMER_USR_VT_ACCESS_EN
991a86bd139SMarc Zyngier | ARCH_TIMER_USR_VCT_ACCESS_EN
9928b8dde00SNathan Lynch | ARCH_TIMER_VIRT_EVT_EN
9938b8dde00SNathan Lynch | ARCH_TIMER_USR_PCT_ACCESS_EN);
9948b8dde00SNathan Lynch
995a86bd139SMarc Zyngier /*
996a86bd139SMarc Zyngier * Enable user access to the virtual counter if it doesn't
997a86bd139SMarc Zyngier * need to be workaround. The vdso may have been already
998a86bd139SMarc Zyngier * disabled though.
999a86bd139SMarc Zyngier */
1000a86bd139SMarc Zyngier if (arch_timer_this_cpu_has_cntvct_wa())
1001a86bd139SMarc Zyngier pr_info("CPU%d: Trapping CNTVCT access\n", smp_processor_id());
1002a86bd139SMarc Zyngier else
10038b8dde00SNathan Lynch cntkctl |= ARCH_TIMER_USR_VCT_ACCESS_EN;
10048b8dde00SNathan Lynch
10058b8dde00SNathan Lynch arch_timer_set_cntkctl(cntkctl);
10068b8dde00SNathan Lynch }
10078b8dde00SNathan Lynch
arch_timer_has_nonsecure_ppi(void)1008f81f03faSMarc Zyngier static bool arch_timer_has_nonsecure_ppi(void)
1009f81f03faSMarc Zyngier {
1010ee34f1e6SFu Wei return (arch_timer_uses_ppi == ARCH_TIMER_PHYS_SECURE_PPI &&
1011ee34f1e6SFu Wei arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI]);
1012f81f03faSMarc Zyngier }
1013f81f03faSMarc Zyngier
check_ppi_trigger(int irq)1014f005bd7eSMarc Zyngier static u32 check_ppi_trigger(int irq)
1015f005bd7eSMarc Zyngier {
1016f005bd7eSMarc Zyngier u32 flags = irq_get_trigger_type(irq);
1017f005bd7eSMarc Zyngier
1018f005bd7eSMarc Zyngier if (flags != IRQF_TRIGGER_HIGH && flags != IRQF_TRIGGER_LOW) {
1019f005bd7eSMarc Zyngier pr_warn("WARNING: Invalid trigger for IRQ%d, assuming level low\n", irq);
1020f005bd7eSMarc Zyngier pr_warn("WARNING: Please fix your firmware\n");
1021f005bd7eSMarc Zyngier flags = IRQF_TRIGGER_LOW;
1022f005bd7eSMarc Zyngier }
1023f005bd7eSMarc Zyngier
1024f005bd7eSMarc Zyngier return flags;
1025f005bd7eSMarc Zyngier }
1026f005bd7eSMarc Zyngier
arch_timer_starting_cpu(unsigned int cpu)10277e86e8bdSRichard Cochran static int arch_timer_starting_cpu(unsigned int cpu)
102822006994SStephen Boyd {
10297e86e8bdSRichard Cochran struct clock_event_device *clk = this_cpu_ptr(arch_timer_evt);
1030f005bd7eSMarc Zyngier u32 flags;
10317e86e8bdSRichard Cochran
10328a5c21dcSFu Wei __arch_timer_setup(ARCH_TIMER_TYPE_CP15, clk);
10338a4da6e3SMark Rutland
1034f005bd7eSMarc Zyngier flags = check_ppi_trigger(arch_timer_ppi[arch_timer_uses_ppi]);
1035f005bd7eSMarc Zyngier enable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], flags);
1036f81f03faSMarc Zyngier
1037f005bd7eSMarc Zyngier if (arch_timer_has_nonsecure_ppi()) {
1038ee34f1e6SFu Wei flags = check_ppi_trigger(arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI]);
1039ee34f1e6SFu Wei enable_percpu_irq(arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI],
1040ee34f1e6SFu Wei flags);
1041f005bd7eSMarc Zyngier }
10428a4da6e3SMark Rutland
10438a4da6e3SMark Rutland arch_counter_set_user_access();
10448a4da6e3SMark Rutland
10458a4da6e3SMark Rutland return 0;
10468a4da6e3SMark Rutland }
10478a4da6e3SMark Rutland
validate_timer_rate(void)1048c265861aSIonela Voinescu static int validate_timer_rate(void)
1049c265861aSIonela Voinescu {
1050c265861aSIonela Voinescu if (!arch_timer_rate)
1051c265861aSIonela Voinescu return -EINVAL;
1052c265861aSIonela Voinescu
1053c265861aSIonela Voinescu /* Arch timer frequency < 1MHz can cause trouble */
1054c265861aSIonela Voinescu WARN_ON(arch_timer_rate < 1000000);
1055c265861aSIonela Voinescu
1056c265861aSIonela Voinescu return 0;
1057c265861aSIonela Voinescu }
1058c265861aSIonela Voinescu
10595d3dfa96SFu Wei /*
10605d3dfa96SFu Wei * For historical reasons, when probing with DT we use whichever (non-zero)
10615d3dfa96SFu Wei * rate was probed first, and don't verify that others match. If the first node
10625d3dfa96SFu Wei * probed has a clock-frequency property, this overrides the HW register.
10635d3dfa96SFu Wei */
arch_timer_of_configure_rate(u32 rate,struct device_node * np)1064e2bf384dSJisheng Zhang static void __init arch_timer_of_configure_rate(u32 rate, struct device_node *np)
10658a4da6e3SMark Rutland {
106622006994SStephen Boyd /* Who has more than one independent system counter? */
106722006994SStephen Boyd if (arch_timer_rate)
106822006994SStephen Boyd return;
10698a4da6e3SMark Rutland
10705d3dfa96SFu Wei if (of_property_read_u32(np, "clock-frequency", &arch_timer_rate))
10715d3dfa96SFu Wei arch_timer_rate = rate;
10728a4da6e3SMark Rutland
10738a4da6e3SMark Rutland /* Check the timer frequency. */
1074c265861aSIonela Voinescu if (validate_timer_rate())
1075ded24019SFu Wei pr_warn("frequency not available\n");
10768a4da6e3SMark Rutland }
10778a4da6e3SMark Rutland
arch_timer_banner(unsigned type)1078e2bf384dSJisheng Zhang static void __init arch_timer_banner(unsigned type)
107922006994SStephen Boyd {
1080ded24019SFu Wei pr_info("%s%s%s timer(s) running at %lu.%02luMHz (%s%s%s).\n",
10818a5c21dcSFu Wei type & ARCH_TIMER_TYPE_CP15 ? "cp15" : "",
10828a5c21dcSFu Wei type == (ARCH_TIMER_TYPE_CP15 | ARCH_TIMER_TYPE_MEM) ?
10838a5c21dcSFu Wei " and " : "",
10848a5c21dcSFu Wei type & ARCH_TIMER_TYPE_MEM ? "mmio" : "",
10858a4da6e3SMark Rutland (unsigned long)arch_timer_rate / 1000000,
10868a4da6e3SMark Rutland (unsigned long)(arch_timer_rate / 10000) % 100,
10878a5c21dcSFu Wei type & ARCH_TIMER_TYPE_CP15 ?
1088ee34f1e6SFu Wei (arch_timer_uses_ppi == ARCH_TIMER_VIRT_PPI) ? "virt" : "phys" :
108922006994SStephen Boyd "",
10908a5c21dcSFu Wei type == (ARCH_TIMER_TYPE_CP15 | ARCH_TIMER_TYPE_MEM) ? "/" : "",
10918a5c21dcSFu Wei type & ARCH_TIMER_TYPE_MEM ?
109222006994SStephen Boyd arch_timer_mem_use_virtual ? "virt" : "phys" :
109322006994SStephen Boyd "");
10948a4da6e3SMark Rutland }
10958a4da6e3SMark Rutland
arch_timer_get_rate(void)10968a4da6e3SMark Rutland u32 arch_timer_get_rate(void)
10978a4da6e3SMark Rutland {
10988a4da6e3SMark Rutland return arch_timer_rate;
10998a4da6e3SMark Rutland }
11008a4da6e3SMark Rutland
arch_timer_evtstrm_available(void)1101ec5c8e42SJulien Thierry bool arch_timer_evtstrm_available(void)
1102ec5c8e42SJulien Thierry {
1103ec5c8e42SJulien Thierry /*
1104ec5c8e42SJulien Thierry * We might get called from a preemptible context. This is fine
1105ec5c8e42SJulien Thierry * because availability of the event stream should be always the same
1106ec5c8e42SJulien Thierry * for a preemptible context and context where we might resume a task.
1107ec5c8e42SJulien Thierry */
1108ec5c8e42SJulien Thierry return cpumask_test_cpu(raw_smp_processor_id(), &evtstrm_available);
1109ec5c8e42SJulien Thierry }
1110ec5c8e42SJulien Thierry
arch_counter_get_cntvct_mem(void)111124ee7607SPeter Zijlstra static noinstr u64 arch_counter_get_cntvct_mem(void)
11128a4da6e3SMark Rutland {
11138b82c4f8SMarc Zyngier return arch_counter_get_cnt_mem(arch_timer_mem, CNTVCT_LO);
11148a4da6e3SMark Rutland }
11158a4da6e3SMark Rutland
1116b4d6ce97SJulien Grall static struct arch_timer_kvm_info arch_timer_kvm_info;
1117b4d6ce97SJulien Grall
arch_timer_get_kvm_info(void)1118b4d6ce97SJulien Grall struct arch_timer_kvm_info *arch_timer_get_kvm_info(void)
1119b4d6ce97SJulien Grall {
1120b4d6ce97SJulien Grall return &arch_timer_kvm_info;
1121b4d6ce97SJulien Grall }
11228a4da6e3SMark Rutland
arch_counter_register(unsigned type)112322006994SStephen Boyd static void __init arch_counter_register(unsigned type)
112422006994SStephen Boyd {
112524ee7607SPeter Zijlstra u64 (*scr)(void);
112622006994SStephen Boyd u64 start_count;
1127c1153d52SOliver Upton int width;
112822006994SStephen Boyd
112922006994SStephen Boyd /* Register the CP15 based counter if we have one */
11308a5c21dcSFu Wei if (type & ARCH_TIMER_TYPE_CP15) {
11310ea41539SMarc Zyngier u64 (*rd)(void);
1132f6dc1576SScott Wood
11330ea41539SMarc Zyngier if ((IS_ENABLED(CONFIG_ARM64) && !is_hyp_mode_available()) ||
11340ea41539SMarc Zyngier arch_timer_uses_ppi == ARCH_TIMER_VIRT_PPI) {
113524ee7607SPeter Zijlstra if (arch_timer_counter_has_wa()) {
11360ea41539SMarc Zyngier rd = arch_counter_get_cntvct_stable;
113724ee7607SPeter Zijlstra scr = raw_counter_get_cntvct_stable;
11380ea41539SMarc Zyngier } else {
113924ee7607SPeter Zijlstra rd = arch_counter_get_cntvct;
114024ee7607SPeter Zijlstra scr = arch_counter_get_cntvct;
114124ee7607SPeter Zijlstra }
114224ee7607SPeter Zijlstra } else {
114324ee7607SPeter Zijlstra if (arch_timer_counter_has_wa()) {
11440ea41539SMarc Zyngier rd = arch_counter_get_cntpct_stable;
114524ee7607SPeter Zijlstra scr = raw_counter_get_cntpct_stable;
114624ee7607SPeter Zijlstra } else {
11470ea41539SMarc Zyngier rd = arch_counter_get_cntpct;
114824ee7607SPeter Zijlstra scr = arch_counter_get_cntpct;
114924ee7607SPeter Zijlstra }
11500ea41539SMarc Zyngier }
11510ea41539SMarc Zyngier
11520ea41539SMarc Zyngier arch_timer_read_counter = rd;
11535e3c6a31SThomas Gleixner clocksource_counter.vdso_clock_mode = vdso_default;
1154423bd69eSNathan Lynch } else {
115522006994SStephen Boyd arch_timer_read_counter = arch_counter_get_cntvct_mem;
115624ee7607SPeter Zijlstra scr = arch_counter_get_cntvct_mem;
1157423bd69eSNathan Lynch }
1158423bd69eSNathan Lynch
1159c1153d52SOliver Upton width = arch_counter_get_width();
1160c1153d52SOliver Upton clocksource_counter.mask = CLOCKSOURCE_MASK(width);
1161c1153d52SOliver Upton cyclecounter.mask = CLOCKSOURCE_MASK(width);
1162c1153d52SOliver Upton
1163d8ec7595SBrian Norris if (!arch_counter_suspend_stop)
1164d8ec7595SBrian Norris clocksource_counter.flags |= CLOCK_SOURCE_SUSPEND_NONSTOP;
116522006994SStephen Boyd start_count = arch_timer_read_counter();
116622006994SStephen Boyd clocksource_register_hz(&clocksource_counter, arch_timer_rate);
116722006994SStephen Boyd cyclecounter.mult = clocksource_counter.mult;
116822006994SStephen Boyd cyclecounter.shift = clocksource_counter.shift;
1169b4d6ce97SJulien Grall timecounter_init(&arch_timer_kvm_info.timecounter,
1170b4d6ce97SJulien Grall &cyclecounter, start_count);
11714a7d3e8aSThierry Reding
117224ee7607SPeter Zijlstra sched_clock_register(scr, width, arch_timer_rate);
117322006994SStephen Boyd }
117422006994SStephen Boyd
arch_timer_stop(struct clock_event_device * clk)11758c37bb3aSPaul Gortmaker static void arch_timer_stop(struct clock_event_device *clk)
11768a4da6e3SMark Rutland {
1177ded24019SFu Wei pr_debug("disable IRQ%d cpu #%d\n", clk->irq, smp_processor_id());
11788a4da6e3SMark Rutland
1179f81f03faSMarc Zyngier disable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi]);
1180f81f03faSMarc Zyngier if (arch_timer_has_nonsecure_ppi())
1181ee34f1e6SFu Wei disable_percpu_irq(arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI]);
11828a4da6e3SMark Rutland }
11838a4da6e3SMark Rutland
arch_timer_dying_cpu(unsigned int cpu)11847e86e8bdSRichard Cochran static int arch_timer_dying_cpu(unsigned int cpu)
11858a4da6e3SMark Rutland {
11867e86e8bdSRichard Cochran struct clock_event_device *clk = this_cpu_ptr(arch_timer_evt);
11878a4da6e3SMark Rutland
11887e86e8bdSRichard Cochran arch_timer_stop(clk);
11897e86e8bdSRichard Cochran return 0;
11908a4da6e3SMark Rutland }
11918a4da6e3SMark Rutland
1192346e7480SSudeep KarkadaNagesha #ifdef CONFIG_CPU_PM
1193bee67c53SMarc Zyngier static DEFINE_PER_CPU(unsigned long, saved_cntkctl);
arch_timer_cpu_pm_notify(struct notifier_block * self,unsigned long action,void * hcpu)1194346e7480SSudeep KarkadaNagesha static int arch_timer_cpu_pm_notify(struct notifier_block *self,
1195346e7480SSudeep KarkadaNagesha unsigned long action, void *hcpu)
1196346e7480SSudeep KarkadaNagesha {
1197ec5c8e42SJulien Thierry if (action == CPU_PM_ENTER) {
1198bee67c53SMarc Zyngier __this_cpu_write(saved_cntkctl, arch_timer_get_cntkctl());
1199ec5c8e42SJulien Thierry
1200ec5c8e42SJulien Thierry cpumask_clear_cpu(smp_processor_id(), &evtstrm_available);
1201ec5c8e42SJulien Thierry } else if (action == CPU_PM_ENTER_FAILED || action == CPU_PM_EXIT) {
1202bee67c53SMarc Zyngier arch_timer_set_cntkctl(__this_cpu_read(saved_cntkctl));
1203ec5c8e42SJulien Thierry
12045a354412SAndrew Murray if (arch_timer_have_evtstrm_feature())
1205ec5c8e42SJulien Thierry cpumask_set_cpu(smp_processor_id(), &evtstrm_available);
1206ec5c8e42SJulien Thierry }
1207346e7480SSudeep KarkadaNagesha return NOTIFY_OK;
1208346e7480SSudeep KarkadaNagesha }
1209346e7480SSudeep KarkadaNagesha
1210346e7480SSudeep KarkadaNagesha static struct notifier_block arch_timer_cpu_pm_notifier = {
1211346e7480SSudeep KarkadaNagesha .notifier_call = arch_timer_cpu_pm_notify,
1212346e7480SSudeep KarkadaNagesha };
1213346e7480SSudeep KarkadaNagesha
arch_timer_cpu_pm_init(void)1214346e7480SSudeep KarkadaNagesha static int __init arch_timer_cpu_pm_init(void)
1215346e7480SSudeep KarkadaNagesha {
1216346e7480SSudeep KarkadaNagesha return cpu_pm_register_notifier(&arch_timer_cpu_pm_notifier);
1217346e7480SSudeep KarkadaNagesha }
12187e86e8bdSRichard Cochran
arch_timer_cpu_pm_deinit(void)12197e86e8bdSRichard Cochran static void __init arch_timer_cpu_pm_deinit(void)
12207e86e8bdSRichard Cochran {
12217e86e8bdSRichard Cochran WARN_ON(cpu_pm_unregister_notifier(&arch_timer_cpu_pm_notifier));
12227e86e8bdSRichard Cochran }
12237e86e8bdSRichard Cochran
1224346e7480SSudeep KarkadaNagesha #else
arch_timer_cpu_pm_init(void)1225346e7480SSudeep KarkadaNagesha static int __init arch_timer_cpu_pm_init(void)
1226346e7480SSudeep KarkadaNagesha {
1227346e7480SSudeep KarkadaNagesha return 0;
1228346e7480SSudeep KarkadaNagesha }
12297e86e8bdSRichard Cochran
arch_timer_cpu_pm_deinit(void)12307e86e8bdSRichard Cochran static void __init arch_timer_cpu_pm_deinit(void)
12317e86e8bdSRichard Cochran {
12327e86e8bdSRichard Cochran }
1233346e7480SSudeep KarkadaNagesha #endif
1234346e7480SSudeep KarkadaNagesha
arch_timer_register(void)12358a4da6e3SMark Rutland static int __init arch_timer_register(void)
12368a4da6e3SMark Rutland {
12378a4da6e3SMark Rutland int err;
12388a4da6e3SMark Rutland int ppi;
12398a4da6e3SMark Rutland
12408a4da6e3SMark Rutland arch_timer_evt = alloc_percpu(struct clock_event_device);
12418a4da6e3SMark Rutland if (!arch_timer_evt) {
12428a4da6e3SMark Rutland err = -ENOMEM;
12438a4da6e3SMark Rutland goto out;
12448a4da6e3SMark Rutland }
12458a4da6e3SMark Rutland
1246f81f03faSMarc Zyngier ppi = arch_timer_ppi[arch_timer_uses_ppi];
1247f81f03faSMarc Zyngier switch (arch_timer_uses_ppi) {
1248ee34f1e6SFu Wei case ARCH_TIMER_VIRT_PPI:
12498a4da6e3SMark Rutland err = request_percpu_irq(ppi, arch_timer_handler_virt,
12508a4da6e3SMark Rutland "arch_timer", arch_timer_evt);
1251f81f03faSMarc Zyngier break;
1252ee34f1e6SFu Wei case ARCH_TIMER_PHYS_SECURE_PPI:
1253ee34f1e6SFu Wei case ARCH_TIMER_PHYS_NONSECURE_PPI:
12548a4da6e3SMark Rutland err = request_percpu_irq(ppi, arch_timer_handler_phys,
12558a4da6e3SMark Rutland "arch_timer", arch_timer_evt);
12564502b6bbSFu Wei if (!err && arch_timer_has_nonsecure_ppi()) {
1257ee34f1e6SFu Wei ppi = arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI];
12588a4da6e3SMark Rutland err = request_percpu_irq(ppi, arch_timer_handler_phys,
12598a4da6e3SMark Rutland "arch_timer", arch_timer_evt);
12608a4da6e3SMark Rutland if (err)
1261ee34f1e6SFu Wei free_percpu_irq(arch_timer_ppi[ARCH_TIMER_PHYS_SECURE_PPI],
12628a4da6e3SMark Rutland arch_timer_evt);
12638a4da6e3SMark Rutland }
1264f81f03faSMarc Zyngier break;
1265ee34f1e6SFu Wei case ARCH_TIMER_HYP_PPI:
1266f81f03faSMarc Zyngier err = request_percpu_irq(ppi, arch_timer_handler_phys,
1267f81f03faSMarc Zyngier "arch_timer", arch_timer_evt);
1268f81f03faSMarc Zyngier break;
1269f81f03faSMarc Zyngier default:
1270f81f03faSMarc Zyngier BUG();
12718a4da6e3SMark Rutland }
12728a4da6e3SMark Rutland
12738a4da6e3SMark Rutland if (err) {
1274ded24019SFu Wei pr_err("can't register interrupt %d (%d)\n", ppi, err);
12758a4da6e3SMark Rutland goto out_free;
12768a4da6e3SMark Rutland }
12778a4da6e3SMark Rutland
1278346e7480SSudeep KarkadaNagesha err = arch_timer_cpu_pm_init();
1279346e7480SSudeep KarkadaNagesha if (err)
1280346e7480SSudeep KarkadaNagesha goto out_unreg_notify;
1281346e7480SSudeep KarkadaNagesha
12827e86e8bdSRichard Cochran /* Register and immediately configure the timer on the boot CPU */
12837e86e8bdSRichard Cochran err = cpuhp_setup_state(CPUHP_AP_ARM_ARCH_TIMER_STARTING,
128473c1b41eSThomas Gleixner "clockevents/arm/arch_timer:starting",
12857e86e8bdSRichard Cochran arch_timer_starting_cpu, arch_timer_dying_cpu);
12867e86e8bdSRichard Cochran if (err)
12877e86e8bdSRichard Cochran goto out_unreg_cpupm;
12888a4da6e3SMark Rutland return 0;
12898a4da6e3SMark Rutland
12907e86e8bdSRichard Cochran out_unreg_cpupm:
12917e86e8bdSRichard Cochran arch_timer_cpu_pm_deinit();
12927e86e8bdSRichard Cochran
1293346e7480SSudeep KarkadaNagesha out_unreg_notify:
1294f81f03faSMarc Zyngier free_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], arch_timer_evt);
1295f81f03faSMarc Zyngier if (arch_timer_has_nonsecure_ppi())
1296ee34f1e6SFu Wei free_percpu_irq(arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI],
12978a4da6e3SMark Rutland arch_timer_evt);
12988a4da6e3SMark Rutland
12998a4da6e3SMark Rutland out_free:
13008a4da6e3SMark Rutland free_percpu(arch_timer_evt);
1301166b76a0SMark Rutland arch_timer_evt = NULL;
13028a4da6e3SMark Rutland out:
13038a4da6e3SMark Rutland return err;
13048a4da6e3SMark Rutland }
13058a4da6e3SMark Rutland
arch_timer_mem_register(void __iomem * base,unsigned int irq)130622006994SStephen Boyd static int __init arch_timer_mem_register(void __iomem *base, unsigned int irq)
130722006994SStephen Boyd {
130822006994SStephen Boyd int ret;
130922006994SStephen Boyd irq_handler_t func;
131022006994SStephen Boyd
131172f47a3fSMarc Zyngier arch_timer_mem = kzalloc(sizeof(*arch_timer_mem), GFP_KERNEL);
131272f47a3fSMarc Zyngier if (!arch_timer_mem)
131322006994SStephen Boyd return -ENOMEM;
131422006994SStephen Boyd
131572f47a3fSMarc Zyngier arch_timer_mem->base = base;
131672f47a3fSMarc Zyngier arch_timer_mem->evt.irq = irq;
131772f47a3fSMarc Zyngier __arch_timer_setup(ARCH_TIMER_TYPE_MEM, &arch_timer_mem->evt);
131822006994SStephen Boyd
131922006994SStephen Boyd if (arch_timer_mem_use_virtual)
132022006994SStephen Boyd func = arch_timer_handler_virt_mem;
132122006994SStephen Boyd else
132222006994SStephen Boyd func = arch_timer_handler_phys_mem;
132322006994SStephen Boyd
132472f47a3fSMarc Zyngier ret = request_irq(irq, func, IRQF_TIMER, "arch_mem_timer", &arch_timer_mem->evt);
132522006994SStephen Boyd if (ret) {
1326ded24019SFu Wei pr_err("Failed to request mem timer irq\n");
132772f47a3fSMarc Zyngier kfree(arch_timer_mem);
132872f47a3fSMarc Zyngier arch_timer_mem = NULL;
132922006994SStephen Boyd }
133022006994SStephen Boyd
133122006994SStephen Boyd return ret;
133222006994SStephen Boyd }
133322006994SStephen Boyd
133422006994SStephen Boyd static const struct of_device_id arch_timer_of_match[] __initconst = {
133522006994SStephen Boyd { .compatible = "arm,armv7-timer", },
133622006994SStephen Boyd { .compatible = "arm,armv8-timer", },
133722006994SStephen Boyd {},
133822006994SStephen Boyd };
133922006994SStephen Boyd
134022006994SStephen Boyd static const struct of_device_id arch_timer_mem_of_match[] __initconst = {
134122006994SStephen Boyd { .compatible = "arm,armv7-timer-mem", },
134222006994SStephen Boyd {},
134322006994SStephen Boyd };
134422006994SStephen Boyd
arch_timer_needs_of_probing(void)134513bf6992SFu Wei static bool __init arch_timer_needs_of_probing(void)
1346c387f07eSSudeep Holla {
1347c387f07eSSudeep Holla struct device_node *dn;
1348566e6dfaSLaurent Pinchart bool needs_probing = false;
134913bf6992SFu Wei unsigned int mask = ARCH_TIMER_TYPE_CP15 | ARCH_TIMER_TYPE_MEM;
1350c387f07eSSudeep Holla
135113bf6992SFu Wei /* We have two timers, and both device-tree nodes are probed. */
135213bf6992SFu Wei if ((arch_timers_present & mask) == mask)
135313bf6992SFu Wei return false;
135413bf6992SFu Wei
135513bf6992SFu Wei /*
135613bf6992SFu Wei * Only one type of timer is probed,
135713bf6992SFu Wei * check if we have another type of timer node in device-tree.
135813bf6992SFu Wei */
135913bf6992SFu Wei if (arch_timers_present & ARCH_TIMER_TYPE_CP15)
136013bf6992SFu Wei dn = of_find_matching_node(NULL, arch_timer_mem_of_match);
136113bf6992SFu Wei else
136213bf6992SFu Wei dn = of_find_matching_node(NULL, arch_timer_of_match);
136313bf6992SFu Wei
136413bf6992SFu Wei if (dn && of_device_is_available(dn))
1365566e6dfaSLaurent Pinchart needs_probing = true;
136613bf6992SFu Wei
1367c387f07eSSudeep Holla of_node_put(dn);
1368c387f07eSSudeep Holla
1369566e6dfaSLaurent Pinchart return needs_probing;
1370c387f07eSSudeep Holla }
1371c387f07eSSudeep Holla
arch_timer_common_init(void)13723c0731dbSDaniel Lezcano static int __init arch_timer_common_init(void)
137322006994SStephen Boyd {
137422006994SStephen Boyd arch_timer_banner(arch_timers_present);
137522006994SStephen Boyd arch_counter_register(arch_timers_present);
13763c0731dbSDaniel Lezcano return arch_timer_arch_init();
137722006994SStephen Boyd }
137822006994SStephen Boyd
13794502b6bbSFu Wei /**
13804502b6bbSFu Wei * arch_timer_select_ppi() - Select suitable PPI for the current system.
13814502b6bbSFu Wei *
13828266891eSMarc Zyngier * If HYP mode is available, we know that the physical timer
13838266891eSMarc Zyngier * has been configured to be accessible from PL1. Use it, so
13848266891eSMarc Zyngier * that a guest can use the virtual timer instead.
13858266891eSMarc Zyngier *
1386f81f03faSMarc Zyngier * On ARMv8.1 with VH extensions, the kernel runs in HYP. VHE
1387f81f03faSMarc Zyngier * accesses to CNTP_*_EL1 registers are silently redirected to
1388f81f03faSMarc Zyngier * their CNTHP_*_EL2 counterparts, and use a different PPI
1389f81f03faSMarc Zyngier * number.
13904502b6bbSFu Wei *
13914502b6bbSFu Wei * If no interrupt provided for virtual timer, we'll have to
13924502b6bbSFu Wei * stick to the physical timer. It'd better be accessible...
13934502b6bbSFu Wei * For arm64 we never use the secure interrupt.
13944502b6bbSFu Wei *
13954502b6bbSFu Wei * Return: a suitable PPI type for the current system.
13968a4da6e3SMark Rutland */
arch_timer_select_ppi(void)13974502b6bbSFu Wei static enum arch_timer_ppi_nr __init arch_timer_select_ppi(void)
13984502b6bbSFu Wei {
13994502b6bbSFu Wei if (is_kernel_in_hyp_mode())
14004502b6bbSFu Wei return ARCH_TIMER_HYP_PPI;
14018a4da6e3SMark Rutland
14024502b6bbSFu Wei if (!is_hyp_mode_available() && arch_timer_ppi[ARCH_TIMER_VIRT_PPI])
14034502b6bbSFu Wei return ARCH_TIMER_VIRT_PPI;
14044502b6bbSFu Wei
14054502b6bbSFu Wei if (IS_ENABLED(CONFIG_ARM64))
14064502b6bbSFu Wei return ARCH_TIMER_PHYS_NONSECURE_PPI;
14074502b6bbSFu Wei
14084502b6bbSFu Wei return ARCH_TIMER_PHYS_SECURE_PPI;
1409f81f03faSMarc Zyngier }
1410f81f03faSMarc Zyngier
arch_timer_populate_kvm_info(void)1411ee793049SAndre Przywara static void __init arch_timer_populate_kvm_info(void)
1412ee793049SAndre Przywara {
1413ee793049SAndre Przywara arch_timer_kvm_info.virtual_irq = arch_timer_ppi[ARCH_TIMER_VIRT_PPI];
1414ee793049SAndre Przywara if (is_kernel_in_hyp_mode())
1415ee793049SAndre Przywara arch_timer_kvm_info.physical_irq = arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI];
1416ee793049SAndre Przywara }
1417ee793049SAndre Przywara
arch_timer_of_init(struct device_node * np)14183c0731dbSDaniel Lezcano static int __init arch_timer_of_init(struct device_node *np)
1419b09ca1ecSHanjun Guo {
142086332e9eSHector Martin int i, irq, ret;
14215d3dfa96SFu Wei u32 rate;
142286332e9eSHector Martin bool has_names;
1423b09ca1ecSHanjun Guo
14248a5c21dcSFu Wei if (arch_timers_present & ARCH_TIMER_TYPE_CP15) {
1425ded24019SFu Wei pr_warn("multiple nodes in dt, skipping\n");
14263c0731dbSDaniel Lezcano return 0;
1427b09ca1ecSHanjun Guo }
1428b09ca1ecSHanjun Guo
14298a5c21dcSFu Wei arch_timers_present |= ARCH_TIMER_TYPE_CP15;
143086332e9eSHector Martin
143108b97fbdSRob Herring (Arm) has_names = of_property_present(np, "interrupt-names");
143286332e9eSHector Martin
143386332e9eSHector Martin for (i = ARCH_TIMER_PHYS_SECURE_PPI; i < ARCH_TIMER_MAX_TIMER_PPI; i++) {
143486332e9eSHector Martin if (has_names)
143586332e9eSHector Martin irq = of_irq_get_byname(np, arch_timer_ppi_names[i]);
143686332e9eSHector Martin else
143786332e9eSHector Martin irq = of_irq_get(np, i);
143886332e9eSHector Martin if (irq > 0)
143986332e9eSHector Martin arch_timer_ppi[i] = irq;
144086332e9eSHector Martin }
1441b09ca1ecSHanjun Guo
1442ee793049SAndre Przywara arch_timer_populate_kvm_info();
1443ca0e1b52SFu Wei
1444c389d701SFu Wei rate = arch_timer_get_cntfrq();
14455d3dfa96SFu Wei arch_timer_of_configure_rate(rate, np);
1446b09ca1ecSHanjun Guo
1447b09ca1ecSHanjun Guo arch_timer_c3stop = !of_property_read_bool(np, "always-on");
1448b09ca1ecSHanjun Guo
1449651bb2e9SMarc Zyngier /* Check for globally applicable workarounds */
1450651bb2e9SMarc Zyngier arch_timer_check_ool_workaround(ate_match_dt, np);
1451f6dc1576SScott Wood
1452b09ca1ecSHanjun Guo /*
1453b09ca1ecSHanjun Guo * If we cannot rely on firmware initializing the timer registers then
1454b09ca1ecSHanjun Guo * we should use the physical timers instead.
1455b09ca1ecSHanjun Guo */
1456b09ca1ecSHanjun Guo if (IS_ENABLED(CONFIG_ARM) &&
1457b09ca1ecSHanjun Guo of_property_read_bool(np, "arm,cpu-registers-not-fw-configured"))
1458ee34f1e6SFu Wei arch_timer_uses_ppi = ARCH_TIMER_PHYS_SECURE_PPI;
14594502b6bbSFu Wei else
14604502b6bbSFu Wei arch_timer_uses_ppi = arch_timer_select_ppi();
14614502b6bbSFu Wei
14624502b6bbSFu Wei if (!arch_timer_ppi[arch_timer_uses_ppi]) {
14634502b6bbSFu Wei pr_err("No interrupt available, giving up\n");
14644502b6bbSFu Wei return -EINVAL;
14654502b6bbSFu Wei }
1466b09ca1ecSHanjun Guo
1467d8ec7595SBrian Norris /* On some systems, the counter stops ticking when in suspend. */
1468d8ec7595SBrian Norris arch_counter_suspend_stop = of_property_read_bool(np,
1469d8ec7595SBrian Norris "arm,no-tick-in-suspend");
1470d8ec7595SBrian Norris
1471ca0e1b52SFu Wei ret = arch_timer_register();
1472ca0e1b52SFu Wei if (ret)
1473ca0e1b52SFu Wei return ret;
1474ca0e1b52SFu Wei
1475ca0e1b52SFu Wei if (arch_timer_needs_of_probing())
1476ca0e1b52SFu Wei return 0;
1477ca0e1b52SFu Wei
1478ca0e1b52SFu Wei return arch_timer_common_init();
1479b09ca1ecSHanjun Guo }
148017273395SDaniel Lezcano TIMER_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", arch_timer_of_init);
148117273395SDaniel Lezcano TIMER_OF_DECLARE(armv8_arch_timer, "arm,armv8-timer", arch_timer_of_init);
148222006994SStephen Boyd
1483c389d701SFu Wei static u32 __init
arch_timer_mem_frame_get_cntfrq(struct arch_timer_mem_frame * frame)1484c389d701SFu Wei arch_timer_mem_frame_get_cntfrq(struct arch_timer_mem_frame *frame)
148522006994SStephen Boyd {
1486c389d701SFu Wei void __iomem *base;
1487c389d701SFu Wei u32 rate;
148822006994SStephen Boyd
1489c389d701SFu Wei base = ioremap(frame->cntbase, frame->size);
1490c389d701SFu Wei if (!base) {
1491c389d701SFu Wei pr_err("Unable to map frame @ %pa\n", &frame->cntbase);
1492c389d701SFu Wei return 0;
1493c389d701SFu Wei }
1494c389d701SFu Wei
14953db1200cSFrank Rowand rate = readl_relaxed(base + CNTFRQ);
1496c389d701SFu Wei
14973db1200cSFrank Rowand iounmap(base);
1498c389d701SFu Wei
1499c389d701SFu Wei return rate;
1500c389d701SFu Wei }
1501c389d701SFu Wei
1502c389d701SFu Wei static struct arch_timer_mem_frame * __init
arch_timer_mem_find_best_frame(struct arch_timer_mem * timer_mem)1503c389d701SFu Wei arch_timer_mem_find_best_frame(struct arch_timer_mem *timer_mem)
1504c389d701SFu Wei {
1505c389d701SFu Wei struct arch_timer_mem_frame *frame, *best_frame = NULL;
1506c389d701SFu Wei void __iomem *cntctlbase;
1507c389d701SFu Wei u32 cnttidr;
1508c389d701SFu Wei int i;
1509c389d701SFu Wei
1510c389d701SFu Wei cntctlbase = ioremap(timer_mem->cntctlbase, timer_mem->size);
151122006994SStephen Boyd if (!cntctlbase) {
1512c389d701SFu Wei pr_err("Can't map CNTCTLBase @ %pa\n",
1513c389d701SFu Wei &timer_mem->cntctlbase);
1514c389d701SFu Wei return NULL;
151522006994SStephen Boyd }
151622006994SStephen Boyd
151722006994SStephen Boyd cnttidr = readl_relaxed(cntctlbase + CNTTIDR);
151822006994SStephen Boyd
151922006994SStephen Boyd /*
152022006994SStephen Boyd * Try to find a virtual capable frame. Otherwise fall back to a
152122006994SStephen Boyd * physical capable frame.
152222006994SStephen Boyd */
1523c389d701SFu Wei for (i = 0; i < ARCH_TIMER_MEM_MAX_FRAMES; i++) {
1524c389d701SFu Wei u32 cntacr = CNTACR_RFRQ | CNTACR_RWPT | CNTACR_RPCT |
1525c389d701SFu Wei CNTACR_RWVT | CNTACR_RVOFF | CNTACR_RVCT;
152622006994SStephen Boyd
1527c389d701SFu Wei frame = &timer_mem->frame[i];
1528c389d701SFu Wei if (!frame->valid)
1529c389d701SFu Wei continue;
153022006994SStephen Boyd
1531e392d603SRobin Murphy /* Try enabling everything, and see what sticks */
1532c389d701SFu Wei writel_relaxed(cntacr, cntctlbase + CNTACR(i));
1533c389d701SFu Wei cntacr = readl_relaxed(cntctlbase + CNTACR(i));
1534e392d603SRobin Murphy
1535c389d701SFu Wei if ((cnttidr & CNTTIDR_VIRT(i)) &&
1536e392d603SRobin Murphy !(~cntacr & (CNTACR_RWVT | CNTACR_RVCT))) {
153722006994SStephen Boyd best_frame = frame;
153822006994SStephen Boyd arch_timer_mem_use_virtual = true;
153922006994SStephen Boyd break;
154022006994SStephen Boyd }
1541e392d603SRobin Murphy
1542e392d603SRobin Murphy if (~cntacr & (CNTACR_RWPT | CNTACR_RPCT))
1543e392d603SRobin Murphy continue;
1544e392d603SRobin Murphy
1545c389d701SFu Wei best_frame = frame;
154622006994SStephen Boyd }
154722006994SStephen Boyd
1548c389d701SFu Wei iounmap(cntctlbase);
1549c389d701SFu Wei
1550f63d947cSSudeep Holla return best_frame;
155122006994SStephen Boyd }
155222006994SStephen Boyd
1553c389d701SFu Wei static int __init
arch_timer_mem_frame_register(struct arch_timer_mem_frame * frame)1554c389d701SFu Wei arch_timer_mem_frame_register(struct arch_timer_mem_frame *frame)
1555c389d701SFu Wei {
1556c389d701SFu Wei void __iomem *base;
15577cbbcbd4SLi kunyu int ret, irq;
1558c389d701SFu Wei
155922006994SStephen Boyd if (arch_timer_mem_use_virtual)
1560c389d701SFu Wei irq = frame->virt_irq;
156122006994SStephen Boyd else
1562c389d701SFu Wei irq = frame->phys_irq;
1563e392d603SRobin Murphy
156422006994SStephen Boyd if (!irq) {
1565ded24019SFu Wei pr_err("Frame missing %s irq.\n",
156622006994SStephen Boyd arch_timer_mem_use_virtual ? "virt" : "phys");
1567c389d701SFu Wei return -EINVAL;
1568c389d701SFu Wei }
1569c389d701SFu Wei
1570c389d701SFu Wei if (!request_mem_region(frame->cntbase, frame->size,
1571c389d701SFu Wei "arch_mem_timer"))
1572c389d701SFu Wei return -EBUSY;
1573c389d701SFu Wei
1574c389d701SFu Wei base = ioremap(frame->cntbase, frame->size);
1575c389d701SFu Wei if (!base) {
1576c389d701SFu Wei pr_err("Can't map frame's registers\n");
1577c389d701SFu Wei return -ENXIO;
1578c389d701SFu Wei }
1579c389d701SFu Wei
1580c389d701SFu Wei ret = arch_timer_mem_register(base, irq);
1581c389d701SFu Wei if (ret) {
1582c389d701SFu Wei iounmap(base);
1583c389d701SFu Wei return ret;
1584c389d701SFu Wei }
1585c389d701SFu Wei
1586c389d701SFu Wei arch_timers_present |= ARCH_TIMER_TYPE_MEM;
1587c389d701SFu Wei
1588c389d701SFu Wei return 0;
1589c389d701SFu Wei }
1590c389d701SFu Wei
arch_timer_mem_of_init(struct device_node * np)1591c389d701SFu Wei static int __init arch_timer_mem_of_init(struct device_node *np)
1592c389d701SFu Wei {
1593c389d701SFu Wei struct arch_timer_mem *timer_mem;
1594c389d701SFu Wei struct arch_timer_mem_frame *frame;
1595c389d701SFu Wei struct resource res;
1596c389d701SFu Wei int ret = -EINVAL;
1597c389d701SFu Wei u32 rate;
1598c389d701SFu Wei
1599c389d701SFu Wei timer_mem = kzalloc(sizeof(*timer_mem), GFP_KERNEL);
1600c389d701SFu Wei if (!timer_mem)
1601c389d701SFu Wei return -ENOMEM;
1602c389d701SFu Wei
1603c389d701SFu Wei if (of_address_to_resource(np, 0, &res))
1604c389d701SFu Wei goto out;
1605c389d701SFu Wei timer_mem->cntctlbase = res.start;
1606c389d701SFu Wei timer_mem->size = resource_size(&res);
1607c389d701SFu Wei
1608a7456d7dSZhang Zekun for_each_available_child_of_node_scoped(np, frame_node) {
1609c389d701SFu Wei u32 n;
1610c389d701SFu Wei struct arch_timer_mem_frame *frame;
1611c389d701SFu Wei
1612c389d701SFu Wei if (of_property_read_u32(frame_node, "frame-number", &n)) {
1613c389d701SFu Wei pr_err(FW_BUG "Missing frame-number.\n");
1614c389d701SFu Wei goto out;
1615c389d701SFu Wei }
1616c389d701SFu Wei if (n >= ARCH_TIMER_MEM_MAX_FRAMES) {
1617c389d701SFu Wei pr_err(FW_BUG "Wrong frame-number, only 0-%u are permitted.\n",
1618c389d701SFu Wei ARCH_TIMER_MEM_MAX_FRAMES - 1);
1619c389d701SFu Wei goto out;
1620c389d701SFu Wei }
1621c389d701SFu Wei frame = &timer_mem->frame[n];
1622c389d701SFu Wei
1623c389d701SFu Wei if (frame->valid) {
1624c389d701SFu Wei pr_err(FW_BUG "Duplicated frame-number.\n");
1625e392d603SRobin Murphy goto out;
162622006994SStephen Boyd }
162722006994SStephen Boyd
1628a7456d7dSZhang Zekun if (of_address_to_resource(frame_node, 0, &res))
16293c0731dbSDaniel Lezcano goto out;
1630a7456d7dSZhang Zekun
1631c389d701SFu Wei frame->cntbase = res.start;
1632c389d701SFu Wei frame->size = resource_size(&res);
16333c0731dbSDaniel Lezcano
1634c389d701SFu Wei frame->virt_irq = irq_of_parse_and_map(frame_node,
1635c389d701SFu Wei ARCH_TIMER_VIRT_SPI);
1636c389d701SFu Wei frame->phys_irq = irq_of_parse_and_map(frame_node,
1637c389d701SFu Wei ARCH_TIMER_PHYS_SPI);
1638c389d701SFu Wei
1639c389d701SFu Wei frame->valid = true;
1640c389d701SFu Wei }
1641c389d701SFu Wei
1642c389d701SFu Wei frame = arch_timer_mem_find_best_frame(timer_mem);
1643c389d701SFu Wei if (!frame) {
164421492e13SArd Biesheuvel pr_err("Unable to find a suitable frame in timer @ %pa\n",
164521492e13SArd Biesheuvel &timer_mem->cntctlbase);
1646c389d701SFu Wei ret = -EINVAL;
1647c389d701SFu Wei goto out;
1648c389d701SFu Wei }
1649c389d701SFu Wei
1650c389d701SFu Wei rate = arch_timer_mem_frame_get_cntfrq(frame);
1651c389d701SFu Wei arch_timer_of_configure_rate(rate, np);
1652c389d701SFu Wei
1653c389d701SFu Wei ret = arch_timer_mem_frame_register(frame);
1654c389d701SFu Wei if (!ret && !arch_timer_needs_of_probing())
1655ca0e1b52SFu Wei ret = arch_timer_common_init();
1656e392d603SRobin Murphy out:
1657c389d701SFu Wei kfree(timer_mem);
16583c0731dbSDaniel Lezcano return ret;
165922006994SStephen Boyd }
166017273395SDaniel Lezcano TIMER_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem",
1661c389d701SFu Wei arch_timer_mem_of_init);
1662b09ca1ecSHanjun Guo
1663f79d2094SFu Wei #ifdef CONFIG_ACPI_GTDT
1664c2743a36SFu Wei static int __init
arch_timer_mem_verify_cntfrq(struct arch_timer_mem * timer_mem)1665c2743a36SFu Wei arch_timer_mem_verify_cntfrq(struct arch_timer_mem *timer_mem)
1666c2743a36SFu Wei {
1667c2743a36SFu Wei struct arch_timer_mem_frame *frame;
1668c2743a36SFu Wei u32 rate;
1669c2743a36SFu Wei int i;
1670c2743a36SFu Wei
1671c2743a36SFu Wei for (i = 0; i < ARCH_TIMER_MEM_MAX_FRAMES; i++) {
1672c2743a36SFu Wei frame = &timer_mem->frame[i];
1673c2743a36SFu Wei
1674c2743a36SFu Wei if (!frame->valid)
1675c2743a36SFu Wei continue;
1676c2743a36SFu Wei
1677c2743a36SFu Wei rate = arch_timer_mem_frame_get_cntfrq(frame);
1678c2743a36SFu Wei if (rate == arch_timer_rate)
1679c2743a36SFu Wei continue;
1680c2743a36SFu Wei
1681c2743a36SFu Wei pr_err(FW_BUG "CNTFRQ mismatch: frame @ %pa: (0x%08lx), CPU: (0x%08lx)\n",
1682c2743a36SFu Wei &frame->cntbase,
1683c2743a36SFu Wei (unsigned long)rate, (unsigned long)arch_timer_rate);
1684c2743a36SFu Wei
1685c2743a36SFu Wei return -EINVAL;
1686c2743a36SFu Wei }
1687c2743a36SFu Wei
1688c2743a36SFu Wei return 0;
1689c2743a36SFu Wei }
1690c2743a36SFu Wei
arch_timer_mem_acpi_init(int platform_timer_count)1691c2743a36SFu Wei static int __init arch_timer_mem_acpi_init(int platform_timer_count)
1692c2743a36SFu Wei {
1693c2743a36SFu Wei struct arch_timer_mem *timers, *timer;
169421492e13SArd Biesheuvel struct arch_timer_mem_frame *frame, *best_frame = NULL;
1695c2743a36SFu Wei int timer_count, i, ret = 0;
1696c2743a36SFu Wei
1697c2743a36SFu Wei timers = kcalloc(platform_timer_count, sizeof(*timers),
1698c2743a36SFu Wei GFP_KERNEL);
1699c2743a36SFu Wei if (!timers)
1700c2743a36SFu Wei return -ENOMEM;
1701c2743a36SFu Wei
1702c2743a36SFu Wei ret = acpi_arch_timer_mem_init(timers, &timer_count);
1703c2743a36SFu Wei if (ret || !timer_count)
1704c2743a36SFu Wei goto out;
1705c2743a36SFu Wei
1706c2743a36SFu Wei /*
1707c2743a36SFu Wei * While unlikely, it's theoretically possible that none of the frames
1708c2743a36SFu Wei * in a timer expose the combination of feature we want.
1709c2743a36SFu Wei */
1710d197f798SMatthias Kaehlcke for (i = 0; i < timer_count; i++) {
1711c2743a36SFu Wei timer = &timers[i];
1712c2743a36SFu Wei
1713c2743a36SFu Wei frame = arch_timer_mem_find_best_frame(timer);
171421492e13SArd Biesheuvel if (!best_frame)
171521492e13SArd Biesheuvel best_frame = frame;
171621492e13SArd Biesheuvel
171721492e13SArd Biesheuvel ret = arch_timer_mem_verify_cntfrq(timer);
171821492e13SArd Biesheuvel if (ret) {
171921492e13SArd Biesheuvel pr_err("Disabling MMIO timers due to CNTFRQ mismatch\n");
172021492e13SArd Biesheuvel goto out;
1721c2743a36SFu Wei }
1722c2743a36SFu Wei
172321492e13SArd Biesheuvel if (!best_frame) /* implies !frame */
172421492e13SArd Biesheuvel /*
172521492e13SArd Biesheuvel * Only complain about missing suitable frames if we
172621492e13SArd Biesheuvel * haven't already found one in a previous iteration.
172721492e13SArd Biesheuvel */
172821492e13SArd Biesheuvel pr_err("Unable to find a suitable frame in timer @ %pa\n",
172921492e13SArd Biesheuvel &timer->cntctlbase);
173021492e13SArd Biesheuvel }
173121492e13SArd Biesheuvel
173221492e13SArd Biesheuvel if (best_frame)
173321492e13SArd Biesheuvel ret = arch_timer_mem_frame_register(best_frame);
1734c2743a36SFu Wei out:
1735c2743a36SFu Wei kfree(timers);
1736c2743a36SFu Wei return ret;
1737c2743a36SFu Wei }
1738c2743a36SFu Wei
1739c2743a36SFu Wei /* Initialize per-processor generic timer and memory-mapped timer(if present) */
arch_timer_acpi_init(struct acpi_table_header * table)1740b09ca1ecSHanjun Guo static int __init arch_timer_acpi_init(struct acpi_table_header *table)
1741b09ca1ecSHanjun Guo {
1742c2743a36SFu Wei int ret, platform_timer_count;
1743b09ca1ecSHanjun Guo
17448a5c21dcSFu Wei if (arch_timers_present & ARCH_TIMER_TYPE_CP15) {
1745ded24019SFu Wei pr_warn("already initialized, skipping\n");
1746b09ca1ecSHanjun Guo return -EINVAL;
1747b09ca1ecSHanjun Guo }
1748b09ca1ecSHanjun Guo
17498a5c21dcSFu Wei arch_timers_present |= ARCH_TIMER_TYPE_CP15;
1750b09ca1ecSHanjun Guo
1751c2743a36SFu Wei ret = acpi_gtdt_init(table, &platform_timer_count);
1752d1b5e552SDejin Zheng if (ret)
1753f79d2094SFu Wei return ret;
1754b09ca1ecSHanjun Guo
1755ee34f1e6SFu Wei arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI] =
1756f79d2094SFu Wei acpi_gtdt_map_ppi(ARCH_TIMER_PHYS_NONSECURE_PPI);
1757b09ca1ecSHanjun Guo
1758ee34f1e6SFu Wei arch_timer_ppi[ARCH_TIMER_VIRT_PPI] =
1759f79d2094SFu Wei acpi_gtdt_map_ppi(ARCH_TIMER_VIRT_PPI);
1760b09ca1ecSHanjun Guo
1761ee34f1e6SFu Wei arch_timer_ppi[ARCH_TIMER_HYP_PPI] =
1762f79d2094SFu Wei acpi_gtdt_map_ppi(ARCH_TIMER_HYP_PPI);
1763b09ca1ecSHanjun Guo
1764ee793049SAndre Przywara arch_timer_populate_kvm_info();
1765ca0e1b52SFu Wei
17665d3dfa96SFu Wei /*
17675d3dfa96SFu Wei * When probing via ACPI, we have no mechanism to override the sysreg
17685d3dfa96SFu Wei * CNTFRQ value. This *must* be correct.
17695d3dfa96SFu Wei */
17705d3dfa96SFu Wei arch_timer_rate = arch_timer_get_cntfrq();
1771c265861aSIonela Voinescu ret = validate_timer_rate();
1772c265861aSIonela Voinescu if (ret) {
17735d3dfa96SFu Wei pr_err(FW_BUG "frequency not available.\n");
1774c265861aSIonela Voinescu return ret;
17755d3dfa96SFu Wei }
1776b09ca1ecSHanjun Guo
17774502b6bbSFu Wei arch_timer_uses_ppi = arch_timer_select_ppi();
17784502b6bbSFu Wei if (!arch_timer_ppi[arch_timer_uses_ppi]) {
17794502b6bbSFu Wei pr_err("No interrupt available, giving up\n");
17804502b6bbSFu Wei return -EINVAL;
17814502b6bbSFu Wei }
17824502b6bbSFu Wei
1783b09ca1ecSHanjun Guo /* Always-on capability */
1784f79d2094SFu Wei arch_timer_c3stop = acpi_gtdt_c3stop(arch_timer_uses_ppi);
1785b09ca1ecSHanjun Guo
17865a38bcacSMarc Zyngier /* Check for globally applicable workarounds */
17875a38bcacSMarc Zyngier arch_timer_check_ool_workaround(ate_match_acpi_oem_info, table);
17885a38bcacSMarc Zyngier
1789ca0e1b52SFu Wei ret = arch_timer_register();
1790ca0e1b52SFu Wei if (ret)
1791ca0e1b52SFu Wei return ret;
1792ca0e1b52SFu Wei
1793c2743a36SFu Wei if (platform_timer_count &&
1794c2743a36SFu Wei arch_timer_mem_acpi_init(platform_timer_count))
1795c2743a36SFu Wei pr_err("Failed to initialize memory-mapped timer.\n");
1796c2743a36SFu Wei
1797ca0e1b52SFu Wei return arch_timer_common_init();
1798b09ca1ecSHanjun Guo }
179977d62f53SDaniel Lezcano TIMER_ACPI_DECLARE(arch_timer, ACPI_SIG_GTDT, arch_timer_acpi_init);
1800b09ca1ecSHanjun Guo #endif
1801300bb1feSJianyong Wu
kvm_arch_ptp_get_crosststamp(u64 * cycle,struct timespec64 * ts,enum clocksource_ids * cs_id)1802300bb1feSJianyong Wu int kvm_arch_ptp_get_crosststamp(u64 *cycle, struct timespec64 *ts,
18039be3b2f0SPeter Hilber enum clocksource_ids *cs_id)
1804300bb1feSJianyong Wu {
1805300bb1feSJianyong Wu struct arm_smccc_res hvc_res;
1806300bb1feSJianyong Wu u32 ptp_counter;
1807300bb1feSJianyong Wu ktime_t ktime;
1808300bb1feSJianyong Wu
1809300bb1feSJianyong Wu if (!IS_ENABLED(CONFIG_HAVE_ARM_SMCCC_DISCOVERY))
1810300bb1feSJianyong Wu return -EOPNOTSUPP;
1811300bb1feSJianyong Wu
1812300bb1feSJianyong Wu if (arch_timer_uses_ppi == ARCH_TIMER_VIRT_PPI)
1813300bb1feSJianyong Wu ptp_counter = KVM_PTP_VIRT_COUNTER;
1814300bb1feSJianyong Wu else
1815300bb1feSJianyong Wu ptp_counter = KVM_PTP_PHYS_COUNTER;
1816300bb1feSJianyong Wu
1817300bb1feSJianyong Wu arm_smccc_1_1_invoke(ARM_SMCCC_VENDOR_HYP_KVM_PTP_FUNC_ID,
1818300bb1feSJianyong Wu ptp_counter, &hvc_res);
1819300bb1feSJianyong Wu
1820300bb1feSJianyong Wu if ((int)(hvc_res.a0) < 0)
1821300bb1feSJianyong Wu return -EOPNOTSUPP;
1822300bb1feSJianyong Wu
1823300bb1feSJianyong Wu ktime = (u64)hvc_res.a0 << 32 | hvc_res.a1;
1824300bb1feSJianyong Wu *ts = ktime_to_timespec64(ktime);
1825300bb1feSJianyong Wu if (cycle)
1826300bb1feSJianyong Wu *cycle = (u64)hvc_res.a2 << 32 | hvc_res.a3;
18279be3b2f0SPeter Hilber if (cs_id)
18289be3b2f0SPeter Hilber *cs_id = CSID_ARM_ARCH_COUNTER;
1829300bb1feSJianyong Wu
1830300bb1feSJianyong Wu return 0;
1831300bb1feSJianyong Wu }
1832300bb1feSJianyong Wu EXPORT_SYMBOL_GPL(kvm_arch_ptp_get_crosststamp);
1833