linux/arch/alpha/kernel/sys_alcor.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 *      linux/arch/alpha/kernel/sys_alcor.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 supporting the ALCOR and XLT (XL-300/366/433).
  10 */
  11
  12#include <linux/kernel.h>
  13#include <linux/types.h>
  14#include <linux/mm.h>
  15#include <linux/sched.h>
  16#include <linux/pci.h>
  17#include <linux/init.h>
  18#include <linux/reboot.h>
  19#include <linux/bitops.h>
  20
  21#include <asm/ptrace.h>
  22#include <asm/io.h>
  23#include <asm/dma.h>
  24#include <asm/mmu_context.h>
  25#include <asm/irq.h>
  26#include <asm/pgtable.h>
  27#include <asm/core_cia.h>
  28#include <asm/tlbflush.h>
  29
  30#include "proto.h"
  31#include "irq_impl.h"
  32#include "pci_impl.h"
  33#include "machvec_impl.h"
  34
  35
  36/* Note mask bit is true for ENABLED irqs.  */
  37static unsigned long cached_irq_mask;
  38
  39static inline void
  40alcor_update_irq_hw(unsigned long mask)
  41{
  42        *(vuip)GRU_INT_MASK = mask;
  43        mb();
  44}
  45
  46static inline void
  47alcor_enable_irq(struct irq_data *d)
  48{
  49        alcor_update_irq_hw(cached_irq_mask |= 1UL << (d->irq - 16));
  50}
  51
  52static void
  53alcor_disable_irq(struct irq_data *d)
  54{
  55        alcor_update_irq_hw(cached_irq_mask &= ~(1UL << (d->irq - 16)));
  56}
  57
  58static void
  59alcor_mask_and_ack_irq(struct irq_data *d)
  60{
  61        alcor_disable_irq(d);
  62
  63        /* On ALCOR/XLT, need to dismiss interrupt via GRU. */
  64        *(vuip)GRU_INT_CLEAR = 1 << (d->irq - 16); mb();
  65        *(vuip)GRU_INT_CLEAR = 0; mb();
  66}
  67
  68static void
  69alcor_isa_mask_and_ack_irq(struct irq_data *d)
  70{
  71        i8259a_mask_and_ack_irq(d);
  72
  73        /* On ALCOR/XLT, need to dismiss interrupt via GRU. */
  74        *(vuip)GRU_INT_CLEAR = 0x80000000; mb();
  75        *(vuip)GRU_INT_CLEAR = 0; mb();
  76}
  77
  78static struct irq_chip alcor_irq_type = {
  79        .name           = "ALCOR",
  80        .irq_unmask     = alcor_enable_irq,
  81        .irq_mask       = alcor_disable_irq,
  82        .irq_mask_ack   = alcor_mask_and_ack_irq,
  83};
  84
  85static void
  86alcor_device_interrupt(unsigned long vector)
  87{
  88        unsigned long pld;
  89        unsigned int i;
  90
  91        /* Read the interrupt summary register of the GRU */
  92        pld = (*(vuip)GRU_INT_REQ) & GRU_INT_REQ_BITS;
  93
  94        /*
  95         * Now for every possible bit set, work through them and call
  96         * the appropriate interrupt handler.
  97         */
  98        while (pld) {
  99                i = ffz(~pld);
 100                pld &= pld - 1; /* clear least bit set */
 101                if (i == 31) {
 102                        isa_device_interrupt(vector);
 103                } else {
 104                        handle_irq(16 + i);
 105                }
 106        }
 107}
 108
 109static void __init
 110alcor_init_irq(void)
 111{
 112        long i;
 113
 114        if (alpha_using_srm)
 115                alpha_mv.device_interrupt = srm_device_interrupt;
 116
 117        *(vuip)GRU_INT_MASK  = 0; mb();                 /* all disabled */
 118        *(vuip)GRU_INT_EDGE  = 0; mb();                 /* all are level */
 119        *(vuip)GRU_INT_HILO  = 0x80000000U; mb();       /* ISA only HI */
 120        *(vuip)GRU_INT_CLEAR = 0; mb();                 /* all clear */
 121
 122        for (i = 16; i < 48; ++i) {
 123                /* On Alcor, at least, lines 20..30 are not connected
 124                   and can generate spurious interrupts if we turn them
 125                   on while IRQ probing.  */
 126                if (i >= 16+20 && i <= 16+30)
 127                        continue;
 128                irq_set_chip_and_handler(i, &alcor_irq_type, handle_level_irq);
 129                irq_set_status_flags(i, IRQ_LEVEL);
 130        }
 131        i8259a_irq_type.irq_ack = alcor_isa_mask_and_ack_irq;
 132
 133        init_i8259a_irqs();
 134        common_init_isa_dma();
 135
 136        setup_irq(16+31, &isa_cascade_irqaction);
 137}
 138
 139
 140/*
 141 * PCI Fixup configuration.
 142 *
 143 * Summary @ GRU_INT_REQ:
 144 * Bit      Meaning
 145 * 0        Interrupt Line A from slot 2
 146 * 1        Interrupt Line B from slot 2
 147 * 2        Interrupt Line C from slot 2
 148 * 3        Interrupt Line D from slot 2
 149 * 4        Interrupt Line A from slot 1
 150 * 5        Interrupt line B from slot 1
 151 * 6        Interrupt Line C from slot 1
 152 * 7        Interrupt Line D from slot 1
 153 * 8        Interrupt Line A from slot 0
 154 * 9        Interrupt Line B from slot 0
 155 *10        Interrupt Line C from slot 0
 156 *11        Interrupt Line D from slot 0
 157 *12        Interrupt Line A from slot 4
 158 *13        Interrupt Line B from slot 4
 159 *14        Interrupt Line C from slot 4
 160 *15        Interrupt Line D from slot 4
 161 *16        Interrupt Line D from slot 3
 162 *17        Interrupt Line D from slot 3
 163 *18        Interrupt Line D from slot 3
 164 *19        Interrupt Line D from slot 3
 165 *20-30     Reserved
 166 *31        EISA interrupt
 167 *
 168 * The device to slot mapping looks like:
 169 *
 170 * Slot     Device
 171 *  6       built-in TULIP (XLT only)
 172 *  7       PCI on board slot 0
 173 *  8       PCI on board slot 3
 174 *  9       PCI on board slot 4
 175 * 10       PCEB (PCI-EISA bridge)
 176 * 11       PCI on board slot 2
 177 * 12       PCI on board slot 1
 178 *   
 179 *
 180 * This two layered interrupt approach means that we allocate IRQ 16 and 
 181 * above for PCI interrupts.  The IRQ relates to which bit the interrupt
 182 * comes in on.  This makes interrupt processing much easier.
 183 */
 184
 185static int
 186alcor_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 187{
 188        static char irq_tab[7][5] = {
 189                /*INT    INTA   INTB   INTC   INTD */
 190                /* note: IDSEL 17 is XLT only */
 191                {16+13, 16+13, 16+13, 16+13, 16+13},    /* IdSel 17,  TULIP  */
 192                { 16+8,  16+8,  16+9, 16+10, 16+11},    /* IdSel 18,  slot 0 */
 193                {16+16, 16+16, 16+17, 16+18, 16+19},    /* IdSel 19,  slot 3 */
 194                {16+12, 16+12, 16+13, 16+14, 16+15},    /* IdSel 20,  slot 4 */
 195                {   -1,    -1,    -1,    -1,    -1},    /* IdSel 21,  PCEB   */
 196                { 16+0,  16+0,  16+1,  16+2,  16+3},    /* IdSel 22,  slot 2 */
 197                { 16+4,  16+4,  16+5,  16+6,  16+7},    /* IdSel 23,  slot 1 */
 198        };
 199        const long min_idsel = 6, max_idsel = 12, irqs_per_slot = 5;
 200        return COMMON_TABLE_LOOKUP;
 201}
 202
 203static void
 204alcor_kill_arch(int mode)
 205{
 206        cia_kill_arch(mode);
 207
 208#ifndef ALPHA_RESTORE_SRM_SETUP
 209        switch(mode) {
 210        case LINUX_REBOOT_CMD_RESTART:
 211                /* Who said DEC engineer's have no sense of humor? ;-)  */
 212                if (alpha_using_srm) {
 213                        *(vuip) GRU_RESET = 0x0000dead;
 214                        mb();
 215                }
 216                break;
 217        case LINUX_REBOOT_CMD_HALT:
 218                break;
 219        case LINUX_REBOOT_CMD_POWER_OFF:
 220                break;
 221        }
 222
 223        halt();
 224#endif
 225}
 226
 227static void __init
 228alcor_init_pci(void)
 229{
 230        struct pci_dev *dev;
 231
 232        cia_init_pci();
 233
 234        /*
 235         * Now we can look to see if we are really running on an XLT-type
 236         * motherboard, by looking for a 21040 TULIP in slot 6, which is
 237         * built into XLT and BRET/MAVERICK, but not available on ALCOR.
 238         */
 239        dev = pci_get_device(PCI_VENDOR_ID_DEC,
 240                              PCI_DEVICE_ID_DEC_TULIP,
 241                              NULL);
 242        if (dev && dev->devfn == PCI_DEVFN(6,0)) {
 243                alpha_mv.sys.cia.gru_int_req_bits = XLT_GRU_INT_REQ_BITS; 
 244                printk(KERN_INFO "%s: Detected AS500 or XLT motherboard.\n",
 245                       __func__);
 246        }
 247        pci_dev_put(dev);
 248}
 249
 250
 251/*
 252 * The System Vectors
 253 */
 254
 255struct alpha_machine_vector alcor_mv __initmv = {
 256        .vector_name            = "Alcor",
 257        DO_EV5_MMU,
 258        DO_DEFAULT_RTC,
 259        DO_CIA_IO,
 260        .machine_check          = cia_machine_check,
 261        .max_isa_dma_address    = ALPHA_ALCOR_MAX_ISA_DMA_ADDRESS,
 262        .min_io_address         = EISA_DEFAULT_IO_BASE,
 263        .min_mem_address        = CIA_DEFAULT_MEM_BASE,
 264
 265        .nr_irqs                = 48,
 266        .device_interrupt       = alcor_device_interrupt,
 267
 268        .init_arch              = cia_init_arch,
 269        .init_irq               = alcor_init_irq,
 270        .init_rtc               = common_init_rtc,
 271        .init_pci               = alcor_init_pci,
 272        .kill_arch              = alcor_kill_arch,
 273        .pci_map_irq            = alcor_map_irq,
 274        .pci_swizzle            = common_swizzle,
 275
 276        .sys = { .cia = {
 277                .gru_int_req_bits = ALCOR_GRU_INT_REQ_BITS
 278        }}
 279};
 280ALIAS_MV(alcor)
 281
 282struct alpha_machine_vector xlt_mv __initmv = {
 283        .vector_name            = "XLT",
 284        DO_EV5_MMU,
 285        DO_DEFAULT_RTC,
 286        DO_CIA_IO,
 287        .machine_check          = cia_machine_check,
 288        .max_isa_dma_address    = ALPHA_MAX_ISA_DMA_ADDRESS,
 289        .min_io_address         = EISA_DEFAULT_IO_BASE,
 290        .min_mem_address        = CIA_DEFAULT_MEM_BASE,
 291
 292        .nr_irqs                = 48,
 293        .device_interrupt       = alcor_device_interrupt,
 294
 295        .init_arch              = cia_init_arch,
 296        .init_irq               = alcor_init_irq,
 297        .init_rtc               = common_init_rtc,
 298        .init_pci               = alcor_init_pci,
 299        .kill_arch              = alcor_kill_arch,
 300        .pci_map_irq            = alcor_map_irq,
 301        .pci_swizzle            = common_swizzle,
 302
 303        .sys = { .cia = {
 304                .gru_int_req_bits = XLT_GRU_INT_REQ_BITS
 305        }}
 306};
 307
 308/* No alpha_mv alias for XLT, since we compile it in unconditionally
 309   with ALCOR; setup_arch knows how to cope.  */
 310