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