xref: /openbmc/linux/arch/riscv/include/asm/timex.h (revision f71a261a)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * Copyright (C) 2012 Regents of the University of California
4  */
5 
6 #ifndef _ASM_RISCV_TIMEX_H
7 #define _ASM_RISCV_TIMEX_H
8 
9 #include <asm/csr.h>
10 
11 typedef unsigned long cycles_t;
12 
13 #ifdef CONFIG_RISCV_M_MODE
14 
15 #include <asm/clint.h>
16 
17 #ifdef CONFIG_64BIT
18 static inline cycles_t get_cycles(void)
19 {
20 	return readq_relaxed(clint_time_val);
21 }
22 #else /* !CONFIG_64BIT */
23 static inline u32 get_cycles(void)
24 {
25 	return readl_relaxed(((u32 *)clint_time_val));
26 }
27 #define get_cycles get_cycles
28 
29 static inline u32 get_cycles_hi(void)
30 {
31 	return readl_relaxed(((u32 *)clint_time_val) + 1);
32 }
33 #define get_cycles_hi get_cycles_hi
34 #endif /* CONFIG_64BIT */
35 
36 /*
37  * Much like MIPS, we may not have a viable counter to use at an early point
38  * in the boot process. Unfortunately we don't have a fallback, so instead
39  * we just return 0.
40  */
41 static inline unsigned long random_get_entropy(void)
42 {
43 	if (unlikely(clint_time_val == NULL))
44 		return random_get_entropy_fallback();
45 	return get_cycles();
46 }
47 #define random_get_entropy()	random_get_entropy()
48 
49 #else /* CONFIG_RISCV_M_MODE */
50 
51 static inline cycles_t get_cycles(void)
52 {
53 	return csr_read(CSR_TIME);
54 }
55 #define get_cycles get_cycles
56 
57 static inline u32 get_cycles_hi(void)
58 {
59 	return csr_read(CSR_TIMEH);
60 }
61 #define get_cycles_hi get_cycles_hi
62 
63 #endif /* !CONFIG_RISCV_M_MODE */
64 
65 #ifdef CONFIG_64BIT
66 static inline u64 get_cycles64(void)
67 {
68 	return get_cycles();
69 }
70 #else /* CONFIG_64BIT */
71 static inline u64 get_cycles64(void)
72 {
73 	u32 hi, lo;
74 
75 	do {
76 		hi = get_cycles_hi();
77 		lo = get_cycles();
78 	} while (hi != get_cycles_hi());
79 
80 	return ((u64)hi << 32) | lo;
81 }
82 #endif /* CONFIG_64BIT */
83 
84 #define ARCH_HAS_READ_CURRENT_TIMER
85 static inline int read_current_timer(unsigned long *timer_val)
86 {
87 	*timer_val = get_cycles();
88 	return 0;
89 }
90 
91 extern void time_init(void);
92 
93 #endif /* _ASM_RISCV_TIMEX_H */
94