| 1 | |
| 2 | |
| 3 | * linux/arch/alpha/kernel/sys_miata.c
|
| 4 | *
|
| 5 | * Copyright (C) 1995 David A Rusling
|
| 6 | * Copyright (C) 1996 Jay A Estabrook
|
| 7 | * Copyright (C) 1998, 1999, 2000 Richard Henderson
|
| 8 | *
|
| 9 | * Code supporting the MIATA (EV56+PYXIS).
|
| 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 |
|
| 20 | #include <asm/ptrace.h>
|
| 21 | #include <asm/dma.h>
|
| 22 | #include <asm/irq.h>
|
| 23 | #include <asm/mmu_context.h>
|
| 24 | #include <asm/io.h>
|
| 25 | #include <asm/core_cia.h>
|
| 26 | #include <asm/tlbflush.h>
|
| 27 |
|
| 28 | #include "proto.h"
|
| 29 | #include "irq_impl.h"
|
| 30 | #include "pci_impl.h"
|
| 31 | #include "machvec_impl.h"
|
| 32 |
|
| 33 |
|
| 34 | static void
|
| 35 | miata_srm_device_interrupt(unsigned long vector)
|
| 36 | {
|
| 37 | int irq;
|
| 38 |
|
| 39 | irq = (vector - 0x800) >> 4;
|
| 40 |
|
| 41 | |
| 42 | * I really hate to do this, but the MIATA SRM console ignores the
|
| 43 | * low 8 bits in the interrupt summary register, and reports the
|
| 44 | * vector 0x80 *lower* than I expected from the bit numbering in
|
| 45 | * the documentation.
|
| 46 | * This was done because the low 8 summary bits really aren't used
|
| 47 | * for reporting any interrupts (the PCI-ISA bridge, bit 7, isn't
|
| 48 | * used for this purpose, as PIC interrupts are delivered as the
|
| 49 | * vectors 0x800-0x8f0).
|
| 50 | * But I really don't want to change the fixup code for allocation
|
| 51 | * of IRQs, nor the alpha_irq_mask maintenance stuff, both of which
|
| 52 | * look nice and clean now.
|
| 53 | * So, here's this grotty hack... :-(
|
| 54 |
|
| 55 | if (irq >= 16)
|
| 56 | irq = irq + 8;
|
| 57 |
|
| 58 | handle_irq(irq);
|
| 59 | }
|
| 60 |
|
| 61 | static void __init
|
| 62 | miata_init_irq(void)
|
| 63 | {
|
| 64 | if (alpha_using_srm)
|
| 65 | alpha_mv.device_interrupt = miata_srm_device_interrupt;
|
| 66 |
|
| 67 | #if 0 |
| 68 | /* These break on MiataGL so we'll try not to do it at all. */
|
| 69 | *(vulp)PYXIS_INT_HILO = 0x000000B2UL; mb(); /* ISA/NMI HI */
|
| 70 | *(vulp)PYXIS_RT_COUNT = 0UL; mb(); /* clear count */
|
| 71 | #endif
|
| 72 |
|
| 73 | init_i8259a_irqs();
|
| 74 |
|
| 75 | |
| 76 | NMI (1), or EIDE (9).
|
| 77 |
|
| 78 | We also disable the risers (4,5), since we don't know how to
|
| 79 | route the interrupts behind the bridge.
|
| 80 | init_pyxis_irqs(0x63b0000);
|
| 81 |
|
| 82 | common_init_isa_dma();
|
| 83 | if (request_irq(16 + 2, no_action, 0, "halt-switch", NULL))
|
| 84 | pr_err("Failed to register halt-switch interrupt\n");
|
| 85 | if (request_irq(16 + 6, no_action, 0, "timer-cascade", NULL))
|
| 86 | pr_err("Failed to register timer-cascade interrupt\n");
|
| 87 | }
|
| 88 |
|
| 89 |
|
| 90 | |
| 91 | * PCI Fixup configuration.
|
| 92 | *
|
| 93 | * Summary @ PYXIS_INT_REQ:
|
| 94 | * Bit Meaning
|
| 95 | * 0 Fan Fault
|
| 96 | * 1 NMI
|
| 97 | * 2 Halt/Reset switch
|
| 98 | * 3 none
|
| 99 | * 4 CID0 (Riser ID)
|
| 100 | * 5 CID1 (Riser ID)
|
| 101 | * 6 Interval timer
|
| 102 | * 7 PCI-ISA Bridge
|
| 103 | * 8 Ethernet
|
| 104 | * 9 EIDE (deprecated, ISA 14/15 used)
|
| 105 | *10 none
|
| 106 | *11 USB
|
| 107 | *12 Interrupt Line A from slot 4
|
| 108 | *13 Interrupt Line B from slot 4
|
| 109 | *14 Interrupt Line C from slot 4
|
| 110 | *15 Interrupt Line D from slot 4
|
| 111 | *16 Interrupt Line A from slot 5
|
| 112 | *17 Interrupt line B from slot 5
|
| 113 | *18 Interrupt Line C from slot 5
|
| 114 | *19 Interrupt Line D from slot 5
|
| 115 | *20 Interrupt Line A from slot 1
|
| 116 | *21 Interrupt Line B from slot 1
|
| 117 | *22 Interrupt Line C from slot 1
|
| 118 | *23 Interrupt Line D from slot 1
|
| 119 | *24 Interrupt Line A from slot 2
|
| 120 | *25 Interrupt Line B from slot 2
|
| 121 | *26 Interrupt Line C from slot 2
|
| 122 | *27 Interrupt Line D from slot 2
|
| 123 | *27 Interrupt Line A from slot 3
|
| 124 | *29 Interrupt Line B from slot 3
|
| 125 | *30 Interrupt Line C from slot 3
|
| 126 | *31 Interrupt Line D from slot 3
|
| 127 | *
|
| 128 | * The device to slot mapping looks like:
|
| 129 | *
|
| 130 | * Slot Device
|
| 131 | * 3 DC21142 Ethernet
|
| 132 | * 4 EIDE CMD646
|
| 133 | * 5 none
|
| 134 | * 6 USB
|
| 135 | * 7 PCI-ISA bridge
|
| 136 | * 8 PCI-PCI Bridge (SBU Riser)
|
| 137 | * 9 none
|
| 138 | * 10 none
|
| 139 | * 11 PCI on board slot 4 (SBU Riser)
|
| 140 | * 12 PCI on board slot 5 (SBU Riser)
|
| 141 | *
|
| 142 | * These are behind the bridge, so I'm not sure what to do...
|
| 143 | *
|
| 144 | * 13 PCI on board slot 1 (SBU Riser)
|
| 145 | * 14 PCI on board slot 2 (SBU Riser)
|
| 146 | * 15 PCI on board slot 3 (SBU Riser)
|
| 147 | *
|
| 148 | *
|
| 149 | * This two layered interrupt approach means that we allocate IRQ 16 and
|
| 150 | * above for PCI interrupts. The IRQ relates to which bit the interrupt
|
| 151 | * comes in on. This makes interrupt processing much easier.
|
| 152 |
|
| 153 |
|
| 154 | static int
|
| 155 | miata_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
|
| 156 | {
|
| 157 | static char irq_tab[18][5] = {
|
| 158 |
|
| 159 | {16+ 8, 16+ 8, 16+ 8, 16+ 8, 16+ 8},
|
| 160 | { -1, -1, -1, -1, -1},
|
| 161 | { -1, -1, -1, -1, -1},
|
| 162 | { -1, -1, -1, -1, -1},
|
| 163 | { -1, -1, -1, -1, -1},
|
| 164 | { -1, -1, -1, -1, -1},
|
| 165 | { -1, -1, -1, -1, -1},
|
| 166 | { -1, -1, -1, -1, -1},
|
| 167 | {16+12, 16+12, 16+13, 16+14, 16+15},
|
| 168 | {16+16, 16+16, 16+17, 16+18, 16+19},
|
| 169 |
|
| 170 | {16+11, 16+11, 16+11, 16+11, 16+11},
|
| 171 | { -1, -1, -1, -1, -1},
|
| 172 | { -1, -1, -1, -1, -1},
|
| 173 | { -1, -1, -1, -1, -1},
|
| 174 | {16+20, 16+20, 16+21, 16+22, 16+23},
|
| 175 | {16+24, 16+24, 16+25, 16+26, 16+27},
|
| 176 | {16+28, 16+28, 16+29, 16+30, 16+31},
|
| 177 |
|
| 178 | { -1, -1, -1, -1, -1},
|
| 179 | };
|
| 180 | const long min_idsel = 3, max_idsel = 20, irqs_per_slot = 5;
|
| 181 |
|
| 182 | |
| 183 | the 2nd 8259 controller. So we have to check for it first.
|
| 184 |
|
| 185 | if((slot == 7) && (PCI_FUNC(dev->devfn) == 3)) {
|
| 186 | struct pci_dev *pdev = pci_get_slot(dev->bus, dev->devfn & ~7);
|
| 187 | u8 irq = 0;
|
| 188 | int ret;
|
| 189 |
|
| 190 | if (!pdev)
|
| 191 | return -1;
|
| 192 |
|
| 193 | ret = pci_read_config_byte(pdev, 0x40, &irq);
|
| 194 | pci_dev_put(pdev);
|
| 195 |
|
| 196 | return ret == PCIBIOS_SUCCESSFUL ? irq : -1;
|
| 197 | }
|
| 198 |
|
| 199 | return COMMON_TABLE_LOOKUP;
|
| 200 | }
|
| 201 |
|
| 202 | static u8
|
| 203 | miata_swizzle(struct pci_dev *dev, u8 *pinp)
|
| 204 | {
|
| 205 | int slot, pin = *pinp;
|
| 206 |
|
| 207 | if (dev->bus->number == 0) {
|
| 208 | slot = PCI_SLOT(dev->devfn);
|
| 209 | }
|
| 210 |
|
| 211 | else if ((PCI_SLOT(dev->bus->self->devfn) == 8) ||
|
| 212 | (PCI_SLOT(dev->bus->self->devfn) == 20)) {
|
| 213 | slot = PCI_SLOT(dev->devfn) + 9;
|
| 214 | }
|
| 215 | else
|
| 216 | {
|
| 217 |
|
| 218 | do {
|
| 219 | if ((PCI_SLOT(dev->bus->self->devfn) == 8) ||
|
| 220 | (PCI_SLOT(dev->bus->self->devfn) == 20)) {
|
| 221 | slot = PCI_SLOT(dev->devfn) + 9;
|
| 222 | break;
|
| 223 | }
|
| 224 | pin = pci_swizzle_interrupt_pin(dev, pin);
|
| 225 |
|
| 226 |
|
| 227 | dev = dev->bus->self;
|
| 228 |
|
| 229 | slot = PCI_SLOT(dev->devfn);
|
| 230 | } while (dev->bus->self);
|
| 231 | }
|
| 232 | *pinp = pin;
|
| 233 | return slot;
|
| 234 | }
|
| 235 |
|
| 236 | static void __init
|
| 237 | miata_init_pci(void)
|
| 238 | {
|
| 239 | cia_init_pci();
|
| 240 | SMC669_Init(0);
|
| 241 | es1888_init();
|
| 242 | }
|
| 243 |
|
| 244 | static void
|
| 245 | miata_kill_arch(int mode)
|
| 246 | {
|
| 247 | cia_kill_arch(mode);
|
| 248 |
|
| 249 | #ifndef ALPHA_RESTORE_SRM_SETUP
|
| 250 | switch(mode) {
|
| 251 | case LINUX_REBOOT_CMD_RESTART:
|
| 252 |
|
| 253 | if (alpha_using_srm) {
|
| 254 | *(vuip) PYXIS_RESET = 0x0000dead;
|
| 255 | mb();
|
| 256 | }
|
| 257 | break;
|
| 258 | case LINUX_REBOOT_CMD_HALT:
|
| 259 | break;
|
| 260 | case LINUX_REBOOT_CMD_POWER_OFF:
|
| 261 | break;
|
| 262 | }
|
| 263 |
|
| 264 | halt();
|
| 265 | #endif
|
| 266 | }
|
| 267 |
|
| 268 |
|
| 269 | |
| 270 | * The System Vector
|
| 271 |
|
| 272 |
|
| 273 | struct alpha_machine_vector miata_mv __initmv = {
|
| 274 | .vector_name = "Miata",
|
| 275 | DO_EV5_MMU,
|
| 276 | DO_DEFAULT_RTC,
|
| 277 | DO_PYXIS_IO,
|
| 278 | .machine_check = cia_machine_check,
|
| 279 | .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
|
| 280 | .min_io_address = DEFAULT_IO_BASE,
|
| 281 | .min_mem_address = DEFAULT_MEM_BASE,
|
| 282 | .pci_dac_offset = PYXIS_DAC_OFFSET,
|
| 283 |
|
| 284 | .nr_irqs = 48,
|
| 285 | .device_interrupt = pyxis_device_interrupt,
|
| 286 |
|
| 287 | .init_arch = pyxis_init_arch,
|
| 288 | .init_irq = miata_init_irq,
|
| 289 | .init_rtc = common_init_rtc,
|
| 290 | .init_pci = miata_init_pci,
|
| 291 | .kill_arch = miata_kill_arch,
|
| 292 | .pci_map_irq = miata_map_irq,
|
| 293 | .pci_swizzle = miata_swizzle,
|
| 294 | };
|
| 295 | ALIAS_MV(miata)
|