1 /* $NetBSD: clock.c,v 1.27 2003/09/22 17:53:47 tsutsui 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.27 2003/09/22 17:53:47 tsutsui 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 __P((void)); /* in locore.s */ 138 void clock_intr __P((struct clockframe)); 139 140 141 static int clock_match __P((struct device *, struct cfdata *, void *args)); 142 static void clock_attach __P((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 __P((struct device *, struct cfdata *, void *args)); 158 static void oclock_attach __P((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(parent, cf, args) 168 struct device *parent; 169 struct cfdata *cf; 170 void *args; 171 { 172 struct confargs *ca = args; 173 174 /* This driver only supports one unit. */ 175 if (intersil_va) 176 return (0); 177 178 /* 179 * The 3/80 can not probe the Intersil absent, 180 * but it never has one, so "just say no." 181 */ 182 if (cpu_machine_id == SUN3X_MACH_80) 183 return (0); 184 185 /* OK, really probe for the Intersil. */ 186 if (bus_peek(ca->ca_bustype, ca->ca_paddr, 1) == -1) 187 return (0); 188 189 /* Default interrupt priority. */ 190 if (ca->ca_intpri == -1) 191 ca->ca_intpri = CLOCK_PRI; 192 193 return (1); 194 } 195 196 /* 197 * Attach the intersil clock. 198 */ 199 static void 200 oclock_attach(parent, self, args) 201 struct device *parent; 202 struct device *self; 203 void *args; 204 { 205 struct confargs *ca = args; 206 caddr_t va; 207 208 printf("\n"); 209 210 /* Get a mapping for it. */ 211 va = bus_mapin(ca->ca_bustype, 212 ca->ca_paddr, sizeof(struct intersil7170)); 213 if (!va) 214 panic("oclock_attach"); 215 intersil_va = va; 216 217 #ifdef DIAGNOSTIC 218 /* Verify correct probe order... */ 219 if (mostek_clk_va) { 220 mostek_clk_va = 0; 221 printf("%s: warning - mostek found also!\n", self->dv_xname); 222 } 223 #endif 224 225 /* 226 * Set the clock to the correct interrupt rate, but 227 * do not enable the interrupt until cpu_initclocks. 228 * XXX: Actually, the interrupt_reg should be zero 229 * at this point, so the clock interrupts should not 230 * affect us, but we need to set the rate... 231 */ 232 intersil_clock->clk_cmd_reg = 233 intersil_command(INTERSIL_CMD_RUN, INTERSIL_CMD_IDISABLE); 234 intersil_clear(); 235 236 /* Set the clock to 100 Hz, but do not enable it yet. */ 237 intersil_clock->clk_intr_reg = INTERSIL_INTER_CSECONDS; 238 239 /* 240 * Can not hook up the ISR until cpu_initclocks() 241 * because hardclock is not ready until then. 242 * For now, the handler is _isr_autovec(), which 243 * will complain if it gets clock interrupts. 244 */ 245 } 246 #endif /* SUN3_470 */ 247 248 249 /* 250 * Is there a Mostek clock? Hard to tell... 251 * (See comment at top of this file.) 252 */ 253 static int 254 clock_match(parent, cf, args) 255 struct device *parent; 256 struct cfdata *cf; 257 void *args; 258 { 259 struct confargs *ca = args; 260 261 /* This driver only supports one unit. */ 262 if (mostek_clk_va) 263 return (0); 264 265 /* If intersil was found, use that. */ 266 if (intersil_va) 267 return (0); 268 /* Else assume a Mostek is there... */ 269 270 /* Default interrupt priority. */ 271 if (ca->ca_intpri == -1) 272 ca->ca_intpri = CLOCK_PRI; 273 274 return (1); 275 } 276 277 /* 278 * Attach the mostek clock. 279 */ 280 static void 281 clock_attach(parent, self, args) 282 struct device *parent; 283 struct device *self; 284 void *args; 285 { 286 struct confargs *ca = args; 287 caddr_t va; 288 289 printf("\n"); 290 291 /* Get a mapping for it. */ 292 va = bus_mapin(ca->ca_bustype, 293 ca->ca_paddr, sizeof(struct mostek_clkreg)); 294 if (!va) 295 panic("clock_attach"); 296 mostek_clk_va = va; 297 298 /* 299 * Can not hook up the ISR until cpu_initclocks() 300 * because hardclock is not ready until then. 301 * For now, the handler is _isr_autovec(), which 302 * will complain if it gets clock interrupts. 303 */ 304 } 305 306 /* 307 * Set and/or clear the desired clock bits in the interrupt 308 * register. We have to be extremely careful that we do it 309 * in such a manner that we don't get ourselves lost. 310 * XXX: Watch out! It's really easy to break this! 311 */ 312 void 313 set_clk_mode(on, off, enable_clk) 314 u_char on, off; 315 int enable_clk; 316 { 317 u_char interreg; 318 319 /* 320 * If we have not yet mapped the register, 321 * then we do not want to do any of this... 322 */ 323 if (!interrupt_reg) 324 return; 325 326 #ifdef DIAGNOSTIC 327 /* Assertion: were are at splhigh! */ 328 if ((getsr() & PSL_IPL) < PSL_IPL7) 329 panic("set_clk_mode: bad ipl"); 330 #endif 331 332 /* 333 * make sure that we are only playing w/ 334 * clock interrupt register bits 335 */ 336 on &= IREG_CLK_BITS; 337 off &= IREG_CLK_BITS; 338 339 /* First, turn off the "master" enable bit. */ 340 single_inst_bclr_b(*interrupt_reg, IREG_ALL_ENAB); 341 342 /* 343 * Save the current interrupt register clock bits, 344 * and turn off/on the requested bits in the copy. 345 */ 346 interreg = *interrupt_reg & IREG_CLK_BITS; 347 interreg &= ~off; 348 interreg |= on; 349 350 /* Clear the CLK5 and CLK7 bits to clear the flip-flops. */ 351 single_inst_bclr_b(*interrupt_reg, IREG_CLK_BITS); 352 353 #ifdef SUN3_470 354 if (intersil_va) { 355 /* 356 * Then disable clock interrupts, and read the clock's 357 * interrupt register to clear any pending signals there. 358 */ 359 intersil_clock->clk_cmd_reg = 360 intersil_command(INTERSIL_CMD_RUN, INTERSIL_CMD_IDISABLE); 361 intersil_clear(); 362 } 363 #endif /* SUN3_470 */ 364 365 /* Set the requested bits in the interrupt register. */ 366 single_inst_bset_b(*interrupt_reg, interreg); 367 368 #ifdef SUN3_470 369 /* Turn the clock back on (maybe) */ 370 if (intersil_va && enable_clk) 371 intersil_clock->clk_cmd_reg = 372 intersil_command(INTERSIL_CMD_RUN, INTERSIL_CMD_IENABLE); 373 #endif /* SUN3_470 */ 374 375 /* Finally, turn the "master" enable back on. */ 376 single_inst_bset_b(*interrupt_reg, IREG_ALL_ENAB); 377 } 378 379 /* 380 * Set up the real-time clock (enable clock interrupts). 381 * Leave stathz 0 since there is no secondary clock available. 382 * Note that clock interrupts MUST STAY DISABLED until here. 383 */ 384 void 385 cpu_initclocks(void) 386 { 387 int s; 388 389 s = splhigh(); 390 391 /* Install isr (in locore.s) that calls clock_intr(). */ 392 isr_add_custom(CLOCK_PRI, (void *)_isr_clock); 393 394 /* Now enable the clock at level 5 in the interrupt reg. */ 395 set_clk_mode(IREG_CLOCK_ENAB_5, 0, 1); 396 397 splx(s); 398 } 399 400 /* 401 * This doesn't need to do anything, as we have only one timer and 402 * profhz==stathz==hz. 403 */ 404 void 405 setstatclockrate(newhz) 406 int newhz; 407 { 408 409 /* nothing */ 410 } 411 412 /* 413 * Clock interrupt handler (for both Intersil and Mostek). 414 * XXX - Is it worth the trouble to save a few cycles here 415 * by making two separate interrupt handlers? 416 * 417 * This is is called by the "custom" interrupt handler. 418 * Note that we can get ZS interrupts while this runs, 419 * and zshard may touch the interrupt_reg, so we must 420 * be careful to use the single_inst_* macros to modify 421 * the interrupt register atomically. 422 */ 423 void 424 clock_intr(cf) 425 struct clockframe cf; 426 { 427 extern char _Idle[]; /* locore.s */ 428 429 #ifdef SUN3_470 430 if (intersil_va) { 431 /* Read the clock interrupt register. */ 432 intersil_clear(); 433 } 434 #endif /* SUN3_470 */ 435 436 /* Pulse the clock intr. enable low. */ 437 single_inst_bclr_b(*interrupt_reg, IREG_CLOCK_ENAB_5); 438 single_inst_bset_b(*interrupt_reg, IREG_CLOCK_ENAB_5); 439 440 #ifdef SUN3_470 441 if (intersil_va) { 442 /* Read the clock intr. reg. AGAIN! */ 443 intersil_clear(); 444 } 445 #endif /* SUN3_470 */ 446 447 intrcnt[CLOCK_PRI]++; 448 uvmexp.intrs++; 449 450 /* Entertainment! */ 451 if (cf.cf_pc == (long)_Idle) 452 leds_intr(); 453 454 /* Call common clock interrupt handler. */ 455 hardclock(&cf); 456 } 457 458 459 /* 460 * Return the best possible estimate of the time in the timeval 461 * to which tvp points. We do this by returning the current time 462 * plus the amount of time since the last clock interrupt. 463 * 464 * Check that this time is no less than any previously-reported time, 465 * which could happen around the time of a clock adjustment. Just for 466 * fun, we guarantee that the time will be greater than the value 467 * obtained by a previous call. 468 */ 469 void 470 microtime(tvp) 471 struct timeval *tvp; 472 { 473 int s; 474 static struct timeval lasttime; 475 476 s = splhigh(); 477 *tvp = time; 478 tvp->tv_usec++; /* XXX */ 479 while (tvp->tv_usec >= 1000000) { 480 tvp->tv_sec++; 481 tvp->tv_usec -= 1000000; 482 } 483 if (tvp->tv_sec == lasttime.tv_sec && 484 tvp->tv_usec <= lasttime.tv_usec && 485 (tvp->tv_usec = lasttime.tv_usec + 1) >= 1000000) { 486 tvp->tv_sec++; 487 tvp->tv_usec -= 1000000; 488 } 489 lasttime = *tvp; 490 splx(s); 491 } 492 493 494 /* 495 * Machine-dependent clock routines. 496 * 497 * Inittodr initializes the time of day hardware which provides 498 * date functions. 499 * 500 * Resettodr restores the time of day hardware after a time change. 501 */ 502 503 static long clk_get_secs __P((void)); 504 static void clk_set_secs __P((long)); 505 506 /* 507 * Initialize the time of day register, based on the time base 508 * which is, e.g. from a filesystem. 509 */ 510 void inittodr(fs_time) 511 time_t fs_time; 512 { 513 long diff, clk_time; 514 long long_ago = (5 * SECYR); 515 int clk_bad = 0; 516 517 /* 518 * Sanity check time from file system. 519 * If it is zero,assume filesystem time is just unknown 520 * instead of preposterous. Don't bark. 521 */ 522 if (fs_time < long_ago) { 523 /* 524 * If fs_time is zero, assume filesystem time is just 525 * unknown instead of preposterous. Don't bark. 526 */ 527 if (fs_time != 0) 528 printf("WARNING: preposterous time in file system\n"); 529 /* 1991/07/01 12:00:00 */ 530 fs_time = 21 * SECYR + 186 * SECDAY + SECDAY / 2; 531 } 532 533 clk_time = clk_get_secs(); 534 535 /* Sanity check time from clock. */ 536 if (clk_time < long_ago) { 537 printf("WARNING: bad date in battery clock"); 538 clk_bad = 1; 539 clk_time = fs_time; 540 } else { 541 /* Does the clock time jive with the file system? */ 542 diff = clk_time - fs_time; 543 if (diff < 0) 544 diff = -diff; 545 if (diff >= (SECDAY*2)) { 546 printf("WARNING: clock %s %d days", 547 (clk_time < fs_time) ? "lost" : "gained", 548 (int) (diff / SECDAY)); 549 clk_bad = 1; 550 } 551 } 552 if (clk_bad) 553 printf(" -- CHECK AND RESET THE DATE!\n"); 554 time.tv_sec = clk_time; 555 } 556 557 /* 558 * Resettodr restores the time of day hardware after a time change. 559 */ 560 void resettodr() 561 { 562 563 clk_set_secs(time.tv_sec); 564 } 565 566 567 /* 568 * Now routines to get and set clock as POSIX time. 569 * Our clock keeps "years since 1/1/1968". 570 */ 571 #define CLOCK_BASE_YEAR 1968 572 #ifdef SUN3_470 573 static void intersil_get_dt __P((struct clock_ymdhms *)); 574 static void intersil_set_dt __P((struct clock_ymdhms *)); 575 #endif /* SUN3_470 */ 576 static void mostek_get_dt __P((struct clock_ymdhms *)); 577 static void mostek_set_dt __P((struct clock_ymdhms *)); 578 579 static long 580 clk_get_secs() 581 { 582 struct clock_ymdhms dt; 583 long secs; 584 585 memset(&dt, 0, sizeof(dt)); 586 587 #ifdef SUN3_470 588 if (intersil_va) 589 intersil_get_dt(&dt); 590 #endif /* SUN3_470 */ 591 if (mostek_clk_va) { 592 /* Read the Mostek. */ 593 mostek_get_dt(&dt); 594 /* Convert BCD values to binary. */ 595 dt.dt_sec = FROMBCD(dt.dt_sec); 596 dt.dt_min = FROMBCD(dt.dt_min); 597 dt.dt_hour = FROMBCD(dt.dt_hour); 598 dt.dt_day = FROMBCD(dt.dt_day); 599 dt.dt_mon = FROMBCD(dt.dt_mon); 600 dt.dt_year = FROMBCD(dt.dt_year); 601 } 602 603 if ((dt.dt_hour > 24) || 604 (dt.dt_day > 31) || 605 (dt.dt_mon > 12)) 606 return (0); 607 608 dt.dt_year += CLOCK_BASE_YEAR; 609 secs = clock_ymdhms_to_secs(&dt); 610 return (secs); 611 } 612 613 static void 614 clk_set_secs(secs) 615 long secs; 616 { 617 struct clock_ymdhms dt; 618 619 clock_secs_to_ymdhms(secs, &dt); 620 dt.dt_year -= CLOCK_BASE_YEAR; 621 622 #ifdef SUN3_470 623 if (intersil_va) 624 intersil_set_dt(&dt); 625 #endif /* SUN3_470 */ 626 627 if (mostek_clk_va) { 628 /* Convert binary values to BCD. */ 629 dt.dt_sec = TOBCD(dt.dt_sec); 630 dt.dt_min = TOBCD(dt.dt_min); 631 dt.dt_hour = TOBCD(dt.dt_hour); 632 dt.dt_day = TOBCD(dt.dt_day); 633 dt.dt_mon = TOBCD(dt.dt_mon); 634 dt.dt_year = TOBCD(dt.dt_year); 635 /* Write the Mostek. */ 636 mostek_set_dt(&dt); 637 } 638 } 639 640 #ifdef SUN3_470 641 642 /* 643 * Routines to copy state into and out of the clock. 644 * The intersil registers have to be read or written 645 * in sequential order (or so it appears). -gwr 646 */ 647 static void 648 intersil_get_dt(struct clock_ymdhms *dt) 649 { 650 volatile struct intersil_dt *isdt; 651 int s; 652 653 isdt = &intersil_clock->counters; 654 s = splhigh(); 655 656 /* Enable read (stop time) */ 657 intersil_clock->clk_cmd_reg = 658 intersil_command(INTERSIL_CMD_STOP, INTERSIL_CMD_IENABLE); 659 660 /* Copy the info. Careful about the order! */ 661 dt->dt_sec = isdt->dt_csec; /* throw-away */ 662 dt->dt_hour = isdt->dt_hour; 663 dt->dt_min = isdt->dt_min; 664 dt->dt_sec = isdt->dt_sec; 665 dt->dt_mon = isdt->dt_month; 666 dt->dt_day = isdt->dt_day; 667 dt->dt_year = isdt->dt_year; 668 dt->dt_wday = isdt->dt_dow; 669 670 /* Done reading (time wears on) */ 671 intersil_clock->clk_cmd_reg = 672 intersil_command(INTERSIL_CMD_RUN, INTERSIL_CMD_IENABLE); 673 splx(s); 674 } 675 676 static void 677 intersil_set_dt(struct clock_ymdhms *dt) 678 { 679 volatile struct intersil_dt *isdt; 680 int s; 681 682 isdt = &intersil_clock->counters; 683 s = splhigh(); 684 685 /* Enable write (stop time) */ 686 intersil_clock->clk_cmd_reg = 687 intersil_command(INTERSIL_CMD_STOP, INTERSIL_CMD_IENABLE); 688 689 /* Copy the info. Careful about the order! */ 690 isdt->dt_csec = 0; 691 isdt->dt_hour = dt->dt_hour; 692 isdt->dt_min = dt->dt_min; 693 isdt->dt_sec = dt->dt_sec; 694 isdt->dt_month= dt->dt_mon; 695 isdt->dt_day = dt->dt_day; 696 isdt->dt_year = dt->dt_year; 697 isdt->dt_dow = dt->dt_wday; 698 699 /* Done writing (time wears on) */ 700 intersil_clock->clk_cmd_reg = 701 intersil_command(INTERSIL_CMD_RUN, INTERSIL_CMD_IENABLE); 702 splx(s); 703 } 704 705 #endif /* SUN3_470 */ 706 707 708 /* 709 * Routines to copy state into and out of the clock. 710 * The clock CSR has to be set for read or write. 711 */ 712 static void 713 mostek_get_dt(struct clock_ymdhms *dt) 714 { 715 volatile struct mostek_clkreg *cl = mostek_clk_va; 716 int s; 717 718 s = splhigh(); 719 720 /* enable read (stop time) */ 721 cl->cl_csr |= CLK_READ; 722 723 /* Copy the info */ 724 dt->dt_sec = cl->cl_sec; 725 dt->dt_min = cl->cl_min; 726 dt->dt_hour = cl->cl_hour; 727 dt->dt_wday = cl->cl_wday; 728 dt->dt_day = cl->cl_mday; 729 dt->dt_mon = cl->cl_month; 730 dt->dt_year = cl->cl_year; 731 732 /* Done reading (time wears on) */ 733 cl->cl_csr &= ~CLK_READ; 734 splx(s); 735 } 736 737 static void 738 mostek_set_dt(struct clock_ymdhms *dt) 739 { 740 volatile struct mostek_clkreg *cl = mostek_clk_va; 741 int s; 742 743 s = splhigh(); 744 /* enable write */ 745 cl->cl_csr |= CLK_WRITE; 746 747 /* Copy the info */ 748 cl->cl_sec = dt->dt_sec; 749 cl->cl_min = dt->dt_min; 750 cl->cl_hour = dt->dt_hour; 751 cl->cl_wday = dt->dt_wday; 752 cl->cl_mday = dt->dt_day; 753 cl->cl_month = dt->dt_mon; 754 cl->cl_year = dt->dt_year; 755 756 /* load them up */ 757 cl->cl_csr &= ~CLK_WRITE; 758 splx(s); 759 } 760 761