serial: exar: Add RS-485 support for Sealevel XR17V35X based cards

Sealevel XR17V35X based cards utilize DTR to control RS-485 Enable, but
the current implementation of 8250_exar uses RTS for the auto-RS485-Enable
mode of the XR17V35X UARTs. This patch implements DTR Auto-RS485 on
Sealevel cards.

Signed-off-by: Matthew Howell <matthew.howell@sealevel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenkoa@linux.intel.com>
Link: https://lore.kernel.org/r/4b8ad8ab6728742464c4e048fdeecb2b40522aef.camel@sealevel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Matthew Howell 2023-09-29 17:40:55 +00:00 committed by Greg Kroah-Hartman
parent 6c756af23b
commit 687911b37e

View file

@ -77,6 +77,9 @@
#define UART_EXAR_RS485_DLY(x) ((x) << 4)
#define UART_EXAR_DLD 0x02 /* Divisor Fractional */
#define UART_EXAR_DLD_485_POLARITY 0x80 /* RS-485 Enable Signal Polarity */
/*
* IOT2040 MPIO wiring semantics:
*
@ -438,6 +441,44 @@ static int generic_rs485_config(struct uart_port *port, struct ktermios *termios
return 0;
}
static int sealevel_rs485_config(struct uart_port *port, struct ktermios *termios,
struct serial_rs485 *rs485)
{
u8 __iomem *p = port->membase;
u8 old_lcr;
u8 efr;
u8 dld;
int ret;
ret = generic_rs485_config(port, termios, rs485);
if (ret)
return ret;
if (rs485->flags & SER_RS485_ENABLED) {
old_lcr = readb(p + UART_LCR);
/* Set EFR[4]=1 to enable enhanced feature registers */
efr = readb(p + UART_XR_EFR);
efr |= UART_EFR_ECB;
writeb(efr, p + UART_XR_EFR);
/* Set MCR to use DTR as Auto-RS485 Enable signal */
writeb(UART_MCR_OUT1, p + UART_MCR);
/* Set LCR[7]=1 to enable access to DLD register */
writeb(old_lcr | UART_LCR_DLAB, p + UART_LCR);
/* Set DLD[7]=1 for inverted RS485 Enable logic */
dld = readb(p + UART_EXAR_DLD);
dld |= UART_EXAR_DLD_485_POLARITY;
writeb(dld, p + UART_EXAR_DLD);
writeb(old_lcr, p + UART_LCR);
}
return 0;
}
static const struct serial_rs485 generic_rs485_supported = {
.flags = SER_RS485_ENABLED,
};
@ -559,6 +600,9 @@ pci_xr17v35x_setup(struct exar8250 *priv, struct pci_dev *pcidev,
port->port.rs485_config = platform->rs485_config;
port->port.rs485_supported = *(platform->rs485_supported);
if (pcidev->subsystem_vendor == PCI_VENDOR_ID_SEALEVEL)
port->port.rs485_config = sealevel_rs485_config;
/*
* Setup the UART clock for the devices on expansion slot to
* half the clock speed of the main chip (which is 125MHz)