// SPDX-License-Identifier: GPL-2.0 /* * Probe module for 8250/16550-type MCHP PCI serial ports. * * Based on drivers/tty/serial/8250/8250_pci.c, * * Copyright (C) 2022 Microchip Technology Inc., All Rights Reserved.
*/
staticint pci1xxxx_get_num_ports(struct pci_dev *dev)
{ switch (dev->subsystem_device) { case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_1p0: case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_1p1: case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_1p2: case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_1p3: case PCI_SUBDEVICE_ID_EFAR_PCI12000: case PCI_SUBDEVICE_ID_EFAR_PCI11010: case PCI_SUBDEVICE_ID_EFAR_PCI11101: case PCI_SUBDEVICE_ID_EFAR_PCI11400: default: return1; case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_2p01: case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_2p02: case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_2p03: case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_2p12: case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_2p13: case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_2p23: return2; case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_3p012: case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_3p123: case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_3p013: case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_3p023: return3; case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_4p: case PCI_SUBDEVICE_ID_EFAR_PCI11414: return4;
}
}
/* * pci1xxxx's uart hardware supports only RTS delay after * Tx and in units of bit times to a maximum of 15
*/ if (rs485->flags & SER_RS485_ENABLED) {
mode_cfg = ADCL_CFG_EN | ADCL_CFG_PIN_SEL;
if (!(rs485->flags & SER_RS485_RTS_ON_SEND))
mode_cfg |= ADCL_CFG_POL_SEL;
/* * Depending on the RX Trigger Level the number of bytes that can be * stored in RX FIFO at a time varies. Each transaction reads data * in DWORDs. If there are less than four remaining valid_byte_count * to read, the data is received one byte at a time.
*/ while (valid_burst_count--) { if (*buff_index > (RX_BUF_SIZE - UART_BURST_SIZE)) break;
burst_buf = (u32 *)&rx_buff[*buff_index];
*burst_buf = readl(port->membase + UART_RX_BURST_FIFO);
*buff_index += UART_BURST_SIZE;
*valid_byte_count -= UART_BURST_SIZE;
}
/* * Each transaction transfers data in DWORDs. If there are less than * four remaining valid_byte_count to transfer or if the circular * buffer has insufficient space for a DWORD, the data is transferred * one byte at a time.
*/ while (valid_burst_count) {
u32 c;
/* * If there are any pending burst count, data is handled by * transmitting DWORDs at a time.
*/ if (valid_burst_count &&
kfifo_len(&tport->xmit_fifo) >= UART_BURST_SIZE) break;
}
}
port->icount.tx++; if (kfifo_is_empty(&tport->xmit_fifo)) break;
} while (data_empty_count && valid_byte_count);
}
if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(port);
/* * With RPM enabled, we have to wait until the FIFO is empty before * the HW can go idle. So we get here once again with empty FIFO and * disable the interrupt and RPM in __stop_tx()
*/ if (kfifo_is_empty(&tport->xmit_fifo) &&
!(up->capabilities & UART_CAP_RPM))
port->ops->stop_tx(port);
}
p = pci_ioremap_bar(pcidev, 0); if (!p) {
dev_err(dev, "remapping of bar 0 memory failed"); return -ENOMEM;
}
data = readl(p + UART_RESET_REG);
if (priv->dev_rev >= 0xC0)
data &= ~UART_RESET_HOT_RESET_DISABLE;
writel(data & ~UART_RESET_D3_RESET_DISABLE, p + UART_RESET_REG);
iounmap(p);
for (i = 0; i < priv->nr; i++) { if (priv->line[i] >= 0) {
pci1xxxx_port_resume(priv->line[i]);
serial8250_resume_port(priv->line[i]);
}
}
return0;
}
staticint pci1xxxx_setup(struct pci_dev *pdev, struct uart_8250_port *port, int port_idx, int rev)
{ int ret;
port->port.flags |= UPF_FIXED_TYPE | UPF_SKIP_TEST;
port->port.type = PORT_MCHP16550A; /* * 8250 core considers prescaller value to be always 16. * The MCHP ports support downscaled mode and hence the * functional UART clock can be lower, i.e. 62.5MHz, than * software expects in order to support higher baud rates. * Assign here 64MHz to support 4Mbps. * * The value itself is not really used anywhere except baud * rate calculations, so we can mangle it as we wish.
*/
port->port.uartclk = 64 * HZ_PER_MHZ;
port->port.set_termios = serial8250_do_set_termios;
port->port.get_divisor = pci1xxxx_get_divisor;
port->port.set_divisor = pci1xxxx_set_divisor;
port->port.rs485_config = pci1xxxx_rs485_config;
port->port.rs485_supported = pci1xxxx_rs485_supported;
/* * C0 and later revisions support Burst operation. * RTS workaround in mctrl is applicable only to B0.
*/ if (rev >= 0xC0)
port->port.handle_irq = pci1xxxx_handle_irq; elseif (rev == 0xB0)
port->port.set_mctrl = pci1xxxx_set_mctrl;
ret = serial8250_pci_setup_port(pdev, port, 0, PORT_OFFSET * port_idx, 0); if (ret < 0) return ret;
staticunsignedint pci1xxxx_get_max_port(int subsys_dev)
{ unsignedint i = MAX_PORTS;
if (subsys_dev < ARRAY_SIZE(logical_to_physical_port_idx)) while (i--) { if (logical_to_physical_port_idx[subsys_dev][i] != -1) return logical_to_physical_port_idx[subsys_dev][i] + 1;
}
if (subsys_dev == PCI_SUBDEVICE_ID_EFAR_PCI11414) return4;
return1;
}
staticint pci1xxxx_logical_to_physical_port_translate(int subsys_dev, int port)
{ if (subsys_dev < ARRAY_SIZE(logical_to_physical_port_idx)) return logical_to_physical_port_idx[subsys_dev][port];
return logical_to_physical_port_idx[0][port];
}
staticint pci1xxxx_get_device_revision(struct pci1xxxx_8250 *priv)
{
u32 regval; int ret;
/* * DEV REV is a system register, HW Syslock bit * should be acquired before accessing the register
*/
ret = pci1xxxx_acquire_sys_lock(priv); if (ret) return ret;
MODULE_IMPORT_NS("SERIAL_8250_PCI");
MODULE_DESCRIPTION("Microchip Technology Inc. PCIe to UART module");
MODULE_AUTHOR("Kumaravel Thiagarajan <kumaravel.thiagarajan@microchip.com>");
MODULE_AUTHOR("Tharun Kumar P <tharunkumar.pasumarthi@microchip.com>");
MODULE_LICENSE("GPL");
Messung V0.5 in Prozent
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.18Bemerkung:
(vorverarbeitet am 2026-06-06)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.