xref: /openbmc/linux/arch/arm64/include/asm/arch_timer.h (revision 0583fe478a7d93be2c814b7e50d6e81c287edfe8)
11aee5d7aSMark Rutland /*
21aee5d7aSMark Rutland  * arch/arm64/include/asm/arch_timer.h
31aee5d7aSMark Rutland  *
41aee5d7aSMark Rutland  * Copyright (C) 2012 ARM Ltd.
51aee5d7aSMark Rutland  * Author: Marc Zyngier <marc.zyngier@arm.com>
61aee5d7aSMark Rutland  *
71aee5d7aSMark Rutland  * This program is free software: you can redistribute it and/or modify
81aee5d7aSMark Rutland  * it under the terms of the GNU General Public License version 2 as
91aee5d7aSMark Rutland  * published by the Free Software Foundation.
101aee5d7aSMark Rutland  *
111aee5d7aSMark Rutland  * This program is distributed in the hope that it will be useful,
121aee5d7aSMark Rutland  * but WITHOUT ANY WARRANTY; without even the implied warranty of
131aee5d7aSMark Rutland  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
141aee5d7aSMark Rutland  * GNU General Public License for more details.
151aee5d7aSMark Rutland  *
161aee5d7aSMark Rutland  * You should have received a copy of the GNU General Public License
171aee5d7aSMark Rutland  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
181aee5d7aSMark Rutland  */
191aee5d7aSMark Rutland #ifndef __ASM_ARCH_TIMER_H
201aee5d7aSMark Rutland #define __ASM_ARCH_TIMER_H
211aee5d7aSMark Rutland 
221aee5d7aSMark Rutland #include <asm/barrier.h>
231aee5d7aSMark Rutland 
241aee5d7aSMark Rutland #include <linux/init.h>
251aee5d7aSMark Rutland #include <linux/types.h>
261aee5d7aSMark Rutland 
271aee5d7aSMark Rutland #include <clocksource/arm_arch_timer.h>
281aee5d7aSMark Rutland 
291aee5d7aSMark Rutland static inline void arch_timer_reg_write(int access, int reg, u32 val)
301aee5d7aSMark Rutland {
311aee5d7aSMark Rutland 	if (access == ARCH_TIMER_PHYS_ACCESS) {
321aee5d7aSMark Rutland 		switch (reg) {
331aee5d7aSMark Rutland 		case ARCH_TIMER_REG_CTRL:
341aee5d7aSMark Rutland 			asm volatile("msr cntp_ctl_el0,  %0" : : "r" (val));
351aee5d7aSMark Rutland 			break;
361aee5d7aSMark Rutland 		case ARCH_TIMER_REG_TVAL:
371aee5d7aSMark Rutland 			asm volatile("msr cntp_tval_el0, %0" : : "r" (val));
381aee5d7aSMark Rutland 			break;
391aee5d7aSMark Rutland 		default:
401aee5d7aSMark Rutland 			BUILD_BUG();
411aee5d7aSMark Rutland 		}
421aee5d7aSMark Rutland 	} else if (access == ARCH_TIMER_VIRT_ACCESS) {
431aee5d7aSMark Rutland 		switch (reg) {
441aee5d7aSMark Rutland 		case ARCH_TIMER_REG_CTRL:
451aee5d7aSMark Rutland 			asm volatile("msr cntv_ctl_el0,  %0" : : "r" (val));
461aee5d7aSMark Rutland 			break;
471aee5d7aSMark Rutland 		case ARCH_TIMER_REG_TVAL:
481aee5d7aSMark Rutland 			asm volatile("msr cntv_tval_el0, %0" : : "r" (val));
491aee5d7aSMark Rutland 			break;
501aee5d7aSMark Rutland 		default:
511aee5d7aSMark Rutland 			BUILD_BUG();
521aee5d7aSMark Rutland 		}
531aee5d7aSMark Rutland 	} else {
541aee5d7aSMark Rutland 		BUILD_BUG();
551aee5d7aSMark Rutland 	}
561aee5d7aSMark Rutland 
571aee5d7aSMark Rutland 	isb();
581aee5d7aSMark Rutland }
591aee5d7aSMark Rutland 
601aee5d7aSMark Rutland static inline u32 arch_timer_reg_read(int access, int reg)
611aee5d7aSMark Rutland {
621aee5d7aSMark Rutland 	u32 val;
631aee5d7aSMark Rutland 
641aee5d7aSMark Rutland 	if (access == ARCH_TIMER_PHYS_ACCESS) {
651aee5d7aSMark Rutland 		switch (reg) {
661aee5d7aSMark Rutland 		case ARCH_TIMER_REG_CTRL:
671aee5d7aSMark Rutland 			asm volatile("mrs %0,  cntp_ctl_el0" : "=r" (val));
681aee5d7aSMark Rutland 			break;
691aee5d7aSMark Rutland 		case ARCH_TIMER_REG_TVAL:
701aee5d7aSMark Rutland 			asm volatile("mrs %0, cntp_tval_el0" : "=r" (val));
711aee5d7aSMark Rutland 			break;
721aee5d7aSMark Rutland 		default:
731aee5d7aSMark Rutland 			BUILD_BUG();
741aee5d7aSMark Rutland 		}
751aee5d7aSMark Rutland 	} else if (access == ARCH_TIMER_VIRT_ACCESS) {
761aee5d7aSMark Rutland 		switch (reg) {
771aee5d7aSMark Rutland 		case ARCH_TIMER_REG_CTRL:
781aee5d7aSMark Rutland 			asm volatile("mrs %0,  cntv_ctl_el0" : "=r" (val));
791aee5d7aSMark Rutland 			break;
801aee5d7aSMark Rutland 		case ARCH_TIMER_REG_TVAL:
811aee5d7aSMark Rutland 			asm volatile("mrs %0, cntv_tval_el0" : "=r" (val));
821aee5d7aSMark Rutland 			break;
831aee5d7aSMark Rutland 		default:
841aee5d7aSMark Rutland 			BUILD_BUG();
851aee5d7aSMark Rutland 		}
861aee5d7aSMark Rutland 	} else {
871aee5d7aSMark Rutland 		BUILD_BUG();
881aee5d7aSMark Rutland 	}
891aee5d7aSMark Rutland 
901aee5d7aSMark Rutland 	return val;
911aee5d7aSMark Rutland }
921aee5d7aSMark Rutland 
931aee5d7aSMark Rutland static inline u32 arch_timer_get_cntfrq(void)
941aee5d7aSMark Rutland {
951aee5d7aSMark Rutland 	u32 val;
961aee5d7aSMark Rutland 	asm volatile("mrs %0,   cntfrq_el0" : "=r" (val));
971aee5d7aSMark Rutland 	return val;
981aee5d7aSMark Rutland }
991aee5d7aSMark Rutland 
1001aee5d7aSMark Rutland static inline void __cpuinit arch_counter_set_user_access(void)
1011aee5d7aSMark Rutland {
1021aee5d7aSMark Rutland 	u32 cntkctl;
1031aee5d7aSMark Rutland 
1041aee5d7aSMark Rutland 	/* Disable user access to the timers and the physical counter. */
1051aee5d7aSMark Rutland 	asm volatile("mrs	%0, cntkctl_el1" : "=r" (cntkctl));
1061aee5d7aSMark Rutland 	cntkctl &= ~((3 << 8) | (1 << 0));
1071aee5d7aSMark Rutland 
1081aee5d7aSMark Rutland 	/* Enable user access to the virtual counter and frequency. */
1091aee5d7aSMark Rutland 	cntkctl |= (1 << 1);
1101aee5d7aSMark Rutland 	asm volatile("msr	cntkctl_el1, %0" : : "r" (cntkctl));
1111aee5d7aSMark Rutland }
1121aee5d7aSMark Rutland 
1131aee5d7aSMark Rutland static inline u64 arch_counter_get_cntpct(void)
1141aee5d7aSMark Rutland {
1151aee5d7aSMark Rutland 	u64 cval;
1161aee5d7aSMark Rutland 
1171aee5d7aSMark Rutland 	isb();
1181aee5d7aSMark Rutland 	asm volatile("mrs %0, cntpct_el0" : "=r" (cval));
1191aee5d7aSMark Rutland 
1201aee5d7aSMark Rutland 	return cval;
1211aee5d7aSMark Rutland }
1221aee5d7aSMark Rutland 
1231aee5d7aSMark Rutland static inline u64 arch_counter_get_cntvct(void)
1241aee5d7aSMark Rutland {
1251aee5d7aSMark Rutland 	u64 cval;
1261aee5d7aSMark Rutland 
1271aee5d7aSMark Rutland 	isb();
1281aee5d7aSMark Rutland 	asm volatile("mrs %0, cntvct_el0" : "=r" (cval));
1291aee5d7aSMark Rutland 
1301aee5d7aSMark Rutland 	return cval;
1311aee5d7aSMark Rutland }
1321aee5d7aSMark Rutland 
133*0583fe47SRob Herring static inline int arch_timer_arch_init(void)
134*0583fe47SRob Herring {
135*0583fe47SRob Herring 	return 0;
136*0583fe47SRob Herring }
137*0583fe47SRob Herring 
1381aee5d7aSMark Rutland #endif
139