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