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/time.h> 12 #include <linux/rtc.h> 13 #include <linux/mm.h> 14 15 #include <linux/adb.h> 16 #include <linux/cuda.h> 17 #include <linux/pmu.h> 18 19 #include <asm/uaccess.h> 20 #include <asm/io.h> 21 #include <asm/segment.h> 22 #include <asm/setup.h> 23 #include <asm/macintosh.h> 24 #include <asm/mac_via.h> 25 #include <asm/mac_oss.h> 26 27 #include <asm/machdep.h> 28 29 /* Offset between Unix time (1970-based) and Mac time (1904-based) */ 30 31 #define RTC_OFFSET 2082844800 32 33 static void (*rom_reset)(void); 34 35 #ifdef CONFIG_ADB_CUDA 36 static long cuda_read_time(void) 37 { 38 struct adb_request req; 39 long time; 40 41 if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0) 42 return 0; 43 while (!req.complete) 44 cuda_poll(); 45 46 time = (req.reply[3] << 24) | (req.reply[4] << 16) 47 | (req.reply[5] << 8) | req.reply[6]; 48 return time - RTC_OFFSET; 49 } 50 51 static void cuda_write_time(long data) 52 { 53 struct adb_request req; 54 data += RTC_OFFSET; 55 if (cuda_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME, 56 (data >> 24) & 0xFF, (data >> 16) & 0xFF, 57 (data >> 8) & 0xFF, data & 0xFF) < 0) 58 return; 59 while (!req.complete) 60 cuda_poll(); 61 } 62 63 static __u8 cuda_read_pram(int offset) 64 { 65 struct adb_request req; 66 if (cuda_request(&req, NULL, 4, CUDA_PACKET, CUDA_GET_PRAM, 67 (offset >> 8) & 0xFF, offset & 0xFF) < 0) 68 return 0; 69 while (!req.complete) 70 cuda_poll(); 71 return req.reply[3]; 72 } 73 74 static void cuda_write_pram(int offset, __u8 data) 75 { 76 struct adb_request req; 77 if (cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_SET_PRAM, 78 (offset >> 8) & 0xFF, offset & 0xFF, data) < 0) 79 return; 80 while (!req.complete) 81 cuda_poll(); 82 } 83 #else 84 #define cuda_read_time() 0 85 #define cuda_write_time(n) 86 #define cuda_read_pram NULL 87 #define cuda_write_pram NULL 88 #endif 89 90 #ifdef CONFIG_ADB_PMU68K 91 static long pmu_read_time(void) 92 { 93 struct adb_request req; 94 long time; 95 96 if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0) 97 return 0; 98 while (!req.complete) 99 pmu_poll(); 100 101 time = (req.reply[1] << 24) | (req.reply[2] << 16) 102 | (req.reply[3] << 8) | req.reply[4]; 103 return time - RTC_OFFSET; 104 } 105 106 static void pmu_write_time(long data) 107 { 108 struct adb_request req; 109 data += RTC_OFFSET; 110 if (pmu_request(&req, NULL, 5, PMU_SET_RTC, 111 (data >> 24) & 0xFF, (data >> 16) & 0xFF, 112 (data >> 8) & 0xFF, data & 0xFF) < 0) 113 return; 114 while (!req.complete) 115 pmu_poll(); 116 } 117 118 static __u8 pmu_read_pram(int offset) 119 { 120 struct adb_request req; 121 if (pmu_request(&req, NULL, 3, PMU_READ_NVRAM, 122 (offset >> 8) & 0xFF, offset & 0xFF) < 0) 123 return 0; 124 while (!req.complete) 125 pmu_poll(); 126 return req.reply[3]; 127 } 128 129 static void pmu_write_pram(int offset, __u8 data) 130 { 131 struct adb_request req; 132 if (pmu_request(&req, NULL, 4, PMU_WRITE_NVRAM, 133 (offset >> 8) & 0xFF, offset & 0xFF, data) < 0) 134 return; 135 while (!req.complete) 136 pmu_poll(); 137 } 138 #else 139 #define pmu_read_time() 0 140 #define pmu_write_time(n) 141 #define pmu_read_pram NULL 142 #define pmu_write_pram NULL 143 #endif 144 145 #if 0 /* def CONFIG_ADB_MACIISI */ 146 extern int maciisi_request(struct adb_request *req, 147 void (*done)(struct adb_request *), int nbytes, ...); 148 149 static long maciisi_read_time(void) 150 { 151 struct adb_request req; 152 long time; 153 154 if (maciisi_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME)) 155 return 0; 156 157 time = (req.reply[3] << 24) | (req.reply[4] << 16) 158 | (req.reply[5] << 8) | req.reply[6]; 159 return time - RTC_OFFSET; 160 } 161 162 static void maciisi_write_time(long data) 163 { 164 struct adb_request req; 165 data += RTC_OFFSET; 166 maciisi_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME, 167 (data >> 24) & 0xFF, (data >> 16) & 0xFF, 168 (data >> 8) & 0xFF, data & 0xFF); 169 } 170 171 static __u8 maciisi_read_pram(int offset) 172 { 173 struct adb_request req; 174 if (maciisi_request(&req, NULL, 4, CUDA_PACKET, CUDA_GET_PRAM, 175 (offset >> 8) & 0xFF, offset & 0xFF)) 176 return 0; 177 return req.reply[3]; 178 } 179 180 static void maciisi_write_pram(int offset, __u8 data) 181 { 182 struct adb_request req; 183 maciisi_request(&req, NULL, 5, CUDA_PACKET, CUDA_SET_PRAM, 184 (offset >> 8) & 0xFF, offset & 0xFF, data); 185 } 186 #else 187 #define maciisi_read_time() 0 188 #define maciisi_write_time(n) 189 #define maciisi_read_pram NULL 190 #define maciisi_write_pram NULL 191 #endif 192 193 /* 194 * VIA PRAM/RTC access routines 195 * 196 * Must be called with interrupts disabled and 197 * the RTC should be enabled. 198 */ 199 200 static __u8 via_pram_readbyte(void) 201 { 202 int i,reg; 203 __u8 data; 204 205 reg = via1[vBufB] & ~VIA1B_vRTCClk; 206 207 /* Set the RTC data line to be an input. */ 208 209 via1[vDirB] &= ~VIA1B_vRTCData; 210 211 /* The bits of the byte come out in MSB order */ 212 213 data = 0; 214 for (i = 0 ; i < 8 ; i++) { 215 via1[vBufB] = reg; 216 via1[vBufB] = reg | VIA1B_vRTCClk; 217 data = (data << 1) | (via1[vBufB] & VIA1B_vRTCData); 218 } 219 220 /* Return RTC data line to output state */ 221 222 via1[vDirB] |= VIA1B_vRTCData; 223 224 return data; 225 } 226 227 static void via_pram_writebyte(__u8 data) 228 { 229 int i,reg,bit; 230 231 reg = via1[vBufB] & ~(VIA1B_vRTCClk | VIA1B_vRTCData); 232 233 /* The bits of the byte go in in MSB order */ 234 235 for (i = 0 ; i < 8 ; i++) { 236 bit = data & 0x80? 1 : 0; 237 data <<= 1; 238 via1[vBufB] = reg | bit; 239 via1[vBufB] = reg | bit | VIA1B_vRTCClk; 240 } 241 } 242 243 /* 244 * Execute a VIA PRAM/RTC command. For read commands 245 * data should point to a one-byte buffer for the 246 * resulting data. For write commands it should point 247 * to the data byte to for the command. 248 * 249 * This function disables all interrupts while running. 250 */ 251 252 static void via_pram_command(int command, __u8 *data) 253 { 254 unsigned long flags; 255 int is_read; 256 257 local_irq_save(flags); 258 259 /* Enable the RTC and make sure the strobe line is high */ 260 261 via1[vBufB] = (via1[vBufB] | VIA1B_vRTCClk) & ~VIA1B_vRTCEnb; 262 263 if (command & 0xFF00) { /* extended (two-byte) command */ 264 via_pram_writebyte((command & 0xFF00) >> 8); 265 via_pram_writebyte(command & 0xFF); 266 is_read = command & 0x8000; 267 } else { /* one-byte command */ 268 via_pram_writebyte(command); 269 is_read = command & 0x80; 270 } 271 if (is_read) { 272 *data = via_pram_readbyte(); 273 } else { 274 via_pram_writebyte(*data); 275 } 276 277 /* All done, disable the RTC */ 278 279 via1[vBufB] |= VIA1B_vRTCEnb; 280 281 local_irq_restore(flags); 282 } 283 284 static __u8 via_read_pram(int offset) 285 { 286 return 0; 287 } 288 289 static void via_write_pram(int offset, __u8 data) 290 { 291 } 292 293 /* 294 * Return the current time in seconds since January 1, 1904. 295 * 296 * This only works on machines with the VIA-based PRAM/RTC, which 297 * is basically any machine with Mac II-style ADB. 298 */ 299 300 static long via_read_time(void) 301 { 302 union { 303 __u8 cdata[4]; 304 long idata; 305 } result, last_result; 306 int count = 1; 307 308 via_pram_command(0x81, &last_result.cdata[3]); 309 via_pram_command(0x85, &last_result.cdata[2]); 310 via_pram_command(0x89, &last_result.cdata[1]); 311 via_pram_command(0x8D, &last_result.cdata[0]); 312 313 /* 314 * The NetBSD guys say to loop until you get the same reading 315 * twice in a row. 316 */ 317 318 while (1) { 319 via_pram_command(0x81, &result.cdata[3]); 320 via_pram_command(0x85, &result.cdata[2]); 321 via_pram_command(0x89, &result.cdata[1]); 322 via_pram_command(0x8D, &result.cdata[0]); 323 324 if (result.idata == last_result.idata) 325 return result.idata - RTC_OFFSET; 326 327 if (++count > 10) 328 break; 329 330 last_result.idata = result.idata; 331 } 332 333 pr_err("via_read_time: failed to read a stable value; " 334 "got 0x%08lx then 0x%08lx\n", 335 last_result.idata, result.idata); 336 337 return 0; 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 #if 0 721 printk("mac_hwclk: read %04d-%02d-%-2d %02d:%02d:%02d\n", 722 t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, 723 t->tm_hour, t->tm_min, t->tm_sec); 724 #endif 725 } else { /* write */ 726 #if 0 727 printk("mac_hwclk: tried to write %04d-%02d-%-2d %02d:%02d:%02d\n", 728 t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, 729 t->tm_hour, t->tm_min, t->tm_sec); 730 #endif 731 732 now = mktime(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, 733 t->tm_hour, t->tm_min, t->tm_sec); 734 735 switch (macintosh_config->adb_type) { 736 case MAC_ADB_II: 737 case MAC_ADB_IOP: 738 via_write_time(now); 739 break; 740 case MAC_ADB_CUDA: 741 cuda_write_time(now); 742 break; 743 case MAC_ADB_PB1: 744 case MAC_ADB_PB2: 745 pmu_write_time(now); 746 break; 747 case MAC_ADB_IISI: 748 maciisi_write_time(now); 749 } 750 } 751 return 0; 752 } 753 754 /* 755 * Set minutes/seconds in the hardware clock 756 */ 757 758 int mac_set_clock_mmss (unsigned long nowtime) 759 { 760 struct rtc_time now; 761 762 mac_hwclk(0, &now); 763 now.tm_sec = nowtime % 60; 764 now.tm_min = (nowtime / 60) % 60; 765 mac_hwclk(1, &now); 766 767 return 0; 768 } 769