linux-serial.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Wolfram Sang <w.sang@pengutronix.de>
To: linux-serial@vger.kernel.org
Cc: linux-kernel@vger.kernel.org, Greg KH <gregkh@suse.de>,
	Alan Cox <alan@linux.intel.com>,
	Claudio Scordino <claudio@evidence.eu.com>,
	Wolfram Sang <w.sang@pengutronix.de>,
	Juergen Beisert <jbe@pengutronix.de>
Subject: [PATCH RESEND 7/8] serial: 8250: add Exar 16V2750 support
Date: Fri,  9 Dec 2011 18:07:19 +0100	[thread overview]
Message-ID: <1323450440-414-8-git-send-email-w.sang@pengutronix.de> (raw)
In-Reply-To: <1323450440-414-1-git-send-email-w.sang@pengutronix.de>

This variant can select the polarity of RTS# when TX is active with
RS485. Add code to support that, too.

Signed-off-by: Juergen Beisert <jbe@pengutronix.de>
Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
---
 drivers/tty/serial/8250.c   |   51 +++++++++++++++++++++++++++++++++++++------
 include/linux/serial_core.h |    3 +-
 include/linux/serial_reg.h  |    1 +
 3 files changed, 47 insertions(+), 8 deletions(-)

diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c
index 8cf6d76..5039e60 100644
--- a/drivers/tty/serial/8250.c
+++ b/drivers/tty/serial/8250.c
@@ -247,6 +247,13 @@ static const struct serial8250_config uart_config[] = {
 				  UART_FCR_T_TRIG_10,
 		.flags		= UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
 	},
+	[PORT_16V2750] = {
+		.name		= "XR16V2750",
+		.fifo_size	= 64,
+		.tx_loadsz	= 32,
+		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+		.flags		= UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
+	},
 	[PORT_16850] = {
 		.name		= "XR16850",
 		.fifo_size	= 128,
@@ -838,6 +845,7 @@ static void autoconfig_has_efr(struct uart_8250_port *up)
 	 * We check for a XR16C850 by setting DLL and DLM to 0, and then
 	 * reading back DLL and DLM.  The chip type depends on the DLM
 	 * value read back:
+	 *  0x0a - XR16V2750
 	 *  0x10 - XR16C850 and the DLL contains the chip revision.
 	 *  0x12 - XR16C2850.
 	 *  0x14 - XR16C854.
@@ -850,6 +858,10 @@ static void autoconfig_has_efr(struct uart_8250_port *up)
 		up->port.type = PORT_16850;
 		return;
 	}
+	if (id2 == 0x0a) {
+		up->port.type = PORT_16V2750;
+		return;
+	}
 
 	/*
 	 * It wasn't an XR16C850.
@@ -2060,7 +2072,7 @@ static int serial8250_startup(struct uart_port *port)
 	/*
 	 * For a XR16C850, we need to set the trigger levels
 	 */
-	if (up->port.type == PORT_16850) {
+	if (up->port.type == PORT_16850 || up->port.type == PORT_16V2750) {
 		unsigned char fctr;
 
 		serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
@@ -2726,9 +2738,9 @@ static int serial8250_ioctl_port(struct uart_port *port,
 	case TIOCSRS485:
 	{
 		struct serial_rs485 rs485ctrl;
-		unsigned char fctr, lcr;
+		unsigned char fctr, lcr, emsr;
 
-		if (port->type != PORT_16850)
+		if (port->type != PORT_16850 && port->type != PORT_16V2750)
 			return -ENOTTY;
 
 		if (copy_from_user(&rs485ctrl, (struct serial_rs485 *)arg,
@@ -2739,6 +2751,34 @@ static int serial8250_ioctl_port(struct uart_port *port,
 			return -EOPNOTSUPP;
 
 		spin_lock_irqsave(&up->port.lock, flags);
+		if (up->port.type == PORT_16V2750) {
+			/* make EMSR visible */
+			serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
+			fctr = serial_inp(up, UART_FCTR);
+			serial_outp(up, UART_FCTR, fctr | UART_FCTR_SCR_SWAP);
+			serial_outp(up, UART_LCR, 0);
+
+			/* set RTS polarity */
+			emsr = serial_inp(up, UART_EMSR) & ~UART_EMSR_RS485_INV;
+			if (rs485ctrl.flags & SER_RS485_RTS_ON_SEND) {
+				emsr |= UART_EMSR_RS485_INV;
+				rs485ctrl.flags &= ~SER_RS485_RTS_AFTER_SEND;
+			} else {
+				rs485ctrl.flags |= SER_RS485_RTS_AFTER_SEND;
+			}
+			serial_outp(up, UART_EMSR, emsr);
+
+			/* make the EMSR invisible */
+			serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
+			fctr = serial_inp(up, UART_FCTR) & ~UART_FCTR_SCR_SWAP;
+			serial_outp(up, UART_FCTR, fctr);
+			serial_outp(up, UART_LCR, 0);
+		} else {
+			/* only mode supported by the 16C850 */
+			rs485ctrl.flags &= ~SER_RS485_RTS_ON_SEND;
+			rs485ctrl.flags |= SER_RS485_RTS_AFTER_SEND;
+		}
+
 		lcr = serial_inp(up, UART_LCR);
 		serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
 		fctr = serial_inp(up, UART_FCTR);
@@ -2750,9 +2790,6 @@ static int serial8250_ioctl_port(struct uart_port *port,
 		serial_outp(up, UART_LCR, lcr);
 		spin_unlock_irqrestore(&up->port.lock, flags);
 
-		/* only mode supported by the 16C850 */
-		rs485ctrl.flags &= ~SER_RS485_RTS_ON_SEND;
-		rs485ctrl.flags |= SER_RS485_RTS_AFTER_SEND;
 		up->rs485_flags = rs485ctrl.flags;
 
 		return 0;
@@ -2762,7 +2799,7 @@ static int serial8250_ioctl_port(struct uart_port *port,
 	{
 		struct serial_rs485 rs485ctrl;
 
-		if (port->type != PORT_16850)
+		if (port->type != PORT_16850 && port->type != PORT_16V2750)
 			return -ENOTTY;
 
 		memset(&rs485ctrl, 0, sizeof(rs485ctrl));
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index eadf33d..72118c5 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -47,7 +47,8 @@
 #define PORT_U6_16550A	19	/* ST-Ericsson U6xxx internal UART */
 #define PORT_TEGRA	20	/* NVIDIA Tegra internal UART */
 #define PORT_XR17D15X	21	/* Exar XR17D15x UART */
-#define PORT_MAX_8250	21	/* max port ID */
+#define PORT_16V2750	22	/* Exar XR16V2750 */
+#define PORT_MAX_8250	22	/* max port ID */
 
 /*
  * ARM specific type numbers.  These are not currently guaranteed
diff --git a/include/linux/serial_reg.h b/include/linux/serial_reg.h
index fb37c4f..0267bab6 100644
--- a/include/linux/serial_reg.h
+++ b/include/linux/serial_reg.h
@@ -216,6 +216,7 @@
 #define UART_EMSR	7	/* Extended Mode Select Register */
 #define UART_EMSR_FIFO_COUNT	0x01  /* Rx/Tx select */
 #define UART_EMSR_ALT_COUNT	0x02  /* Alternating count select */
+#define UART_EMSR_RS485_INV	0x08  /* RS485 RTS output inversion */
 
 /*
  * The Intel XScale on-chip UARTs define these bits
-- 
1.7.7.3

  parent reply	other threads:[~2011-12-09 17:07 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-12-09 17:07 [PATCH RESEND 0/8] serial: 8250: support hw-based RS485 direction control Wolfram Sang
2011-12-09 17:07 ` [PATCH RESEND 1/8] serial: 8250: replace hardcoded 0xbf with #define Wolfram Sang
2011-12-09 18:58   ` Alan Cox
2011-12-09 17:07 ` [PATCH RESEND 2/8] serial: 8250: Add ioctl to enable auto rs485 mode with some Exar UARTs Wolfram Sang
2011-12-09 19:00   ` Alan Cox
2011-12-09 17:07 ` [PATCH RESEND 3/8] serial: 8250: save rs485_flags per instance Wolfram Sang
2011-12-09 19:10   ` Alan Cox
2011-12-09 17:07 ` [PATCH RESEND 4/8] serial: 8250: add RX_DURING_TX capability to RS485 mode Wolfram Sang
2011-12-09 17:07 ` [PATCH RESEND 5/8] serial: 8250: reject delaying RTS with RS485 Wolfram Sang
2011-12-09 17:07 ` [PATCH RESEND 6/8] serial: 8250: update rs485 flags with polarity settings Wolfram Sang
2011-12-09 19:13   ` Alan Cox
2011-12-09 17:07 ` Wolfram Sang [this message]
2011-12-09 17:07 ` [PATCH RESEND 8/8] serial: 8250: fix comment about accessing EMSR Wolfram Sang
2011-12-12 14:42 ` [PATCH RESEND 0/8] serial: 8250: support hw-based RS485 direction control Claudio Scordino

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1323450440-414-8-git-send-email-w.sang@pengutronix.de \
    --to=w.sang@pengutronix.de \
    --cc=alan@linux.intel.com \
    --cc=claudio@evidence.eu.com \
    --cc=gregkh@suse.de \
    --cc=jbe@pengutronix.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-serial@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).