aboutsummaryrefslogtreecommitdiff
path: root/arch/riscv64
diff options
context:
space:
mode:
Diffstat (limited to 'arch/riscv64')
-rw-r--r--arch/riscv64/include/csr.h4
-rw-r--r--arch/riscv64/kernel/timer.c35
2 files changed, 34 insertions, 5 deletions
diff --git a/arch/riscv64/include/csr.h b/arch/riscv64/include/csr.h
index 39e8dc9..ae0763b 100644
--- a/arch/riscv64/include/csr.h
+++ b/arch/riscv64/include/csr.h
@@ -5,6 +5,10 @@
#define SATP_MODE_Sv39 0x8000000000000000
#define SATP_MODE_Sv48 0x9000000000000000
+/* unprivileged CSR registers */
+#define CSR_TIME 0xc01
+#define CSR_TIMEH 0xc81
+
/* supervisor CSR registers */
#define CSR_SSTATUS 0x100
#define CSR_SIE 0x104
diff --git a/arch/riscv64/kernel/timer.c b/arch/riscv64/kernel/timer.c
index 02f080c..1f79c5b 100644
--- a/arch/riscv64/kernel/timer.c
+++ b/arch/riscv64/kernel/timer.c
@@ -1,20 +1,45 @@
#include <arch/timer.h>
+#include <libfdt.h>
+#include <csr.h>
#include <sbi.h>
ticks_t stat_timer(const void *fdt)
{
- /* TODO: read from fdt */
- return 0;
+ int cpu_offset = fdt_path_offset(fdt, "/cpus");
+ uint8_t *tf_reg = (uint8_t *)fdt_getprop(fdt, cpu_offset,
+ "timebase-frequency", NULL);
+ return (ticks_t)fdt_load_int32_ptr(tf_reg);
}
void set_timer(ticks_t ticks)
{
- /* TODO */
sbi_set_timer(ticks);
}
+#if __riscv_xlen == 64
+static ticks_t get_ticks64()
+{
+ ticks_t ticks = 0;
+ csr_read(CSR_TIME, ticks);
+ return ticks;
+}
+#else
+static ticks_t get_ticks64()
+{
+ ticks_t ticksh, ticksl, check;
+
+ /* avoid overflow between reading high and low */
+ do {
+ csr_read(CSR_TIMEH, ticksh);
+ csr_read(CSR_TIME, ticksl);
+ csr_read(CSR_TIMEH, check);
+ } while (ticksh != check);
+
+ return (ticksh << 32) | ticksl;
+}
+#endif
+
ticks_t current_ticks()
{
- /* TODO */
- return 0;
+ return get_ticks64();
}