diff options
Diffstat (limited to 'drivers/clocksource')
-rw-r--r-- | drivers/clocksource/timer-riscv.c | 23 |
1 files changed, 19 insertions, 4 deletions
diff --git a/drivers/clocksource/timer-riscv.c b/drivers/clocksource/timer-riscv.c index d083bfb535f6..4e54856ce2a5 100644 --- a/drivers/clocksource/timer-riscv.c +++ b/drivers/clocksource/timer-riscv.c @@ -3,9 +3,9 @@ * Copyright (C) 2012 Regents of the University of California * Copyright (C) 2017 SiFive * - * All RISC-V systems have a timer attached to every hart. These timers can be - * read from the "time" and "timeh" CSRs, and can use the SBI to setup - * events. + * All RISC-V systems have a timer attached to every hart. These timers can + * either be read from the "time" and "timeh" CSRs, and can use the SBI to + * setup events, or directly accessed using MMIO registers. */ #include <linux/clocksource.h> #include <linux/clockchips.h> @@ -13,14 +13,29 @@ #include <linux/delay.h> #include <linux/irq.h> #include <linux/sched_clock.h> +#include <linux/io-64-nonatomic-lo-hi.h> #include <asm/smp.h> #include <asm/sbi.h> +u64 __iomem *riscv_time_cmp; +u64 __iomem *riscv_time_val; + +static inline void mmio_set_timer(u64 val) +{ + void __iomem *r; + + r = riscv_time_cmp + cpuid_to_hartid_map(smp_processor_id()); + writeq_relaxed(val, r); +} + static int riscv_clock_next_event(unsigned long delta, struct clock_event_device *ce) { csr_set(CSR_IE, IE_TIE); - sbi_set_timer(get_cycles64() + delta); + if (IS_ENABLED(CONFIG_RISCV_SBI)) + sbi_set_timer(get_cycles64() + delta); + else + mmio_set_timer(get_cycles64() + delta); return 0; } |