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
next prev 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).