1/* 2 * linux/arch/alpha/kernel/sys_sable.c 3 * 4 * Copyright (C) 1995 David A Rusling 5 * Copyright (C) 1996 Jay A Estabrook 6 * Copyright (C) 1998, 1999 Richard Henderson 7 * 8 * Code supporting the Sable and Sable-Gamma systems. 9 */ 10 11#include <linux/config.h> 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 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_t2.h> 27 28#include "proto.h" 29#include "irq_impl.h" 30#include "pci_impl.h" 31#include "machvec_impl.h" 32 33spinlock_t sable_irq_lock = SPIN_LOCK_UNLOCKED; 34 35/* 36 * For SABLE, which is really baroque, we manage 40 IRQ's, but the 37 * hardware really only supports 24, not via normal ISA PIC, 38 * but cascaded custom 8259's, etc. 39 * 0-7 (char at 536) 40 * 8-15 (char at 53a) 41 * 16-23 (char at 53c) 42 * 43 * Summary Registers (536/53a/53c): 44 * 45 * Bit Meaning Kernel IRQ 46 *------------------------------------------ 47 * 0 PCI slot 0 34 48 * 1 NCR810 (builtin) 33 49 * 2 TULIP (builtin) 32 50 * 3 mouse 12 51 * 4 PCI slot 1 35 52 * 5 PCI slot 2 36 53 * 6 keyboard 1 54 * 7 floppy 6 55 * 8 COM2 3 56 * 9 parallel port 7 57 *10 EISA irq 3 - 58 *11 EISA irq 4 - 59 *12 EISA irq 5 5 60 *13 EISA irq 6 - 61 *14 EISA irq 7 - 62 *15 COM1 4 63 *16 EISA irq 9 9 64 *17 EISA irq 10 10 65 *18 EISA irq 11 11 66 *19 EISA irq 12 - 67 *20 EISA irq 13 - 68 *21 EISA irq 14 14 69 *22 NC 15 70 *23 IIC - 71 */ 72 73static struct 74{ 75 char irq_to_mask[40]; 76 char mask_to_irq[40]; 77 78 /* Note mask bit is true for DISABLED irqs. */ 79 unsigned long shadow_mask; 80} sable_irq_swizzle = { 81 { 82 -1, 6, -1, 8, 15, 12, 7, 9, /* pseudo PIC 0-7 */ 83 -1, 16, 17, 18, 3, -1, 21, 22, /* pseudo PIC 8-15 */ 84 -1, -1, -1, -1, -1, -1, -1, -1, /* pseudo EISA 0-7 */ 85 -1, -1, -1, -1, -1, -1, -1, -1, /* pseudo EISA 8-15 */ 86 2, 1, 0, 4, 5, -1, -1, -1, /* pseudo PCI */ 87 }, 88 { 89 34, 33, 32, 12, 35, 36, 1, 6, /* mask 0-7 */ 90 3, 7, -1, -1, 5, -1, -1, 4, /* mask 8-15 */ 91 9, 10, 11, -1, -1, 14, 15, -1, /* mask 16-23 */ 92 }, 93 -1 94}; 95 96static inline void 97sable_update_irq_hw(unsigned long bit, unsigned long mask) 98{ 99 int port = 0x537; 100 101 if (bit >= 16) { 102 port = 0x53d; 103 mask >>= 16; 104 } else if (bit >= 8) { 105 port = 0x53b; 106 mask >>= 8; 107 } 108 109 outb(mask, port); 110} 111 112static inline void 113sable_ack_irq_hw(unsigned long bit) 114{ 115 int port, val1, val2; 116 117 if (bit >= 16) { 118 port = 0x53c; 119 val1 = 0xE0 | (bit - 16); 120 val2 = 0xE0 | 4; 121 } else if (bit >= 8) { 122 port = 0x53a; 123 val1 = 0xE0 | (bit - 8); 124 val2 = 0xE0 | 3; 125 } else { 126 port = 0x536; 127 val1 = 0xE0 | (bit - 0); 128 val2 = 0xE0 | 1; 129 } 130 131 outb(val1, port); /* ack the slave */ 132 outb(val2, 0x534); /* ack the master */ 133} 134 135static inline void 136sable_enable_irq(unsigned int irq) 137{ 138 unsigned long bit, mask; 139 140 bit = sable_irq_swizzle.irq_to_mask[irq]; 141 spin_lock(&sable_irq_lock); 142 mask = sable_irq_swizzle.shadow_mask &= ~(1UL << bit); 143 sable_update_irq_hw(bit, mask); 144 spin_unlock(&sable_irq_lock); 145} 146 147static void 148sable_disable_irq(unsigned int irq) 149{ 150 unsigned long bit, mask; 151 152 bit = sable_irq_swizzle.irq_to_mask[irq]; 153 spin_lock(&sable_irq_lock); 154 mask = sable_irq_swizzle.shadow_mask |= 1UL << bit; 155 sable_update_irq_hw(bit, mask); 156 spin_unlock(&sable_irq_lock); 157} 158 159static unsigned int 160sable_startup_irq(unsigned int irq) 161{ 162 sable_enable_irq(irq); 163 return 0; 164} 165 166static void 167sable_end_irq(unsigned int irq) 168{ 169 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) 170 sable_enable_irq(irq); 171} 172 173static void 174sable_mask_and_ack_irq(unsigned int irq) 175{ 176 unsigned long bit, mask; 177 178 bit = sable_irq_swizzle.irq_to_mask[irq]; 179 spin_lock(&sable_irq_lock); 180 mask = sable_irq_swizzle.shadow_mask |= 1UL << bit; 181 sable_update_irq_hw(bit, mask); 182 sable_ack_irq_hw(bit); 183 spin_unlock(&sable_irq_lock); 184} 185 186static struct hw_interrupt_type sable_irq_type = { 187 typename: "SABLE", 188 startup: sable_startup_irq, 189 shutdown: sable_disable_irq, 190 enable: sable_enable_irq, 191 disable: sable_disable_irq, 192 ack: sable_mask_and_ack_irq, 193 end: sable_end_irq, 194}; 195 196static void 197sable_srm_device_interrupt(unsigned long vector, struct pt_regs * regs) 198{ 199 /* Note that the vector reported by the SRM PALcode corresponds 200 to the interrupt mask bits, but we have to manage via more 201 normal IRQs. */ 202 203 int bit, irq; 204 205 bit = (vector - 0x800) >> 4; 206 irq = sable_irq_swizzle.mask_to_irq[bit]; 207 handle_irq(irq, regs); 208} 209 210static void __init 211sable_init_irq(void) 212{ 213 long i; 214 215 outb(-1, 0x537); /* slave 0 */ 216 outb(-1, 0x53b); /* slave 1 */ 217 outb(-1, 0x53d); /* slave 2 */ 218 outb(0x44, 0x535); /* enable cascades in master */ 219 220 for (i = 0; i < 40; ++i) { 221 irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL; 222 irq_desc[i].handler = &sable_irq_type; 223 } 224 225 common_init_isa_dma(); 226} 227 228 229/* 230 * PCI Fixup configuration for ALPHA SABLE (2100) - 2100A is different ?? 231 * 232 * The device to slot mapping looks like: 233 * 234 * Slot Device 235 * 0 TULIP 236 * 1 SCSI 237 * 2 PCI-EISA bridge 238 * 3 none 239 * 4 none 240 * 5 none 241 * 6 PCI on board slot 0 242 * 7 PCI on board slot 1 243 * 8 PCI on board slot 2 244 * 245 * 246 * This two layered interrupt approach means that we allocate IRQ 16 and 247 * above for PCI interrupts. The IRQ relates to which bit the interrupt 248 * comes in on. This makes interrupt processing much easier. 249 */ 250/* 251 * NOTE: the IRQ assignments below are arbitrary, but need to be consistent 252 * with the values in the irq swizzling tables above. 253 */ 254 255static int __init 256sable_map_irq(struct pci_dev *dev, u8 slot, u8 pin) 257{ 258 static char irq_tab[9][5] __initdata = { 259 /*INT INTA INTB INTC INTD */ 260 { 32+0, 32+0, 32+0, 32+0, 32+0}, /* IdSel 0, TULIP */ 261 { 32+1, 32+1, 32+1, 32+1, 32+1}, /* IdSel 1, SCSI */ 262 { -1, -1, -1, -1, -1}, /* IdSel 2, SIO */ 263 { -1, -1, -1, -1, -1}, /* IdSel 3, none */ 264 { -1, -1, -1, -1, -1}, /* IdSel 4, none */ 265 { -1, -1, -1, -1, -1}, /* IdSel 5, none */ 266 { 32+2, 32+2, 32+2, 32+2, 32+2}, /* IdSel 6, slot 0 */ 267 { 32+3, 32+3, 32+3, 32+3, 32+3}, /* IdSel 7, slot 1 */ 268 { 32+4, 32+4, 32+4, 32+4, 32+4}, /* IdSel 8, slot 2 */ 269 }; 270 const long min_idsel = 0, max_idsel = 8, irqs_per_slot = 5; 271 return COMMON_TABLE_LOOKUP; 272} 273 274 275/* 276 * The System Vectors 277 * 278 * In order that T2_HAE_ADDRESS should be a constant, we play 279 * these games with GAMMA_BIAS. 280 */ 281 282#if defined(CONFIG_ALPHA_GENERIC) || !defined(CONFIG_ALPHA_GAMMA) 283#undef GAMMA_BIAS 284#define GAMMA_BIAS 0 285struct alpha_machine_vector sable_mv __initmv = { 286 vector_name: "Sable", 287 DO_EV4_MMU, 288 DO_DEFAULT_RTC, 289 DO_T2_IO, 290 DO_T2_BUS, 291 machine_check: t2_machine_check, 292 max_dma_address: ALPHA_MAX_DMA_ADDRESS, 293 min_io_address: EISA_DEFAULT_IO_BASE, 294 min_mem_address: DEFAULT_MEM_BASE, 295 296 nr_irqs: 40, 297 device_interrupt: sable_srm_device_interrupt, 298 299 init_arch: t2_init_arch, 300 init_irq: sable_init_irq, 301 init_rtc: common_init_rtc, 302 init_pci: common_init_pci, 303 kill_arch: NULL, 304 pci_map_irq: sable_map_irq, 305 pci_swizzle: common_swizzle, 306 307 sys: { t2: { 308 gamma_bias: 0 309 } } 310}; 311ALIAS_MV(sable) 312#endif 313 314#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_GAMMA) 315#undef GAMMA_BIAS 316#define GAMMA_BIAS _GAMMA_BIAS 317struct alpha_machine_vector sable_gamma_mv __initmv = { 318 vector_name: "Sable-Gamma", 319 DO_EV5_MMU, 320 DO_DEFAULT_RTC, 321 DO_T2_IO, 322 DO_T2_BUS, 323 machine_check: t2_machine_check, 324 max_dma_address: ALPHA_MAX_DMA_ADDRESS, 325 min_io_address: EISA_DEFAULT_IO_BASE, 326 min_mem_address: DEFAULT_MEM_BASE, 327 328 nr_irqs: 40, 329 device_interrupt: sable_srm_device_interrupt, 330 331 init_arch: t2_init_arch, 332 init_irq: sable_init_irq, 333 init_rtc: common_init_rtc, 334 init_pci: common_init_pci, 335 pci_map_irq: sable_map_irq, 336 pci_swizzle: common_swizzle, 337 338 sys: { t2: { 339 gamma_bias: _GAMMA_BIAS 340 } } 341}; 342ALIAS_MV(sable_gamma) 343#endif 344