1 /*
2  * Copyright (c) 2018-2023 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <limits.h>
8 
9 #include <zephyr/init.h>
10 #include <zephyr/devicetree.h>
11 #include <zephyr/drivers/timer/system_timer.h>
12 #include <zephyr/sys_clock.h>
13 #include <zephyr/spinlock.h>
14 #include <zephyr/irq.h>
15 
16 /* andestech,machine-timer */
17 #if DT_HAS_COMPAT_STATUS_OKAY(andestech_machine_timer)
18 #define DT_DRV_COMPAT andestech_machine_timer
19 
20 #define MTIME_REG	DT_INST_REG_ADDR(0)
21 #define MTIMECMP_REG	(DT_INST_REG_ADDR(0) + 8)
22 #define TIMER_IRQN	DT_INST_IRQN(0)
23 /* neorv32-machine-timer */
24 #elif DT_HAS_COMPAT_STATUS_OKAY(neorv32_machine_timer)
25 #define DT_DRV_COMPAT neorv32_machine_timer
26 
27 #define MTIME_REG	DT_INST_REG_ADDR(0)
28 #define MTIMECMP_REG	(DT_INST_REG_ADDR(0) + 8)
29 #define TIMER_IRQN	DT_INST_IRQN(0)
30 /* nuclei,systimer */
31 #elif DT_HAS_COMPAT_STATUS_OKAY(nuclei_systimer)
32 #define DT_DRV_COMPAT nuclei_systimer
33 
34 #define MTIME_REG	DT_INST_REG_ADDR(0)
35 #define MTIMECMP_REG	(DT_INST_REG_ADDR(0) + 8)
36 #define TIMER_IRQN	DT_INST_IRQ_BY_IDX(0, 1, irq)
37 /* sifive,clint0 */
38 #elif DT_HAS_COMPAT_STATUS_OKAY(sifive_clint0)
39 #define DT_DRV_COMPAT sifive_clint0
40 
41 #define MTIME_REG	(DT_INST_REG_ADDR(0) + 0xbff8U)
42 #define MTIMECMP_REG	(DT_INST_REG_ADDR(0) + 0x4000U)
43 #define TIMER_IRQN	DT_INST_IRQ_BY_IDX(0, 1, irq)
44 /* telink,machine-timer */
45 #elif DT_HAS_COMPAT_STATUS_OKAY(telink_machine_timer)
46 #define DT_DRV_COMPAT telink_machine_timer
47 
48 #define MTIME_REG	DT_INST_REG_ADDR(0)
49 #define MTIMECMP_REG	(DT_INST_REG_ADDR(0) + 8)
50 #define TIMER_IRQN	DT_INST_IRQN(0)
51 /* lowrisc,machine-timer */
52 #elif DT_HAS_COMPAT_STATUS_OKAY(lowrisc_machine_timer)
53 #define DT_DRV_COMPAT lowrisc_machine_timer
54 
55 #define MTIME_REG	(DT_INST_REG_ADDR(0) + 0x110)
56 #define MTIMECMP_REG	(DT_INST_REG_ADDR(0) + 0x118)
57 #define TIMER_IRQN	DT_INST_IRQN(0)
58 /* niosv-machine-timer */
59 #elif DT_HAS_COMPAT_STATUS_OKAY(niosv_machine_timer)
60 #define DT_DRV_COMPAT niosv_machine_timer
61 
62 #define MTIMECMP_REG	DT_INST_REG_ADDR(0)
63 #define MTIME_REG	(DT_INST_REG_ADDR(0) + 8)
64 #define TIMER_IRQN	DT_INST_IRQN(0)
65 /* scr,machine-timer*/
66 #elif DT_HAS_COMPAT_STATUS_OKAY(scr_machine_timer)
67 #define DT_DRV_COMPAT scr_machine_timer
68 #define MTIMER_HAS_DIVIDER
69 
70 #define MTIMEDIV_REG	(DT_INST_REG_ADDR_U64(0) + 4)
71 #define MTIME_REG	(DT_INST_REG_ADDR_U64(0) + 8)
72 #define MTIMECMP_REG	(DT_INST_REG_ADDR_U64(0) + 16)
73 #define TIMER_IRQN	DT_INST_IRQN(0)
74 #endif
75 
76 #define CYC_PER_TICK (uint32_t)(sys_clock_hw_cycles_per_sec() \
77 				/ CONFIG_SYS_CLOCK_TICKS_PER_SEC)
78 
79 /* the unsigned long cast limits divisions to native CPU register width */
80 #define cycle_diff_t unsigned long
81 #define CYCLE_DIFF_MAX (~(cycle_diff_t)0)
82 
83 /*
84  * We have two constraints on the maximum number of cycles we can wait for.
85  *
86  * 1) sys_clock_announce() accepts at most INT32_MAX ticks.
87  *
88  * 2) The number of cycles between two reports must fit in a cycle_diff_t
89  *    variable before converting it to ticks.
90  *
91  * Then:
92  *
93  * 3) Pick the smallest between (1) and (2).
94  *
95  * 4) Take into account some room for the unavoidable IRQ servicing latency.
96  *    Let's use 3/4 of the max range.
97  *
98  * Finally let's add the LSB value to the result so to clear out a bunch of
99  * consecutive set bits coming from the original max values to produce a
100  * nicer literal for assembly generation.
101  */
102 #define CYCLES_MAX_1	((uint64_t)INT32_MAX * (uint64_t)CYC_PER_TICK)
103 #define CYCLES_MAX_2	((uint64_t)CYCLE_DIFF_MAX)
104 #define CYCLES_MAX_3	MIN(CYCLES_MAX_1, CYCLES_MAX_2)
105 #define CYCLES_MAX_4	(CYCLES_MAX_3 / 2 + CYCLES_MAX_3 / 4)
106 #define CYCLES_MAX	(CYCLES_MAX_4 + LSB_GET(CYCLES_MAX_4))
107 
108 static struct k_spinlock lock;
109 static uint64_t last_count;
110 static uint64_t last_ticks;
111 static uint32_t last_elapsed;
112 
113 #if defined(CONFIG_TEST)
114 const int32_t z_sys_timer_irq_for_test = TIMER_IRQN;
115 #endif
116 
get_hart_mtimecmp(void)117 static uintptr_t get_hart_mtimecmp(void)
118 {
119 	return MTIMECMP_REG + (arch_proc_id() * 8);
120 }
121 
set_mtimecmp(uint64_t time)122 static void set_mtimecmp(uint64_t time)
123 {
124 #ifdef CONFIG_64BIT
125 	*(volatile uint64_t *)get_hart_mtimecmp() = time;
126 #else
127 	volatile uint32_t *r = (uint32_t *)get_hart_mtimecmp();
128 
129 	/* Per spec, the RISC-V MTIME/MTIMECMP registers are 64 bit,
130 	 * but are NOT internally latched for multiword transfers.  So
131 	 * we have to be careful about sequencing to avoid triggering
132 	 * spurious interrupts: always set the high word to a max
133 	 * value first.
134 	 */
135 	r[1] = 0xffffffff;
136 	r[0] = (uint32_t)time;
137 	r[1] = (uint32_t)(time >> 32);
138 #endif
139 }
140 
set_divider(void)141 static void set_divider(void)
142 {
143 #ifdef MTIMER_HAS_DIVIDER
144 	*(volatile uint32_t *)MTIMEDIV_REG =
145 		CONFIG_RISCV_MACHINE_TIMER_SYSTEM_CLOCK_DIVIDER;
146 #endif
147 }
148 
mtime(void)149 static uint64_t mtime(void)
150 {
151 #ifdef CONFIG_64BIT
152 	return *(volatile uint64_t *)MTIME_REG;
153 #else
154 	volatile uint32_t *r = (uint32_t *)MTIME_REG;
155 	uint32_t lo, hi;
156 
157 	/* Likewise, must guard against rollover when reading */
158 	do {
159 		hi = r[1];
160 		lo = r[0];
161 	} while (r[1] != hi);
162 
163 	return (((uint64_t)hi) << 32) | lo;
164 #endif
165 }
166 
timer_isr(const void * arg)167 static void timer_isr(const void *arg)
168 {
169 	ARG_UNUSED(arg);
170 
171 	k_spinlock_key_t key = k_spin_lock(&lock);
172 
173 	uint64_t now = mtime();
174 	uint64_t dcycles = now - last_count;
175 	uint32_t dticks = (cycle_diff_t)dcycles / CYC_PER_TICK;
176 
177 	last_count += (cycle_diff_t)dticks * CYC_PER_TICK;
178 	last_ticks += dticks;
179 	last_elapsed = 0;
180 
181 	if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) {
182 		uint64_t next = last_count + CYC_PER_TICK;
183 
184 		set_mtimecmp(next);
185 	}
186 
187 	k_spin_unlock(&lock, key);
188 	sys_clock_announce(dticks);
189 }
190 
sys_clock_set_timeout(int32_t ticks,bool idle)191 void sys_clock_set_timeout(int32_t ticks, bool idle)
192 {
193 	ARG_UNUSED(idle);
194 
195 	if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) {
196 		return;
197 	}
198 
199 	k_spinlock_key_t key = k_spin_lock(&lock);
200 	uint64_t cyc;
201 
202 	if (ticks == K_TICKS_FOREVER) {
203 		cyc = last_count + CYCLES_MAX;
204 	} else {
205 		cyc = (last_ticks + last_elapsed + ticks) * CYC_PER_TICK;
206 		if ((cyc - last_count) > CYCLES_MAX) {
207 			cyc = last_count + CYCLES_MAX;
208 		}
209 	}
210 	set_mtimecmp(cyc);
211 
212 	k_spin_unlock(&lock, key);
213 }
214 
sys_clock_elapsed(void)215 uint32_t sys_clock_elapsed(void)
216 {
217 	if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) {
218 		return 0;
219 	}
220 
221 	k_spinlock_key_t key = k_spin_lock(&lock);
222 	uint64_t now = mtime();
223 	uint64_t dcycles = now - last_count;
224 	uint32_t dticks = (cycle_diff_t)dcycles / CYC_PER_TICK;
225 
226 	last_elapsed = dticks;
227 	k_spin_unlock(&lock, key);
228 	return dticks;
229 }
230 
sys_clock_cycle_get_32(void)231 uint32_t sys_clock_cycle_get_32(void)
232 {
233 	return ((uint32_t)mtime()) << CONFIG_RISCV_MACHINE_TIMER_SYSTEM_CLOCK_DIVIDER;
234 }
235 
sys_clock_cycle_get_64(void)236 uint64_t sys_clock_cycle_get_64(void)
237 {
238 	return mtime() << CONFIG_RISCV_MACHINE_TIMER_SYSTEM_CLOCK_DIVIDER;
239 }
240 
sys_clock_driver_init(void)241 static int sys_clock_driver_init(void)
242 {
243 
244 	set_divider();
245 
246 	IRQ_CONNECT(TIMER_IRQN, 0, timer_isr, NULL, 0);
247 	last_ticks = mtime() / CYC_PER_TICK;
248 	last_count = last_ticks * CYC_PER_TICK;
249 	set_mtimecmp(last_count + CYC_PER_TICK);
250 	irq_enable(TIMER_IRQN);
251 	return 0;
252 }
253 
254 #ifdef CONFIG_SMP
smp_timer_init(void)255 void smp_timer_init(void)
256 {
257 	set_mtimecmp(last_count + CYC_PER_TICK);
258 	irq_enable(TIMER_IRQN);
259 }
260 #endif
261 
262 SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2,
263 	 CONFIG_SYSTEM_CLOCK_INIT_PRIORITY);
264