1 1.9 skrll /* $NetBSD: clock_machdep.c,v 1.9 2024/08/04 08:16:25 skrll Exp $ */ 2 1.3 skrll 3 1.1 matt /*- 4 1.1 matt * Copyright (c) 2014 The NetBSD Foundation, Inc. 5 1.1 matt * All rights reserved. 6 1.1 matt * 7 1.1 matt * This code is derived from software contributed to The NetBSD Foundation 8 1.1 matt * by Matt Thomas of 3am Software Foundry. 9 1.1 matt * 10 1.1 matt * Redistribution and use in source and binary forms, with or without 11 1.1 matt * modification, are permitted provided that the following conditions 12 1.1 matt * are met: 13 1.1 matt * 1. Redistributions of source code must retain the above copyright 14 1.1 matt * notice, this list of conditions and the following disclaimer. 15 1.1 matt * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 matt * notice, this list of conditions and the following disclaimer in the 17 1.1 matt * documentation and/or other materials provided with the distribution. 18 1.1 matt * 19 1.1 matt * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 matt * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 matt * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 matt * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 matt * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 matt * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 matt * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 matt * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 matt * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 matt * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 matt * POSSIBILITY OF SUCH DAMAGE. 30 1.1 matt */ 31 1.1 matt 32 1.1 matt #include <sys/cdefs.h> 33 1.1 matt 34 1.9 skrll __RCSID("$NetBSD: clock_machdep.c,v 1.9 2024/08/04 08:16:25 skrll Exp $"); 35 1.1 matt 36 1.1 matt #include <sys/param.h> 37 1.4 skrll #include <sys/cpu.h> 38 1.6 skrll #include <sys/device.h> 39 1.1 matt #include <sys/systm.h> 40 1.4 skrll #include <sys/timetc.h> 41 1.4 skrll 42 1.4 skrll #include <machine/machdep.h> 43 1.4 skrll #include <machine/sbi.h> 44 1.4 skrll #include <machine/sysreg.h> 45 1.4 skrll 46 1.4 skrll static void (*_riscv_timer_init)(void) = riscv_timer_init; 47 1.4 skrll 48 1.4 skrll static uint32_t timer_frequency; 49 1.4 skrll static uint32_t timer_ticks_per_hz; 50 1.7 skrll static uint32_t timer_ticks_per_usec; 51 1.4 skrll 52 1.4 skrll static u_int 53 1.4 skrll timer_get_timecount(struct timecounter *tc) 54 1.4 skrll { 55 1.4 skrll return csr_time_read(); 56 1.4 skrll } 57 1.4 skrll 58 1.4 skrll static struct timecounter tc = { 59 1.4 skrll .tc_get_timecount = timer_get_timecount, 60 1.4 skrll .tc_counter_mask = ~0u, 61 1.4 skrll .tc_name = "riscv", 62 1.4 skrll .tc_quality = 100, 63 1.4 skrll }; 64 1.4 skrll 65 1.4 skrll 66 1.4 skrll void 67 1.4 skrll riscv_timer_frequency_set(uint32_t freq) 68 1.4 skrll { 69 1.4 skrll timer_frequency = freq; 70 1.4 skrll timer_ticks_per_hz = freq / hz; 71 1.7 skrll timer_ticks_per_usec = freq / 1000000; 72 1.4 skrll } 73 1.4 skrll 74 1.5 skrll uint32_t 75 1.5 skrll riscv_timer_frequency_get(void) 76 1.5 skrll { 77 1.5 skrll return timer_frequency; 78 1.5 skrll } 79 1.4 skrll 80 1.4 skrll void 81 1.4 skrll riscv_timer_register(void (*timerfn)(void)) 82 1.4 skrll { 83 1.9 skrll if (_riscv_timer_init != NULL) { 84 1.4 skrll #ifdef DIAGNOSTIC 85 1.9 skrll aprint_verbose("%s: timer already registered\n", __func__); 86 1.4 skrll #endif 87 1.9 skrll } 88 1.4 skrll _riscv_timer_init = timerfn; 89 1.4 skrll } 90 1.4 skrll 91 1.5 skrll void 92 1.4 skrll riscv_timer_init(void) 93 1.4 skrll { 94 1.4 skrll struct cpu_info * const ci = curcpu(); 95 1.4 skrll 96 1.6 skrll evcnt_attach_dynamic(&ci->ci_ev_timer, EVCNT_TYPE_INTR, 97 1.6 skrll NULL, device_xname(ci->ci_dev), "timer"); 98 1.6 skrll 99 1.4 skrll ci->ci_lastintr = csr_time_read(); 100 1.5 skrll uint64_t next = ci->ci_lastintr + timer_ticks_per_hz; 101 1.4 skrll ci->ci_lastintr_scheduled = next; 102 1.4 skrll 103 1.4 skrll sbi_set_timer(next); /* schedule next timer interrupt */ 104 1.4 skrll csr_sie_set(SIE_STIE); /* enable supervisor timer intr */ 105 1.4 skrll 106 1.5 skrll if (cpu_index(ci) == 0) { 107 1.5 skrll tc.tc_frequency = timer_frequency; 108 1.5 skrll tc_init(&tc); 109 1.5 skrll } 110 1.4 skrll } 111 1.4 skrll 112 1.4 skrll 113 1.4 skrll int 114 1.4 skrll riscv_timer_intr(void *arg) 115 1.4 skrll { 116 1.4 skrll struct cpu_info * const ci = curcpu(); 117 1.4 skrll struct clockframe * const cf = arg; 118 1.4 skrll 119 1.4 skrll csr_sip_clear(SIP_STIP); /* clean pending interrupt status */ 120 1.4 skrll 121 1.4 skrll const uint64_t now = csr_time_read(); 122 1.4 skrll 123 1.4 skrll ci->ci_lastintr = now; 124 1.4 skrll ci->ci_ev_timer.ev_count++; 125 1.4 skrll 126 1.4 skrll ci->ci_lastintr_scheduled += timer_ticks_per_hz; 127 1.8 riastrad while (__predict_false(ci->ci_lastintr_scheduled < now)) { 128 1.8 riastrad ci->ci_lastintr_scheduled += timer_ticks_per_hz; 129 1.8 riastrad /* XXX count missed timer interrupts */ 130 1.8 riastrad } 131 1.4 skrll sbi_set_timer(ci->ci_lastintr_scheduled); 132 1.4 skrll 133 1.4 skrll hardclock(cf); 134 1.4 skrll 135 1.4 skrll return 1; 136 1.4 skrll } 137 1.4 skrll 138 1.1 matt 139 1.1 matt void 140 1.1 matt cpu_initclocks(void) 141 1.1 matt { 142 1.4 skrll if (_riscv_timer_init == NULL) 143 1.4 skrll panic("cpu_initclocks: no timer registered"); 144 1.4 skrll _riscv_timer_init(); 145 1.1 matt } 146 1.1 matt 147 1.4 skrll 148 1.1 matt void 149 1.2 skrll setstatclockrate(int newhz) 150 1.1 matt { 151 1.1 matt } 152 1.7 skrll 153 1.7 skrll void 154 1.7 skrll delay(unsigned long us) 155 1.7 skrll { 156 1.9 skrll const uint64_t ticks = (uint64_t)us * timer_ticks_per_usec; 157 1.9 skrll const uint64_t finish = csr_time_read() + ticks; 158 1.7 skrll 159 1.9 skrll while (csr_time_read() < finish) { 160 1.9 skrll /* spin, baby spin */ 161 1.9 skrll } 162 1.7 skrll } 163