summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Qin <richard.qin.x@gmail.com>2026-05-13 16:18:15 +0800
committerRichard Qin <richard.qin.x@gmail.com>2026-05-13 16:18:15 +0800
commit0d572ed18a504ccf7e0046d948f78451edc22df5 (patch)
tree5430984a471a1d5f6c8eedd29426ac37204f5e90
parent9ffa213782210094ab639c956af868c4d1a05ed5 (diff)
downloadlume-0d572ed18a504ccf7e0046d948f78451edc22df5.tar.gz
lume-0d572ed18a504ccf7e0046d948f78451edc22df5.tar.xz
feat: implement MI Timer Subsystem with initialization and tick handling
-rw-r--r--na/include/lume/timer.h24
-rw-r--r--na/kernel/timer.cc44
2 files changed, 68 insertions, 0 deletions
diff --git a/na/include/lume/timer.h b/na/include/lume/timer.h
new file mode 100644
index 0000000..e7de2f1
--- /dev/null
+++ b/na/include/lume/timer.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* Copyright (C) 2026 Richard Qin */
+
+#pragma once
+
+#include <lume/types.h>
+
+/*
+ * MI Timer Subsystem
+ */
+
+extern uint64 g_jiffies;
+
+// BSP global initialization
+void timer_init();
+
+// AP per-CPU initialization
+void timer_init_ap();
+
+// Handle timer interrupt tick (called from TrapHandler)
+void timer_tick();
+
+// Get configured timebase frequency
+uint64 timer_get_freq();
diff --git a/na/kernel/timer.cc b/na/kernel/timer.cc
new file mode 100644
index 0000000..01e8f9d
--- /dev/null
+++ b/na/kernel/timer.cc
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* Copyright (C) 2026 Richard Qin */
+
+#include <lume/timer.h>
+#include <lume/fdt.h>
+#include <lume/sched.h>
+#include <arch/cpu.h>
+#include <arch/sbi.h>
+
+uint64 g_jiffies = 0;
+static uint64 g_timer_freq = 10000000;
+static uint64 g_tick_interval = 0;
+
+static void timer_set_next() {
+ arch::sbi::set_timer(arch::cpu::read_time() + g_tick_interval);
+}
+
+void timer_init() {
+ DeviceNode* cpus = fdt_get_node_by_path("/cpus");
+ if (cpus) {
+ g_timer_freq = cpus->get_prop_u32("timebase-frequency", g_timer_freq);
+ }
+
+ // Default 100 Hz (10ms per tick)
+ g_tick_interval = g_timer_freq / 100;
+
+ timer_set_next();
+ arch::cpu::timer_intr_on();
+}
+
+void timer_init_ap() {
+ timer_set_next();
+ arch::cpu::timer_intr_on();
+}
+
+void timer_tick() {
+ g_jiffies++;
+ timer_set_next();
+ sched_tick();
+}
+
+uint64 timer_get_freq() {
+ return g_timer_freq;
+}