Commit | Line | Data |
---|---|---|
022c03a2 MZ |
1 | #ifndef __ASMARM_ARCH_TIMER_H |
2 | #define __ASMARM_ARCH_TIMER_H | |
3 | ||
ec944c93 | 4 | #include <asm/barrier.h> |
923df96b | 5 | #include <asm/errno.h> |
a1b2dde7 | 6 | #include <linux/clocksource.h> |
8a4da6e3 | 7 | #include <linux/init.h> |
ec944c93 | 8 | #include <linux/types.h> |
923df96b | 9 | |
8a4da6e3 MR |
10 | #include <clocksource/arm_arch_timer.h> |
11 | ||
022c03a2 | 12 | #ifdef CONFIG_ARM_ARCH_TIMER |
0583fe47 | 13 | int arch_timer_arch_init(void); |
ec944c93 MR |
14 | |
15 | /* | |
16 | * These register accessors are marked inline so the compiler can | |
17 | * nicely work out which register we want, and chuck away the rest of | |
18 | * the code. At least it does so with a recent GCC (4.6.3). | |
19 | */ | |
e09f3cc0 | 20 | static __always_inline |
60faddf6 | 21 | void arch_timer_reg_write_cp15(int access, enum arch_timer_reg reg, u32 val) |
ec944c93 MR |
22 | { |
23 | if (access == ARCH_TIMER_PHYS_ACCESS) { | |
24 | switch (reg) { | |
25 | case ARCH_TIMER_REG_CTRL: | |
26 | asm volatile("mcr p15, 0, %0, c14, c2, 1" : : "r" (val)); | |
27 | break; | |
28 | case ARCH_TIMER_REG_TVAL: | |
29 | asm volatile("mcr p15, 0, %0, c14, c2, 0" : : "r" (val)); | |
30 | break; | |
31 | } | |
e09f3cc0 | 32 | } else if (access == ARCH_TIMER_VIRT_ACCESS) { |
ec944c93 MR |
33 | switch (reg) { |
34 | case ARCH_TIMER_REG_CTRL: | |
35 | asm volatile("mcr p15, 0, %0, c14, c3, 1" : : "r" (val)); | |
36 | break; | |
37 | case ARCH_TIMER_REG_TVAL: | |
38 | asm volatile("mcr p15, 0, %0, c14, c3, 0" : : "r" (val)); | |
39 | break; | |
40 | } | |
41 | } | |
45801042 MR |
42 | |
43 | isb(); | |
ec944c93 MR |
44 | } |
45 | ||
e09f3cc0 | 46 | static __always_inline |
60faddf6 | 47 | u32 arch_timer_reg_read_cp15(int access, enum arch_timer_reg reg) |
ec944c93 MR |
48 | { |
49 | u32 val = 0; | |
50 | ||
51 | if (access == ARCH_TIMER_PHYS_ACCESS) { | |
52 | switch (reg) { | |
53 | case ARCH_TIMER_REG_CTRL: | |
54 | asm volatile("mrc p15, 0, %0, c14, c2, 1" : "=r" (val)); | |
55 | break; | |
56 | case ARCH_TIMER_REG_TVAL: | |
57 | asm volatile("mrc p15, 0, %0, c14, c2, 0" : "=r" (val)); | |
58 | break; | |
59 | } | |
e09f3cc0 | 60 | } else if (access == ARCH_TIMER_VIRT_ACCESS) { |
ec944c93 MR |
61 | switch (reg) { |
62 | case ARCH_TIMER_REG_CTRL: | |
63 | asm volatile("mrc p15, 0, %0, c14, c3, 1" : "=r" (val)); | |
64 | break; | |
65 | case ARCH_TIMER_REG_TVAL: | |
66 | asm volatile("mrc p15, 0, %0, c14, c3, 0" : "=r" (val)); | |
67 | break; | |
68 | } | |
69 | } | |
70 | ||
71 | return val; | |
72 | } | |
73 | ||
74 | static inline u32 arch_timer_get_cntfrq(void) | |
75 | { | |
76 | u32 val; | |
77 | asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (val)); | |
78 | return val; | |
79 | } | |
80 | ||
0b46b8a7 SR |
81 | static inline u64 arch_counter_get_cntpct(void) |
82 | { | |
83 | u64 cval; | |
84 | ||
85 | isb(); | |
86 | asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r" (cval)); | |
87 | return cval; | |
88 | } | |
89 | ||
ec944c93 MR |
90 | static inline u64 arch_counter_get_cntvct(void) |
91 | { | |
92 | u64 cval; | |
93 | ||
45801042 | 94 | isb(); |
ec944c93 MR |
95 | asm volatile("mrrc p15, 1, %Q0, %R0, c14" : "=r" (cval)); |
96 | return cval; | |
97 | } | |
b2deabe3 | 98 | |
e9faebc6 | 99 | static inline u32 arch_timer_get_cntkctl(void) |
b2deabe3 MR |
100 | { |
101 | u32 cntkctl; | |
b2deabe3 | 102 | asm volatile("mrc p15, 0, %0, c14, c1, 0" : "=r" (cntkctl)); |
e9faebc6 SK |
103 | return cntkctl; |
104 | } | |
105 | ||
106 | static inline void arch_timer_set_cntkctl(u32 cntkctl) | |
107 | { | |
108 | asm volatile("mcr p15, 0, %0, c14, c1, 0" : : "r" (cntkctl)); | |
109 | } | |
110 | ||
022c03a2 MZ |
111 | #endif |
112 | ||
113 | #endif |