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
11typedef unsigned long cycles_t;
12
13#ifdef CONFIG_RISCV_M_MODE
14
15#include <asm/clint.h>
16
17#ifdef CONFIG_64BIT
18static inline cycles_t get_cycles(void)
19{
20	return readq_relaxed(clint_time_val);
21}
22#else /* !CONFIG_64BIT */
23static inline u32 get_cycles(void)
24{
25	return readl_relaxed(((u32 *)clint_time_val));
26}
27#define get_cycles get_cycles
28
29static 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 */
41static 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
51static inline cycles_t get_cycles(void)
52{
53	return csr_read(CSR_TIME);
54}
55#define get_cycles get_cycles
56
57static 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
66static inline u64 get_cycles64(void)
67{
68	return get_cycles();
69}
70#else /* CONFIG_64BIT */
71static 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
85static inline int read_current_timer(unsigned long *timer_val)
86{
87	*timer_val = get_cycles();
88	return 0;
89}
90
91#endif /* _ASM_RISCV_TIMEX_H */
92