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 */ 35static __always_inline 36void 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 61static __always_inline 62u32 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 89static 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 96static 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 103static inline void arch_timer_set_cntkctl(u32 cntkctl) 104{ 105 asm volatile("msr cntkctl_el1, %0" : : "r" (cntkctl)); 106} 107 108static 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 117static 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 127static inline int arch_timer_arch_init(void) 128{ 129 return 0; 130} 131 132#endif 133