1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2024, James Raphael Tiovalen <jamestiotio@gmail.com> 4 */ 5 #include <libcflat.h> 6 #include <devicetree.h> 7 #include <limits.h> 8 #include <asm/csr.h> 9 #include <asm/delay.h> 10 #include <asm/isa.h> 11 #include <asm/sbi.h> 12 #include <asm/setup.h> 13 #include <asm/smp.h> 14 #include <asm/timer.h> 15 16 void timer_get_frequency(void) 17 { 18 const struct fdt_property *prop; 19 u32 *data; 20 int cpus, len; 21 22 assert_msg(dt_available(), "ACPI not yet supported"); 23 24 const void *fdt = dt_fdt(); 25 26 cpus = fdt_path_offset(fdt, "/cpus"); 27 assert(cpus >= 0); 28 29 prop = fdt_get_property(fdt, cpus, "timebase-frequency", &len); 30 assert(prop != NULL && len == 4); 31 32 data = (u32 *)prop->data; 33 timebase_frequency = fdt32_to_cpu(*data); 34 } 35 36 void timer_start(unsigned long duration_us) 37 { 38 uint64_t next = timer_get_cycles() + usec_to_cycles((uint64_t)duration_us); 39 40 if (cpu_has_extension(smp_processor_id(), ISA_SSTC)) { 41 csr_write(CSR_STIMECMP, (unsigned long)next); 42 if (__riscv_xlen == 32) 43 csr_write(CSR_STIMECMPH, (unsigned long)(next >> 32)); 44 } else if (sbi_probe(SBI_EXT_TIME)) { 45 struct sbiret ret = sbi_set_timer(next); 46 assert(ret.error == SBI_SUCCESS); 47 assert(!(next >> 32)); 48 } else { 49 assert_msg(false, "No timer to start!"); 50 } 51 } 52 53 void timer_stop(void) 54 { 55 if (cpu_has_extension(smp_processor_id(), ISA_SSTC)) { 56 /* 57 * Subtract one from ULONG_MAX to workaround QEMU using that 58 * exact number to decide *not* to update the timer. IOW, if 59 * we used ULONG_MAX, then we wouldn't stop the timer at all, 60 * but one less is still a big number ("infinity") and it gets 61 * QEMU to do what we want. 62 */ 63 csr_write(CSR_STIMECMP, ULONG_MAX - 1); 64 if (__riscv_xlen == 32) 65 csr_write(CSR_STIMECMPH, ULONG_MAX - 1); 66 } else if (sbi_probe(SBI_EXT_TIME)) { 67 struct sbiret ret = sbi_set_timer(ULONG_MAX); 68 assert(ret.error == SBI_SUCCESS); 69 } else { 70 assert_msg(false, "No timer to stop!"); 71 } 72 } 73