0001
0002
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
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
0157
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
0166
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");