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