1caab277bSThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */ 21aee5d7aSMark Rutland /* 31aee5d7aSMark Rutland * arch/arm64/include/asm/arch_timer.h 41aee5d7aSMark Rutland * 51aee5d7aSMark Rutland * Copyright (C) 2012 ARM Ltd. 61aee5d7aSMark Rutland * Author: Marc Zyngier <marc.zyngier@arm.com> 71aee5d7aSMark Rutland */ 81aee5d7aSMark Rutland #ifndef __ASM_ARCH_TIMER_H 91aee5d7aSMark Rutland #define __ASM_ARCH_TIMER_H 101aee5d7aSMark Rutland 111aee5d7aSMark Rutland #include <asm/barrier.h> 125a354412SAndrew Murray #include <asm/hwcap.h> 13cd5f22d7SMark Rutland #include <asm/sysreg.h> 141aee5d7aSMark Rutland 15082471a8SPaul Walmsley #include <linux/bug.h> 161aee5d7aSMark Rutland #include <linux/init.h> 17f6dc1576SScott Wood #include <linux/jump_label.h> 186acc71ccSMarc Zyngier #include <linux/smp.h> 191aee5d7aSMark Rutland #include <linux/types.h> 201aee5d7aSMark Rutland 211aee5d7aSMark Rutland #include <clocksource/arm_arch_timer.h> 221aee5d7aSMark Rutland 2316d10ef2SDing Tianhong #if IS_ENABLED(CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND) 245ef19a16SMarc Zyngier #define has_erratum_handler(h) \ 255ef19a16SMarc Zyngier ({ \ 265ef19a16SMarc Zyngier const struct arch_timer_erratum_workaround *__wa; \ 275ef19a16SMarc Zyngier __wa = __this_cpu_read(timer_unstable_counter_workaround); \ 285ef19a16SMarc Zyngier (__wa && __wa->h); \ 295ef19a16SMarc Zyngier }) 305ef19a16SMarc Zyngier 315ef19a16SMarc Zyngier #define erratum_handler(h) \ 325ef19a16SMarc Zyngier ({ \ 335ef19a16SMarc Zyngier const struct arch_timer_erratum_workaround *__wa; \ 345ef19a16SMarc Zyngier __wa = __this_cpu_read(timer_unstable_counter_workaround); \ 35db26f8f2SMarc Zyngier (__wa && __wa->h) ? ({ isb(); __wa->h;}) : arch_timer_##h; \ 365ef19a16SMarc Zyngier }) 375ef19a16SMarc Zyngier 38f6dc1576SScott Wood #else 395ef19a16SMarc Zyngier #define has_erratum_handler(h) false 405ef19a16SMarc Zyngier #define erratum_handler(h) (arch_timer_##h) 41f6dc1576SScott Wood #endif 42f6dc1576SScott Wood 43651bb2e9SMarc Zyngier enum arch_timer_erratum_match_type { 44651bb2e9SMarc Zyngier ate_match_dt, 450064030cSMarc Zyngier ate_match_local_cap_id, 465a38bcacSMarc Zyngier ate_match_acpi_oem_info, 47651bb2e9SMarc Zyngier }; 48f6dc1576SScott Wood 4901d3e3ffSMarc Zyngier struct clock_event_device; 5001d3e3ffSMarc Zyngier 5116d10ef2SDing Tianhong struct arch_timer_erratum_workaround { 52651bb2e9SMarc Zyngier enum arch_timer_erratum_match_type match_type; 53651bb2e9SMarc Zyngier const void *id; 54651bb2e9SMarc Zyngier const char *desc; 55f2e600c1SChristoffer Dall u64 (*read_cntpct_el0)(void); 5616d10ef2SDing Tianhong u64 (*read_cntvct_el0)(void); 5701d3e3ffSMarc Zyngier int (*set_next_event_phys)(unsigned long, struct clock_event_device *); 5801d3e3ffSMarc Zyngier int (*set_next_event_virt)(unsigned long, struct clock_event_device *); 59c1fbec4aSMarc Zyngier bool disable_compat_vdso; 6016d10ef2SDing Tianhong }; 6116d10ef2SDing Tianhong 626acc71ccSMarc Zyngier DECLARE_PER_CPU(const struct arch_timer_erratum_workaround *, 636acc71ccSMarc Zyngier timer_unstable_counter_workaround); 64f6dc1576SScott Wood 6557f27666SMarc Zyngier static inline notrace u64 arch_timer_read_cntpct_el0(void) 6657f27666SMarc Zyngier { 679ee840a9SMarc Zyngier u64 cnt; 689ee840a9SMarc Zyngier 699ee840a9SMarc Zyngier asm volatile(ALTERNATIVE("isb\n mrs %0, cntpct_el0", 709ee840a9SMarc Zyngier "nop\n" __mrs_s("%0", SYS_CNTPCTSS_EL0), 719ee840a9SMarc Zyngier ARM64_HAS_ECV) 729ee840a9SMarc Zyngier : "=r" (cnt)); 739ee840a9SMarc Zyngier 749ee840a9SMarc Zyngier return cnt; 7557f27666SMarc Zyngier } 7657f27666SMarc Zyngier 7757f27666SMarc Zyngier static inline notrace u64 arch_timer_read_cntvct_el0(void) 7857f27666SMarc Zyngier { 799ee840a9SMarc Zyngier u64 cnt; 809ee840a9SMarc Zyngier 819ee840a9SMarc Zyngier asm volatile(ALTERNATIVE("isb\n mrs %0, cntvct_el0", 829ee840a9SMarc Zyngier "nop\n" __mrs_s("%0", SYS_CNTVCTSS_EL0), 839ee840a9SMarc Zyngier ARM64_HAS_ECV) 849ee840a9SMarc Zyngier : "=r" (cnt)); 859ee840a9SMarc Zyngier 869ee840a9SMarc Zyngier return cnt; 8757f27666SMarc Zyngier } 8857f27666SMarc Zyngier 89f6dc1576SScott Wood #define arch_timer_reg_read_stable(reg) \ 90f6dc1576SScott Wood ({ \ 91*24ee7607SPeter Zijlstra erratum_handler(read_ ## reg)(); \ 92f6dc1576SScott Wood }) 93f6dc1576SScott Wood 94e09f3cc0SStephen Boyd /* 95e09f3cc0SStephen Boyd * These register accessors are marked inline so the compiler can 96e09f3cc0SStephen Boyd * nicely work out which register we want, and chuck away the rest of 97e09f3cc0SStephen Boyd * the code. 98e09f3cc0SStephen Boyd */ 99e09f3cc0SStephen Boyd static __always_inline 1001e8d9292SMarc Zyngier void arch_timer_reg_write_cp15(int access, enum arch_timer_reg reg, u64 val) 1011aee5d7aSMark Rutland { 1021aee5d7aSMark Rutland if (access == ARCH_TIMER_PHYS_ACCESS) { 1031aee5d7aSMark Rutland switch (reg) { 1041aee5d7aSMark Rutland case ARCH_TIMER_REG_CTRL: 105cd5f22d7SMark Rutland write_sysreg(val, cntp_ctl_el0); 106ec8f7f33SMarc Zyngier isb(); 1071aee5d7aSMark Rutland break; 108a38b71b0SMarc Zyngier case ARCH_TIMER_REG_CVAL: 109a38b71b0SMarc Zyngier write_sysreg(val, cntp_cval_el0); 1101aee5d7aSMark Rutland break; 1114775bc63SMarc Zyngier default: 1124775bc63SMarc Zyngier BUILD_BUG(); 1131aee5d7aSMark Rutland } 1141aee5d7aSMark Rutland } else if (access == ARCH_TIMER_VIRT_ACCESS) { 1151aee5d7aSMark Rutland switch (reg) { 1161aee5d7aSMark Rutland case ARCH_TIMER_REG_CTRL: 117cd5f22d7SMark Rutland write_sysreg(val, cntv_ctl_el0); 118ec8f7f33SMarc Zyngier isb(); 1191aee5d7aSMark Rutland break; 120a38b71b0SMarc Zyngier case ARCH_TIMER_REG_CVAL: 121a38b71b0SMarc Zyngier write_sysreg(val, cntv_cval_el0); 1221aee5d7aSMark Rutland break; 1234775bc63SMarc Zyngier default: 1244775bc63SMarc Zyngier BUILD_BUG(); 1251aee5d7aSMark Rutland } 1264775bc63SMarc Zyngier } else { 1274775bc63SMarc Zyngier BUILD_BUG(); 1281aee5d7aSMark Rutland } 1291aee5d7aSMark Rutland } 1301aee5d7aSMark Rutland 131e09f3cc0SStephen Boyd static __always_inline 132a38b71b0SMarc Zyngier u64 arch_timer_reg_read_cp15(int access, enum arch_timer_reg reg) 1331aee5d7aSMark Rutland { 1341aee5d7aSMark Rutland if (access == ARCH_TIMER_PHYS_ACCESS) { 1351aee5d7aSMark Rutland switch (reg) { 1361aee5d7aSMark Rutland case ARCH_TIMER_REG_CTRL: 137cd5f22d7SMark Rutland return read_sysreg(cntp_ctl_el0); 1384775bc63SMarc Zyngier default: 1394775bc63SMarc Zyngier BUILD_BUG(); 1401aee5d7aSMark Rutland } 1411aee5d7aSMark Rutland } else if (access == ARCH_TIMER_VIRT_ACCESS) { 1421aee5d7aSMark Rutland switch (reg) { 1431aee5d7aSMark Rutland case ARCH_TIMER_REG_CTRL: 144cd5f22d7SMark Rutland return read_sysreg(cntv_ctl_el0); 1454775bc63SMarc Zyngier default: 1464775bc63SMarc Zyngier BUILD_BUG(); 1471aee5d7aSMark Rutland } 1481aee5d7aSMark Rutland } 1491aee5d7aSMark Rutland 1504775bc63SMarc Zyngier BUILD_BUG(); 1514775bc63SMarc Zyngier unreachable(); 1521aee5d7aSMark Rutland } 1531aee5d7aSMark Rutland 1541aee5d7aSMark Rutland static inline u32 arch_timer_get_cntfrq(void) 1551aee5d7aSMark Rutland { 156cd5f22d7SMark Rutland return read_sysreg(cntfrq_el0); 1571aee5d7aSMark Rutland } 1581aee5d7aSMark Rutland 15946efe547SSudeep KarkadaNagesha static inline u32 arch_timer_get_cntkctl(void) 1601aee5d7aSMark Rutland { 161cd5f22d7SMark Rutland return read_sysreg(cntkctl_el1); 16246efe547SSudeep KarkadaNagesha } 16346efe547SSudeep KarkadaNagesha 16446efe547SSudeep KarkadaNagesha static inline void arch_timer_set_cntkctl(u32 cntkctl) 16546efe547SSudeep KarkadaNagesha { 166cd5f22d7SMark Rutland write_sysreg(cntkctl, cntkctl_el1); 167ec5c8e42SJulien Thierry isb(); 16846efe547SSudeep KarkadaNagesha } 16946efe547SSudeep KarkadaNagesha 170f31e98bfSAnders Roxell static __always_inline u64 __arch_counter_get_cntpct_stable(void) 1710b46b8a7SSonny Rao { 17275a19a02SWill Deacon u64 cnt; 17375a19a02SWill Deacon 17475a19a02SWill Deacon cnt = arch_timer_reg_read_stable(cntpct_el0); 17575a19a02SWill Deacon arch_counter_enforce_ordering(cnt); 17675a19a02SWill Deacon return cnt; 1770b46b8a7SSonny Rao } 1780b46b8a7SSonny Rao 179f31e98bfSAnders Roxell static __always_inline u64 __arch_counter_get_cntpct(void) 1800ea41539SMarc Zyngier { 18124cf262dSWill Deacon u64 cnt; 18224cf262dSWill Deacon 1839ee840a9SMarc Zyngier asm volatile(ALTERNATIVE("isb\n mrs %0, cntpct_el0", 1849ee840a9SMarc Zyngier "nop\n" __mrs_s("%0", SYS_CNTPCTSS_EL0), 1859ee840a9SMarc Zyngier ARM64_HAS_ECV) 1869ee840a9SMarc Zyngier : "=r" (cnt)); 18724cf262dSWill Deacon arch_counter_enforce_ordering(cnt); 18824cf262dSWill Deacon return cnt; 1890ea41539SMarc Zyngier } 1900ea41539SMarc Zyngier 191f31e98bfSAnders Roxell static __always_inline u64 __arch_counter_get_cntvct_stable(void) 1921aee5d7aSMark Rutland { 19375a19a02SWill Deacon u64 cnt; 19475a19a02SWill Deacon 19575a19a02SWill Deacon cnt = arch_timer_reg_read_stable(cntvct_el0); 19675a19a02SWill Deacon arch_counter_enforce_ordering(cnt); 19775a19a02SWill Deacon return cnt; 1981aee5d7aSMark Rutland } 1991aee5d7aSMark Rutland 200f31e98bfSAnders Roxell static __always_inline u64 __arch_counter_get_cntvct(void) 2010ea41539SMarc Zyngier { 20224cf262dSWill Deacon u64 cnt; 20324cf262dSWill Deacon 2049ee840a9SMarc Zyngier asm volatile(ALTERNATIVE("isb\n mrs %0, cntvct_el0", 2059ee840a9SMarc Zyngier "nop\n" __mrs_s("%0", SYS_CNTVCTSS_EL0), 2069ee840a9SMarc Zyngier ARM64_HAS_ECV) 2079ee840a9SMarc Zyngier : "=r" (cnt)); 20824cf262dSWill Deacon arch_counter_enforce_ordering(cnt); 20924cf262dSWill Deacon return cnt; 2100ea41539SMarc Zyngier } 2110ea41539SMarc Zyngier 2120583fe47SRob Herring static inline int arch_timer_arch_init(void) 2130583fe47SRob Herring { 2140583fe47SRob Herring return 0; 2150583fe47SRob Herring } 2160583fe47SRob Herring 2175a354412SAndrew Murray static inline void arch_timer_set_evtstrm_feature(void) 2185a354412SAndrew Murray { 2195a354412SAndrew Murray cpu_set_named_feature(EVTSTRM); 2205a354412SAndrew Murray #ifdef CONFIG_COMPAT 2215a354412SAndrew Murray compat_elf_hwcap |= COMPAT_HWCAP_EVTSTRM; 2225a354412SAndrew Murray #endif 2235a354412SAndrew Murray } 2245a354412SAndrew Murray 2255a354412SAndrew Murray static inline bool arch_timer_have_evtstrm_feature(void) 2265a354412SAndrew Murray { 2275a354412SAndrew Murray return cpu_have_named_feature(EVTSTRM); 2285a354412SAndrew Murray } 2291aee5d7aSMark Rutland #endif 230