Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

serial: add support for ITE 887x chips

Add support for the it887x-chips (PCI) manufactured by ITE.

Signed-off-by: Niels de Vos <niels.devos@wincor-nixdorf.com>
Cc: Russell King <rmk@arm.linux.org.uk>
Acked-by: Alan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Niels de Vos and committed by
Linus Torvalds
84f8c6fc 20620d68

+159
+159
drivers/serial/8250_pci.c
··· 580 580 return num_serial; 581 581 } 582 582 583 + /* 584 + * ITE support by Niels de Vos <niels.devos@wincor-nixdorf.com> 585 + * 586 + * These chips are available with optionally one parallel port and up to 587 + * two serial ports. Unfortunately they all have the same product id. 588 + * 589 + * Basic configuration is done over a region of 32 I/O ports. The base 590 + * ioport is called INTA or INTC, depending on docs/other drivers. 591 + * 592 + * The region of the 32 I/O ports is configured in POSIO0R... 593 + */ 594 + 595 + /* registers */ 596 + #define ITE_887x_MISCR 0x9c 597 + #define ITE_887x_INTCBAR 0x78 598 + #define ITE_887x_UARTBAR 0x7c 599 + #define ITE_887x_PS0BAR 0x10 600 + #define ITE_887x_POSIO0 0x60 601 + 602 + /* I/O space size */ 603 + #define ITE_887x_IOSIZE 32 604 + /* I/O space size (bits 26-24; 8 bytes = 011b) */ 605 + #define ITE_887x_POSIO_IOSIZE_8 (3 << 24) 606 + /* I/O space size (bits 26-24; 32 bytes = 101b) */ 607 + #define ITE_887x_POSIO_IOSIZE_32 (5 << 24) 608 + /* Decoding speed (1 = slow, 2 = medium, 3 = fast) */ 609 + #define ITE_887x_POSIO_SPEED (3 << 29) 610 + /* enable IO_Space bit */ 611 + #define ITE_887x_POSIO_ENABLE (1 << 31) 612 + 613 + static int __devinit pci_ite887x_init(struct pci_dev *dev) 614 + { 615 + /* inta_addr are the configuration addresses of the ITE */ 616 + static const short inta_addr[] = { 0x2a0, 0x2c0, 0x220, 0x240, 0x1e0, 617 + 0x200, 0x280, 0 }; 618 + int ret, i, type; 619 + struct resource *iobase = NULL; 620 + u32 miscr, uartbar, ioport; 621 + 622 + /* search for the base-ioport */ 623 + i = 0; 624 + while (inta_addr[i] && iobase == NULL) { 625 + iobase = request_region(inta_addr[i], ITE_887x_IOSIZE, 626 + "ite887x"); 627 + if (iobase != NULL) { 628 + /* write POSIO0R - speed | size | ioport */ 629 + pci_write_config_dword(dev, ITE_887x_POSIO0, 630 + ITE_887x_POSIO_ENABLE | ITE_887x_POSIO_SPEED | 631 + ITE_887x_POSIO_IOSIZE_32 | inta_addr[i]); 632 + /* write INTCBAR - ioport */ 633 + pci_write_config_dword(dev, ITE_887x_INTCBAR, inta_addr[i]); 634 + ret = inb(inta_addr[i]); 635 + if (ret != 0xff) { 636 + /* ioport connected */ 637 + break; 638 + } 639 + release_region(iobase->start, ITE_887x_IOSIZE); 640 + iobase = NULL; 641 + } 642 + i++; 643 + } 644 + 645 + if (!inta_addr[i]) { 646 + printk(KERN_ERR "ite887x: could not find iobase\n"); 647 + return -ENODEV; 648 + } 649 + 650 + /* start of undocumented type checking (see parport_pc.c) */ 651 + type = inb(iobase->start + 0x18) & 0x0f; 652 + 653 + switch (type) { 654 + case 0x2: /* ITE8871 (1P) */ 655 + case 0xa: /* ITE8875 (1P) */ 656 + ret = 0; 657 + break; 658 + case 0xe: /* ITE8872 (2S1P) */ 659 + ret = 2; 660 + break; 661 + case 0x6: /* ITE8873 (1S) */ 662 + ret = 1; 663 + break; 664 + case 0x8: /* ITE8874 (2S) */ 665 + ret = 2; 666 + break; 667 + default: 668 + moan_device("Unknown ITE887x", dev); 669 + ret = -ENODEV; 670 + } 671 + 672 + /* configure all serial ports */ 673 + for (i = 0; i < ret; i++) { 674 + /* read the I/O port from the device */ 675 + pci_read_config_dword(dev, ITE_887x_PS0BAR + (0x4 * (i + 1)), 676 + &ioport); 677 + ioport &= 0x0000FF00; /* the actual base address */ 678 + pci_write_config_dword(dev, ITE_887x_POSIO0 + (0x4 * (i + 1)), 679 + ITE_887x_POSIO_ENABLE | ITE_887x_POSIO_SPEED | 680 + ITE_887x_POSIO_IOSIZE_8 | ioport); 681 + 682 + /* write the ioport to the UARTBAR */ 683 + pci_read_config_dword(dev, ITE_887x_UARTBAR, &uartbar); 684 + uartbar &= ~(0xffff << (16 * i)); /* clear half the reg */ 685 + uartbar |= (ioport << (16 * i)); /* set the ioport */ 686 + pci_write_config_dword(dev, ITE_887x_UARTBAR, uartbar); 687 + 688 + /* get current config */ 689 + pci_read_config_dword(dev, ITE_887x_MISCR, &miscr); 690 + /* disable interrupts (UARTx_Routing[3:0]) */ 691 + miscr &= ~(0xf << (12 - 4 * i)); 692 + /* activate the UART (UARTx_En) */ 693 + miscr |= 1 << (23 - i); 694 + /* write new config with activated UART */ 695 + pci_write_config_dword(dev, ITE_887x_MISCR, miscr); 696 + } 697 + 698 + if (ret <= 0) { 699 + /* the device has no UARTs if we get here */ 700 + release_region(iobase->start, ITE_887x_IOSIZE); 701 + } 702 + 703 + return ret; 704 + } 705 + 706 + static void __devexit pci_ite887x_exit(struct pci_dev *dev) 707 + { 708 + u32 ioport; 709 + /* the ioport is bit 0-15 in POSIO0R */ 710 + pci_read_config_dword(dev, ITE_887x_POSIO0, &ioport); 711 + ioport &= 0xffff; 712 + release_region(ioport, ITE_887x_IOSIZE); 713 + } 714 + 583 715 static int 584 716 pci_default_setup(struct serial_private *priv, struct pciserial_board *board, 585 717 struct uart_port *port, int idx) ··· 783 651 .subdevice = PCI_ANY_ID, 784 652 .init = pci_inteli960ni_init, 785 653 .setup = pci_default_setup, 654 + }, 655 + /* 656 + * ITE 657 + */ 658 + { 659 + .vendor = PCI_VENDOR_ID_ITE, 660 + .device = PCI_DEVICE_ID_ITE_8872, 661 + .subvendor = PCI_ANY_ID, 662 + .subdevice = PCI_ANY_ID, 663 + .init = pci_ite887x_init, 664 + .setup = pci_default_setup, 665 + .exit = __devexit_p(pci_ite887x_exit), 786 666 }, 787 667 /* 788 668 * Panacom ··· 1077 933 1078 934 pbn_b1_2_1250000, 1079 935 936 + pbn_b1_bt_1_115200, 1080 937 pbn_b1_bt_2_921600, 1081 938 1082 939 pbn_b1_1_1382400, ··· 1353 1208 .flags = FL_BASE1, 1354 1209 .num_ports = 2, 1355 1210 .base_baud = 1250000, 1211 + .uart_offset = 8, 1212 + }, 1213 + 1214 + [pbn_b1_bt_1_115200] = { 1215 + .flags = FL_BASE1|FL_BASE_BARS, 1216 + .num_ports = 1, 1217 + .base_baud = 115200, 1356 1218 .uart_offset = 8, 1357 1219 }, 1358 1220 ··· 2516 2364 { PCI_VENDOR_ID_TOPIC, PCI_DEVICE_ID_TOPIC_TP560, 2517 2365 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2518 2366 pbn_b0_1_115200 }, 2367 + /* 2368 + * ITE 2369 + */ 2370 + { PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_8872, 2371 + PCI_ANY_ID, PCI_ANY_ID, 2372 + 0, 0, 2373 + pbn_b1_bt_1_115200 }, 2519 2374 2520 2375 /* 2521 2376 * IntaShield IS-200