cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

8250_pericom.c (7713B)


      1// SPDX-License-Identifier: GPL-2.0
      2/* Driver for Pericom UART */
      3
      4#include <linux/bits.h>
      5#include <linux/module.h>
      6#include <linux/overflow.h>
      7#include <linux/pci.h>
      8
      9#include "8250.h"
     10
     11#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM_2SDB	0x1051
     12#define PCI_DEVICE_ID_ACCESSIO_MPCIE_COM_2S	0x1053
     13#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM422_4	0x105a
     14#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM485_4	0x105b
     15#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM_4SDB	0x105c
     16#define PCI_DEVICE_ID_ACCESSIO_MPCIE_COM_4S	0x105e
     17#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM422_8	0x106a
     18#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM485_8	0x106b
     19#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM232_2DB	0x1091
     20#define PCI_DEVICE_ID_ACCESSIO_MPCIE_COM232_2	0x1093
     21#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM232_4	0x1098
     22#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM232_4DB	0x1099
     23#define PCI_DEVICE_ID_ACCESSIO_MPCIE_COM232_4	0x109b
     24#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM232_8	0x10a9
     25#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM_2SMDB	0x10d1
     26#define PCI_DEVICE_ID_ACCESSIO_MPCIE_COM_2SM	0x10d3
     27#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM_4SM	0x10d9
     28#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM_4SMDB	0x10da
     29#define PCI_DEVICE_ID_ACCESSIO_MPCIE_COM_4SM	0x10dc
     30#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM_8SM	0x10e9
     31#define PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM485_1	0x1108
     32#define PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM422_2	0x1110
     33#define PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM485_2	0x1111
     34#define PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM422_4	0x1118
     35#define PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM485_4	0x1119
     36#define PCI_DEVICE_ID_ACCESSIO_PCIE_ICM_2S	0x1152
     37#define PCI_DEVICE_ID_ACCESSIO_PCIE_ICM_4S	0x115a
     38#define PCI_DEVICE_ID_ACCESSIO_PCIE_ICM232_2	0x1190
     39#define PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM232_2	0x1191
     40#define PCI_DEVICE_ID_ACCESSIO_PCIE_ICM232_4	0x1198
     41#define PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM232_4	0x1199
     42#define PCI_DEVICE_ID_ACCESSIO_PCIE_ICM_2SM	0x11d0
     43#define PCI_DEVICE_ID_ACCESSIO_PCIE_ICM_4SM	0x11d8
     44
     45struct pericom8250 {
     46	void __iomem *virt;
     47	unsigned int nr;
     48	int line[];
     49};
     50
     51static void pericom_do_set_divisor(struct uart_port *port, unsigned int baud,
     52				   unsigned int quot, unsigned int quot_frac)
     53{
     54	int scr;
     55
     56	for (scr = 16; scr > 4; scr--) {
     57		unsigned int maxrate = port->uartclk / scr;
     58		unsigned int divisor = max(maxrate / baud, 1U);
     59		int delta = maxrate / divisor - baud;
     60
     61		if (baud > maxrate + baud / 50)
     62			continue;
     63
     64		if (delta > baud / 50)
     65			divisor++;
     66
     67		if (divisor > 0xffff)
     68			continue;
     69
     70		/* Update delta due to possible divisor change */
     71		delta = maxrate / divisor - baud;
     72		if (abs(delta) < baud / 50) {
     73			struct uart_8250_port *up = up_to_u8250p(port);
     74			int lcr = serial_port_in(port, UART_LCR);
     75
     76			serial_port_out(port, UART_LCR, lcr | 0x80);
     77			serial_dl_write(up, divisor);
     78			serial_port_out(port, 2, 16 - scr);
     79			serial_port_out(port, UART_LCR, lcr);
     80			return;
     81		}
     82	}
     83}
     84
     85static int pericom8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
     86{
     87	unsigned int nr, i, bar = 0, maxnr;
     88	struct pericom8250 *pericom;
     89	struct uart_8250_port uart;
     90	int ret;
     91
     92	ret = pcim_enable_device(pdev);
     93	if (ret)
     94		return ret;
     95
     96	maxnr = pci_resource_len(pdev, bar) >> 3;
     97
     98	if (pdev->vendor == PCI_VENDOR_ID_PERICOM)
     99		nr = pdev->device & 0x0f;
    100	else if (pdev->vendor == PCI_VENDOR_ID_ACCESSIO)
    101		nr = BIT(((pdev->device & 0x38) >> 3) - 1);
    102	else
    103		nr = 1;
    104
    105	pericom = devm_kzalloc(&pdev->dev, struct_size(pericom, line, nr), GFP_KERNEL);
    106	if (!pericom)
    107		return -ENOMEM;
    108
    109	pericom->virt = pcim_iomap(pdev, bar, 0);
    110	if (!pericom->virt)
    111		return -ENOMEM;
    112
    113	memset(&uart, 0, sizeof(uart));
    114
    115	uart.port.dev = &pdev->dev;
    116	uart.port.irq = pdev->irq;
    117	uart.port.private_data = pericom;
    118	uart.port.iotype = UPIO_PORT;
    119	uart.port.uartclk = 921600 * 16;
    120	uart.port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
    121	uart.port.set_divisor = pericom_do_set_divisor;
    122	for (i = 0; i < nr && i < maxnr; i++) {
    123		unsigned int offset = (i == 3 && nr == 4) ? 0x38 : i * 0x8;
    124
    125		uart.port.iobase = pci_resource_start(pdev, bar) + offset;
    126
    127		dev_dbg(&pdev->dev, "Setup PCI port: port %lx, irq %d, type %d\n",
    128			uart.port.iobase, uart.port.irq, uart.port.iotype);
    129
    130		pericom->line[i] = serial8250_register_8250_port(&uart);
    131		if (pericom->line[i] < 0) {
    132			dev_err(&pdev->dev,
    133				"Couldn't register serial port %lx, irq %d, type %d, error %d\n",
    134				uart.port.iobase, uart.port.irq,
    135				uart.port.iotype, pericom->line[i]);
    136			break;
    137		}
    138	}
    139	pericom->nr = i;
    140
    141	pci_set_drvdata(pdev, pericom);
    142	return 0;
    143}
    144
    145static void pericom8250_remove(struct pci_dev *pdev)
    146{
    147	struct pericom8250 *pericom = pci_get_drvdata(pdev);
    148	unsigned int i;
    149
    150	for (i = 0; i < pericom->nr; i++)
    151		serial8250_unregister_port(pericom->line[i]);
    152}
    153
    154static const struct pci_device_id pericom8250_pci_ids[] = {
    155	/*
    156	 * Pericom PI7C9X795[1248] Uno/Dual/Quad/Octal UART
    157	 * (Only 7954 has an offset jump for port 4)
    158	 */
    159	{ PCI_VDEVICE(PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7951) },
    160	{ PCI_VDEVICE(PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7952) },
    161	{ PCI_VDEVICE(PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7954) },
    162	{ PCI_VDEVICE(PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7958) },
    163
    164	/*
    165	 * ACCES I/O Products quad
    166	 * (Only 7954 has an offset jump for port 4)
    167	 */
    168	{ PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM_2SDB) },
    169	{ PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_COM_2S) },
    170	{ PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM422_4) },
    171	{ PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM485_4) },
    172	{ PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM_4SDB) },
    173	{ PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_COM_4S) },
    174	{ PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM422_8) },
    175	{ PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM485_8) },
    176	{ PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM232_2DB) },
    177	{ PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_COM232_2) },
    178	{ PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM232_4) },
    179	{ PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM232_4DB) },
    180	{ PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_COM232_4) },
    181	{ PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM232_8) },
    182	{ PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM_2SMDB) },
    183	{ PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_COM_2SM) },
    184	{ PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM_4SM) },
    185	{ PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM_4SMDB) },
    186	{ PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_COM_4SM) },
    187	{ PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM_8SM) },
    188	{ PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM485_1) },
    189	{ PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM422_2) },
    190	{ PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM485_2) },
    191	{ PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM422_4) },
    192	{ PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM485_4) },
    193	{ PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_ICM_2S) },
    194	{ PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_ICM_4S) },
    195	{ PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_ICM232_2) },
    196	{ PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM232_2) },
    197	{ PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_ICM232_4) },
    198	{ PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM232_4) },
    199	{ PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_ICM_2SM) },
    200	{ PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_ICM_4SM) },
    201	{ }
    202};
    203MODULE_DEVICE_TABLE(pci, pericom8250_pci_ids);
    204
    205static struct pci_driver pericom8250_pci_driver = {
    206	.name           = "8250_pericom",
    207	.id_table       = pericom8250_pci_ids,
    208	.probe          = pericom8250_probe,
    209	.remove         = pericom8250_remove,
    210};
    211module_pci_driver(pericom8250_pci_driver);
    212
    213MODULE_LICENSE("GPL v2");
    214MODULE_DESCRIPTION("Pericom UART driver");