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