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