18a4da6e3SMark Rutland /*
28a4da6e3SMark Rutland  *  linux/drivers/clocksource/arm_arch_timer.c
38a4da6e3SMark Rutland  *
48a4da6e3SMark Rutland  *  Copyright (C) 2011 ARM Ltd.
58a4da6e3SMark Rutland  *  All Rights Reserved
68a4da6e3SMark Rutland  *
78a4da6e3SMark Rutland  * This program is free software; you can redistribute it and/or modify
88a4da6e3SMark Rutland  * it under the terms of the GNU General Public License version 2 as
98a4da6e3SMark Rutland  * published by the Free Software Foundation.
108a4da6e3SMark Rutland  */
11f005bd7eSMarc Zyngier 
12f005bd7eSMarc Zyngier #define pr_fmt(fmt)	"arm_arch_timer: " fmt
13f005bd7eSMarc Zyngier 
148a4da6e3SMark Rutland #include <linux/init.h>
158a4da6e3SMark Rutland #include <linux/kernel.h>
168a4da6e3SMark Rutland #include <linux/device.h>
178a4da6e3SMark Rutland #include <linux/smp.h>
188a4da6e3SMark Rutland #include <linux/cpu.h>
19346e7480SSudeep KarkadaNagesha #include <linux/cpu_pm.h>
208a4da6e3SMark Rutland #include <linux/clockchips.h>
217c8f1e78SRichard Cochran #include <linux/clocksource.h>
228a4da6e3SMark Rutland #include <linux/interrupt.h>
238a4da6e3SMark Rutland #include <linux/of_irq.h>
2422006994SStephen Boyd #include <linux/of_address.h>
258a4da6e3SMark Rutland #include <linux/io.h>
2622006994SStephen Boyd #include <linux/slab.h>
27e6017571SIngo Molnar #include <linux/sched/clock.h>
2865cd4f6cSStephen Boyd #include <linux/sched_clock.h>
29b09ca1ecSHanjun Guo #include <linux/acpi.h>
308a4da6e3SMark Rutland 
318a4da6e3SMark Rutland #include <asm/arch_timer.h>
328266891eSMarc Zyngier #include <asm/virt.h>
338a4da6e3SMark Rutland 
348a4da6e3SMark Rutland #include <clocksource/arm_arch_timer.h>
358a4da6e3SMark Rutland 
3622006994SStephen Boyd #define CNTTIDR		0x08
3722006994SStephen Boyd #define CNTTIDR_VIRT(n)	(BIT(1) << ((n) * 4))
3822006994SStephen Boyd 
39e392d603SRobin Murphy #define CNTACR(n)	(0x40 + ((n) * 4))
40e392d603SRobin Murphy #define CNTACR_RPCT	BIT(0)
41e392d603SRobin Murphy #define CNTACR_RVCT	BIT(1)
42e392d603SRobin Murphy #define CNTACR_RFRQ	BIT(2)
43e392d603SRobin Murphy #define CNTACR_RVOFF	BIT(3)
44e392d603SRobin Murphy #define CNTACR_RWVT	BIT(4)
45e392d603SRobin Murphy #define CNTACR_RWPT	BIT(5)
46e392d603SRobin Murphy 
4722006994SStephen Boyd #define CNTVCT_LO	0x08
4822006994SStephen Boyd #define CNTVCT_HI	0x0c
4922006994SStephen Boyd #define CNTFRQ		0x10
5022006994SStephen Boyd #define CNTP_TVAL	0x28
5122006994SStephen Boyd #define CNTP_CTL	0x2c
5222006994SStephen Boyd #define CNTV_TVAL	0x38
5322006994SStephen Boyd #define CNTV_CTL	0x3c
5422006994SStephen Boyd 
5522006994SStephen Boyd #define ARCH_CP15_TIMER	BIT(0)
5622006994SStephen Boyd #define ARCH_MEM_TIMER	BIT(1)
5722006994SStephen Boyd static unsigned arch_timers_present __initdata;
5822006994SStephen Boyd 
5922006994SStephen Boyd static void __iomem *arch_counter_base;
6022006994SStephen Boyd 
6122006994SStephen Boyd struct arch_timer {
6222006994SStephen Boyd 	void __iomem *base;
6322006994SStephen Boyd 	struct clock_event_device evt;
6422006994SStephen Boyd };
6522006994SStephen Boyd 
6622006994SStephen Boyd #define to_arch_timer(e) container_of(e, struct arch_timer, evt)
6722006994SStephen Boyd 
688a4da6e3SMark Rutland static u32 arch_timer_rate;
698a4da6e3SMark Rutland 
708a4da6e3SMark Rutland enum ppi_nr {
718a4da6e3SMark Rutland 	PHYS_SECURE_PPI,
728a4da6e3SMark Rutland 	PHYS_NONSECURE_PPI,
738a4da6e3SMark Rutland 	VIRT_PPI,
748a4da6e3SMark Rutland 	HYP_PPI,
758a4da6e3SMark Rutland 	MAX_TIMER_PPI
768a4da6e3SMark Rutland };
778a4da6e3SMark Rutland 
788a4da6e3SMark Rutland static int arch_timer_ppi[MAX_TIMER_PPI];
798a4da6e3SMark Rutland 
808a4da6e3SMark Rutland static struct clock_event_device __percpu *arch_timer_evt;
818a4da6e3SMark Rutland 
82f81f03faSMarc Zyngier static enum ppi_nr arch_timer_uses_ppi = VIRT_PPI;
8382a56194SLorenzo Pieralisi static bool arch_timer_c3stop;
8422006994SStephen Boyd static bool arch_timer_mem_use_virtual;
85d8ec7595SBrian Norris static bool arch_counter_suspend_stop;
868a4da6e3SMark Rutland 
8746fd5c6bSWill Deacon static bool evtstrm_enable = IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM);
8846fd5c6bSWill Deacon 
8946fd5c6bSWill Deacon static int __init early_evtstrm_cfg(char *buf)
9046fd5c6bSWill Deacon {
9146fd5c6bSWill Deacon 	return strtobool(buf, &evtstrm_enable);
9246fd5c6bSWill Deacon }
9346fd5c6bSWill Deacon early_param("clocksource.arm_arch_timer.evtstrm", early_evtstrm_cfg);
9446fd5c6bSWill Deacon 
958a4da6e3SMark Rutland /*
968a4da6e3SMark Rutland  * Architected system timer support.
978a4da6e3SMark Rutland  */
988a4da6e3SMark Rutland 
99*f4e00a1aSMarc Zyngier static __always_inline
100*f4e00a1aSMarc Zyngier void arch_timer_reg_write(int access, enum arch_timer_reg reg, u32 val,
101*f4e00a1aSMarc Zyngier 			  struct clock_event_device *clk)
102*f4e00a1aSMarc Zyngier {
103*f4e00a1aSMarc Zyngier 	if (access == ARCH_TIMER_MEM_PHYS_ACCESS) {
104*f4e00a1aSMarc Zyngier 		struct arch_timer *timer = to_arch_timer(clk);
105*f4e00a1aSMarc Zyngier 		switch (reg) {
106*f4e00a1aSMarc Zyngier 		case ARCH_TIMER_REG_CTRL:
107*f4e00a1aSMarc Zyngier 			writel_relaxed(val, timer->base + CNTP_CTL);
108*f4e00a1aSMarc Zyngier 			break;
109*f4e00a1aSMarc Zyngier 		case ARCH_TIMER_REG_TVAL:
110*f4e00a1aSMarc Zyngier 			writel_relaxed(val, timer->base + CNTP_TVAL);
111*f4e00a1aSMarc Zyngier 			break;
112*f4e00a1aSMarc Zyngier 		}
113*f4e00a1aSMarc Zyngier 	} else if (access == ARCH_TIMER_MEM_VIRT_ACCESS) {
114*f4e00a1aSMarc Zyngier 		struct arch_timer *timer = to_arch_timer(clk);
115*f4e00a1aSMarc Zyngier 		switch (reg) {
116*f4e00a1aSMarc Zyngier 		case ARCH_TIMER_REG_CTRL:
117*f4e00a1aSMarc Zyngier 			writel_relaxed(val, timer->base + CNTV_CTL);
118*f4e00a1aSMarc Zyngier 			break;
119*f4e00a1aSMarc Zyngier 		case ARCH_TIMER_REG_TVAL:
120*f4e00a1aSMarc Zyngier 			writel_relaxed(val, timer->base + CNTV_TVAL);
121*f4e00a1aSMarc Zyngier 			break;
122*f4e00a1aSMarc Zyngier 		}
123*f4e00a1aSMarc Zyngier 	} else {
124*f4e00a1aSMarc Zyngier 		arch_timer_reg_write_cp15(access, reg, val);
125*f4e00a1aSMarc Zyngier 	}
126*f4e00a1aSMarc Zyngier }
127*f4e00a1aSMarc Zyngier 
128*f4e00a1aSMarc Zyngier static __always_inline
129*f4e00a1aSMarc Zyngier u32 arch_timer_reg_read(int access, enum arch_timer_reg reg,
130*f4e00a1aSMarc Zyngier 			struct clock_event_device *clk)
131*f4e00a1aSMarc Zyngier {
132*f4e00a1aSMarc Zyngier 	u32 val;
133*f4e00a1aSMarc Zyngier 
134*f4e00a1aSMarc Zyngier 	if (access == ARCH_TIMER_MEM_PHYS_ACCESS) {
135*f4e00a1aSMarc Zyngier 		struct arch_timer *timer = to_arch_timer(clk);
136*f4e00a1aSMarc Zyngier 		switch (reg) {
137*f4e00a1aSMarc Zyngier 		case ARCH_TIMER_REG_CTRL:
138*f4e00a1aSMarc Zyngier 			val = readl_relaxed(timer->base + CNTP_CTL);
139*f4e00a1aSMarc Zyngier 			break;
140*f4e00a1aSMarc Zyngier 		case ARCH_TIMER_REG_TVAL:
141*f4e00a1aSMarc Zyngier 			val = readl_relaxed(timer->base + CNTP_TVAL);
142*f4e00a1aSMarc Zyngier 			break;
143*f4e00a1aSMarc Zyngier 		}
144*f4e00a1aSMarc Zyngier 	} else if (access == ARCH_TIMER_MEM_VIRT_ACCESS) {
145*f4e00a1aSMarc Zyngier 		struct arch_timer *timer = to_arch_timer(clk);
146*f4e00a1aSMarc Zyngier 		switch (reg) {
147*f4e00a1aSMarc Zyngier 		case ARCH_TIMER_REG_CTRL:
148*f4e00a1aSMarc Zyngier 			val = readl_relaxed(timer->base + CNTV_CTL);
149*f4e00a1aSMarc Zyngier 			break;
150*f4e00a1aSMarc Zyngier 		case ARCH_TIMER_REG_TVAL:
151*f4e00a1aSMarc Zyngier 			val = readl_relaxed(timer->base + CNTV_TVAL);
152*f4e00a1aSMarc Zyngier 			break;
153*f4e00a1aSMarc Zyngier 		}
154*f4e00a1aSMarc Zyngier 	} else {
155*f4e00a1aSMarc Zyngier 		val = arch_timer_reg_read_cp15(access, reg);
156*f4e00a1aSMarc Zyngier 	}
157*f4e00a1aSMarc Zyngier 
158*f4e00a1aSMarc Zyngier 	return val;
159*f4e00a1aSMarc Zyngier }
160*f4e00a1aSMarc Zyngier 
161f6dc1576SScott Wood #ifdef CONFIG_FSL_ERRATUM_A008585
16216d10ef2SDing Tianhong /*
16316d10ef2SDing Tianhong  * The number of retries is an arbitrary value well beyond the highest number
16416d10ef2SDing Tianhong  * of iterations the loop has been observed to take.
16516d10ef2SDing Tianhong  */
16616d10ef2SDing Tianhong #define __fsl_a008585_read_reg(reg) ({			\
16716d10ef2SDing Tianhong 	u64 _old, _new;					\
16816d10ef2SDing Tianhong 	int _retries = 200;				\
16916d10ef2SDing Tianhong 							\
17016d10ef2SDing Tianhong 	do {						\
17116d10ef2SDing Tianhong 		_old = read_sysreg(reg);		\
17216d10ef2SDing Tianhong 		_new = read_sysreg(reg);		\
17316d10ef2SDing Tianhong 		_retries--;				\
17416d10ef2SDing Tianhong 	} while (unlikely(_old != _new) && _retries);	\
17516d10ef2SDing Tianhong 							\
17616d10ef2SDing Tianhong 	WARN_ON_ONCE(!_retries);			\
17716d10ef2SDing Tianhong 	_new;						\
17816d10ef2SDing Tianhong })
179f6dc1576SScott Wood 
18016d10ef2SDing Tianhong static u32 notrace fsl_a008585_read_cntp_tval_el0(void)
181f6dc1576SScott Wood {
182f6dc1576SScott Wood 	return __fsl_a008585_read_reg(cntp_tval_el0);
183f6dc1576SScott Wood }
184f6dc1576SScott Wood 
18516d10ef2SDing Tianhong static u32 notrace fsl_a008585_read_cntv_tval_el0(void)
186f6dc1576SScott Wood {
187f6dc1576SScott Wood 	return __fsl_a008585_read_reg(cntv_tval_el0);
188f6dc1576SScott Wood }
189f6dc1576SScott Wood 
19016d10ef2SDing Tianhong static u64 notrace fsl_a008585_read_cntvct_el0(void)
191f6dc1576SScott Wood {
192f6dc1576SScott Wood 	return __fsl_a008585_read_reg(cntvct_el0);
193f6dc1576SScott Wood }
19416d10ef2SDing Tianhong #endif
19516d10ef2SDing Tianhong 
196bb42ca47SDing Tianhong #ifdef CONFIG_HISILICON_ERRATUM_161010101
197bb42ca47SDing Tianhong /*
198bb42ca47SDing Tianhong  * Verify whether the value of the second read is larger than the first by
199bb42ca47SDing Tianhong  * less than 32 is the only way to confirm the value is correct, so clear the
200bb42ca47SDing Tianhong  * lower 5 bits to check whether the difference is greater than 32 or not.
201bb42ca47SDing Tianhong  * Theoretically the erratum should not occur more than twice in succession
202bb42ca47SDing Tianhong  * when reading the system counter, but it is possible that some interrupts
203bb42ca47SDing Tianhong  * may lead to more than twice read errors, triggering the warning, so setting
204bb42ca47SDing Tianhong  * the number of retries far beyond the number of iterations the loop has been
205bb42ca47SDing Tianhong  * observed to take.
206bb42ca47SDing Tianhong  */
207bb42ca47SDing Tianhong #define __hisi_161010101_read_reg(reg) ({				\
208bb42ca47SDing Tianhong 	u64 _old, _new;						\
209bb42ca47SDing Tianhong 	int _retries = 50;					\
210bb42ca47SDing Tianhong 								\
211bb42ca47SDing Tianhong 	do {							\
212bb42ca47SDing Tianhong 		_old = read_sysreg(reg);			\
213bb42ca47SDing Tianhong 		_new = read_sysreg(reg);			\
214bb42ca47SDing Tianhong 		_retries--;					\
215bb42ca47SDing Tianhong 	} while (unlikely((_new - _old) >> 5) && _retries);	\
216bb42ca47SDing Tianhong 								\
217bb42ca47SDing Tianhong 	WARN_ON_ONCE(!_retries);				\
218bb42ca47SDing Tianhong 	_new;							\
219bb42ca47SDing Tianhong })
220bb42ca47SDing Tianhong 
221bb42ca47SDing Tianhong static u32 notrace hisi_161010101_read_cntp_tval_el0(void)
222bb42ca47SDing Tianhong {
223bb42ca47SDing Tianhong 	return __hisi_161010101_read_reg(cntp_tval_el0);
224bb42ca47SDing Tianhong }
225bb42ca47SDing Tianhong 
226bb42ca47SDing Tianhong static u32 notrace hisi_161010101_read_cntv_tval_el0(void)
227bb42ca47SDing Tianhong {
228bb42ca47SDing Tianhong 	return __hisi_161010101_read_reg(cntv_tval_el0);
229bb42ca47SDing Tianhong }
230bb42ca47SDing Tianhong 
231bb42ca47SDing Tianhong static u64 notrace hisi_161010101_read_cntvct_el0(void)
232bb42ca47SDing Tianhong {
233bb42ca47SDing Tianhong 	return __hisi_161010101_read_reg(cntvct_el0);
234bb42ca47SDing Tianhong }
235bb42ca47SDing Tianhong #endif
236bb42ca47SDing Tianhong 
23716d10ef2SDing Tianhong #ifdef CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND
23816d10ef2SDing Tianhong const struct arch_timer_erratum_workaround *timer_unstable_counter_workaround = NULL;
23916d10ef2SDing Tianhong EXPORT_SYMBOL_GPL(timer_unstable_counter_workaround);
24016d10ef2SDing Tianhong 
24116d10ef2SDing Tianhong DEFINE_STATIC_KEY_FALSE(arch_timer_read_ool_enabled);
24216d10ef2SDing Tianhong EXPORT_SYMBOL_GPL(arch_timer_read_ool_enabled);
24316d10ef2SDing Tianhong 
24416d10ef2SDing Tianhong static const struct arch_timer_erratum_workaround ool_workarounds[] = {
24516d10ef2SDing Tianhong #ifdef CONFIG_FSL_ERRATUM_A008585
24616d10ef2SDing Tianhong 	{
247651bb2e9SMarc Zyngier 		.match_type = ate_match_dt,
24816d10ef2SDing Tianhong 		.id = "fsl,erratum-a008585",
249651bb2e9SMarc Zyngier 		.desc = "Freescale erratum a005858",
25016d10ef2SDing Tianhong 		.read_cntp_tval_el0 = fsl_a008585_read_cntp_tval_el0,
25116d10ef2SDing Tianhong 		.read_cntv_tval_el0 = fsl_a008585_read_cntv_tval_el0,
25216d10ef2SDing Tianhong 		.read_cntvct_el0 = fsl_a008585_read_cntvct_el0,
25316d10ef2SDing Tianhong 	},
25416d10ef2SDing Tianhong #endif
255bb42ca47SDing Tianhong #ifdef CONFIG_HISILICON_ERRATUM_161010101
256bb42ca47SDing Tianhong 	{
257651bb2e9SMarc Zyngier 		.match_type = ate_match_dt,
258bb42ca47SDing Tianhong 		.id = "hisilicon,erratum-161010101",
259651bb2e9SMarc Zyngier 		.desc = "HiSilicon erratum 161010101",
260bb42ca47SDing Tianhong 		.read_cntp_tval_el0 = hisi_161010101_read_cntp_tval_el0,
261bb42ca47SDing Tianhong 		.read_cntv_tval_el0 = hisi_161010101_read_cntv_tval_el0,
262bb42ca47SDing Tianhong 		.read_cntvct_el0 = hisi_161010101_read_cntvct_el0,
263bb42ca47SDing Tianhong 	},
264bb42ca47SDing Tianhong #endif
26516d10ef2SDing Tianhong };
266651bb2e9SMarc Zyngier 
267651bb2e9SMarc Zyngier typedef bool (*ate_match_fn_t)(const struct arch_timer_erratum_workaround *,
268651bb2e9SMarc Zyngier 			       const void *);
269651bb2e9SMarc Zyngier 
270651bb2e9SMarc Zyngier static
271651bb2e9SMarc Zyngier bool arch_timer_check_dt_erratum(const struct arch_timer_erratum_workaround *wa,
272651bb2e9SMarc Zyngier 				 const void *arg)
273651bb2e9SMarc Zyngier {
274651bb2e9SMarc Zyngier 	const struct device_node *np = arg;
275651bb2e9SMarc Zyngier 
276651bb2e9SMarc Zyngier 	return of_property_read_bool(np, wa->id);
277651bb2e9SMarc Zyngier }
278651bb2e9SMarc Zyngier 
2790064030cSMarc Zyngier static
2800064030cSMarc Zyngier bool arch_timer_check_local_cap_erratum(const struct arch_timer_erratum_workaround *wa,
2810064030cSMarc Zyngier 					const void *arg)
2820064030cSMarc Zyngier {
2830064030cSMarc Zyngier 	return this_cpu_has_cap((uintptr_t)wa->id);
2840064030cSMarc Zyngier }
2850064030cSMarc Zyngier 
286651bb2e9SMarc Zyngier static const struct arch_timer_erratum_workaround *
287651bb2e9SMarc Zyngier arch_timer_iterate_errata(enum arch_timer_erratum_match_type type,
288651bb2e9SMarc Zyngier 			  ate_match_fn_t match_fn,
289651bb2e9SMarc Zyngier 			  void *arg)
290651bb2e9SMarc Zyngier {
291651bb2e9SMarc Zyngier 	int i;
292651bb2e9SMarc Zyngier 
293651bb2e9SMarc Zyngier 	for (i = 0; i < ARRAY_SIZE(ool_workarounds); i++) {
294651bb2e9SMarc Zyngier 		if (ool_workarounds[i].match_type != type)
295651bb2e9SMarc Zyngier 			continue;
296651bb2e9SMarc Zyngier 
297651bb2e9SMarc Zyngier 		if (match_fn(&ool_workarounds[i], arg))
298651bb2e9SMarc Zyngier 			return &ool_workarounds[i];
299651bb2e9SMarc Zyngier 	}
300651bb2e9SMarc Zyngier 
301651bb2e9SMarc Zyngier 	return NULL;
302651bb2e9SMarc Zyngier }
303651bb2e9SMarc Zyngier 
304651bb2e9SMarc Zyngier static
305651bb2e9SMarc Zyngier void arch_timer_enable_workaround(const struct arch_timer_erratum_workaround *wa)
306651bb2e9SMarc Zyngier {
307651bb2e9SMarc Zyngier 	timer_unstable_counter_workaround = wa;
308651bb2e9SMarc Zyngier 	static_branch_enable(&arch_timer_read_ool_enabled);
309651bb2e9SMarc Zyngier }
310651bb2e9SMarc Zyngier 
311651bb2e9SMarc Zyngier static void arch_timer_check_ool_workaround(enum arch_timer_erratum_match_type type,
312651bb2e9SMarc Zyngier 					    void *arg)
313651bb2e9SMarc Zyngier {
314651bb2e9SMarc Zyngier 	const struct arch_timer_erratum_workaround *wa;
315651bb2e9SMarc Zyngier 	ate_match_fn_t match_fn = NULL;
3160064030cSMarc Zyngier 	bool local = false;
317651bb2e9SMarc Zyngier 
318651bb2e9SMarc Zyngier 	switch (type) {
319651bb2e9SMarc Zyngier 	case ate_match_dt:
320651bb2e9SMarc Zyngier 		match_fn = arch_timer_check_dt_erratum;
321651bb2e9SMarc Zyngier 		break;
3220064030cSMarc Zyngier 	case ate_match_local_cap_id:
3230064030cSMarc Zyngier 		match_fn = arch_timer_check_local_cap_erratum;
3240064030cSMarc Zyngier 		local = true;
3250064030cSMarc Zyngier 		break;
326651bb2e9SMarc Zyngier 	default:
327651bb2e9SMarc Zyngier 		WARN_ON(1);
328651bb2e9SMarc Zyngier 		return;
329651bb2e9SMarc Zyngier 	}
330651bb2e9SMarc Zyngier 
331651bb2e9SMarc Zyngier 	wa = arch_timer_iterate_errata(type, match_fn, arg);
332651bb2e9SMarc Zyngier 	if (!wa)
333651bb2e9SMarc Zyngier 		return;
334651bb2e9SMarc Zyngier 
3350064030cSMarc Zyngier 	if (needs_unstable_timer_counter_workaround()) {
3360064030cSMarc Zyngier 		if (wa != timer_unstable_counter_workaround)
3370064030cSMarc Zyngier 			pr_warn("Can't enable workaround for %s (clashes with %s\n)",
3380064030cSMarc Zyngier 				wa->desc,
3390064030cSMarc Zyngier 				timer_unstable_counter_workaround->desc);
3400064030cSMarc Zyngier 		return;
3410064030cSMarc Zyngier 	}
3420064030cSMarc Zyngier 
343651bb2e9SMarc Zyngier 	arch_timer_enable_workaround(wa);
3440064030cSMarc Zyngier 	pr_info("Enabling %s workaround for %s\n",
3450064030cSMarc Zyngier 		local ? "local" : "global", wa->desc);
346651bb2e9SMarc Zyngier }
347651bb2e9SMarc Zyngier 
348651bb2e9SMarc Zyngier #else
349651bb2e9SMarc Zyngier #define arch_timer_check_ool_workaround(t,a)		do { } while(0)
35016d10ef2SDing Tianhong #endif /* CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND */
351f6dc1576SScott Wood 
352e09f3cc0SStephen Boyd static __always_inline irqreturn_t timer_handler(const int access,
3538a4da6e3SMark Rutland 					struct clock_event_device *evt)
3548a4da6e3SMark Rutland {
3558a4da6e3SMark Rutland 	unsigned long ctrl;
356cfb6d656SThomas Gleixner 
35760faddf6SStephen Boyd 	ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL, evt);
3588a4da6e3SMark Rutland 	if (ctrl & ARCH_TIMER_CTRL_IT_STAT) {
3598a4da6e3SMark Rutland 		ctrl |= ARCH_TIMER_CTRL_IT_MASK;
36060faddf6SStephen Boyd 		arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, evt);
3618a4da6e3SMark Rutland 		evt->event_handler(evt);
3628a4da6e3SMark Rutland 		return IRQ_HANDLED;
3638a4da6e3SMark Rutland 	}
3648a4da6e3SMark Rutland 
3658a4da6e3SMark Rutland 	return IRQ_NONE;
3668a4da6e3SMark Rutland }
3678a4da6e3SMark Rutland 
3688a4da6e3SMark Rutland static irqreturn_t arch_timer_handler_virt(int irq, void *dev_id)
3698a4da6e3SMark Rutland {
3708a4da6e3SMark Rutland 	struct clock_event_device *evt = dev_id;
3718a4da6e3SMark Rutland 
3728a4da6e3SMark Rutland 	return timer_handler(ARCH_TIMER_VIRT_ACCESS, evt);
3738a4da6e3SMark Rutland }
3748a4da6e3SMark Rutland 
3758a4da6e3SMark Rutland static irqreturn_t arch_timer_handler_phys(int irq, void *dev_id)
3768a4da6e3SMark Rutland {
3778a4da6e3SMark Rutland 	struct clock_event_device *evt = dev_id;
3788a4da6e3SMark Rutland 
3798a4da6e3SMark Rutland 	return timer_handler(ARCH_TIMER_PHYS_ACCESS, evt);
3808a4da6e3SMark Rutland }
3818a4da6e3SMark Rutland 
38222006994SStephen Boyd static irqreturn_t arch_timer_handler_phys_mem(int irq, void *dev_id)
38322006994SStephen Boyd {
38422006994SStephen Boyd 	struct clock_event_device *evt = dev_id;
38522006994SStephen Boyd 
38622006994SStephen Boyd 	return timer_handler(ARCH_TIMER_MEM_PHYS_ACCESS, evt);
38722006994SStephen Boyd }
38822006994SStephen Boyd 
38922006994SStephen Boyd static irqreturn_t arch_timer_handler_virt_mem(int irq, void *dev_id)
39022006994SStephen Boyd {
39122006994SStephen Boyd 	struct clock_event_device *evt = dev_id;
39222006994SStephen Boyd 
39322006994SStephen Boyd 	return timer_handler(ARCH_TIMER_MEM_VIRT_ACCESS, evt);
39422006994SStephen Boyd }
39522006994SStephen Boyd 
39646c5bfddSViresh Kumar static __always_inline int timer_shutdown(const int access,
39760faddf6SStephen Boyd 					  struct clock_event_device *clk)
3988a4da6e3SMark Rutland {
3998a4da6e3SMark Rutland 	unsigned long ctrl;
40046c5bfddSViresh Kumar 
40160faddf6SStephen Boyd 	ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL, clk);
4028a4da6e3SMark Rutland 	ctrl &= ~ARCH_TIMER_CTRL_ENABLE;
40360faddf6SStephen Boyd 	arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk);
40446c5bfddSViresh Kumar 
40546c5bfddSViresh Kumar 	return 0;
4068a4da6e3SMark Rutland }
4078a4da6e3SMark Rutland 
40846c5bfddSViresh Kumar static int arch_timer_shutdown_virt(struct clock_event_device *clk)
4098a4da6e3SMark Rutland {
41046c5bfddSViresh Kumar 	return timer_shutdown(ARCH_TIMER_VIRT_ACCESS, clk);
4118a4da6e3SMark Rutland }
4128a4da6e3SMark Rutland 
41346c5bfddSViresh Kumar static int arch_timer_shutdown_phys(struct clock_event_device *clk)
4148a4da6e3SMark Rutland {
41546c5bfddSViresh Kumar 	return timer_shutdown(ARCH_TIMER_PHYS_ACCESS, clk);
4168a4da6e3SMark Rutland }
4178a4da6e3SMark Rutland 
41846c5bfddSViresh Kumar static int arch_timer_shutdown_virt_mem(struct clock_event_device *clk)
41922006994SStephen Boyd {
42046c5bfddSViresh Kumar 	return timer_shutdown(ARCH_TIMER_MEM_VIRT_ACCESS, clk);
42122006994SStephen Boyd }
42222006994SStephen Boyd 
42346c5bfddSViresh Kumar static int arch_timer_shutdown_phys_mem(struct clock_event_device *clk)
42422006994SStephen Boyd {
42546c5bfddSViresh Kumar 	return timer_shutdown(ARCH_TIMER_MEM_PHYS_ACCESS, clk);
42622006994SStephen Boyd }
42722006994SStephen Boyd 
42860faddf6SStephen Boyd static __always_inline void set_next_event(const int access, unsigned long evt,
42960faddf6SStephen Boyd 					   struct clock_event_device *clk)
4308a4da6e3SMark Rutland {
4318a4da6e3SMark Rutland 	unsigned long ctrl;
43260faddf6SStephen Boyd 	ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL, clk);
4338a4da6e3SMark Rutland 	ctrl |= ARCH_TIMER_CTRL_ENABLE;
4348a4da6e3SMark Rutland 	ctrl &= ~ARCH_TIMER_CTRL_IT_MASK;
43560faddf6SStephen Boyd 	arch_timer_reg_write(access, ARCH_TIMER_REG_TVAL, evt, clk);
43660faddf6SStephen Boyd 	arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk);
4378a4da6e3SMark Rutland }
4388a4da6e3SMark Rutland 
43916d10ef2SDing Tianhong #ifdef CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND
44016d10ef2SDing Tianhong static __always_inline void erratum_set_next_event_generic(const int access,
441f6dc1576SScott Wood 		unsigned long evt, struct clock_event_device *clk)
442f6dc1576SScott Wood {
443f6dc1576SScott Wood 	unsigned long ctrl;
444f6dc1576SScott Wood 	u64 cval = evt + arch_counter_get_cntvct();
445f6dc1576SScott Wood 
446f6dc1576SScott Wood 	ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL, clk);
447f6dc1576SScott Wood 	ctrl |= ARCH_TIMER_CTRL_ENABLE;
448f6dc1576SScott Wood 	ctrl &= ~ARCH_TIMER_CTRL_IT_MASK;
449f6dc1576SScott Wood 
450f6dc1576SScott Wood 	if (access == ARCH_TIMER_PHYS_ACCESS)
451f6dc1576SScott Wood 		write_sysreg(cval, cntp_cval_el0);
452f6dc1576SScott Wood 	else if (access == ARCH_TIMER_VIRT_ACCESS)
453f6dc1576SScott Wood 		write_sysreg(cval, cntv_cval_el0);
454f6dc1576SScott Wood 
455f6dc1576SScott Wood 	arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk);
456f6dc1576SScott Wood }
457f6dc1576SScott Wood 
45816d10ef2SDing Tianhong static int erratum_set_next_event_virt(unsigned long evt,
459f6dc1576SScott Wood 					   struct clock_event_device *clk)
460f6dc1576SScott Wood {
46116d10ef2SDing Tianhong 	erratum_set_next_event_generic(ARCH_TIMER_VIRT_ACCESS, evt, clk);
462f6dc1576SScott Wood 	return 0;
463f6dc1576SScott Wood }
464f6dc1576SScott Wood 
46516d10ef2SDing Tianhong static int erratum_set_next_event_phys(unsigned long evt,
466f6dc1576SScott Wood 					   struct clock_event_device *clk)
467f6dc1576SScott Wood {
46816d10ef2SDing Tianhong 	erratum_set_next_event_generic(ARCH_TIMER_PHYS_ACCESS, evt, clk);
469f6dc1576SScott Wood 	return 0;
470f6dc1576SScott Wood }
47116d10ef2SDing Tianhong #endif /* CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND */
472f6dc1576SScott Wood 
4738a4da6e3SMark Rutland static int arch_timer_set_next_event_virt(unsigned long evt,
47460faddf6SStephen Boyd 					  struct clock_event_device *clk)
4758a4da6e3SMark Rutland {
47660faddf6SStephen Boyd 	set_next_event(ARCH_TIMER_VIRT_ACCESS, evt, clk);
4778a4da6e3SMark Rutland 	return 0;
4788a4da6e3SMark Rutland }
4798a4da6e3SMark Rutland 
4808a4da6e3SMark Rutland static int arch_timer_set_next_event_phys(unsigned long evt,
48160faddf6SStephen Boyd 					  struct clock_event_device *clk)
4828a4da6e3SMark Rutland {
48360faddf6SStephen Boyd 	set_next_event(ARCH_TIMER_PHYS_ACCESS, evt, clk);
4848a4da6e3SMark Rutland 	return 0;
4858a4da6e3SMark Rutland }
4868a4da6e3SMark Rutland 
48722006994SStephen Boyd static int arch_timer_set_next_event_virt_mem(unsigned long evt,
48822006994SStephen Boyd 					      struct clock_event_device *clk)
4898a4da6e3SMark Rutland {
49022006994SStephen Boyd 	set_next_event(ARCH_TIMER_MEM_VIRT_ACCESS, evt, clk);
49122006994SStephen Boyd 	return 0;
49222006994SStephen Boyd }
49322006994SStephen Boyd 
49422006994SStephen Boyd static int arch_timer_set_next_event_phys_mem(unsigned long evt,
49522006994SStephen Boyd 					      struct clock_event_device *clk)
49622006994SStephen Boyd {
49722006994SStephen Boyd 	set_next_event(ARCH_TIMER_MEM_PHYS_ACCESS, evt, clk);
49822006994SStephen Boyd 	return 0;
49922006994SStephen Boyd }
50022006994SStephen Boyd 
50116d10ef2SDing Tianhong static void erratum_workaround_set_sne(struct clock_event_device *clk)
502f6dc1576SScott Wood {
50316d10ef2SDing Tianhong #ifdef CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND
504f6dc1576SScott Wood 	if (!static_branch_unlikely(&arch_timer_read_ool_enabled))
505f6dc1576SScott Wood 		return;
506f6dc1576SScott Wood 
507f6dc1576SScott Wood 	if (arch_timer_uses_ppi == VIRT_PPI)
50816d10ef2SDing Tianhong 		clk->set_next_event = erratum_set_next_event_virt;
509f6dc1576SScott Wood 	else
51016d10ef2SDing Tianhong 		clk->set_next_event = erratum_set_next_event_phys;
511f6dc1576SScott Wood #endif
512f6dc1576SScott Wood }
513f6dc1576SScott Wood 
514cfb6d656SThomas Gleixner static void __arch_timer_setup(unsigned type,
51522006994SStephen Boyd 			       struct clock_event_device *clk)
51622006994SStephen Boyd {
51722006994SStephen Boyd 	clk->features = CLOCK_EVT_FEAT_ONESHOT;
51822006994SStephen Boyd 
51922006994SStephen Boyd 	if (type == ARCH_CP15_TIMER) {
52082a56194SLorenzo Pieralisi 		if (arch_timer_c3stop)
52122006994SStephen Boyd 			clk->features |= CLOCK_EVT_FEAT_C3STOP;
5228a4da6e3SMark Rutland 		clk->name = "arch_sys_timer";
5238a4da6e3SMark Rutland 		clk->rating = 450;
52422006994SStephen Boyd 		clk->cpumask = cpumask_of(smp_processor_id());
525f81f03faSMarc Zyngier 		clk->irq = arch_timer_ppi[arch_timer_uses_ppi];
526f81f03faSMarc Zyngier 		switch (arch_timer_uses_ppi) {
527f81f03faSMarc Zyngier 		case VIRT_PPI:
52846c5bfddSViresh Kumar 			clk->set_state_shutdown = arch_timer_shutdown_virt;
529cf8c5009SViresh Kumar 			clk->set_state_oneshot_stopped = arch_timer_shutdown_virt;
5308a4da6e3SMark Rutland 			clk->set_next_event = arch_timer_set_next_event_virt;
531f81f03faSMarc Zyngier 			break;
532f81f03faSMarc Zyngier 		case PHYS_SECURE_PPI:
533f81f03faSMarc Zyngier 		case PHYS_NONSECURE_PPI:
534f81f03faSMarc Zyngier 		case HYP_PPI:
53546c5bfddSViresh Kumar 			clk->set_state_shutdown = arch_timer_shutdown_phys;
536cf8c5009SViresh Kumar 			clk->set_state_oneshot_stopped = arch_timer_shutdown_phys;
5378a4da6e3SMark Rutland 			clk->set_next_event = arch_timer_set_next_event_phys;
538f81f03faSMarc Zyngier 			break;
539f81f03faSMarc Zyngier 		default:
540f81f03faSMarc Zyngier 			BUG();
5418a4da6e3SMark Rutland 		}
542f6dc1576SScott Wood 
5430064030cSMarc Zyngier 		arch_timer_check_ool_workaround(ate_match_local_cap_id, NULL);
5440064030cSMarc Zyngier 
54516d10ef2SDing Tianhong 		erratum_workaround_set_sne(clk);
54622006994SStephen Boyd 	} else {
5477b52ad2eSStephen Boyd 		clk->features |= CLOCK_EVT_FEAT_DYNIRQ;
54822006994SStephen Boyd 		clk->name = "arch_mem_timer";
54922006994SStephen Boyd 		clk->rating = 400;
55022006994SStephen Boyd 		clk->cpumask = cpu_all_mask;
55122006994SStephen Boyd 		if (arch_timer_mem_use_virtual) {
55246c5bfddSViresh Kumar 			clk->set_state_shutdown = arch_timer_shutdown_virt_mem;
553cf8c5009SViresh Kumar 			clk->set_state_oneshot_stopped = arch_timer_shutdown_virt_mem;
55422006994SStephen Boyd 			clk->set_next_event =
55522006994SStephen Boyd 				arch_timer_set_next_event_virt_mem;
55622006994SStephen Boyd 		} else {
55746c5bfddSViresh Kumar 			clk->set_state_shutdown = arch_timer_shutdown_phys_mem;
558cf8c5009SViresh Kumar 			clk->set_state_oneshot_stopped = arch_timer_shutdown_phys_mem;
55922006994SStephen Boyd 			clk->set_next_event =
56022006994SStephen Boyd 				arch_timer_set_next_event_phys_mem;
56122006994SStephen Boyd 		}
56222006994SStephen Boyd 	}
5638a4da6e3SMark Rutland 
56446c5bfddSViresh Kumar 	clk->set_state_shutdown(clk);
5658a4da6e3SMark Rutland 
56622006994SStephen Boyd 	clockevents_config_and_register(clk, arch_timer_rate, 0xf, 0x7fffffff);
56722006994SStephen Boyd }
5688a4da6e3SMark Rutland 
569e1ce5c7aSNathan Lynch static void arch_timer_evtstrm_enable(int divider)
570e1ce5c7aSNathan Lynch {
571e1ce5c7aSNathan Lynch 	u32 cntkctl = arch_timer_get_cntkctl();
572e1ce5c7aSNathan Lynch 
573e1ce5c7aSNathan Lynch 	cntkctl &= ~ARCH_TIMER_EVT_TRIGGER_MASK;
574e1ce5c7aSNathan Lynch 	/* Set the divider and enable virtual event stream */
575e1ce5c7aSNathan Lynch 	cntkctl |= (divider << ARCH_TIMER_EVT_TRIGGER_SHIFT)
576e1ce5c7aSNathan Lynch 			| ARCH_TIMER_VIRT_EVT_EN;
577e1ce5c7aSNathan Lynch 	arch_timer_set_cntkctl(cntkctl);
578e1ce5c7aSNathan Lynch 	elf_hwcap |= HWCAP_EVTSTRM;
579e1ce5c7aSNathan Lynch #ifdef CONFIG_COMPAT
580e1ce5c7aSNathan Lynch 	compat_elf_hwcap |= COMPAT_HWCAP_EVTSTRM;
581e1ce5c7aSNathan Lynch #endif
582e1ce5c7aSNathan Lynch }
583e1ce5c7aSNathan Lynch 
584037f6377SWill Deacon static void arch_timer_configure_evtstream(void)
585037f6377SWill Deacon {
586037f6377SWill Deacon 	int evt_stream_div, pos;
587037f6377SWill Deacon 
588037f6377SWill Deacon 	/* Find the closest power of two to the divisor */
589037f6377SWill Deacon 	evt_stream_div = arch_timer_rate / ARCH_TIMER_EVT_STREAM_FREQ;
590037f6377SWill Deacon 	pos = fls(evt_stream_div);
591037f6377SWill Deacon 	if (pos > 1 && !(evt_stream_div & (1 << (pos - 2))))
592037f6377SWill Deacon 		pos--;
593037f6377SWill Deacon 	/* enable event stream */
594037f6377SWill Deacon 	arch_timer_evtstrm_enable(min(pos, 15));
595037f6377SWill Deacon }
596037f6377SWill Deacon 
5978b8dde00SNathan Lynch static void arch_counter_set_user_access(void)
5988b8dde00SNathan Lynch {
5998b8dde00SNathan Lynch 	u32 cntkctl = arch_timer_get_cntkctl();
6008b8dde00SNathan Lynch 
6018b8dde00SNathan Lynch 	/* Disable user access to the timers and the physical counter */
6028b8dde00SNathan Lynch 	/* Also disable virtual event stream */
6038b8dde00SNathan Lynch 	cntkctl &= ~(ARCH_TIMER_USR_PT_ACCESS_EN
6048b8dde00SNathan Lynch 			| ARCH_TIMER_USR_VT_ACCESS_EN
6058b8dde00SNathan Lynch 			| ARCH_TIMER_VIRT_EVT_EN
6068b8dde00SNathan Lynch 			| ARCH_TIMER_USR_PCT_ACCESS_EN);
6078b8dde00SNathan Lynch 
6088b8dde00SNathan Lynch 	/* Enable user access to the virtual counter */
6098b8dde00SNathan Lynch 	cntkctl |= ARCH_TIMER_USR_VCT_ACCESS_EN;
6108b8dde00SNathan Lynch 
6118b8dde00SNathan Lynch 	arch_timer_set_cntkctl(cntkctl);
6128b8dde00SNathan Lynch }
6138b8dde00SNathan Lynch 
614f81f03faSMarc Zyngier static bool arch_timer_has_nonsecure_ppi(void)
615f81f03faSMarc Zyngier {
616f81f03faSMarc Zyngier 	return (arch_timer_uses_ppi == PHYS_SECURE_PPI &&
617f81f03faSMarc Zyngier 		arch_timer_ppi[PHYS_NONSECURE_PPI]);
618f81f03faSMarc Zyngier }
619f81f03faSMarc Zyngier 
620f005bd7eSMarc Zyngier static u32 check_ppi_trigger(int irq)
621f005bd7eSMarc Zyngier {
622f005bd7eSMarc Zyngier 	u32 flags = irq_get_trigger_type(irq);
623f005bd7eSMarc Zyngier 
624f005bd7eSMarc Zyngier 	if (flags != IRQF_TRIGGER_HIGH && flags != IRQF_TRIGGER_LOW) {
625f005bd7eSMarc Zyngier 		pr_warn("WARNING: Invalid trigger for IRQ%d, assuming level low\n", irq);
626f005bd7eSMarc Zyngier 		pr_warn("WARNING: Please fix your firmware\n");
627f005bd7eSMarc Zyngier 		flags = IRQF_TRIGGER_LOW;
628f005bd7eSMarc Zyngier 	}
629f005bd7eSMarc Zyngier 
630f005bd7eSMarc Zyngier 	return flags;
631f005bd7eSMarc Zyngier }
632f005bd7eSMarc Zyngier 
6337e86e8bdSRichard Cochran static int arch_timer_starting_cpu(unsigned int cpu)
63422006994SStephen Boyd {
6357e86e8bdSRichard Cochran 	struct clock_event_device *clk = this_cpu_ptr(arch_timer_evt);
636f005bd7eSMarc Zyngier 	u32 flags;
6377e86e8bdSRichard Cochran 
63822006994SStephen Boyd 	__arch_timer_setup(ARCH_CP15_TIMER, clk);
6398a4da6e3SMark Rutland 
640f005bd7eSMarc Zyngier 	flags = check_ppi_trigger(arch_timer_ppi[arch_timer_uses_ppi]);
641f005bd7eSMarc Zyngier 	enable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], flags);
642f81f03faSMarc Zyngier 
643f005bd7eSMarc Zyngier 	if (arch_timer_has_nonsecure_ppi()) {
644f005bd7eSMarc Zyngier 		flags = check_ppi_trigger(arch_timer_ppi[PHYS_NONSECURE_PPI]);
645f005bd7eSMarc Zyngier 		enable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], flags);
646f005bd7eSMarc Zyngier 	}
6478a4da6e3SMark Rutland 
6488a4da6e3SMark Rutland 	arch_counter_set_user_access();
64946fd5c6bSWill Deacon 	if (evtstrm_enable)
650037f6377SWill Deacon 		arch_timer_configure_evtstream();
6518a4da6e3SMark Rutland 
6528a4da6e3SMark Rutland 	return 0;
6538a4da6e3SMark Rutland }
6548a4da6e3SMark Rutland 
65522006994SStephen Boyd static void
65622006994SStephen Boyd arch_timer_detect_rate(void __iomem *cntbase, struct device_node *np)
6578a4da6e3SMark Rutland {
65822006994SStephen Boyd 	/* Who has more than one independent system counter? */
65922006994SStephen Boyd 	if (arch_timer_rate)
66022006994SStephen Boyd 		return;
6618a4da6e3SMark Rutland 
662b09ca1ecSHanjun Guo 	/*
663b09ca1ecSHanjun Guo 	 * Try to determine the frequency from the device tree or CNTFRQ,
664b09ca1ecSHanjun Guo 	 * if ACPI is enabled, get the frequency from CNTFRQ ONLY.
665b09ca1ecSHanjun Guo 	 */
666b09ca1ecSHanjun Guo 	if (!acpi_disabled ||
667b09ca1ecSHanjun Guo 	    of_property_read_u32(np, "clock-frequency", &arch_timer_rate)) {
66822006994SStephen Boyd 		if (cntbase)
66922006994SStephen Boyd 			arch_timer_rate = readl_relaxed(cntbase + CNTFRQ);
67022006994SStephen Boyd 		else
67122006994SStephen Boyd 			arch_timer_rate = arch_timer_get_cntfrq();
67222006994SStephen Boyd 	}
6738a4da6e3SMark Rutland 
6748a4da6e3SMark Rutland 	/* Check the timer frequency. */
67522006994SStephen Boyd 	if (arch_timer_rate == 0)
6768a4da6e3SMark Rutland 		pr_warn("Architected timer frequency not available\n");
6778a4da6e3SMark Rutland }
6788a4da6e3SMark Rutland 
67922006994SStephen Boyd static void arch_timer_banner(unsigned type)
68022006994SStephen Boyd {
68122006994SStephen Boyd 	pr_info("Architected %s%s%s timer(s) running at %lu.%02luMHz (%s%s%s).\n",
68222006994SStephen Boyd 		     type & ARCH_CP15_TIMER ? "cp15" : "",
68322006994SStephen Boyd 		     type == (ARCH_CP15_TIMER | ARCH_MEM_TIMER) ?  " and " : "",
68422006994SStephen Boyd 		     type & ARCH_MEM_TIMER ? "mmio" : "",
6858a4da6e3SMark Rutland 		     (unsigned long)arch_timer_rate / 1000000,
6868a4da6e3SMark Rutland 		     (unsigned long)(arch_timer_rate / 10000) % 100,
68722006994SStephen Boyd 		     type & ARCH_CP15_TIMER ?
688f81f03faSMarc Zyngier 		     (arch_timer_uses_ppi == VIRT_PPI) ? "virt" : "phys" :
68922006994SStephen Boyd 			"",
69022006994SStephen Boyd 		     type == (ARCH_CP15_TIMER | ARCH_MEM_TIMER) ?  "/" : "",
69122006994SStephen Boyd 		     type & ARCH_MEM_TIMER ?
69222006994SStephen Boyd 			arch_timer_mem_use_virtual ? "virt" : "phys" :
69322006994SStephen Boyd 			"");
6948a4da6e3SMark Rutland }
6958a4da6e3SMark Rutland 
6968a4da6e3SMark Rutland u32 arch_timer_get_rate(void)
6978a4da6e3SMark Rutland {
6988a4da6e3SMark Rutland 	return arch_timer_rate;
6998a4da6e3SMark Rutland }
7008a4da6e3SMark Rutland 
70122006994SStephen Boyd static u64 arch_counter_get_cntvct_mem(void)
7028a4da6e3SMark Rutland {
70322006994SStephen Boyd 	u32 vct_lo, vct_hi, tmp_hi;
70422006994SStephen Boyd 
70522006994SStephen Boyd 	do {
70622006994SStephen Boyd 		vct_hi = readl_relaxed(arch_counter_base + CNTVCT_HI);
70722006994SStephen Boyd 		vct_lo = readl_relaxed(arch_counter_base + CNTVCT_LO);
70822006994SStephen Boyd 		tmp_hi = readl_relaxed(arch_counter_base + CNTVCT_HI);
70922006994SStephen Boyd 	} while (vct_hi != tmp_hi);
71022006994SStephen Boyd 
71122006994SStephen Boyd 	return ((u64) vct_hi << 32) | vct_lo;
7128a4da6e3SMark Rutland }
7138a4da6e3SMark Rutland 
71422006994SStephen Boyd /*
71522006994SStephen Boyd  * Default to cp15 based access because arm64 uses this function for
71622006994SStephen Boyd  * sched_clock() before DT is probed and the cp15 method is guaranteed
71722006994SStephen Boyd  * to exist on arm64. arm doesn't use this before DT is probed so even
71822006994SStephen Boyd  * if we don't have the cp15 accessors we won't have a problem.
71922006994SStephen Boyd  */
72022006994SStephen Boyd u64 (*arch_timer_read_counter)(void) = arch_counter_get_cntvct;
72122006994SStephen Boyd 
722a5a1d1c2SThomas Gleixner static u64 arch_counter_read(struct clocksource *cs)
7238a4da6e3SMark Rutland {
72422006994SStephen Boyd 	return arch_timer_read_counter();
7258a4da6e3SMark Rutland }
7268a4da6e3SMark Rutland 
727a5a1d1c2SThomas Gleixner static u64 arch_counter_read_cc(const struct cyclecounter *cc)
7288a4da6e3SMark Rutland {
72922006994SStephen Boyd 	return arch_timer_read_counter();
7308a4da6e3SMark Rutland }
7318a4da6e3SMark Rutland 
7328a4da6e3SMark Rutland static struct clocksource clocksource_counter = {
7338a4da6e3SMark Rutland 	.name	= "arch_sys_counter",
7348a4da6e3SMark Rutland 	.rating	= 400,
7358a4da6e3SMark Rutland 	.read	= arch_counter_read,
7368a4da6e3SMark Rutland 	.mask	= CLOCKSOURCE_MASK(56),
737d8ec7595SBrian Norris 	.flags	= CLOCK_SOURCE_IS_CONTINUOUS,
7388a4da6e3SMark Rutland };
7398a4da6e3SMark Rutland 
7403d837bc0SBhumika Goyal static struct cyclecounter cyclecounter __ro_after_init = {
7418a4da6e3SMark Rutland 	.read	= arch_counter_read_cc,
7428a4da6e3SMark Rutland 	.mask	= CLOCKSOURCE_MASK(56),
7438a4da6e3SMark Rutland };
7448a4da6e3SMark Rutland 
745b4d6ce97SJulien Grall static struct arch_timer_kvm_info arch_timer_kvm_info;
746b4d6ce97SJulien Grall 
747b4d6ce97SJulien Grall struct arch_timer_kvm_info *arch_timer_get_kvm_info(void)
748b4d6ce97SJulien Grall {
749b4d6ce97SJulien Grall 	return &arch_timer_kvm_info;
750b4d6ce97SJulien Grall }
7518a4da6e3SMark Rutland 
75222006994SStephen Boyd static void __init arch_counter_register(unsigned type)
75322006994SStephen Boyd {
75422006994SStephen Boyd 	u64 start_count;
75522006994SStephen Boyd 
75622006994SStephen Boyd 	/* Register the CP15 based counter if we have one */
757423bd69eSNathan Lynch 	if (type & ARCH_CP15_TIMER) {
758f81f03faSMarc Zyngier 		if (IS_ENABLED(CONFIG_ARM64) || arch_timer_uses_ppi == VIRT_PPI)
75922006994SStephen Boyd 			arch_timer_read_counter = arch_counter_get_cntvct;
7600b46b8a7SSonny Rao 		else
7610b46b8a7SSonny Rao 			arch_timer_read_counter = arch_counter_get_cntpct;
762f6dc1576SScott Wood 
7631d8f51d4SScott Wood 		clocksource_counter.archdata.vdso_direct = true;
7641d8f51d4SScott Wood 
76516d10ef2SDing Tianhong #ifdef CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND
766f6dc1576SScott Wood 		/*
767f6dc1576SScott Wood 		 * Don't use the vdso fastpath if errata require using
768f6dc1576SScott Wood 		 * the out-of-line counter accessor.
769f6dc1576SScott Wood 		 */
770f6dc1576SScott Wood 		if (static_branch_unlikely(&arch_timer_read_ool_enabled))
7711d8f51d4SScott Wood 			clocksource_counter.archdata.vdso_direct = false;
772f6dc1576SScott Wood #endif
773423bd69eSNathan Lynch 	} else {
77422006994SStephen Boyd 		arch_timer_read_counter = arch_counter_get_cntvct_mem;
775423bd69eSNathan Lynch 	}
776423bd69eSNathan Lynch 
777d8ec7595SBrian Norris 	if (!arch_counter_suspend_stop)
778d8ec7595SBrian Norris 		clocksource_counter.flags |= CLOCK_SOURCE_SUSPEND_NONSTOP;
77922006994SStephen Boyd 	start_count = arch_timer_read_counter();
78022006994SStephen Boyd 	clocksource_register_hz(&clocksource_counter, arch_timer_rate);
78122006994SStephen Boyd 	cyclecounter.mult = clocksource_counter.mult;
78222006994SStephen Boyd 	cyclecounter.shift = clocksource_counter.shift;
783b4d6ce97SJulien Grall 	timecounter_init(&arch_timer_kvm_info.timecounter,
784b4d6ce97SJulien Grall 			 &cyclecounter, start_count);
7854a7d3e8aSThierry Reding 
7864a7d3e8aSThierry Reding 	/* 56 bits minimum, so we assume worst case rollover */
7874a7d3e8aSThierry Reding 	sched_clock_register(arch_timer_read_counter, 56, arch_timer_rate);
78822006994SStephen Boyd }
78922006994SStephen Boyd 
7908c37bb3aSPaul Gortmaker static void arch_timer_stop(struct clock_event_device *clk)
7918a4da6e3SMark Rutland {
7928a4da6e3SMark Rutland 	pr_debug("arch_timer_teardown disable IRQ%d cpu #%d\n",
7938a4da6e3SMark Rutland 		 clk->irq, smp_processor_id());
7948a4da6e3SMark Rutland 
795f81f03faSMarc Zyngier 	disable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi]);
796f81f03faSMarc Zyngier 	if (arch_timer_has_nonsecure_ppi())
7978a4da6e3SMark Rutland 		disable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI]);
7988a4da6e3SMark Rutland 
79946c5bfddSViresh Kumar 	clk->set_state_shutdown(clk);
8008a4da6e3SMark Rutland }
8018a4da6e3SMark Rutland 
8027e86e8bdSRichard Cochran static int arch_timer_dying_cpu(unsigned int cpu)
8038a4da6e3SMark Rutland {
8047e86e8bdSRichard Cochran 	struct clock_event_device *clk = this_cpu_ptr(arch_timer_evt);
8058a4da6e3SMark Rutland 
8067e86e8bdSRichard Cochran 	arch_timer_stop(clk);
8077e86e8bdSRichard Cochran 	return 0;
8088a4da6e3SMark Rutland }
8098a4da6e3SMark Rutland 
810346e7480SSudeep KarkadaNagesha #ifdef CONFIG_CPU_PM
811346e7480SSudeep KarkadaNagesha static unsigned int saved_cntkctl;
812346e7480SSudeep KarkadaNagesha static int arch_timer_cpu_pm_notify(struct notifier_block *self,
813346e7480SSudeep KarkadaNagesha 				    unsigned long action, void *hcpu)
814346e7480SSudeep KarkadaNagesha {
815346e7480SSudeep KarkadaNagesha 	if (action == CPU_PM_ENTER)
816346e7480SSudeep KarkadaNagesha 		saved_cntkctl = arch_timer_get_cntkctl();
817346e7480SSudeep KarkadaNagesha 	else if (action == CPU_PM_ENTER_FAILED || action == CPU_PM_EXIT)
818346e7480SSudeep KarkadaNagesha 		arch_timer_set_cntkctl(saved_cntkctl);
819346e7480SSudeep KarkadaNagesha 	return NOTIFY_OK;
820346e7480SSudeep KarkadaNagesha }
821346e7480SSudeep KarkadaNagesha 
822346e7480SSudeep KarkadaNagesha static struct notifier_block arch_timer_cpu_pm_notifier = {
823346e7480SSudeep KarkadaNagesha 	.notifier_call = arch_timer_cpu_pm_notify,
824346e7480SSudeep KarkadaNagesha };
825346e7480SSudeep KarkadaNagesha 
826346e7480SSudeep KarkadaNagesha static int __init arch_timer_cpu_pm_init(void)
827346e7480SSudeep KarkadaNagesha {
828346e7480SSudeep KarkadaNagesha 	return cpu_pm_register_notifier(&arch_timer_cpu_pm_notifier);
829346e7480SSudeep KarkadaNagesha }
8307e86e8bdSRichard Cochran 
8317e86e8bdSRichard Cochran static void __init arch_timer_cpu_pm_deinit(void)
8327e86e8bdSRichard Cochran {
8337e86e8bdSRichard Cochran 	WARN_ON(cpu_pm_unregister_notifier(&arch_timer_cpu_pm_notifier));
8347e86e8bdSRichard Cochran }
8357e86e8bdSRichard Cochran 
836346e7480SSudeep KarkadaNagesha #else
837346e7480SSudeep KarkadaNagesha static int __init arch_timer_cpu_pm_init(void)
838346e7480SSudeep KarkadaNagesha {
839346e7480SSudeep KarkadaNagesha 	return 0;
840346e7480SSudeep KarkadaNagesha }
8417e86e8bdSRichard Cochran 
8427e86e8bdSRichard Cochran static void __init arch_timer_cpu_pm_deinit(void)
8437e86e8bdSRichard Cochran {
8447e86e8bdSRichard Cochran }
845346e7480SSudeep KarkadaNagesha #endif
846346e7480SSudeep KarkadaNagesha 
8478a4da6e3SMark Rutland static int __init arch_timer_register(void)
8488a4da6e3SMark Rutland {
8498a4da6e3SMark Rutland 	int err;
8508a4da6e3SMark Rutland 	int ppi;
8518a4da6e3SMark Rutland 
8528a4da6e3SMark Rutland 	arch_timer_evt = alloc_percpu(struct clock_event_device);
8538a4da6e3SMark Rutland 	if (!arch_timer_evt) {
8548a4da6e3SMark Rutland 		err = -ENOMEM;
8558a4da6e3SMark Rutland 		goto out;
8568a4da6e3SMark Rutland 	}
8578a4da6e3SMark Rutland 
858f81f03faSMarc Zyngier 	ppi = arch_timer_ppi[arch_timer_uses_ppi];
859f81f03faSMarc Zyngier 	switch (arch_timer_uses_ppi) {
860f81f03faSMarc Zyngier 	case VIRT_PPI:
8618a4da6e3SMark Rutland 		err = request_percpu_irq(ppi, arch_timer_handler_virt,
8628a4da6e3SMark Rutland 					 "arch_timer", arch_timer_evt);
863f81f03faSMarc Zyngier 		break;
864f81f03faSMarc Zyngier 	case PHYS_SECURE_PPI:
865f81f03faSMarc Zyngier 	case PHYS_NONSECURE_PPI:
8668a4da6e3SMark Rutland 		err = request_percpu_irq(ppi, arch_timer_handler_phys,
8678a4da6e3SMark Rutland 					 "arch_timer", arch_timer_evt);
8688a4da6e3SMark Rutland 		if (!err && arch_timer_ppi[PHYS_NONSECURE_PPI]) {
8698a4da6e3SMark Rutland 			ppi = arch_timer_ppi[PHYS_NONSECURE_PPI];
8708a4da6e3SMark Rutland 			err = request_percpu_irq(ppi, arch_timer_handler_phys,
8718a4da6e3SMark Rutland 						 "arch_timer", arch_timer_evt);
8728a4da6e3SMark Rutland 			if (err)
8738a4da6e3SMark Rutland 				free_percpu_irq(arch_timer_ppi[PHYS_SECURE_PPI],
8748a4da6e3SMark Rutland 						arch_timer_evt);
8758a4da6e3SMark Rutland 		}
876f81f03faSMarc Zyngier 		break;
877f81f03faSMarc Zyngier 	case HYP_PPI:
878f81f03faSMarc Zyngier 		err = request_percpu_irq(ppi, arch_timer_handler_phys,
879f81f03faSMarc Zyngier 					 "arch_timer", arch_timer_evt);
880f81f03faSMarc Zyngier 		break;
881f81f03faSMarc Zyngier 	default:
882f81f03faSMarc Zyngier 		BUG();
8838a4da6e3SMark Rutland 	}
8848a4da6e3SMark Rutland 
8858a4da6e3SMark Rutland 	if (err) {
8868a4da6e3SMark Rutland 		pr_err("arch_timer: can't register interrupt %d (%d)\n",
8878a4da6e3SMark Rutland 		       ppi, err);
8888a4da6e3SMark Rutland 		goto out_free;
8898a4da6e3SMark Rutland 	}
8908a4da6e3SMark Rutland 
891346e7480SSudeep KarkadaNagesha 	err = arch_timer_cpu_pm_init();
892346e7480SSudeep KarkadaNagesha 	if (err)
893346e7480SSudeep KarkadaNagesha 		goto out_unreg_notify;
894346e7480SSudeep KarkadaNagesha 
8958a4da6e3SMark Rutland 
8967e86e8bdSRichard Cochran 	/* Register and immediately configure the timer on the boot CPU */
8977e86e8bdSRichard Cochran 	err = cpuhp_setup_state(CPUHP_AP_ARM_ARCH_TIMER_STARTING,
89873c1b41eSThomas Gleixner 				"clockevents/arm/arch_timer:starting",
8997e86e8bdSRichard Cochran 				arch_timer_starting_cpu, arch_timer_dying_cpu);
9007e86e8bdSRichard Cochran 	if (err)
9017e86e8bdSRichard Cochran 		goto out_unreg_cpupm;
9028a4da6e3SMark Rutland 	return 0;
9038a4da6e3SMark Rutland 
9047e86e8bdSRichard Cochran out_unreg_cpupm:
9057e86e8bdSRichard Cochran 	arch_timer_cpu_pm_deinit();
9067e86e8bdSRichard Cochran 
907346e7480SSudeep KarkadaNagesha out_unreg_notify:
908f81f03faSMarc Zyngier 	free_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], arch_timer_evt);
909f81f03faSMarc Zyngier 	if (arch_timer_has_nonsecure_ppi())
9108a4da6e3SMark Rutland 		free_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI],
9118a4da6e3SMark Rutland 				arch_timer_evt);
9128a4da6e3SMark Rutland 
9138a4da6e3SMark Rutland out_free:
9148a4da6e3SMark Rutland 	free_percpu(arch_timer_evt);
9158a4da6e3SMark Rutland out:
9168a4da6e3SMark Rutland 	return err;
9178a4da6e3SMark Rutland }
9188a4da6e3SMark Rutland 
91922006994SStephen Boyd static int __init arch_timer_mem_register(void __iomem *base, unsigned int irq)
92022006994SStephen Boyd {
92122006994SStephen Boyd 	int ret;
92222006994SStephen Boyd 	irq_handler_t func;
92322006994SStephen Boyd 	struct arch_timer *t;
92422006994SStephen Boyd 
92522006994SStephen Boyd 	t = kzalloc(sizeof(*t), GFP_KERNEL);
92622006994SStephen Boyd 	if (!t)
92722006994SStephen Boyd 		return -ENOMEM;
92822006994SStephen Boyd 
92922006994SStephen Boyd 	t->base = base;
93022006994SStephen Boyd 	t->evt.irq = irq;
93122006994SStephen Boyd 	__arch_timer_setup(ARCH_MEM_TIMER, &t->evt);
93222006994SStephen Boyd 
93322006994SStephen Boyd 	if (arch_timer_mem_use_virtual)
93422006994SStephen Boyd 		func = arch_timer_handler_virt_mem;
93522006994SStephen Boyd 	else
93622006994SStephen Boyd 		func = arch_timer_handler_phys_mem;
93722006994SStephen Boyd 
93822006994SStephen Boyd 	ret = request_irq(irq, func, IRQF_TIMER, "arch_mem_timer", &t->evt);
93922006994SStephen Boyd 	if (ret) {
94022006994SStephen Boyd 		pr_err("arch_timer: Failed to request mem timer irq\n");
94122006994SStephen Boyd 		kfree(t);
94222006994SStephen Boyd 	}
94322006994SStephen Boyd 
94422006994SStephen Boyd 	return ret;
94522006994SStephen Boyd }
94622006994SStephen Boyd 
94722006994SStephen Boyd static const struct of_device_id arch_timer_of_match[] __initconst = {
94822006994SStephen Boyd 	{ .compatible   = "arm,armv7-timer",    },
94922006994SStephen Boyd 	{ .compatible   = "arm,armv8-timer",    },
95022006994SStephen Boyd 	{},
95122006994SStephen Boyd };
95222006994SStephen Boyd 
95322006994SStephen Boyd static const struct of_device_id arch_timer_mem_of_match[] __initconst = {
95422006994SStephen Boyd 	{ .compatible   = "arm,armv7-timer-mem", },
95522006994SStephen Boyd 	{},
95622006994SStephen Boyd };
95722006994SStephen Boyd 
958c387f07eSSudeep Holla static bool __init
959566e6dfaSLaurent Pinchart arch_timer_needs_probing(int type, const struct of_device_id *matches)
960c387f07eSSudeep Holla {
961c387f07eSSudeep Holla 	struct device_node *dn;
962566e6dfaSLaurent Pinchart 	bool needs_probing = false;
963c387f07eSSudeep Holla 
964c387f07eSSudeep Holla 	dn = of_find_matching_node(NULL, matches);
96559aa896dSMarc Zyngier 	if (dn && of_device_is_available(dn) && !(arch_timers_present & type))
966566e6dfaSLaurent Pinchart 		needs_probing = true;
967c387f07eSSudeep Holla 	of_node_put(dn);
968c387f07eSSudeep Holla 
969566e6dfaSLaurent Pinchart 	return needs_probing;
970c387f07eSSudeep Holla }
971c387f07eSSudeep Holla 
9723c0731dbSDaniel Lezcano static int __init arch_timer_common_init(void)
97322006994SStephen Boyd {
97422006994SStephen Boyd 	unsigned mask = ARCH_CP15_TIMER | ARCH_MEM_TIMER;
97522006994SStephen Boyd 
97622006994SStephen Boyd 	/* Wait until both nodes are probed if we have two timers */
97722006994SStephen Boyd 	if ((arch_timers_present & mask) != mask) {
978566e6dfaSLaurent Pinchart 		if (arch_timer_needs_probing(ARCH_MEM_TIMER, arch_timer_mem_of_match))
9793c0731dbSDaniel Lezcano 			return 0;
980566e6dfaSLaurent Pinchart 		if (arch_timer_needs_probing(ARCH_CP15_TIMER, arch_timer_of_match))
9813c0731dbSDaniel Lezcano 			return 0;
98222006994SStephen Boyd 	}
98322006994SStephen Boyd 
98422006994SStephen Boyd 	arch_timer_banner(arch_timers_present);
98522006994SStephen Boyd 	arch_counter_register(arch_timers_present);
9863c0731dbSDaniel Lezcano 	return arch_timer_arch_init();
98722006994SStephen Boyd }
98822006994SStephen Boyd 
9893c0731dbSDaniel Lezcano static int __init arch_timer_init(void)
9908a4da6e3SMark Rutland {
9913c0731dbSDaniel Lezcano 	int ret;
99265b5732dSDoug Anderson 	/*
9938266891eSMarc Zyngier 	 * If HYP mode is available, we know that the physical timer
9948266891eSMarc Zyngier 	 * has been configured to be accessible from PL1. Use it, so
9958266891eSMarc Zyngier 	 * that a guest can use the virtual timer instead.
9968266891eSMarc Zyngier 	 *
9978a4da6e3SMark Rutland 	 * If no interrupt provided for virtual timer, we'll have to
9988a4da6e3SMark Rutland 	 * stick to the physical timer. It'd better be accessible...
999f81f03faSMarc Zyngier 	 *
1000f81f03faSMarc Zyngier 	 * On ARMv8.1 with VH extensions, the kernel runs in HYP. VHE
1001f81f03faSMarc Zyngier 	 * accesses to CNTP_*_EL1 registers are silently redirected to
1002f81f03faSMarc Zyngier 	 * their CNTHP_*_EL2 counterparts, and use a different PPI
1003f81f03faSMarc Zyngier 	 * number.
10048a4da6e3SMark Rutland 	 */
10058266891eSMarc Zyngier 	if (is_hyp_mode_available() || !arch_timer_ppi[VIRT_PPI]) {
1006f81f03faSMarc Zyngier 		bool has_ppi;
10078a4da6e3SMark Rutland 
1008f81f03faSMarc Zyngier 		if (is_kernel_in_hyp_mode()) {
1009f81f03faSMarc Zyngier 			arch_timer_uses_ppi = HYP_PPI;
1010f81f03faSMarc Zyngier 			has_ppi = !!arch_timer_ppi[HYP_PPI];
1011f81f03faSMarc Zyngier 		} else {
1012f81f03faSMarc Zyngier 			arch_timer_uses_ppi = PHYS_SECURE_PPI;
1013f81f03faSMarc Zyngier 			has_ppi = (!!arch_timer_ppi[PHYS_SECURE_PPI] ||
1014f81f03faSMarc Zyngier 				   !!arch_timer_ppi[PHYS_NONSECURE_PPI]);
1015f81f03faSMarc Zyngier 		}
1016f81f03faSMarc Zyngier 
1017f81f03faSMarc Zyngier 		if (!has_ppi) {
10188a4da6e3SMark Rutland 			pr_warn("arch_timer: No interrupt available, giving up\n");
10193c0731dbSDaniel Lezcano 			return -EINVAL;
10208a4da6e3SMark Rutland 		}
10218a4da6e3SMark Rutland 	}
10228a4da6e3SMark Rutland 
10233c0731dbSDaniel Lezcano 	ret = arch_timer_register();
10243c0731dbSDaniel Lezcano 	if (ret)
10253c0731dbSDaniel Lezcano 		return ret;
10263c0731dbSDaniel Lezcano 
10273c0731dbSDaniel Lezcano 	ret = arch_timer_common_init();
10283c0731dbSDaniel Lezcano 	if (ret)
10293c0731dbSDaniel Lezcano 		return ret;
1030d9b5e415SJulien Grall 
1031d9b5e415SJulien Grall 	arch_timer_kvm_info.virtual_irq = arch_timer_ppi[VIRT_PPI];
10323c0731dbSDaniel Lezcano 
10333c0731dbSDaniel Lezcano 	return 0;
10348a4da6e3SMark Rutland }
1035b09ca1ecSHanjun Guo 
10363c0731dbSDaniel Lezcano static int __init arch_timer_of_init(struct device_node *np)
1037b09ca1ecSHanjun Guo {
1038b09ca1ecSHanjun Guo 	int i;
1039b09ca1ecSHanjun Guo 
1040b09ca1ecSHanjun Guo 	if (arch_timers_present & ARCH_CP15_TIMER) {
1041b09ca1ecSHanjun Guo 		pr_warn("arch_timer: multiple nodes in dt, skipping\n");
10423c0731dbSDaniel Lezcano 		return 0;
1043b09ca1ecSHanjun Guo 	}
1044b09ca1ecSHanjun Guo 
1045b09ca1ecSHanjun Guo 	arch_timers_present |= ARCH_CP15_TIMER;
1046b09ca1ecSHanjun Guo 	for (i = PHYS_SECURE_PPI; i < MAX_TIMER_PPI; i++)
1047b09ca1ecSHanjun Guo 		arch_timer_ppi[i] = irq_of_parse_and_map(np, i);
1048b09ca1ecSHanjun Guo 
1049b09ca1ecSHanjun Guo 	arch_timer_detect_rate(NULL, np);
1050b09ca1ecSHanjun Guo 
1051b09ca1ecSHanjun Guo 	arch_timer_c3stop = !of_property_read_bool(np, "always-on");
1052b09ca1ecSHanjun Guo 
1053651bb2e9SMarc Zyngier 	/* Check for globally applicable workarounds */
1054651bb2e9SMarc Zyngier 	arch_timer_check_ool_workaround(ate_match_dt, np);
1055f6dc1576SScott Wood 
1056b09ca1ecSHanjun Guo 	/*
1057b09ca1ecSHanjun Guo 	 * If we cannot rely on firmware initializing the timer registers then
1058b09ca1ecSHanjun Guo 	 * we should use the physical timers instead.
1059b09ca1ecSHanjun Guo 	 */
1060b09ca1ecSHanjun Guo 	if (IS_ENABLED(CONFIG_ARM) &&
1061b09ca1ecSHanjun Guo 	    of_property_read_bool(np, "arm,cpu-registers-not-fw-configured"))
1062f81f03faSMarc Zyngier 		arch_timer_uses_ppi = PHYS_SECURE_PPI;
1063b09ca1ecSHanjun Guo 
1064d8ec7595SBrian Norris 	/* On some systems, the counter stops ticking when in suspend. */
1065d8ec7595SBrian Norris 	arch_counter_suspend_stop = of_property_read_bool(np,
1066d8ec7595SBrian Norris 							 "arm,no-tick-in-suspend");
1067d8ec7595SBrian Norris 
10683c0731dbSDaniel Lezcano 	return arch_timer_init();
1069b09ca1ecSHanjun Guo }
1070177cf6e5SDaniel Lezcano CLOCKSOURCE_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", arch_timer_of_init);
1071177cf6e5SDaniel Lezcano CLOCKSOURCE_OF_DECLARE(armv8_arch_timer, "arm,armv8-timer", arch_timer_of_init);
107222006994SStephen Boyd 
10733c0731dbSDaniel Lezcano static int __init arch_timer_mem_init(struct device_node *np)
107422006994SStephen Boyd {
107522006994SStephen Boyd 	struct device_node *frame, *best_frame = NULL;
107622006994SStephen Boyd 	void __iomem *cntctlbase, *base;
10773c0731dbSDaniel Lezcano 	unsigned int irq, ret = -EINVAL;
107822006994SStephen Boyd 	u32 cnttidr;
107922006994SStephen Boyd 
108022006994SStephen Boyd 	arch_timers_present |= ARCH_MEM_TIMER;
108122006994SStephen Boyd 	cntctlbase = of_iomap(np, 0);
108222006994SStephen Boyd 	if (!cntctlbase) {
108322006994SStephen Boyd 		pr_err("arch_timer: Can't find CNTCTLBase\n");
10843c0731dbSDaniel Lezcano 		return -ENXIO;
108522006994SStephen Boyd 	}
108622006994SStephen Boyd 
108722006994SStephen Boyd 	cnttidr = readl_relaxed(cntctlbase + CNTTIDR);
108822006994SStephen Boyd 
108922006994SStephen Boyd 	/*
109022006994SStephen Boyd 	 * Try to find a virtual capable frame. Otherwise fall back to a
109122006994SStephen Boyd 	 * physical capable frame.
109222006994SStephen Boyd 	 */
109322006994SStephen Boyd 	for_each_available_child_of_node(np, frame) {
109422006994SStephen Boyd 		int n;
1095e392d603SRobin Murphy 		u32 cntacr;
109622006994SStephen Boyd 
109722006994SStephen Boyd 		if (of_property_read_u32(frame, "frame-number", &n)) {
109822006994SStephen Boyd 			pr_err("arch_timer: Missing frame-number\n");
109922006994SStephen Boyd 			of_node_put(frame);
1100e392d603SRobin Murphy 			goto out;
110122006994SStephen Boyd 		}
110222006994SStephen Boyd 
1103e392d603SRobin Murphy 		/* Try enabling everything, and see what sticks */
1104e392d603SRobin Murphy 		cntacr = CNTACR_RFRQ | CNTACR_RWPT | CNTACR_RPCT |
1105e392d603SRobin Murphy 			 CNTACR_RWVT | CNTACR_RVOFF | CNTACR_RVCT;
1106e392d603SRobin Murphy 		writel_relaxed(cntacr, cntctlbase + CNTACR(n));
1107e392d603SRobin Murphy 		cntacr = readl_relaxed(cntctlbase + CNTACR(n));
1108e392d603SRobin Murphy 
1109e392d603SRobin Murphy 		if ((cnttidr & CNTTIDR_VIRT(n)) &&
1110e392d603SRobin Murphy 		    !(~cntacr & (CNTACR_RWVT | CNTACR_RVCT))) {
111122006994SStephen Boyd 			of_node_put(best_frame);
111222006994SStephen Boyd 			best_frame = frame;
111322006994SStephen Boyd 			arch_timer_mem_use_virtual = true;
111422006994SStephen Boyd 			break;
111522006994SStephen Boyd 		}
1116e392d603SRobin Murphy 
1117e392d603SRobin Murphy 		if (~cntacr & (CNTACR_RWPT | CNTACR_RPCT))
1118e392d603SRobin Murphy 			continue;
1119e392d603SRobin Murphy 
112022006994SStephen Boyd 		of_node_put(best_frame);
112122006994SStephen Boyd 		best_frame = of_node_get(frame);
112222006994SStephen Boyd 	}
112322006994SStephen Boyd 
11243c0731dbSDaniel Lezcano 	ret= -ENXIO;
1125f947ee14SStephen Boyd 	base = arch_counter_base = of_io_request_and_map(best_frame, 0,
1126f947ee14SStephen Boyd 							 "arch_mem_timer");
1127f947ee14SStephen Boyd 	if (IS_ERR(base)) {
112822006994SStephen Boyd 		pr_err("arch_timer: Can't map frame's registers\n");
1129e392d603SRobin Murphy 		goto out;
113022006994SStephen Boyd 	}
113122006994SStephen Boyd 
113222006994SStephen Boyd 	if (arch_timer_mem_use_virtual)
113322006994SStephen Boyd 		irq = irq_of_parse_and_map(best_frame, 1);
113422006994SStephen Boyd 	else
113522006994SStephen Boyd 		irq = irq_of_parse_and_map(best_frame, 0);
1136e392d603SRobin Murphy 
11373c0731dbSDaniel Lezcano 	ret = -EINVAL;
113822006994SStephen Boyd 	if (!irq) {
113922006994SStephen Boyd 		pr_err("arch_timer: Frame missing %s irq",
114022006994SStephen Boyd 		       arch_timer_mem_use_virtual ? "virt" : "phys");
1141e392d603SRobin Murphy 		goto out;
114222006994SStephen Boyd 	}
114322006994SStephen Boyd 
114422006994SStephen Boyd 	arch_timer_detect_rate(base, np);
11453c0731dbSDaniel Lezcano 	ret = arch_timer_mem_register(base, irq);
11463c0731dbSDaniel Lezcano 	if (ret)
11473c0731dbSDaniel Lezcano 		goto out;
11483c0731dbSDaniel Lezcano 
11493c0731dbSDaniel Lezcano 	return arch_timer_common_init();
1150e392d603SRobin Murphy out:
1151e392d603SRobin Murphy 	iounmap(cntctlbase);
1152e392d603SRobin Murphy 	of_node_put(best_frame);
11533c0731dbSDaniel Lezcano 	return ret;
115422006994SStephen Boyd }
1155177cf6e5SDaniel Lezcano CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem",
115622006994SStephen Boyd 		       arch_timer_mem_init);
1157b09ca1ecSHanjun Guo 
1158b09ca1ecSHanjun Guo #ifdef CONFIG_ACPI
1159b09ca1ecSHanjun Guo static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
1160b09ca1ecSHanjun Guo {
1161b09ca1ecSHanjun Guo 	int trigger, polarity;
1162b09ca1ecSHanjun Guo 
1163b09ca1ecSHanjun Guo 	if (!interrupt)
1164b09ca1ecSHanjun Guo 		return 0;
1165b09ca1ecSHanjun Guo 
1166b09ca1ecSHanjun Guo 	trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
1167b09ca1ecSHanjun Guo 			: ACPI_LEVEL_SENSITIVE;
1168b09ca1ecSHanjun Guo 
1169b09ca1ecSHanjun Guo 	polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
1170b09ca1ecSHanjun Guo 			: ACPI_ACTIVE_HIGH;
1171b09ca1ecSHanjun Guo 
1172b09ca1ecSHanjun Guo 	return acpi_register_gsi(NULL, interrupt, trigger, polarity);
1173b09ca1ecSHanjun Guo }
1174b09ca1ecSHanjun Guo 
1175b09ca1ecSHanjun Guo /* Initialize per-processor generic timer */
1176b09ca1ecSHanjun Guo static int __init arch_timer_acpi_init(struct acpi_table_header *table)
1177b09ca1ecSHanjun Guo {
1178b09ca1ecSHanjun Guo 	struct acpi_table_gtdt *gtdt;
1179b09ca1ecSHanjun Guo 
1180b09ca1ecSHanjun Guo 	if (arch_timers_present & ARCH_CP15_TIMER) {
1181b09ca1ecSHanjun Guo 		pr_warn("arch_timer: already initialized, skipping\n");
1182b09ca1ecSHanjun Guo 		return -EINVAL;
1183b09ca1ecSHanjun Guo 	}
1184b09ca1ecSHanjun Guo 
1185b09ca1ecSHanjun Guo 	gtdt = container_of(table, struct acpi_table_gtdt, header);
1186b09ca1ecSHanjun Guo 
1187b09ca1ecSHanjun Guo 	arch_timers_present |= ARCH_CP15_TIMER;
1188b09ca1ecSHanjun Guo 
1189b09ca1ecSHanjun Guo 	arch_timer_ppi[PHYS_SECURE_PPI] =
1190b09ca1ecSHanjun Guo 		map_generic_timer_interrupt(gtdt->secure_el1_interrupt,
1191b09ca1ecSHanjun Guo 		gtdt->secure_el1_flags);
1192b09ca1ecSHanjun Guo 
1193b09ca1ecSHanjun Guo 	arch_timer_ppi[PHYS_NONSECURE_PPI] =
1194b09ca1ecSHanjun Guo 		map_generic_timer_interrupt(gtdt->non_secure_el1_interrupt,
1195b09ca1ecSHanjun Guo 		gtdt->non_secure_el1_flags);
1196b09ca1ecSHanjun Guo 
1197b09ca1ecSHanjun Guo 	arch_timer_ppi[VIRT_PPI] =
1198b09ca1ecSHanjun Guo 		map_generic_timer_interrupt(gtdt->virtual_timer_interrupt,
1199b09ca1ecSHanjun Guo 		gtdt->virtual_timer_flags);
1200b09ca1ecSHanjun Guo 
1201b09ca1ecSHanjun Guo 	arch_timer_ppi[HYP_PPI] =
1202b09ca1ecSHanjun Guo 		map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt,
1203b09ca1ecSHanjun Guo 		gtdt->non_secure_el2_flags);
1204b09ca1ecSHanjun Guo 
1205b09ca1ecSHanjun Guo 	/* Get the frequency from CNTFRQ */
1206b09ca1ecSHanjun Guo 	arch_timer_detect_rate(NULL, NULL);
1207b09ca1ecSHanjun Guo 
1208b09ca1ecSHanjun Guo 	/* Always-on capability */
1209b09ca1ecSHanjun Guo 	arch_timer_c3stop = !(gtdt->non_secure_el1_flags & ACPI_GTDT_ALWAYS_ON);
1210b09ca1ecSHanjun Guo 
1211b09ca1ecSHanjun Guo 	arch_timer_init();
1212b09ca1ecSHanjun Guo 	return 0;
1213b09ca1ecSHanjun Guo }
1214ae281cbdSMarc Zyngier CLOCKSOURCE_ACPI_DECLARE(arch_timer, ACPI_SIG_GTDT, arch_timer_acpi_init);
1215b09ca1ecSHanjun Guo #endif
1216