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