linux/arch/alpha/kernel/sys_sio.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 *      linux/arch/alpha/kernel/sys_sio.c
   4 *
   5 *      Copyright (C) 1995 David A Rusling
   6 *      Copyright (C) 1996 Jay A Estabrook
   7 *      Copyright (C) 1998, 1999 Richard Henderson
   8 *
   9 * Code for all boards that route the PCI interrupts through the SIO
  10 * PCI/ISA bridge.  This includes Noname (AXPpci33), Multia (UDB),
  11 * Kenetics's Platform 2000, Avanti (AlphaStation), XL, and AlphaBook1.
  12 */
  13
  14#include <linux/kernel.h>
  15#include <linux/types.h>
  16#include <linux/mm.h>
  17#include <linux/sched.h>
  18#include <linux/pci.h>
  19#include <linux/init.h>
  20#include <linux/screen_info.h>
  21
  22#include <asm/compiler.h>
  23#include <asm/ptrace.h>
  24#include <asm/dma.h>
  25#include <asm/irq.h>
  26#include <asm/mmu_context.h>
  27#include <asm/io.h>
  28#include <asm/core_apecs.h>
  29#include <asm/core_lca.h>
  30#include <asm/tlbflush.h>
  31
  32#include "proto.h"
  33#include "irq_impl.h"
  34#include "pci_impl.h"
  35#include "machvec_impl.h"
  36#include "pc873xx.h"
  37
  38#if defined(ALPHA_RESTORE_SRM_SETUP)
  39/* Save LCA configuration data as the console had it set up.  */
  40struct 
  41{
  42        unsigned int orig_route_tab; /* for SAVE/RESTORE */
  43} saved_config __attribute((common));
  44#endif
  45
  46
  47static void __init
  48sio_init_irq(void)
  49{
  50        if (alpha_using_srm)
  51                alpha_mv.device_interrupt = srm_device_interrupt;
  52
  53        init_i8259a_irqs();
  54        common_init_isa_dma();
  55}
  56
  57static inline void __init
  58alphabook1_init_arch(void)
  59{
  60        /* The AlphaBook1 has LCD video fixed at 800x600,
  61           37 rows and 100 cols. */
  62        screen_info.orig_y = 37;
  63        screen_info.orig_video_cols = 100;
  64        screen_info.orig_video_lines = 37;
  65
  66        lca_init_arch();
  67}
  68
  69
  70/*
  71 * sio_route_tab selects irq routing in PCI/ISA bridge so that:
  72 *              PIRQ0 -> irq 15
  73 *              PIRQ1 -> irq  9
  74 *              PIRQ2 -> irq 10
  75 *              PIRQ3 -> irq 11
  76 *
  77 * This probably ought to be configurable via MILO.  For
  78 * example, sound boards seem to like using IRQ 9.
  79 *
  80 * This is NOT how we should do it. PIRQ0-X should have
  81 * their own IRQs, the way intel uses the IO-APIC IRQs.
  82 */
  83
  84static void __init
  85sio_pci_route(void)
  86{
  87        unsigned int orig_route_tab;
  88
  89        /* First, ALWAYS read and print the original setting. */
  90        pci_bus_read_config_dword(pci_isa_hose->bus, PCI_DEVFN(7, 0), 0x60,
  91                                  &orig_route_tab);
  92        printk("%s: PIRQ original 0x%x new 0x%x\n", __func__,
  93               orig_route_tab, alpha_mv.sys.sio.route_tab);
  94
  95#if defined(ALPHA_RESTORE_SRM_SETUP)
  96        saved_config.orig_route_tab = orig_route_tab;
  97#endif
  98
  99        /* Now override with desired setting. */
 100        pci_bus_write_config_dword(pci_isa_hose->bus, PCI_DEVFN(7, 0), 0x60,
 101                                   alpha_mv.sys.sio.route_tab);
 102}
 103
 104static bool sio_pci_dev_irq_needs_level(const struct pci_dev *dev)
 105{
 106        if ((dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) &&
 107            (dev->class >> 8 != PCI_CLASS_BRIDGE_PCMCIA))
 108                return false;
 109
 110        return true;
 111}
 112
 113static unsigned int __init
 114sio_collect_irq_levels(void)
 115{
 116        unsigned int level_bits = 0;
 117        struct pci_dev *dev = NULL;
 118
 119        /* Iterate through the devices, collecting IRQ levels.  */
 120        for_each_pci_dev(dev) {
 121                if (!sio_pci_dev_irq_needs_level(dev))
 122                        continue;
 123
 124                if (dev->irq)
 125                        level_bits |= (1 << dev->irq);
 126        }
 127        return level_bits;
 128}
 129
 130static void __sio_fixup_irq_levels(unsigned int level_bits, bool reset)
 131{
 132        unsigned int old_level_bits;
 133
 134        /*
 135         * Now, make all PCI interrupts level sensitive.  Notice:
 136         * these registers must be accessed byte-wise.  inw()/outw()
 137         * don't work.
 138         *
 139         * Make sure to turn off any level bits set for IRQs 9,10,11,15,
 140         *  so that the only bits getting set are for devices actually found.
 141         * Note that we do preserve the remainder of the bits, which we hope
 142         *  will be set correctly by ARC/SRM.
 143         *
 144         * Note: we at least preserve any level-set bits on AlphaBook1
 145         */
 146        old_level_bits = inb(0x4d0) | (inb(0x4d1) << 8);
 147
 148        if (reset)
 149                old_level_bits &= 0x71ff;
 150
 151        level_bits |= old_level_bits;
 152
 153        outb((level_bits >> 0) & 0xff, 0x4d0);
 154        outb((level_bits >> 8) & 0xff, 0x4d1);
 155}
 156
 157static inline void
 158sio_fixup_irq_levels(unsigned int level_bits)
 159{
 160        __sio_fixup_irq_levels(level_bits, true);
 161}
 162
 163static inline int
 164noname_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 165{
 166        /*
 167         * The Noname board has 5 PCI slots with each of the 4
 168         * interrupt pins routed to different pins on the PCI/ISA
 169         * bridge (PIRQ0-PIRQ3).  The table below is based on
 170         * information available at:
 171         *
 172         *   http://ftp.digital.com/pub/DEC/axppci/ref_interrupts.txt
 173         *
 174         * I have no information on the Avanti interrupt routing, but
 175         * the routing seems to be identical to the Noname except
 176         * that the Avanti has an additional slot whose routing I'm
 177         * unsure of.
 178         *
 179         * pirq_tab[0] is a fake entry to deal with old PCI boards
 180         * that have the interrupt pin number hardwired to 0 (meaning
 181         * that they use the default INTA line, if they are interrupt
 182         * driven at all).
 183         */
 184        static char irq_tab[][5] = {
 185                /*INT A   B   C   D */
 186                { 3,  3,  3,  3,  3}, /* idsel  6 (53c810) */ 
 187                {-1, -1, -1, -1, -1}, /* idsel  7 (SIO: PCI/ISA bridge) */
 188                { 2,  2, -1, -1, -1}, /* idsel  8 (Hack: slot closest ISA) */
 189                {-1, -1, -1, -1, -1}, /* idsel  9 (unused) */
 190                {-1, -1, -1, -1, -1}, /* idsel 10 (unused) */
 191                { 0,  0,  2,  1,  0}, /* idsel 11 KN25_PCI_SLOT0 */
 192                { 1,  1,  0,  2,  1}, /* idsel 12 KN25_PCI_SLOT1 */
 193                { 2,  2,  1,  0,  2}, /* idsel 13 KN25_PCI_SLOT2 */
 194                { 0,  0,  0,  0,  0}, /* idsel 14 AS255 TULIP */
 195        };
 196        const long min_idsel = 6, max_idsel = 14, irqs_per_slot = 5;
 197        int irq = COMMON_TABLE_LOOKUP, tmp;
 198        tmp = __kernel_extbl(alpha_mv.sys.sio.route_tab, irq);
 199
 200        irq = irq >= 0 ? tmp : -1;
 201
 202        /* Fixup IRQ level if an actual IRQ mapping is detected */
 203        if (sio_pci_dev_irq_needs_level(dev) && irq >= 0)
 204                __sio_fixup_irq_levels(1 << irq, false);
 205
 206        return irq;
 207}
 208
 209static inline int
 210p2k_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 211{
 212        static char irq_tab[][5] = {
 213                /*INT A   B   C   D */
 214                { 0,  0, -1, -1, -1}, /* idsel  6 (53c810) */
 215                {-1, -1, -1, -1, -1}, /* idsel  7 (SIO: PCI/ISA bridge) */
 216                { 1,  1,  2,  3,  0}, /* idsel  8 (slot A) */
 217                { 2,  2,  3,  0,  1}, /* idsel  9 (slot B) */
 218                {-1, -1, -1, -1, -1}, /* idsel 10 (unused) */
 219                {-1, -1, -1, -1, -1}, /* idsel 11 (unused) */
 220                { 3,  3, -1, -1, -1}, /* idsel 12 (CMD0646) */
 221        };
 222        const long min_idsel = 6, max_idsel = 12, irqs_per_slot = 5;
 223        int irq = COMMON_TABLE_LOOKUP, tmp;
 224        tmp = __kernel_extbl(alpha_mv.sys.sio.route_tab, irq);
 225        return irq >= 0 ? tmp : -1;
 226}
 227
 228static inline void __init
 229noname_init_pci(void)
 230{
 231        common_init_pci();
 232        sio_pci_route();
 233        sio_fixup_irq_levels(sio_collect_irq_levels());
 234
 235        if (pc873xx_probe() == -1) {
 236                printk(KERN_ERR "Probing for PC873xx Super IO chip failed.\n");
 237        } else {
 238                printk(KERN_INFO "Found %s Super IO chip at 0x%x\n",
 239                        pc873xx_get_model(), pc873xx_get_base());
 240
 241                /* Enabling things in the Super IO chip doesn't actually
 242                 * configure and enable things, the legacy drivers still
 243                 * need to do the actual configuration and enabling.
 244                 * This only unblocks them.
 245                 */
 246
 247#if !defined(CONFIG_ALPHA_AVANTI)
 248                /* Don't bother on the Avanti family.
 249                 * None of them had on-board IDE.
 250                 */
 251                pc873xx_enable_ide();
 252#endif
 253                pc873xx_enable_epp19();
 254        }
 255}
 256
 257static inline void __init
 258alphabook1_init_pci(void)
 259{
 260        struct pci_dev *dev;
 261        unsigned char orig, config;
 262
 263        common_init_pci();
 264        sio_pci_route();
 265
 266        /*
 267         * On the AlphaBook1, the PCMCIA chip (Cirrus 6729)
 268         * is sensitive to PCI bus bursts, so we must DISABLE
 269         * burst mode for the NCR 8xx SCSI... :-(
 270         *
 271         * Note that the NCR810 SCSI driver must preserve the
 272         * setting of the bit in order for this to work.  At the
 273         * moment (2.0.29), ncr53c8xx.c does NOT do this, but
 274         * 53c7,8xx.c DOES.
 275         */
 276
 277        dev = NULL;
 278        while ((dev = pci_get_device(PCI_VENDOR_ID_NCR, PCI_ANY_ID, dev))) {
 279                if (dev->device == PCI_DEVICE_ID_NCR_53C810
 280                    || dev->device == PCI_DEVICE_ID_NCR_53C815
 281                    || dev->device == PCI_DEVICE_ID_NCR_53C820
 282                    || dev->device == PCI_DEVICE_ID_NCR_53C825) {
 283                        unsigned long io_port;
 284                        unsigned char ctest4;
 285
 286                        io_port = dev->resource[0].start;
 287                        ctest4 = inb(io_port+0x21);
 288                        if (!(ctest4 & 0x80)) {
 289                                printk("AlphaBook1 NCR init: setting"
 290                                       " burst disable\n");
 291                                outb(ctest4 | 0x80, io_port+0x21);
 292                        }
 293                }
 294        }
 295
 296        /* Do not set *ANY* level triggers for AlphaBook1. */
 297        sio_fixup_irq_levels(0);
 298
 299        /* Make sure that register PR1 indicates 1Mb mem */
 300        outb(0x0f, 0x3ce); orig = inb(0x3cf);   /* read PR5  */
 301        outb(0x0f, 0x3ce); outb(0x05, 0x3cf);   /* unlock PR0-4 */
 302        outb(0x0b, 0x3ce); config = inb(0x3cf); /* read PR1 */
 303        if ((config & 0xc0) != 0xc0) {
 304                printk("AlphaBook1 VGA init: setting 1Mb memory\n");
 305                config |= 0xc0;
 306                outb(0x0b, 0x3ce); outb(config, 0x3cf); /* write PR1 */
 307        }
 308        outb(0x0f, 0x3ce); outb(orig, 0x3cf); /* (re)lock PR0-4 */
 309}
 310
 311void
 312sio_kill_arch(int mode)
 313{
 314#if defined(ALPHA_RESTORE_SRM_SETUP)
 315        /* Since we cannot read the PCI DMA Window CSRs, we
 316         * cannot restore them here.
 317         *
 318         * However, we CAN read the PIRQ route register, so restore it
 319         * now...
 320         */
 321        pci_bus_write_config_dword(pci_isa_hose->bus, PCI_DEVFN(7, 0), 0x60,
 322                                   saved_config.orig_route_tab);
 323#endif
 324}
 325
 326
 327/*
 328 * The System Vectors
 329 */
 330
 331#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_BOOK1)
 332struct alpha_machine_vector alphabook1_mv __initmv = {
 333        .vector_name            = "AlphaBook1",
 334        DO_EV4_MMU,
 335        DO_DEFAULT_RTC,
 336        DO_LCA_IO,
 337        .machine_check          = lca_machine_check,
 338        .max_isa_dma_address    = ALPHA_MAX_ISA_DMA_ADDRESS,
 339        .min_io_address         = DEFAULT_IO_BASE,
 340        .min_mem_address        = APECS_AND_LCA_DEFAULT_MEM_BASE,
 341
 342        .nr_irqs                = 16,
 343        .device_interrupt       = isa_device_interrupt,
 344
 345        .init_arch              = alphabook1_init_arch,
 346        .init_irq               = sio_init_irq,
 347        .init_rtc               = common_init_rtc,
 348        .init_pci               = alphabook1_init_pci,
 349        .kill_arch              = sio_kill_arch,
 350        .pci_map_irq            = noname_map_irq,
 351        .pci_swizzle            = common_swizzle,
 352
 353        .sys = { .sio = {
 354                /* NCR810 SCSI is 14, PCMCIA controller is 15.  */
 355                .route_tab      = 0x0e0f0a0a,
 356        }}
 357};
 358ALIAS_MV(alphabook1)
 359#endif
 360
 361#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_AVANTI)
 362struct alpha_machine_vector avanti_mv __initmv = {
 363        .vector_name            = "Avanti",
 364        DO_EV4_MMU,
 365        DO_DEFAULT_RTC,
 366        DO_APECS_IO,
 367        .machine_check          = apecs_machine_check,
 368        .max_isa_dma_address    = ALPHA_MAX_ISA_DMA_ADDRESS,
 369        .min_io_address         = DEFAULT_IO_BASE,
 370        .min_mem_address        = APECS_AND_LCA_DEFAULT_MEM_BASE,
 371
 372        .nr_irqs                = 16,
 373        .device_interrupt       = isa_device_interrupt,
 374
 375        .init_arch              = apecs_init_arch,
 376        .init_irq               = sio_init_irq,
 377        .init_rtc               = common_init_rtc,
 378        .init_pci               = noname_init_pci,
 379        .kill_arch              = sio_kill_arch,
 380        .pci_map_irq            = noname_map_irq,
 381        .pci_swizzle            = common_swizzle,
 382
 383        .sys = { .sio = {
 384                .route_tab      = 0x0b0a050f, /* leave 14 for IDE, 9 for SND */
 385        }}
 386};
 387ALIAS_MV(avanti)
 388#endif
 389
 390#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_NONAME)
 391struct alpha_machine_vector noname_mv __initmv = {
 392        .vector_name            = "Noname",
 393        DO_EV4_MMU,
 394        DO_DEFAULT_RTC,
 395        DO_LCA_IO,
 396        .machine_check          = lca_machine_check,
 397        .max_isa_dma_address    = ALPHA_MAX_ISA_DMA_ADDRESS,
 398        .min_io_address         = DEFAULT_IO_BASE,
 399        .min_mem_address        = APECS_AND_LCA_DEFAULT_MEM_BASE,
 400
 401        .nr_irqs                = 16,
 402        .device_interrupt       = srm_device_interrupt,
 403
 404        .init_arch              = lca_init_arch,
 405        .init_irq               = sio_init_irq,
 406        .init_rtc               = common_init_rtc,
 407        .init_pci               = noname_init_pci,
 408        .kill_arch              = sio_kill_arch,
 409        .pci_map_irq            = noname_map_irq,
 410        .pci_swizzle            = common_swizzle,
 411
 412        .sys = { .sio = {
 413                /* For UDB, the only available PCI slot must not map to IRQ 9,
 414                   since that's the builtin MSS sound chip. That PCI slot
 415                   will map to PIRQ1 (for INTA at least), so we give it IRQ 15
 416                   instead.
 417
 418                   Unfortunately we have to do this for NONAME as well, since
 419                   they are co-indicated when the platform type "Noname" is
 420                   selected... :-(  */
 421
 422                .route_tab      = 0x0b0a0f0d,
 423        }}
 424};
 425ALIAS_MV(noname)
 426#endif
 427
 428#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_P2K)
 429struct alpha_machine_vector p2k_mv __initmv = {
 430        .vector_name            = "Platform2000",
 431        DO_EV4_MMU,
 432        DO_DEFAULT_RTC,
 433        DO_LCA_IO,
 434        .machine_check          = lca_machine_check,
 435        .max_isa_dma_address    = ALPHA_MAX_ISA_DMA_ADDRESS,
 436        .min_io_address         = DEFAULT_IO_BASE,
 437        .min_mem_address        = APECS_AND_LCA_DEFAULT_MEM_BASE,
 438
 439        .nr_irqs                = 16,
 440        .device_interrupt       = srm_device_interrupt,
 441
 442        .init_arch              = lca_init_arch,
 443        .init_irq               = sio_init_irq,
 444        .init_rtc               = common_init_rtc,
 445        .init_pci               = noname_init_pci,
 446        .kill_arch              = sio_kill_arch,
 447        .pci_map_irq            = p2k_map_irq,
 448        .pci_swizzle            = common_swizzle,
 449
 450        .sys = { .sio = {
 451                .route_tab      = 0x0b0a090f,
 452        }}
 453};
 454ALIAS_MV(p2k)
 455#endif
 456
 457#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_XL)
 458struct alpha_machine_vector xl_mv __initmv = {
 459        .vector_name            = "XL",
 460        DO_EV4_MMU,
 461        DO_DEFAULT_RTC,
 462        DO_APECS_IO,
 463        .machine_check          = apecs_machine_check,
 464        .max_isa_dma_address    = ALPHA_XL_MAX_ISA_DMA_ADDRESS,
 465        .min_io_address         = DEFAULT_IO_BASE,
 466        .min_mem_address        = XL_DEFAULT_MEM_BASE,
 467
 468        .nr_irqs                = 16,
 469        .device_interrupt       = isa_device_interrupt,
 470
 471        .init_arch              = apecs_init_arch,
 472        .init_irq               = sio_init_irq,
 473        .init_rtc               = common_init_rtc,
 474        .init_pci               = noname_init_pci,
 475        .kill_arch              = sio_kill_arch,
 476        .pci_map_irq            = noname_map_irq,
 477        .pci_swizzle            = common_swizzle,
 478
 479        .sys = { .sio = {
 480                .route_tab      = 0x0b0a090f,
 481        }}
 482};
 483ALIAS_MV(xl)
 484#endif
 485