| /* 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 */ |