root/src/system/kernel/arch/riscv64/arch_timer.cpp
/*
 * Copyright 2019-2021, Haiku Inc. All rights reserved.
 * Distributed under the terms of the MIT License.
 *
 * Authors:
 *              Adrien Destugues <pulkomandy@pulkomandy.tk>
 */


#include <arch_cpu_defs.h>
#include <arch_int.h>
#include <arch/timer.h>
#include <boot/kernel_args.h>
#include <debug.h>
#include <kernel.h>
#include <platform/sbi/sbi_syscalls.h>
#include <timer.h>
#include <Clint.h>

#include <smp.h>


extern uint32 gPlatform;

static uint64 sTimerConversionFactor;


void
arch_timer_set_hardware_timer(bigtime_t timeout)
{
/*
        dprintf("arch_timer_set_hardware_timer(%" B_PRIu64 "), cpu: %" B_PRId32 "\n", timeout,
                smp_get_current_cpu());
*/
        uint64 scaledTimeout = (static_cast<__uint128_t>(timeout) * sTimerConversionFactor) >> 32;

        SetBitsSie(1 << sTimerInt);

        switch (gPlatform) {
                case kPlatformMNative:
                        MSyscall(kMSyscallSetTimer, true, gClintRegs->mtime + scaledTimeout);
                        break;
                case kPlatformSbi: {
                        sbi_set_timer(CpuTime() + scaledTimeout);
                        break;
                }
                default:
                        ;
        }
}


void
arch_timer_clear_hardware_timer()
{
        ClearBitsSie(1 << sTimerInt);

        switch (gPlatform) {
                case kPlatformMNative:
                        MSyscall(kMSyscallSetTimer, false);
                        break;
                case kPlatformSbi: {
                        // Do nothing, it is not possible to clear SBI timer, so we only disable supervisor
                        // timer interrupt. SBI timer still can be triggered, but its interrupt will be not
                        // delivered to kernel.
                        break;
                }
                default:
                        ;
        }
}


int
arch_init_timer(kernel_args *args)
{
        sTimerConversionFactor = (1LL << 32) * args->arch_args.timerFrequency / 1000000LL;

        return B_OK;
}