xref: /linux/arch/arm/include/asm/arch_timer.h (revision b2deabe3ba664a1ec47400c0ca285e951874e0cc)
1 #ifndef __ASMARM_ARCH_TIMER_H
2 #define __ASMARM_ARCH_TIMER_H
3 
4 #include <asm/barrier.h>
5 #include <asm/errno.h>
6 #include <linux/clocksource.h>
7 #include <linux/types.h>
8 
9 #ifdef CONFIG_ARM_ARCH_TIMER
10 int arch_timer_of_register(void);
11 int arch_timer_sched_clock_init(void);
12 struct timecounter *arch_timer_get_timecounter(void);
13 
14 #define ARCH_TIMER_CTRL_ENABLE		(1 << 0)
15 #define ARCH_TIMER_CTRL_IT_MASK		(1 << 1)
16 #define ARCH_TIMER_CTRL_IT_STAT		(1 << 2)
17 
18 #define ARCH_TIMER_REG_CTRL		0
19 #define ARCH_TIMER_REG_TVAL		1
20 
21 #define ARCH_TIMER_PHYS_ACCESS		0
22 #define ARCH_TIMER_VIRT_ACCESS		1
23 
24 /*
25  * These register accessors are marked inline so the compiler can
26  * nicely work out which register we want, and chuck away the rest of
27  * the code. At least it does so with a recent GCC (4.6.3).
28  */
29 static inline void arch_timer_reg_write(const int access, const int reg, u32 val)
30 {
31 	if (access == ARCH_TIMER_PHYS_ACCESS) {
32 		switch (reg) {
33 		case ARCH_TIMER_REG_CTRL:
34 			asm volatile("mcr p15, 0, %0, c14, c2, 1" : : "r" (val));
35 			break;
36 		case ARCH_TIMER_REG_TVAL:
37 			asm volatile("mcr p15, 0, %0, c14, c2, 0" : : "r" (val));
38 			break;
39 		}
40 	}
41 
42 	if (access == ARCH_TIMER_VIRT_ACCESS) {
43 		switch (reg) {
44 		case ARCH_TIMER_REG_CTRL:
45 			asm volatile("mcr p15, 0, %0, c14, c3, 1" : : "r" (val));
46 			break;
47 		case ARCH_TIMER_REG_TVAL:
48 			asm volatile("mcr p15, 0, %0, c14, c3, 0" : : "r" (val));
49 			break;
50 		}
51 	}
52 
53 	isb();
54 }
55 
56 static inline u32 arch_timer_reg_read(const int access, const int reg)
57 {
58 	u32 val = 0;
59 
60 	if (access == ARCH_TIMER_PHYS_ACCESS) {
61 		switch (reg) {
62 		case ARCH_TIMER_REG_CTRL:
63 			asm volatile("mrc p15, 0, %0, c14, c2, 1" : "=r" (val));
64 			break;
65 		case ARCH_TIMER_REG_TVAL:
66 			asm volatile("mrc p15, 0, %0, c14, c2, 0" : "=r" (val));
67 			break;
68 		}
69 	}
70 
71 	if (access == ARCH_TIMER_VIRT_ACCESS) {
72 		switch (reg) {
73 		case ARCH_TIMER_REG_CTRL:
74 			asm volatile("mrc p15, 0, %0, c14, c3, 1" : "=r" (val));
75 			break;
76 		case ARCH_TIMER_REG_TVAL:
77 			asm volatile("mrc p15, 0, %0, c14, c3, 0" : "=r" (val));
78 			break;
79 		}
80 	}
81 
82 	return val;
83 }
84 
85 static inline u32 arch_timer_get_cntfrq(void)
86 {
87 	u32 val;
88 	asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (val));
89 	return val;
90 }
91 
92 static inline u64 arch_counter_get_cntpct(void)
93 {
94 	u64 cval;
95 
96 	isb();
97 	asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r" (cval));
98 	return cval;
99 }
100 
101 static inline u64 arch_counter_get_cntvct(void)
102 {
103 	u64 cval;
104 
105 	isb();
106 	asm volatile("mrrc p15, 1, %Q0, %R0, c14" : "=r" (cval));
107 	return cval;
108 }
109 
110 static inline void __cpuinit arch_counter_set_user_access(void)
111 {
112 	u32 cntkctl;
113 
114 	asm volatile("mrc p15, 0, %0, c14, c1, 0" : "=r" (cntkctl));
115 
116 	/* disable user access to everything */
117 	cntkctl &= ~((3 << 8) | (7 << 0));
118 
119 	asm volatile("mcr p15, 0, %0, c14, c1, 0" : : "r" (cntkctl));
120 }
121 #else
122 static inline int arch_timer_of_register(void)
123 {
124 	return -ENXIO;
125 }
126 
127 static inline int arch_timer_sched_clock_init(void)
128 {
129 	return -ENXIO;
130 }
131 
132 static inline struct timecounter *arch_timer_get_timecounter(void)
133 {
134 	return NULL;
135 }
136 #endif
137 
138 #endif
139