xref: /linux/arch/arm/include/asm/arch_timer.h (revision 8a4da6e36c582ff746191eca85b6c1c068dbfbd6)
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>
7*8a4da6e3SMark Rutland #include <linux/init.h>
8ec944c93SMark Rutland #include <linux/types.h>
9923df96bSWill Deacon 
10*8a4da6e3SMark Rutland #include <clocksource/arm_arch_timer.h>
11*8a4da6e3SMark Rutland 
12022c03a2SMarc Zyngier #ifdef CONFIG_ARM_ARCH_TIMER
130075242bSMarc Zyngier int arch_timer_of_register(void);
14fb8a99f9SMarc Zyngier int arch_timer_sched_clock_init(void);
15ec944c93SMark Rutland 
16ec944c93SMark Rutland /*
17ec944c93SMark Rutland  * These register accessors are marked inline so the compiler can
18ec944c93SMark Rutland  * nicely work out which register we want, and chuck away the rest of
19ec944c93SMark Rutland  * the code. At least it does so with a recent GCC (4.6.3).
20ec944c93SMark Rutland  */
21ec944c93SMark Rutland static inline void arch_timer_reg_write(const int access, const int reg, u32 val)
22ec944c93SMark Rutland {
23ec944c93SMark Rutland 	if (access == ARCH_TIMER_PHYS_ACCESS) {
24ec944c93SMark Rutland 		switch (reg) {
25ec944c93SMark Rutland 		case ARCH_TIMER_REG_CTRL:
26ec944c93SMark Rutland 			asm volatile("mcr p15, 0, %0, c14, c2, 1" : : "r" (val));
27ec944c93SMark Rutland 			break;
28ec944c93SMark Rutland 		case ARCH_TIMER_REG_TVAL:
29ec944c93SMark Rutland 			asm volatile("mcr p15, 0, %0, c14, c2, 0" : : "r" (val));
30ec944c93SMark Rutland 			break;
31ec944c93SMark Rutland 		}
32ec944c93SMark Rutland 	}
33ec944c93SMark Rutland 
34ec944c93SMark Rutland 	if (access == ARCH_TIMER_VIRT_ACCESS) {
35ec944c93SMark Rutland 		switch (reg) {
36ec944c93SMark Rutland 		case ARCH_TIMER_REG_CTRL:
37ec944c93SMark Rutland 			asm volatile("mcr p15, 0, %0, c14, c3, 1" : : "r" (val));
38ec944c93SMark Rutland 			break;
39ec944c93SMark Rutland 		case ARCH_TIMER_REG_TVAL:
40ec944c93SMark Rutland 			asm volatile("mcr p15, 0, %0, c14, c3, 0" : : "r" (val));
41ec944c93SMark Rutland 			break;
42ec944c93SMark Rutland 		}
43ec944c93SMark Rutland 	}
4445801042SMark Rutland 
4545801042SMark Rutland 	isb();
46ec944c93SMark Rutland }
47ec944c93SMark Rutland 
48ec944c93SMark Rutland static inline u32 arch_timer_reg_read(const int access, const int reg)
49ec944c93SMark Rutland {
50ec944c93SMark Rutland 	u32 val = 0;
51ec944c93SMark Rutland 
52ec944c93SMark Rutland 	if (access == ARCH_TIMER_PHYS_ACCESS) {
53ec944c93SMark Rutland 		switch (reg) {
54ec944c93SMark Rutland 		case ARCH_TIMER_REG_CTRL:
55ec944c93SMark Rutland 			asm volatile("mrc p15, 0, %0, c14, c2, 1" : "=r" (val));
56ec944c93SMark Rutland 			break;
57ec944c93SMark Rutland 		case ARCH_TIMER_REG_TVAL:
58ec944c93SMark Rutland 			asm volatile("mrc p15, 0, %0, c14, c2, 0" : "=r" (val));
59ec944c93SMark Rutland 			break;
60ec944c93SMark Rutland 		}
61ec944c93SMark Rutland 	}
62ec944c93SMark Rutland 
63ec944c93SMark Rutland 	if (access == ARCH_TIMER_VIRT_ACCESS) {
64ec944c93SMark Rutland 		switch (reg) {
65ec944c93SMark Rutland 		case ARCH_TIMER_REG_CTRL:
66ec944c93SMark Rutland 			asm volatile("mrc p15, 0, %0, c14, c3, 1" : "=r" (val));
67ec944c93SMark Rutland 			break;
68ec944c93SMark Rutland 		case ARCH_TIMER_REG_TVAL:
69ec944c93SMark Rutland 			asm volatile("mrc p15, 0, %0, c14, c3, 0" : "=r" (val));
70ec944c93SMark Rutland 			break;
71ec944c93SMark Rutland 		}
72ec944c93SMark Rutland 	}
73ec944c93SMark Rutland 
74ec944c93SMark Rutland 	return val;
75ec944c93SMark Rutland }
76ec944c93SMark Rutland 
77ec944c93SMark Rutland static inline u32 arch_timer_get_cntfrq(void)
78ec944c93SMark Rutland {
79ec944c93SMark Rutland 	u32 val;
80ec944c93SMark Rutland 	asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (val));
81ec944c93SMark Rutland 	return val;
82ec944c93SMark Rutland }
83ec944c93SMark Rutland 
84ec944c93SMark Rutland static inline u64 arch_counter_get_cntpct(void)
85ec944c93SMark Rutland {
86ec944c93SMark Rutland 	u64 cval;
87ec944c93SMark Rutland 
8845801042SMark Rutland 	isb();
89ec944c93SMark Rutland 	asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r" (cval));
90ec944c93SMark Rutland 	return cval;
91ec944c93SMark Rutland }
92ec944c93SMark Rutland 
93ec944c93SMark Rutland static inline u64 arch_counter_get_cntvct(void)
94ec944c93SMark Rutland {
95ec944c93SMark Rutland 	u64 cval;
96ec944c93SMark Rutland 
9745801042SMark Rutland 	isb();
98ec944c93SMark Rutland 	asm volatile("mrrc p15, 1, %Q0, %R0, c14" : "=r" (cval));
99ec944c93SMark Rutland 	return cval;
100ec944c93SMark Rutland }
101b2deabe3SMark Rutland 
102b2deabe3SMark Rutland static inline void __cpuinit arch_counter_set_user_access(void)
103b2deabe3SMark Rutland {
104b2deabe3SMark Rutland 	u32 cntkctl;
105b2deabe3SMark Rutland 
106b2deabe3SMark Rutland 	asm volatile("mrc p15, 0, %0, c14, c1, 0" : "=r" (cntkctl));
107b2deabe3SMark Rutland 
108b2deabe3SMark Rutland 	/* disable user access to everything */
109b2deabe3SMark Rutland 	cntkctl &= ~((3 << 8) | (7 << 0));
110b2deabe3SMark Rutland 
111b2deabe3SMark Rutland 	asm volatile("mcr p15, 0, %0, c14, c1, 0" : : "r" (cntkctl));
112b2deabe3SMark Rutland }
113022c03a2SMarc Zyngier #else
1140075242bSMarc Zyngier static inline int arch_timer_of_register(void)
1150075242bSMarc Zyngier {
1160075242bSMarc Zyngier 	return -ENXIO;
1170075242bSMarc Zyngier }
1180075242bSMarc Zyngier 
1193f61c80eSMarc Zyngier static inline int arch_timer_sched_clock_init(void)
1203f61c80eSMarc Zyngier {
1213f61c80eSMarc Zyngier 	return -ENXIO;
1223f61c80eSMarc Zyngier }
123022c03a2SMarc Zyngier #endif
124022c03a2SMarc Zyngier 
125022c03a2SMarc Zyngier #endif
126