Files
lk/arch/riscv/time.c
Elliot Berman e50d7db612 [arch][riscv] Add support for running in supervisor mode
Add support for running LK in supervisor mode or machine mode.
- Macro-ify CSR access to use correct CSR # or use SBI call as req'd
- Add support to make SBI calls
- Split CLINT and lk timer abstraction so that RISC-V timer can use SBI
  as required.
- Add support for booting other harts as primary since hart0 on U540
  does not support S-mode. A map is used to get LK cpu number from
  hartid.
2020-01-16 23:06:28 -08:00

73 lines
1.7 KiB
C

/*
* Copyright (c) 2018 Travis Geiselbrecht
*
* Use of this source code is governed by a MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT
*/
#include <lk/reg.h>
#include <lk/debug.h>
#include <lk/trace.h>
#include <lk/err.h>
#include <lk/trace.h>
#include <arch/riscv.h>
#include <arch/ops.h>
#include <platform.h>
#include <platform/timer.h>
#define LOCAL_TRACE 0
static platform_timer_callback timer_cb;
static void *timer_arg;
status_t platform_set_oneshot_timer (platform_timer_callback callback, void *arg, lk_time_t interval) {
LTRACEF("cb %p, arg %p, interval %u\n", callback, arg, interval);
// disable timer
riscv_csr_clear(RISCV_CSR_XIE, RISCV_CSR_XIE_TIE);
timer_cb = callback;
timer_arg = arg;
// enable the timer
riscv_csr_set(RISCV_CSR_XIE, RISCV_CSR_XIE_TIE);
// convert interval to ticks
uint64_t ticks = riscv_get_time() + ((interval * ARCH_RISCV_MTIME_RATE) / 1000u);
#if RISCV_M_MODE
extern void clint_set_timer(uint64_t ticks);
clint_set_timer(ticks);
#elif RISCV_S_MODE
sbi_set_timer(ticks);
#endif
return NO_ERROR;
}
lk_bigtime_t current_time_hires(void) {
return riscv_get_time() / (ARCH_RISCV_MTIME_RATE / 1000000u);
}
lk_time_t current_time(void) {
return riscv_get_time() / (ARCH_RISCV_MTIME_RATE / 1000u);
}
void platform_stop_timer(void) {
riscv_csr_clear(RISCV_CSR_XIE, RISCV_CSR_XIE_TIE);
}
enum handler_return riscv_timer_exception(void) {
LTRACEF("tick\n");
riscv_csr_clear(RISCV_CSR_XIE, RISCV_CSR_XIE_TIE);
enum handler_return ret = INT_NO_RESCHEDULE;
if (timer_cb) {
ret = timer_cb(timer_arg, current_time());
}
return ret;
}