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