1 /* $NetBSD: timer.c,v 1.34 2018/01/12 09:47:44 mrg Exp $ */ 2 3 /* 4 * Copyright (c) 1992, 1993 5 * The Regents of the University of California. All rights reserved. 6 * Copyright (c) 1994 Gordon W. Ross 7 * Copyright (c) 1993 Adam Glass 8 * Copyright (c) 1996 Paul Kranenburg 9 * Copyright (c) 1996 10 * The President and Fellows of Harvard College. All rights reserved. 11 * 12 * This software was developed by the Computer Systems Engineering group 13 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 14 * contributed to Berkeley. 15 * 16 * All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by Harvard University. 19 * This product includes software developed by the University of 20 * California, Lawrence Berkeley Laboratory. 21 * 22 * Redistribution and use in source and binary forms, with or without 23 * modification, are permitted provided that the following conditions 24 * are met: 25 * 26 * 1. Redistributions of source code must retain the above copyright 27 * notice, this list of conditions and the following disclaimer. 28 * 2. Redistributions in binary form must reproduce the above copyright 29 * notice, this list of conditions and the following disclaimer in the 30 * documentation and/or other materials provided with the distribution. 31 * 3. All advertising materials mentioning features or use of this software 32 * must display the following acknowledgement: 33 * This product includes software developed by the University of 34 * California, Berkeley and its contributors. 35 * This product includes software developed by Paul Kranenburg. 36 * This product includes software developed by Harvard University. 37 * 4. Neither the name of the University nor the names of its contributors 38 * may be used to endorse or promote products derived from this software 39 * without specific prior written permission. 40 * 41 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51 * SUCH DAMAGE. 52 * 53 * @(#)clock.c 8.1 (Berkeley) 6/11/93 54 */ 55 56 /* 57 * Kernel clocks provided by "timer" device. The hardclock is provided by 58 * the timer register (aka system counter). The statclock is provided by 59 * per CPU counter register(s) (aka processor counter(s)). 60 */ 61 62 #include <sys/cdefs.h> 63 __KERNEL_RCSID(0, "$NetBSD: timer.c,v 1.34 2018/01/12 09:47:44 mrg Exp $"); 64 65 #include <sys/param.h> 66 #include <sys/kernel.h> 67 #include <sys/device.h> 68 #include <sys/systm.h> 69 #include <sys/timetc.h> 70 71 #include <machine/autoconf.h> 72 #include <sys/bus.h> 73 74 #include <sparc/sparc/timerreg.h> 75 #include <sparc/sparc/timervar.h> 76 77 static struct intrhand level10; 78 static struct intrhand level14; 79 80 static u_int timer_get_timecount(struct timecounter *); 81 82 void *sched_cookie; 83 84 /* 85 * timecounter local state 86 */ 87 static struct counter { 88 __cpu_simple_lock_t lock; /* protects access to offset, reg, last* */ 89 volatile u_int *cntreg; /* counter register to read */ 90 u_int limit; /* limit we count up to */ 91 u_int offset; /* accumulated offset due to wraps */ 92 u_int shift; /* scaling for valid bits */ 93 u_int mask; /* valid bit mask */ 94 u_int lastcnt; /* the last* values are used to notice */ 95 u_int lastres; /* and fix up cases where it would appear */ 96 u_int lastoffset; /* time went backwards. */ 97 } cntr __aligned(CACHE_LINE_SIZE); 98 99 /* 100 * define timecounter 101 */ 102 103 static struct timecounter counter_timecounter = { 104 .tc_get_timecount = timer_get_timecount, 105 .tc_poll_pps = NULL, 106 .tc_counter_mask = ~0u, 107 .tc_frequency = 0, 108 .tc_name = "timer-counter", 109 .tc_quality = 100, 110 .tc_priv = &cntr, 111 }; 112 113 /* 114 * timer_get_timecount provide current counter value 115 */ 116 __attribute__((__optimize__("Os"))) 117 static u_int 118 timer_get_timecount(struct timecounter *tc) 119 { 120 u_int cnt, res, fixup, offset; 121 int s; 122 123 /* 124 * We use splhigh/__cpu_simple_lock here as we don't want 125 * any mutex or lockdebug overhead. The lock protects a 126 * bunch of the members of cntr that are written here to 127 * deal with the various minor races to be observed and 128 * worked around. 129 */ 130 s = splhigh(); 131 __cpu_simple_lock(&cntr.lock); 132 res = cnt = *cntr.cntreg; 133 134 res &= ~TMR_LIMIT; 135 offset = cntr.offset; 136 137 /* 138 * There are 3 cases here: 139 * - limit reached, interrupt not yet processed. 140 * - count reset but offset the same, race between handling 141 * the interrupt and tickle_tc() updating the offset. 142 * - normal case. 143 * 144 * For the first two cases, add the limit so that we avoid 145 * time going backwards. 146 */ 147 if (cnt != res) { 148 fixup = cntr.limit; 149 } else if (res < cntr.lastcnt && offset == cntr.lastoffset) { 150 fixup = cntr.limit; 151 } else { 152 fixup = 0; 153 } 154 155 cntr.lastcnt = res; 156 cntr.lastoffset = offset; 157 158 res >>= cntr.shift; 159 res &= cntr.mask; 160 161 res += fixup + offset; 162 163 /* 164 * This handles early-boot cases where the counter resets twice 165 * before the offset is updated, and we have a stupid check to 166 * ensure overflow hasn't happened. 167 */ 168 if (res < cntr.lastres && res > (TMR_MASK+1) << 3) 169 res = cntr.lastres + 1; 170 171 cntr.lastres = res; 172 173 __cpu_simple_unlock(&cntr.lock); 174 splx(s); 175 176 return res; 177 } 178 179 void 180 tickle_tc(void) 181 { 182 183 if (timecounter->tc_get_timecount == timer_get_timecount) { 184 /* 185 * This could be protected by cntr.lock/splhigh but the update 186 * happens at IPL10 already and as a 32 bit value it should 187 * never be seen as a partial update, so skip it here. This 188 * also probably slows down the actual offset update, making 189 * one of the cases above more likely to need the workaround. 190 */ 191 cntr.offset += cntr.limit; 192 } 193 } 194 195 /* 196 * sun4/sun4c/sun4m common timer attach code 197 */ 198 void 199 timerattach(volatile int *cntreg, volatile int *limreg) 200 { 201 u_int prec = 0, t0; 202 203 /* 204 * Calibrate delay() by tweaking the magic constant 205 * until a delay(100) actually reads (at least) 100 us on the clock. 206 * Note: sun4m clocks tick with 500ns periods. 207 */ 208 for (timerblurb = 1; ; timerblurb++) { 209 int discard; 210 u_int t1; 211 212 /* Reset counter register by writing some large limit value */ 213 discard = *limreg; 214 __USE(discard); 215 *limreg = tmr_ustolim(TMR_MASK-1); 216 217 t0 = *cntreg; 218 delay(100); 219 t1 = *cntreg; 220 221 prec |= (t0 ^ t1) | (*cntreg ^ *cntreg); 222 223 if (t1 & TMR_LIMIT) 224 panic("delay calibration"); 225 226 t0 = (t0 >> TMR_SHIFT) & TMR_MASK; 227 t1 = (t1 >> TMR_SHIFT) & TMR_MASK; 228 229 if (t1 >= t0 + 100) 230 break; 231 } 232 233 /* find lowest active bit */ 234 for (t0 = 0; t0 < TMR_SHIFT; t0++) 235 if ((1 << t0) & prec) 236 break; 237 238 __cpu_simple_lock_init(&cntr.lock); 239 240 cntr.shift = t0; 241 cntr.mask = (1 << (31-t0))-1; 242 counter_timecounter.tc_frequency = 1000000 * (TMR_SHIFT - t0 + 1); 243 244 printf(": delay constant %d, frequency = %" PRIu64 " Hz\n", 245 timerblurb, counter_timecounter.tc_frequency); 246 247 #if defined(SUN4) || defined(SUN4C) 248 if (CPU_ISSUN4 || CPU_ISSUN4C) { 249 timer_init = timer_init_4; 250 level10.ih_fun = clockintr_4; 251 level14.ih_fun = statintr_4; 252 cntr.limit = tmr_ustolim(tick); 253 } 254 #endif 255 #if defined(SUN4M) 256 if (CPU_ISSUN4M) { 257 timer_init = timer_init_4m; 258 level10.ih_fun = clockintr_4m; 259 level14.ih_fun = statintr_4m; 260 cntr.limit = tmr_ustolim4m(tick); 261 } 262 #endif 263 264 /* link interrupt handlers */ 265 intr_establish(10, 0, &level10, NULL, true); 266 intr_establish(14, 0, &level14, NULL, true); 267 268 /* Establish a soft interrupt at a lower level for schedclock */ 269 sched_cookie = sparc_softintr_establish(IPL_SCHED, schedintr, NULL); 270 if (sched_cookie == NULL) 271 panic("timerattach: cannot establish schedintr"); 272 273 cntr.cntreg = cntreg; 274 cntr.limit >>= cntr.shift; 275 276 /* start at non-zero, so that cntr.oldoffset is less */ 277 cntr.offset = cntr.limit; 278 279 tc_init(&counter_timecounter); 280 } 281 282 /* 283 * Both sun4 and sun4m can attach a timer on obio. 284 * The sun4m OPENPROM calls the timer the "counter". 285 * The sun4 timer must be probed. 286 */ 287 static int 288 timermatch_obio(device_t parent, cfdata_t cf, void *aux) 289 { 290 #if defined(SUN4) || defined(SUN4M) 291 union obio_attach_args *uoba = aux; 292 #endif 293 #if defined(SUN4) 294 struct obio4_attach_args *oba; 295 #endif 296 297 #if defined(SUN4M) 298 if (uoba->uoba_isobio4 == 0) 299 return (strcmp("counter", uoba->uoba_sbus.sa_name) == 0); 300 #endif /* SUN4M */ 301 302 if (CPU_ISSUN4 == 0) { 303 printf("timermatch_obio: attach args mixed up\n"); 304 return (0); 305 } 306 307 #if defined(SUN4) 308 /* Only these sun4s have "timer" (others have "oclock") */ 309 if (cpuinfo.cpu_type != CPUTYP_4_300 && 310 cpuinfo.cpu_type != CPUTYP_4_400) 311 return (0); 312 313 /* Make sure there is something there */ 314 oba = &uoba->uoba_oba4; 315 return (bus_space_probe(oba->oba_bustag, oba->oba_paddr, 316 4, /* probe size */ 317 0, /* offset */ 318 0, /* flags */ 319 NULL, NULL)); 320 #endif /* SUN4 */ 321 panic("timermatch_obio: impossible"); 322 } 323 324 static void 325 timerattach_obio(device_t parent, device_t self, void *aux) 326 { 327 union obio_attach_args *uoba = aux; 328 329 if (uoba->uoba_isobio4 == 0) { 330 #if defined(SUN4M) 331 /* sun4m timer at obio */ 332 timerattach_obio_4m(parent, self, aux); 333 #endif /* SUN4M */ 334 return; 335 } 336 337 if (uoba->uoba_isobio4 != 0) { 338 #if defined(SUN4) 339 /* sun4 timer at obio */ 340 timerattach_obio_4(parent, self, aux); 341 #endif /* SUN4 */ 342 } 343 } 344 345 CFATTACH_DECL_NEW(timer_obio, 0, 346 timermatch_obio, timerattach_obio, NULL, NULL); 347 348 /* 349 * Only sun4c attaches a timer at mainbus 350 */ 351 static int 352 timermatch_mainbus(device_t parent, cfdata_t cf, void *aux) 353 { 354 #if defined(SUN4C) 355 struct mainbus_attach_args *ma = aux; 356 357 return (strcmp("counter-timer", ma->ma_name) == 0); 358 #else 359 return (0); 360 #endif 361 } 362 363 static void 364 timerattach_mainbus(device_t parent, device_t self, void *aux) 365 { 366 367 #if defined(SUN4C) 368 timerattach_mainbus_4c(parent, self, aux); 369 #endif /* SUN4C */ 370 } 371 372 CFATTACH_DECL_NEW(timer_mainbus, 0, 373 timermatch_mainbus, timerattach_mainbus, NULL, NULL); 374