1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * linux/arch/alpha/kernel/sys_cabriolet.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 Cabriolet (AlphaPC64), EB66+, and EB164, 10 * PC164 and LX164. 11 */ 12 13 #include <linux/kernel.h> 14 #include <linux/types.h> 15 #include <linux/mm.h> 16 #include <linux/sched.h> 17 #include <linux/pci.h> 18 #include <linux/init.h> 19 #include <linux/bitops.h> 20 21 #include <asm/ptrace.h> 22 #include <asm/dma.h> 23 #include <asm/irq.h> 24 #include <asm/mmu_context.h> 25 #include <asm/io.h> 26 #include <asm/pgtable.h> 27 #include <asm/core_apecs.h> 28 #include <asm/core_cia.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 /* Note mask bit is true for DISABLED irqs. */ 39 static unsigned long cached_irq_mask = ~0UL; 40 41 static inline void 42 cabriolet_update_irq_hw(unsigned int irq, unsigned long mask) 43 { 44 int ofs = (irq - 16) / 8; 45 outb(mask >> (16 + ofs * 8), 0x804 + ofs); 46 } 47 48 static inline void 49 cabriolet_enable_irq(struct irq_data *d) 50 { 51 cabriolet_update_irq_hw(d->irq, cached_irq_mask &= ~(1UL << d->irq)); 52 } 53 54 static void 55 cabriolet_disable_irq(struct irq_data *d) 56 { 57 cabriolet_update_irq_hw(d->irq, cached_irq_mask |= 1UL << d->irq); 58 } 59 60 static struct irq_chip cabriolet_irq_type = { 61 .name = "CABRIOLET", 62 .irq_unmask = cabriolet_enable_irq, 63 .irq_mask = cabriolet_disable_irq, 64 .irq_mask_ack = cabriolet_disable_irq, 65 }; 66 67 static void 68 cabriolet_device_interrupt(unsigned long v) 69 { 70 unsigned long pld; 71 unsigned int i; 72 73 /* Read the interrupt summary registers */ 74 pld = inb(0x804) | (inb(0x805) << 8) | (inb(0x806) << 16); 75 76 /* 77 * Now for every possible bit set, work through them and call 78 * the appropriate interrupt handler. 79 */ 80 while (pld) { 81 i = ffz(~pld); 82 pld &= pld - 1; /* clear least bit set */ 83 if (i == 4) { 84 isa_device_interrupt(v); 85 } else { 86 handle_irq(16 + i); 87 } 88 } 89 } 90 91 static void __init 92 common_init_irq(void (*srm_dev_int)(unsigned long v)) 93 { 94 init_i8259a_irqs(); 95 96 if (alpha_using_srm) { 97 alpha_mv.device_interrupt = srm_dev_int; 98 init_srm_irqs(35, 0); 99 } 100 else { 101 long i; 102 103 outb(0xff, 0x804); 104 outb(0xff, 0x805); 105 outb(0xff, 0x806); 106 107 for (i = 16; i < 35; ++i) { 108 irq_set_chip_and_handler(i, &cabriolet_irq_type, 109 handle_level_irq); 110 irq_set_status_flags(i, IRQ_LEVEL); 111 } 112 } 113 114 common_init_isa_dma(); 115 if (request_irq(16 + 4, no_action, 0, "isa-cascade", NULL)) 116 pr_err("Failed to register isa-cascade interrupt\n"); 117 } 118 119 #ifndef CONFIG_ALPHA_PC164 120 static void __init 121 cabriolet_init_irq(void) 122 { 123 common_init_irq(srm_device_interrupt); 124 } 125 #endif 126 127 #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_PC164) 128 /* In theory, the PC164 has the same interrupt hardware as the other 129 Cabriolet based systems. However, something got screwed up late 130 in the development cycle which broke the interrupt masking hardware. 131 Repeat, it is not possible to mask and ack interrupts. At all. 132 133 In an attempt to work around this, while processing interrupts, 134 we do not allow the IPL to drop below what it is currently. This 135 prevents the possibility of recursion. 136 137 ??? Another option might be to force all PCI devices to use edge 138 triggered rather than level triggered interrupts. That might be 139 too invasive though. */ 140 141 static void 142 pc164_srm_device_interrupt(unsigned long v) 143 { 144 __min_ipl = getipl(); 145 srm_device_interrupt(v); 146 __min_ipl = 0; 147 } 148 149 static void 150 pc164_device_interrupt(unsigned long v) 151 { 152 __min_ipl = getipl(); 153 cabriolet_device_interrupt(v); 154 __min_ipl = 0; 155 } 156 157 static void __init 158 pc164_init_irq(void) 159 { 160 common_init_irq(pc164_srm_device_interrupt); 161 } 162 #endif 163 164 /* 165 * The EB66+ is very similar to the EB66 except that it does not have 166 * the on-board NCR and Tulip chips. In the code below, I have used 167 * slot number to refer to the id select line and *not* the slot 168 * number used in the EB66+ documentation. However, in the table, 169 * I've given the slot number, the id select line and the Jxx number 170 * that's printed on the board. The interrupt pins from the PCI slots 171 * are wired into 3 interrupt summary registers at 0x804, 0x805 and 172 * 0x806 ISA. 173 * 174 * In the table, -1 means don't assign an IRQ number. This is usually 175 * because it is the Saturn IO (SIO) PCI/ISA Bridge Chip. 176 */ 177 178 static inline int 179 eb66p_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) 180 { 181 static char irq_tab[5][5] = { 182 /*INT INTA INTB INTC INTD */ 183 {16+0, 16+0, 16+5, 16+9, 16+13}, /* IdSel 6, slot 0, J25 */ 184 {16+1, 16+1, 16+6, 16+10, 16+14}, /* IdSel 7, slot 1, J26 */ 185 { -1, -1, -1, -1, -1}, /* IdSel 8, SIO */ 186 {16+2, 16+2, 16+7, 16+11, 16+15}, /* IdSel 9, slot 2, J27 */ 187 {16+3, 16+3, 16+8, 16+12, 16+6} /* IdSel 10, slot 3, J28 */ 188 }; 189 const long min_idsel = 6, max_idsel = 10, irqs_per_slot = 5; 190 return COMMON_TABLE_LOOKUP; 191 } 192 193 194 /* 195 * The AlphaPC64 is very similar to the EB66+ except that its slots 196 * are numbered differently. In the code below, I have used slot 197 * number to refer to the id select line and *not* the slot number 198 * used in the AlphaPC64 documentation. However, in the table, I've 199 * given the slot number, the id select line and the Jxx number that's 200 * printed on the board. The interrupt pins from the PCI slots are 201 * wired into 3 interrupt summary registers at 0x804, 0x805 and 0x806 202 * ISA. 203 * 204 * In the table, -1 means don't assign an IRQ number. This is usually 205 * because it is the Saturn IO (SIO) PCI/ISA Bridge Chip. 206 */ 207 208 static inline int 209 cabriolet_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) 210 { 211 static char irq_tab[5][5] = { 212 /*INT INTA INTB INTC INTD */ 213 { 16+2, 16+2, 16+7, 16+11, 16+15}, /* IdSel 5, slot 2, J21 */ 214 { 16+0, 16+0, 16+5, 16+9, 16+13}, /* IdSel 6, slot 0, J19 */ 215 { 16+1, 16+1, 16+6, 16+10, 16+14}, /* IdSel 7, slot 1, J20 */ 216 { -1, -1, -1, -1, -1}, /* IdSel 8, SIO */ 217 { 16+3, 16+3, 16+8, 16+12, 16+16} /* IdSel 9, slot 3, J22 */ 218 }; 219 const long min_idsel = 5, max_idsel = 9, irqs_per_slot = 5; 220 return COMMON_TABLE_LOOKUP; 221 } 222 223 static inline void __init 224 cabriolet_enable_ide(void) 225 { 226 if (pc873xx_probe() == -1) { 227 printk(KERN_ERR "Probing for PC873xx Super IO chip failed.\n"); 228 } else { 229 printk(KERN_INFO "Found %s Super IO chip at 0x%x\n", 230 pc873xx_get_model(), pc873xx_get_base()); 231 232 pc873xx_enable_ide(); 233 } 234 } 235 236 static inline void __init 237 cabriolet_init_pci(void) 238 { 239 common_init_pci(); 240 cabriolet_enable_ide(); 241 } 242 243 static inline void __init 244 cia_cab_init_pci(void) 245 { 246 cia_init_pci(); 247 cabriolet_enable_ide(); 248 } 249 250 /* 251 * The PC164 and LX164 have 19 PCI interrupts, four from each of the four 252 * PCI slots, the SIO, PCI/IDE, and USB. 253 * 254 * Each of the interrupts can be individually masked. This is 255 * accomplished by setting the appropriate bit in the mask register. 256 * A bit is set by writing a "1" to the desired position in the mask 257 * register and cleared by writing a "0". There are 3 mask registers 258 * located at ISA address 804h, 805h and 806h. 259 * 260 * An I/O read at ISA address 804h, 805h, 806h will return the 261 * state of the 11 PCI interrupts and not the state of the MASKED 262 * interrupts. 263 * 264 * Note: A write to I/O 804h, 805h, and 806h the mask register will be 265 * updated. 266 * 267 * 268 * ISA DATA<7:0> 269 * ISA +--------------------------------------------------------------+ 270 * ADDRESS | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 271 * +==============================================================+ 272 * 0x804 | INTB0 | USB | IDE | SIO | INTA3 |INTA2 | INTA1 | INTA0 | 273 * +--------------------------------------------------------------+ 274 * 0x805 | INTD0 | INTC3 | INTC2 | INTC1 | INTC0 |INTB3 | INTB2 | INTB1 | 275 * +--------------------------------------------------------------+ 276 * 0x806 | Rsrv | Rsrv | Rsrv | Rsrv | Rsrv |INTD3 | INTD2 | INTD1 | 277 * +--------------------------------------------------------------+ 278 * * Rsrv = reserved bits 279 * Note: The mask register is write-only. 280 * 281 * IdSel 282 * 5 32 bit PCI option slot 2 283 * 6 64 bit PCI option slot 0 284 * 7 64 bit PCI option slot 1 285 * 8 Saturn I/O 286 * 9 32 bit PCI option slot 3 287 * 10 USB 288 * 11 IDE 289 * 290 */ 291 292 static inline int 293 alphapc164_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) 294 { 295 static char irq_tab[7][5] = { 296 /*INT INTA INTB INTC INTD */ 297 { 16+2, 16+2, 16+9, 16+13, 16+17}, /* IdSel 5, slot 2, J20 */ 298 { 16+0, 16+0, 16+7, 16+11, 16+15}, /* IdSel 6, slot 0, J29 */ 299 { 16+1, 16+1, 16+8, 16+12, 16+16}, /* IdSel 7, slot 1, J26 */ 300 { -1, -1, -1, -1, -1}, /* IdSel 8, SIO */ 301 { 16+3, 16+3, 16+10, 16+14, 16+18}, /* IdSel 9, slot 3, J19 */ 302 { 16+6, 16+6, 16+6, 16+6, 16+6}, /* IdSel 10, USB */ 303 { 16+5, 16+5, 16+5, 16+5, 16+5} /* IdSel 11, IDE */ 304 }; 305 const long min_idsel = 5, max_idsel = 11, irqs_per_slot = 5; 306 return COMMON_TABLE_LOOKUP; 307 } 308 309 static inline void __init 310 alphapc164_init_pci(void) 311 { 312 cia_init_pci(); 313 SMC93x_Init(); 314 } 315 316 317 /* 318 * The System Vector 319 */ 320 321 #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_CABRIOLET) 322 struct alpha_machine_vector cabriolet_mv __initmv = { 323 .vector_name = "Cabriolet", 324 DO_EV4_MMU, 325 DO_DEFAULT_RTC, 326 DO_APECS_IO, 327 .machine_check = apecs_machine_check, 328 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, 329 .min_io_address = DEFAULT_IO_BASE, 330 .min_mem_address = APECS_AND_LCA_DEFAULT_MEM_BASE, 331 332 .nr_irqs = 35, 333 .device_interrupt = cabriolet_device_interrupt, 334 335 .init_arch = apecs_init_arch, 336 .init_irq = cabriolet_init_irq, 337 .init_rtc = common_init_rtc, 338 .init_pci = cabriolet_init_pci, 339 .pci_map_irq = cabriolet_map_irq, 340 .pci_swizzle = common_swizzle, 341 }; 342 #ifndef CONFIG_ALPHA_EB64P 343 ALIAS_MV(cabriolet) 344 #endif 345 #endif 346 347 #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_EB164) 348 struct alpha_machine_vector eb164_mv __initmv = { 349 .vector_name = "EB164", 350 DO_EV5_MMU, 351 DO_DEFAULT_RTC, 352 DO_CIA_IO, 353 .machine_check = cia_machine_check, 354 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, 355 .min_io_address = DEFAULT_IO_BASE, 356 .min_mem_address = CIA_DEFAULT_MEM_BASE, 357 358 .nr_irqs = 35, 359 .device_interrupt = cabriolet_device_interrupt, 360 361 .init_arch = cia_init_arch, 362 .init_irq = cabriolet_init_irq, 363 .init_rtc = common_init_rtc, 364 .init_pci = cia_cab_init_pci, 365 .kill_arch = cia_kill_arch, 366 .pci_map_irq = cabriolet_map_irq, 367 .pci_swizzle = common_swizzle, 368 }; 369 ALIAS_MV(eb164) 370 #endif 371 372 #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_EB66P) 373 struct alpha_machine_vector eb66p_mv __initmv = { 374 .vector_name = "EB66+", 375 DO_EV4_MMU, 376 DO_DEFAULT_RTC, 377 DO_LCA_IO, 378 .machine_check = lca_machine_check, 379 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, 380 .min_io_address = DEFAULT_IO_BASE, 381 .min_mem_address = APECS_AND_LCA_DEFAULT_MEM_BASE, 382 383 .nr_irqs = 35, 384 .device_interrupt = cabriolet_device_interrupt, 385 386 .init_arch = lca_init_arch, 387 .init_irq = cabriolet_init_irq, 388 .init_rtc = common_init_rtc, 389 .init_pci = cabriolet_init_pci, 390 .pci_map_irq = eb66p_map_irq, 391 .pci_swizzle = common_swizzle, 392 }; 393 ALIAS_MV(eb66p) 394 #endif 395 396 #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_LX164) 397 struct alpha_machine_vector lx164_mv __initmv = { 398 .vector_name = "LX164", 399 DO_EV5_MMU, 400 DO_DEFAULT_RTC, 401 DO_PYXIS_IO, 402 .machine_check = cia_machine_check, 403 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, 404 .min_io_address = DEFAULT_IO_BASE, 405 .min_mem_address = DEFAULT_MEM_BASE, 406 .pci_dac_offset = PYXIS_DAC_OFFSET, 407 408 .nr_irqs = 35, 409 .device_interrupt = cabriolet_device_interrupt, 410 411 .init_arch = pyxis_init_arch, 412 .init_irq = cabriolet_init_irq, 413 .init_rtc = common_init_rtc, 414 .init_pci = alphapc164_init_pci, 415 .kill_arch = cia_kill_arch, 416 .pci_map_irq = alphapc164_map_irq, 417 .pci_swizzle = common_swizzle, 418 }; 419 ALIAS_MV(lx164) 420 #endif 421 422 #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_PC164) 423 struct alpha_machine_vector pc164_mv __initmv = { 424 .vector_name = "PC164", 425 DO_EV5_MMU, 426 DO_DEFAULT_RTC, 427 DO_CIA_IO, 428 .machine_check = cia_machine_check, 429 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, 430 .min_io_address = DEFAULT_IO_BASE, 431 .min_mem_address = CIA_DEFAULT_MEM_BASE, 432 433 .nr_irqs = 35, 434 .device_interrupt = pc164_device_interrupt, 435 436 .init_arch = cia_init_arch, 437 .init_irq = pc164_init_irq, 438 .init_rtc = common_init_rtc, 439 .init_pci = alphapc164_init_pci, 440 .kill_arch = cia_kill_arch, 441 .pci_map_irq = alphapc164_map_irq, 442 .pci_swizzle = common_swizzle, 443 }; 444 ALIAS_MV(pc164) 445 #endif 446