xref: /linux/tools/testing/selftests/kvm/include/loongarch/arch_timer.h (revision 8040280405364822f50c4c91cdbc29cf391c4091)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * LoongArch Constant Timer specific interface
4  */
5 #ifndef SELFTEST_KVM_ARCH_TIMER_H
6 #define SELFTEST_KVM_ARCH_TIMER_H
7 
8 #include "processor.h"
9 
10 /* LoongArch timer frequency is constant 100MHZ */
11 #define TIMER_FREQ		(100UL << 20)
12 #define msec_to_cycles(msec)	(TIMER_FREQ * (unsigned long)(msec) / 1000)
13 #define usec_to_cycles(usec)	(TIMER_FREQ * (unsigned long)(usec) / 1000000)
14 #define cycles_to_usec(cycles)	((unsigned long)(cycles) * 1000000 / TIMER_FREQ)
15 
16 static inline unsigned long timer_get_cycles(void)
17 {
18 	unsigned long val = 0;
19 
20 	__asm__ __volatile__(
21 		"rdtime.d %0, $zero\n\t"
22 		: "=r"(val)
23 		:
24 	);
25 
26 	return val;
27 }
28 
29 static inline unsigned long timer_get_cfg(void)
30 {
31 	return csr_read(LOONGARCH_CSR_TCFG);
32 }
33 
34 static inline unsigned long timer_get_val(void)
35 {
36 	return csr_read(LOONGARCH_CSR_TVAL);
37 }
38 
39 static inline void disable_timer(void)
40 {
41 	csr_write(0, LOONGARCH_CSR_TCFG);
42 }
43 
44 static inline void timer_irq_enable(void)
45 {
46 	unsigned long val;
47 
48 	val = csr_read(LOONGARCH_CSR_ECFG);
49 	val |= ECFGF_TIMER;
50 	csr_write(val, LOONGARCH_CSR_ECFG);
51 }
52 
53 static inline void timer_irq_disable(void)
54 {
55 	unsigned long val;
56 
57 	val = csr_read(LOONGARCH_CSR_ECFG);
58 	val &= ~ECFGF_TIMER;
59 	csr_write(val, LOONGARCH_CSR_ECFG);
60 }
61 
62 static inline void timer_set_next_cmp_ms(unsigned int msec, bool period)
63 {
64 	unsigned long val;
65 
66 	val = msec_to_cycles(msec) & CSR_TCFG_VAL;
67 	val |= CSR_TCFG_EN;
68 	if (period)
69 		val |= CSR_TCFG_PERIOD;
70 	csr_write(val, LOONGARCH_CSR_TCFG);
71 }
72 
73 static inline void __delay(uint64_t cycles)
74 {
75 	uint64_t start = timer_get_cycles();
76 
77 	while ((timer_get_cycles() - start) < cycles)
78 		cpu_relax();
79 }
80 
81 static inline void udelay(unsigned long usec)
82 {
83 	__delay(usec_to_cycles(usec));
84 }
85 #endif /* SELFTEST_KVM_ARCH_TIMER_H */
86