1 /* 2 * Miscellaneous Mac68K-specific stuff 3 */ 4 5 #include <linux/types.h> 6 #include <linux/errno.h> 7 #include <linux/miscdevice.h> 8 #include <linux/kernel.h> 9 #include <linux/delay.h> 10 #include <linux/sched.h> 11 #include <linux/slab.h> 12 #include <linux/time.h> 13 #include <linux/rtc.h> 14 #include <linux/mm.h> 15 16 #include <linux/adb.h> 17 #include <linux/cuda.h> 18 #include <linux/pmu.h> 19 20 #include <asm/uaccess.h> 21 #include <asm/io.h> 22 #include <asm/rtc.h> 23 #include <asm/system.h> 24 #include <asm/segment.h> 25 #include <asm/setup.h> 26 #include <asm/macintosh.h> 27 #include <asm/mac_via.h> 28 #include <asm/mac_oss.h> 29 30 #define BOOTINFO_COMPAT_1_0 31 #include <asm/bootinfo.h> 32 #include <asm/machdep.h> 33 34 /* Offset between Unix time (1970-based) and Mac time (1904-based) */ 35 36 #define RTC_OFFSET 2082844800 37 38 extern struct mac_booter_data mac_bi_data; 39 static void (*rom_reset)(void); 40 41 #ifdef CONFIG_ADB_CUDA 42 static long cuda_read_time(void) 43 { 44 struct adb_request req; 45 long time; 46 47 if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0) 48 return 0; 49 while (!req.complete) 50 cuda_poll(); 51 52 time = (req.reply[3] << 24) | (req.reply[4] << 16) 53 | (req.reply[5] << 8) | req.reply[6]; 54 return time - RTC_OFFSET; 55 } 56 57 static void cuda_write_time(long data) 58 { 59 struct adb_request req; 60 data += RTC_OFFSET; 61 if (cuda_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME, 62 (data >> 24) & 0xFF, (data >> 16) & 0xFF, 63 (data >> 8) & 0xFF, data & 0xFF) < 0) 64 return; 65 while (!req.complete) 66 cuda_poll(); 67 } 68 69 static __u8 cuda_read_pram(int offset) 70 { 71 struct adb_request req; 72 if (cuda_request(&req, NULL, 4, CUDA_PACKET, CUDA_GET_PRAM, 73 (offset >> 8) & 0xFF, offset & 0xFF) < 0) 74 return 0; 75 while (!req.complete) 76 cuda_poll(); 77 return req.reply[3]; 78 } 79 80 static void cuda_write_pram(int offset, __u8 data) 81 { 82 struct adb_request req; 83 if (cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_SET_PRAM, 84 (offset >> 8) & 0xFF, offset & 0xFF, data) < 0) 85 return; 86 while (!req.complete) 87 cuda_poll(); 88 } 89 #else 90 #define cuda_read_time() 0 91 #define cuda_write_time(n) 92 #define cuda_read_pram NULL 93 #define cuda_write_pram NULL 94 #endif 95 96 #ifdef CONFIG_ADB_PMU68K 97 static long pmu_read_time(void) 98 { 99 struct adb_request req; 100 long time; 101 102 if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0) 103 return 0; 104 while (!req.complete) 105 pmu_poll(); 106 107 time = (req.reply[0] << 24) | (req.reply[1] << 16) 108 | (req.reply[2] << 8) | req.reply[3]; 109 return time - RTC_OFFSET; 110 } 111 112 static void pmu_write_time(long data) 113 { 114 struct adb_request req; 115 data += RTC_OFFSET; 116 if (pmu_request(&req, NULL, 5, PMU_SET_RTC, 117 (data >> 24) & 0xFF, (data >> 16) & 0xFF, 118 (data >> 8) & 0xFF, data & 0xFF) < 0) 119 return; 120 while (!req.complete) 121 pmu_poll(); 122 } 123 124 static __u8 pmu_read_pram(int offset) 125 { 126 struct adb_request req; 127 if (pmu_request(&req, NULL, 3, PMU_READ_NVRAM, 128 (offset >> 8) & 0xFF, offset & 0xFF) < 0) 129 return 0; 130 while (!req.complete) 131 pmu_poll(); 132 return req.reply[3]; 133 } 134 135 static void pmu_write_pram(int offset, __u8 data) 136 { 137 struct adb_request req; 138 if (pmu_request(&req, NULL, 4, PMU_WRITE_NVRAM, 139 (offset >> 8) & 0xFF, offset & 0xFF, data) < 0) 140 return; 141 while (!req.complete) 142 pmu_poll(); 143 } 144 #else 145 #define pmu_read_time() 0 146 #define pmu_write_time(n) 147 #define pmu_read_pram NULL 148 #define pmu_write_pram NULL 149 #endif 150 151 #ifdef CONFIG_ADB_MACIISI 152 extern int maciisi_request(struct adb_request *req, 153 void (*done)(struct adb_request *), int nbytes, ...); 154 155 static long maciisi_read_time(void) 156 { 157 struct adb_request req; 158 long time; 159 160 if (maciisi_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME)) 161 return 0; 162 163 time = (req.reply[3] << 24) | (req.reply[4] << 16) 164 | (req.reply[5] << 8) | req.reply[6]; 165 return time - RTC_OFFSET; 166 } 167 168 static void maciisi_write_time(long data) 169 { 170 struct adb_request req; 171 data += RTC_OFFSET; 172 maciisi_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME, 173 (data >> 24) & 0xFF, (data >> 16) & 0xFF, 174 (data >> 8) & 0xFF, data & 0xFF); 175 } 176 177 static __u8 maciisi_read_pram(int offset) 178 { 179 struct adb_request req; 180 if (maciisi_request(&req, NULL, 4, CUDA_PACKET, CUDA_GET_PRAM, 181 (offset >> 8) & 0xFF, offset & 0xFF)) 182 return 0; 183 return req.reply[3]; 184 } 185 186 static void maciisi_write_pram(int offset, __u8 data) 187 { 188 struct adb_request req; 189 maciisi_request(&req, NULL, 5, CUDA_PACKET, CUDA_SET_PRAM, 190 (offset >> 8) & 0xFF, offset & 0xFF, data); 191 } 192 #else 193 #define maciisi_read_time() 0 194 #define maciisi_write_time(n) 195 #define maciisi_read_pram NULL 196 #define maciisi_write_pram NULL 197 #endif 198 199 /* 200 * VIA PRAM/RTC access routines 201 * 202 * Must be called with interrupts disabled and 203 * the RTC should be enabled. 204 */ 205 206 static __u8 via_pram_readbyte(void) 207 { 208 int i,reg; 209 __u8 data; 210 211 reg = via1[vBufB] & ~VIA1B_vRTCClk; 212 213 /* Set the RTC data line to be an input. */ 214 215 via1[vDirB] &= ~VIA1B_vRTCData; 216 217 /* The bits of the byte come out in MSB order */ 218 219 data = 0; 220 for (i = 0 ; i < 8 ; i++) { 221 via1[vBufB] = reg; 222 via1[vBufB] = reg | VIA1B_vRTCClk; 223 data = (data << 1) | (via1[vBufB] & VIA1B_vRTCData); 224 } 225 226 /* Return RTC data line to output state */ 227 228 via1[vDirB] |= VIA1B_vRTCData; 229 230 return data; 231 } 232 233 static void via_pram_writebyte(__u8 data) 234 { 235 int i,reg,bit; 236 237 reg = via1[vBufB] & ~(VIA1B_vRTCClk | VIA1B_vRTCData); 238 239 /* The bits of the byte go in in MSB order */ 240 241 for (i = 0 ; i < 8 ; i++) { 242 bit = data & 0x80? 1 : 0; 243 data <<= 1; 244 via1[vBufB] = reg | bit; 245 via1[vBufB] = reg | bit | VIA1B_vRTCClk; 246 } 247 } 248 249 /* 250 * Execute a VIA PRAM/RTC command. For read commands 251 * data should point to a one-byte buffer for the 252 * resulting data. For write commands it should point 253 * to the data byte to for the command. 254 * 255 * This function disables all interrupts while running. 256 */ 257 258 static void via_pram_command(int command, __u8 *data) 259 { 260 unsigned long flags; 261 int is_read; 262 263 local_irq_save(flags); 264 265 /* Enable the RTC and make sure the strobe line is high */ 266 267 via1[vBufB] = (via1[vBufB] | VIA1B_vRTCClk) & ~VIA1B_vRTCEnb; 268 269 if (command & 0xFF00) { /* extended (two-byte) command */ 270 via_pram_writebyte((command & 0xFF00) >> 8); 271 via_pram_writebyte(command & 0xFF); 272 is_read = command & 0x8000; 273 } else { /* one-byte command */ 274 via_pram_writebyte(command); 275 is_read = command & 0x80; 276 } 277 if (is_read) { 278 *data = via_pram_readbyte(); 279 } else { 280 via_pram_writebyte(*data); 281 } 282 283 /* All done, disable the RTC */ 284 285 via1[vBufB] |= VIA1B_vRTCEnb; 286 287 local_irq_restore(flags); 288 } 289 290 static __u8 via_read_pram(int offset) 291 { 292 return 0; 293 } 294 295 static void via_write_pram(int offset, __u8 data) 296 { 297 } 298 299 /* 300 * Return the current time in seconds since January 1, 1904. 301 * 302 * This only works on machines with the VIA-based PRAM/RTC, which 303 * is basically any machine with Mac II-style ADB. 304 */ 305 306 static long via_read_time(void) 307 { 308 union { 309 __u8 cdata[4]; 310 long idata; 311 } result, last_result; 312 int ct; 313 314 /* 315 * The NetBSD guys say to loop until you get the same reading 316 * twice in a row. 317 */ 318 319 ct = 0; 320 do { 321 if (++ct > 10) { 322 printk("via_read_time: couldn't get valid time, " 323 "last read = 0x%08lx and 0x%08lx\n", 324 last_result.idata, result.idata); 325 break; 326 } 327 328 last_result.idata = result.idata; 329 result.idata = 0; 330 331 via_pram_command(0x81, &result.cdata[3]); 332 via_pram_command(0x85, &result.cdata[2]); 333 via_pram_command(0x89, &result.cdata[1]); 334 via_pram_command(0x8D, &result.cdata[0]); 335 } while (result.idata != last_result.idata); 336 337 return result.idata - RTC_OFFSET; 338 } 339 340 /* 341 * Set the current time to a number of seconds since January 1, 1904. 342 * 343 * This only works on machines with the VIA-based PRAM/RTC, which 344 * is basically any machine with Mac II-style ADB. 345 */ 346 347 static void via_write_time(long time) 348 { 349 union { 350 __u8 cdata[4]; 351 long idata; 352 } data; 353 __u8 temp; 354 355 /* Clear the write protect bit */ 356 357 temp = 0x55; 358 via_pram_command(0x35, &temp); 359 360 data.idata = time + RTC_OFFSET; 361 via_pram_command(0x01, &data.cdata[3]); 362 via_pram_command(0x05, &data.cdata[2]); 363 via_pram_command(0x09, &data.cdata[1]); 364 via_pram_command(0x0D, &data.cdata[0]); 365 366 /* Set the write protect bit */ 367 368 temp = 0xD5; 369 via_pram_command(0x35, &temp); 370 } 371 372 static void via_shutdown(void) 373 { 374 if (rbv_present) { 375 via2[rBufB] &= ~0x04; 376 } else { 377 /* Direction of vDirB is output */ 378 via2[vDirB] |= 0x04; 379 /* Send a value of 0 on that line */ 380 via2[vBufB] &= ~0x04; 381 mdelay(1000); 382 } 383 } 384 385 /* 386 * FIXME: not sure how this is supposed to work exactly... 387 */ 388 389 static void oss_shutdown(void) 390 { 391 oss->rom_ctrl = OSS_POWEROFF; 392 } 393 394 #ifdef CONFIG_ADB_CUDA 395 396 static void cuda_restart(void) 397 { 398 struct adb_request req; 399 if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_RESET_SYSTEM) < 0) 400 return; 401 while (!req.complete) 402 cuda_poll(); 403 } 404 405 static void cuda_shutdown(void) 406 { 407 struct adb_request req; 408 if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_POWERDOWN) < 0) 409 return; 410 while (!req.complete) 411 cuda_poll(); 412 } 413 414 #endif /* CONFIG_ADB_CUDA */ 415 416 #ifdef CONFIG_ADB_PMU68K 417 418 void pmu_restart(void) 419 { 420 struct adb_request req; 421 if (pmu_request(&req, NULL, 422 2, PMU_SET_INTR_MASK, PMU_INT_ADB|PMU_INT_TICK) < 0) 423 return; 424 while (!req.complete) 425 pmu_poll(); 426 if (pmu_request(&req, NULL, 1, PMU_RESET) < 0) 427 return; 428 while (!req.complete) 429 pmu_poll(); 430 } 431 432 void pmu_shutdown(void) 433 { 434 struct adb_request req; 435 if (pmu_request(&req, NULL, 436 2, PMU_SET_INTR_MASK, PMU_INT_ADB|PMU_INT_TICK) < 0) 437 return; 438 while (!req.complete) 439 pmu_poll(); 440 if (pmu_request(&req, NULL, 5, PMU_SHUTDOWN, 'M', 'A', 'T', 'T') < 0) 441 return; 442 while (!req.complete) 443 pmu_poll(); 444 } 445 446 #endif 447 448 /* 449 *------------------------------------------------------------------- 450 * Below this point are the generic routines; they'll dispatch to the 451 * correct routine for the hardware on which we're running. 452 *------------------------------------------------------------------- 453 */ 454 455 void mac_pram_read(int offset, __u8 *buffer, int len) 456 { 457 __u8 (*func)(int); 458 int i; 459 460 switch(macintosh_config->adb_type) { 461 case MAC_ADB_IISI: 462 func = maciisi_read_pram; break; 463 case MAC_ADB_PB1: 464 case MAC_ADB_PB2: 465 func = pmu_read_pram; break; 466 case MAC_ADB_CUDA: 467 func = cuda_read_pram; break; 468 default: 469 func = via_read_pram; 470 } 471 if (!func) 472 return; 473 for (i = 0 ; i < len ; i++) { 474 buffer[i] = (*func)(offset++); 475 } 476 } 477 478 void mac_pram_write(int offset, __u8 *buffer, int len) 479 { 480 void (*func)(int, __u8); 481 int i; 482 483 switch(macintosh_config->adb_type) { 484 case MAC_ADB_IISI: 485 func = maciisi_write_pram; break; 486 case MAC_ADB_PB1: 487 case MAC_ADB_PB2: 488 func = pmu_write_pram; break; 489 case MAC_ADB_CUDA: 490 func = cuda_write_pram; break; 491 default: 492 func = via_write_pram; 493 } 494 if (!func) 495 return; 496 for (i = 0 ; i < len ; i++) { 497 (*func)(offset++, buffer[i]); 498 } 499 } 500 501 void mac_poweroff(void) 502 { 503 /* 504 * MAC_ADB_IISI may need to be moved up here if it doesn't actually 505 * work using the ADB packet method. --David Kilzer 506 */ 507 508 if (oss_present) { 509 oss_shutdown(); 510 } else if (macintosh_config->adb_type == MAC_ADB_II) { 511 via_shutdown(); 512 #ifdef CONFIG_ADB_CUDA 513 } else if (macintosh_config->adb_type == MAC_ADB_CUDA) { 514 cuda_shutdown(); 515 #endif 516 #ifdef CONFIG_ADB_PMU68K 517 } else if (macintosh_config->adb_type == MAC_ADB_PB1 518 || macintosh_config->adb_type == MAC_ADB_PB2) { 519 pmu_shutdown(); 520 #endif 521 } 522 local_irq_enable(); 523 printk("It is now safe to turn off your Macintosh.\n"); 524 while(1); 525 } 526 527 void mac_reset(void) 528 { 529 if (macintosh_config->adb_type == MAC_ADB_II) { 530 unsigned long flags; 531 532 /* need ROMBASE in booter */ 533 /* indeed, plus need to MAP THE ROM !! */ 534 535 if (mac_bi_data.rombase == 0) 536 mac_bi_data.rombase = 0x40800000; 537 538 /* works on some */ 539 rom_reset = (void *) (mac_bi_data.rombase + 0xa); 540 541 if (macintosh_config->ident == MAC_MODEL_SE30) { 542 /* 543 * MSch: Machines known to crash on ROM reset ... 544 */ 545 } else { 546 local_irq_save(flags); 547 548 rom_reset(); 549 550 local_irq_restore(flags); 551 } 552 #ifdef CONFIG_ADB_CUDA 553 } else if (macintosh_config->adb_type == MAC_ADB_CUDA) { 554 cuda_restart(); 555 #endif 556 #ifdef CONFIG_ADB_PMU68K 557 } else if (macintosh_config->adb_type == MAC_ADB_PB1 558 || macintosh_config->adb_type == MAC_ADB_PB2) { 559 pmu_restart(); 560 #endif 561 } else if (CPU_IS_030) { 562 563 /* 030-specific reset routine. The idea is general, but the 564 * specific registers to reset are '030-specific. Until I 565 * have a non-030 machine, I can't test anything else. 566 * -- C. Scott Ananian <cananian@alumni.princeton.edu> 567 */ 568 569 unsigned long rombase = 0x40000000; 570 571 /* make a 1-to-1 mapping, using the transparent tran. reg. */ 572 unsigned long virt = (unsigned long) mac_reset; 573 unsigned long phys = virt_to_phys(mac_reset); 574 unsigned long addr = (phys&0xFF000000)|0x8777; 575 unsigned long offset = phys-virt; 576 local_irq_disable(); /* lets not screw this up, ok? */ 577 __asm__ __volatile__(".chip 68030\n\t" 578 "pmove %0,%/tt0\n\t" 579 ".chip 68k" 580 : : "m" (addr)); 581 /* Now jump to physical address so we can disable MMU */ 582 __asm__ __volatile__( 583 ".chip 68030\n\t" 584 "lea %/pc@(1f),%/a0\n\t" 585 "addl %0,%/a0\n\t"/* fixup target address and stack ptr */ 586 "addl %0,%/sp\n\t" 587 "pflusha\n\t" 588 "jmp %/a0@\n\t" /* jump into physical memory */ 589 "0:.long 0\n\t" /* a constant zero. */ 590 /* OK. Now reset everything and jump to reset vector. */ 591 "1:\n\t" 592 "lea %/pc@(0b),%/a0\n\t" 593 "pmove %/a0@, %/tc\n\t" /* disable mmu */ 594 "pmove %/a0@, %/tt0\n\t" /* disable tt0 */ 595 "pmove %/a0@, %/tt1\n\t" /* disable tt1 */ 596 "movel #0, %/a0\n\t" 597 "movec %/a0, %/vbr\n\t" /* clear vector base register */ 598 "movec %/a0, %/cacr\n\t" /* disable caches */ 599 "movel #0x0808,%/a0\n\t" 600 "movec %/a0, %/cacr\n\t" /* flush i&d caches */ 601 "movew #0x2700,%/sr\n\t" /* set up status register */ 602 "movel %1@(0x0),%/a0\n\t"/* load interrupt stack pointer */ 603 "movec %/a0, %/isp\n\t" 604 "movel %1@(0x4),%/a0\n\t" /* load reset vector */ 605 "reset\n\t" /* reset external devices */ 606 "jmp %/a0@\n\t" /* jump to the reset vector */ 607 ".chip 68k" 608 : : "r" (offset), "a" (rombase) : "a0"); 609 } 610 611 /* should never get here */ 612 local_irq_enable(); 613 printk ("Restart failed. Please restart manually.\n"); 614 while(1); 615 } 616 617 /* 618 * This function translates seconds since 1970 into a proper date. 619 * 620 * Algorithm cribbed from glibc2.1, __offtime(). 621 */ 622 #define SECS_PER_MINUTE (60) 623 #define SECS_PER_HOUR (SECS_PER_MINUTE * 60) 624 #define SECS_PER_DAY (SECS_PER_HOUR * 24) 625 626 static void unmktime(unsigned long time, long offset, 627 int *yearp, int *monp, int *dayp, 628 int *hourp, int *minp, int *secp) 629 { 630 /* How many days come before each month (0-12). */ 631 static const unsigned short int __mon_yday[2][13] = 632 { 633 /* Normal years. */ 634 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, 635 /* Leap years. */ 636 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } 637 }; 638 long int days, rem, y, wday, yday; 639 const unsigned short int *ip; 640 641 days = time / SECS_PER_DAY; 642 rem = time % SECS_PER_DAY; 643 rem += offset; 644 while (rem < 0) { 645 rem += SECS_PER_DAY; 646 --days; 647 } 648 while (rem >= SECS_PER_DAY) { 649 rem -= SECS_PER_DAY; 650 ++days; 651 } 652 *hourp = rem / SECS_PER_HOUR; 653 rem %= SECS_PER_HOUR; 654 *minp = rem / SECS_PER_MINUTE; 655 *secp = rem % SECS_PER_MINUTE; 656 /* January 1, 1970 was a Thursday. */ 657 wday = (4 + days) % 7; /* Day in the week. Not currently used */ 658 if (wday < 0) wday += 7; 659 y = 1970; 660 661 #define DIV(a, b) ((a) / (b) - ((a) % (b) < 0)) 662 #define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400)) 663 #define __isleap(year) \ 664 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) 665 666 while (days < 0 || days >= (__isleap (y) ? 366 : 365)) 667 { 668 /* Guess a corrected year, assuming 365 days per year. */ 669 long int yg = y + days / 365 - (days % 365 < 0); 670 671 /* Adjust DAYS and Y to match the guessed year. */ 672 days -= ((yg - y) * 365 673 + LEAPS_THRU_END_OF (yg - 1) 674 - LEAPS_THRU_END_OF (y - 1)); 675 y = yg; 676 } 677 *yearp = y - 1900; 678 yday = days; /* day in the year. Not currently used. */ 679 ip = __mon_yday[__isleap(y)]; 680 for (y = 11; days < (long int) ip[y]; --y) 681 continue; 682 days -= ip[y]; 683 *monp = y; 684 *dayp = days + 1; /* day in the month */ 685 return; 686 } 687 688 /* 689 * Read/write the hardware clock. 690 */ 691 692 int mac_hwclk(int op, struct rtc_time *t) 693 { 694 unsigned long now; 695 696 if (!op) { /* read */ 697 switch (macintosh_config->adb_type) { 698 case MAC_ADB_II: 699 case MAC_ADB_IOP: 700 now = via_read_time(); 701 break; 702 case MAC_ADB_IISI: 703 now = maciisi_read_time(); 704 break; 705 case MAC_ADB_PB1: 706 case MAC_ADB_PB2: 707 now = pmu_read_time(); 708 break; 709 case MAC_ADB_CUDA: 710 now = cuda_read_time(); 711 break; 712 default: 713 now = 0; 714 } 715 716 t->tm_wday = 0; 717 unmktime(now, 0, 718 &t->tm_year, &t->tm_mon, &t->tm_mday, 719 &t->tm_hour, &t->tm_min, &t->tm_sec); 720 printk("mac_hwclk: read %04d-%02d-%-2d %02d:%02d:%02d\n", 721 t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); 722 } else { /* write */ 723 printk("mac_hwclk: tried to write %04d-%02d-%-2d %02d:%02d:%02d\n", 724 t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); 725 726 #if 0 /* it trashes my rtc */ 727 now = mktime(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, 728 t->tm_hour, t->tm_min, t->tm_sec); 729 730 switch (macintosh_config->adb_type) { 731 case MAC_ADB_II: 732 case MAC_ADB_IOP: 733 via_write_time(now); 734 break; 735 case MAC_ADB_CUDA: 736 cuda_write_time(now); 737 break; 738 case MAC_ADB_PB1: 739 case MAC_ADB_PB2: 740 pmu_write_time(now); 741 break; 742 case MAC_ADB_IISI: 743 maciisi_write_time(now); 744 } 745 #endif 746 } 747 return 0; 748 } 749 750 /* 751 * Set minutes/seconds in the hardware clock 752 */ 753 754 int mac_set_clock_mmss (unsigned long nowtime) 755 { 756 struct rtc_time now; 757 758 mac_hwclk(0, &now); 759 now.tm_sec = nowtime % 60; 760 now.tm_min = (nowtime / 60) % 60; 761 mac_hwclk(1, &now); 762 763 return 0; 764 } 765