1 /* 2 * 6522 Versatile Interface Adapter (VIA) 3 * 4 * There are two of these on the Mac II. Some IRQ's 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 * PRAM/RTC access algorithms are from the NetBSD RTC toolkit version 1.08b 17 * by Erik Vogan and adapted to Linux by Joshua M. Thompson (funaho@jurai.org) 18 * 19 */ 20 21 #include <linux/types.h> 22 #include <linux/kernel.h> 23 #include <linux/mm.h> 24 #include <linux/delay.h> 25 #include <linux/init.h> 26 #include <linux/ide.h> 27 28 #include <asm/bootinfo.h> 29 #include <asm/macintosh.h> 30 #include <asm/macints.h> 31 #include <asm/machw.h> 32 #include <asm/mac_via.h> 33 #include <asm/mac_psc.h> 34 35 volatile __u8 *via1, *via2; 36 #if 0 37 /* See note in mac_via.h about how this is possibly not useful */ 38 volatile long *via_memory_bogon=(long *)&via_memory_bogon; 39 #endif 40 int rbv_present,via_alt_mapping; 41 __u8 rbv_clear; 42 43 /* 44 * Globals for accessing the VIA chip registers without having to 45 * check if we're hitting a real VIA or an RBV. Normally you could 46 * just hit the combined register (ie, vIER|rIER) but that seems to 47 * break on AV Macs...probably because they actually decode more than 48 * eight address bits. Why can't Apple engineers at least be 49 * _consistently_ lazy? - 1999-05-21 (jmt) 50 */ 51 52 static int gIER,gIFR,gBufA,gBufB; 53 54 /* 55 * Timer defs. 56 */ 57 58 #define TICK_SIZE 10000 59 #define MAC_CLOCK_TICK (783300/HZ) /* ticks per HZ */ 60 #define MAC_CLOCK_LOW (MAC_CLOCK_TICK&0xFF) 61 #define MAC_CLOCK_HIGH (MAC_CLOCK_TICK>>8) 62 63 static int nubus_active; 64 65 void via_debug_dump(void); 66 irqreturn_t via1_irq(int, void *, struct pt_regs *); 67 irqreturn_t via2_irq(int, void *, struct pt_regs *); 68 irqreturn_t via_nubus_irq(int, void *, struct pt_regs *); 69 void via_irq_enable(int irq); 70 void via_irq_disable(int irq); 71 void via_irq_clear(int irq); 72 73 extern irqreturn_t mac_scc_dispatch(int, void *, struct pt_regs *); 74 extern int oss_present; 75 76 /* 77 * Initialize the VIAs 78 * 79 * First we figure out where they actually _are_ as well as what type of 80 * VIA we have for VIA2 (it could be a real VIA or an RBV or even an OSS.) 81 * Then we pretty much clear them out and disable all IRQ sources. 82 * 83 * Note: the OSS is actually "detected" here and not in oss_init(). It just 84 * seems more logical to do it here since via_init() needs to know 85 * these things anyways. 86 */ 87 88 void __init via_init(void) 89 { 90 switch(macintosh_config->via_type) { 91 92 /* IIci, IIsi, IIvx, IIvi (P6xx), LC series */ 93 94 case MAC_VIA_IIci: 95 via1 = (void *) VIA1_BASE; 96 if (macintosh_config->ident == MAC_MODEL_IIFX) { 97 via2 = NULL; 98 rbv_present = 0; 99 oss_present = 1; 100 } else { 101 via2 = (void *) RBV_BASE; 102 rbv_present = 1; 103 oss_present = 0; 104 } 105 if (macintosh_config->ident == MAC_MODEL_LCIII) { 106 rbv_clear = 0x00; 107 } else { 108 /* on most RBVs (& unlike the VIAs), you */ 109 /* need to set bit 7 when you write to IFR */ 110 /* in order for your clear to occur. */ 111 rbv_clear = 0x80; 112 } 113 gIER = rIER; 114 gIFR = rIFR; 115 gBufA = rSIFR; 116 gBufB = rBufB; 117 break; 118 119 /* Quadra and early MacIIs agree on the VIA locations */ 120 121 case MAC_VIA_QUADRA: 122 case MAC_VIA_II: 123 via1 = (void *) VIA1_BASE; 124 via2 = (void *) VIA2_BASE; 125 rbv_present = 0; 126 oss_present = 0; 127 rbv_clear = 0x00; 128 gIER = vIER; 129 gIFR = vIFR; 130 gBufA = vBufA; 131 gBufB = vBufB; 132 break; 133 default: 134 panic("UNKNOWN VIA TYPE"); 135 } 136 137 printk(KERN_INFO "VIA1 at %p is a 6522 or clone\n", via1); 138 139 printk(KERN_INFO "VIA2 at %p is ", via2); 140 if (rbv_present) { 141 printk(KERN_INFO "an RBV\n"); 142 } else if (oss_present) { 143 printk(KERN_INFO "an OSS\n"); 144 } else { 145 printk(KERN_INFO "a 6522 or clone\n"); 146 } 147 148 #ifdef DEBUG_VIA 149 via_debug_dump(); 150 #endif 151 152 /* 153 * Shut down all IRQ sources, reset the timers, and 154 * kill the timer latch on VIA1. 155 */ 156 157 via1[vIER] = 0x7F; 158 via1[vIFR] = 0x7F; 159 via1[vT1LL] = 0; 160 via1[vT1LH] = 0; 161 via1[vT1CL] = 0; 162 via1[vT1CH] = 0; 163 via1[vT2CL] = 0; 164 via1[vT2CH] = 0; 165 via1[vACR] &= 0x3F; 166 167 /* 168 * SE/30: disable video IRQ 169 * XXX: testing for SE/30 VBL 170 */ 171 172 if (macintosh_config->ident == MAC_MODEL_SE30) { 173 via1[vDirB] |= 0x40; 174 via1[vBufB] |= 0x40; 175 } 176 177 /* 178 * Set the RTC bits to a known state: all lines to outputs and 179 * RTC disabled (yes that's 0 to enable and 1 to disable). 180 */ 181 182 via1[vDirB] |= (VIA1B_vRTCEnb | VIA1B_vRTCClk | VIA1B_vRTCData); 183 via1[vBufB] |= (VIA1B_vRTCEnb | VIA1B_vRTCClk); 184 185 /* Everything below this point is VIA2/RBV only... */ 186 187 if (oss_present) return; 188 189 #if 1 190 /* Some machines support an alternate IRQ mapping that spreads */ 191 /* Ethernet and Sound out to their own autolevel IRQs and moves */ 192 /* VIA1 to level 6. A/UX uses this mapping and we do too. Note */ 193 /* that the IIfx emulates this alternate mapping using the OSS. */ 194 195 switch(macintosh_config->ident) { 196 case MAC_MODEL_C610: 197 case MAC_MODEL_Q610: 198 case MAC_MODEL_C650: 199 case MAC_MODEL_Q650: 200 case MAC_MODEL_Q700: 201 case MAC_MODEL_Q800: 202 case MAC_MODEL_Q900: 203 case MAC_MODEL_Q950: 204 via_alt_mapping = 1; 205 via1[vDirB] |= 0x40; 206 via1[vBufB] &= ~0x40; 207 break; 208 default: 209 via_alt_mapping = 0; 210 break; 211 } 212 #else 213 via_alt_mapping = 0; 214 #endif 215 216 /* 217 * Now initialize VIA2. For RBV we just kill all interrupts; 218 * for a regular VIA we also reset the timers and stuff. 219 */ 220 221 via2[gIER] = 0x7F; 222 via2[gIFR] = 0x7F | rbv_clear; 223 if (!rbv_present) { 224 via2[vT1LL] = 0; 225 via2[vT1LH] = 0; 226 via2[vT1CL] = 0; 227 via2[vT1CH] = 0; 228 via2[vT2CL] = 0; 229 via2[vT2CH] = 0; 230 via2[vACR] &= 0x3F; 231 } 232 } 233 234 /* 235 * Start the 100 Hz clock 236 */ 237 238 void __init via_init_clock(irqreturn_t (*func)(int, void *, struct pt_regs *)) 239 { 240 via1[vACR] |= 0x40; 241 via1[vT1LL] = MAC_CLOCK_LOW; 242 via1[vT1LH] = MAC_CLOCK_HIGH; 243 via1[vT1CL] = MAC_CLOCK_LOW; 244 via1[vT1CH] = MAC_CLOCK_HIGH; 245 246 request_irq(IRQ_MAC_TIMER_1, func, IRQ_FLG_LOCK, "timer", func); 247 } 248 249 /* 250 * Register the interrupt dispatchers for VIA or RBV machines only. 251 */ 252 253 void __init via_register_interrupts(void) 254 { 255 if (via_alt_mapping) { 256 request_irq(IRQ_AUTO_1, via1_irq, 257 IRQ_FLG_LOCK|IRQ_FLG_FAST, "software", 258 (void *) via1); 259 request_irq(IRQ_AUTO_6, via1_irq, 260 IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1", 261 (void *) via1); 262 } else { 263 request_irq(IRQ_AUTO_1, via1_irq, 264 IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1", 265 (void *) via1); 266 } 267 request_irq(IRQ_AUTO_2, via2_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST, 268 "via2", (void *) via2); 269 if (!psc_present) { 270 request_irq(IRQ_AUTO_4, mac_scc_dispatch, IRQ_FLG_LOCK, 271 "scc", mac_scc_dispatch); 272 } 273 request_irq(IRQ_MAC_NUBUS, via_nubus_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST, 274 "nubus", (void *) via2); 275 } 276 277 /* 278 * Debugging dump, used in various places to see what's going on. 279 */ 280 281 void via_debug_dump(void) 282 { 283 printk(KERN_DEBUG "VIA1: DDRA = 0x%02X DDRB = 0x%02X ACR = 0x%02X\n", 284 (uint) via1[vDirA], (uint) via1[vDirB], (uint) via1[vACR]); 285 printk(KERN_DEBUG " PCR = 0x%02X IFR = 0x%02X IER = 0x%02X\n", 286 (uint) via1[vPCR], (uint) via1[vIFR], (uint) via1[vIER]); 287 if (oss_present) { 288 printk(KERN_DEBUG "VIA2: <OSS>\n"); 289 } else if (rbv_present) { 290 printk(KERN_DEBUG "VIA2: IFR = 0x%02X IER = 0x%02X\n", 291 (uint) via2[rIFR], (uint) via2[rIER]); 292 printk(KERN_DEBUG " SIFR = 0x%02X SIER = 0x%02X\n", 293 (uint) via2[rSIFR], (uint) via2[rSIER]); 294 } else { 295 printk(KERN_DEBUG "VIA2: DDRA = 0x%02X DDRB = 0x%02X ACR = 0x%02X\n", 296 (uint) via2[vDirA], (uint) via2[vDirB], 297 (uint) via2[vACR]); 298 printk(KERN_DEBUG " PCR = 0x%02X IFR = 0x%02X IER = 0x%02X\n", 299 (uint) via2[vPCR], 300 (uint) via2[vIFR], (uint) via2[vIER]); 301 } 302 } 303 304 /* 305 * This is always executed with interrupts disabled. 306 * 307 * TBI: get time offset between scheduling timer ticks 308 */ 309 310 unsigned long mac_gettimeoffset (void) 311 { 312 unsigned long ticks, offset = 0; 313 314 /* read VIA1 timer 2 current value */ 315 ticks = via1[vT1CL] | (via1[vT1CH] << 8); 316 /* The probability of underflow is less than 2% */ 317 if (ticks > MAC_CLOCK_TICK - MAC_CLOCK_TICK / 50) 318 /* Check for pending timer interrupt in VIA1 IFR */ 319 if (via1[vIFR] & 0x40) offset = TICK_SIZE; 320 321 ticks = MAC_CLOCK_TICK - ticks; 322 ticks = ticks * 10000L / MAC_CLOCK_TICK; 323 324 return ticks + offset; 325 } 326 327 /* 328 * Flush the L2 cache on Macs that have it by flipping 329 * the system into 24-bit mode for an instant. 330 */ 331 332 void via_flush_cache(void) 333 { 334 via2[gBufB] &= ~VIA2B_vMode32; 335 via2[gBufB] |= VIA2B_vMode32; 336 } 337 338 /* 339 * Return the status of the L2 cache on a IIci 340 */ 341 342 int via_get_cache_disable(void) 343 { 344 /* Safeguard against being called accidentally */ 345 if (!via2) { 346 printk(KERN_ERR "via_get_cache_disable called on a non-VIA machine!\n"); 347 return 1; 348 } 349 350 return (int) via2[gBufB] & VIA2B_vCDis; 351 } 352 353 /* 354 * Initialize VIA2 for Nubus access 355 */ 356 357 void __init via_nubus_init(void) 358 { 359 /* don't set nubus_active = 0 here, it kills the Baboon */ 360 /* interrupt that we've already registered. */ 361 362 /* unlock nubus transactions */ 363 364 if (!rbv_present) { 365 /* set the line to be an output on non-RBV machines */ 366 if ((macintosh_config->adb_type != MAC_ADB_PB1) && 367 (macintosh_config->adb_type != MAC_ADB_PB2)) { 368 via2[vDirB] |= 0x02; 369 } 370 } 371 372 /* this seems to be an ADB bit on PMU machines */ 373 /* according to MkLinux. -- jmt */ 374 375 if ((macintosh_config->adb_type != MAC_ADB_PB1) && 376 (macintosh_config->adb_type != MAC_ADB_PB2)) { 377 via2[gBufB] |= 0x02; 378 } 379 380 /* disable nubus slot interrupts. */ 381 if (rbv_present) { 382 via2[rSIER] = 0x7F; 383 via2[rSIER] = nubus_active | 0x80; 384 } else { 385 /* These are ADB bits on PMU */ 386 if ((macintosh_config->adb_type != MAC_ADB_PB1) && 387 (macintosh_config->adb_type != MAC_ADB_PB2)) { 388 switch(macintosh_config->ident) 389 { 390 case MAC_MODEL_II: 391 case MAC_MODEL_IIX: 392 case MAC_MODEL_IICX: 393 case MAC_MODEL_SE30: 394 via2[vBufA] |= 0x3F; 395 via2[vDirA] = ~nubus_active | 0xc0; 396 break; 397 default: 398 via2[vBufA] = 0xFF; 399 via2[vDirA] = ~nubus_active; 400 } 401 } 402 } 403 } 404 405 /* 406 * The generic VIA interrupt routines (shamelessly stolen from Alan Cox's 407 * via6522.c :-), disable/pending masks added. 408 * 409 * The new interrupt architecture in macints.c takes care of a lot of the 410 * gruntwork for us, including tallying the interrupts and calling the 411 * handlers on the linked list. All we need to do here is basically generate 412 * the machspec interrupt number after clearing the interrupt. 413 */ 414 415 irqreturn_t via1_irq(int irq, void *dev_id, struct pt_regs *regs) 416 { 417 int irq_bit, i; 418 unsigned char events, mask; 419 420 mask = via1[vIER] & 0x7F; 421 if (!(events = via1[vIFR] & mask)) 422 return IRQ_NONE; 423 424 for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1) 425 if (events & irq_bit) { 426 via1[vIER] = irq_bit; 427 m68k_handle_int(VIA1_SOURCE_BASE + i, regs); 428 via1[vIFR] = irq_bit; 429 via1[vIER] = irq_bit | 0x80; 430 } 431 432 #if 0 /* freakin' pmu is doing weird stuff */ 433 if (!oss_present) { 434 /* This (still) seems to be necessary to get IDE 435 working. However, if you enable VBL interrupts, 436 you're screwed... */ 437 /* FIXME: should we check the SLOTIRQ bit before 438 pulling this stunt? */ 439 /* No, it won't be set. that's why we're doing this. */ 440 via_irq_disable(IRQ_MAC_NUBUS); 441 via_irq_clear(IRQ_MAC_NUBUS); 442 m68k_handle_int(IRQ_MAC_NUBUS, regs); 443 via_irq_enable(IRQ_MAC_NUBUS); 444 } 445 #endif 446 return IRQ_HANDLED; 447 } 448 449 irqreturn_t via2_irq(int irq, void *dev_id, struct pt_regs *regs) 450 { 451 int irq_bit, i; 452 unsigned char events, mask; 453 454 mask = via2[gIER] & 0x7F; 455 if (!(events = via2[gIFR] & mask)) 456 return IRQ_NONE; 457 458 for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1) 459 if (events & irq_bit) { 460 via2[gIER] = irq_bit; 461 via2[gIFR] = irq_bit | rbv_clear; 462 m68k_handle_int(VIA2_SOURCE_BASE + i, regs); 463 via2[gIER] = irq_bit | 0x80; 464 } 465 return IRQ_HANDLED; 466 } 467 468 /* 469 * Dispatch Nubus interrupts. We are called as a secondary dispatch by the 470 * VIA2 dispatcher as a fast interrupt handler. 471 */ 472 473 irqreturn_t via_nubus_irq(int irq, void *dev_id, struct pt_regs *regs) 474 { 475 int irq_bit, i; 476 unsigned char events; 477 478 if (!(events = ~via2[gBufA] & nubus_active)) 479 return IRQ_NONE; 480 481 for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1) { 482 if (events & irq_bit) { 483 via_irq_disable(NUBUS_SOURCE_BASE + i); 484 m68k_handle_int(NUBUS_SOURCE_BASE + i, regs); 485 via_irq_enable(NUBUS_SOURCE_BASE + i); 486 } 487 } 488 return IRQ_HANDLED; 489 } 490 491 void via_irq_enable(int irq) { 492 int irq_src = IRQ_SRC(irq); 493 int irq_idx = IRQ_IDX(irq); 494 int irq_bit = 1 << irq_idx; 495 496 #ifdef DEBUG_IRQUSE 497 printk(KERN_DEBUG "via_irq_enable(%d)\n", irq); 498 #endif 499 500 if (irq_src == 1) { 501 via1[vIER] = irq_bit | 0x80; 502 } else if (irq_src == 2) { 503 /* 504 * Set vPCR for SCSI interrupts (but not on RBV) 505 */ 506 if ((irq_idx == 0) && !rbv_present) { 507 if (macintosh_config->scsi_type == MAC_SCSI_OLD) { 508 /* CB2 (IRQ) indep. input, positive edge */ 509 /* CA2 (DRQ) indep. input, positive edge */ 510 via2[vPCR] = 0x66; 511 } else { 512 /* CB2 (IRQ) indep. input, negative edge */ 513 /* CA2 (DRQ) indep. input, negative edge */ 514 via2[vPCR] = 0x22; 515 } 516 } 517 via2[gIER] = irq_bit | 0x80; 518 } else if (irq_src == 7) { 519 nubus_active |= irq_bit; 520 if (rbv_present) { 521 /* enable the slot interrupt. SIER works like IER. */ 522 via2[rSIER] = IER_SET_BIT(irq_idx); 523 } else { 524 /* Make sure the bit is an input, to enable the irq */ 525 /* But not on PowerBooks, that's ADB... */ 526 if ((macintosh_config->adb_type != MAC_ADB_PB1) && 527 (macintosh_config->adb_type != MAC_ADB_PB2)) { 528 switch(macintosh_config->ident) 529 { 530 case MAC_MODEL_II: 531 case MAC_MODEL_IIX: 532 case MAC_MODEL_IICX: 533 case MAC_MODEL_SE30: 534 via2[vDirA] &= (~irq_bit | 0xc0); 535 break; 536 default: 537 via2[vDirA] &= ~irq_bit; 538 } 539 } 540 } 541 } 542 } 543 544 void via_irq_disable(int irq) { 545 int irq_src = IRQ_SRC(irq); 546 int irq_idx = IRQ_IDX(irq); 547 int irq_bit = 1 << irq_idx; 548 549 #ifdef DEBUG_IRQUSE 550 printk(KERN_DEBUG "via_irq_disable(%d)\n", irq); 551 #endif 552 553 if (irq_src == 1) { 554 via1[vIER] = irq_bit; 555 } else if (irq_src == 2) { 556 via2[gIER] = irq_bit; 557 } else if (irq_src == 7) { 558 if (rbv_present) { 559 /* disable the slot interrupt. SIER works like IER. */ 560 via2[rSIER] = IER_CLR_BIT(irq_idx); 561 } else { 562 /* disable the nubus irq by changing dir to output */ 563 /* except on PMU */ 564 if ((macintosh_config->adb_type != MAC_ADB_PB1) && 565 (macintosh_config->adb_type != MAC_ADB_PB2)) { 566 via2[vDirA] |= irq_bit; 567 } 568 } 569 nubus_active &= ~irq_bit; 570 } 571 } 572 573 void via_irq_clear(int irq) { 574 int irq_src = IRQ_SRC(irq); 575 int irq_idx = IRQ_IDX(irq); 576 int irq_bit = 1 << irq_idx; 577 578 if (irq_src == 1) { 579 via1[vIFR] = irq_bit; 580 } else if (irq_src == 2) { 581 via2[gIFR] = irq_bit | rbv_clear; 582 } else if (irq_src == 7) { 583 /* FIXME: hmm.. */ 584 } 585 } 586 587 /* 588 * Returns nonzero if an interrupt is pending on the given 589 * VIA/IRQ combination. 590 */ 591 592 int via_irq_pending(int irq) 593 { 594 int irq_src = IRQ_SRC(irq); 595 int irq_idx = IRQ_IDX(irq); 596 int irq_bit = 1 << irq_idx; 597 598 if (irq_src == 1) { 599 return via1[vIFR] & irq_bit; 600 } else if (irq_src == 2) { 601 return via2[gIFR] & irq_bit; 602 } else if (irq_src == 7) { 603 return ~via2[gBufA] & irq_bit; 604 } 605 return 0; 606 } 607