0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059 #include <linux/errno.h>
0060 #include <linux/init.h>
0061 #include <linux/module.h>
0062 #include <linux/types.h>
0063 #include <linux/interrupt.h>
0064 #include <linux/ioport.h>
0065 #include <linux/serial.h>
0066 #include <linux/pci.h>
0067 #include <linux/parport.h>
0068 #include <linux/parport_pc.h>
0069 #include <linux/termios.h>
0070 #include <linux/tty.h>
0071 #include <linux/serial_core.h>
0072 #include <linux/serial_8250.h>
0073 #include <linux/delay.h>
0074
0075 #include <asm/io.h>
0076 #include <asm/hardware.h>
0077 #include <asm/superio.h>
0078
0079 static struct superio_device sio_dev;
0080
0081
0082 #undef DEBUG_SUPERIO_INIT
0083
0084 #ifdef DEBUG_SUPERIO_INIT
0085 #define DBG_INIT(x...) printk(x)
0086 #else
0087 #define DBG_INIT(x...)
0088 #endif
0089
0090 #define SUPERIO "SuperIO"
0091 #define PFX SUPERIO ": "
0092
0093 static irqreturn_t
0094 superio_interrupt(int parent_irq, void *devp)
0095 {
0096 u8 results;
0097 u8 local_irq;
0098
0099
0100 outb (OCW3_POLL,IC_PIC1+0);
0101
0102 results = inb(IC_PIC1+0);
0103
0104
0105
0106
0107
0108
0109 if ((results & 0x80) == 0) {
0110
0111
0112
0113
0114 return IRQ_NONE;
0115 }
0116
0117
0118 local_irq = results & 0x0f;
0119
0120 if (local_irq == 2 || local_irq > 7) {
0121 printk(KERN_ERR PFX "slave interrupted!\n");
0122 return IRQ_HANDLED;
0123 }
0124
0125 if (local_irq == 7) {
0126
0127
0128
0129 outb(OCW3_ISR,IC_PIC1+0);
0130 results = inb(IC_PIC1+0);
0131 if ((results & 0x80) == 0) {
0132 printk(KERN_WARNING PFX "spurious interrupt!\n");
0133 return IRQ_HANDLED;
0134 }
0135 }
0136
0137
0138 generic_handle_irq(local_irq);
0139
0140
0141
0142
0143 outb((OCW2_SEOI|local_irq),IC_PIC1 + 0);
0144 return IRQ_HANDLED;
0145 }
0146
0147
0148 static void
0149 superio_init(struct pci_dev *pcidev)
0150 {
0151 struct superio_device *sio = &sio_dev;
0152 struct pci_dev *pdev = sio->lio_pdev;
0153 u16 word;
0154 int ret;
0155
0156 if (sio->suckyio_irq_enabled)
0157 return;
0158
0159 BUG_ON(!pdev);
0160 BUG_ON(!sio->usb_pdev);
0161
0162
0163 pdev->irq = sio->usb_pdev->irq;
0164
0165
0166 sio->usb_pdev->irq = superio_fixup_irq(sio->usb_pdev);
0167
0168 printk(KERN_INFO PFX "Found NS87560 Legacy I/O device at %s (IRQ %i)\n",
0169 pci_name(pdev), pdev->irq);
0170
0171 pci_read_config_dword (pdev, SIO_SP1BAR, &sio->sp1_base);
0172 sio->sp1_base &= ~1;
0173 printk(KERN_INFO PFX "Serial port 1 at 0x%x\n", sio->sp1_base);
0174
0175 pci_read_config_dword (pdev, SIO_SP2BAR, &sio->sp2_base);
0176 sio->sp2_base &= ~1;
0177 printk(KERN_INFO PFX "Serial port 2 at 0x%x\n", sio->sp2_base);
0178
0179 pci_read_config_dword (pdev, SIO_PPBAR, &sio->pp_base);
0180 sio->pp_base &= ~1;
0181 printk(KERN_INFO PFX "Parallel port at 0x%x\n", sio->pp_base);
0182
0183 pci_read_config_dword (pdev, SIO_FDCBAR, &sio->fdc_base);
0184 sio->fdc_base &= ~1;
0185 printk(KERN_INFO PFX "Floppy controller at 0x%x\n", sio->fdc_base);
0186 pci_read_config_dword (pdev, SIO_ACPIBAR, &sio->acpi_base);
0187 sio->acpi_base &= ~1;
0188 printk(KERN_INFO PFX "ACPI at 0x%x\n", sio->acpi_base);
0189
0190 request_region (IC_PIC1, 0x1f, "pic1");
0191 request_region (IC_PIC2, 0x1f, "pic2");
0192 request_region (sio->acpi_base, 0x1f, "acpi");
0193
0194
0195 pci_read_config_word (pdev, PCI_COMMAND, &word);
0196 word |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY | PCI_COMMAND_IO;
0197 pci_write_config_word (pdev, PCI_COMMAND, word);
0198
0199 pci_set_master (pdev);
0200 ret = pci_enable_device(pdev);
0201 BUG_ON(ret < 0);
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218 pci_write_config_dword (pdev, 0x64, 0x82000000U);
0219
0220
0221
0222
0223
0224
0225
0226 pci_write_config_dword (pdev, TRIGGER_2, 0x07654300U);
0227
0228
0229
0230
0231
0232
0233
0234 pci_write_config_dword (pdev, CFG_IR_INTAB, 0x00001000U);
0235
0236
0237
0238
0239
0240
0241 pci_write_config_dword (pdev, CFG_IR_USB, 0x4c880000U);
0242
0243
0244 outb (0x11,IC_PIC1+0);
0245 outb (0x00,IC_PIC1+1);
0246 outb (0x04,IC_PIC1+1);
0247 outb (0x01,IC_PIC1+1);
0248
0249
0250 outb (0xff,IC_PIC1+1);
0251 outb (0xc2,IC_PIC1+0);
0252
0253
0254 outb (0x11,IC_PIC2+0);
0255 outb (0x00,IC_PIC2+1);
0256 outb (0x02,IC_PIC2+1);
0257 outb (0x01,IC_PIC2+1);
0258
0259
0260 outb (0xff,IC_PIC1+1);
0261 outb (0x68,IC_PIC1+0);
0262
0263
0264 outb (0xff,IC_PIC1+1);
0265
0266
0267 outb(1, sio->acpi_base + USB_REG_CR);
0268 if (inb(sio->acpi_base + USB_REG_CR) & 1)
0269 printk(KERN_INFO PFX "USB regulator enabled\n");
0270 else
0271 printk(KERN_ERR PFX "USB regulator not initialized!\n");
0272
0273 if (request_irq(pdev->irq, superio_interrupt, 0,
0274 SUPERIO, (void *)sio)) {
0275
0276 printk(KERN_ERR PFX "could not get irq\n");
0277 BUG();
0278 return;
0279 }
0280
0281 sio->suckyio_irq_enabled = 1;
0282 }
0283 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87560_LIO, superio_init);
0284
0285 static void superio_mask_irq(struct irq_data *d)
0286 {
0287 unsigned int irq = d->irq;
0288 u8 r8;
0289
0290 if ((irq < 1) || (irq == 2) || (irq > 7)) {
0291 printk(KERN_ERR PFX "Illegal irq number.\n");
0292 BUG();
0293 return;
0294 }
0295
0296
0297
0298 r8 = inb(IC_PIC1+1);
0299 r8 |= (1 << irq);
0300 outb (r8,IC_PIC1+1);
0301 }
0302
0303 static void superio_unmask_irq(struct irq_data *d)
0304 {
0305 unsigned int irq = d->irq;
0306 u8 r8;
0307
0308 if ((irq < 1) || (irq == 2) || (irq > 7)) {
0309 printk(KERN_ERR PFX "Illegal irq number (%d).\n", irq);
0310 BUG();
0311 return;
0312 }
0313
0314
0315 r8 = inb(IC_PIC1+1);
0316 r8 &= ~(1 << irq);
0317 outb (r8,IC_PIC1+1);
0318 }
0319
0320 static struct irq_chip superio_interrupt_type = {
0321 .name = SUPERIO,
0322 .irq_unmask = superio_unmask_irq,
0323 .irq_mask = superio_mask_irq,
0324 };
0325
0326 #ifdef DEBUG_SUPERIO_INIT
0327 static unsigned short expected_device[3] = {
0328 PCI_DEVICE_ID_NS_87415,
0329 PCI_DEVICE_ID_NS_87560_LIO,
0330 PCI_DEVICE_ID_NS_87560_USB
0331 };
0332 #endif
0333
0334 int superio_fixup_irq(struct pci_dev *pcidev)
0335 {
0336 int local_irq, i;
0337
0338 #ifdef DEBUG_SUPERIO_INIT
0339 int fn;
0340 fn = PCI_FUNC(pcidev->devfn);
0341
0342
0343 if (expected_device[fn] != pcidev->device) {
0344 BUG();
0345 return -1;
0346 }
0347 printk(KERN_DEBUG "superio_fixup_irq(%s) ven 0x%x dev 0x%x from %ps\n",
0348 pci_name(pcidev),
0349 pcidev->vendor, pcidev->device,
0350 __builtin_return_address(0));
0351 #endif
0352
0353 for (i = 0; i < 16; i++) {
0354 irq_set_chip_and_handler(i, &superio_interrupt_type,
0355 handle_simple_irq);
0356 }
0357
0358
0359
0360
0361
0362
0363
0364 switch(pcidev->device) {
0365 case PCI_DEVICE_ID_NS_87415:
0366 local_irq = IDE_IRQ;
0367 break;
0368 case PCI_DEVICE_ID_NS_87560_LIO:
0369 sio_dev.lio_pdev = pcidev;
0370 return -1;
0371 case PCI_DEVICE_ID_NS_87560_USB:
0372 sio_dev.usb_pdev = pcidev;
0373 local_irq = USB_IRQ;
0374 break;
0375 default:
0376 local_irq = -1;
0377 BUG();
0378 break;
0379 }
0380
0381 return local_irq;
0382 }
0383
0384 static void __init superio_serial_init(void)
0385 {
0386 #ifdef CONFIG_SERIAL_8250
0387 int retval;
0388 struct uart_port serial_port;
0389
0390 memset(&serial_port, 0, sizeof(serial_port));
0391 serial_port.iotype = UPIO_PORT;
0392 serial_port.type = PORT_16550A;
0393 serial_port.uartclk = 115200*16;
0394 serial_port.flags = UPF_FIXED_PORT | UPF_FIXED_TYPE |
0395 UPF_BOOT_AUTOCONF;
0396
0397
0398 serial_port.iobase = sio_dev.sp1_base;
0399 serial_port.irq = SP1_IRQ;
0400 serial_port.line = 0;
0401 retval = early_serial_setup(&serial_port);
0402 if (retval < 0) {
0403 printk(KERN_WARNING PFX "Register Serial #0 failed.\n");
0404 return;
0405 }
0406
0407
0408 serial_port.iobase = sio_dev.sp2_base;
0409 serial_port.irq = SP2_IRQ;
0410 serial_port.line = 1;
0411 retval = early_serial_setup(&serial_port);
0412 if (retval < 0)
0413 printk(KERN_WARNING PFX "Register Serial #1 failed.\n");
0414 #endif
0415 }
0416
0417
0418 static void __init superio_parport_init(void)
0419 {
0420 #ifdef CONFIG_PARPORT_PC
0421 if (!parport_pc_probe_port(sio_dev.pp_base,
0422 0 ,
0423 PAR_IRQ,
0424 PARPORT_DMA_NONE ,
0425 NULL ,
0426 0 ))
0427
0428 printk(KERN_WARNING PFX "Probing parallel port failed.\n");
0429 #endif
0430 }
0431
0432
0433 static void superio_fixup_pci(struct pci_dev *pdev)
0434 {
0435 u8 prog;
0436
0437 pdev->class |= 0x5;
0438 pci_write_config_byte(pdev, PCI_CLASS_PROG, pdev->class);
0439
0440 pci_read_config_byte(pdev, PCI_CLASS_PROG, &prog);
0441 printk("PCI: Enabled native mode for NS87415 (pif=0x%x)\n", prog);
0442 }
0443 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87415, superio_fixup_pci);
0444
0445
0446 static int __init
0447 superio_probe(struct pci_dev *dev, const struct pci_device_id *id)
0448 {
0449 struct superio_device *sio = &sio_dev;
0450
0451
0452
0453
0454
0455
0456 DBG_INIT("superio_probe(%s) ven 0x%x dev 0x%x sv 0x%x sd 0x%x class 0x%x\n",
0457 pci_name(dev),
0458 dev->vendor, dev->device,
0459 dev->subsystem_vendor, dev->subsystem_device,
0460 dev->class);
0461
0462 BUG_ON(!sio->suckyio_irq_enabled);
0463
0464 if (dev->device == PCI_DEVICE_ID_NS_87560_LIO) {
0465 superio_parport_init();
0466 superio_serial_init();
0467
0468 return 0;
0469 } else if (dev->device == PCI_DEVICE_ID_NS_87415) {
0470 DBG_INIT("superio_probe: ignoring IDE 87415\n");
0471 } else if (dev->device == PCI_DEVICE_ID_NS_87560_USB) {
0472 DBG_INIT("superio_probe: ignoring USB OHCI controller\n");
0473 } else {
0474 DBG_INIT("superio_probe: WTF? Fire Extinguisher?\n");
0475 }
0476
0477
0478 return -ENODEV;
0479 }
0480
0481 static const struct pci_device_id superio_tbl[] __initconst = {
0482 { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87560_LIO) },
0483 { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87560_USB) },
0484 { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87415) },
0485 { 0, }
0486 };
0487
0488 static struct pci_driver superio_driver __refdata = {
0489 .name = SUPERIO,
0490 .id_table = superio_tbl,
0491 .probe = superio_probe,
0492 };
0493
0494 module_pci_driver(superio_driver);