1/*
2 * Copyright 2019-2021, Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Adrien Destugues <pulkomandy@pulkomandy.tk>
7 */
8
9
10#include <arch_cpu_defs.h>
11#include <arch_int.h>
12#include <arch/timer.h>
13#include <boot/kernel_args.h>
14#include <debug.h>
15#include <kernel.h>
16#include <platform/sbi/sbi_syscalls.h>
17#include <timer.h>
18#include <Clint.h>
19
20#include <smp.h>
21
22
23extern uint32 gPlatform;
24
25static uint64 sTimerConversionFactor;
26
27
28void
29arch_timer_set_hardware_timer(bigtime_t timeout)
30{
31/*
32	dprintf("arch_timer_set_hardware_timer(%" B_PRIu64 "), cpu: %" B_PRId32 "\n", timeout,
33		smp_get_current_cpu());
34*/
35	uint64 scaledTimeout = (static_cast<__uint128_t>(timeout) * sTimerConversionFactor) >> 32;
36
37	SetBitsSie(1 << sTimerInt);
38
39	switch (gPlatform) {
40		case kPlatformMNative:
41			MSyscall(kMSyscallSetTimer, true, gClintRegs->mtime + scaledTimeout);
42			break;
43		case kPlatformSbi: {
44			sbi_set_timer(CpuTime() + scaledTimeout);
45			break;
46		}
47		default:
48			;
49	}
50}
51
52
53void
54arch_timer_clear_hardware_timer()
55{
56	ClearBitsSie(1 << sTimerInt);
57
58	switch (gPlatform) {
59		case kPlatformMNative:
60			MSyscall(kMSyscallSetTimer, false);
61			break;
62		case kPlatformSbi: {
63			// Do nothing, it is not possible to clear SBI timer, so we only disable supervisor
64			// timer interrupt. SBI timer still can be triggered, but its interrupt will be not
65			// delivered to kernel.
66			break;
67		}
68		default:
69			;
70	}
71}
72
73
74int
75arch_init_timer(kernel_args *args)
76{
77	sTimerConversionFactor = (1LL << 32) * args->arch_args.timerFrequency / 1000000LL;
78
79	return B_OK;
80}
81