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:
parent
6c756af23b
commit
687911b37e
@ -77,6 +77,9 @@
|
|||||||
|
|
||||||
#define UART_EXAR_RS485_DLY(x) ((x) << 4)
|
#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:
|
* IOT2040 MPIO wiring semantics:
|
||||||
*
|
*
|
||||||
@ -438,6 +441,44 @@ static int generic_rs485_config(struct uart_port *port, struct ktermios *termios
|
|||||||
return 0;
|
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 = {
|
static const struct serial_rs485 generic_rs485_supported = {
|
||||||
.flags = SER_RS485_ENABLED,
|
.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_config = platform->rs485_config;
|
||||||
port->port.rs485_supported = *(platform->rs485_supported);
|
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
|
* Setup the UART clock for the devices on expansion slot to
|
||||||
* half the clock speed of the main chip (which is 125MHz)
|
* half the clock speed of the main chip (which is 125MHz)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user