11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* National Semiconductor NS87560UBD Super I/O controller used in 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * HP [BCJ]x000 workstations. 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This chip is a horrid piece of engineering, and National 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * denies any knowledge of its existence. Thus no datasheet is 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * available off www.national.com. 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (C) Copyright 2000 Linuxcare, Inc. 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (C) Copyright 2000 Linuxcare Canada, Inc. 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (C) Copyright 2000 Martin K. Petersen <mkp@linuxcare.com> 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (C) Copyright 2000 Alex deVries <alex@onefishtwo.ca> 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (C) Copyright 2001 John Marvin <jsm fc hp com> 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (C) Copyright 2003 Grant Grundler <grundler parisc-linux org> 147efe1611b2db9025ffc52a686897ab91820caeb4Kyle McMartin * (C) Copyright 2005 Kyle McMartin <kyle@parisc-linux.org> 155076c15862644edb91d2e3436b2fa3e07b28385dHelge Deller * (C) Copyright 2006 Helge Deller <deller@gmx.de> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * modify it under the terms of the GNU General Public License as 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * published by the Free Software Foundation; either version 2 of 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the License, or (at your option) any later version. 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The initial version of this is by Martin Peterson. Alex deVries 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * has spent a bit of time trying to coax it into working. 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Major changes to get basic interrupt infrastructure working to 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * hopefully be able to support all SuperIO devices. Currently 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * works with serial. -- John Marvin <jsm@fc.hp.com> 28a39cf72ceb406e152c4682c0b635a96f1439c5edKyle McMartin * 29a39cf72ceb406e152c4682c0b635a96f1439c5edKyle McMartin * Converted superio_init() to be a PCI_FIXUP_FINAL callee. 30a39cf72ceb406e152c4682c0b635a96f1439c5edKyle McMartin * -- Kyle McMartin <kyle@parisc-linux.org> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* NOTES: 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 0 is an IDE controller. It is identical to a PC87415 IDE 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * controller (and identifies itself as such). 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 1 is a "Legacy I/O" controller. Under this function is a 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * whole mess of legacy I/O peripherals. Of course, HP hasn't enabled 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * all the functionality in hardware, but the following is available: 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Two 16550A compatible serial controllers 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * An IEEE 1284 compatible parallel port 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * A floppy disk controller 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function 2 is a USB controller. 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We must be incredibly careful during initialization. Since all 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * interrupts are routed through function 1 (which is not allowed by 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the PCI spec), we need to program the PICs on the legacy I/O port 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * *before* we attempt to set up IDE and USB. @#$!& 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * According to HP, devices are only enabled by firmware if they have 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * a physical device connected. 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Configuration register bits: 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0x5A: FDC, SP1, IDE1, SP2, IDE2, PAR, Reserved, P92 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0x5B: RTC, 8259, 8254, DMA1, DMA2, KBC, P61, APM 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h> 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h> 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h> 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/serial.h> 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h> 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/parport.h> 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/parport_pc.h> 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/termios.h> 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/tty.h> 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/serial_core.h> 76b187f180cc942e50007aa039f8e3a620ee5f3171Yinghai Lu#include <linux/serial_8250.h> 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h> 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h> 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/hardware.h> 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/superio.h> 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct superio_device sio_dev; 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef DEBUG_SUPERIO_INIT 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG_SUPERIO_INIT 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DBG_INIT(x...) printk(x) 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DBG_INIT(x...) 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9416541c8745e28f62b3dcb6cb354b73c9c01ea178Kyle McMartin#define SUPERIO "SuperIO" 9516541c8745e28f62b3dcb6cb354b73c9c01ea178Kyle McMartin#define PFX SUPERIO ": " 9616541c8745e28f62b3dcb6cb354b73c9c01ea178Kyle McMartin 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic irqreturn_t 987d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellssuperio_interrupt(int parent_irq, void *devp) 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 results; 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 local_irq; 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Poll the 8259 to see if there's an interrupt. */ 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb (OCW3_POLL,IC_PIC1+0); 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds results = inb(IC_PIC1+0); 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Bit 7: 1 = active Interrupt; 0 = no Interrupt pending 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Bits 6-3: zero 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Bits 2-0: highest priority, active requesting interrupt ID (0-7) 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((results & 0x80) == 0) { 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* I suspect "spurious" interrupts are from unmasking an IRQ. 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We don't know if an interrupt was/is pending and thus 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * just call the handler for that IRQ as if it were pending. 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return IRQ_NONE; 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check to see which device is interrupting */ 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds local_irq = results & 0x0f; 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (local_irq == 2 || local_irq > 7) { 12516541c8745e28f62b3dcb6cb354b73c9c01ea178Kyle McMartin printk(KERN_ERR PFX "slave interrupted!\n"); 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return IRQ_HANDLED; 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (local_irq == 7) { 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Could be spurious. Check in service bits */ 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(OCW3_ISR,IC_PIC1+0); 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds results = inb(IC_PIC1+0); 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((results & 0x80) == 0) { /* if ISR7 not set: spurious */ 13616541c8745e28f62b3dcb6cb354b73c9c01ea178Kyle McMartin printk(KERN_WARNING PFX "spurious interrupt!\n"); 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return IRQ_HANDLED; 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Call the appropriate device's interrupt */ 142ba20085c20f1c9e8af546dea6ad0efa421bdef32Kyle McMartin generic_handle_irq(local_irq); 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set EOI - forces a new interrupt if a lower priority device 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * still needs service. 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb((OCW2_SEOI|local_irq),IC_PIC1 + 0); 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return IRQ_HANDLED; 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Initialize Super I/O device */ 152a39cf72ceb406e152c4682c0b635a96f1439c5edKyle McMartinstatic void 153a39cf72ceb406e152c4682c0b635a96f1439c5edKyle McMartinsuperio_init(struct pci_dev *pcidev) 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 155a39cf72ceb406e152c4682c0b635a96f1439c5edKyle McMartin struct superio_device *sio = &sio_dev; 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pci_dev *pdev = sio->lio_pdev; 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 word; 15819c4d5664aaf9419dfe6b24990a93305fded6403Kyle McMartin int ret; 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16067a5a59d3301949f51f2d617d689f005c6d21470Helge Deller if (sio->suckyio_irq_enabled) 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 163b74945547f0679003ede4d1afcd0aa169059a436Eric Sesterhenn BUG_ON(!pdev); 164b74945547f0679003ede4d1afcd0aa169059a436Eric Sesterhenn BUG_ON(!sio->usb_pdev); 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* use the IRQ iosapic found for USB INT D... */ 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pdev->irq = sio->usb_pdev->irq; 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ...then properly fixup the USB to point at suckyio PIC */ 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sio->usb_pdev->irq = superio_fixup_irq(sio->usb_pdev); 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 172a3bee03e718c9251456676b71a723a34c999e891Frans Pop printk(KERN_INFO PFX "Found NS87560 Legacy I/O device at %s (IRQ %i)\n", 173a39cf72ceb406e152c4682c0b635a96f1439c5edKyle McMartin pci_name(pdev), pdev->irq); 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_read_config_dword (pdev, SIO_SP1BAR, &sio->sp1_base); 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sio->sp1_base &= ~1; 17716541c8745e28f62b3dcb6cb354b73c9c01ea178Kyle McMartin printk(KERN_INFO PFX "Serial port 1 at 0x%x\n", sio->sp1_base); 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_read_config_dword (pdev, SIO_SP2BAR, &sio->sp2_base); 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sio->sp2_base &= ~1; 18116541c8745e28f62b3dcb6cb354b73c9c01ea178Kyle McMartin printk(KERN_INFO PFX "Serial port 2 at 0x%x\n", sio->sp2_base); 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_read_config_dword (pdev, SIO_PPBAR, &sio->pp_base); 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sio->pp_base &= ~1; 18516541c8745e28f62b3dcb6cb354b73c9c01ea178Kyle McMartin printk(KERN_INFO PFX "Parallel port at 0x%x\n", sio->pp_base); 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_read_config_dword (pdev, SIO_FDCBAR, &sio->fdc_base); 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sio->fdc_base &= ~1; 18916541c8745e28f62b3dcb6cb354b73c9c01ea178Kyle McMartin printk(KERN_INFO PFX "Floppy controller at 0x%x\n", sio->fdc_base); 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_read_config_dword (pdev, SIO_ACPIBAR, &sio->acpi_base); 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sio->acpi_base &= ~1; 19216541c8745e28f62b3dcb6cb354b73c9c01ea178Kyle McMartin printk(KERN_INFO PFX "ACPI at 0x%x\n", sio->acpi_base); 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds request_region (IC_PIC1, 0x1f, "pic1"); 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds request_region (IC_PIC2, 0x1f, "pic2"); 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds request_region (sio->acpi_base, 0x1f, "acpi"); 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Enable the legacy I/O function */ 19967a5a59d3301949f51f2d617d689f005c6d21470Helge Deller pci_read_config_word (pdev, PCI_COMMAND, &word); 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds word |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY | PCI_COMMAND_IO; 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_write_config_word (pdev, PCI_COMMAND, word); 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_set_master (pdev); 20419c4d5664aaf9419dfe6b24990a93305fded6403Kyle McMartin ret = pci_enable_device(pdev); 20519c4d5664aaf9419dfe6b24990a93305fded6403Kyle McMartin BUG_ON(ret < 0); /* not too much we can do about this... */ 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Next project is programming the onboard interrupt controllers. 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * PDC hasn't done this for us, since it's using polled I/O. 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * XXX Use dword writes to avoid bugs in Elroy or Suckyio Config 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * space access. PCI is by nature a 32-bit bus and config 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * space can be sensitive to that. 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 0x64 - 0x67 : 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DMA Rtg 2 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DMA Rtg 3 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DMA Chan Ctl 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds TRIGGER_1 == 0x82 USB & IDE level triggered, rest to edge 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_write_config_dword (pdev, 0x64, 0x82000000U); 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 0x68 - 0x6b : 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds TRIGGER_2 == 0x00 all edge triggered (not used) 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CFG_IR_SER == 0x43 SerPort1 = IRQ3, SerPort2 = IRQ4 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CFG_IR_PF == 0x65 ParPort = IRQ5, FloppyCtlr = IRQ6 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CFG_IR_IDE == 0x07 IDE1 = IRQ7, reserved 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_write_config_dword (pdev, TRIGGER_2, 0x07654300U); 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 0x6c - 0x6f : 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CFG_IR_INTAB == 0x00 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CFG_IR_INTCD == 0x10 USB = IRQ1 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CFG_IR_PS2 == 0x00 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CFG_IR_FXBUS == 0x00 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_write_config_dword (pdev, CFG_IR_INTAB, 0x00001000U); 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 0x70 - 0x73 : 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CFG_IR_USB == 0x00 not used. USB is connected to INTD. 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CFG_IR_ACPI == 0x00 not used. 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DMA Priority == 0x4c88 Power on default value. NFC. 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_write_config_dword (pdev, CFG_IR_USB, 0x4c880000U); 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* PIC1 Initialization Command Word register programming */ 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb (0x11,IC_PIC1+0); /* ICW1: ICW4 write req | ICW1 */ 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb (0x00,IC_PIC1+1); /* ICW2: interrupt vector table - not used */ 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb (0x04,IC_PIC1+1); /* ICW3: Cascade */ 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb (0x01,IC_PIC1+1); /* ICW4: x86 mode */ 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* PIC1 Program Operational Control Words */ 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb (0xff,IC_PIC1+1); /* OCW1: Mask all interrupts */ 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb (0xc2,IC_PIC1+0); /* OCW2: priority (3-7,0-2) */ 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* PIC2 Initialization Command Word register programming */ 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb (0x11,IC_PIC2+0); /* ICW1: ICW4 write req | ICW1 */ 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb (0x00,IC_PIC2+1); /* ICW2: N/A */ 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb (0x02,IC_PIC2+1); /* ICW3: Slave ID code */ 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb (0x01,IC_PIC2+1); /* ICW4: x86 mode */ 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Program Operational Control Words */ 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb (0xff,IC_PIC1+1); /* OCW1: Mask all interrupts */ 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb (0x68,IC_PIC1+0); /* OCW3: OCW3 select | ESMM | SMM */ 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Write master mask reg */ 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb (0xff,IC_PIC1+1); 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Setup USB power regulation */ 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(1, sio->acpi_base + USB_REG_CR); 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (inb(sio->acpi_base + USB_REG_CR) & 1) 27316541c8745e28f62b3dcb6cb354b73c9c01ea178Kyle McMartin printk(KERN_INFO PFX "USB regulator enabled\n"); 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 27516541c8745e28f62b3dcb6cb354b73c9c01ea178Kyle McMartin printk(KERN_ERR PFX "USB regulator not initialized!\n"); 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2778c56e7214effd2fa50359e58832ad9c3eb51a3deThomas Gleixner if (request_irq(pdev->irq, superio_interrupt, IRQF_DISABLED, 27816541c8745e28f62b3dcb6cb354b73c9c01ea178Kyle McMartin SUPERIO, (void *)sio)) { 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28016541c8745e28f62b3dcb6cb354b73c9c01ea178Kyle McMartin printk(KERN_ERR PFX "could not get irq\n"); 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BUG(); 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sio->suckyio_irq_enabled = 1; 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 287a39cf72ceb406e152c4682c0b635a96f1439c5edKyle McMartinDECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87560_LIO, superio_init); 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2894c4231ea2f794d73bbb50b8d84e00c66a012a607Thomas Gleixnerstatic void superio_mask_irq(struct irq_data *d) 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2914c4231ea2f794d73bbb50b8d84e00c66a012a607Thomas Gleixner unsigned int irq = d->irq; 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 r8; 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((irq < 1) || (irq == 2) || (irq > 7)) { 29516541c8745e28f62b3dcb6cb354b73c9c01ea178Kyle McMartin printk(KERN_ERR PFX "Illegal irq number.\n"); 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BUG(); 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Mask interrupt */ 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r8 = inb(IC_PIC1+1); 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r8 |= (1 << irq); 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb (r8,IC_PIC1+1); 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3074c4231ea2f794d73bbb50b8d84e00c66a012a607Thomas Gleixnerstatic void superio_unmask_irq(struct irq_data *d) 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3094c4231ea2f794d73bbb50b8d84e00c66a012a607Thomas Gleixner unsigned int irq = d->irq; 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 r8; 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((irq < 1) || (irq == 2) || (irq > 7)) { 31316541c8745e28f62b3dcb6cb354b73c9c01ea178Kyle McMartin printk(KERN_ERR PFX "Illegal irq number (%d).\n", irq); 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BUG(); 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Unmask interrupt */ 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r8 = inb(IC_PIC1+1); 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r8 &= ~(1 << irq); 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb (r8,IC_PIC1+1); 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 324dfe07565021959f0f646e9e775810c1bfbe0f6d6Thomas Gleixnerstatic struct irq_chip superio_interrupt_type = { 3254c4231ea2f794d73bbb50b8d84e00c66a012a607Thomas Gleixner .name = SUPERIO, 3264c4231ea2f794d73bbb50b8d84e00c66a012a607Thomas Gleixner .irq_unmask = superio_unmask_irq, 3274c4231ea2f794d73bbb50b8d84e00c66a012a607Thomas Gleixner .irq_mask = superio_mask_irq, 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG_SUPERIO_INIT 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned short expected_device[3] = { 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PCI_DEVICE_ID_NS_87415, 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PCI_DEVICE_ID_NS_87560_LIO, 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PCI_DEVICE_ID_NS_87560_USB 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint superio_fixup_irq(struct pci_dev *pcidev) 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int local_irq, i; 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG_SUPERIO_INIT 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int fn; 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fn = PCI_FUNC(pcidev->devfn); 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Verify the function number matches the expected device id. */ 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (expected_device[fn] != pcidev->device) { 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BUG(); 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -1; 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("superio_fixup_irq(%s) ven 0x%x dev 0x%x from %p\n", 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_name(pcidev), 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcidev->vendor, pcidev->device, 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __builtin_return_address(0)); 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 16; i++) { 358e2f571d294cc5f944539088bed46abae375b75f6Thomas Gleixner irq_set_chip_and_handler(i, &superio_interrupt_type, 359e2f571d294cc5f944539088bed46abae375b75f6Thomas Gleixner handle_simple_irq); 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We don't allocate a SuperIO irq for the legacy IO function, 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * since it is a "bridge". Instead, we will allocate irq's for 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * each legacy device as they are initialized. 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch(pcidev->device) { 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PCI_DEVICE_ID_NS_87415: /* Function 0 */ 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds local_irq = IDE_IRQ; 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PCI_DEVICE_ID_NS_87560_LIO: /* Function 1 */ 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sio_dev.lio_pdev = pcidev; /* save for superio_init() */ 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -1; 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PCI_DEVICE_ID_NS_87560_USB: /* Function 2 */ 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sio_dev.usb_pdev = pcidev; /* save for superio_init() */ 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds local_irq = USB_IRQ; 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds local_irq = -1; 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BUG(); 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return local_irq; 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3888c678b101a08a6543e62ab60aace93042456aa9dHelge Dellerstatic void __init superio_serial_init(void) 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SERIAL_8250 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval; 3925076c15862644edb91d2e3436b2fa3e07b28385dHelge Deller struct uart_port serial_port; 3935076c15862644edb91d2e3436b2fa3e07b28385dHelge Deller 3945076c15862644edb91d2e3436b2fa3e07b28385dHelge Deller memset(&serial_port, 0, sizeof(serial_port)); 3955076c15862644edb91d2e3436b2fa3e07b28385dHelge Deller serial_port.iotype = UPIO_PORT; 3965076c15862644edb91d2e3436b2fa3e07b28385dHelge Deller serial_port.type = PORT_16550A; 3975076c15862644edb91d2e3436b2fa3e07b28385dHelge Deller serial_port.uartclk = 115200*16; 3985076c15862644edb91d2e3436b2fa3e07b28385dHelge Deller serial_port.fifosize = 16; 3995076c15862644edb91d2e3436b2fa3e07b28385dHelge Deller 4005076c15862644edb91d2e3436b2fa3e07b28385dHelge Deller /* serial port #1 */ 4015076c15862644edb91d2e3436b2fa3e07b28385dHelge Deller serial_port.iobase = sio_dev.sp1_base; 4025076c15862644edb91d2e3436b2fa3e07b28385dHelge Deller serial_port.irq = SP1_IRQ; 4035076c15862644edb91d2e3436b2fa3e07b28385dHelge Deller serial_port.line = 0; 4045076c15862644edb91d2e3436b2fa3e07b28385dHelge Deller retval = early_serial_setup(&serial_port); 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) { 40616541c8745e28f62b3dcb6cb354b73c9c01ea178Kyle McMartin printk(KERN_WARNING PFX "Register Serial #0 failed.\n"); 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4105076c15862644edb91d2e3436b2fa3e07b28385dHelge Deller /* serial port #2 */ 4115076c15862644edb91d2e3436b2fa3e07b28385dHelge Deller serial_port.iobase = sio_dev.sp2_base; 4125076c15862644edb91d2e3436b2fa3e07b28385dHelge Deller serial_port.irq = SP2_IRQ; 4135076c15862644edb91d2e3436b2fa3e07b28385dHelge Deller serial_port.line = 1; 4145076c15862644edb91d2e3436b2fa3e07b28385dHelge Deller retval = early_serial_setup(&serial_port); 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) 41616541c8745e28f62b3dcb6cb354b73c9c01ea178Kyle McMartin printk(KERN_WARNING PFX "Register Serial #1 failed.\n"); 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* CONFIG_SERIAL_8250 */ 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4218c678b101a08a6543e62ab60aace93042456aa9dHelge Dellerstatic void __init superio_parport_init(void) 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PARPORT_PC 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!parport_pc_probe_port(sio_dev.pp_base, 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0 /*base_hi*/, 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PAR_IRQ, 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PARPORT_DMA_NONE /* dma */, 4280c5cb79198d80eaea273f3e91cb418d559f13462Alexander Beregalov NULL /*struct pci_dev* */, 4290c5cb79198d80eaea273f3e91cb418d559f13462Alexander Beregalov 0 /* shared irq flags */)) 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 43116541c8745e28f62b3dcb6cb354b73c9c01ea178Kyle McMartin printk(KERN_WARNING PFX "Probing parallel port failed.\n"); 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* CONFIG_PARPORT_PC */ 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void superio_fixup_pci(struct pci_dev *pdev) 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 prog; 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pdev->class |= 0x5; 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_write_config_byte(pdev, PCI_CLASS_PROG, pdev->class); 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_read_config_byte(pdev, PCI_CLASS_PROG, &prog); 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("PCI: Enabled native mode for NS87415 (pif=0x%x)\n", prog); 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsDECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87415, superio_fixup_pci); 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4498c678b101a08a6543e62ab60aace93042456aa9dHelge Dellerstatic int __init 450a39cf72ceb406e152c4682c0b635a96f1439c5edKyle McMartinsuperio_probe(struct pci_dev *dev, const struct pci_device_id *id) 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 452a39cf72ceb406e152c4682c0b635a96f1439c5edKyle McMartin struct superio_device *sio = &sio_dev; 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ** superio_probe(00:0e.0) ven 0x100b dev 0x2 sv 0x0 sd 0x0 class 0x1018a 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ** superio_probe(00:0e.1) ven 0x100b dev 0xe sv 0x0 sd 0x0 class 0x68000 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ** superio_probe(00:0e.2) ven 0x100b dev 0x12 sv 0x0 sd 0x0 class 0xc0310 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DBG_INIT("superio_probe(%s) ven 0x%x dev 0x%x sv 0x%x sd 0x%x class 0x%x\n", 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_name(dev), 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->vendor, dev->device, 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->subsystem_vendor, dev->subsystem_device, 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->class); 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 465b74945547f0679003ede4d1afcd0aa169059a436Eric Sesterhenn BUG_ON(!sio->suckyio_irq_enabled); /* Enabled by PCI_FIXUP_FINAL */ 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->device == PCI_DEVICE_ID_NS_87560_LIO) { /* Function 1 */ 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds superio_parport_init(); 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds superio_serial_init(); 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* REVISIT XXX : superio_fdc_init() ? */ 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (dev->device == PCI_DEVICE_ID_NS_87415) { /* Function 0 */ 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DBG_INIT("superio_probe: ignoring IDE 87415\n"); 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (dev->device == PCI_DEVICE_ID_NS_87560_USB) { /* Function 2 */ 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DBG_INIT("superio_probe: ignoring USB OHCI controller\n"); 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DBG_INIT("superio_probe: WTF? Fire Extinguisher?\n"); 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 480a39cf72ceb406e152c4682c0b635a96f1439c5edKyle McMartin /* Let appropriate other driver claim this device. */ 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4848c678b101a08a6543e62ab60aace93042456aa9dHelge Dellerstatic const struct pci_device_id superio_tbl[] = { 485a39cf72ceb406e152c4682c0b635a96f1439c5edKyle McMartin { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87560_LIO) }, 486a39cf72ceb406e152c4682c0b635a96f1439c5edKyle McMartin { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87560_USB) }, 487a39cf72ceb406e152c4682c0b635a96f1439c5edKyle McMartin { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87415) }, 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 0, } 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pci_driver superio_driver = { 49216541c8745e28f62b3dcb6cb354b73c9c01ea178Kyle McMartin .name = SUPERIO, 493a39cf72ceb406e152c4682c0b635a96f1439c5edKyle McMartin .id_table = superio_tbl, 494a39cf72ceb406e152c4682c0b635a96f1439c5edKyle McMartin .probe = superio_probe, 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init superio_modinit(void) 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return pci_register_driver(&superio_driver); 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit superio_exit(void) 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_unregister_driver(&superio_driver); 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(superio_modinit); 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(superio_exit); 509