162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2012 Regents of the University of California 462306a36Sopenharmony_ci * Copyright (C) 2017 SiFive 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * All RISC-V systems have a timer attached to every hart. These timers can 762306a36Sopenharmony_ci * either be read from the "time" and "timeh" CSRs, and can use the SBI to 862306a36Sopenharmony_ci * setup events, or directly accessed using MMIO registers. 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#define pr_fmt(fmt) "riscv-timer: " fmt 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include <linux/acpi.h> 1462306a36Sopenharmony_ci#include <linux/clocksource.h> 1562306a36Sopenharmony_ci#include <linux/clockchips.h> 1662306a36Sopenharmony_ci#include <linux/cpu.h> 1762306a36Sopenharmony_ci#include <linux/delay.h> 1862306a36Sopenharmony_ci#include <linux/irq.h> 1962306a36Sopenharmony_ci#include <linux/irqdomain.h> 2062306a36Sopenharmony_ci#include <linux/module.h> 2162306a36Sopenharmony_ci#include <linux/sched_clock.h> 2262306a36Sopenharmony_ci#include <linux/io-64-nonatomic-lo-hi.h> 2362306a36Sopenharmony_ci#include <linux/interrupt.h> 2462306a36Sopenharmony_ci#include <linux/of_irq.h> 2562306a36Sopenharmony_ci#include <clocksource/timer-riscv.h> 2662306a36Sopenharmony_ci#include <asm/smp.h> 2762306a36Sopenharmony_ci#include <asm/hwcap.h> 2862306a36Sopenharmony_ci#include <asm/sbi.h> 2962306a36Sopenharmony_ci#include <asm/timex.h> 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_cistatic DEFINE_STATIC_KEY_FALSE(riscv_sstc_available); 3262306a36Sopenharmony_cistatic bool riscv_timer_cannot_wake_cpu; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cistatic int riscv_clock_next_event(unsigned long delta, 3562306a36Sopenharmony_ci struct clock_event_device *ce) 3662306a36Sopenharmony_ci{ 3762306a36Sopenharmony_ci u64 next_tval = get_cycles64() + delta; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci csr_set(CSR_IE, IE_TIE); 4062306a36Sopenharmony_ci if (static_branch_likely(&riscv_sstc_available)) { 4162306a36Sopenharmony_ci#if defined(CONFIG_32BIT) 4262306a36Sopenharmony_ci csr_write(CSR_STIMECMP, next_tval & 0xFFFFFFFF); 4362306a36Sopenharmony_ci csr_write(CSR_STIMECMPH, next_tval >> 32); 4462306a36Sopenharmony_ci#else 4562306a36Sopenharmony_ci csr_write(CSR_STIMECMP, next_tval); 4662306a36Sopenharmony_ci#endif 4762306a36Sopenharmony_ci } else 4862306a36Sopenharmony_ci sbi_set_timer(next_tval); 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci return 0; 5162306a36Sopenharmony_ci} 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_cistatic unsigned int riscv_clock_event_irq; 5462306a36Sopenharmony_cistatic DEFINE_PER_CPU(struct clock_event_device, riscv_clock_event) = { 5562306a36Sopenharmony_ci .name = "riscv_timer_clockevent", 5662306a36Sopenharmony_ci .features = CLOCK_EVT_FEAT_ONESHOT, 5762306a36Sopenharmony_ci .rating = 100, 5862306a36Sopenharmony_ci .set_next_event = riscv_clock_next_event, 5962306a36Sopenharmony_ci}; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci/* 6262306a36Sopenharmony_ci * It is guaranteed that all the timers across all the harts are synchronized 6362306a36Sopenharmony_ci * within one tick of each other, so while this could technically go 6462306a36Sopenharmony_ci * backwards when hopping between CPUs, practically it won't happen. 6562306a36Sopenharmony_ci */ 6662306a36Sopenharmony_cistatic unsigned long long riscv_clocksource_rdtime(struct clocksource *cs) 6762306a36Sopenharmony_ci{ 6862306a36Sopenharmony_ci return get_cycles64(); 6962306a36Sopenharmony_ci} 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_cistatic u64 notrace riscv_sched_clock(void) 7262306a36Sopenharmony_ci{ 7362306a36Sopenharmony_ci return get_cycles64(); 7462306a36Sopenharmony_ci} 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_cistatic struct clocksource riscv_clocksource = { 7762306a36Sopenharmony_ci .name = "riscv_clocksource", 7862306a36Sopenharmony_ci .rating = 400, 7962306a36Sopenharmony_ci .mask = CLOCKSOURCE_MASK(64), 8062306a36Sopenharmony_ci .flags = CLOCK_SOURCE_IS_CONTINUOUS, 8162306a36Sopenharmony_ci .read = riscv_clocksource_rdtime, 8262306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_GENERIC_GETTIMEOFDAY) 8362306a36Sopenharmony_ci .vdso_clock_mode = VDSO_CLOCKMODE_ARCHTIMER, 8462306a36Sopenharmony_ci#else 8562306a36Sopenharmony_ci .vdso_clock_mode = VDSO_CLOCKMODE_NONE, 8662306a36Sopenharmony_ci#endif 8762306a36Sopenharmony_ci}; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_cistatic int riscv_timer_starting_cpu(unsigned int cpu) 9062306a36Sopenharmony_ci{ 9162306a36Sopenharmony_ci struct clock_event_device *ce = per_cpu_ptr(&riscv_clock_event, cpu); 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci ce->cpumask = cpumask_of(cpu); 9462306a36Sopenharmony_ci ce->irq = riscv_clock_event_irq; 9562306a36Sopenharmony_ci if (riscv_timer_cannot_wake_cpu) 9662306a36Sopenharmony_ci ce->features |= CLOCK_EVT_FEAT_C3STOP; 9762306a36Sopenharmony_ci clockevents_config_and_register(ce, riscv_timebase, 100, 0x7fffffff); 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci enable_percpu_irq(riscv_clock_event_irq, 10062306a36Sopenharmony_ci irq_get_trigger_type(riscv_clock_event_irq)); 10162306a36Sopenharmony_ci return 0; 10262306a36Sopenharmony_ci} 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_cistatic int riscv_timer_dying_cpu(unsigned int cpu) 10562306a36Sopenharmony_ci{ 10662306a36Sopenharmony_ci disable_percpu_irq(riscv_clock_event_irq); 10762306a36Sopenharmony_ci return 0; 10862306a36Sopenharmony_ci} 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_civoid riscv_cs_get_mult_shift(u32 *mult, u32 *shift) 11162306a36Sopenharmony_ci{ 11262306a36Sopenharmony_ci *mult = riscv_clocksource.mult; 11362306a36Sopenharmony_ci *shift = riscv_clocksource.shift; 11462306a36Sopenharmony_ci} 11562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(riscv_cs_get_mult_shift); 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci/* called directly from the low-level interrupt handler */ 11862306a36Sopenharmony_cistatic irqreturn_t riscv_timer_interrupt(int irq, void *dev_id) 11962306a36Sopenharmony_ci{ 12062306a36Sopenharmony_ci struct clock_event_device *evdev = this_cpu_ptr(&riscv_clock_event); 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci csr_clear(CSR_IE, IE_TIE); 12362306a36Sopenharmony_ci evdev->event_handler(evdev); 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci return IRQ_HANDLED; 12662306a36Sopenharmony_ci} 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_cistatic int __init riscv_timer_init_common(void) 12962306a36Sopenharmony_ci{ 13062306a36Sopenharmony_ci int error; 13162306a36Sopenharmony_ci struct irq_domain *domain; 13262306a36Sopenharmony_ci struct fwnode_handle *intc_fwnode = riscv_get_intc_hwnode(); 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci domain = irq_find_matching_fwnode(intc_fwnode, DOMAIN_BUS_ANY); 13562306a36Sopenharmony_ci if (!domain) { 13662306a36Sopenharmony_ci pr_err("Failed to find irq_domain for INTC node [%pfwP]\n", 13762306a36Sopenharmony_ci intc_fwnode); 13862306a36Sopenharmony_ci return -ENODEV; 13962306a36Sopenharmony_ci } 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci riscv_clock_event_irq = irq_create_mapping(domain, RV_IRQ_TIMER); 14262306a36Sopenharmony_ci if (!riscv_clock_event_irq) { 14362306a36Sopenharmony_ci pr_err("Failed to map timer interrupt for node [%pfwP]\n", intc_fwnode); 14462306a36Sopenharmony_ci return -ENODEV; 14562306a36Sopenharmony_ci } 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci error = clocksource_register_hz(&riscv_clocksource, riscv_timebase); 14862306a36Sopenharmony_ci if (error) { 14962306a36Sopenharmony_ci pr_err("RISCV timer registration failed [%d]\n", error); 15062306a36Sopenharmony_ci return error; 15162306a36Sopenharmony_ci } 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci sched_clock_register(riscv_sched_clock, 64, riscv_timebase); 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci error = request_percpu_irq(riscv_clock_event_irq, 15662306a36Sopenharmony_ci riscv_timer_interrupt, 15762306a36Sopenharmony_ci "riscv-timer", &riscv_clock_event); 15862306a36Sopenharmony_ci if (error) { 15962306a36Sopenharmony_ci pr_err("registering percpu irq failed [%d]\n", error); 16062306a36Sopenharmony_ci return error; 16162306a36Sopenharmony_ci } 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci if (riscv_isa_extension_available(NULL, SSTC)) { 16462306a36Sopenharmony_ci pr_info("Timer interrupt in S-mode is available via sstc extension\n"); 16562306a36Sopenharmony_ci static_branch_enable(&riscv_sstc_available); 16662306a36Sopenharmony_ci } 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci error = cpuhp_setup_state(CPUHP_AP_RISCV_TIMER_STARTING, 16962306a36Sopenharmony_ci "clockevents/riscv/timer:starting", 17062306a36Sopenharmony_ci riscv_timer_starting_cpu, riscv_timer_dying_cpu); 17162306a36Sopenharmony_ci if (error) 17262306a36Sopenharmony_ci pr_err("cpu hp setup state failed for RISCV timer [%d]\n", 17362306a36Sopenharmony_ci error); 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci return error; 17662306a36Sopenharmony_ci} 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_cistatic int __init riscv_timer_init_dt(struct device_node *n) 17962306a36Sopenharmony_ci{ 18062306a36Sopenharmony_ci int cpuid, error; 18162306a36Sopenharmony_ci unsigned long hartid; 18262306a36Sopenharmony_ci struct device_node *child; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci error = riscv_of_processor_hartid(n, &hartid); 18562306a36Sopenharmony_ci if (error < 0) { 18662306a36Sopenharmony_ci pr_warn("Invalid hartid for node [%pOF] error = [%lu]\n", 18762306a36Sopenharmony_ci n, hartid); 18862306a36Sopenharmony_ci return error; 18962306a36Sopenharmony_ci } 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci cpuid = riscv_hartid_to_cpuid(hartid); 19262306a36Sopenharmony_ci if (cpuid < 0) { 19362306a36Sopenharmony_ci pr_warn("Invalid cpuid for hartid [%lu]\n", hartid); 19462306a36Sopenharmony_ci return cpuid; 19562306a36Sopenharmony_ci } 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci if (cpuid != smp_processor_id()) 19862306a36Sopenharmony_ci return 0; 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci child = of_find_compatible_node(NULL, NULL, "riscv,timer"); 20162306a36Sopenharmony_ci if (child) { 20262306a36Sopenharmony_ci riscv_timer_cannot_wake_cpu = of_property_read_bool(child, 20362306a36Sopenharmony_ci "riscv,timer-cannot-wake-cpu"); 20462306a36Sopenharmony_ci of_node_put(child); 20562306a36Sopenharmony_ci } 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci return riscv_timer_init_common(); 20862306a36Sopenharmony_ci} 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ciTIMER_OF_DECLARE(riscv_timer, "riscv", riscv_timer_init_dt); 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci#ifdef CONFIG_ACPI 21362306a36Sopenharmony_cistatic int __init riscv_timer_acpi_init(struct acpi_table_header *table) 21462306a36Sopenharmony_ci{ 21562306a36Sopenharmony_ci return riscv_timer_init_common(); 21662306a36Sopenharmony_ci} 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ciTIMER_ACPI_DECLARE(aclint_mtimer, ACPI_SIG_RHCT, riscv_timer_acpi_init); 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci#endif 221