Skip to content

Commit 5d98446

Browse files
avpatelpalmer-dabbelt
authored andcommitted
clocksource: timer-riscv: Don't enable/disable timer interrupt
Currently, we enable/disable timer interrupt at runtime to start/stop timer events. This makes timer interrupt state go out-of-sync with the Linux interrupt subsystem. To address the above issue, we can stop a per-HART timer interrupt by setting U64_MAX in timecmp CSR (or sbi_set_timer()) at the time of handling timer interrupt. Signed-off-by: Anup Patel <apatel@ventanamicro.com> Reviewed-by: Conor Dooley <conor.dooley@microchip.com> Acked-by: Palmer Dabbelt <palmer@rivosinc.com> Link: https://lore.kernel.org/r/20230710131902.1459180-2-apatel@ventanamicro.com Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
1 parent a9429d5 commit 5d98446

File tree

1 file changed

+13
-2
lines changed

1 file changed

+13
-2
lines changed

drivers/clocksource/timer-riscv.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <linux/io-64-nonatomic-lo-hi.h>
2323
#include <linux/interrupt.h>
2424
#include <linux/of_irq.h>
25+
#include <linux/limits.h>
2526
#include <clocksource/timer-riscv.h>
2627
#include <asm/smp.h>
2728
#include <asm/hwcap.h>
@@ -31,12 +32,22 @@
3132
static DEFINE_STATIC_KEY_FALSE(riscv_sstc_available);
3233
static bool riscv_timer_cannot_wake_cpu;
3334

35+
static void riscv_clock_event_stop(void)
36+
{
37+
if (static_branch_likely(&riscv_sstc_available)) {
38+
csr_write(CSR_STIMECMP, ULONG_MAX);
39+
if (IS_ENABLED(CONFIG_32BIT))
40+
csr_write(CSR_STIMECMPH, ULONG_MAX);
41+
} else {
42+
sbi_set_timer(U64_MAX);
43+
}
44+
}
45+
3446
static int riscv_clock_next_event(unsigned long delta,
3547
struct clock_event_device *ce)
3648
{
3749
u64 next_tval = get_cycles64() + delta;
3850

39-
csr_set(CSR_IE, IE_TIE);
4051
if (static_branch_likely(&riscv_sstc_available)) {
4152
#if defined(CONFIG_32BIT)
4253
csr_write(CSR_STIMECMP, next_tval & 0xFFFFFFFF);
@@ -119,7 +130,7 @@ static irqreturn_t riscv_timer_interrupt(int irq, void *dev_id)
119130
{
120131
struct clock_event_device *evdev = this_cpu_ptr(&riscv_clock_event);
121132

122-
csr_clear(CSR_IE, IE_TIE);
133+
riscv_clock_event_stop();
123134
evdev->event_handler(evdev);
124135

125136
return IRQ_HANDLED;

0 commit comments

Comments
 (0)