1 /* $NetBSD: clock.c,v 1.2 2024/01/08 05:11:32 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 2023 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * Copyright (c) 1992, 1993 34 * The Regents of the University of California. All rights reserved. 35 * 36 * This software was developed by the Computer Systems Engineering group 37 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 38 * contributed to Berkeley. 39 * 40 * All advertising materials mentioning features or use of this software 41 * must display the following acknowledgement: 42 * This product includes software developed by the University of 43 * California, Lawrence Berkeley Laboratory. 44 * 45 * Redistribution and use in source and binary forms, with or without 46 * modification, are permitted provided that the following conditions 47 * are met: 48 * 1. Redistributions of source code must retain the above copyright 49 * notice, this list of conditions and the following disclaimer. 50 * 2. Redistributions in binary form must reproduce the above copyright 51 * notice, this list of conditions and the following disclaimer in the 52 * documentation and/or other materials provided with the distribution. 53 * 3. Neither the name of the University nor the names of its contributors 54 * may be used to endorse or promote products derived from this software 55 * without specific prior written permission. 56 * 57 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 58 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 59 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 60 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 61 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 62 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 63 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 64 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 65 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 66 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 67 * SUCH DAMAGE. 68 * 69 * @(#)clock.c 8.1 (Berkeley) 6/11/93 70 */ 71 72 #include <sys/cdefs.h> 73 __KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.2 2024/01/08 05:11:32 thorpej Exp $"); 74 75 #include <sys/param.h> 76 #include <sys/kernel.h> 77 #include <sys/systm.h> 78 #include <sys/device.h> 79 80 #include <machine/clockvar.h> 81 #include <machine/psl.h> 82 #include <machine/bus.h> 83 84 static struct clock_vars { 85 struct clock_attach_args *args; 86 struct evcnt counter; 87 } virt68k_clocks[NCLOCKS]; 88 89 static struct clock_handlers { 90 const char *name; 91 void (*func)(struct clockframe *); 92 } virt68k_clock_handlers[] = { 93 [CLOCK_HARDCLOCK] = { .name = "hardclock", 94 .func = hardclock }, 95 [CLOCK_STATCLOCK] = { .name = "statclock", 96 .func = statclock }, 97 }; 98 99 void *clock_devices[NCLOCKS]; 100 101 /* 102 * Statistics clock interval and variance, in usec. Variance must be a 103 * power of two. Since this gives us an even number, not an odd number, 104 * we discard one case and compensate. That is, a variance of 1024 would 105 * give us offsets in [0..1023]. Instead, we take offsets in [1..1023]. 106 * This is symmetric about the point 512, or statvar/2, and thus averages 107 * to that value (assuming uniform random numbers). 108 */ 109 /* XXX fix comment to match value */ 110 int clock_statvar = 8192; 111 int clock_statmin; /* statclock interval - (1/2 * variance) */ 112 113 static void (*clock_delay_func)(device_t, unsigned int); 114 static device_t clock_delay_dev; 115 116 /* 117 * Common parts of clock autoconfiguration. 118 */ 119 void 120 clock_attach(device_t dev, struct clock_attach_args *ca, 121 void (*delay_func)(device_t, unsigned int)) 122 { 123 /* Hook up that which we need. */ 124 KASSERT(ca->ca_which >= 0); 125 KASSERT(ca->ca_which < NCLOCKS); 126 127 KASSERT(clock_devices[ca->ca_which] == NULL); 128 KASSERT(virt68k_clocks[ca->ca_which].args == NULL); 129 130 clock_devices[ca->ca_which] = ca->ca_arg; 131 virt68k_clocks[ca->ca_which].args = ca; 132 133 evcnt_attach_dynamic(&virt68k_clocks[ca->ca_which].counter, 134 EVCNT_TYPE_INTR, ca->ca_parent_evcnt, 135 device_xname(dev), virt68k_clock_handlers[ca->ca_which].name); 136 137 if (delay_func != NULL && clock_delay_dev == NULL) { 138 aprint_normal_dev(dev, "Using as delay() timer.\n"); 139 clock_delay_func = delay_func; 140 clock_delay_dev = dev; 141 } 142 } 143 144 void 145 delay(unsigned int usec) 146 { 147 if (clock_delay_func != NULL) { 148 (*clock_delay_func)(clock_delay_dev, usec); 149 } 150 } 151 152 const char * 153 clock_name(int which) 154 { 155 KASSERT(which >= 0); 156 KASSERT(which < NCLOCKS); 157 158 return virt68k_clock_handlers[which].name; 159 } 160 161 /* 162 * Set up the real-time and statistics clocks. Leave stathz 0 only 163 * if no alternative timer is available. 164 * 165 * The frequencies of these clocks must be an even number of microseconds. 166 */ 167 void 168 cpu_initclocks(void) 169 { 170 int i, statint = 0, minint = 0; 171 172 if (virt68k_clocks[CLOCK_HARDCLOCK].args == NULL) { 173 panic("Clock not configured"); 174 } 175 176 if (1000000 % hz) { 177 aprint_error("Cannot get %d Hz clock; using 100 Hz\n", hz); 178 hz = 100; 179 tick = 1000000 / hz; 180 } 181 182 if (virt68k_clocks[CLOCK_STATCLOCK].args == NULL) { 183 aprint_normal("No statclock; using hardclock.\n"); 184 stathz = 0; 185 statint = 0; 186 } else if (stathz == 0) { 187 stathz = hz; 188 if (1000000 % stathz) { 189 aprint_error("Cannot get %d Hz statclock; " 190 "using 100 Hz\n", stathz); 191 stathz = 100; 192 } 193 profhz = stathz; /* always */ 194 statint = 1000000 / stathz; 195 minint = statint / 2 + 100; 196 while (clock_statvar > minint) 197 clock_statvar >>= 1; 198 clock_statmin = statint - (clock_statvar >> 1); 199 } 200 201 for (i = 0; i < NCLOCKS; i++) { 202 struct clock_attach_args *ca = virt68k_clocks[i].args; 203 unsigned int freq, interval; 204 205 if (ca == NULL) { 206 continue; 207 } 208 switch (i) { 209 case CLOCK_HARDCLOCK: 210 freq = hz; 211 interval = tick; 212 break; 213 214 case CLOCK_STATCLOCK: 215 freq = stathz; 216 interval = statint; 217 break; 218 219 default: 220 KASSERT(0); 221 } 222 223 aprint_normal("Initialzing %s: freq=%u Hz, interval=%u usec\n", 224 clock_name(i), freq, interval); 225 ca->ca_initfunc(ca->ca_arg, interval, 226 &virt68k_clocks[i].counter, 227 virt68k_clock_handlers[i].func); 228 } 229 } 230 231 void 232 setstatclockrate(int newhz) 233 { 234 235 /* XXX should we do something here? XXX */ 236 } 237