1 /* 2 * 6522 Versatile Interface Adapter (VIA) 3 * 4 * There are two of these on the Mac II. Some IRQs are vectored 5 * via them as are assorted bits and bobs - eg RTC, ADB. 6 * 7 * CSA: Motorola seems to have removed documentation on the 6522 from 8 * their web site; try 9 * http://nerini.drf.com/vectrex/other/text/chips/6522/ 10 * http://www.zymurgy.net/classic/vic20/vicdet1.htm 11 * and 12 * http://193.23.168.87/mikro_laborversuche/via_iobaustein/via6522_1.html 13 * for info. A full-text web search on 6522 AND VIA will probably also 14 * net some usefulness. <cananian@alumni.princeton.edu> 20apr1999 15 * 16 * Additional data is here (the SY6522 was used in the Mac II etc): 17 * http://www.6502.org/documents/datasheets/synertek/synertek_sy6522.pdf 18 * http://www.6502.org/documents/datasheets/synertek/synertek_sy6522_programming_reference.pdf 19 * 20 * PRAM/RTC access algorithms are from the NetBSD RTC toolkit version 1.08b 21 * by Erik Vogan and adapted to Linux by Joshua M. Thompson (funaho@jurai.org) 22 * 23 */ 24 25 #include <linux/types.h> 26 #include <linux/kernel.h> 27 #include <linux/mm.h> 28 #include <linux/delay.h> 29 #include <linux/init.h> 30 #include <linux/module.h> 31 32 #include <asm/bootinfo.h> 33 #include <asm/macintosh.h> 34 #include <asm/macints.h> 35 #include <asm/mac_via.h> 36 #include <asm/mac_psc.h> 37 #include <asm/mac_oss.h> 38 39 volatile __u8 *via1, *via2; 40 int rbv_present; 41 int via_alt_mapping; 42 EXPORT_SYMBOL(via_alt_mapping); 43 static __u8 rbv_clear; 44 45 /* 46 * Globals for accessing the VIA chip registers without having to 47 * check if we're hitting a real VIA or an RBV. Normally you could 48 * just hit the combined register (ie, vIER|rIER) but that seems to 49 * break on AV Macs...probably because they actually decode more than 50 * eight address bits. Why can't Apple engineers at least be 51 * _consistently_ lazy? - 1999-05-21 (jmt) 52 */ 53 54 static int gIER,gIFR,gBufA,gBufB; 55 56 /* 57 * Timer defs. 58 */ 59 60 #define TICK_SIZE 10000 61 #define MAC_CLOCK_TICK (783300/HZ) /* ticks per HZ */ 62 #define MAC_CLOCK_LOW (MAC_CLOCK_TICK&0xFF) 63 #define MAC_CLOCK_HIGH (MAC_CLOCK_TICK>>8) 64 65 /* To disable a NuBus slot on Quadras we make that slot IRQ line an output set 66 * high. On RBV we just use the slot interrupt enable register. On Macs with 67 * genuine VIA chips we must use nubus_disabled to keep track of disabled slot 68 * interrupts. When any slot IRQ is disabled we mask the (edge triggered) CA1 69 * or "SLOTS" interrupt. When no slot is disabled, we unmask the CA1 interrupt. 70 * So, on genuine VIAs, having more than one NuBus IRQ can mean trouble, 71 * because closing one of those drivers can mask all of the NuBus interrupts. 72 * Also, since we can't mask the unregistered slot IRQs on genuine VIAs, it's 73 * possible to get interrupts from cards that MacOS or the ROM has configured 74 * but we have not. FWIW, "Designing Cards and Drivers for Macintosh II and 75 * Macintosh SE", page 9-8, says, a slot IRQ with no driver would crash MacOS. 76 */ 77 static u8 nubus_disabled; 78 79 void via_debug_dump(void); 80 irqreturn_t via1_irq(int, void *); 81 irqreturn_t via2_irq(int, void *); 82 irqreturn_t via_nubus_irq(int, void *); 83 void via_irq_enable(int irq); 84 void via_irq_disable(int irq); 85 void via_irq_clear(int irq); 86 87 /* 88 * Initialize the VIAs 89 * 90 * First we figure out where they actually _are_ as well as what type of 91 * VIA we have for VIA2 (it could be a real VIA or an RBV or even an OSS.) 92 * Then we pretty much clear them out and disable all IRQ sources. 93 * 94 * Note: the OSS is actually "detected" here and not in oss_init(). It just 95 * seems more logical to do it here since via_init() needs to know 96 * these things anyways. 97 */ 98 99 void __init via_init(void) 100 { 101 switch(macintosh_config->via_type) { 102 103 /* IIci, IIsi, IIvx, IIvi (P6xx), LC series */ 104 105 case MAC_VIA_IIci: 106 via1 = (void *) VIA1_BASE; 107 if (macintosh_config->ident == MAC_MODEL_IIFX) { 108 via2 = NULL; 109 rbv_present = 0; 110 oss_present = 1; 111 } else { 112 via2 = (void *) RBV_BASE; 113 rbv_present = 1; 114 oss_present = 0; 115 } 116 if (macintosh_config->ident == MAC_MODEL_LCIII) { 117 rbv_clear = 0x00; 118 } else { 119 /* on most RBVs (& unlike the VIAs), you */ 120 /* need to set bit 7 when you write to IFR */ 121 /* in order for your clear to occur. */ 122 rbv_clear = 0x80; 123 } 124 gIER = rIER; 125 gIFR = rIFR; 126 gBufA = rSIFR; 127 gBufB = rBufB; 128 break; 129 130 /* Quadra and early MacIIs agree on the VIA locations */ 131 132 case MAC_VIA_QUADRA: 133 case MAC_VIA_II: 134 via1 = (void *) VIA1_BASE; 135 via2 = (void *) VIA2_BASE; 136 rbv_present = 0; 137 oss_present = 0; 138 rbv_clear = 0x00; 139 gIER = vIER; 140 gIFR = vIFR; 141 gBufA = vBufA; 142 gBufB = vBufB; 143 break; 144 default: 145 panic("UNKNOWN VIA TYPE"); 146 } 147 148 printk(KERN_INFO "VIA1 at %p is a 6522 or clone\n", via1); 149 150 printk(KERN_INFO "VIA2 at %p is ", via2); 151 if (rbv_present) { 152 printk("an RBV\n"); 153 } else if (oss_present) { 154 printk("an OSS\n"); 155 } else { 156 printk("a 6522 or clone\n"); 157 } 158 159 #ifdef DEBUG_VIA 160 via_debug_dump(); 161 #endif 162 163 /* 164 * Shut down all IRQ sources, reset the timers, and 165 * kill the timer latch on VIA1. 166 */ 167 168 via1[vIER] = 0x7F; 169 via1[vIFR] = 0x7F; 170 via1[vT1LL] = 0; 171 via1[vT1LH] = 0; 172 via1[vT1CL] = 0; 173 via1[vT1CH] = 0; 174 via1[vT2CL] = 0; 175 via1[vT2CH] = 0; 176 via1[vACR] &= ~0xC0; /* setup T1 timer with no PB7 output */ 177 via1[vACR] &= ~0x03; /* disable port A & B latches */ 178 179 /* 180 * SE/30: disable video IRQ 181 * XXX: testing for SE/30 VBL 182 */ 183 184 if (macintosh_config->ident == MAC_MODEL_SE30) { 185 via1[vDirB] |= 0x40; 186 via1[vBufB] |= 0x40; 187 } 188 189 /* 190 * Set the RTC bits to a known state: all lines to outputs and 191 * RTC disabled (yes that's 0 to enable and 1 to disable). 192 */ 193 194 via1[vDirB] |= (VIA1B_vRTCEnb | VIA1B_vRTCClk | VIA1B_vRTCData); 195 via1[vBufB] |= (VIA1B_vRTCEnb | VIA1B_vRTCClk); 196 197 /* Everything below this point is VIA2/RBV only... */ 198 199 if (oss_present) 200 return; 201 202 /* Some machines support an alternate IRQ mapping that spreads */ 203 /* Ethernet and Sound out to their own autolevel IRQs and moves */ 204 /* VIA1 to level 6. A/UX uses this mapping and we do too. Note */ 205 /* that the IIfx emulates this alternate mapping using the OSS. */ 206 207 via_alt_mapping = 0; 208 if (macintosh_config->via_type == MAC_VIA_QUADRA) 209 switch (macintosh_config->ident) { 210 case MAC_MODEL_C660: 211 case MAC_MODEL_Q840: 212 /* not applicable */ 213 break; 214 case MAC_MODEL_P588: 215 case MAC_MODEL_TV: 216 case MAC_MODEL_PB140: 217 case MAC_MODEL_PB145: 218 case MAC_MODEL_PB160: 219 case MAC_MODEL_PB165: 220 case MAC_MODEL_PB165C: 221 case MAC_MODEL_PB170: 222 case MAC_MODEL_PB180: 223 case MAC_MODEL_PB180C: 224 case MAC_MODEL_PB190: 225 case MAC_MODEL_PB520: 226 /* not yet tested */ 227 break; 228 default: 229 via_alt_mapping = 1; 230 via1[vDirB] |= 0x40; 231 via1[vBufB] &= ~0x40; 232 break; 233 } 234 235 /* 236 * Now initialize VIA2. For RBV we just kill all interrupts; 237 * for a regular VIA we also reset the timers and stuff. 238 */ 239 240 via2[gIER] = 0x7F; 241 via2[gIFR] = 0x7F | rbv_clear; 242 if (!rbv_present) { 243 via2[vT1LL] = 0; 244 via2[vT1LH] = 0; 245 via2[vT1CL] = 0; 246 via2[vT1CH] = 0; 247 via2[vT2CL] = 0; 248 via2[vT2CH] = 0; 249 via2[vACR] &= ~0xC0; /* setup T1 timer with no PB7 output */ 250 via2[vACR] &= ~0x03; /* disable port A & B latches */ 251 } 252 253 /* 254 * Set vPCR for control line interrupts (but not on RBV) 255 */ 256 if (!rbv_present) { 257 /* For all VIA types, CA1 (SLOTS IRQ) and CB1 (ASC IRQ) 258 * are made negative edge triggered here. 259 */ 260 if (macintosh_config->scsi_type == MAC_SCSI_OLD) { 261 /* CB2 (IRQ) indep. input, positive edge */ 262 /* CA2 (DRQ) indep. input, positive edge */ 263 via2[vPCR] = 0x66; 264 } else { 265 /* CB2 (IRQ) indep. input, negative edge */ 266 /* CA2 (DRQ) indep. input, negative edge */ 267 via2[vPCR] = 0x22; 268 } 269 } 270 } 271 272 /* 273 * Start the 100 Hz clock 274 */ 275 276 void __init via_init_clock(irq_handler_t func) 277 { 278 via1[vACR] |= 0x40; 279 via1[vT1LL] = MAC_CLOCK_LOW; 280 via1[vT1LH] = MAC_CLOCK_HIGH; 281 via1[vT1CL] = MAC_CLOCK_LOW; 282 via1[vT1CH] = MAC_CLOCK_HIGH; 283 284 if (request_irq(IRQ_MAC_TIMER_1, func, IRQ_FLG_LOCK, "timer", func)) 285 pr_err("Couldn't register %s interrupt\n", "timer"); 286 } 287 288 /* 289 * Register the interrupt dispatchers for VIA or RBV machines only. 290 */ 291 292 void __init via_register_interrupts(void) 293 { 294 if (via_alt_mapping) { 295 if (request_irq(IRQ_AUTO_1, via1_irq, 296 IRQ_FLG_LOCK|IRQ_FLG_FAST, "software", 297 (void *) via1)) 298 pr_err("Couldn't register %s interrupt\n", "software"); 299 if (request_irq(IRQ_AUTO_6, via1_irq, 300 IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1", 301 (void *) via1)) 302 pr_err("Couldn't register %s interrupt\n", "via1"); 303 } else { 304 if (request_irq(IRQ_AUTO_1, via1_irq, 305 IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1", 306 (void *) via1)) 307 pr_err("Couldn't register %s interrupt\n", "via1"); 308 } 309 if (request_irq(IRQ_AUTO_2, via2_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST, 310 "via2", (void *) via2)) 311 pr_err("Couldn't register %s interrupt\n", "via2"); 312 if (request_irq(IRQ_MAC_NUBUS, via_nubus_irq, 313 IRQ_FLG_LOCK|IRQ_FLG_FAST, "nubus", (void *) via2)) 314 pr_err("Couldn't register %s interrupt\n", "nubus"); 315 } 316 317 /* 318 * Debugging dump, used in various places to see what's going on. 319 */ 320 321 void via_debug_dump(void) 322 { 323 printk(KERN_DEBUG "VIA1: DDRA = 0x%02X DDRB = 0x%02X ACR = 0x%02X\n", 324 (uint) via1[vDirA], (uint) via1[vDirB], (uint) via1[vACR]); 325 printk(KERN_DEBUG " PCR = 0x%02X IFR = 0x%02X IER = 0x%02X\n", 326 (uint) via1[vPCR], (uint) via1[vIFR], (uint) via1[vIER]); 327 if (oss_present) { 328 printk(KERN_DEBUG "VIA2: <OSS>\n"); 329 } else if (rbv_present) { 330 printk(KERN_DEBUG "VIA2: IFR = 0x%02X IER = 0x%02X\n", 331 (uint) via2[rIFR], (uint) via2[rIER]); 332 printk(KERN_DEBUG " SIFR = 0x%02X SIER = 0x%02X\n", 333 (uint) via2[rSIFR], (uint) via2[rSIER]); 334 } else { 335 printk(KERN_DEBUG "VIA2: DDRA = 0x%02X DDRB = 0x%02X ACR = 0x%02X\n", 336 (uint) via2[vDirA], (uint) via2[vDirB], 337 (uint) via2[vACR]); 338 printk(KERN_DEBUG " PCR = 0x%02X IFR = 0x%02X IER = 0x%02X\n", 339 (uint) via2[vPCR], 340 (uint) via2[vIFR], (uint) via2[vIER]); 341 } 342 } 343 344 /* 345 * This is always executed with interrupts disabled. 346 * 347 * TBI: get time offset between scheduling timer ticks 348 */ 349 350 unsigned long mac_gettimeoffset (void) 351 { 352 unsigned long ticks, offset = 0; 353 354 /* read VIA1 timer 2 current value */ 355 ticks = via1[vT1CL] | (via1[vT1CH] << 8); 356 /* The probability of underflow is less than 2% */ 357 if (ticks > MAC_CLOCK_TICK - MAC_CLOCK_TICK / 50) 358 /* Check for pending timer interrupt in VIA1 IFR */ 359 if (via1[vIFR] & 0x40) offset = TICK_SIZE; 360 361 ticks = MAC_CLOCK_TICK - ticks; 362 ticks = ticks * 10000L / MAC_CLOCK_TICK; 363 364 return ticks + offset; 365 } 366 367 /* 368 * Flush the L2 cache on Macs that have it by flipping 369 * the system into 24-bit mode for an instant. 370 */ 371 372 void via_flush_cache(void) 373 { 374 via2[gBufB] &= ~VIA2B_vMode32; 375 via2[gBufB] |= VIA2B_vMode32; 376 } 377 378 /* 379 * Return the status of the L2 cache on a IIci 380 */ 381 382 int via_get_cache_disable(void) 383 { 384 /* Safeguard against being called accidentally */ 385 if (!via2) { 386 printk(KERN_ERR "via_get_cache_disable called on a non-VIA machine!\n"); 387 return 1; 388 } 389 390 return (int) via2[gBufB] & VIA2B_vCDis; 391 } 392 393 /* 394 * Initialize VIA2 for Nubus access 395 */ 396 397 void __init via_nubus_init(void) 398 { 399 /* unlock nubus transactions */ 400 401 if ((macintosh_config->adb_type != MAC_ADB_PB1) && 402 (macintosh_config->adb_type != MAC_ADB_PB2)) { 403 /* set the line to be an output on non-RBV machines */ 404 if (!rbv_present) 405 via2[vDirB] |= 0x02; 406 407 /* this seems to be an ADB bit on PMU machines */ 408 /* according to MkLinux. -- jmt */ 409 via2[gBufB] |= 0x02; 410 } 411 412 /* Disable all the slot interrupts (where possible). */ 413 414 switch (macintosh_config->via_type) { 415 case MAC_VIA_II: 416 /* Just make the port A lines inputs. */ 417 switch(macintosh_config->ident) { 418 case MAC_MODEL_II: 419 case MAC_MODEL_IIX: 420 case MAC_MODEL_IICX: 421 case MAC_MODEL_SE30: 422 /* The top two bits are RAM size outputs. */ 423 via2[vDirA] &= 0xC0; 424 break; 425 default: 426 via2[vDirA] &= 0x80; 427 } 428 break; 429 case MAC_VIA_IIci: 430 /* RBV. Disable all the slot interrupts. SIER works like IER. */ 431 via2[rSIER] = 0x7F; 432 break; 433 case MAC_VIA_QUADRA: 434 /* Disable the inactive slot interrupts by making those lines outputs. */ 435 if ((macintosh_config->adb_type != MAC_ADB_PB1) && 436 (macintosh_config->adb_type != MAC_ADB_PB2)) { 437 via2[vBufA] |= 0x7F; 438 via2[vDirA] |= 0x7F; 439 } 440 break; 441 } 442 } 443 444 /* 445 * The generic VIA interrupt routines (shamelessly stolen from Alan Cox's 446 * via6522.c :-), disable/pending masks added. 447 */ 448 449 irqreturn_t via1_irq(int irq, void *dev_id) 450 { 451 int irq_num; 452 unsigned char irq_bit, events; 453 454 events = via1[vIFR] & via1[vIER] & 0x7F; 455 if (!events) 456 return IRQ_NONE; 457 458 irq_num = VIA1_SOURCE_BASE; 459 irq_bit = 1; 460 do { 461 if (events & irq_bit) { 462 via1[vIFR] = irq_bit; 463 m68k_handle_int(irq_num); 464 } 465 ++irq_num; 466 irq_bit <<= 1; 467 } while (events >= irq_bit); 468 return IRQ_HANDLED; 469 } 470 471 irqreturn_t via2_irq(int irq, void *dev_id) 472 { 473 int irq_num; 474 unsigned char irq_bit, events; 475 476 events = via2[gIFR] & via2[gIER] & 0x7F; 477 if (!events) 478 return IRQ_NONE; 479 480 irq_num = VIA2_SOURCE_BASE; 481 irq_bit = 1; 482 do { 483 if (events & irq_bit) { 484 via2[gIFR] = irq_bit | rbv_clear; 485 m68k_handle_int(irq_num); 486 } 487 ++irq_num; 488 irq_bit <<= 1; 489 } while (events >= irq_bit); 490 return IRQ_HANDLED; 491 } 492 493 /* 494 * Dispatch Nubus interrupts. We are called as a secondary dispatch by the 495 * VIA2 dispatcher as a fast interrupt handler. 496 */ 497 498 irqreturn_t via_nubus_irq(int irq, void *dev_id) 499 { 500 int slot_irq; 501 unsigned char slot_bit, events; 502 503 events = ~via2[gBufA] & 0x7F; 504 if (rbv_present) 505 events &= via2[rSIER]; 506 else 507 events &= ~via2[vDirA]; 508 if (!events) 509 return IRQ_NONE; 510 511 do { 512 slot_irq = IRQ_NUBUS_F; 513 slot_bit = 0x40; 514 do { 515 if (events & slot_bit) { 516 events &= ~slot_bit; 517 m68k_handle_int(slot_irq); 518 } 519 --slot_irq; 520 slot_bit >>= 1; 521 } while (events); 522 523 /* clear the CA1 interrupt and make certain there's no more. */ 524 via2[gIFR] = 0x02 | rbv_clear; 525 events = ~via2[gBufA] & 0x7F; 526 if (rbv_present) 527 events &= via2[rSIER]; 528 else 529 events &= ~via2[vDirA]; 530 } while (events); 531 return IRQ_HANDLED; 532 } 533 534 void via_irq_enable(int irq) { 535 int irq_src = IRQ_SRC(irq); 536 int irq_idx = IRQ_IDX(irq); 537 538 #ifdef DEBUG_IRQUSE 539 printk(KERN_DEBUG "via_irq_enable(%d)\n", irq); 540 #endif 541 542 if (irq_src == 1) { 543 via1[vIER] = IER_SET_BIT(irq_idx); 544 } else if (irq_src == 2) { 545 if (irq != IRQ_MAC_NUBUS || nubus_disabled == 0) 546 via2[gIER] = IER_SET_BIT(irq_idx); 547 } else if (irq_src == 7) { 548 switch (macintosh_config->via_type) { 549 case MAC_VIA_II: 550 nubus_disabled &= ~(1 << irq_idx); 551 /* Enable the CA1 interrupt when no slot is disabled. */ 552 if (!nubus_disabled) 553 via2[gIER] = IER_SET_BIT(1); 554 break; 555 case MAC_VIA_IIci: 556 /* On RBV, enable the slot interrupt. 557 * SIER works like IER. 558 */ 559 via2[rSIER] = IER_SET_BIT(irq_idx); 560 break; 561 case MAC_VIA_QUADRA: 562 /* Make the port A line an input to enable the slot irq. 563 * But not on PowerBooks, that's ADB. 564 */ 565 if ((macintosh_config->adb_type != MAC_ADB_PB1) && 566 (macintosh_config->adb_type != MAC_ADB_PB2)) 567 via2[vDirA] &= ~(1 << irq_idx); 568 break; 569 } 570 } 571 } 572 573 void via_irq_disable(int irq) { 574 int irq_src = IRQ_SRC(irq); 575 int irq_idx = IRQ_IDX(irq); 576 577 #ifdef DEBUG_IRQUSE 578 printk(KERN_DEBUG "via_irq_disable(%d)\n", irq); 579 #endif 580 581 if (irq_src == 1) { 582 via1[vIER] = IER_CLR_BIT(irq_idx); 583 } else if (irq_src == 2) { 584 via2[gIER] = IER_CLR_BIT(irq_idx); 585 } else if (irq_src == 7) { 586 switch (macintosh_config->via_type) { 587 case MAC_VIA_II: 588 nubus_disabled |= 1 << irq_idx; 589 if (nubus_disabled) 590 via2[gIER] = IER_CLR_BIT(1); 591 break; 592 case MAC_VIA_IIci: 593 via2[rSIER] = IER_CLR_BIT(irq_idx); 594 break; 595 case MAC_VIA_QUADRA: 596 if ((macintosh_config->adb_type != MAC_ADB_PB1) && 597 (macintosh_config->adb_type != MAC_ADB_PB2)) 598 via2[vDirA] |= 1 << irq_idx; 599 break; 600 } 601 } 602 } 603 604 void via_irq_clear(int irq) { 605 int irq_src = IRQ_SRC(irq); 606 int irq_idx = IRQ_IDX(irq); 607 int irq_bit = 1 << irq_idx; 608 609 if (irq_src == 1) { 610 via1[vIFR] = irq_bit; 611 } else if (irq_src == 2) { 612 via2[gIFR] = irq_bit | rbv_clear; 613 } else if (irq_src == 7) { 614 /* FIXME: There is no way to clear an individual nubus slot 615 * IRQ flag, other than getting the device to do it. 616 */ 617 } 618 } 619 620 /* 621 * Returns nonzero if an interrupt is pending on the given 622 * VIA/IRQ combination. 623 */ 624 625 int via_irq_pending(int irq) 626 { 627 int irq_src = IRQ_SRC(irq); 628 int irq_idx = IRQ_IDX(irq); 629 int irq_bit = 1 << irq_idx; 630 631 if (irq_src == 1) { 632 return via1[vIFR] & irq_bit; 633 } else if (irq_src == 2) { 634 return via2[gIFR] & irq_bit; 635 } else if (irq_src == 7) { 636 /* Always 0 for MAC_VIA_QUADRA if the slot irq is disabled. */ 637 return ~via2[gBufA] & irq_bit; 638 } 639 return 0; 640 } 641 642 void via1_set_head(int head) 643 { 644 if (head == 0) 645 via1[vBufA] &= ~VIA1A_vHeadSel; 646 else 647 via1[vBufA] |= VIA1A_vHeadSel; 648 } 649 EXPORT_SYMBOL(via1_set_head); 650