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> 7ec944c93SMark 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); 13ec944c93SMark Rutland 14ec944c93SMark Rutland #define ARCH_TIMER_CTRL_ENABLE (1 << 0) 15ec944c93SMark Rutland #define ARCH_TIMER_CTRL_IT_MASK (1 << 1) 16ec944c93SMark Rutland #define ARCH_TIMER_CTRL_IT_STAT (1 << 2) 17ec944c93SMark Rutland 18ec944c93SMark Rutland #define ARCH_TIMER_REG_CTRL 0 19ec944c93SMark Rutland #define ARCH_TIMER_REG_TVAL 1 20ec944c93SMark Rutland 21ec944c93SMark Rutland #define ARCH_TIMER_PHYS_ACCESS 0 22ec944c93SMark Rutland #define ARCH_TIMER_VIRT_ACCESS 1 23ec944c93SMark Rutland 24ec944c93SMark Rutland /* 25ec944c93SMark Rutland * These register accessors are marked inline so the compiler can 26ec944c93SMark Rutland * nicely work out which register we want, and chuck away the rest of 27ec944c93SMark Rutland * the code. At least it does so with a recent GCC (4.6.3). 28ec944c93SMark Rutland */ 29ec944c93SMark Rutland static inline void arch_timer_reg_write(const int access, const int reg, u32 val) 30ec944c93SMark Rutland { 31ec944c93SMark Rutland if (access == ARCH_TIMER_PHYS_ACCESS) { 32ec944c93SMark Rutland switch (reg) { 33ec944c93SMark Rutland case ARCH_TIMER_REG_CTRL: 34ec944c93SMark Rutland asm volatile("mcr p15, 0, %0, c14, c2, 1" : : "r" (val)); 35ec944c93SMark Rutland break; 36ec944c93SMark Rutland case ARCH_TIMER_REG_TVAL: 37ec944c93SMark Rutland asm volatile("mcr p15, 0, %0, c14, c2, 0" : : "r" (val)); 38ec944c93SMark Rutland break; 39ec944c93SMark Rutland } 40ec944c93SMark Rutland } 41ec944c93SMark Rutland 42ec944c93SMark Rutland if (access == ARCH_TIMER_VIRT_ACCESS) { 43ec944c93SMark Rutland switch (reg) { 44ec944c93SMark Rutland case ARCH_TIMER_REG_CTRL: 45ec944c93SMark Rutland asm volatile("mcr p15, 0, %0, c14, c3, 1" : : "r" (val)); 46ec944c93SMark Rutland break; 47ec944c93SMark Rutland case ARCH_TIMER_REG_TVAL: 48ec944c93SMark Rutland asm volatile("mcr p15, 0, %0, c14, c3, 0" : : "r" (val)); 49ec944c93SMark Rutland break; 50ec944c93SMark Rutland } 51ec944c93SMark Rutland } 52*45801042SMark Rutland 53*45801042SMark Rutland isb(); 54ec944c93SMark Rutland } 55ec944c93SMark Rutland 56ec944c93SMark Rutland static inline u32 arch_timer_reg_read(const int access, const int reg) 57ec944c93SMark Rutland { 58ec944c93SMark Rutland u32 val = 0; 59ec944c93SMark Rutland 60ec944c93SMark Rutland if (access == ARCH_TIMER_PHYS_ACCESS) { 61ec944c93SMark Rutland switch (reg) { 62ec944c93SMark Rutland case ARCH_TIMER_REG_CTRL: 63ec944c93SMark Rutland asm volatile("mrc p15, 0, %0, c14, c2, 1" : "=r" (val)); 64ec944c93SMark Rutland break; 65ec944c93SMark Rutland case ARCH_TIMER_REG_TVAL: 66ec944c93SMark Rutland asm volatile("mrc p15, 0, %0, c14, c2, 0" : "=r" (val)); 67ec944c93SMark Rutland break; 68ec944c93SMark Rutland } 69ec944c93SMark Rutland } 70ec944c93SMark Rutland 71ec944c93SMark Rutland if (access == ARCH_TIMER_VIRT_ACCESS) { 72ec944c93SMark Rutland switch (reg) { 73ec944c93SMark Rutland case ARCH_TIMER_REG_CTRL: 74ec944c93SMark Rutland asm volatile("mrc p15, 0, %0, c14, c3, 1" : "=r" (val)); 75ec944c93SMark Rutland break; 76ec944c93SMark Rutland case ARCH_TIMER_REG_TVAL: 77ec944c93SMark Rutland asm volatile("mrc p15, 0, %0, c14, c3, 0" : "=r" (val)); 78ec944c93SMark Rutland break; 79ec944c93SMark Rutland } 80ec944c93SMark Rutland } 81ec944c93SMark Rutland 82ec944c93SMark Rutland return val; 83ec944c93SMark Rutland } 84ec944c93SMark Rutland 85ec944c93SMark Rutland static inline u32 arch_timer_get_cntfrq(void) 86ec944c93SMark Rutland { 87ec944c93SMark Rutland u32 val; 88ec944c93SMark Rutland asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (val)); 89ec944c93SMark Rutland return val; 90ec944c93SMark Rutland } 91ec944c93SMark Rutland 92ec944c93SMark Rutland static inline u64 arch_counter_get_cntpct(void) 93ec944c93SMark Rutland { 94ec944c93SMark Rutland u64 cval; 95ec944c93SMark Rutland 96*45801042SMark Rutland isb(); 97ec944c93SMark Rutland asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r" (cval)); 98ec944c93SMark Rutland return cval; 99ec944c93SMark Rutland } 100ec944c93SMark Rutland 101ec944c93SMark Rutland static inline u64 arch_counter_get_cntvct(void) 102ec944c93SMark Rutland { 103ec944c93SMark Rutland u64 cval; 104ec944c93SMark Rutland 105*45801042SMark Rutland isb(); 106ec944c93SMark Rutland asm volatile("mrrc p15, 1, %Q0, %R0, c14" : "=r" (cval)); 107ec944c93SMark Rutland return cval; 108ec944c93SMark Rutland } 109022c03a2SMarc Zyngier #else 1100075242bSMarc Zyngier static inline int arch_timer_of_register(void) 1110075242bSMarc Zyngier { 1120075242bSMarc Zyngier return -ENXIO; 1130075242bSMarc Zyngier } 1140075242bSMarc Zyngier 1153f61c80eSMarc Zyngier static inline int arch_timer_sched_clock_init(void) 1163f61c80eSMarc Zyngier { 1173f61c80eSMarc Zyngier return -ENXIO; 1183f61c80eSMarc Zyngier } 119a1b2dde7SMarc Zyngier 120a1b2dde7SMarc Zyngier static inline struct timecounter *arch_timer_get_timecounter(void) 121a1b2dde7SMarc Zyngier { 122a1b2dde7SMarc Zyngier return NULL; 123a1b2dde7SMarc Zyngier } 124022c03a2SMarc Zyngier #endif 125022c03a2SMarc Zyngier 126022c03a2SMarc Zyngier #endif 127