1/* $OpenBSD: clock.c,v 1.87 2024/04/08 20:05:51 miod Exp $ */ 2/* $NetBSD: clock.c,v 1.41 2001/07/24 19:29:25 eeh Exp $ */ 3 4/* 5 * Copyright (c) 1992, 1993 6 * The Regents of the University of California. All rights reserved. 7 * Copyright (c) 1994 Gordon W. Ross 8 * Copyright (c) 1993 Adam Glass 9 * Copyright (c) 1996 Paul Kranenburg 10 * Copyright (c) 1996 11 * The President and Fellows of Harvard College. All rights reserved. 12 * 13 * This software was developed by the Computer Systems Engineering group 14 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 15 * contributed to Berkeley. 16 * 17 * All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by Harvard University. 20 * This product includes software developed by the University of 21 * California, Lawrence Berkeley Laboratory. 22 * 23 * Redistribution and use in source and binary forms, with or without 24 * modification, are permitted provided that the following conditions 25 * are met: 26 * 27 * 1. Redistributions of source code must retain the above copyright 28 * notice, this list of conditions and the following disclaimer. 29 * 2. Redistributions in binary form must reproduce the above copyright 30 * notice, this list of conditions and the following disclaimer in the 31 * documentation and/or other materials provided with the distribution. 32 * 3. All advertising materials mentioning features or use of this software 33 * must display the following acknowledgement: 34 * This product includes software developed by the University of 35 * California, Berkeley and its contributors. 36 * This product includes software developed by Paul Kranenburg. 37 * This product includes software developed by Harvard University. 38 * 4. Neither the name of the University nor the names of its contributors 39 * may be used to endorse or promote products derived from this software 40 * without specific prior written permission. 41 * 42 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 43 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 44 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 45 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 46 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 47 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 48 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 49 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 50 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 51 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 52 * SUCH DAMAGE. 53 * 54 * @(#)clock.c 8.1 (Berkeley) 6/11/93 55 * 56 */ 57 58/* 59 * Clock driver. This is the id prom and eeprom driver as well 60 * and includes the timer register functions too. 61 */ 62 63/* Define this for a 1/4s clock to ease debugging */ 64/* #define INTR_DEBUG */ 65 66#include <sys/param.h> 67#include <sys/kernel.h> 68#include <sys/device.h> 69#include <sys/malloc.h> 70#include <sys/systm.h> 71#include <sys/clockintr.h> 72#include <sys/sched.h> 73#include <sys/stdint.h> 74#include <sys/timetc.h> 75#include <sys/atomic.h> 76 77#include <machine/bus.h> 78#include <machine/autoconf.h> 79#include <machine/cpu.h> 80#include <machine/idprom.h> 81 82#include <dev/clock_subr.h> 83#include <dev/ic/mk48txxreg.h> 84 85#include <sparc64/dev/iommureg.h> 86#include <sparc64/dev/sbusreg.h> 87#include <dev/sbus/sbusvar.h> 88#include <sparc64/dev/ebusreg.h> 89#include <sparc64/dev/ebusvar.h> 90#include <sparc64/dev/fhcvar.h> 91 92extern u_int64_t cpu_clockrate; 93 94struct clock_wenable_info { 95 bus_space_tag_t cwi_bt; 96 bus_space_handle_t cwi_bh; 97 bus_size_t cwi_size; 98}; 99 100struct cfdriver clock_cd = { 101 NULL, "clock", DV_DULL 102}; 103 104u_int tick_get_timecount(struct timecounter *); 105 106struct timecounter tick_timecounter = { 107 .tc_get_timecount = tick_get_timecount, 108 .tc_counter_mask = ~0u, 109 .tc_frequency = 0, 110 .tc_name = "tick", 111 .tc_quality = 0, 112 .tc_priv = NULL, 113 .tc_user = TC_TICK, 114}; 115 116u_int sys_tick_get_timecount(struct timecounter *); 117 118struct timecounter sys_tick_timecounter = { 119 .tc_get_timecount = sys_tick_get_timecount, 120 .tc_counter_mask = ~0u, 121 .tc_frequency = 0, 122 .tc_name = "sys_tick", 123 .tc_quality = 1000, 124 .tc_priv = NULL, 125 .tc_user = TC_SYS_TICK, 126}; 127 128void tick_start(void); 129void sys_tick_start(void); 130void stick_start(void); 131 132int tickintr(void *); 133int sys_tickintr(void *); 134int stickintr(void *); 135 136/* %TICK is at most a 63-bit counter. */ 137#define TICK_COUNT_MASK 0x7fffffffffffffff 138 139uint64_t tick_nsec_cycle_ratio; 140uint64_t tick_nsec_max; 141 142void tick_rearm(void *, uint64_t); 143void tick_trigger(void *); 144 145const struct intrclock tick_intrclock = { 146 .ic_rearm = tick_rearm, 147 .ic_trigger = tick_trigger 148}; 149 150/* %STICK is at most a 63-bit counter. */ 151#define STICK_COUNT_MASK 0x7fffffffffffffff 152 153uint64_t sys_tick_nsec_cycle_ratio; 154uint64_t sys_tick_nsec_max; 155 156void sys_tick_rearm(void *, uint64_t); 157void sys_tick_trigger(void *); 158 159const struct intrclock sys_tick_intrclock = { 160 .ic_rearm = sys_tick_rearm, 161 .ic_trigger = sys_tick_trigger 162}; 163 164void stick_rearm(void *, uint64_t); 165void stick_trigger(void *); 166 167const struct intrclock stick_intrclock = { 168 .ic_rearm = stick_rearm, 169 .ic_trigger = stick_trigger 170}; 171 172void sparc64_raise_clockintr(void); 173 174static struct intrhand level10 = { 175 .ih_fun = tickintr, 176 .ih_number = 1, 177 .ih_pil = 10, 178 .ih_name = "clock" 179}; 180 181/* 182 * clock (eeprom) attaches at the sbus or the ebus (PCI) 183 */ 184static int clockmatch_sbus(struct device *, void *, void *); 185static void clockattach_sbus(struct device *, struct device *, void *); 186static int clockmatch_ebus(struct device *, void *, void *); 187static void clockattach_ebus(struct device *, struct device *, void *); 188static int clockmatch_fhc(struct device *, void *, void *); 189static void clockattach_fhc(struct device *, struct device *, void *); 190static void clockattach(int, bus_space_tag_t, bus_space_handle_t); 191 192const struct cfattach clock_sbus_ca = { 193 sizeof(struct device), clockmatch_sbus, clockattach_sbus 194}; 195 196const struct cfattach clock_ebus_ca = { 197 sizeof(struct device), clockmatch_ebus, clockattach_ebus 198}; 199 200const struct cfattach clock_fhc_ca = { 201 sizeof(struct device), clockmatch_fhc, clockattach_fhc 202}; 203 204/* Global TOD clock handle & idprom pointer */ 205extern todr_chip_handle_t todr_handle; 206static struct idprom *idprom; 207 208int clock_bus_wenable(struct todr_chip_handle *, int); 209void myetheraddr(u_char *); 210struct idprom *getidprom(void); 211 212/* 213 * The OPENPROM calls the clock the "eeprom", so we have to have our 214 * own special match function to call it the "clock". 215 */ 216static int 217clockmatch_sbus(struct device *parent, void *cf, void *aux) 218{ 219 struct sbus_attach_args *sa = aux; 220 221 return (strcmp("eeprom", sa->sa_name) == 0); 222} 223 224static int 225clockmatch_ebus(struct device *parent, void *cf, void *aux) 226{ 227 struct ebus_attach_args *ea = aux; 228 229 return (strcmp("eeprom", ea->ea_name) == 0); 230} 231 232static int 233clockmatch_fhc(struct device *parent, void *cf, void *aux) 234{ 235 struct fhc_attach_args *fa = aux; 236 237 return (strcmp("eeprom", fa->fa_name) == 0); 238} 239 240/* 241 * Attach a clock (really `eeprom') to the sbus or ebus. 242 * 243 * We ignore any existing virtual address as we need to map 244 * this read-only and make it read-write only temporarily, 245 * whenever we read or write the clock chip. The clock also 246 * contains the ID ``PROM'', and I have already had the pleasure 247 * of reloading the cpu type, Ethernet address, etc, by hand from 248 * the console FORTH interpreter. I intend not to enjoy it again. 249 * 250 * the MK48T02 is 2K. the MK48T08 is 8K, and the MK48T59 is 251 * supposed to be identical to it. 252 * 253 * This is *UGLY*! We probably have multiple mappings. But I do 254 * know that this all fits inside an 8K page, so I'll just map in 255 * once. 256 * 257 * What we really need is some way to record the bus attach args 258 * so we can call *_bus_map() later with BUS_SPACE_MAP_READONLY 259 * or not to write enable/disable the device registers. This is 260 * a non-trivial operation. 261 */ 262 263static void 264clockattach_sbus(struct device *parent, struct device *self, void *aux) 265{ 266 struct sbus_attach_args *sa = aux; 267 bus_space_tag_t bt = sa->sa_bustag; 268 int sz; 269 static struct clock_wenable_info cwi; 270 271 /* use sa->sa_regs[0].size? */ 272 sz = 8192; 273 274 if (sbus_bus_map(bt, 275 sa->sa_slot, 276 (sa->sa_offset & ~NBPG), 277 sz, 278 BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_READONLY, 279 0, &cwi.cwi_bh) != 0) { 280 printf("%s: can't map register\n", self->dv_xname); 281 return; 282 } 283 clockattach(sa->sa_node, bt, cwi.cwi_bh); 284 285 /* Save info for the clock wenable call. */ 286 cwi.cwi_bt = bt; 287 cwi.cwi_size = sz; 288 todr_handle->bus_cookie = &cwi; 289 todr_handle->todr_setwen = clock_bus_wenable; 290} 291 292/* 293 * Write en/dis-able clock registers. We coordinate so that several 294 * writers can run simultaneously. 295 * XXX There is still a race here. The page change and the "writers" 296 * change are not atomic. 297 */ 298int 299clock_bus_wenable(struct todr_chip_handle *handle, int onoff) 300{ 301 int s, err = 0; 302 int prot; /* nonzero => change prot */ 303 volatile static int writers; 304 struct clock_wenable_info *cwi = handle->bus_cookie; 305 306 s = splhigh(); 307 if (onoff) 308 prot = writers++ == 0 ? 1 : 0; 309 else 310 prot = --writers == 0 ? 1 : 0; 311 splx(s); 312 313 if (prot) { 314 err = bus_space_protect(cwi->cwi_bt, cwi->cwi_bh, cwi->cwi_size, 315 onoff ? 0 : BUS_SPACE_MAP_READONLY); 316 if (err) 317 printf("clock_wenable_info: WARNING -- cannot %s " 318 "page protection\n", onoff ? "disable" : "enable"); 319 } 320 return (err); 321} 322 323static void 324clockattach_ebus(struct device *parent, struct device *self, void *aux) 325{ 326 struct ebus_attach_args *ea = aux; 327 bus_space_tag_t bt; 328 int sz; 329 static struct clock_wenable_info cwi; 330 331 /* hard code to 8K? */ 332 sz = ea->ea_regs[0].size; 333 334 if (ebus_bus_map(ea->ea_iotag, 0, 335 EBUS_PADDR_FROM_REG(&ea->ea_regs[0]), sz, 0, 0, &cwi.cwi_bh) == 0) { 336 bt = ea->ea_iotag; 337 } else if (ebus_bus_map(ea->ea_memtag, 0, 338 EBUS_PADDR_FROM_REG(&ea->ea_regs[0]), sz, 339 BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_READONLY, 340 0, &cwi.cwi_bh) == 0) { 341 bt = ea->ea_memtag; 342 } else { 343 printf("%s: can't map register\n", self->dv_xname); 344 return; 345 } 346 347 clockattach(ea->ea_node, bt, cwi.cwi_bh); 348 349 /* Save info for the clock wenable call. */ 350 cwi.cwi_bt = bt; 351 cwi.cwi_size = sz; 352 todr_handle->bus_cookie = &cwi; 353 todr_handle->todr_setwen = (ea->ea_memtag == bt) ? 354 clock_bus_wenable : NULL; 355} 356 357static void 358clockattach_fhc(struct device *parent, struct device *self, void *aux) 359{ 360 struct fhc_attach_args *fa = aux; 361 bus_space_tag_t bt = fa->fa_bustag; 362 int sz; 363 static struct clock_wenable_info cwi; 364 365 /* use sa->sa_regs[0].size? */ 366 sz = 8192; 367 368 if (fhc_bus_map(bt, fa->fa_reg[0].fbr_slot, 369 (fa->fa_reg[0].fbr_offset & ~NBPG), fa->fa_reg[0].fbr_size, 370 BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_READONLY, &cwi.cwi_bh) != 0) { 371 printf("%s: can't map register\n", self->dv_xname); 372 return; 373 } 374 375 clockattach(fa->fa_node, bt, cwi.cwi_bh); 376 377 /* Save info for the clock wenable call. */ 378 cwi.cwi_bt = bt; 379 cwi.cwi_size = sz; 380 todr_handle->bus_cookie = &cwi; 381 todr_handle->todr_setwen = clock_bus_wenable; 382} 383 384static void 385clockattach(int node, bus_space_tag_t bt, bus_space_handle_t bh) 386{ 387 char *model; 388 struct idprom *idp; 389 int h; 390 391 model = getpropstring(node, "model"); 392 393#ifdef DIAGNOSTIC 394 if (model == NULL) 395 panic("clockattach: no model property"); 396#endif 397 398 /* Our TOD clock year 0 is 1968 */ 399 if ((todr_handle = mk48txx_attach(bt, bh, model, 1968)) == NULL) 400 panic("Can't attach %s tod clock", model); 401 402#define IDPROM_OFFSET (8*1024 - 40) /* XXX - get nvram sz from driver */ 403 if (idprom == NULL) { 404 idp = getidprom(); 405 if (idp == NULL) 406 idp = (struct idprom *)(bus_space_vaddr(bt, bh) + 407 IDPROM_OFFSET); 408 idprom = idp; 409 } else 410 idp = idprom; 411 h = idp->id_machine << 24; 412 h |= idp->id_hostid[0] << 16; 413 h |= idp->id_hostid[1] << 8; 414 h |= idp->id_hostid[2]; 415 hostid = h; 416 printf("\n"); 417} 418 419struct idprom * 420getidprom(void) 421{ 422 struct idprom *idp = NULL; 423 int node, n; 424 425 node = findroot(); 426 if (getprop(node, "idprom", sizeof(*idp), &n, (void **)&idp) != 0) 427 return (NULL); 428 if (n != 1) { 429 free(idp, M_DEVBUF, 0); 430 return (NULL); 431 } 432 return (idp); 433} 434 435/* 436 * XXX this belongs elsewhere 437 */ 438void 439myetheraddr(u_char *cp) 440{ 441 struct idprom *idp; 442 443 if ((idp = idprom) == NULL) { 444 int node, n; 445 446 node = findroot(); 447 if (getprop(node, "idprom", sizeof *idp, &n, (void **)&idp) || 448 n != 1) { 449 printf("\nmyetheraddr: clock not setup yet, " 450 "and no idprom property in /\n"); 451 return; 452 } 453 } 454 455 cp[0] = idp->id_ether[0]; 456 cp[1] = idp->id_ether[1]; 457 cp[2] = idp->id_ether[2]; 458 cp[3] = idp->id_ether[3]; 459 cp[4] = idp->id_ether[4]; 460 cp[5] = idp->id_ether[5]; 461 if (idprom == NULL) 462 free(idp, M_DEVBUF, 0); 463} 464 465/* 466 * Set up the real-time and statistics clocks. 467 * 468 * The frequencies of these clocks must be an even number of microseconds. 469 */ 470void 471cpu_initclocks(void) 472{ 473 u_int sys_tick_rate; 474 int impl = 0; 475 476 if (1000000 % hz) { 477 printf("cannot get %d Hz clock; using 100 Hz\n", hz); 478 hz = 100; 479 tick = 1000000 / hz; 480 tick_nsec = 1000000000 / hz; 481 } 482 483 stathz = hz; 484 profhz = stathz * 10; 485 statclock_is_randomized = 1; 486 487 /* Make sure we have a sane cpu_clockrate -- we'll need it */ 488 if (!cpu_clockrate) 489 /* Default to 200MHz clock XXXXX */ 490 cpu_clockrate = 200000000; 491 492 tick_timecounter.tc_frequency = cpu_clockrate; 493 tc_init(&tick_timecounter); 494 495 /* 496 * UltraSPARC IIe processors do have a STICK register, but it 497 * lives on the PCI host bridge and isn't accessible through 498 * ASR24. 499 */ 500 if (CPU_ISSUN4U || CPU_ISSUN4US) 501 impl = (getver() & VER_IMPL) >> VER_IMPL_SHIFT; 502 503 sys_tick_rate = getpropint(findroot(), "stick-frequency", 0); 504 if (sys_tick_rate > 0 && impl != IMPL_HUMMINGBIRD) { 505 sys_tick_timecounter.tc_frequency = sys_tick_rate; 506 tc_init(&sys_tick_timecounter); 507 } 508 509 struct cpu_info *ci; 510 511 /* 512 * Establish a level 10 interrupt handler 513 * 514 * We will have a conflict with the softint handler, 515 * so we set the ih_number to 1. 516 */ 517 intr_establish(&level10); 518 evcount_percpu(&level10.ih_count); 519 520 if (sys_tick_rate > 0) { 521 sys_tick_nsec_cycle_ratio = 522 sys_tick_rate * (1ULL << 32) / 1000000000; 523 sys_tick_nsec_max = UINT64_MAX / sys_tick_nsec_cycle_ratio; 524 if (impl == IMPL_HUMMINGBIRD) { 525 level10.ih_fun = stickintr; 526 cpu_start_clock = stick_start; 527 } else { 528 level10.ih_fun = sys_tickintr; 529 cpu_start_clock = sys_tick_start; 530 } 531 } else { 532 tick_nsec_cycle_ratio = 533 cpu_clockrate * (1ULL << 32) / 1000000000; 534 tick_nsec_max = UINT64_MAX / tick_nsec_cycle_ratio; 535 level10.ih_fun = tickintr; 536 cpu_start_clock = tick_start; 537 } 538 539 for (ci = cpus; ci != NULL; ci = ci->ci_next) 540 memcpy(&ci->ci_tickintr, &level10, sizeof(level10)); 541} 542 543void 544cpu_startclock(void) 545{ 546 cpu_start_clock(); 547} 548 549void 550setstatclockrate(int newhz) 551{ 552} 553 554/* 555 * Level 10 (clock) interrupts. If we are using the FORTH PROM for 556 * console input, we need to check for that here as well, and generate 557 * a software interrupt to read it. 558 * 559 * %tick is really a level-14 interrupt. We need to remap this in 560 * locore.s to a level 10. 561 */ 562int 563tickintr(void *cap) 564{ 565 clockintr_dispatch(cap); 566 evcount_inc(&level10.ih_count); 567 return (1); 568} 569 570int 571sys_tickintr(void *cap) 572{ 573 clockintr_dispatch(cap); 574 evcount_inc(&level10.ih_count); 575 return (1); 576} 577 578int 579stickintr(void *cap) 580{ 581 clockintr_dispatch(cap); 582 evcount_inc(&level10.ih_count); 583 return (1); 584} 585 586void 587tick_start(void) 588{ 589 tick_enable(); 590 591 clockintr_cpu_init(&tick_intrclock); 592 clockintr_trigger(); 593} 594 595void 596tick_rearm(void *unused, uint64_t nsecs) 597{ 598 uint64_t s, t0; 599 uint32_t cycles; 600 601 if (nsecs > tick_nsec_max) 602 nsecs = tick_nsec_max; 603 cycles = (nsecs * tick_nsec_cycle_ratio) >> 32; 604 605 s = intr_disable(); 606 t0 = tick(); 607 tickcmpr_set((t0 + cycles) & TICK_COUNT_MASK); 608 if (cycles <= ((tick() - t0) & TICK_COUNT_MASK)) 609 sparc64_raise_clockintr(); 610 intr_restore(s); 611} 612 613void 614tick_trigger(void *unused) 615{ 616 sparc64_raise_clockintr(); 617} 618 619void 620sys_tick_start(void) 621{ 622 if (CPU_ISSUN4U || CPU_ISSUN4US) { 623 tick_enable(); 624 sys_tick_enable(); 625 } 626 627 clockintr_cpu_init(&sys_tick_intrclock); 628 clockintr_trigger(); 629} 630 631void 632sys_tick_rearm(void *unused, uint64_t nsecs) 633{ 634 uint64_t s, t0; 635 uint32_t cycles; 636 637 if (nsecs > sys_tick_nsec_max) 638 nsecs = sys_tick_nsec_max; 639 cycles = (nsecs * sys_tick_nsec_cycle_ratio) >> 32; 640 641 s = intr_disable(); 642 t0 = sys_tick(); 643 sys_tickcmpr_set((t0 + cycles) & STICK_COUNT_MASK); 644 if (cycles <= ((sys_tick() - t0) & STICK_COUNT_MASK)) 645 sparc64_raise_clockintr(); 646 intr_restore(s); 647} 648 649void 650sys_tick_trigger(void *unused) 651{ 652 sparc64_raise_clockintr(); 653} 654 655void 656stick_start(void) 657{ 658 tick_enable(); 659 660 clockintr_cpu_init(&stick_intrclock); 661 clockintr_trigger(); 662} 663 664void 665stick_rearm(void *unused, uint64_t nsecs) 666{ 667 uint64_t s, t0; 668 uint32_t cycles; 669 670 if (nsecs > sys_tick_nsec_max) 671 nsecs = sys_tick_nsec_max; 672 cycles = (nsecs * sys_tick_nsec_cycle_ratio) >> 32; 673 674 s = intr_disable(); 675 t0 = stick(); 676 stickcmpr_set((t0 + cycles) & STICK_COUNT_MASK); 677 if (cycles <= ((stick() - t0) & STICK_COUNT_MASK)) 678 sparc64_raise_clockintr(); 679 intr_restore(s); 680} 681 682void 683stick_trigger(void *unused) 684{ 685 sparc64_raise_clockintr(); 686} 687 688u_int 689tick_get_timecount(struct timecounter *tc) 690{ 691 u_int64_t tick; 692 693 __asm volatile("rd %%tick, %0" : "=r" (tick)); 694 695 return (tick & ~0u); 696} 697 698u_int 699sys_tick_get_timecount(struct timecounter *tc) 700{ 701 u_int64_t tick; 702 703 __asm volatile("rd %%sys_tick, %0" : "=r" (tick)); 704 705 return (tick & ~0u); 706} 707 708void 709sparc64_raise_clockintr(void) 710{ 711 send_softint(PIL_CLOCK, &curcpu()->ci_tickintr); 712} 713