linux/arch/m68k/mac/via.c
<<
>>
Prefs
   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#include <linux/irq.h>
  32
  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
  39volatile __u8 *via1, *via2;
  40int rbv_present;
  41int via_alt_mapping;
  42EXPORT_SYMBOL(via_alt_mapping);
  43static __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
  54static 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
  66/*
  67 * On Macs with a genuine VIA chip there is no way to mask an individual slot
  68 * interrupt. This limitation also seems to apply to VIA clone logic cores in
  69 * Quadra-like ASICs. (RBV and OSS machines don't have this limitation.)
  70 *
  71 * We used to fake it by configuring the relevant VIA pin as an output
  72 * (to mask the interrupt) or input (to unmask). That scheme did not work on
  73 * (at least) the Quadra 700. A NuBus card's /NMRQ signal is an open-collector
  74 * circuit (see Designing Cards and Drivers for Macintosh II and Macintosh SE,
  75 * p. 10-11 etc) but VIA outputs are not (see datasheet).
  76 *
  77 * Driving these outputs high must cause the VIA to source current and the
  78 * card to sink current when it asserts /NMRQ. Current will flow but the pin
  79 * voltage is uncertain and so the /NMRQ condition may still cause a transition
  80 * at the VIA2 CA1 input (which explains the lost interrupts). A side effect
  81 * is that a disabled slot IRQ can never be tested as pending or not.
  82 *
  83 * Driving these outputs low doesn't work either. All the slot /NMRQ lines are
  84 * (active low) OR'd together to generate the CA1 (aka "SLOTS") interrupt (see
  85 * The Guide To Macintosh Family Hardware, 2nd edition p. 167). If we drive a
  86 * disabled /NMRQ line low, the falling edge immediately triggers a CA1
  87 * interrupt and all slot interrupts after that will generate no transition
  88 * and therefore no interrupt, even after being re-enabled.
  89 *
  90 * So we make the VIA port A I/O lines inputs and use nubus_disabled to keep
  91 * track of their states. When any slot IRQ becomes disabled we mask the CA1
  92 * umbrella interrupt. Only when all slot IRQs become enabled do we unmask
  93 * the CA1 interrupt. It must remain enabled even when cards have no interrupt
  94 * handler registered. Drivers must therefore disable a slot interrupt at the
  95 * device before they call free_irq (like shared and autovector interrupts).
  96 *
  97 * There is also a related problem when MacOS is used to boot Linux. A network
  98 * card brought up by a MacOS driver may raise an interrupt while Linux boots.
  99 * This can be fatal since it can't be handled until the right driver loads
 100 * (if such a driver exists at all). Apparently related to this hardware
 101 * limitation, "Designing Cards and Drivers", p. 9-8, says that a slot
 102 * interrupt with no driver would crash MacOS (the book was written before
 103 * the appearance of Macs with RBV or OSS).
 104 */
 105
 106static u8 nubus_disabled;
 107
 108void via_debug_dump(void);
 109
 110/*
 111 * Initialize the VIAs
 112 *
 113 * First we figure out where they actually _are_ as well as what type of
 114 * VIA we have for VIA2 (it could be a real VIA or an RBV or even an OSS.)
 115 * Then we pretty much clear them out and disable all IRQ sources.
 116 *
 117 * Note: the OSS is actually "detected" here and not in oss_init(). It just
 118 *       seems more logical to do it here since via_init() needs to know
 119 *       these things anyways.
 120 */
 121
 122void __init via_init(void)
 123{
 124        switch(macintosh_config->via_type) {
 125
 126                /* IIci, IIsi, IIvx, IIvi (P6xx), LC series */
 127
 128                case MAC_VIA_IICI:
 129                        via1 = (void *) VIA1_BASE;
 130                        if (macintosh_config->ident == MAC_MODEL_IIFX) {
 131                                via2 = NULL;
 132                                rbv_present = 0;
 133                                oss_present = 1;
 134                        } else {
 135                                via2 = (void *) RBV_BASE;
 136                                rbv_present = 1;
 137                                oss_present = 0;
 138                        }
 139                        if (macintosh_config->ident == MAC_MODEL_LCIII) {
 140                                rbv_clear = 0x00;
 141                        } else {
 142                                /* on most RBVs (& unlike the VIAs), you   */
 143                                /* need to set bit 7 when you write to IFR */
 144                                /* in order for your clear to occur.       */
 145                                rbv_clear = 0x80;
 146                        }
 147                        gIER = rIER;
 148                        gIFR = rIFR;
 149                        gBufA = rSIFR;
 150                        gBufB = rBufB;
 151                        break;
 152
 153                /* Quadra and early MacIIs agree on the VIA locations */
 154
 155                case MAC_VIA_QUADRA:
 156                case MAC_VIA_II:
 157                        via1 = (void *) VIA1_BASE;
 158                        via2 = (void *) VIA2_BASE;
 159                        rbv_present = 0;
 160                        oss_present = 0;
 161                        rbv_clear = 0x00;
 162                        gIER = vIER;
 163                        gIFR = vIFR;
 164                        gBufA = vBufA;
 165                        gBufB = vBufB;
 166                        break;
 167                default:
 168                        panic("UNKNOWN VIA TYPE");
 169        }
 170
 171        printk(KERN_INFO "VIA1 at %p is a 6522 or clone\n", via1);
 172
 173        printk(KERN_INFO "VIA2 at %p is ", via2);
 174        if (rbv_present) {
 175                printk("an RBV\n");
 176        } else if (oss_present) {
 177                printk("an OSS\n");
 178        } else {
 179                printk("a 6522 or clone\n");
 180        }
 181
 182#ifdef DEBUG_VIA
 183        via_debug_dump();
 184#endif
 185
 186        /*
 187         * Shut down all IRQ sources, reset the timers, and
 188         * kill the timer latch on VIA1.
 189         */
 190
 191        via1[vIER] = 0x7F;
 192        via1[vIFR] = 0x7F;
 193        via1[vT1LL] = 0;
 194        via1[vT1LH] = 0;
 195        via1[vT1CL] = 0;
 196        via1[vT1CH] = 0;
 197        via1[vT2CL] = 0;
 198        via1[vT2CH] = 0;
 199        via1[vACR] &= ~0xC0; /* setup T1 timer with no PB7 output */
 200        via1[vACR] &= ~0x03; /* disable port A & B latches */
 201
 202        /*
 203         * SE/30: disable video IRQ
 204         * XXX: testing for SE/30 VBL
 205         */
 206
 207        if (macintosh_config->ident == MAC_MODEL_SE30) {
 208                via1[vDirB] |= 0x40;
 209                via1[vBufB] |= 0x40;
 210        }
 211
 212        /*
 213         * Set the RTC bits to a known state: all lines to outputs and
 214         * RTC disabled (yes that's 0 to enable and 1 to disable).
 215         */
 216
 217        via1[vDirB] |= (VIA1B_vRTCEnb | VIA1B_vRTCClk | VIA1B_vRTCData);
 218        via1[vBufB] |= (VIA1B_vRTCEnb | VIA1B_vRTCClk);
 219
 220        /* Everything below this point is VIA2/RBV only... */
 221
 222        if (oss_present)
 223                return;
 224
 225        if ((macintosh_config->via_type == MAC_VIA_QUADRA) &&
 226            (macintosh_config->adb_type != MAC_ADB_PB1) &&
 227            (macintosh_config->adb_type != MAC_ADB_PB2) &&
 228            (macintosh_config->ident    != MAC_MODEL_C660) &&
 229            (macintosh_config->ident    != MAC_MODEL_Q840)) {
 230                via_alt_mapping = 1;
 231                via1[vDirB] |= 0x40;
 232                via1[vBufB] &= ~0x40;
 233        } else {
 234                via_alt_mapping = 0;
 235        }
 236
 237        /*
 238         * Now initialize VIA2. For RBV we just kill all interrupts;
 239         * for a regular VIA we also reset the timers and stuff.
 240         */
 241
 242        via2[gIER] = 0x7F;
 243        via2[gIFR] = 0x7F | rbv_clear;
 244        if (!rbv_present) {
 245                via2[vT1LL] = 0;
 246                via2[vT1LH] = 0;
 247                via2[vT1CL] = 0;
 248                via2[vT1CH] = 0;
 249                via2[vT2CL] = 0;
 250                via2[vT2CH] = 0;
 251                via2[vACR] &= ~0xC0; /* setup T1 timer with no PB7 output */
 252                via2[vACR] &= ~0x03; /* disable port A & B latches */
 253        }
 254
 255        /* Everything below this point is VIA2 only... */
 256
 257        if (rbv_present)
 258                return;
 259
 260        /*
 261         * Set vPCR for control line interrupts.
 262         *
 263         * CA1 (SLOTS IRQ), CB1 (ASC IRQ): negative edge trigger.
 264         *
 265         * Macs with ESP SCSI have a negative edge triggered SCSI interrupt.
 266         * Testing reveals that PowerBooks do too. However, the SE/30
 267         * schematic diagram shows an active high NCR5380 IRQ line.
 268         */
 269
 270        pr_debug("VIA2 vPCR is 0x%02X\n", via2[vPCR]);
 271        if (macintosh_config->via_type == MAC_VIA_II) {
 272                /* CA2 (SCSI DRQ), CB2 (SCSI IRQ): indep. input, pos. edge */
 273                via2[vPCR] = 0x66;
 274        } else {
 275                /* CA2 (SCSI DRQ), CB2 (SCSI IRQ): indep. input, neg. edge */
 276                via2[vPCR] = 0x22;
 277        }
 278}
 279
 280/*
 281 * Start the 100 Hz clock
 282 */
 283
 284void __init via_init_clock(irq_handler_t func)
 285{
 286        via1[vACR] |= 0x40;
 287        via1[vT1LL] = MAC_CLOCK_LOW;
 288        via1[vT1LH] = MAC_CLOCK_HIGH;
 289        via1[vT1CL] = MAC_CLOCK_LOW;
 290        via1[vT1CH] = MAC_CLOCK_HIGH;
 291
 292        if (request_irq(IRQ_MAC_TIMER_1, func, 0, "timer", func))
 293                pr_err("Couldn't register %s interrupt\n", "timer");
 294}
 295
 296/*
 297 * Debugging dump, used in various places to see what's going on.
 298 */
 299
 300void via_debug_dump(void)
 301{
 302        printk(KERN_DEBUG "VIA1: DDRA = 0x%02X DDRB = 0x%02X ACR = 0x%02X\n",
 303                (uint) via1[vDirA], (uint) via1[vDirB], (uint) via1[vACR]);
 304        printk(KERN_DEBUG "         PCR = 0x%02X  IFR = 0x%02X IER = 0x%02X\n",
 305                (uint) via1[vPCR], (uint) via1[vIFR], (uint) via1[vIER]);
 306        if (oss_present) {
 307                printk(KERN_DEBUG "VIA2: <OSS>\n");
 308        } else if (rbv_present) {
 309                printk(KERN_DEBUG "VIA2:  IFR = 0x%02X  IER = 0x%02X\n",
 310                        (uint) via2[rIFR], (uint) via2[rIER]);
 311                printk(KERN_DEBUG "      SIFR = 0x%02X SIER = 0x%02X\n",
 312                        (uint) via2[rSIFR], (uint) via2[rSIER]);
 313        } else {
 314                printk(KERN_DEBUG "VIA2: DDRA = 0x%02X DDRB = 0x%02X ACR = 0x%02X\n",
 315                        (uint) via2[vDirA], (uint) via2[vDirB],
 316                        (uint) via2[vACR]);
 317                printk(KERN_DEBUG "         PCR = 0x%02X  IFR = 0x%02X IER = 0x%02X\n",
 318                        (uint) via2[vPCR],
 319                        (uint) via2[vIFR], (uint) via2[vIER]);
 320        }
 321}
 322
 323/*
 324 * This is always executed with interrupts disabled.
 325 *
 326 * TBI: get time offset between scheduling timer ticks
 327 */
 328
 329u32 mac_gettimeoffset(void)
 330{
 331        unsigned long ticks, offset = 0;
 332
 333        /* read VIA1 timer 2 current value */
 334        ticks = via1[vT1CL] | (via1[vT1CH] << 8);
 335        /* The probability of underflow is less than 2% */
 336        if (ticks > MAC_CLOCK_TICK - MAC_CLOCK_TICK / 50)
 337                /* Check for pending timer interrupt in VIA1 IFR */
 338                if (via1[vIFR] & 0x40) offset = TICK_SIZE;
 339
 340        ticks = MAC_CLOCK_TICK - ticks;
 341        ticks = ticks * 10000L / MAC_CLOCK_TICK;
 342
 343        return (ticks + offset) * 1000;
 344}
 345
 346/*
 347 * Flush the L2 cache on Macs that have it by flipping
 348 * the system into 24-bit mode for an instant.
 349 */
 350
 351void via_flush_cache(void)
 352{
 353        via2[gBufB] &= ~VIA2B_vMode32;
 354        via2[gBufB] |= VIA2B_vMode32;
 355}
 356
 357/*
 358 * Return the status of the L2 cache on a IIci
 359 */
 360
 361int via_get_cache_disable(void)
 362{
 363        /* Safeguard against being called accidentally */
 364        if (!via2) {
 365                printk(KERN_ERR "via_get_cache_disable called on a non-VIA machine!\n");
 366                return 1;
 367        }
 368
 369        return (int) via2[gBufB] & VIA2B_vCDis;
 370}
 371
 372/*
 373 * Initialize VIA2 for Nubus access
 374 */
 375
 376void __init via_nubus_init(void)
 377{
 378        /* unlock nubus transactions */
 379
 380        if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
 381            (macintosh_config->adb_type != MAC_ADB_PB2)) {
 382                /* set the line to be an output on non-RBV machines */
 383                if (!rbv_present)
 384                        via2[vDirB] |= 0x02;
 385
 386                /* this seems to be an ADB bit on PMU machines */
 387                /* according to MkLinux.  -- jmt               */
 388                via2[gBufB] |= 0x02;
 389        }
 390
 391        /*
 392         * Disable the slot interrupts. On some hardware that's not possible.
 393         * On some hardware it's unclear what all of these I/O lines do.
 394         */
 395
 396        switch (macintosh_config->via_type) {
 397        case MAC_VIA_II:
 398        case MAC_VIA_QUADRA:
 399                pr_debug("VIA2 vDirA is 0x%02X\n", via2[vDirA]);
 400                break;
 401        case MAC_VIA_IICI:
 402                /* RBV. Disable all the slot interrupts. SIER works like IER. */
 403                via2[rSIER] = 0x7F;
 404                break;
 405        }
 406}
 407
 408void via_nubus_irq_startup(int irq)
 409{
 410        int irq_idx = IRQ_IDX(irq);
 411
 412        switch (macintosh_config->via_type) {
 413        case MAC_VIA_II:
 414        case MAC_VIA_QUADRA:
 415                /* Make the port A line an input. Probably redundant. */
 416                if (macintosh_config->via_type == MAC_VIA_II) {
 417                        /* The top two bits are RAM size outputs. */
 418                        via2[vDirA] &= 0xC0 | ~(1 << irq_idx);
 419                } else {
 420                        /* Allow NuBus slots 9 through F. */
 421                        via2[vDirA] &= 0x80 | ~(1 << irq_idx);
 422                }
 423                /* fall through */
 424        case MAC_VIA_IICI:
 425                via_irq_enable(irq);
 426                break;
 427        }
 428}
 429
 430void via_nubus_irq_shutdown(int irq)
 431{
 432        switch (macintosh_config->via_type) {
 433        case MAC_VIA_II:
 434        case MAC_VIA_QUADRA:
 435                /* Ensure that the umbrella CA1 interrupt remains enabled. */
 436                via_irq_enable(irq);
 437                break;
 438        case MAC_VIA_IICI:
 439                via_irq_disable(irq);
 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
 449void via1_irq(struct irq_desc *desc)
 450{
 451        int irq_num;
 452        unsigned char irq_bit, events;
 453
 454        events = via1[vIFR] & via1[vIER] & 0x7F;
 455        if (!events)
 456                return;
 457
 458        irq_num = VIA1_SOURCE_BASE;
 459        irq_bit = 1;
 460        do {
 461                if (events & irq_bit) {
 462                        via1[vIFR] = irq_bit;
 463                        generic_handle_irq(irq_num);
 464                }
 465                ++irq_num;
 466                irq_bit <<= 1;
 467        } while (events >= irq_bit);
 468}
 469
 470static void via2_irq(struct irq_desc *desc)
 471{
 472        int irq_num;
 473        unsigned char irq_bit, events;
 474
 475        events = via2[gIFR] & via2[gIER] & 0x7F;
 476        if (!events)
 477                return;
 478
 479        irq_num = VIA2_SOURCE_BASE;
 480        irq_bit = 1;
 481        do {
 482                if (events & irq_bit) {
 483                        via2[gIFR] = irq_bit | rbv_clear;
 484                        generic_handle_irq(irq_num);
 485                }
 486                ++irq_num;
 487                irq_bit <<= 1;
 488        } while (events >= irq_bit);
 489}
 490
 491/*
 492 * Dispatch Nubus interrupts. We are called as a secondary dispatch by the
 493 * VIA2 dispatcher as a fast interrupt handler.
 494 */
 495
 496static void via_nubus_irq(struct irq_desc *desc)
 497{
 498        int slot_irq;
 499        unsigned char slot_bit, events;
 500
 501        events = ~via2[gBufA] & 0x7F;
 502        if (rbv_present)
 503                events &= via2[rSIER];
 504        else
 505                events &= ~via2[vDirA];
 506        if (!events)
 507                return;
 508
 509        do {
 510                slot_irq = IRQ_NUBUS_F;
 511                slot_bit = 0x40;
 512                do {
 513                        if (events & slot_bit) {
 514                                events &= ~slot_bit;
 515                                generic_handle_irq(slot_irq);
 516                        }
 517                        --slot_irq;
 518                        slot_bit >>= 1;
 519                } while (events);
 520
 521                /* clear the CA1 interrupt and make certain there's no more. */
 522                via2[gIFR] = 0x02 | rbv_clear;
 523                events = ~via2[gBufA] & 0x7F;
 524                if (rbv_present)
 525                        events &= via2[rSIER];
 526                else
 527                        events &= ~via2[vDirA];
 528        } while (events);
 529}
 530
 531/*
 532 * Register the interrupt dispatchers for VIA or RBV machines only.
 533 */
 534
 535void __init via_register_interrupts(void)
 536{
 537        if (via_alt_mapping) {
 538                /* software interrupt */
 539                irq_set_chained_handler(IRQ_AUTO_1, via1_irq);
 540                /* via1 interrupt */
 541                irq_set_chained_handler(IRQ_AUTO_6, via1_irq);
 542        } else {
 543                irq_set_chained_handler(IRQ_AUTO_1, via1_irq);
 544        }
 545        irq_set_chained_handler(IRQ_AUTO_2, via2_irq);
 546        irq_set_chained_handler(IRQ_MAC_NUBUS, via_nubus_irq);
 547}
 548
 549void via_irq_enable(int irq) {
 550        int irq_src     = IRQ_SRC(irq);
 551        int irq_idx     = IRQ_IDX(irq);
 552
 553#ifdef DEBUG_IRQUSE
 554        printk(KERN_DEBUG "via_irq_enable(%d)\n", irq);
 555#endif
 556
 557        if (irq_src == 1) {
 558                via1[vIER] = IER_SET_BIT(irq_idx);
 559        } else if (irq_src == 2) {
 560                if (irq != IRQ_MAC_NUBUS || nubus_disabled == 0)
 561                        via2[gIER] = IER_SET_BIT(irq_idx);
 562        } else if (irq_src == 7) {
 563                switch (macintosh_config->via_type) {
 564                case MAC_VIA_II:
 565                case MAC_VIA_QUADRA:
 566                        nubus_disabled &= ~(1 << irq_idx);
 567                        /* Enable the CA1 interrupt when no slot is disabled. */
 568                        if (!nubus_disabled)
 569                                via2[gIER] = IER_SET_BIT(1);
 570                        break;
 571                case MAC_VIA_IICI:
 572                        /* On RBV, enable the slot interrupt.
 573                         * SIER works like IER.
 574                         */
 575                        via2[rSIER] = IER_SET_BIT(irq_idx);
 576                        break;
 577                }
 578        }
 579}
 580
 581void via_irq_disable(int irq) {
 582        int irq_src     = IRQ_SRC(irq);
 583        int irq_idx     = IRQ_IDX(irq);
 584
 585#ifdef DEBUG_IRQUSE
 586        printk(KERN_DEBUG "via_irq_disable(%d)\n", irq);
 587#endif
 588
 589        if (irq_src == 1) {
 590                via1[vIER] = IER_CLR_BIT(irq_idx);
 591        } else if (irq_src == 2) {
 592                via2[gIER] = IER_CLR_BIT(irq_idx);
 593        } else if (irq_src == 7) {
 594                switch (macintosh_config->via_type) {
 595                case MAC_VIA_II:
 596                case MAC_VIA_QUADRA:
 597                        nubus_disabled |= 1 << irq_idx;
 598                        if (nubus_disabled)
 599                                via2[gIER] = IER_CLR_BIT(1);
 600                        break;
 601                case MAC_VIA_IICI:
 602                        via2[rSIER] = IER_CLR_BIT(irq_idx);
 603                        break;
 604                }
 605        }
 606}
 607
 608void via1_set_head(int head)
 609{
 610        if (head == 0)
 611                via1[vBufA] &= ~VIA1A_vHeadSel;
 612        else
 613                via1[vBufA] |= VIA1A_vHeadSel;
 614}
 615EXPORT_SYMBOL(via1_set_head);
 616
 617int via2_scsi_drq_pending(void)
 618{
 619        return via2[gIFR] & (1 << IRQ_IDX(IRQ_MAC_SCSIDRQ));
 620}
 621EXPORT_SYMBOL(via2_scsi_drq_pending);
 622