diff options
Diffstat (limited to 'drivers/clocksource/timer-riscv.c')
-rw-r--r-- | drivers/clocksource/timer-riscv.c | 23 |
1 files changed, 20 insertions, 3 deletions
diff --git a/drivers/clocksource/timer-riscv.c b/drivers/clocksource/timer-riscv.c index da3071b387..57857c0dfb 100644 --- a/drivers/clocksource/timer-riscv.c +++ b/drivers/clocksource/timer-riscv.c @@ -22,21 +22,32 @@ #include <linux/io-64-nonatomic-lo-hi.h> #include <linux/interrupt.h> #include <linux/of_irq.h> +#include <linux/limits.h> #include <clocksource/timer-riscv.h> #include <asm/smp.h> -#include <asm/hwcap.h> +#include <asm/cpufeature.h> #include <asm/sbi.h> #include <asm/timex.h> static DEFINE_STATIC_KEY_FALSE(riscv_sstc_available); static bool riscv_timer_cannot_wake_cpu; +static void riscv_clock_event_stop(void) +{ + if (static_branch_likely(&riscv_sstc_available)) { + csr_write(CSR_STIMECMP, ULONG_MAX); + if (IS_ENABLED(CONFIG_32BIT)) + csr_write(CSR_STIMECMPH, ULONG_MAX); + } else { + sbi_set_timer(U64_MAX); + } +} + static int riscv_clock_next_event(unsigned long delta, struct clock_event_device *ce) { u64 next_tval = get_cycles64() + delta; - csr_set(CSR_IE, IE_TIE); if (static_branch_likely(&riscv_sstc_available)) { #if defined(CONFIG_32BIT) csr_write(CSR_STIMECMP, next_tval & 0xFFFFFFFF); @@ -94,6 +105,8 @@ static int riscv_timer_starting_cpu(unsigned int cpu) ce->irq = riscv_clock_event_irq; if (riscv_timer_cannot_wake_cpu) ce->features |= CLOCK_EVT_FEAT_C3STOP; + if (static_branch_likely(&riscv_sstc_available)) + ce->rating = 450; clockevents_config_and_register(ce, riscv_timebase, 100, 0x7fffffff); enable_percpu_irq(riscv_clock_event_irq, @@ -119,7 +132,7 @@ static irqreturn_t riscv_timer_interrupt(int irq, void *dev_id) { struct clock_event_device *evdev = this_cpu_ptr(&riscv_clock_event); - csr_clear(CSR_IE, IE_TIE); + riscv_clock_event_stop(); evdev->event_handler(evdev); return IRQ_HANDLED; @@ -212,6 +225,10 @@ TIMER_OF_DECLARE(riscv_timer, "riscv", riscv_timer_init_dt); #ifdef CONFIG_ACPI static int __init riscv_timer_acpi_init(struct acpi_table_header *table) { + struct acpi_table_rhct *rhct = (struct acpi_table_rhct *)table; + + riscv_timer_cannot_wake_cpu = rhct->flags & ACPI_RHCT_TIMER_CANNOT_WAKEUP_CPU; + return riscv_timer_init_common(); } |