1 /* $NetBSD: clock.c,v 1.30 2005/12/11 12:19:27 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1982, 1990, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * the Systems Programming Group of the University of Utah Computer 9 * Science Department. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * from: Utah Hdr: clock.c 1.18 91/01/21$ 36 * from: @(#)clock.c 8.2 (Berkeley) 1/12/94 37 */ 38 39 /* 40 * Copyright (c) 1994 Gordon W. Ross 41 * Copyright (c) 1993 Adam Glass 42 * Copyright (c) 1988 University of Utah. 43 * 44 * This code is derived from software contributed to Berkeley by 45 * the Systems Programming Group of the University of Utah Computer 46 * Science Department. 47 * 48 * Redistribution and use in source and binary forms, with or without 49 * modification, are permitted provided that the following conditions 50 * are met: 51 * 1. Redistributions of source code must retain the above copyright 52 * notice, this list of conditions and the following disclaimer. 53 * 2. Redistributions in binary form must reproduce the above copyright 54 * notice, this list of conditions and the following disclaimer in the 55 * documentation and/or other materials provided with the distribution. 56 * 3. All advertising materials mentioning features or use of this software 57 * must display the following acknowledgement: 58 * This product includes software developed by the University of 59 * California, Berkeley and its contributors. 60 * 4. Neither the name of the University nor the names of its contributors 61 * may be used to endorse or promote products derived from this software 62 * without specific prior written permission. 63 * 64 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 65 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 66 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 67 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 68 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 69 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 70 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 71 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 72 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 73 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 74 * SUCH DAMAGE. 75 * 76 * from: Utah Hdr: clock.c 1.18 91/01/21$ 77 * from: @(#)clock.c 8.2 (Berkeley) 1/12/94 78 */ 79 80 /* 81 * Machine-dependent clock routines. Sun3X machines may have 82 * either the Mostek 48T02 or the Intersil 7170 clock. 83 * 84 * It is tricky to determine which you have, because there is 85 * always something responding at the address where the Mostek 86 * clock might be found: either a Mostek or plain-old EEPROM. 87 * Therefore, we cheat. If we find an Intersil clock, assume 88 * that what responds at the end of the EEPROM space is just 89 * plain-old EEPROM (not a Mostek clock). Worse, there are 90 * H/W problems with probing for an Intersil on the 3/80, so 91 * on that machine we "know" there is a Mostek clock. 92 * 93 * Note that the probing algorithm described above requires 94 * that we probe the intersil before we probe the mostek! 95 */ 96 97 #include <sys/cdefs.h> 98 __KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.30 2005/12/11 12:19:27 christos Exp $"); 99 100 #include <sys/param.h> 101 #include <sys/systm.h> 102 #include <sys/time.h> 103 #include <sys/kernel.h> 104 #include <sys/device.h> 105 106 #include <uvm/uvm_extern.h> 107 108 #include <m68k/asm_single.h> 109 110 #include <machine/autoconf.h> 111 #include <machine/cpu.h> 112 #include <machine/idprom.h> 113 #include <machine/leds.h> 114 115 #include <dev/clock_subr.h> 116 #include <dev/ic/intersil7170.h> 117 118 #include <sun3/sun3/machdep.h> 119 #include <sun3/sun3/interreg.h> 120 121 #include <sun3/sun3x/mk48t02.h> 122 123 extern int intrcnt[]; 124 125 #define SUN3_470 Yes 126 127 #define CLOCK_PRI 5 128 #define IREG_CLK_BITS (IREG_CLOCK_ENAB_7 | IREG_CLOCK_ENAB_5) 129 130 /* 131 * Only one of these two variables should be non-zero after 132 * autoconfiguration determines which clock we have. 133 */ 134 static volatile void *intersil_va; 135 static volatile void *mostek_clk_va; 136 137 void _isr_clock(void); /* in locore.s */ 138 void clock_intr(struct clockframe); 139 140 141 static int clock_match(struct device *, struct cfdata *, void *); 142 static void clock_attach(struct device *, struct device *, void *); 143 144 CFATTACH_DECL(clock, sizeof(struct device), 145 clock_match, clock_attach, NULL, NULL); 146 147 #ifdef SUN3_470 148 149 #define intersil_clock ((volatile struct intersil7170 *) intersil_va) 150 151 #define intersil_command(run, interrupt) \ 152 (run | interrupt | INTERSIL_CMD_FREQ_32K | INTERSIL_CMD_24HR_MODE | \ 153 INTERSIL_CMD_NORMAL_MODE) 154 155 #define intersil_clear() (void)intersil_clock->clk_intr_reg 156 157 static int oclock_match(struct device *, struct cfdata *, void *); 158 static void oclock_attach(struct device *, struct device *, void *); 159 160 CFATTACH_DECL(oclock, sizeof(struct device), 161 oclock_match, oclock_attach, NULL, NULL); 162 163 /* 164 * Is there an intersil clock? 165 */ 166 static int 167 oclock_match(struct device *parent, struct cfdata *cf, void *args) 168 { 169 struct confargs *ca = args; 170 171 /* This driver only supports one unit. */ 172 if (intersil_va) 173 return (0); 174 175 /* 176 * The 3/80 can not probe the Intersil absent, 177 * but it never has one, so "just say no." 178 */ 179 if (cpu_machine_id == ID_SUN3X_80) 180 return (0); 181 182 /* OK, really probe for the Intersil. */ 183 if (bus_peek(ca->ca_bustype, ca->ca_paddr, 1) == -1) 184 return (0); 185 186 /* Default interrupt priority. */ 187 if (ca->ca_intpri == -1) 188 ca->ca_intpri = CLOCK_PRI; 189 190 return (1); 191 } 192 193 /* 194 * Attach the intersil clock. 195 */ 196 static void 197 oclock_attach(struct device *parent, struct device *self, void *args) 198 { 199 struct confargs *ca = args; 200 caddr_t va; 201 202 printf("\n"); 203 204 /* Get a mapping for it. */ 205 va = bus_mapin(ca->ca_bustype, 206 ca->ca_paddr, sizeof(struct intersil7170)); 207 if (!va) 208 panic("oclock_attach"); 209 intersil_va = va; 210 211 #ifdef DIAGNOSTIC 212 /* Verify correct probe order... */ 213 if (mostek_clk_va) { 214 mostek_clk_va = 0; 215 printf("%s: warning - mostek found also!\n", self->dv_xname); 216 } 217 #endif 218 219 /* 220 * Set the clock to the correct interrupt rate, but 221 * do not enable the interrupt until cpu_initclocks. 222 * XXX: Actually, the interrupt_reg should be zero 223 * at this point, so the clock interrupts should not 224 * affect us, but we need to set the rate... 225 */ 226 intersil_clock->clk_cmd_reg = 227 intersil_command(INTERSIL_CMD_RUN, INTERSIL_CMD_IDISABLE); 228 intersil_clear(); 229 230 /* Set the clock to 100 Hz, but do not enable it yet. */ 231 intersil_clock->clk_intr_reg = INTERSIL_INTER_CSECONDS; 232 233 /* 234 * Can not hook up the ISR until cpu_initclocks() 235 * because hardclock is not ready until then. 236 * For now, the handler is _isr_autovec(), which 237 * will complain if it gets clock interrupts. 238 */ 239 } 240 #endif /* SUN3_470 */ 241 242 243 /* 244 * Is there a Mostek clock? Hard to tell... 245 * (See comment at top of this file.) 246 */ 247 static int 248 clock_match(struct device *parent, struct cfdata *cf, void *args) 249 { 250 struct confargs *ca = args; 251 252 /* This driver only supports one unit. */ 253 if (mostek_clk_va) 254 return (0); 255 256 /* If intersil was found, use that. */ 257 if (intersil_va) 258 return (0); 259 /* Else assume a Mostek is there... */ 260 261 /* Default interrupt priority. */ 262 if (ca->ca_intpri == -1) 263 ca->ca_intpri = CLOCK_PRI; 264 265 return (1); 266 } 267 268 /* 269 * Attach the mostek clock. 270 */ 271 static void 272 clock_attach(struct device *parent, struct device *self, void *args) 273 { 274 struct confargs *ca = args; 275 caddr_t va; 276 277 printf("\n"); 278 279 /* Get a mapping for it. */ 280 va = bus_mapin(ca->ca_bustype, 281 ca->ca_paddr, sizeof(struct mostek_clkreg)); 282 if (!va) 283 panic("clock_attach"); 284 mostek_clk_va = va; 285 286 /* 287 * Can not hook up the ISR until cpu_initclocks() 288 * because hardclock is not ready until then. 289 * For now, the handler is _isr_autovec(), which 290 * will complain if it gets clock interrupts. 291 */ 292 } 293 294 /* 295 * Set and/or clear the desired clock bits in the interrupt 296 * register. We have to be extremely careful that we do it 297 * in such a manner that we don't get ourselves lost. 298 * XXX: Watch out! It's really easy to break this! 299 */ 300 void 301 set_clk_mode(u_char on, u_char off, int enable_clk) 302 { 303 u_char interreg; 304 305 /* 306 * If we have not yet mapped the register, 307 * then we do not want to do any of this... 308 */ 309 if (!interrupt_reg) 310 return; 311 312 #ifdef DIAGNOSTIC 313 /* Assertion: were are at splhigh! */ 314 if ((getsr() & PSL_IPL) < PSL_IPL7) 315 panic("set_clk_mode: bad ipl"); 316 #endif 317 318 /* 319 * make sure that we are only playing w/ 320 * clock interrupt register bits 321 */ 322 on &= IREG_CLK_BITS; 323 off &= IREG_CLK_BITS; 324 325 /* First, turn off the "master" enable bit. */ 326 single_inst_bclr_b(*interrupt_reg, IREG_ALL_ENAB); 327 328 /* 329 * Save the current interrupt register clock bits, 330 * and turn off/on the requested bits in the copy. 331 */ 332 interreg = *interrupt_reg & IREG_CLK_BITS; 333 interreg &= ~off; 334 interreg |= on; 335 336 /* Clear the CLK5 and CLK7 bits to clear the flip-flops. */ 337 single_inst_bclr_b(*interrupt_reg, IREG_CLK_BITS); 338 339 #ifdef SUN3_470 340 if (intersil_va) { 341 /* 342 * Then disable clock interrupts, and read the clock's 343 * interrupt register to clear any pending signals there. 344 */ 345 intersil_clock->clk_cmd_reg = 346 intersil_command(INTERSIL_CMD_RUN, INTERSIL_CMD_IDISABLE); 347 intersil_clear(); 348 } 349 #endif /* SUN3_470 */ 350 351 /* Set the requested bits in the interrupt register. */ 352 single_inst_bset_b(*interrupt_reg, interreg); 353 354 #ifdef SUN3_470 355 /* Turn the clock back on (maybe) */ 356 if (intersil_va && enable_clk) 357 intersil_clock->clk_cmd_reg = 358 intersil_command(INTERSIL_CMD_RUN, INTERSIL_CMD_IENABLE); 359 #endif /* SUN3_470 */ 360 361 /* Finally, turn the "master" enable back on. */ 362 single_inst_bset_b(*interrupt_reg, IREG_ALL_ENAB); 363 } 364 365 /* 366 * Set up the real-time clock (enable clock interrupts). 367 * Leave stathz 0 since there is no secondary clock available. 368 * Note that clock interrupts MUST STAY DISABLED until here. 369 */ 370 void 371 cpu_initclocks(void) 372 { 373 int s; 374 375 s = splhigh(); 376 377 /* Install isr (in locore.s) that calls clock_intr(). */ 378 isr_add_custom(CLOCK_PRI, (void *)_isr_clock); 379 380 /* Now enable the clock at level 5 in the interrupt reg. */ 381 set_clk_mode(IREG_CLOCK_ENAB_5, 0, 1); 382 383 splx(s); 384 } 385 386 /* 387 * This doesn't need to do anything, as we have only one timer and 388 * profhz==stathz==hz. 389 */ 390 void 391 setstatclockrate(int newhz) 392 { 393 394 /* nothing */ 395 } 396 397 /* 398 * Clock interrupt handler (for both Intersil and Mostek). 399 * XXX - Is it worth the trouble to save a few cycles here 400 * by making two separate interrupt handlers? 401 * 402 * This is is called by the "custom" interrupt handler. 403 * Note that we can get ZS interrupts while this runs, 404 * and zshard may touch the interrupt_reg, so we must 405 * be careful to use the single_inst_* macros to modify 406 * the interrupt register atomically. 407 */ 408 void 409 clock_intr(struct clockframe cf) 410 { 411 extern char _Idle[]; /* locore.s */ 412 413 #ifdef SUN3_470 414 if (intersil_va) { 415 /* Read the clock interrupt register. */ 416 intersil_clear(); 417 } 418 #endif /* SUN3_470 */ 419 420 /* Pulse the clock intr. enable low. */ 421 single_inst_bclr_b(*interrupt_reg, IREG_CLOCK_ENAB_5); 422 single_inst_bset_b(*interrupt_reg, IREG_CLOCK_ENAB_5); 423 424 #ifdef SUN3_470 425 if (intersil_va) { 426 /* Read the clock intr. reg. AGAIN! */ 427 intersil_clear(); 428 } 429 #endif /* SUN3_470 */ 430 431 intrcnt[CLOCK_PRI]++; 432 uvmexp.intrs++; 433 434 /* Entertainment! */ 435 if (cf.cf_pc == (long)_Idle) 436 leds_intr(); 437 438 /* Call common clock interrupt handler. */ 439 hardclock(&cf); 440 } 441 442 443 /* 444 * Return the best possible estimate of the time in the timeval 445 * to which tvp points. We do this by returning the current time 446 * plus the amount of time since the last clock interrupt. 447 * 448 * Check that this time is no less than any previously-reported time, 449 * which could happen around the time of a clock adjustment. Just for 450 * fun, we guarantee that the time will be greater than the value 451 * obtained by a previous call. 452 */ 453 void 454 microtime(struct timeval *tvp) 455 { 456 int s; 457 static struct timeval lasttime; 458 459 s = splhigh(); 460 *tvp = time; 461 tvp->tv_usec++; /* XXX */ 462 while (tvp->tv_usec >= 1000000) { 463 tvp->tv_sec++; 464 tvp->tv_usec -= 1000000; 465 } 466 if (tvp->tv_sec == lasttime.tv_sec && 467 tvp->tv_usec <= lasttime.tv_usec && 468 (tvp->tv_usec = lasttime.tv_usec + 1) >= 1000000) { 469 tvp->tv_sec++; 470 tvp->tv_usec -= 1000000; 471 } 472 lasttime = *tvp; 473 splx(s); 474 } 475 476 477 /* 478 * Machine-dependent clock routines. 479 * 480 * Inittodr initializes the time of day hardware which provides 481 * date functions. 482 * 483 * Resettodr restores the time of day hardware after a time change. 484 */ 485 486 static long clk_get_secs(void); 487 static void clk_set_secs(long); 488 489 /* 490 * Initialize the time of day register, based on the time base 491 * which is, e.g. from a filesystem. 492 */ 493 void 494 inittodr(time_t fs_time) 495 { 496 long diff, clk_time; 497 long long_ago = (5 * SECYR); 498 int clk_bad = 0; 499 500 /* 501 * Sanity check time from file system. 502 * If it is zero,assume filesystem time is just unknown 503 * instead of preposterous. Don't bark. 504 */ 505 if (fs_time < long_ago) { 506 /* 507 * If fs_time is zero, assume filesystem time is just 508 * unknown instead of preposterous. Don't bark. 509 */ 510 if (fs_time != 0) 511 printf("WARNING: preposterous time in file system\n"); 512 /* 1991/07/01 12:00:00 */ 513 fs_time = 21 * SECYR + 186 * SECDAY + SECDAY / 2; 514 } 515 516 clk_time = clk_get_secs(); 517 518 /* Sanity check time from clock. */ 519 if (clk_time < long_ago) { 520 printf("WARNING: bad date in battery clock"); 521 clk_bad = 1; 522 clk_time = fs_time; 523 } else { 524 /* Does the clock time jive with the file system? */ 525 diff = clk_time - fs_time; 526 if (diff < 0) 527 diff = -diff; 528 if (diff >= (SECDAY*2)) { 529 printf("WARNING: clock %s %d days", 530 (clk_time < fs_time) ? "lost" : "gained", 531 (int) (diff / SECDAY)); 532 clk_bad = 1; 533 } 534 } 535 if (clk_bad) 536 printf(" -- CHECK AND RESET THE DATE!\n"); 537 time.tv_sec = clk_time; 538 } 539 540 /* 541 * Resettodr restores the time of day hardware after a time change. 542 */ 543 void 544 resettodr(void) 545 { 546 547 clk_set_secs(time.tv_sec); 548 } 549 550 551 /* 552 * Now routines to get and set clock as POSIX time. 553 * Our clock keeps "years since 1/1/1968". 554 */ 555 #define CLOCK_BASE_YEAR 1968 556 #ifdef SUN3_470 557 static void intersil_get_dt(struct clock_ymdhms *); 558 static void intersil_set_dt(struct clock_ymdhms *); 559 #endif /* SUN3_470 */ 560 static void mostek_get_dt(struct clock_ymdhms *); 561 static void mostek_set_dt(struct clock_ymdhms *); 562 563 static long 564 clk_get_secs(void) 565 { 566 struct clock_ymdhms dt; 567 long secs; 568 569 memset(&dt, 0, sizeof(dt)); 570 571 #ifdef SUN3_470 572 if (intersil_va) 573 intersil_get_dt(&dt); 574 #endif /* SUN3_470 */ 575 if (mostek_clk_va) { 576 /* Read the Mostek. */ 577 mostek_get_dt(&dt); 578 /* Convert BCD values to binary. */ 579 dt.dt_sec = FROMBCD(dt.dt_sec); 580 dt.dt_min = FROMBCD(dt.dt_min); 581 dt.dt_hour = FROMBCD(dt.dt_hour); 582 dt.dt_day = FROMBCD(dt.dt_day); 583 dt.dt_mon = FROMBCD(dt.dt_mon); 584 dt.dt_year = FROMBCD(dt.dt_year); 585 } 586 587 if ((dt.dt_hour > 24) || 588 (dt.dt_day > 31) || 589 (dt.dt_mon > 12)) 590 return (0); 591 592 dt.dt_year += CLOCK_BASE_YEAR; 593 secs = clock_ymdhms_to_secs(&dt); 594 return (secs); 595 } 596 597 static void 598 clk_set_secs(long secs) 599 { 600 struct clock_ymdhms dt; 601 602 clock_secs_to_ymdhms(secs, &dt); 603 dt.dt_year -= CLOCK_BASE_YEAR; 604 605 #ifdef SUN3_470 606 if (intersil_va) 607 intersil_set_dt(&dt); 608 #endif /* SUN3_470 */ 609 610 if (mostek_clk_va) { 611 /* Convert binary values to BCD. */ 612 dt.dt_sec = TOBCD(dt.dt_sec); 613 dt.dt_min = TOBCD(dt.dt_min); 614 dt.dt_hour = TOBCD(dt.dt_hour); 615 dt.dt_day = TOBCD(dt.dt_day); 616 dt.dt_mon = TOBCD(dt.dt_mon); 617 dt.dt_year = TOBCD(dt.dt_year); 618 /* Write the Mostek. */ 619 mostek_set_dt(&dt); 620 } 621 } 622 623 #ifdef SUN3_470 624 625 /* 626 * Routines to copy state into and out of the clock. 627 * The intersil registers have to be read or written 628 * in sequential order (or so it appears). -gwr 629 */ 630 static void 631 intersil_get_dt(struct clock_ymdhms *dt) 632 { 633 volatile struct intersil_dt *isdt; 634 int s; 635 636 isdt = &intersil_clock->counters; 637 s = splhigh(); 638 639 /* Enable read (stop time) */ 640 intersil_clock->clk_cmd_reg = 641 intersil_command(INTERSIL_CMD_STOP, INTERSIL_CMD_IENABLE); 642 643 /* Copy the info. Careful about the order! */ 644 dt->dt_sec = isdt->dt_csec; /* throw-away */ 645 dt->dt_hour = isdt->dt_hour; 646 dt->dt_min = isdt->dt_min; 647 dt->dt_sec = isdt->dt_sec; 648 dt->dt_mon = isdt->dt_month; 649 dt->dt_day = isdt->dt_day; 650 dt->dt_year = isdt->dt_year; 651 dt->dt_wday = isdt->dt_dow; 652 653 /* Done reading (time wears on) */ 654 intersil_clock->clk_cmd_reg = 655 intersil_command(INTERSIL_CMD_RUN, INTERSIL_CMD_IENABLE); 656 splx(s); 657 } 658 659 static void 660 intersil_set_dt(struct clock_ymdhms *dt) 661 { 662 volatile struct intersil_dt *isdt; 663 int s; 664 665 isdt = &intersil_clock->counters; 666 s = splhigh(); 667 668 /* Enable write (stop time) */ 669 intersil_clock->clk_cmd_reg = 670 intersil_command(INTERSIL_CMD_STOP, INTERSIL_CMD_IENABLE); 671 672 /* Copy the info. Careful about the order! */ 673 isdt->dt_csec = 0; 674 isdt->dt_hour = dt->dt_hour; 675 isdt->dt_min = dt->dt_min; 676 isdt->dt_sec = dt->dt_sec; 677 isdt->dt_month= dt->dt_mon; 678 isdt->dt_day = dt->dt_day; 679 isdt->dt_year = dt->dt_year; 680 isdt->dt_dow = dt->dt_wday; 681 682 /* Done writing (time wears on) */ 683 intersil_clock->clk_cmd_reg = 684 intersil_command(INTERSIL_CMD_RUN, INTERSIL_CMD_IENABLE); 685 splx(s); 686 } 687 688 #endif /* SUN3_470 */ 689 690 691 /* 692 * Routines to copy state into and out of the clock. 693 * The clock CSR has to be set for read or write. 694 */ 695 static void 696 mostek_get_dt(struct clock_ymdhms *dt) 697 { 698 volatile struct mostek_clkreg *cl = mostek_clk_va; 699 int s; 700 701 s = splhigh(); 702 703 /* enable read (stop time) */ 704 cl->cl_csr |= CLK_READ; 705 706 /* Copy the info */ 707 dt->dt_sec = cl->cl_sec; 708 dt->dt_min = cl->cl_min; 709 dt->dt_hour = cl->cl_hour; 710 dt->dt_wday = cl->cl_wday; 711 dt->dt_day = cl->cl_mday; 712 dt->dt_mon = cl->cl_month; 713 dt->dt_year = cl->cl_year; 714 715 /* Done reading (time wears on) */ 716 cl->cl_csr &= ~CLK_READ; 717 splx(s); 718 } 719 720 static void 721 mostek_set_dt(struct clock_ymdhms *dt) 722 { 723 volatile struct mostek_clkreg *cl = mostek_clk_va; 724 int s; 725 726 s = splhigh(); 727 /* enable write */ 728 cl->cl_csr |= CLK_WRITE; 729 730 /* Copy the info */ 731 cl->cl_sec = dt->dt_sec; 732 cl->cl_min = dt->dt_min; 733 cl->cl_hour = dt->dt_hour; 734 cl->cl_wday = dt->dt_wday; 735 cl->cl_mday = dt->dt_day; 736 cl->cl_month = dt->dt_mon; 737 cl->cl_year = dt->dt_year; 738 739 /* load them up */ 740 cl->cl_csr &= ~CLK_WRITE; 741 splx(s); 742 } 743 744