diff options
Diffstat (limited to 'drivers/parisc/superio.c')
| -rw-r--r-- | drivers/parisc/superio.c | 186 |
1 files changed, 86 insertions, 100 deletions
diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c index bab3bcabcb6..a042d065a0c 100644 --- a/drivers/parisc/superio.c +++ b/drivers/parisc/superio.c @@ -12,6 +12,7 @@ * (C) Copyright 2001 John Marvin <jsm fc hp com> * (C) Copyright 2003 Grant Grundler <grundler parisc-linux org> * (C) Copyright 2005 Kyle McMartin <kyle@parisc-linux.org> + * (C) Copyright 2006 Helge Deller <deller@gmx.de> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -24,6 +25,9 @@ * Major changes to get basic interrupt infrastructure working to * hopefully be able to support all SuperIO devices. Currently * works with serial. -- John Marvin <jsm@fc.hp.com> + * + * Converted superio_init() to be a PCI_FIXUP_FINAL callee. + * -- Kyle McMartin <kyle@parisc-linux.org> */ @@ -69,6 +73,7 @@ #include <linux/termios.h> #include <linux/tty.h> #include <linux/serial_core.h> +#include <linux/serial_8250.h> #include <linux/delay.h> #include <asm/io.h> @@ -86,8 +91,11 @@ static struct superio_device sio_dev; #define DBG_INIT(x...) #endif +#define SUPERIO "SuperIO" +#define PFX SUPERIO ": " + static irqreturn_t -superio_interrupt(int parent_irq, void *devp, struct pt_regs *regs) +superio_interrupt(int parent_irq, void *devp) { u8 results; u8 local_irq; @@ -114,7 +122,7 @@ superio_interrupt(int parent_irq, void *devp, struct pt_regs *regs) local_irq = results & 0x0f; if (local_irq == 2 || local_irq > 7) { - printk(KERN_ERR "SuperIO: slave interrupted!\n"); + printk(KERN_ERR PFX "slave interrupted!\n"); return IRQ_HANDLED; } @@ -125,13 +133,13 @@ superio_interrupt(int parent_irq, void *devp, struct pt_regs *regs) outb(OCW3_ISR,IC_PIC1+0); results = inb(IC_PIC1+0); if ((results & 0x80) == 0) { /* if ISR7 not set: spurious */ - printk(KERN_WARNING "SuperIO: spurious interrupt!\n"); + printk(KERN_WARNING PFX "spurious interrupt!\n"); return IRQ_HANDLED; } } /* Call the appropriate device's interrupt */ - __do_IRQ(local_irq, regs); + generic_handle_irq(local_irq); /* set EOI - forces a new interrupt if a lower priority device * still needs service. @@ -141,18 +149,19 @@ superio_interrupt(int parent_irq, void *devp, struct pt_regs *regs) } /* Initialize Super I/O device */ - -static void __devinit -superio_init(struct superio_device *sio) +static void +superio_init(struct pci_dev *pcidev) { + struct superio_device *sio = &sio_dev; struct pci_dev *pdev = sio->lio_pdev; u16 word; + int ret; - if (sio->suckyio_irq_enabled) + if (sio->suckyio_irq_enabled) return; - if (!pdev) BUG(); - if (!sio->usb_pdev) BUG(); + BUG_ON(!pdev); + BUG_ON(!sio->usb_pdev); /* use the IRQ iosapic found for USB INT D... */ pdev->irq = sio->usb_pdev->irq; @@ -160,39 +169,40 @@ superio_init(struct superio_device *sio) /* ...then properly fixup the USB to point at suckyio PIC */ sio->usb_pdev->irq = superio_fixup_irq(sio->usb_pdev); - printk (KERN_INFO "SuperIO: Found NS87560 Legacy I/O device at %s (IRQ %i) \n", - pci_name(pdev),pdev->irq); + printk(KERN_INFO PFX "Found NS87560 Legacy I/O device at %s (IRQ %i)\n", + pci_name(pdev), pdev->irq); pci_read_config_dword (pdev, SIO_SP1BAR, &sio->sp1_base); sio->sp1_base &= ~1; - printk (KERN_INFO "SuperIO: Serial port 1 at 0x%x\n", sio->sp1_base); + printk(KERN_INFO PFX "Serial port 1 at 0x%x\n", sio->sp1_base); pci_read_config_dword (pdev, SIO_SP2BAR, &sio->sp2_base); sio->sp2_base &= ~1; - printk (KERN_INFO "SuperIO: Serial port 2 at 0x%x\n", sio->sp2_base); + printk(KERN_INFO PFX "Serial port 2 at 0x%x\n", sio->sp2_base); pci_read_config_dword (pdev, SIO_PPBAR, &sio->pp_base); sio->pp_base &= ~1; - printk (KERN_INFO "SuperIO: Parallel port at 0x%x\n", sio->pp_base); + printk(KERN_INFO PFX "Parallel port at 0x%x\n", sio->pp_base); pci_read_config_dword (pdev, SIO_FDCBAR, &sio->fdc_base); sio->fdc_base &= ~1; - printk (KERN_INFO "SuperIO: Floppy controller at 0x%x\n", sio->fdc_base); + printk(KERN_INFO PFX "Floppy controller at 0x%x\n", sio->fdc_base); pci_read_config_dword (pdev, SIO_ACPIBAR, &sio->acpi_base); sio->acpi_base &= ~1; - printk (KERN_INFO "SuperIO: ACPI at 0x%x\n", sio->acpi_base); + printk(KERN_INFO PFX "ACPI at 0x%x\n", sio->acpi_base); request_region (IC_PIC1, 0x1f, "pic1"); request_region (IC_PIC2, 0x1f, "pic2"); request_region (sio->acpi_base, 0x1f, "acpi"); /* Enable the legacy I/O function */ - pci_read_config_word (pdev, PCI_COMMAND, &word); + pci_read_config_word (pdev, PCI_COMMAND, &word); word |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY | PCI_COMMAND_IO; pci_write_config_word (pdev, PCI_COMMAND, word); pci_set_master (pdev); - pci_enable_device(pdev); + ret = pci_enable_device(pdev); + BUG_ON(ret < 0); /* not too much we can do about this... */ /* * Next project is programming the onboard interrupt controllers. @@ -260,28 +270,29 @@ superio_init(struct superio_device *sio) /* Setup USB power regulation */ outb(1, sio->acpi_base + USB_REG_CR); if (inb(sio->acpi_base + USB_REG_CR) & 1) - printk(KERN_INFO "SuperIO: USB regulator enabled\n"); + printk(KERN_INFO PFX "USB regulator enabled\n"); else - printk(KERN_ERR "USB regulator not initialized!\n"); + printk(KERN_ERR PFX "USB regulator not initialized!\n"); - if (request_irq(pdev->irq, superio_interrupt, SA_INTERRUPT, - "SuperIO", (void *)sio)) { + if (request_irq(pdev->irq, superio_interrupt, 0, + SUPERIO, (void *)sio)) { - printk(KERN_ERR "SuperIO: could not get irq\n"); + printk(KERN_ERR PFX "could not get irq\n"); BUG(); return; } sio->suckyio_irq_enabled = 1; } +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87560_LIO, superio_init); - -static void superio_disable_irq(unsigned int irq) +static void superio_mask_irq(struct irq_data *d) { + unsigned int irq = d->irq; u8 r8; if ((irq < 1) || (irq == 2) || (irq > 7)) { - printk(KERN_ERR "SuperIO: Illegal irq number.\n"); + printk(KERN_ERR PFX "Illegal irq number.\n"); BUG(); return; } @@ -293,12 +304,13 @@ static void superio_disable_irq(unsigned int irq) outb (r8,IC_PIC1+1); } -static void superio_enable_irq(unsigned int irq) +static void superio_unmask_irq(struct irq_data *d) { + unsigned int irq = d->irq; u8 r8; if ((irq < 1) || (irq == 2) || (irq > 7)) { - printk(KERN_ERR "SuperIO: Illegal irq number (%d).\n", irq); + printk(KERN_ERR PFX "Illegal irq number (%d).\n", irq); BUG(); return; } @@ -309,20 +321,10 @@ static void superio_enable_irq(unsigned int irq) outb (r8,IC_PIC1+1); } -static unsigned int superio_startup_irq(unsigned int irq) -{ - superio_enable_irq(irq); - return 0; -} - -static struct hw_interrupt_type superio_interrupt_type = { - .typename = "SuperIO", - .startup = superio_startup_irq, - .shutdown = superio_disable_irq, - .enable = superio_enable_irq, - .disable = superio_disable_irq, - .ack = no_ack_irq, - .end = no_end_irq, +static struct irq_chip superio_interrupt_type = { + .name = SUPERIO, + .irq_unmask = superio_unmask_irq, + .irq_mask = superio_mask_irq, }; #ifdef DEBUG_SUPERIO_INIT @@ -346,14 +348,15 @@ int superio_fixup_irq(struct pci_dev *pcidev) BUG(); return -1; } - printk("superio_fixup_irq(%s) ven 0x%x dev 0x%x from %p\n", + printk("superio_fixup_irq(%s) ven 0x%x dev 0x%x from %pf\n", pci_name(pcidev), pcidev->vendor, pcidev->device, __builtin_return_address(0)); #endif for (i = 0; i < 16; i++) { - irq_desc[i].handler = &superio_interrupt_type; + irq_set_chip_and_handler(i, &superio_interrupt_type, + handle_simple_irq); } /* @@ -382,59 +385,50 @@ int superio_fixup_irq(struct pci_dev *pcidev) return local_irq; } -static struct uart_port serial[] = { - { - .iotype = UPIO_PORT, - .line = 0, - .type = PORT_16550A, - .uartclk = 115200*16, - .fifosize = 16, - }, - { - .iotype = UPIO_PORT, - .line = 1, - .type = PORT_16550A, - .uartclk = 115200*16, - .fifosize = 16, - } -}; - -static void __devinit superio_serial_init(void) +static void __init superio_serial_init(void) { #ifdef CONFIG_SERIAL_8250 int retval; - - serial[0].iobase = sio_dev.sp1_base; - serial[0].irq = SP1_IRQ; - spin_lock_init(&serial[0].lock); - - retval = early_serial_setup(&serial[0]); + struct uart_port serial_port; + + memset(&serial_port, 0, sizeof(serial_port)); + serial_port.iotype = UPIO_PORT; + serial_port.type = PORT_16550A; + serial_port.uartclk = 115200*16; + serial_port.fifosize = 16; + + /* serial port #1 */ + serial_port.iobase = sio_dev.sp1_base; + serial_port.irq = SP1_IRQ; + serial_port.line = 0; + retval = early_serial_setup(&serial_port); if (retval < 0) { - printk(KERN_WARNING "SuperIO: Register Serial #0 failed.\n"); + printk(KERN_WARNING PFX "Register Serial #0 failed.\n"); return; } - serial[1].iobase = sio_dev.sp2_base; - serial[1].irq = SP2_IRQ; - spin_lock_init(&serial[1].lock); - retval = early_serial_setup(&serial[1]); - + /* serial port #2 */ + serial_port.iobase = sio_dev.sp2_base; + serial_port.irq = SP2_IRQ; + serial_port.line = 1; + retval = early_serial_setup(&serial_port); if (retval < 0) - printk(KERN_WARNING "SuperIO: Register Serial #1 failed.\n"); + printk(KERN_WARNING PFX "Register Serial #1 failed.\n"); #endif /* CONFIG_SERIAL_8250 */ } -static void __devinit superio_parport_init(void) +static void __init superio_parport_init(void) { #ifdef CONFIG_PARPORT_PC if (!parport_pc_probe_port(sio_dev.pp_base, 0 /*base_hi*/, PAR_IRQ, PARPORT_DMA_NONE /* dma */, - NULL /*struct pci_dev* */) ) + NULL /*struct pci_dev* */, + 0 /* shared irq flags */)) - printk(KERN_WARNING "SuperIO: Probing parallel port failed.\n"); + printk(KERN_WARNING PFX "Probing parallel port failed.\n"); #endif /* CONFIG_PARPORT_PC */ } @@ -452,8 +446,10 @@ static void superio_fixup_pci(struct pci_dev *pdev) DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87415, superio_fixup_pci); -static int __devinit superio_probe(struct pci_dev *dev, const struct pci_device_id *id) +static int __init +superio_probe(struct pci_dev *dev, const struct pci_device_id *id) { + struct superio_device *sio = &sio_dev; /* ** superio_probe(00:0e.0) ven 0x100b dev 0x2 sv 0x0 sd 0x0 class 0x1018a @@ -466,7 +462,7 @@ static int __devinit superio_probe(struct pci_dev *dev, const struct pci_device_ dev->subsystem_vendor, dev->subsystem_device, dev->class); - superio_init(&sio_dev); + BUG_ON(!sio->suckyio_irq_enabled); /* Enabled by PCI_FIXUP_FINAL */ if (dev->device == PCI_DEVICE_ID_NS_87560_LIO) { /* Function 1 */ superio_parport_init(); @@ -481,31 +477,21 @@ static int __devinit superio_probe(struct pci_dev *dev, const struct pci_device_ DBG_INIT("superio_probe: WTF? Fire Extinguisher?\n"); } - /* Let appropriate other driver claim this device. */ + /* Let appropriate other driver claim this device. */ return -ENODEV; } -static struct pci_device_id superio_tbl[] = { - { PCI_VENDOR_ID_NS, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, +static const struct pci_device_id superio_tbl[] = { + { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87560_LIO) }, + { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87560_USB) }, + { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87415) }, { 0, } }; static struct pci_driver superio_driver = { - .name = "SuperIO", - .id_table = superio_tbl, - .probe = superio_probe, + .name = SUPERIO, + .id_table = superio_tbl, + .probe = superio_probe, }; -static int __init superio_modinit(void) -{ - return pci_register_driver(&superio_driver); -} - -static void __exit superio_exit(void) -{ - pci_unregister_driver(&superio_driver); -} - - -module_init(superio_modinit); -module_exit(superio_exit); +module_pci_driver(superio_driver); |
