1 /* $NetBSD: clock.c,v 1.36 2001/03/15 06:10:35 chs Exp $ */ 2 3 /* 4 * Copyright (c) 1988 University of Utah. 5 * Copyright (c) 1982, 1990 The Regents of the University of California. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * the Systems Programming Group of the University of Utah Computer 10 * Science Department. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the University of 23 * California, Berkeley and its contributors. 24 * 4. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * from: Utah $Hdr: clock.c 1.18 91/01/21$ 41 * 42 * @(#)clock.c 7.6 (Berkeley) 5/7/91 43 */ 44 45 #include <sys/param.h> 46 #include <sys/kernel.h> 47 #include <sys/device.h> 48 #include <sys/systm.h> 49 #include <machine/psl.h> 50 #include <machine/cpu.h> 51 #include <amiga/amiga/device.h> 52 #include <amiga/amiga/custom.h> 53 #include <amiga/amiga/cia.h> 54 #ifdef DRACO 55 #include <amiga/amiga/drcustom.h> 56 #include <m68k/include/asm_single.h> 57 #endif 58 #include <amiga/dev/rtc.h> 59 #include <amiga/dev/zbusvar.h> 60 61 #if defined(PROF) && defined(PROFTIMER) 62 #include <sys/PROF.h> 63 #endif 64 65 /* the clocks run at NTSC: 715.909kHz or PAL: 709.379kHz. 66 We're using a 100 Hz clock. */ 67 68 #define CLK_INTERVAL amiga_clk_interval 69 int amiga_clk_interval; 70 int eclockfreq; 71 struct CIA *clockcia; 72 73 /* 74 * Machine-dependent clock routines. 75 * 76 * Startrtclock restarts the real-time clock, which provides 77 * hardclock interrupts to kern_clock.c. 78 * 79 * Inittodr initializes the time of day hardware which provides 80 * date functions. 81 * 82 * Resettodr restores the time of day hardware after a time change. 83 * 84 * A note on the real-time clock: 85 * We actually load the clock with CLK_INTERVAL-1 instead of CLK_INTERVAL. 86 * This is because the counter decrements to zero after N+1 enabled clock 87 * periods where N is the value loaded into the counter. 88 */ 89 90 int clockmatch __P((struct device *, struct cfdata *, void *)); 91 void clockattach __P((struct device *, struct device *, void *)); 92 void cpu_initclocks __P((void)); 93 void calibrate_delay __P((struct device *)); 94 95 struct cfattach clock_ca = { 96 sizeof(struct device), clockmatch, clockattach 97 }; 98 99 int 100 clockmatch(pdp, cfp, auxp) 101 struct device *pdp; 102 struct cfdata *cfp; 103 void *auxp; 104 { 105 if (matchname("clock", auxp)) 106 return(1); 107 return(0); 108 } 109 110 /* 111 * Start the real-time clock. 112 */ 113 void 114 clockattach(pdp, dp, auxp) 115 struct device *pdp, *dp; 116 void *auxp; 117 { 118 char *clockchip; 119 unsigned short interval; 120 #ifdef DRACO 121 u_char dracorev; 122 #endif 123 124 if (eclockfreq == 0) 125 eclockfreq = 715909; /* guess NTSC */ 126 127 CLK_INTERVAL = (eclockfreq / 100); 128 129 #ifdef DRACO 130 dracorev = is_draco(); 131 if (dracorev >= 4) { 132 CLK_INTERVAL = (eclockfreq / 700); 133 clockchip = "QuickLogic"; 134 } else if (dracorev) { 135 clockcia = (struct CIA *)CIAAbase; 136 clockchip = "CIA A"; 137 } else 138 #endif 139 { 140 clockcia = (struct CIA *)CIABbase; 141 clockchip = "CIA B"; 142 } 143 144 if (dp) 145 printf(": %s system hz %d hardware hz %d\n", clockchip, hz, 146 #ifdef DRACO 147 dracorev >= 4 ? eclockfreq / 7 : eclockfreq); 148 #else 149 eclockfreq); 150 #endif 151 152 #ifdef DRACO 153 if (dracorev >= 4) { 154 /* 155 * can't preload anything beforehand, timer is free_running; 156 * but need this for delay calibration. 157 */ 158 159 draco_ioct->io_timerlo = CLK_INTERVAL & 0xff; 160 draco_ioct->io_timerhi = CLK_INTERVAL >> 8; 161 162 calibrate_delay(dp); 163 164 return; 165 } 166 #endif 167 /* 168 * stop timer A 169 */ 170 clockcia->cra = clockcia->cra & 0xc0; 171 clockcia->icr = 1 << 0; /* disable timer A interrupt */ 172 interval = clockcia->icr; /* and make sure it's clear */ 173 174 /* 175 * load interval into registers. 176 * the clocks run at NTSC: 715.909kHz or PAL: 709.379kHz 177 * supprort for PAL WHEN?!?! XXX 178 */ 179 interval = CLK_INTERVAL - 1; 180 181 /* 182 * order of setting is important ! 183 */ 184 clockcia->talo = interval & 0xff; 185 clockcia->tahi = interval >> 8; 186 /* 187 * start timer A in continuous mode 188 */ 189 clockcia->cra = (clockcia->cra & 0xc0) | 1; 190 191 calibrate_delay(dp); 192 } 193 194 /* 195 * Calibrate delay loop. 196 * We use two iterations because we don't have enough bits to do a factor of 197 * 8 with better than 1%. 198 * 199 * XXX Note that we MUST stay below 1 tick if using clkread(), even for 200 * underestimated values of delaydivisor. 201 * 202 * XXX the "ns" below is only correct for a shift of 10 bits, and even then 203 * off by 2.4% 204 */ 205 206 void calibrate_delay(dp) 207 struct device *dp; 208 { 209 unsigned long t1, t2; 210 extern u_int32_t delaydivisor; 211 /* XXX this should be defined elsewhere */ 212 213 if (dp) 214 printf("Calibrating delay loop... "); 215 216 do { 217 t1 = clkread(); 218 delay(1024); 219 t2 = clkread(); 220 } while (t2 <= t1); 221 t2 -= t1; 222 delaydivisor = (delaydivisor * t2 + 1023) >> 10; 223 #ifdef DEBUG 224 if (dp) 225 printf("\ndiff %ld us, new divisor %u/1024 us\n", t2, 226 delaydivisor); 227 do { 228 t1 = clkread(); 229 delay(1024); 230 t2 = clkread(); 231 } while (t2 <= t1); 232 t2 -= t1; 233 delaydivisor = (delaydivisor * t2 + 1023) >> 10; 234 if (dp) 235 printf("diff %ld us, new divisor %u/1024 us\n", t2, 236 delaydivisor); 237 #endif 238 do { 239 t1 = clkread(); 240 delay(1024); 241 t2 = clkread(); 242 } while (t2 <= t1); 243 t2 -= t1; 244 delaydivisor = (delaydivisor * t2 + 1023) >> 10; 245 #ifdef DEBUG 246 if (dp) 247 printf("diff %ld us, new divisor ", t2); 248 #endif 249 if (dp) 250 printf("%u/1024 us\n", delaydivisor); 251 } 252 253 void 254 cpu_initclocks() 255 { 256 #ifdef DRACO 257 unsigned char dracorev; 258 dracorev = is_draco(); 259 if (dracorev >= 4) { 260 draco_ioct->io_timerlo = CLK_INTERVAL & 0xFF; 261 draco_ioct->io_timerhi = CLK_INTERVAL >> 8; 262 draco_ioct->io_timerrst = 0; /* any value resets */ 263 single_inst_bset_b(draco_ioct->io_status2, DRSTAT2_TMRINTENA); 264 265 return; 266 } 267 #endif 268 /* 269 * enable interrupts for timer A 270 */ 271 clockcia->icr = (1<<7) | (1<<0); 272 273 /* 274 * start timer A in continuous shot mode 275 */ 276 clockcia->cra = (clockcia->cra & 0xc0) | 1; 277 278 /* 279 * and globally enable interrupts for ciab 280 */ 281 #ifdef DRACO 282 if (dracorev) /* we use cia a on DraCo */ 283 single_inst_bset_b(*draco_intena, DRIRQ_INT2); 284 else 285 #endif 286 custom.intena = INTF_SETCLR | INTF_EXTER; 287 288 } 289 290 void 291 setstatclockrate(hz) 292 int hz; 293 { 294 } 295 296 /* 297 * Returns number of usec since last recorded clock "tick" 298 * (i.e. clock interrupt). 299 */ 300 u_long 301 clkread() 302 { 303 u_int interval; 304 u_char hi, hi2, lo; 305 306 #ifdef DRACO 307 if (is_draco() >= 4) { 308 hi2 = draco_ioct->io_chiprev; /* latch timer */ 309 hi = draco_ioct->io_timerhi; 310 lo = draco_ioct->io_timerlo; 311 interval = ((hi<<8) | lo); 312 if (interval > CLK_INTERVAL) /* timer underflow */ 313 interval = 65536 + CLK_INTERVAL - interval; 314 else 315 interval = CLK_INTERVAL - interval; 316 317 } else 318 #endif 319 { 320 hi = clockcia->tahi; 321 lo = clockcia->talo; 322 hi2 = clockcia->tahi; 323 if (hi != hi2) { 324 lo = clockcia->talo; 325 hi = hi2; 326 } 327 328 interval = (CLK_INTERVAL - 1) - ((hi<<8) | lo); 329 330 /* 331 * should read ICR and if there's an int pending, adjust 332 * interval. However, since reading ICR clears the interrupt, 333 * we'd lose a hardclock int, and this is not tolerable. 334 */ 335 } 336 337 return((interval * tick) / CLK_INTERVAL); 338 } 339 340 #if notyet 341 342 /* implement this later. I'd suggest using both timers in CIA-A, they're 343 not yet used. */ 344 345 #include "clock.h" 346 #if NCLOCK > 0 347 /* 348 * /dev/clock: mappable high resolution timer. 349 * 350 * This code implements a 32-bit recycling counter (with a 4 usec period) 351 * using timers 2 & 3 on the 6840 clock chip. The counter can be mapped 352 * RO into a user's address space to achieve low overhead (no system calls), 353 * high-precision timing. 354 * 355 * Note that timer 3 is also used for the high precision profiling timer 356 * (PROFTIMER code above). Care should be taken when both uses are 357 * configured as only a token effort is made to avoid conflicting use. 358 */ 359 #include <sys/proc.h> 360 #include <sys/resourcevar.h> 361 #include <sys/ioctl.h> 362 #include <sys/malloc.h> 363 #include <uvm/uvm_extern.h> 364 #include <amiga/amiga/clockioctl.h> 365 #include <sys/specdev.h> 366 #include <sys/vnode.h> 367 #include <sys/mman.h> 368 369 int clockon = 0; /* non-zero if high-res timer enabled */ 370 #ifdef PROFTIMER 371 int profprocs = 0; /* # of procs using profiling timer */ 372 #endif 373 #ifdef DEBUG 374 int clockdebug = 0; 375 #endif 376 377 /*ARGSUSED*/ 378 clockopen(dev, flags) 379 dev_t dev; 380 { 381 #ifdef PROFTIMER 382 #ifdef PROF 383 /* 384 * Kernel profiling enabled, give up. 385 */ 386 if (profiling) 387 return(EBUSY); 388 #endif 389 /* 390 * If any user processes are profiling, give up. 391 */ 392 if (profprocs) 393 return(EBUSY); 394 #endif 395 if (!clockon) { 396 startclock(); 397 clockon++; 398 } 399 return(0); 400 } 401 402 /*ARGSUSED*/ 403 clockclose(dev, flags) 404 dev_t dev; 405 { 406 (void) clockunmmap(dev, (caddr_t)0, curproc); /* XXX */ 407 stopclock(); 408 clockon = 0; 409 return(0); 410 } 411 412 /*ARGSUSED*/ 413 clockioctl(dev, cmd, data, flag, p) 414 dev_t dev; 415 u_long cmd; 416 caddr_t data; 417 struct proc *p; 418 { 419 int error = 0; 420 421 switch (cmd) { 422 423 case CLOCKMAP: 424 error = clockmmap(dev, (caddr_t *)data, p); 425 break; 426 427 case CLOCKUNMAP: 428 error = clockunmmap(dev, *(caddr_t *)data, p); 429 break; 430 431 case CLOCKGETRES: 432 *(int *)data = CLK_RESOLUTION; 433 break; 434 435 default: 436 error = EINVAL; 437 break; 438 } 439 return(error); 440 } 441 442 /*ARGSUSED*/ 443 clockmap(dev, off, prot) 444 dev_t dev; 445 { 446 return((off + (INTIOBASE+CLKBASE+CLKSR-1)) >> PGSHIFT); 447 } 448 449 clockmmap(dev, addrp, p) 450 dev_t dev; 451 caddr_t *addrp; 452 struct proc *p; 453 { 454 int error; 455 struct vnode vn; 456 struct specinfo si; 457 int flags; 458 459 flags = MAP_FILE|MAP_SHARED; 460 if (*addrp) 461 flags |= MAP_FIXED; 462 else 463 *addrp = (caddr_t)0x1000000; /* XXX */ 464 vn.v_type = VCHR; /* XXX */ 465 vn.v_specinfo = &si; /* XXX */ 466 vn.v_rdev = dev; /* XXX */ 467 error = vm_mmap(&p->p_vmspace->vm_map, (vm_offset_t *)addrp, 468 PAGE_SIZE, VM_PROT_ALL, flags, (caddr_t)&vn, 0); 469 return(error); 470 } 471 472 clockunmmap(dev, addr, p) 473 dev_t dev; 474 caddr_t addr; 475 struct proc *p; 476 { 477 int rv; 478 479 if (addr == 0) 480 return(EINVAL); /* XXX: how do we deal with this? */ 481 uvm_deallocate(p->p_vmspace->vm_map, (vm_offset_t)addr, PAGE_SIZE); 482 return 0; 483 } 484 485 startclock() 486 { 487 register struct clkreg *clk = (struct clkreg *)clkstd[0]; 488 489 clk->clk_msb2 = -1; clk->clk_lsb2 = -1; 490 clk->clk_msb3 = -1; clk->clk_lsb3 = -1; 491 492 clk->clk_cr2 = CLK_CR3; 493 clk->clk_cr3 = CLK_OENAB|CLK_8BIT; 494 clk->clk_cr2 = CLK_CR1; 495 clk->clk_cr1 = CLK_IENAB; 496 } 497 498 stopclock() 499 { 500 register struct clkreg *clk = (struct clkreg *)clkstd[0]; 501 502 clk->clk_cr2 = CLK_CR3; 503 clk->clk_cr3 = 0; 504 clk->clk_cr2 = CLK_CR1; 505 clk->clk_cr1 = CLK_IENAB; 506 } 507 #endif 508 509 #endif 510 511 512 #ifdef PROFTIMER 513 /* 514 * This code allows the amiga kernel to use one of the extra timers on 515 * the clock chip for profiling, instead of the regular system timer. 516 * The advantage of this is that the profiling timer can be turned up to 517 * a higher interrupt rate, giving finer resolution timing. The profclock 518 * routine is called from the lev6intr in locore, and is a specialized 519 * routine that calls addupc. The overhead then is far less than if 520 * hardclock/softclock was called. Further, the context switch code in 521 * locore has been changed to turn the profile clock on/off when switching 522 * into/out of a process that is profiling (startprofclock/stopprofclock). 523 * This reduces the impact of the profiling clock on other users, and might 524 * possibly increase the accuracy of the profiling. 525 */ 526 int profint = PRF_INTERVAL; /* Clock ticks between interrupts */ 527 int profscale = 0; /* Scale factor from sys clock to prof clock */ 528 char profon = 0; /* Is profiling clock on? */ 529 530 /* profon values - do not change, locore.s assumes these values */ 531 #define PRF_NONE 0x00 532 #define PRF_USER 0x01 533 #define PRF_KERNEL 0x80 534 535 initprofclock() 536 { 537 #if NCLOCK > 0 538 struct proc *p = curproc; /* XXX */ 539 540 /* 541 * If the high-res timer is running, force profiling off. 542 * Unfortunately, this gets reflected back to the user not as 543 * an error but as a lack of results. 544 */ 545 if (clockon) { 546 p->p_stats->p_prof.pr_scale = 0; 547 return; 548 } 549 /* 550 * Keep track of the number of user processes that are profiling 551 * by checking the scale value. 552 * 553 * XXX: this all assumes that the profiling code is well behaved; 554 * i.e. profil() is called once per process with pcscale non-zero 555 * to turn it on, and once with pcscale zero to turn it off. 556 * Also assumes you don't do any forks or execs. Oh well, there 557 * is always adb... 558 */ 559 if (p->p_stats->p_prof.pr_scale) 560 profprocs++; 561 else 562 profprocs--; 563 #endif 564 /* 565 * The profile interrupt interval must be an even divisor 566 * of the CLK_INTERVAL so that scaling from a system clock 567 * tick to a profile clock tick is possible using integer math. 568 */ 569 if (profint > CLK_INTERVAL || (CLK_INTERVAL % profint) != 0) 570 profint = CLK_INTERVAL; 571 profscale = CLK_INTERVAL / profint; 572 } 573 574 startprofclock() 575 { 576 unsigned short interval; 577 578 /* stop timer B */ 579 clockcia->crb = clockcia->crb & 0xc0; 580 581 /* load interval into registers. 582 the clocks run at NTSC: 715.909kHz or PAL: 709.379kHz */ 583 584 interval = profint - 1; 585 586 /* order of setting is important ! */ 587 clockcia->tblo = interval & 0xff; 588 clockcia->tbhi = interval >> 8; 589 590 /* enable interrupts for timer B */ 591 clockcia->icr = (1<<7) | (1<<1); 592 593 /* start timer B in continuous shot mode */ 594 clockcia->crb = (clockcia->crb & 0xc0) | 1; 595 } 596 597 stopprofclock() 598 { 599 /* stop timer B */ 600 clockcia->crb = clockcia->crb & 0xc0; 601 } 602 603 #ifdef PROF 604 /* 605 * profclock() is expanded in line in lev6intr() unless profiling kernel. 606 * Assumes it is called with clock interrupts blocked. 607 */ 608 profclock(pc, ps) 609 caddr_t pc; 610 int ps; 611 { 612 /* 613 * Came from user mode. 614 * If this process is being profiled record the tick. 615 */ 616 if (USERMODE(ps)) { 617 if (p->p_stats.p_prof.pr_scale) 618 addupc(pc, &curproc->p_stats.p_prof, 1); 619 } 620 /* 621 * Came from kernel (supervisor) mode. 622 * If we are profiling the kernel, record the tick. 623 */ 624 else if (profiling < 2) { 625 register int s = pc - s_lowpc; 626 627 if (s < s_textsize) 628 kcount[s / (HISTFRACTION * sizeof (*kcount))]++; 629 } 630 /* 631 * Kernel profiling was on but has been disabled. 632 * Mark as no longer profiling kernel and if all profiling done, 633 * disable the clock. 634 */ 635 if (profiling && (profon & PRF_KERNEL)) { 636 profon &= ~PRF_KERNEL; 637 if (profon == PRF_NONE) 638 stopprofclock(); 639 } 640 } 641 #endif 642 #endif 643 644 /* 645 * Initialize the time of day register, based on the time base which is, e.g. 646 * from a filesystem. 647 */ 648 void 649 inittodr(base) 650 time_t base; 651 { 652 struct timeval tvbuf; 653 654 tvbuf.tv_usec = 0; 655 tvbuf.tv_sec = base; /* assume no battery clock exists */ 656 657 if (ugettod == NULL) 658 printf("WARNING: no battery clock\n"); 659 else { 660 ugettod(&tvbuf); 661 tvbuf.tv_sec += rtc_offset * 60; 662 } 663 664 if (tvbuf.tv_sec < base) { 665 printf("WARNING: bad date in battery clock\n"); 666 tvbuf.tv_sec = base; 667 } 668 669 time = tvbuf; 670 } 671 672 void 673 resettodr() 674 { 675 struct timeval tvbuf; 676 677 if (!usettod) 678 return; 679 680 tvbuf = time; 681 682 tvbuf.tv_sec -= rtc_offset * 60; 683 684 if (!usettod(&tvbuf)) 685 printf("Cannot set battery backed clock\n"); 686 } 687