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