Commit 687911b3 authored by Matthew Howell's avatar Matthew Howell Committed by Greg Kroah-Hartman
Browse files

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: default avatarMatthew Howell <matthew.howell@sealevel.com>
Reviewed-by: default avatarAndy Shevchenko <andriy.shevchenkoa@linux.intel.com>
Link: https://lore.kernel.org/r/4b8ad8ab6728742464c4e048fdeecb2b40522aef.camel@sealevel.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 6c756af2
Loading
Loading
Loading
Loading
+44 −0
Original line number Diff line number Diff line
@@ -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)