xref: /linux/arch/arm/include/asm/arch_timer.h (revision 45801042225c66a66fb2cb50fae6ff71883a99d6)
1022c03a2SMarc Zyngier #ifndef __ASMARM_ARCH_TIMER_H
2022c03a2SMarc Zyngier #define __ASMARM_ARCH_TIMER_H
3022c03a2SMarc Zyngier 
4ec944c93SMark Rutland #include <asm/barrier.h>
5923df96bSWill Deacon #include <asm/errno.h>
6a1b2dde7SMarc Zyngier #include <linux/clocksource.h>
7ec944c93SMark Rutland #include <linux/types.h>
8923df96bSWill Deacon 
9022c03a2SMarc Zyngier #ifdef CONFIG_ARM_ARCH_TIMER
100075242bSMarc Zyngier int arch_timer_of_register(void);
11fb8a99f9SMarc Zyngier int arch_timer_sched_clock_init(void);
12a1b2dde7SMarc Zyngier struct timecounter *arch_timer_get_timecounter(void);
13ec944c93SMark Rutland 
14ec944c93SMark Rutland #define ARCH_TIMER_CTRL_ENABLE		(1 << 0)
15ec944c93SMark Rutland #define ARCH_TIMER_CTRL_IT_MASK		(1 << 1)
16ec944c93SMark Rutland #define ARCH_TIMER_CTRL_IT_STAT		(1 << 2)
17ec944c93SMark Rutland 
18ec944c93SMark Rutland #define ARCH_TIMER_REG_CTRL		0
19ec944c93SMark Rutland #define ARCH_TIMER_REG_TVAL		1
20ec944c93SMark Rutland 
21ec944c93SMark Rutland #define ARCH_TIMER_PHYS_ACCESS		0
22ec944c93SMark Rutland #define ARCH_TIMER_VIRT_ACCESS		1
23ec944c93SMark Rutland 
24ec944c93SMark Rutland /*
25ec944c93SMark Rutland  * These register accessors are marked inline so the compiler can
26ec944c93SMark Rutland  * nicely work out which register we want, and chuck away the rest of
27ec944c93SMark Rutland  * the code. At least it does so with a recent GCC (4.6.3).
28ec944c93SMark Rutland  */
29ec944c93SMark Rutland static inline void arch_timer_reg_write(const int access, const int reg, u32 val)
30ec944c93SMark Rutland {
31ec944c93SMark Rutland 	if (access == ARCH_TIMER_PHYS_ACCESS) {
32ec944c93SMark Rutland 		switch (reg) {
33ec944c93SMark Rutland 		case ARCH_TIMER_REG_CTRL:
34ec944c93SMark Rutland 			asm volatile("mcr p15, 0, %0, c14, c2, 1" : : "r" (val));
35ec944c93SMark Rutland 			break;
36ec944c93SMark Rutland 		case ARCH_TIMER_REG_TVAL:
37ec944c93SMark Rutland 			asm volatile("mcr p15, 0, %0, c14, c2, 0" : : "r" (val));
38ec944c93SMark Rutland 			break;
39ec944c93SMark Rutland 		}
40ec944c93SMark Rutland 	}
41ec944c93SMark Rutland 
42ec944c93SMark Rutland 	if (access == ARCH_TIMER_VIRT_ACCESS) {
43ec944c93SMark Rutland 		switch (reg) {
44ec944c93SMark Rutland 		case ARCH_TIMER_REG_CTRL:
45ec944c93SMark Rutland 			asm volatile("mcr p15, 0, %0, c14, c3, 1" : : "r" (val));
46ec944c93SMark Rutland 			break;
47ec944c93SMark Rutland 		case ARCH_TIMER_REG_TVAL:
48ec944c93SMark Rutland 			asm volatile("mcr p15, 0, %0, c14, c3, 0" : : "r" (val));
49ec944c93SMark Rutland 			break;
50ec944c93SMark Rutland 		}
51ec944c93SMark Rutland 	}
52*45801042SMark Rutland 
53*45801042SMark Rutland 	isb();
54ec944c93SMark Rutland }
55ec944c93SMark Rutland 
56ec944c93SMark Rutland static inline u32 arch_timer_reg_read(const int access, const int reg)
57ec944c93SMark Rutland {
58ec944c93SMark Rutland 	u32 val = 0;
59ec944c93SMark Rutland 
60ec944c93SMark Rutland 	if (access == ARCH_TIMER_PHYS_ACCESS) {
61ec944c93SMark Rutland 		switch (reg) {
62ec944c93SMark Rutland 		case ARCH_TIMER_REG_CTRL:
63ec944c93SMark Rutland 			asm volatile("mrc p15, 0, %0, c14, c2, 1" : "=r" (val));
64ec944c93SMark Rutland 			break;
65ec944c93SMark Rutland 		case ARCH_TIMER_REG_TVAL:
66ec944c93SMark Rutland 			asm volatile("mrc p15, 0, %0, c14, c2, 0" : "=r" (val));
67ec944c93SMark Rutland 			break;
68ec944c93SMark Rutland 		}
69ec944c93SMark Rutland 	}
70ec944c93SMark Rutland 
71ec944c93SMark Rutland 	if (access == ARCH_TIMER_VIRT_ACCESS) {
72ec944c93SMark Rutland 		switch (reg) {
73ec944c93SMark Rutland 		case ARCH_TIMER_REG_CTRL:
74ec944c93SMark Rutland 			asm volatile("mrc p15, 0, %0, c14, c3, 1" : "=r" (val));
75ec944c93SMark Rutland 			break;
76ec944c93SMark Rutland 		case ARCH_TIMER_REG_TVAL:
77ec944c93SMark Rutland 			asm volatile("mrc p15, 0, %0, c14, c3, 0" : "=r" (val));
78ec944c93SMark Rutland 			break;
79ec944c93SMark Rutland 		}
80ec944c93SMark Rutland 	}
81ec944c93SMark Rutland 
82ec944c93SMark Rutland 	return val;
83ec944c93SMark Rutland }
84ec944c93SMark Rutland 
85ec944c93SMark Rutland static inline u32 arch_timer_get_cntfrq(void)
86ec944c93SMark Rutland {
87ec944c93SMark Rutland 	u32 val;
88ec944c93SMark Rutland 	asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (val));
89ec944c93SMark Rutland 	return val;
90ec944c93SMark Rutland }
91ec944c93SMark Rutland 
92ec944c93SMark Rutland static inline u64 arch_counter_get_cntpct(void)
93ec944c93SMark Rutland {
94ec944c93SMark Rutland 	u64 cval;
95ec944c93SMark Rutland 
96*45801042SMark Rutland 	isb();
97ec944c93SMark Rutland 	asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r" (cval));
98ec944c93SMark Rutland 	return cval;
99ec944c93SMark Rutland }
100ec944c93SMark Rutland 
101ec944c93SMark Rutland static inline u64 arch_counter_get_cntvct(void)
102ec944c93SMark Rutland {
103ec944c93SMark Rutland 	u64 cval;
104ec944c93SMark Rutland 
105*45801042SMark Rutland 	isb();
106ec944c93SMark Rutland 	asm volatile("mrrc p15, 1, %Q0, %R0, c14" : "=r" (cval));
107ec944c93SMark Rutland 	return cval;
108ec944c93SMark Rutland }
109022c03a2SMarc Zyngier #else
1100075242bSMarc Zyngier static inline int arch_timer_of_register(void)
1110075242bSMarc Zyngier {
1120075242bSMarc Zyngier 	return -ENXIO;
1130075242bSMarc Zyngier }
1140075242bSMarc Zyngier 
1153f61c80eSMarc Zyngier static inline int arch_timer_sched_clock_init(void)
1163f61c80eSMarc Zyngier {
1173f61c80eSMarc Zyngier 	return -ENXIO;
1183f61c80eSMarc Zyngier }
119a1b2dde7SMarc Zyngier 
120a1b2dde7SMarc Zyngier static inline struct timecounter *arch_timer_get_timecounter(void)
121a1b2dde7SMarc Zyngier {
122a1b2dde7SMarc Zyngier 	return NULL;
123a1b2dde7SMarc Zyngier }
124022c03a2SMarc Zyngier #endif
125022c03a2SMarc Zyngier 
126022c03a2SMarc Zyngier #endif
127