Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Driver for Pericom UART */
0003 
0004 #include <linux/bits.h>
0005 #include <linux/module.h>
0006 #include <linux/overflow.h>
0007 #include <linux/pci.h>
0008 
0009 #include "8250.h"
0010 
0011 #define PCI_DEVICE_ID_ACCESSIO_PCIE_COM_2SDB    0x1051
0012 #define PCI_DEVICE_ID_ACCESSIO_MPCIE_COM_2S 0x1053
0013 #define PCI_DEVICE_ID_ACCESSIO_PCIE_COM422_4    0x105a
0014 #define PCI_DEVICE_ID_ACCESSIO_PCIE_COM485_4    0x105b
0015 #define PCI_DEVICE_ID_ACCESSIO_PCIE_COM_4SDB    0x105c
0016 #define PCI_DEVICE_ID_ACCESSIO_MPCIE_COM_4S 0x105e
0017 #define PCI_DEVICE_ID_ACCESSIO_PCIE_COM422_8    0x106a
0018 #define PCI_DEVICE_ID_ACCESSIO_PCIE_COM485_8    0x106b
0019 #define PCI_DEVICE_ID_ACCESSIO_PCIE_COM232_2DB  0x1091
0020 #define PCI_DEVICE_ID_ACCESSIO_MPCIE_COM232_2   0x1093
0021 #define PCI_DEVICE_ID_ACCESSIO_PCIE_COM232_4    0x1098
0022 #define PCI_DEVICE_ID_ACCESSIO_PCIE_COM232_4DB  0x1099
0023 #define PCI_DEVICE_ID_ACCESSIO_MPCIE_COM232_4   0x109b
0024 #define PCI_DEVICE_ID_ACCESSIO_PCIE_COM232_8    0x10a9
0025 #define PCI_DEVICE_ID_ACCESSIO_PCIE_COM_2SMDB   0x10d1
0026 #define PCI_DEVICE_ID_ACCESSIO_MPCIE_COM_2SM    0x10d3
0027 #define PCI_DEVICE_ID_ACCESSIO_PCIE_COM_4SM 0x10d9
0028 #define PCI_DEVICE_ID_ACCESSIO_PCIE_COM_4SMDB   0x10da
0029 #define PCI_DEVICE_ID_ACCESSIO_MPCIE_COM_4SM    0x10dc
0030 #define PCI_DEVICE_ID_ACCESSIO_PCIE_COM_8SM 0x10e9
0031 #define PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM485_1   0x1108
0032 #define PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM422_2   0x1110
0033 #define PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM485_2   0x1111
0034 #define PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM422_4   0x1118
0035 #define PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM485_4   0x1119
0036 #define PCI_DEVICE_ID_ACCESSIO_PCIE_ICM_2S  0x1152
0037 #define PCI_DEVICE_ID_ACCESSIO_PCIE_ICM_4S  0x115a
0038 #define PCI_DEVICE_ID_ACCESSIO_PCIE_ICM232_2    0x1190
0039 #define PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM232_2   0x1191
0040 #define PCI_DEVICE_ID_ACCESSIO_PCIE_ICM232_4    0x1198
0041 #define PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM232_4   0x1199
0042 #define PCI_DEVICE_ID_ACCESSIO_PCIE_ICM_2SM 0x11d0
0043 #define PCI_DEVICE_ID_ACCESSIO_PCIE_ICM_4SM 0x11d8
0044 
0045 struct pericom8250 {
0046     void __iomem *virt;
0047     unsigned int nr;
0048     int line[];
0049 };
0050 
0051 static void pericom_do_set_divisor(struct uart_port *port, unsigned int baud,
0052                    unsigned int quot, unsigned int quot_frac)
0053 {
0054     int scr;
0055 
0056     for (scr = 16; scr > 4; scr--) {
0057         unsigned int maxrate = port->uartclk / scr;
0058         unsigned int divisor = max(maxrate / baud, 1U);
0059         int delta = maxrate / divisor - baud;
0060 
0061         if (baud > maxrate + baud / 50)
0062             continue;
0063 
0064         if (delta > baud / 50)
0065             divisor++;
0066 
0067         if (divisor > 0xffff)
0068             continue;
0069 
0070         /* Update delta due to possible divisor change */
0071         delta = maxrate / divisor - baud;
0072         if (abs(delta) < baud / 50) {
0073             struct uart_8250_port *up = up_to_u8250p(port);
0074             int lcr = serial_port_in(port, UART_LCR);
0075 
0076             serial_port_out(port, UART_LCR, lcr | UART_LCR_DLAB);
0077             serial_dl_write(up, divisor);
0078             serial_port_out(port, 2, 16 - scr);
0079             serial_port_out(port, UART_LCR, lcr);
0080             return;
0081         }
0082     }
0083 }
0084 
0085 static int pericom8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
0086 {
0087     unsigned int nr, i, bar = 0, maxnr;
0088     struct pericom8250 *pericom;
0089     struct uart_8250_port uart;
0090     int ret;
0091 
0092     ret = pcim_enable_device(pdev);
0093     if (ret)
0094         return ret;
0095 
0096     maxnr = pci_resource_len(pdev, bar) >> 3;
0097 
0098     if (pdev->vendor == PCI_VENDOR_ID_PERICOM)
0099         nr = pdev->device & 0x0f;
0100     else if (pdev->vendor == PCI_VENDOR_ID_ACCESSIO)
0101         nr = BIT(((pdev->device & 0x38) >> 3) - 1);
0102     else
0103         nr = 1;
0104 
0105     pericom = devm_kzalloc(&pdev->dev, struct_size(pericom, line, nr), GFP_KERNEL);
0106     if (!pericom)
0107         return -ENOMEM;
0108 
0109     pericom->virt = pcim_iomap(pdev, bar, 0);
0110     if (!pericom->virt)
0111         return -ENOMEM;
0112 
0113     memset(&uart, 0, sizeof(uart));
0114 
0115     uart.port.dev = &pdev->dev;
0116     uart.port.irq = pdev->irq;
0117     uart.port.private_data = pericom;
0118     uart.port.iotype = UPIO_PORT;
0119     uart.port.uartclk = 921600 * 16;
0120     uart.port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
0121     uart.port.set_divisor = pericom_do_set_divisor;
0122     for (i = 0; i < nr && i < maxnr; i++) {
0123         unsigned int offset = (i == 3 && nr == 4) ? 0x38 : i * 0x8;
0124 
0125         uart.port.iobase = pci_resource_start(pdev, bar) + offset;
0126 
0127         dev_dbg(&pdev->dev, "Setup PCI port: port %lx, irq %d, type %d\n",
0128             uart.port.iobase, uart.port.irq, uart.port.iotype);
0129 
0130         pericom->line[i] = serial8250_register_8250_port(&uart);
0131         if (pericom->line[i] < 0) {
0132             dev_err(&pdev->dev,
0133                 "Couldn't register serial port %lx, irq %d, type %d, error %d\n",
0134                 uart.port.iobase, uart.port.irq,
0135                 uart.port.iotype, pericom->line[i]);
0136             break;
0137         }
0138     }
0139     pericom->nr = i;
0140 
0141     pci_set_drvdata(pdev, pericom);
0142     return 0;
0143 }
0144 
0145 static void pericom8250_remove(struct pci_dev *pdev)
0146 {
0147     struct pericom8250 *pericom = pci_get_drvdata(pdev);
0148     unsigned int i;
0149 
0150     for (i = 0; i < pericom->nr; i++)
0151         serial8250_unregister_port(pericom->line[i]);
0152 }
0153 
0154 static const struct pci_device_id pericom8250_pci_ids[] = {
0155     /*
0156      * Pericom PI7C9X795[1248] Uno/Dual/Quad/Octal UART
0157      * (Only 7954 has an offset jump for port 4)
0158      */
0159     { PCI_VDEVICE(PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7951) },
0160     { PCI_VDEVICE(PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7952) },
0161     { PCI_VDEVICE(PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7954) },
0162     { PCI_VDEVICE(PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7958) },
0163 
0164     /*
0165      * ACCES I/O Products quad
0166      * (Only 7954 has an offset jump for port 4)
0167      */
0168     { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM_2SDB) },
0169     { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_COM_2S) },
0170     { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM422_4) },
0171     { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM485_4) },
0172     { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM_4SDB) },
0173     { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_COM_4S) },
0174     { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM422_8) },
0175     { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM485_8) },
0176     { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM232_2DB) },
0177     { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_COM232_2) },
0178     { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM232_4) },
0179     { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM232_4DB) },
0180     { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_COM232_4) },
0181     { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM232_8) },
0182     { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM_2SMDB) },
0183     { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_COM_2SM) },
0184     { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM_4SM) },
0185     { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM_4SMDB) },
0186     { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_COM_4SM) },
0187     { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM_8SM) },
0188     { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM485_1) },
0189     { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM422_2) },
0190     { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM485_2) },
0191     { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM422_4) },
0192     { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM485_4) },
0193     { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_ICM_2S) },
0194     { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_ICM_4S) },
0195     { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_ICM232_2) },
0196     { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM232_2) },
0197     { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_ICM232_4) },
0198     { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM232_4) },
0199     { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_ICM_2SM) },
0200     { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_ICM_4SM) },
0201     { }
0202 };
0203 MODULE_DEVICE_TABLE(pci, pericom8250_pci_ids);
0204 
0205 static struct pci_driver pericom8250_pci_driver = {
0206     .name           = "8250_pericom",
0207     .id_table       = pericom8250_pci_ids,
0208     .probe          = pericom8250_probe,
0209     .remove         = pericom8250_remove,
0210 };
0211 module_pci_driver(pericom8250_pci_driver);
0212 
0213 MODULE_LICENSE("GPL v2");
0214 MODULE_DESCRIPTION("Pericom UART driver");