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