1 /* 2 * arch/arm64/include/asm/arch_timer.h 3 * 4 * Copyright (C) 2012 ARM Ltd. 5 * Author: Marc Zyngier <marc.zyngier@arm.com> 6 * 7 * This program is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 #ifndef __ASM_ARCH_TIMER_H 20 #define __ASM_ARCH_TIMER_H 21 22 #include <asm/barrier.h> 23 24 #include <linux/bug.h> 25 #include <linux/init.h> 26 #include <linux/types.h> 27 28 #include <clocksource/arm_arch_timer.h> 29 30 /* 31 * These register accessors are marked inline so the compiler can 32 * nicely work out which register we want, and chuck away the rest of 33 * the code. 34 */ 35 static __always_inline 36 void arch_timer_reg_write_cp15(int access, enum arch_timer_reg reg, u32 val) 37 { 38 if (access == ARCH_TIMER_PHYS_ACCESS) { 39 switch (reg) { 40 case ARCH_TIMER_REG_CTRL: 41 asm volatile("msr cntp_ctl_el0, %0" : : "r" (val)); 42 break; 43 case ARCH_TIMER_REG_TVAL: 44 asm volatile("msr cntp_tval_el0, %0" : : "r" (val)); 45 break; 46 } 47 } else if (access == ARCH_TIMER_VIRT_ACCESS) { 48 switch (reg) { 49 case ARCH_TIMER_REG_CTRL: 50 asm volatile("msr cntv_ctl_el0, %0" : : "r" (val)); 51 break; 52 case ARCH_TIMER_REG_TVAL: 53 asm volatile("msr cntv_tval_el0, %0" : : "r" (val)); 54 break; 55 } 56 } 57 58 isb(); 59 } 60 61 static __always_inline 62 u32 arch_timer_reg_read_cp15(int access, enum arch_timer_reg reg) 63 { 64 u32 val; 65 66 if (access == ARCH_TIMER_PHYS_ACCESS) { 67 switch (reg) { 68 case ARCH_TIMER_REG_CTRL: 69 asm volatile("mrs %0, cntp_ctl_el0" : "=r" (val)); 70 break; 71 case ARCH_TIMER_REG_TVAL: 72 asm volatile("mrs %0, cntp_tval_el0" : "=r" (val)); 73 break; 74 } 75 } else if (access == ARCH_TIMER_VIRT_ACCESS) { 76 switch (reg) { 77 case ARCH_TIMER_REG_CTRL: 78 asm volatile("mrs %0, cntv_ctl_el0" : "=r" (val)); 79 break; 80 case ARCH_TIMER_REG_TVAL: 81 asm volatile("mrs %0, cntv_tval_el0" : "=r" (val)); 82 break; 83 } 84 } 85 86 return val; 87 } 88 89 static inline u32 arch_timer_get_cntfrq(void) 90 { 91 u32 val; 92 asm volatile("mrs %0, cntfrq_el0" : "=r" (val)); 93 return val; 94 } 95 96 static inline u32 arch_timer_get_cntkctl(void) 97 { 98 u32 cntkctl; 99 asm volatile("mrs %0, cntkctl_el1" : "=r" (cntkctl)); 100 return cntkctl; 101 } 102 103 static inline void arch_timer_set_cntkctl(u32 cntkctl) 104 { 105 asm volatile("msr cntkctl_el1, %0" : : "r" (cntkctl)); 106 } 107 108 static inline u64 arch_counter_get_cntpct(void) 109 { 110 /* 111 * AArch64 kernel and user space mandate the use of CNTVCT. 112 */ 113 BUG(); 114 return 0; 115 } 116 117 static inline u64 arch_counter_get_cntvct(void) 118 { 119 u64 cval; 120 121 isb(); 122 asm volatile("mrs %0, cntvct_el0" : "=r" (cval)); 123 124 return cval; 125 } 126 127 static inline int arch_timer_arch_init(void) 128 { 129 return 0; 130 } 131 132 #endif 133