1/* 2 * SGI Visual Workstation support and quirks, unmaintained. 3 * 4 * Split out from setup.c by davej@suse.de 5 * 6 * Copyright (C) 1999 Bent Hagemark, Ingo Molnar 7 * 8 * SGI Visual Workstation interrupt controller 9 * 10 * The Cobalt system ASIC in the Visual Workstation contains a "Cobalt" APIC 11 * which serves as the main interrupt controller in the system. Non-legacy 12 * hardware in the system uses this controller directly. Legacy devices 13 * are connected to the PIIX4 which in turn has its 8259(s) connected to 14 * a of the Cobalt APIC entry. 15 * 16 * 09/02/2000 - Updated for 2.4 by jbarnes@sgi.com 17 * 18 * 25/11/2002 - Updated for 2.5 by Andrey Panin <pazke@orbita1.ru> 19 */ 20#include <linux/interrupt.h> 21#include <linux/module.h> 22#include <linux/init.h> 23#include <linux/smp.h> 24 25#include <asm/visws/cobalt.h> 26#include <asm/visws/piix4.h> 27#include <asm/io_apic.h> 28#include <asm/fixmap.h> 29#include <asm/reboot.h> 30#include <asm/setup.h> 31#include <asm/apic.h> 32#include <asm/e820.h> 33#include <asm/time.h> 34#include <asm/io.h> 35 36#include <linux/kernel_stat.h> 37 38#include <asm/i8259.h> 39#include <asm/irq_vectors.h> 40#include <asm/visws/lithium.h> 41 42#include <linux/sched.h> 43#include <linux/kernel.h> 44#include <linux/pci.h> 45#include <linux/pci_ids.h> 46 47extern int no_broadcast; 48 49char visws_board_type = -1; 50char visws_board_rev = -1; 51 52static void __init visws_time_init(void) 53{ 54 printk(KERN_INFO "Starting Cobalt Timer system clock\n"); 55 56 /* Set the countdown value */ 57 co_cpu_write(CO_CPU_TIMEVAL, CO_TIME_HZ/HZ); 58 59 /* Start the timer */ 60 co_cpu_write(CO_CPU_CTRL, co_cpu_read(CO_CPU_CTRL) | CO_CTRL_TIMERUN); 61 62 /* Enable (unmask) the timer interrupt */ 63 co_cpu_write(CO_CPU_CTRL, co_cpu_read(CO_CPU_CTRL) & ~CO_CTRL_TIMEMASK); 64 65 setup_default_timer_irq(); 66} 67 68/* Replaces the default init_ISA_irqs in the generic setup */ 69static void __init visws_pre_intr_init(void) 70{ 71 init_VISWS_APIC_irqs(); 72} 73 74/* Quirk for machine specific memory setup. */ 75 76#define MB (1024 * 1024) 77 78unsigned long sgivwfb_mem_phys; 79unsigned long sgivwfb_mem_size; 80EXPORT_SYMBOL(sgivwfb_mem_phys); 81EXPORT_SYMBOL(sgivwfb_mem_size); 82 83long long mem_size __initdata = 0; 84 85static char * __init visws_memory_setup(void) 86{ 87 long long gfx_mem_size = 8 * MB; 88 89 mem_size = boot_params.alt_mem_k; 90 91 if (!mem_size) { 92 printk(KERN_WARNING "Bootloader didn't set memory size, upgrade it !\n"); 93 mem_size = 128 * MB; 94 } 95 96 /* 97 * this hardcodes the graphics memory to 8 MB 98 * it really should be sized dynamically (or at least 99 * set as a boot param) 100 */ 101 if (!sgivwfb_mem_size) { 102 printk(KERN_WARNING "Defaulting to 8 MB framebuffer size\n"); 103 sgivwfb_mem_size = 8 * MB; 104 } 105 106 /* 107 * Trim to nearest MB 108 */ 109 sgivwfb_mem_size &= ~((1 << 20) - 1); 110 sgivwfb_mem_phys = mem_size - gfx_mem_size; 111 112 e820_add_region(0, LOWMEMSIZE(), E820_RAM); 113 e820_add_region(HIGH_MEMORY, mem_size - sgivwfb_mem_size - HIGH_MEMORY, E820_RAM); 114 e820_add_region(sgivwfb_mem_phys, sgivwfb_mem_size, E820_RESERVED); 115 116 return "PROM"; 117} 118 119static void visws_machine_emergency_restart(void) 120{ 121 /* 122 * Visual Workstations restart after this 123 * register is poked on the PIIX4 124 */ 125 outb(PIIX4_RESET_VAL, PIIX4_RESET_PORT); 126} 127 128static void visws_machine_power_off(void) 129{ 130 unsigned short pm_status; 131/* extern unsigned int pci_bus0; */ 132 133 while ((pm_status = inw(PMSTS_PORT)) & 0x100) 134 outw(pm_status, PMSTS_PORT); 135 136 outw(PM_SUSPEND_ENABLE, PMCNTRL_PORT); 137 138 mdelay(10); 139 140#define PCI_CONF1_ADDRESS(bus, devfn, reg) \ 141 (0x80000000 | (bus << 16) | (devfn << 8) | (reg & ~3)) 142 143/* outl(PCI_CONF1_ADDRESS(pci_bus0, SPECIAL_DEV, SPECIAL_REG), 0xCF8); */ 144 outl(PIIX_SPECIAL_STOP, 0xCFC); 145} 146 147static void __init visws_get_smp_config(unsigned int early) 148{ 149} 150 151/* 152 * The Visual Workstation is Intel MP compliant in the hardware 153 * sense, but it doesn't have a BIOS(-configuration table). 154 * No problem for Linux. 155 */ 156 157static void __init MP_processor_info(struct mpc_cpu *m) 158{ 159 int ver, logical_apicid; 160 physid_mask_t apic_cpus; 161 162 if (!(m->cpuflag & CPU_ENABLED)) 163 return; 164 165 logical_apicid = m->apicid; 166 printk(KERN_INFO "%sCPU #%d %u:%u APIC version %d\n", 167 m->cpuflag & CPU_BOOTPROCESSOR ? "Bootup " : "", 168 m->apicid, (m->cpufeature & CPU_FAMILY_MASK) >> 8, 169 (m->cpufeature & CPU_MODEL_MASK) >> 4, m->apicver); 170 171 if (m->cpuflag & CPU_BOOTPROCESSOR) 172 boot_cpu_physical_apicid = m->apicid; 173 174 ver = m->apicver; 175 if ((ver >= 0x14 && m->apicid >= 0xff) || m->apicid >= 0xf) { 176 printk(KERN_ERR "Processor #%d INVALID. (Max ID: %d).\n", 177 m->apicid, MAX_APICS); 178 return; 179 } 180 181 apic->apicid_to_cpu_present(m->apicid, &apic_cpus); 182 physids_or(phys_cpu_present_map, phys_cpu_present_map, apic_cpus); 183 /* 184 * Validate version 185 */ 186 if (ver == 0x0) { 187 printk(KERN_ERR "BIOS bug, APIC version is 0 for CPU#%d! " 188 "fixing up to 0x10. (tell your hw vendor)\n", 189 m->apicid); 190 ver = 0x10; 191 } 192 apic_version[m->apicid] = ver; 193} 194 195static void __init visws_find_smp_config(void) 196{ 197 struct mpc_cpu *mp = phys_to_virt(CO_CPU_TAB_PHYS); 198 unsigned short ncpus = readw(phys_to_virt(CO_CPU_NUM_PHYS)); 199 200 if (ncpus > CO_CPU_MAX) { 201 printk(KERN_WARNING "find_visws_smp: got cpu count of %d at %p\n", 202 ncpus, mp); 203 204 ncpus = CO_CPU_MAX; 205 } 206 207 if (ncpus > setup_max_cpus) 208 ncpus = setup_max_cpus; 209 210#ifdef CONFIG_X86_LOCAL_APIC 211 smp_found_config = 1; 212#endif 213 while (ncpus--) 214 MP_processor_info(mp++); 215 216 mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; 217} 218 219static void visws_trap_init(void); 220 221void __init visws_early_detect(void) 222{ 223 int raw; 224 225 visws_board_type = (char)(inb_p(PIIX_GPI_BD_REG) & PIIX_GPI_BD_REG) 226 >> PIIX_GPI_BD_SHIFT; 227 228 if (visws_board_type < 0) 229 return; 230 231 /* 232 * Override the default platform setup functions 233 */ 234 x86_init.resources.memory_setup = visws_memory_setup; 235 x86_init.mpparse.get_smp_config = visws_get_smp_config; 236 x86_init.mpparse.find_smp_config = visws_find_smp_config; 237 x86_init.irqs.pre_vector_init = visws_pre_intr_init; 238 x86_init.irqs.trap_init = visws_trap_init; 239 x86_init.timers.timer_init = visws_time_init; 240 x86_init.pci.init = pci_visws_init; 241 x86_init.pci.init_irq = x86_init_noop; 242 243 /* 244 * Install reboot quirks: 245 */ 246 pm_power_off = visws_machine_power_off; 247 machine_ops.emergency_restart = visws_machine_emergency_restart; 248 249 /* 250 * Do not use broadcast IPIs: 251 */ 252 no_broadcast = 0; 253 254#ifdef CONFIG_X86_IO_APIC 255 /* 256 * Turn off IO-APIC detection and initialization: 257 */ 258 skip_ioapic_setup = 1; 259#endif 260 261 /* 262 * Get Board rev. 263 * First, we have to initialize the 307 part to allow us access 264 * to the GPIO registers. Let's map them at 0x0fc0 which is right 265 * after the PIIX4 PM section. 266 */ 267 outb_p(SIO_DEV_SEL, SIO_INDEX); 268 outb_p(SIO_GP_DEV, SIO_DATA); /* Talk to GPIO regs. */ 269 270 outb_p(SIO_DEV_MSB, SIO_INDEX); 271 outb_p(SIO_GP_MSB, SIO_DATA); /* MSB of GPIO base address */ 272 273 outb_p(SIO_DEV_LSB, SIO_INDEX); 274 outb_p(SIO_GP_LSB, SIO_DATA); /* LSB of GPIO base address */ 275 276 outb_p(SIO_DEV_ENB, SIO_INDEX); 277 outb_p(1, SIO_DATA); /* Enable GPIO registers. */ 278 279 /* 280 * Now, we have to map the power management section to write 281 * a bit which enables access to the GPIO registers. 282 * What lunatic came up with this shit? 283 */ 284 outb_p(SIO_DEV_SEL, SIO_INDEX); 285 outb_p(SIO_PM_DEV, SIO_DATA); /* Talk to GPIO regs. */ 286 287 outb_p(SIO_DEV_MSB, SIO_INDEX); 288 outb_p(SIO_PM_MSB, SIO_DATA); /* MSB of PM base address */ 289 290 outb_p(SIO_DEV_LSB, SIO_INDEX); 291 outb_p(SIO_PM_LSB, SIO_DATA); /* LSB of PM base address */ 292 293 outb_p(SIO_DEV_ENB, SIO_INDEX); 294 outb_p(1, SIO_DATA); /* Enable PM registers. */ 295 296 /* 297 * Now, write the PM register which enables the GPIO registers. 298 */ 299 outb_p(SIO_PM_FER2, SIO_PM_INDEX); 300 outb_p(SIO_PM_GP_EN, SIO_PM_DATA); 301 302 /* 303 * Now, initialize the GPIO registers. 304 * We want them all to be inputs which is the 305 * power on default, so let's leave them alone. 306 * So, let's just read the board rev! 307 */ 308 raw = inb_p(SIO_GP_DATA1); 309 raw &= 0x7f; /* 7 bits of valid board revision ID. */ 310 311 if (visws_board_type == VISWS_320) { 312 if (raw < 0x6) { 313 visws_board_rev = 4; 314 } else if (raw < 0xc) { 315 visws_board_rev = 5; 316 } else { 317 visws_board_rev = 6; 318 } 319 } else if (visws_board_type == VISWS_540) { 320 visws_board_rev = 2; 321 } else { 322 visws_board_rev = raw; 323 } 324 325 printk(KERN_INFO "Silicon Graphics Visual Workstation %s (rev %d) detected\n", 326 (visws_board_type == VISWS_320 ? "320" : 327 (visws_board_type == VISWS_540 ? "540" : 328 "unknown")), visws_board_rev); 329} 330 331#define A01234 (LI_INTA_0 | LI_INTA_1 | LI_INTA_2 | LI_INTA_3 | LI_INTA_4) 332#define BCD (LI_INTB | LI_INTC | LI_INTD) 333#define ALLDEVS (A01234 | BCD) 334 335static __init void lithium_init(void) 336{ 337 set_fixmap(FIX_LI_PCIA, LI_PCI_A_PHYS); 338 set_fixmap(FIX_LI_PCIB, LI_PCI_B_PHYS); 339 340 if ((li_pcia_read16(PCI_VENDOR_ID) != PCI_VENDOR_ID_SGI) || 341 (li_pcia_read16(PCI_DEVICE_ID) != PCI_DEVICE_ID_SGI_LITHIUM)) { 342 printk(KERN_EMERG "Lithium hostbridge %c not found\n", 'A'); 343/* panic("This machine is not SGI Visual Workstation 320/540"); */ 344 } 345 346 if ((li_pcib_read16(PCI_VENDOR_ID) != PCI_VENDOR_ID_SGI) || 347 (li_pcib_read16(PCI_DEVICE_ID) != PCI_DEVICE_ID_SGI_LITHIUM)) { 348 printk(KERN_EMERG "Lithium hostbridge %c not found\n", 'B'); 349/* panic("This machine is not SGI Visual Workstation 320/540"); */ 350 } 351 352 li_pcia_write16(LI_PCI_INTEN, ALLDEVS); 353 li_pcib_write16(LI_PCI_INTEN, ALLDEVS); 354} 355 356static __init void cobalt_init(void) 357{ 358 /* 359 * On normal SMP PC this is used only with SMP, but we have to 360 * use it and set it up here to start the Cobalt clock 361 */ 362 set_fixmap(FIX_APIC_BASE, APIC_DEFAULT_PHYS_BASE); 363 setup_local_APIC(); 364 printk(KERN_INFO "Local APIC Version %#x, ID %#x\n", 365 (unsigned int)apic_read(APIC_LVR), 366 (unsigned int)apic_read(APIC_ID)); 367 368 set_fixmap(FIX_CO_CPU, CO_CPU_PHYS); 369 set_fixmap(FIX_CO_APIC, CO_APIC_PHYS); 370 printk(KERN_INFO "Cobalt Revision %#lx, APIC ID %#lx\n", 371 co_cpu_read(CO_CPU_REV), co_apic_read(CO_APIC_ID)); 372 373 /* Enable Cobalt APIC being careful to NOT change the ID! */ 374 co_apic_write(CO_APIC_ID, co_apic_read(CO_APIC_ID) | CO_APIC_ENABLE); 375 376 printk(KERN_INFO "Cobalt APIC enabled: ID reg %#lx\n", 377 co_apic_read(CO_APIC_ID)); 378} 379 380static void __init visws_trap_init(void) 381{ 382 lithium_init(); 383 cobalt_init(); 384} 385 386/* 387 * IRQ controller / APIC support: 388 */ 389 390static DEFINE_SPINLOCK(cobalt_lock); 391 392/* 393 * Set the given Cobalt APIC Redirection Table entry to point 394 * to the given IDT vector/index. 395 */ 396static inline void co_apic_set(int entry, int irq) 397{ 398 co_apic_write(CO_APIC_LO(entry), CO_APIC_LEVEL | (irq + FIRST_EXTERNAL_VECTOR)); 399 co_apic_write(CO_APIC_HI(entry), 0); 400} 401 402/* 403 * Cobalt (IO)-APIC functions to handle PCI devices. 404 */ 405static inline int co_apic_ide0_hack(void) 406{ 407 extern char visws_board_type; 408 extern char visws_board_rev; 409 410 if (visws_board_type == VISWS_320 && visws_board_rev == 5) 411 return 5; 412 return CO_APIC_IDE0; 413} 414 415static int is_co_apic(unsigned int irq) 416{ 417 if (IS_CO_APIC(irq)) 418 return CO_APIC(irq); 419 420 switch (irq) { 421 case 0: return CO_APIC_CPU; 422 case CO_IRQ_IDE0: return co_apic_ide0_hack(); 423 case CO_IRQ_IDE1: return CO_APIC_IDE1; 424 default: return -1; 425 } 426} 427 428 429/* 430 * This is the SGI Cobalt (IO-)APIC: 431 */ 432 433static void enable_cobalt_irq(unsigned int irq) 434{ 435 co_apic_set(is_co_apic(irq), irq); 436} 437 438static void disable_cobalt_irq(unsigned int irq) 439{ 440 int entry = is_co_apic(irq); 441 442 co_apic_write(CO_APIC_LO(entry), CO_APIC_MASK); 443 co_apic_read(CO_APIC_LO(entry)); 444} 445 446/* 447 * "irq" really just serves to identify the device. Here is where we 448 * map this to the Cobalt APIC entry where it's physically wired. 449 * This is called via request_irq -> setup_irq -> irq_desc->startup() 450 */ 451static unsigned int startup_cobalt_irq(unsigned int irq) 452{ 453 unsigned long flags; 454 struct irq_desc *desc = irq_to_desc(irq); 455 456 spin_lock_irqsave(&cobalt_lock, flags); 457 if ((desc->status & (IRQ_DISABLED | IRQ_INPROGRESS | IRQ_WAITING))) 458 desc->status &= ~(IRQ_DISABLED | IRQ_INPROGRESS | IRQ_WAITING); 459 enable_cobalt_irq(irq); 460 spin_unlock_irqrestore(&cobalt_lock, flags); 461 return 0; 462} 463 464static void ack_cobalt_irq(unsigned int irq) 465{ 466 unsigned long flags; 467 468 spin_lock_irqsave(&cobalt_lock, flags); 469 disable_cobalt_irq(irq); 470 apic_write(APIC_EOI, APIC_EIO_ACK); 471 spin_unlock_irqrestore(&cobalt_lock, flags); 472} 473 474static void end_cobalt_irq(unsigned int irq) 475{ 476 unsigned long flags; 477 struct irq_desc *desc = irq_to_desc(irq); 478 479 spin_lock_irqsave(&cobalt_lock, flags); 480 if (!(desc->status & (IRQ_DISABLED | IRQ_INPROGRESS))) 481 enable_cobalt_irq(irq); 482 spin_unlock_irqrestore(&cobalt_lock, flags); 483} 484 485static struct irq_chip cobalt_irq_type = { 486 .name = "Cobalt-APIC", 487 .startup = startup_cobalt_irq, 488 .shutdown = disable_cobalt_irq, 489 .enable = enable_cobalt_irq, 490 .disable = disable_cobalt_irq, 491 .ack = ack_cobalt_irq, 492 .end = end_cobalt_irq, 493}; 494 495 496/* 497 * This is the PIIX4-based 8259 that is wired up indirectly to Cobalt 498 * -- not the manner expected by the code in i8259.c. 499 * 500 * there is a 'master' physical interrupt source that gets sent to 501 * the CPU. But in the chipset there are various 'virtual' interrupts 502 * waiting to be handled. We represent this to Linux through a 'master' 503 * interrupt controller type, and through a special virtual interrupt- 504 * controller. Device drivers only see the virtual interrupt sources. 505 */ 506static unsigned int startup_piix4_master_irq(unsigned int irq) 507{ 508 legacy_pic->init(0); 509 510 return startup_cobalt_irq(irq); 511} 512 513static void end_piix4_master_irq(unsigned int irq) 514{ 515 unsigned long flags; 516 517 spin_lock_irqsave(&cobalt_lock, flags); 518 enable_cobalt_irq(irq); 519 spin_unlock_irqrestore(&cobalt_lock, flags); 520} 521 522static struct irq_chip piix4_master_irq_type = { 523 .name = "PIIX4-master", 524 .startup = startup_piix4_master_irq, 525 .ack = ack_cobalt_irq, 526 .end = end_piix4_master_irq, 527}; 528 529 530static struct irq_chip piix4_virtual_irq_type = { 531 .name = "PIIX4-virtual", 532}; 533 534 535/* 536 * PIIX4-8259 master/virtual functions to handle interrupt requests 537 * from legacy devices: floppy, parallel, serial, rtc. 538 * 539 * None of these get Cobalt APIC entries, neither do they have IDT 540 * entries. These interrupts are purely virtual and distributed from 541 * the 'master' interrupt source: CO_IRQ_8259. 542 * 543 * When the 8259 interrupts its handler figures out which of these 544 * devices is interrupting and dispatches to its handler. 545 * 546 * CAREFUL: devices see the 'virtual' interrupt only. Thus disable/ 547 * enable_irq gets the right irq. This 'master' irq is never directly 548 * manipulated by any driver. 549 */ 550static irqreturn_t piix4_master_intr(int irq, void *dev_id) 551{ 552 int realirq; 553 struct irq_desc *desc; 554 unsigned long flags; 555 556 raw_spin_lock_irqsave(&i8259A_lock, flags); 557 558 /* Find out what's interrupting in the PIIX4 master 8259 */ 559 outb(0x0c, 0x20); /* OCW3 Poll command */ 560 realirq = inb(0x20); 561 562 /* 563 * Bit 7 == 0 means invalid/spurious 564 */ 565 if (unlikely(!(realirq & 0x80))) 566 goto out_unlock; 567 568 realirq &= 7; 569 570 if (unlikely(realirq == 2)) { 571 outb(0x0c, 0xa0); 572 realirq = inb(0xa0); 573 574 if (unlikely(!(realirq & 0x80))) 575 goto out_unlock; 576 577 realirq = (realirq & 7) + 8; 578 } 579 580 /* mask and ack interrupt */ 581 cached_irq_mask |= 1 << realirq; 582 if (unlikely(realirq > 7)) { 583 inb(0xa1); 584 outb(cached_slave_mask, 0xa1); 585 outb(0x60 + (realirq & 7), 0xa0); 586 outb(0x60 + 2, 0x20); 587 } else { 588 inb(0x21); 589 outb(cached_master_mask, 0x21); 590 outb(0x60 + realirq, 0x20); 591 } 592 593 raw_spin_unlock_irqrestore(&i8259A_lock, flags); 594 595 desc = irq_to_desc(realirq); 596 597 /* 598 * handle this 'virtual interrupt' as a Cobalt one now. 599 */ 600 kstat_incr_irqs_this_cpu(realirq, desc); 601 602 if (likely(desc->action != NULL)) 603 handle_IRQ_event(realirq, desc->action); 604 605 if (!(desc->status & IRQ_DISABLED)) 606 legacy_pic->chip->unmask(realirq); 607 608 return IRQ_HANDLED; 609 610out_unlock: 611 raw_spin_unlock_irqrestore(&i8259A_lock, flags); 612 return IRQ_NONE; 613} 614 615static struct irqaction master_action = { 616 .handler = piix4_master_intr, 617 .name = "PIIX4-8259", 618}; 619 620static struct irqaction cascade_action = { 621 .handler = no_action, 622 .name = "cascade", 623}; 624 625static inline void set_piix4_virtual_irq_type(void) 626{ 627 piix4_virtual_irq_type.shutdown = i8259A_chip.mask; 628 piix4_virtual_irq_type.enable = i8259A_chip.unmask; 629 piix4_virtual_irq_type.disable = i8259A_chip.mask; 630} 631 632void init_VISWS_APIC_irqs(void) 633{ 634 int i; 635 636 for (i = 0; i < CO_IRQ_APIC0 + CO_APIC_LAST + 1; i++) { 637 struct irq_desc *desc = irq_to_desc(i); 638 639 desc->status = IRQ_DISABLED; 640 desc->action = 0; 641 desc->depth = 1; 642 643 if (i == 0) { 644 desc->chip = &cobalt_irq_type; 645 } 646 else if (i == CO_IRQ_IDE0) { 647 desc->chip = &cobalt_irq_type; 648 } 649 else if (i == CO_IRQ_IDE1) { 650 desc->chip = &cobalt_irq_type; 651 } 652 else if (i == CO_IRQ_8259) { 653 desc->chip = &piix4_master_irq_type; 654 } 655 else if (i < CO_IRQ_APIC0) { 656 set_piix4_virtual_irq_type(); 657 desc->chip = &piix4_virtual_irq_type; 658 } 659 else if (IS_CO_APIC(i)) { 660 desc->chip = &cobalt_irq_type; 661 } 662 } 663 664 setup_irq(CO_IRQ_8259, &master_action); 665 setup_irq(2, &cascade_action); 666} 667