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

serial/8250: Add support for NI-Serial PXI/PXIe+485 devices

Add support for NI-Serial PXIe-RS232, PXI-RS485 and PXIe-RS485 devices.

Signed-off-by: Je Yen Tam <je.yen.tam@ni.com>
Link: https://lore.kernel.org/r/20190726074012.2590-1-je.yen.tam@ni.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Je Yen Tam and committed by
Greg Kroah-Hartman
fdc2de87 fe94347d

+288 -4
+288 -4
drivers/tty/serial/8250/8250_pci.c
··· 730 730 } 731 731 732 732 /* UART Port Control Register */ 733 - #define NI8430_PORTCON 0x0f 734 - #define NI8430_PORTCON_TXVR_ENABLE (1 << 3) 733 + #define NI16550_PCR_OFFSET 0x0f 734 + #define NI16550_PCR_RS422 0x00 735 + #define NI16550_PCR_ECHO_RS485 0x01 736 + #define NI16550_PCR_DTR_RS485 0x02 737 + #define NI16550_PCR_AUTO_RS485 0x03 738 + #define NI16550_PCR_WIRE_MODE_MASK 0x03 739 + #define NI16550_PCR_TXVR_ENABLE_BIT BIT(3) 740 + #define NI16550_PCR_RS485_TERMINATION_BIT BIT(6) 741 + #define NI16550_ACR_DTR_AUTO_DTR (0x2 << 3) 742 + #define NI16550_ACR_DTR_MANUAL_DTR (0x0 << 3) 735 743 736 744 static int 737 745 pci_ni8430_setup(struct serial_private *priv, ··· 761 753 return -ENOMEM; 762 754 763 755 /* enable the transceiver */ 764 - writeb(readb(p + offset + NI8430_PORTCON) | NI8430_PORTCON_TXVR_ENABLE, 765 - p + offset + NI8430_PORTCON); 756 + writeb(readb(p + offset + NI16550_PCR_OFFSET) | NI16550_PCR_TXVR_ENABLE_BIT, 757 + p + offset + NI16550_PCR_OFFSET); 766 758 767 759 iounmap(p); 768 760 769 761 return setup_port(priv, port, bar, offset, board->reg_shift); 762 + } 763 + 764 + static int pci_ni8431_config_rs485(struct uart_port *port, 765 + struct serial_rs485 *rs485) 766 + { 767 + u8 pcr, acr; 768 + struct uart_8250_port *up; 769 + 770 + up = container_of(port, struct uart_8250_port, port); 771 + acr = up->acr; 772 + pcr = port->serial_in(port, NI16550_PCR_OFFSET); 773 + pcr &= ~NI16550_PCR_WIRE_MODE_MASK; 774 + 775 + if (rs485->flags & SER_RS485_ENABLED) { 776 + /* RS-485 */ 777 + if ((rs485->flags & SER_RS485_RX_DURING_TX) && 778 + (rs485->flags & SER_RS485_RTS_ON_SEND)) { 779 + dev_dbg(port->dev, "Invalid 2-wire mode\n"); 780 + return -EINVAL; 781 + } 782 + 783 + if (rs485->flags & SER_RS485_RX_DURING_TX) { 784 + /* Echo */ 785 + dev_vdbg(port->dev, "2-wire DTR with echo\n"); 786 + pcr |= NI16550_PCR_ECHO_RS485; 787 + acr |= NI16550_ACR_DTR_MANUAL_DTR; 788 + } else { 789 + /* Auto or DTR */ 790 + if (rs485->flags & SER_RS485_RTS_ON_SEND) { 791 + /* Auto */ 792 + dev_vdbg(port->dev, "2-wire Auto\n"); 793 + pcr |= NI16550_PCR_AUTO_RS485; 794 + acr |= NI16550_ACR_DTR_AUTO_DTR; 795 + } else { 796 + /* DTR-controlled */ 797 + /* No Echo */ 798 + dev_vdbg(port->dev, "2-wire DTR no echo\n"); 799 + pcr |= NI16550_PCR_DTR_RS485; 800 + acr |= NI16550_ACR_DTR_MANUAL_DTR; 801 + } 802 + } 803 + } else { 804 + /* RS-422 */ 805 + dev_vdbg(port->dev, "4-wire\n"); 806 + pcr |= NI16550_PCR_RS422; 807 + acr |= NI16550_ACR_DTR_MANUAL_DTR; 808 + } 809 + 810 + dev_dbg(port->dev, "write pcr: 0x%08x\n", pcr); 811 + port->serial_out(port, NI16550_PCR_OFFSET, pcr); 812 + 813 + up->acr = acr; 814 + port->serial_out(port, UART_SCR, UART_ACR); 815 + port->serial_out(port, UART_ICR, up->acr); 816 + 817 + /* Update the cache. */ 818 + port->rs485 = *rs485; 819 + 820 + return 0; 821 + } 822 + 823 + static int pci_ni8431_setup(struct serial_private *priv, 824 + const struct pciserial_board *board, 825 + struct uart_8250_port *uart, int idx) 826 + { 827 + u8 pcr, acr; 828 + struct pci_dev *dev = priv->dev; 829 + void __iomem *addr; 830 + unsigned int bar, offset = board->first_offset; 831 + 832 + if (idx >= board->num_ports) 833 + return 1; 834 + 835 + bar = FL_GET_BASE(board->flags); 836 + offset += idx * board->uart_offset; 837 + 838 + addr = pci_ioremap_bar(dev, bar); 839 + if (!addr) 840 + return -ENOMEM; 841 + 842 + /* enable the transceiver */ 843 + writeb(readb(addr + NI16550_PCR_OFFSET) | NI16550_PCR_TXVR_ENABLE_BIT, 844 + addr + NI16550_PCR_OFFSET); 845 + 846 + pcr = readb(addr + NI16550_PCR_OFFSET); 847 + pcr &= ~NI16550_PCR_WIRE_MODE_MASK; 848 + 849 + /* set wire mode to default RS-422 */ 850 + pcr |= NI16550_PCR_RS422; 851 + acr = NI16550_ACR_DTR_MANUAL_DTR; 852 + 853 + /* write port configuration to register */ 854 + writeb(pcr, addr + NI16550_PCR_OFFSET); 855 + 856 + /* access and write to UART acr register */ 857 + writeb(UART_ACR, addr + UART_SCR); 858 + writeb(acr, addr + UART_ICR); 859 + 860 + uart->port.rs485_config = &pci_ni8431_config_rs485; 861 + 862 + iounmap(addr); 863 + 864 + return setup_port(priv, uart, bar, offset, board->reg_shift); 770 865 } 771 866 772 867 static int pci_netmos_9900_setup(struct serial_private *priv, ··· 1897 1786 #define PCI_DEVICE_ID_ACCESIO_PCIE_COM_8SM 0x10E9 1898 1787 #define PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4SM 0x11D8 1899 1788 1789 + #define PCIE_DEVICE_ID_NI_PXIE8430_2328 0x74C2 1790 + #define PCIE_DEVICE_ID_NI_PXIE8430_23216 0x74C1 1791 + #define PCI_DEVICE_ID_NI_PXI8431_4852 0x7081 1792 + #define PCI_DEVICE_ID_NI_PXI8431_4854 0x70DE 1793 + #define PCI_DEVICE_ID_NI_PXI8431_4858 0x70E3 1794 + #define PCI_DEVICE_ID_NI_PXI8433_4852 0x70E9 1795 + #define PCI_DEVICE_ID_NI_PXI8433_4854 0x70ED 1796 + #define PCIE_DEVICE_ID_NI_PXIE8431_4858 0x74C4 1797 + #define PCIE_DEVICE_ID_NI_PXIE8431_48516 0x74C3 1900 1798 1901 1799 1902 1800 /* Unknown vendors/cards - this should not be in linux/pci_ids.h */ ··· 2129 2009 .subdevice = PCI_ANY_ID, 2130 2010 .init = pci_ni8430_init, 2131 2011 .setup = pci_ni8430_setup, 2012 + .exit = pci_ni8430_exit, 2013 + }, 2014 + { 2015 + .vendor = PCI_VENDOR_ID_NI, 2016 + .device = PCIE_DEVICE_ID_NI_PXIE8430_2328, 2017 + .subvendor = PCI_ANY_ID, 2018 + .subdevice = PCI_ANY_ID, 2019 + .init = pci_ni8430_init, 2020 + .setup = pci_ni8430_setup, 2021 + .exit = pci_ni8430_exit, 2022 + }, 2023 + { 2024 + .vendor = PCI_VENDOR_ID_NI, 2025 + .device = PCIE_DEVICE_ID_NI_PXIE8430_23216, 2026 + .subvendor = PCI_ANY_ID, 2027 + .subdevice = PCI_ANY_ID, 2028 + .init = pci_ni8430_init, 2029 + .setup = pci_ni8430_setup, 2030 + .exit = pci_ni8430_exit, 2031 + }, 2032 + { 2033 + .vendor = PCI_VENDOR_ID_NI, 2034 + .device = PCI_DEVICE_ID_NI_PXI8431_4852, 2035 + .subvendor = PCI_ANY_ID, 2036 + .subdevice = PCI_ANY_ID, 2037 + .init = pci_ni8430_init, 2038 + .setup = pci_ni8431_setup, 2039 + .exit = pci_ni8430_exit, 2040 + }, 2041 + { 2042 + .vendor = PCI_VENDOR_ID_NI, 2043 + .device = PCI_DEVICE_ID_NI_PXI8431_4854, 2044 + .subvendor = PCI_ANY_ID, 2045 + .subdevice = PCI_ANY_ID, 2046 + .init = pci_ni8430_init, 2047 + .setup = pci_ni8431_setup, 2048 + .exit = pci_ni8430_exit, 2049 + }, 2050 + { 2051 + .vendor = PCI_VENDOR_ID_NI, 2052 + .device = PCI_DEVICE_ID_NI_PXI8431_4858, 2053 + .subvendor = PCI_ANY_ID, 2054 + .subdevice = PCI_ANY_ID, 2055 + .init = pci_ni8430_init, 2056 + .setup = pci_ni8431_setup, 2057 + .exit = pci_ni8430_exit, 2058 + }, 2059 + { 2060 + .vendor = PCI_VENDOR_ID_NI, 2061 + .device = PCI_DEVICE_ID_NI_PXI8433_4852, 2062 + .subvendor = PCI_ANY_ID, 2063 + .subdevice = PCI_ANY_ID, 2064 + .init = pci_ni8430_init, 2065 + .setup = pci_ni8431_setup, 2066 + .exit = pci_ni8430_exit, 2067 + }, 2068 + { 2069 + .vendor = PCI_VENDOR_ID_NI, 2070 + .device = PCI_DEVICE_ID_NI_PXI8433_4854, 2071 + .subvendor = PCI_ANY_ID, 2072 + .subdevice = PCI_ANY_ID, 2073 + .init = pci_ni8430_init, 2074 + .setup = pci_ni8431_setup, 2075 + .exit = pci_ni8430_exit, 2076 + }, 2077 + { 2078 + .vendor = PCI_VENDOR_ID_NI, 2079 + .device = PCIE_DEVICE_ID_NI_PXIE8431_4858, 2080 + .subvendor = PCI_ANY_ID, 2081 + .subdevice = PCI_ANY_ID, 2082 + .init = pci_ni8430_init, 2083 + .setup = pci_ni8431_setup, 2084 + .exit = pci_ni8430_exit, 2085 + }, 2086 + { 2087 + .vendor = PCI_VENDOR_ID_NI, 2088 + .device = PCIE_DEVICE_ID_NI_PXIE8431_48516, 2089 + .subvendor = PCI_ANY_ID, 2090 + .subdevice = PCI_ANY_ID, 2091 + .init = pci_ni8430_init, 2092 + .setup = pci_ni8431_setup, 2132 2093 .exit = pci_ni8430_exit, 2133 2094 }, 2134 2095 /* Quatech */ ··· 2941 2740 pbn_ni8430_4, 2942 2741 pbn_ni8430_8, 2943 2742 pbn_ni8430_16, 2743 + pbn_ni8430_pxie_8, 2744 + pbn_ni8430_pxie_16, 2745 + pbn_ni8431_2, 2746 + pbn_ni8431_4, 2747 + pbn_ni8431_8, 2748 + pbn_ni8431_pxie_8, 2749 + pbn_ni8431_pxie_16, 2944 2750 pbn_ADDIDATA_PCIe_1_3906250, 2945 2751 pbn_ADDIDATA_PCIe_2_3906250, 2946 2752 pbn_ADDIDATA_PCIe_4_3906250, ··· 3586 3378 .flags = FL_BASE0, 3587 3379 .num_ports = 2, 3588 3380 .base_baud = 3686400, 3381 + .uart_offset = 0x10, 3382 + .first_offset = 0x800, 3383 + }, 3384 + [pbn_ni8430_pxie_16] = { 3385 + .flags = FL_BASE0, 3386 + .num_ports = 16, 3387 + .base_baud = 3125000, 3388 + .uart_offset = 0x10, 3389 + .first_offset = 0x800, 3390 + }, 3391 + [pbn_ni8430_pxie_8] = { 3392 + .flags = FL_BASE0, 3393 + .num_ports = 8, 3394 + .base_baud = 3125000, 3395 + .uart_offset = 0x10, 3396 + .first_offset = 0x800, 3397 + }, 3398 + [pbn_ni8431_8] = { 3399 + .flags = FL_BASE0, 3400 + .num_ports = 8, 3401 + .base_baud = 3686400, 3402 + .uart_offset = 0x10, 3403 + .first_offset = 0x800, 3404 + }, 3405 + [pbn_ni8431_4] = { 3406 + .flags = FL_BASE0, 3407 + .num_ports = 4, 3408 + .base_baud = 3686400, 3409 + .uart_offset = 0x10, 3410 + .first_offset = 0x800, 3411 + }, 3412 + [pbn_ni8431_2] = { 3413 + .flags = FL_BASE0, 3414 + .num_ports = 2, 3415 + .base_baud = 3686400, 3416 + .uart_offset = 0x10, 3417 + .first_offset = 0x800, 3418 + }, 3419 + [pbn_ni8431_pxie_16] = { 3420 + .flags = FL_BASE0, 3421 + .num_ports = 16, 3422 + .base_baud = 3125000, 3423 + .uart_offset = 0x10, 3424 + .first_offset = 0x800, 3425 + }, 3426 + [pbn_ni8431_pxie_8] = { 3427 + .flags = FL_BASE0, 3428 + .num_ports = 8, 3429 + .base_baud = 3125000, 3589 3430 .uart_offset = 0x10, 3590 3431 .first_offset = 0x800, 3591 3432 }, ··· 5320 5063 { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8432_2324, 5321 5064 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5322 5065 pbn_ni8430_4 }, 5066 + { PCI_VENDOR_ID_NI, PCIE_DEVICE_ID_NI_PXIE8430_2328, 5067 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5068 + pbn_ni8430_pxie_8 }, 5069 + { PCI_VENDOR_ID_NI, PCIE_DEVICE_ID_NI_PXIE8430_23216, 5070 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5071 + pbn_ni8430_pxie_16 }, 5072 + { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8431_4852, 5073 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5074 + pbn_ni8431_2 }, 5075 + { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8431_4854, 5076 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5077 + pbn_ni8431_4 }, 5078 + { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8431_4858, 5079 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5080 + pbn_ni8431_8 }, 5081 + { PCI_VENDOR_ID_NI, PCIE_DEVICE_ID_NI_PXIE8431_4858, 5082 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5083 + pbn_ni8431_pxie_8 }, 5084 + { PCI_VENDOR_ID_NI, PCIE_DEVICE_ID_NI_PXIE8431_48516, 5085 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5086 + pbn_ni8431_pxie_16 }, 5087 + { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8433_4852, 5088 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5089 + pbn_ni8431_2 }, 5090 + { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8433_4854, 5091 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5092 + pbn_ni8431_4 }, 5323 5093 5324 5094 /* 5325 5095 * ADDI-DATA GmbH communication cards <info@addi-data.com>