/* SPDX-License-Identifier: GPL-2.0 */ /* * RISC-V Arch Timer(sstc) specific interface * * Copyright (c) 2024 Intel Corporation */ #ifndef SELFTEST_KVM_ARCH_TIMER_H #define SELFTEST_KVM_ARCH_TIMER_H #include <asm/csr.h> #include <asm/vdso/processor.h> static unsigned long timer_freq; #define msec_to_cycles(msec) \ ((timer_freq) * (uint64_t)(msec) / 1000) #define usec_to_cycles(usec) \ ((timer_freq) * (uint64_t)(usec) / 1000000) #define cycles_to_usec(cycles) \ ((uint64_t)(cycles) * 1000000 / (timer_freq)) static inline uint64_t timer_get_cycles(void) { return csr_read(CSR_TIME); } static inline void timer_set_cmp(uint64_t cval) { csr_write(CSR_STIMECMP, cval); } static inline uint64_t timer_get_cmp(void) { return csr_read(CSR_STIMECMP); } static inline void timer_irq_enable(void) { csr_set(CSR_SIE, IE_TIE); } static inline void timer_irq_disable(void) { csr_clear(CSR_SIE, IE_TIE); } static inline void timer_set_next_cmp_ms(uint32_t msec) { uint64_t now_ct = timer_get_cycles(); uint64_t next_ct = now_ct + msec_to_cycles(msec); timer_set_cmp(next_ct); } static inline void __delay(uint64_t cycles) { uint64_t start = timer_get_cycles(); while ((timer_get_cycles() - start) < cycles) cpu_relax(); } static inline void udelay(unsigned long usec) { __delay(usec_to_cycles(usec)); } #endif /* SELFTEST_KVM_ARCH_TIMER_H */