| 1 | |
| 2 | |
| 3 | * HP [BCJ]x000 workstations.
|
| 4 | *
|
| 5 | * This chip is a horrid piece of engineering, and National
|
| 6 | * denies any knowledge of its existence. Thus no datasheet is
|
| 7 | * available off www.national.com.
|
| 8 | *
|
| 9 | * (C) Copyright 2000 Linuxcare, Inc.
|
| 10 | * (C) Copyright 2000 Linuxcare Canada, Inc.
|
| 11 | * (C) Copyright 2000 Martin K. Petersen <[email protected]>
|
| 12 | * (C) Copyright 2000 Alex deVries <[email protected]>
|
| 13 | * (C) Copyright 2001 John Marvin <jsm fc hp com>
|
| 14 | * (C) Copyright 2003 Grant Grundler <grundler parisc-linux org>
|
| 15 | * (C) Copyright 2005 Kyle McMartin <[email protected]>
|
| 16 | * (C) Copyright 2006 Helge Deller <[email protected]>
|
| 17 | *
|
| 18 | * The initial version of this is by Martin Petersen. Alex deVries
|
| 19 | * has spent a bit of time trying to coax it into working.
|
| 20 | *
|
| 21 | * Major changes to get basic interrupt infrastructure working to
|
| 22 | * hopefully be able to support all SuperIO devices. Currently
|
| 23 | * works with serial. -- John Marvin <[email protected]>
|
| 24 | *
|
| 25 | * Converted superio_init() to be a PCI_FIXUP_FINAL callee.
|
| 26 | * -- Kyle McMartin <[email protected]>
|
| 27 |
|
| 28 |
|
| 29 |
|
| 30 | |
| 31 | *
|
| 32 | * Function 0 is an IDE controller. It is identical to a PC87415 IDE
|
| 33 | * controller (and identifies itself as such).
|
| 34 | *
|
| 35 | * Function 1 is a "Legacy I/O" controller. Under this function is a
|
| 36 | * whole mess of legacy I/O peripherals. Of course, HP hasn't enabled
|
| 37 | * all the functionality in hardware, but the following is available:
|
| 38 | *
|
| 39 | * Two 16550A compatible serial controllers
|
| 40 | * An IEEE 1284 compatible parallel port
|
| 41 | * A floppy disk controller
|
| 42 | *
|
| 43 | * Function 2 is a USB controller.
|
| 44 | *
|
| 45 | * We must be incredibly careful during initialization. Since all
|
| 46 | * interrupts are routed through function 1 (which is not allowed by
|
| 47 | * the PCI spec), we need to program the PICs on the legacy I/O port
|
| 48 | * *before* we attempt to set up IDE and USB. @#$!&
|
| 49 | *
|
| 50 | * According to HP, devices are only enabled by firmware if they have
|
| 51 | * a physical device connected.
|
| 52 | *
|
| 53 | * Configuration register bits:
|
| 54 | * 0x5A: FDC, SP1, IDE1, SP2, IDE2, PAR, Reserved, P92
|
| 55 | * 0x5B: RTC, 8259, 8254, DMA1, DMA2, KBC, P61, APM
|
| 56 | *
|
| 57 |
|
| 58 |
|
| 59 | #include <linux/errno.h>
|
| 60 | #include <linux/init.h>
|
| 61 | #include <linux/module.h>
|
| 62 | #include <linux/types.h>
|
| 63 | #include <linux/interrupt.h>
|
| 64 | #include <linux/ioport.h>
|
| 65 | #include <linux/serial.h>
|
| 66 | #include <linux/pci.h>
|
| 67 | #include <linux/parport.h>
|
| 68 | #include <linux/parport_pc.h>
|
| 69 | #include <linux/termios.h>
|
| 70 | #include <linux/tty.h>
|
| 71 | #include <linux/serial_core.h>
|
| 72 | #include <linux/serial_8250.h>
|
| 73 | #include <linux/delay.h>
|
| 74 |
|
| 75 | #include <asm/io.h>
|
| 76 | #include <asm/hardware.h>
|
| 77 | #include <asm/superio.h>
|
| 78 |
|
| 79 | static struct superio_device sio_dev;
|
| 80 |
|
| 81 |
|
| 82 | #undef DEBUG_SUPERIO_INIT
|
| 83 |
|
| 84 | #ifdef DEBUG_SUPERIO_INIT
|
| 85 | #define DBG_INIT(x...) printk(x)
|
| 86 | #else
|
| 87 | #define DBG_INIT(x...)
|
| 88 | #endif
|
| 89 |
|
| 90 | #define SUPERIO "SuperIO"
|
| 91 | #define PFX SUPERIO ": "
|
| 92 |
|
| 93 | static irqreturn_t
|
| 94 | superio_interrupt(int parent_irq, void *devp)
|
| 95 | {
|
| 96 | u8 results;
|
| 97 | u8 local_irq;
|
| 98 |
|
| 99 |
|
| 100 | outb (OCW3_POLL,IC_PIC1+0);
|
| 101 |
|
| 102 | results = inb(IC_PIC1+0);
|
| 103 |
|
| 104 | |
| 105 | * Bit 7: 1 = active Interrupt; 0 = no Interrupt pending
|
| 106 | * Bits 6-3: zero
|
| 107 | * Bits 2-0: highest priority, active requesting interrupt ID (0-7)
|
| 108 |
|
| 109 | if ((results & 0x80) == 0) {
|
| 110 | |
| 111 | * We don't know if an interrupt was/is pending and thus
|
| 112 | * just call the handler for that IRQ as if it were pending.
|
| 113 |
|
| 114 | return IRQ_NONE;
|
| 115 | }
|
| 116 |
|
| 117 |
|
| 118 | local_irq = results & 0x0f;
|
| 119 |
|
| 120 | if (local_irq == 2 || local_irq > 7) {
|
| 121 | printk(KERN_ERR PFX "slave interrupted!\n");
|
| 122 | return IRQ_HANDLED;
|
| 123 | }
|
| 124 |
|
| 125 | if (local_irq == 7) {
|
| 126 |
|
| 127 |
|
| 128 |
|
| 129 | outb(OCW3_ISR,IC_PIC1+0);
|
| 130 | results = inb(IC_PIC1+0);
|
| 131 | if ((results & 0x80) == 0) {
|
| 132 | printk(KERN_WARNING PFX "spurious interrupt!\n");
|
| 133 | return IRQ_HANDLED;
|
| 134 | }
|
| 135 | }
|
| 136 |
|
| 137 |
|
| 138 | generic_handle_irq(local_irq);
|
| 139 |
|
| 140 | |
| 141 | * still needs service.
|
| 142 |
|
| 143 | outb((OCW2_SEOI|local_irq),IC_PIC1 + 0);
|
| 144 | return IRQ_HANDLED;
|
| 145 | }
|
| 146 |
|
| 147 |
|
| 148 | static void
|
| 149 | superio_init(struct pci_dev *pcidev)
|
| 150 | {
|
| 151 | struct superio_device *sio = &sio_dev;
|
| 152 | struct pci_dev *pdev = sio->lio_pdev;
|
| 153 | u16 word;
|
| 154 | int ret;
|
| 155 |
|
| 156 | if (sio->suckyio_irq_enabled)
|
| 157 | return;
|
| 158 |
|
| 159 | BUG_ON(!pdev);
|
| 160 | BUG_ON(!sio->usb_pdev);
|
| 161 |
|
| 162 |
|
| 163 | pdev->irq = sio->usb_pdev->irq;
|
| 164 |
|
| 165 |
|
| 166 | sio->usb_pdev->irq = superio_fixup_irq(sio->usb_pdev);
|
| 167 |
|
| 168 | printk(KERN_INFO PFX "Found NS87560 Legacy I/O device at %s (IRQ %i)\n",
|
| 169 | pci_name(pdev), pdev->irq);
|
| 170 |
|
| 171 | pci_read_config_dword (pdev, SIO_SP1BAR, &sio->sp1_base);
|
| 172 | sio->sp1_base &= ~1;
|
| 173 | printk(KERN_INFO PFX "Serial port 1 at 0x%x\n", sio->sp1_base);
|
| 174 |
|
| 175 | pci_read_config_dword (pdev, SIO_SP2BAR, &sio->sp2_base);
|
| 176 | sio->sp2_base &= ~1;
|
| 177 | printk(KERN_INFO PFX "Serial port 2 at 0x%x\n", sio->sp2_base);
|
| 178 |
|
| 179 | pci_read_config_dword (pdev, SIO_PPBAR, &sio->pp_base);
|
| 180 | sio->pp_base &= ~1;
|
| 181 | printk(KERN_INFO PFX "Parallel port at 0x%x\n", sio->pp_base);
|
| 182 |
|
| 183 | pci_read_config_dword (pdev, SIO_FDCBAR, &sio->fdc_base);
|
| 184 | sio->fdc_base &= ~1;
|
| 185 | printk(KERN_INFO PFX "Floppy controller at 0x%x\n", sio->fdc_base);
|
| 186 | pci_read_config_dword (pdev, SIO_ACPIBAR, &sio->acpi_base);
|
| 187 | sio->acpi_base &= ~1;
|
| 188 | printk(KERN_INFO PFX "ACPI at 0x%x\n", sio->acpi_base);
|
| 189 |
|
| 190 | request_region (IC_PIC1, 0x1f, "pic1");
|
| 191 | request_region (IC_PIC2, 0x1f, "pic2");
|
| 192 | request_region (sio->acpi_base, 0x1f, "acpi");
|
| 193 |
|
| 194 |
|
| 195 | pci_read_config_word (pdev, PCI_COMMAND, &word);
|
| 196 | word |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY | PCI_COMMAND_IO;
|
| 197 | pci_write_config_word (pdev, PCI_COMMAND, word);
|
| 198 |
|
| 199 | pci_set_master (pdev);
|
| 200 | ret = pci_enable_device(pdev);
|
| 201 | BUG_ON(ret < 0);
|
| 202 |
|
| 203 | |
| 204 | * Next project is programming the onboard interrupt controllers.
|
| 205 | * PDC hasn't done this for us, since it's using polled I/O.
|
| 206 | *
|
| 207 | * XXX Use dword writes to avoid bugs in Elroy or Suckyio Config
|
| 208 | * space access. PCI is by nature a 32-bit bus and config
|
| 209 | * space can be sensitive to that.
|
| 210 |
|
| 211 |
|
| 212 | |
| 213 | DMA Rtg 2
|
| 214 | DMA Rtg 3
|
| 215 | DMA Chan Ctl
|
| 216 | TRIGGER_1 == 0x82 USB & IDE level triggered, rest to edge
|
| 217 |
|
| 218 | pci_write_config_dword (pdev, 0x64, 0x82000000U);
|
| 219 |
|
| 220 | |
| 221 | TRIGGER_2 == 0x00 all edge triggered (not used)
|
| 222 | CFG_IR_SER == 0x43 SerPort1 = IRQ3, SerPort2 = IRQ4
|
| 223 | CFG_IR_PF == 0x65 ParPort = IRQ5, FloppyCtlr = IRQ6
|
| 224 | CFG_IR_IDE == 0x07 IDE1 = IRQ7, reserved
|
| 225 |
|
| 226 | pci_write_config_dword (pdev, TRIGGER_2, 0x07654300U);
|
| 227 |
|
| 228 | |
| 229 | CFG_IR_INTAB == 0x00
|
| 230 | CFG_IR_INTCD == 0x10 USB = IRQ1
|
| 231 | CFG_IR_PS2 == 0x00
|
| 232 | CFG_IR_FXBUS == 0x00
|
| 233 |
|
| 234 | pci_write_config_dword (pdev, CFG_IR_INTAB, 0x00001000U);
|
| 235 |
|
| 236 | |
| 237 | CFG_IR_USB == 0x00 not used. USB is connected to INTD.
|
| 238 | CFG_IR_ACPI == 0x00 not used.
|
| 239 | DMA Priority == 0x4c88 Power on default value. NFC.
|
| 240 |
|
| 241 | pci_write_config_dword (pdev, CFG_IR_USB, 0x4c880000U);
|
| 242 |
|
| 243 |
|
| 244 | outb (0x11,IC_PIC1+0);
|
| 245 | outb (0x00,IC_PIC1+1);
|
| 246 | outb (0x04,IC_PIC1+1);
|
| 247 | outb (0x01,IC_PIC1+1);
|
| 248 |
|
| 249 |
|
| 250 | outb (0xff,IC_PIC1+1);
|
| 251 | outb (0xc2,IC_PIC1+0);
|
| 252 |
|
| 253 |
|
| 254 | outb (0x11,IC_PIC2+0);
|
| 255 | outb (0x00,IC_PIC2+1);
|
| 256 | outb (0x02,IC_PIC2+1);
|
| 257 | outb (0x01,IC_PIC2+1);
|
| 258 |
|
| 259 |
|
| 260 | outb (0xff,IC_PIC1+1);
|
| 261 | outb (0x68,IC_PIC1+0);
|
| 262 |
|
| 263 |
|
| 264 | outb (0xff,IC_PIC1+1);
|
| 265 |
|
| 266 |
|
| 267 | outb(1, sio->acpi_base + USB_REG_CR);
|
| 268 | if (inb(sio->acpi_base + USB_REG_CR) & 1)
|
| 269 | printk(KERN_INFO PFX "USB regulator enabled\n");
|
| 270 | else
|
| 271 | printk(KERN_ERR PFX "USB regulator not initialized!\n");
|
| 272 |
|
| 273 | if (request_irq(pdev->irq, superio_interrupt, 0,
|
| 274 | SUPERIO, (void *)sio)) {
|
| 275 |
|
| 276 | printk(KERN_ERR PFX "could not get irq\n");
|
| 277 | BUG();
|
| 278 | return;
|
| 279 | }
|
| 280 |
|
| 281 | sio->suckyio_irq_enabled = 1;
|
| 282 | }
|
| 283 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87560_LIO, superio_init);
|
| 284 |
|
| 285 | static void superio_mask_irq(struct irq_data *d)
|
| 286 | {
|
| 287 | unsigned int irq = d->irq;
|
| 288 | u8 r8;
|
| 289 |
|
| 290 | if ((irq < 1) || (irq == 2) || (irq > 7)) {
|
| 291 | printk(KERN_ERR PFX "Illegal irq number.\n");
|
| 292 | BUG();
|
| 293 | return;
|
| 294 | }
|
| 295 |
|
| 296 |
|
| 297 |
|
| 298 | r8 = inb(IC_PIC1+1);
|
| 299 | r8 |= (1 << irq);
|
| 300 | outb (r8,IC_PIC1+1);
|
| 301 | }
|
| 302 |
|
| 303 | static void superio_unmask_irq(struct irq_data *d)
|
| 304 | {
|
| 305 | unsigned int irq = d->irq;
|
| 306 | u8 r8;
|
| 307 |
|
| 308 | if ((irq < 1) || (irq == 2) || (irq > 7)) {
|
| 309 | printk(KERN_ERR PFX "Illegal irq number (%d).\n", irq);
|
| 310 | BUG();
|
| 311 | return;
|
| 312 | }
|
| 313 |
|
| 314 |
|
| 315 | r8 = inb(IC_PIC1+1);
|
| 316 | r8 &= ~(1 << irq);
|
| 317 | outb (r8,IC_PIC1+1);
|
| 318 | }
|
| 319 |
|
| 320 | static struct irq_chip superio_interrupt_type = {
|
| 321 | .name = SUPERIO,
|
| 322 | .irq_unmask = superio_unmask_irq,
|
| 323 | .irq_mask = superio_mask_irq,
|
| 324 | };
|
| 325 |
|
| 326 | #ifdef DEBUG_SUPERIO_INIT
|
| 327 | static unsigned short expected_device[3] = {
|
| 328 | PCI_DEVICE_ID_NS_87415,
|
| 329 | PCI_DEVICE_ID_NS_87560_LIO,
|
| 330 | PCI_DEVICE_ID_NS_87560_USB
|
| 331 | };
|
| 332 | #endif
|
| 333 |
|
| 334 | int superio_fixup_irq(struct pci_dev *pcidev)
|
| 335 | {
|
| 336 | int local_irq, i;
|
| 337 |
|
| 338 | #ifdef DEBUG_SUPERIO_INIT
|
| 339 | int fn;
|
| 340 | fn = PCI_FUNC(pcidev->devfn);
|
| 341 |
|
| 342 |
|
| 343 | if (expected_device[fn] != pcidev->device) {
|
| 344 | BUG();
|
| 345 | return -1;
|
| 346 | }
|
| 347 | printk(KERN_DEBUG "superio_fixup_irq(%s) ven 0x%x dev 0x%x from %ps\n",
|
| 348 | pci_name(pcidev),
|
| 349 | pcidev->vendor, pcidev->device,
|
| 350 | __builtin_return_address(0));
|
| 351 | #endif
|
| 352 |
|
| 353 | for (i = 0; i < 16; i++) {
|
| 354 | irq_set_chip_and_handler(i, &superio_interrupt_type,
|
| 355 | handle_simple_irq);
|
| 356 | }
|
| 357 |
|
| 358 | |
| 359 | * We don't allocate a SuperIO irq for the legacy IO function,
|
| 360 | * since it is a "bridge". Instead, we will allocate irq's for
|
| 361 | * each legacy device as they are initialized.
|
| 362 |
|
| 363 |
|
| 364 | switch(pcidev->device) {
|
| 365 | case PCI_DEVICE_ID_NS_87415:
|
| 366 | local_irq = IDE_IRQ;
|
| 367 | break;
|
| 368 | case PCI_DEVICE_ID_NS_87560_LIO:
|
| 369 | sio_dev.lio_pdev = pcidev;
|
| 370 | return -1;
|
| 371 | case PCI_DEVICE_ID_NS_87560_USB:
|
| 372 | sio_dev.usb_pdev = pcidev;
|
| 373 | local_irq = USB_IRQ;
|
| 374 | break;
|
| 375 | default:
|
| 376 | local_irq = -1;
|
| 377 | BUG();
|
| 378 | break;
|
| 379 | }
|
| 380 |
|
| 381 | return local_irq;
|
| 382 | }
|
| 383 |
|
| 384 | static void __init superio_serial_init(void)
|
| 385 | {
|
| 386 | #ifdef CONFIG_SERIAL_8250
|
| 387 | int retval;
|
| 388 | struct uart_port serial_port;
|
| 389 |
|
| 390 | memset(&serial_port, 0, sizeof(serial_port));
|
| 391 | serial_port.iotype = UPIO_PORT;
|
| 392 | serial_port.type = PORT_16550A;
|
| 393 | serial_port.uartclk = 115200*16;
|
| 394 | serial_port.flags = UPF_FIXED_PORT | UPF_FIXED_TYPE |
|
| 395 | UPF_BOOT_AUTOCONF;
|
| 396 |
|
| 397 |
|
| 398 | serial_port.iobase = sio_dev.sp1_base;
|
| 399 | serial_port.irq = SP1_IRQ;
|
| 400 | serial_port.line = 0;
|
| 401 | retval = early_serial_setup(&serial_port);
|
| 402 | if (retval < 0) {
|
| 403 | printk(KERN_WARNING PFX "Register Serial #0 failed.\n");
|
| 404 | return;
|
| 405 | }
|
| 406 |
|
| 407 |
|
| 408 | serial_port.iobase = sio_dev.sp2_base;
|
| 409 | serial_port.irq = SP2_IRQ;
|
| 410 | serial_port.line = 1;
|
| 411 | retval = early_serial_setup(&serial_port);
|
| 412 | if (retval < 0)
|
| 413 | printk(KERN_WARNING PFX "Register Serial #1 failed.\n");
|
| 414 | #endif
|
| 415 | }
|
| 416 |
|
| 417 |
|
| 418 | static void __init superio_parport_init(void)
|
| 419 | {
|
| 420 | #ifdef CONFIG_PARPORT_PC
|
| 421 | if (!parport_pc_probe_port(sio_dev.pp_base,
|
| 422 | 0 ,
|
| 423 | PAR_IRQ,
|
| 424 | PARPORT_DMA_NONE ,
|
| 425 | NULL ,
|
| 426 | 0 ))
|
| 427 |
|
| 428 | printk(KERN_WARNING PFX "Probing parallel port failed.\n");
|
| 429 | #endif
|
| 430 | }
|
| 431 |
|
| 432 |
|
| 433 | static void superio_fixup_pci(struct pci_dev *pdev)
|
| 434 | {
|
| 435 | u8 prog;
|
| 436 |
|
| 437 | pdev->class |= 0x5;
|
| 438 | pci_write_config_byte(pdev, PCI_CLASS_PROG, pdev->class);
|
| 439 |
|
| 440 | pci_read_config_byte(pdev, PCI_CLASS_PROG, &prog);
|
| 441 | printk("PCI: Enabled native mode for NS87415 (pif=0x%x)\n", prog);
|
| 442 | }
|
| 443 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87415, superio_fixup_pci);
|
| 444 |
|
| 445 |
|
| 446 | static int __init
|
| 447 | superio_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
| 448 | {
|
| 449 | struct superio_device *sio = &sio_dev;
|
| 450 |
|
| 451 | |
| 452 | ** superio_probe(00:0e.0) ven 0x100b dev 0x2 sv 0x0 sd 0x0 class 0x1018a
|
| 453 | ** superio_probe(00:0e.1) ven 0x100b dev 0xe sv 0x0 sd 0x0 class 0x68000
|
| 454 | ** superio_probe(00:0e.2) ven 0x100b dev 0x12 sv 0x0 sd 0x0 class 0xc0310
|
| 455 |
|
| 456 | DBG_INIT("superio_probe(%s) ven 0x%x dev 0x%x sv 0x%x sd 0x%x class 0x%x\n",
|
| 457 | pci_name(dev),
|
| 458 | dev->vendor, dev->device,
|
| 459 | dev->subsystem_vendor, dev->subsystem_device,
|
| 460 | dev->class);
|
| 461 |
|
| 462 | BUG_ON(!sio->suckyio_irq_enabled);
|
| 463 |
|
| 464 | if (dev->device == PCI_DEVICE_ID_NS_87560_LIO) {
|
| 465 | superio_parport_init();
|
| 466 | superio_serial_init();
|
| 467 |
|
| 468 | return 0;
|
| 469 | } else if (dev->device == PCI_DEVICE_ID_NS_87415) {
|
| 470 | DBG_INIT("superio_probe: ignoring IDE 87415\n");
|
| 471 | } else if (dev->device == PCI_DEVICE_ID_NS_87560_USB) {
|
| 472 | DBG_INIT("superio_probe: ignoring USB OHCI controller\n");
|
| 473 | } else {
|
| 474 | DBG_INIT("superio_probe: WTF? Fire Extinguisher?\n");
|
| 475 | }
|
| 476 |
|
| 477 |
|
| 478 | return -ENODEV;
|
| 479 | }
|
| 480 |
|
| 481 | static const struct pci_device_id superio_tbl[] __initconst = {
|
| 482 | { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87560_LIO) },
|
| 483 | { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87560_USB) },
|
| 484 | { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87415) },
|
| 485 | { 0, }
|
| 486 | };
|
| 487 |
|
| 488 | static struct pci_driver superio_driver __refdata = {
|
| 489 | .name = SUPERIO,
|
| 490 | .id_table = superio_tbl,
|
| 491 | .probe = superio_probe,
|
| 492 | };
|
| 493 |
|
| 494 | module_pci_driver(superio_driver);
|