* [PATCH 0/8] serial: 8250: support hw-based RS485 direction control (finally!)
@ 2011-11-16 16:24 Wolfram Sang
2011-11-16 16:24 ` [PATCH 1/8] serial: 8250: replace hardcoded 0xbf with #define Wolfram Sang
` (8 more replies)
0 siblings, 9 replies; 15+ messages in thread
From: Wolfram Sang @ 2011-11-16 16:24 UTC (permalink / raw)
To: linux-serial
Cc: linux-kernel, Alan Cox, Claudio Scordino, Juergen Beisert,
Matthias Fuchs, Wolfram Sang
Some 8250-variants control the direction pin for RS485 in hardware. Linux has
RS485 support these days, so update the 8250-driver to adhere to that. There
have been attempts for mainlining this before. So, I started with the version
from Matthias which got no further comments, a proof-of-concept for the 16V2750
from Jürgen, and reworked it to match the current state of RS485 in Linux. Some
minor cleanup patches came along the way. Really looking forward to
comments/tags, because I think it is really time to get this functionality into
mainline once and for all ;)
Code is based on 3.2-rc2, tested on a OMAP-based custom board with a 16V2750.
A git tree can be found here:
git://git.pengutronix.de/git/wsa/linux-2.6.git 8250_rs485
Thanks and regards,
Wolfram
Matthias Fuchs (1):
serial: 8250: Add ioctl to enable auto rs485 mode with some Exar UARTs
Wolfram Sang (7):
serial: 8250: replace hardcoded 0xbf with #define
serial: 8250: save rs485_flags per instance
serial: 8250: add RX_DURING_TX capability to RS485 mode
serial: 8250: reject delaying RTS with RS485
serial: 8250: update rs485 flags with polarity settings
serial: 8250: add Exar 16V2750 support
serial: 8250: fix comment about accessing EMSR
drivers/tty/serial/8250.c | 143 +++++++++++++++++++++++++++++++++++++++---
include/linux/serial_core.h | 3 +-
include/linux/serial_reg.h | 4 +-
3 files changed, 137 insertions(+), 13 deletions(-)
--
1.7.7.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 1/8] serial: 8250: replace hardcoded 0xbf with #define
2011-11-16 16:24 [PATCH 0/8] serial: 8250: support hw-based RS485 direction control (finally!) Wolfram Sang
@ 2011-11-16 16:24 ` Wolfram Sang
2011-11-16 16:24 ` [PATCH 2/8] serial: 8250: Add ioctl to enable auto rs485 mode with some Exar UARTs Wolfram Sang
` (7 subsequent siblings)
8 siblings, 0 replies; 15+ messages in thread
From: Wolfram Sang @ 2011-11-16 16:24 UTC (permalink / raw)
To: linux-serial
Cc: linux-kernel, Alan Cox, Claudio Scordino, Juergen Beisert,
Matthias Fuchs, Wolfram Sang
Makes it easier to find all occurences requesting CONF_MODE_B.
Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
---
drivers/tty/serial/8250.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c
index eeadf1b..f8f2320 100644
--- a/drivers/tty/serial/8250.c
+++ b/drivers/tty/serial/8250.c
@@ -2000,7 +2000,7 @@ static int serial8250_startup(struct uart_port *port)
serial_outp(up, UART_IER, 0);
serial_outp(up, UART_LCR, 0);
serial_icr_write(up, UART_CSR, 0); /* Reset the UART */
- serial_outp(up, UART_LCR, 0xBF);
+ serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
serial_outp(up, UART_EFR, UART_EFR_ECB);
serial_outp(up, UART_LCR, 0);
}
--
1.7.7.1
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 2/8] serial: 8250: Add ioctl to enable auto rs485 mode with some Exar UARTs
2011-11-16 16:24 [PATCH 0/8] serial: 8250: support hw-based RS485 direction control (finally!) Wolfram Sang
2011-11-16 16:24 ` [PATCH 1/8] serial: 8250: replace hardcoded 0xbf with #define Wolfram Sang
@ 2011-11-16 16:24 ` Wolfram Sang
2011-11-17 9:40 ` Claudio Scordino
2011-11-16 16:24 ` [PATCH 3/8] serial: 8250: save rs485_flags per instance Wolfram Sang
` (6 subsequent siblings)
8 siblings, 1 reply; 15+ messages in thread
From: Wolfram Sang @ 2011-11-16 16:24 UTC (permalink / raw)
To: linux-serial
Cc: linux-kernel, Alan Cox, Claudio Scordino, Juergen Beisert,
Matthias Fuchs, Wolfram Sang
From: Matthias Fuchs <mfuchs@ma-fu.de>
Some Exar UARTs support an auto rs485 mode. In this mode
the UART's RTS# pin is activated during transmitting and
can be used to enable a rs485 line driver. This has nothing
to do with attempts to do this by manually asserting/
deasserting handshake lines in software.
Signed-off-by: Matthias Fuchs <mfuchs@ma-fu.de>
[wsa] Replaced 0xbf with define, saved some line-breaks.
Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
---
drivers/tty/serial/8250.c | 68 ++++++++++++++++++++++++++++++++++++++++++++
include/linux/serial_reg.h | 1 +
2 files changed, 69 insertions(+), 0 deletions(-)
diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c
index f8f2320..920b4df 100644
--- a/drivers/tty/serial/8250.c
+++ b/drivers/tty/serial/8250.c
@@ -38,6 +38,7 @@
#include <linux/nmi.h>
#include <linux/mutex.h>
#include <linux/slab.h>
+#include <linux/uaccess.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -2698,6 +2699,72 @@ serial8250_type(struct uart_port *port)
return uart_config[type].name;
}
+static int serial8250_ioctl_port(struct uart_port *port,
+ unsigned int cmd, unsigned long arg)
+{
+ struct uart_8250_port *up = (struct uart_8250_port *)port;
+ unsigned long flags;
+
+ switch (cmd) {
+ case TIOCSRS485:
+ {
+ struct serial_rs485 rs485ctrl;
+ unsigned char fctr, lcr;
+
+ if (port->type != PORT_16850)
+ return -ENOTTY;
+
+ if (copy_from_user(&rs485ctrl, (struct serial_rs485 *)arg,
+ sizeof(rs485ctrl)))
+ return -EFAULT;
+
+ spin_lock_irqsave(&up->port.lock, flags);
+ lcr = serial_inp(up, UART_LCR);
+ serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
+ fctr = serial_inp(up, UART_FCTR);
+ if (rs485ctrl.flags & SER_RS485_ENABLED)
+ fctr |= UART_FCTR_RS485;
+ else
+ fctr &= ~UART_FCTR_RS485;
+ serial_outp(up, UART_FCTR, fctr);
+ serial_outp(up, UART_LCR, lcr);
+ spin_unlock_irqrestore(&up->port.lock, flags);
+ return 0;
+ }
+
+ case TIOCGRS485:
+ {
+ struct serial_rs485 rs485ctrl;
+ unsigned char lcr;
+
+ if (port->type != PORT_16850)
+ return -ENOTTY;
+
+ memset(&rs485ctrl, 0, sizeof(rs485ctrl));
+
+ spin_lock_irqsave(&up->port.lock, flags);
+ lcr = serial_inp(up, UART_LCR);
+ serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
+ if (serial_inp(up, UART_FCTR) & UART_FCTR_RS485)
+ rs485ctrl.flags = SER_RS485_ENABLED;
+ else
+ rs485ctrl.flags = 0;
+ serial_outp(up, UART_LCR, lcr);
+ spin_unlock_irqrestore(&up->port.lock, flags);
+
+ if (copy_to_user((struct serial_rs485 *)arg, &rs485ctrl,
+ sizeof(rs485ctrl)))
+ return -EFAULT;
+ return 0;
+ }
+
+ default:
+ return -ENOIOCTLCMD;
+ }
+
+ return 0;
+}
+
static struct uart_ops serial8250_pops = {
.tx_empty = serial8250_tx_empty,
.set_mctrl = serial8250_set_mctrl,
@@ -2717,6 +2784,7 @@ static struct uart_ops serial8250_pops = {
.request_port = serial8250_request_port,
.config_port = serial8250_config_port,
.verify_port = serial8250_verify_port,
+ .ioctl = serial8250_ioctl_port,
#ifdef CONFIG_CONSOLE_POLL
.poll_get_char = serial8250_get_poll_char,
.poll_put_char = serial8250_put_poll_char,
diff --git a/include/linux/serial_reg.h b/include/linux/serial_reg.h
index 8ce70d7..fb37c4f 100644
--- a/include/linux/serial_reg.h
+++ b/include/linux/serial_reg.h
@@ -201,6 +201,7 @@
#define UART_FCTR_RTS_8DELAY 0x03
#define UART_FCTR_IRDA 0x04 /* IrDa data encode select */
#define UART_FCTR_TX_INT 0x08 /* Tx interrupt type select */
+#define UART_FCTR_RS485 0x08 /* Auto RS485 mode */
#define UART_FCTR_TRGA 0x00 /* Tx/Rx 550 trigger table select */
#define UART_FCTR_TRGB 0x10 /* Tx/Rx 650 trigger table select */
#define UART_FCTR_TRGC 0x20 /* Tx/Rx 654 trigger table select */
--
1.7.7.1
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 3/8] serial: 8250: save rs485_flags per instance
2011-11-16 16:24 [PATCH 0/8] serial: 8250: support hw-based RS485 direction control (finally!) Wolfram Sang
2011-11-16 16:24 ` [PATCH 1/8] serial: 8250: replace hardcoded 0xbf with #define Wolfram Sang
2011-11-16 16:24 ` [PATCH 2/8] serial: 8250: Add ioctl to enable auto rs485 mode with some Exar UARTs Wolfram Sang
@ 2011-11-16 16:24 ` Wolfram Sang
2011-11-16 16:24 ` [PATCH 4/8] serial: 8250: add RX_DURING_TX capability to RS485 mode Wolfram Sang
` (5 subsequent siblings)
8 siblings, 0 replies; 15+ messages in thread
From: Wolfram Sang @ 2011-11-16 16:24 UTC (permalink / raw)
To: linux-serial
Cc: linux-kernel, Alan Cox, Claudio Scordino, Juergen Beisert,
Matthias Fuchs, Wolfram Sang
This avoids mangling with registers when reading the RS485 status via IOCTL.
Also, features can check their configuration at runtime which will be needed
for a later patch.
Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
---
drivers/tty/serial/8250.c | 16 +++++-----------
1 files changed, 5 insertions(+), 11 deletions(-)
diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c
index 920b4df..b5d3248 100644
--- a/drivers/tty/serial/8250.c
+++ b/drivers/tty/serial/8250.c
@@ -154,6 +154,7 @@ struct uart_8250_port {
unsigned char lsr_saved_flags;
#define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
unsigned char msr_saved_flags;
+ __u32 rs485_flags; /* copied from IOCTL */
};
struct irq_info {
@@ -2729,28 +2730,21 @@ static int serial8250_ioctl_port(struct uart_port *port,
serial_outp(up, UART_FCTR, fctr);
serial_outp(up, UART_LCR, lcr);
spin_unlock_irqrestore(&up->port.lock, flags);
+
+ up->rs485_flags = rs485ctrl.flags;
+
return 0;
}
case TIOCGRS485:
{
struct serial_rs485 rs485ctrl;
- unsigned char lcr;
if (port->type != PORT_16850)
return -ENOTTY;
memset(&rs485ctrl, 0, sizeof(rs485ctrl));
-
- spin_lock_irqsave(&up->port.lock, flags);
- lcr = serial_inp(up, UART_LCR);
- serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
- if (serial_inp(up, UART_FCTR) & UART_FCTR_RS485)
- rs485ctrl.flags = SER_RS485_ENABLED;
- else
- rs485ctrl.flags = 0;
- serial_outp(up, UART_LCR, lcr);
- spin_unlock_irqrestore(&up->port.lock, flags);
+ rs485ctrl.flags = up->rs485_flags;
if (copy_to_user((struct serial_rs485 *)arg, &rs485ctrl,
sizeof(rs485ctrl)))
--
1.7.7.1
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 4/8] serial: 8250: add RX_DURING_TX capability to RS485 mode
2011-11-16 16:24 [PATCH 0/8] serial: 8250: support hw-based RS485 direction control (finally!) Wolfram Sang
` (2 preceding siblings ...)
2011-11-16 16:24 ` [PATCH 3/8] serial: 8250: save rs485_flags per instance Wolfram Sang
@ 2011-11-16 16:24 ` Wolfram Sang
2011-11-16 16:24 ` [PATCH 5/8] serial: 8250: reject delaying RTS with RS485 Wolfram Sang
` (4 subsequent siblings)
8 siblings, 0 replies; 15+ messages in thread
From: Wolfram Sang @ 2011-11-16 16:24 UTC (permalink / raw)
To: linux-serial
Cc: linux-kernel, Alan Cox, Claudio Scordino, Juergen Beisert,
Matthias Fuchs, Wolfram Sang
Signed-off-by: Juergen Beisert <jbe@pengutronix.de>
Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
---
drivers/tty/serial/8250.c | 34 +++++++++++++++++++++++++---------
1 files changed, 25 insertions(+), 9 deletions(-)
diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c
index b5d3248..6a2f47f 100644
--- a/drivers/tty/serial/8250.c
+++ b/drivers/tty/serial/8250.c
@@ -1304,6 +1304,26 @@ static void autoconfig_irq(struct uart_8250_port *up)
up->port.irq = (irq > 0) ? irq : 0;
}
+static void serial8250_stop_rx(struct uart_port *port)
+{
+ struct uart_8250_port *up =
+ container_of(port, struct uart_8250_port, port);
+
+ up->ier &= ~UART_IER_RLSI;
+ up->port.read_status_mask &= ~UART_LSR_DR;
+ serial_out(up, UART_IER, up->ier);
+}
+
+static void serial8250_start_rx(struct uart_port *port)
+{
+ struct uart_8250_port *up =
+ container_of(port, struct uart_8250_port, port);
+
+ up->ier |= UART_IER_RLSI;
+ up->port.read_status_mask |= UART_LSR_DR;
+ serial_out(up, UART_IER, up->ier);
+}
+
static inline void __stop_tx(struct uart_8250_port *p)
{
if (p->ier & UART_IER_THRI) {
@@ -1326,6 +1346,9 @@ static void serial8250_stop_tx(struct uart_port *port)
up->acr |= UART_ACR_TXDIS;
serial_icr_write(up, UART_ACR, up->acr);
}
+
+ if (!(up->rs485_flags & SER_RS485_RX_DURING_TX))
+ serial8250_start_rx(port);
}
static void transmit_chars(struct uart_8250_port *up);
@@ -1357,16 +1380,9 @@ static void serial8250_start_tx(struct uart_port *port)
up->acr &= ~UART_ACR_TXDIS;
serial_icr_write(up, UART_ACR, up->acr);
}
-}
-static void serial8250_stop_rx(struct uart_port *port)
-{
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
-
- up->ier &= ~UART_IER_RLSI;
- up->port.read_status_mask &= ~UART_LSR_DR;
- serial_out(up, UART_IER, up->ier);
+ if (!(up->rs485_flags & SER_RS485_RX_DURING_TX))
+ serial8250_stop_rx(port);
}
static void serial8250_enable_ms(struct uart_port *port)
--
1.7.7.1
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 5/8] serial: 8250: reject delaying RTS with RS485
2011-11-16 16:24 [PATCH 0/8] serial: 8250: support hw-based RS485 direction control (finally!) Wolfram Sang
` (3 preceding siblings ...)
2011-11-16 16:24 ` [PATCH 4/8] serial: 8250: add RX_DURING_TX capability to RS485 mode Wolfram Sang
@ 2011-11-16 16:24 ` Wolfram Sang
2011-11-17 9:43 ` Claudio Scordino
2011-11-16 16:24 ` [PATCH 6/8] serial: 8250: update rs485 flags with polarity settings Wolfram Sang
` (3 subsequent siblings)
8 siblings, 1 reply; 15+ messages in thread
From: Wolfram Sang @ 2011-11-16 16:24 UTC (permalink / raw)
To: linux-serial
Cc: linux-kernel, Alan Cox, Claudio Scordino, Juergen Beisert,
Matthias Fuchs, Wolfram Sang
There might be chips capable of doing this, but for now nothing is implemented,
so reject usage of this feature.
Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
---
drivers/tty/serial/8250.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c
index 6a2f47f..28b3608 100644
--- a/drivers/tty/serial/8250.c
+++ b/drivers/tty/serial/8250.c
@@ -2735,6 +2735,9 @@ static int serial8250_ioctl_port(struct uart_port *port,
sizeof(rs485ctrl)))
return -EFAULT;
+ if (rs485ctrl.delay_rts_before_send || rs485ctrl.delay_rts_after_send)
+ return -EOPNOTSUPP;
+
spin_lock_irqsave(&up->port.lock, flags);
lcr = serial_inp(up, UART_LCR);
serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
--
1.7.7.1
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 6/8] serial: 8250: update rs485 flags with polarity settings
2011-11-16 16:24 [PATCH 0/8] serial: 8250: support hw-based RS485 direction control (finally!) Wolfram Sang
` (4 preceding siblings ...)
2011-11-16 16:24 ` [PATCH 5/8] serial: 8250: reject delaying RTS with RS485 Wolfram Sang
@ 2011-11-16 16:24 ` Wolfram Sang
2011-11-16 16:24 ` [PATCH 7/8] serial: 8250: add Exar 16V2750 support Wolfram Sang
` (2 subsequent siblings)
8 siblings, 0 replies; 15+ messages in thread
From: Wolfram Sang @ 2011-11-16 16:24 UTC (permalink / raw)
To: linux-serial
Cc: linux-kernel, Alan Cox, Claudio Scordino, Juergen Beisert,
Matthias Fuchs, Wolfram Sang
Report the only mode we can support with the 16C850.
Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
---
drivers/tty/serial/8250.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c
index 28b3608..8cf6d76 100644
--- a/drivers/tty/serial/8250.c
+++ b/drivers/tty/serial/8250.c
@@ -2750,6 +2750,9 @@ 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;
--
1.7.7.1
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 7/8] serial: 8250: add Exar 16V2750 support
2011-11-16 16:24 [PATCH 0/8] serial: 8250: support hw-based RS485 direction control (finally!) Wolfram Sang
` (5 preceding siblings ...)
2011-11-16 16:24 ` [PATCH 6/8] serial: 8250: update rs485 flags with polarity settings Wolfram Sang
@ 2011-11-16 16:24 ` Wolfram Sang
2011-11-16 16:24 ` [PATCH 8/8] serial: 8250: fix comment about accessing EMSR Wolfram Sang
2011-11-23 15:03 ` [PATCH 0/8] serial: 8250: support hw-based RS485 direction control (finally!) Wolfram Sang
8 siblings, 0 replies; 15+ messages in thread
From: Wolfram Sang @ 2011-11-16 16:24 UTC (permalink / raw)
To: linux-serial
Cc: linux-kernel, Alan Cox, Claudio Scordino, Juergen Beisert,
Matthias Fuchs, Wolfram Sang
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.1
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 8/8] serial: 8250: fix comment about accessing EMSR
2011-11-16 16:24 [PATCH 0/8] serial: 8250: support hw-based RS485 direction control (finally!) Wolfram Sang
` (6 preceding siblings ...)
2011-11-16 16:24 ` [PATCH 7/8] serial: 8250: add Exar 16V2750 support Wolfram Sang
@ 2011-11-16 16:24 ` Wolfram Sang
2011-11-23 15:03 ` [PATCH 0/8] serial: 8250: support hw-based RS485 direction control (finally!) Wolfram Sang
8 siblings, 0 replies; 15+ messages in thread
From: Wolfram Sang @ 2011-11-16 16:24 UTC (permalink / raw)
To: linux-serial
Cc: linux-kernel, Alan Cox, Claudio Scordino, Juergen Beisert,
Matthias Fuchs, Wolfram Sang
All docs I checked do say LCR should NOT be 0xBF (16c850, 16c854,
16v2750). Fix it according to that, since the only usage of the register
currently implements the revised access method. If somebody later finds
a derivate which actually does need 0xBF to enable that register, we can
update the comment again with precise references.
Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
---
include/linux/serial_reg.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/include/linux/serial_reg.h b/include/linux/serial_reg.h
index 0267bab6..0a1beca 100644
--- a/include/linux/serial_reg.h
+++ b/include/linux/serial_reg.h
@@ -211,7 +211,7 @@
#define UART_FCTR_TX 0x80 /* Programmable trigger mode select */
/*
- * LCR=0xBF, FCTR[6]=1
+ * LCR!=0xBF (some docs say =0), FCTR[6]=1, XR16C85x
*/
#define UART_EMSR 7 /* Extended Mode Select Register */
#define UART_EMSR_FIFO_COUNT 0x01 /* Rx/Tx select */
--
1.7.7.1
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH 2/8] serial: 8250: Add ioctl to enable auto rs485 mode with some Exar UARTs
2011-11-16 16:24 ` [PATCH 2/8] serial: 8250: Add ioctl to enable auto rs485 mode with some Exar UARTs Wolfram Sang
@ 2011-11-17 9:40 ` Claudio Scordino
2011-11-17 10:09 ` Wolfram Sang
0 siblings, 1 reply; 15+ messages in thread
From: Claudio Scordino @ 2011-11-17 9:40 UTC (permalink / raw)
To: Wolfram Sang
Cc: linux-serial, linux-kernel, Alan Cox, Juergen Beisert,
Matthias Fuchs
Hi Wolfram,
Il 16/11/2011 17:24, Wolfram Sang ha scritto:
> From: Matthias Fuchs<mfuchs@ma-fu.de>
>
> Some Exar UARTs support an auto rs485 mode. In this mode
> the UART's RTS# pin is activated during transmitting and
> can be used to enable a rs485 line driver. This has nothing
> to do with attempts to do this by manually asserting/
> deasserting handshake lines in software.
>
> Signed-off-by: Matthias Fuchs<mfuchs@ma-fu.de>
>
> [wsa] Replaced 0xbf with define, saved some line-breaks.
>
> Signed-off-by: Wolfram Sang<w.sang@pengutronix.de>
> ---
> drivers/tty/serial/8250.c | 68 ++++++++++++++++++++++++++++++++++++++++++++
> include/linux/serial_reg.h | 1 +
> 2 files changed, 69 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c
> index f8f2320..920b4df 100644
> --- a/drivers/tty/serial/8250.c
> +++ b/drivers/tty/serial/8250.c
> @@ -38,6 +38,7 @@
> #include<linux/nmi.h>
> #include<linux/mutex.h>
> #include<linux/slab.h>
> +#include<linux/uaccess.h>
>
> #include<asm/io.h>
> #include<asm/irq.h>
> @@ -2698,6 +2699,72 @@ serial8250_type(struct uart_port *port)
> return uart_config[type].name;
> }
>
> +static int serial8250_ioctl_port(struct uart_port *port,
> + unsigned int cmd, unsigned long arg)
> +{
> + struct uart_8250_port *up = (struct uart_8250_port *)port;
> + unsigned long flags;
> +
> + switch (cmd) {
> + case TIOCSRS485:
> + {
> + struct serial_rs485 rs485ctrl;
> + unsigned char fctr, lcr;
> +
> + if (port->type != PORT_16850)
> + return -ENOTTY;
> +
> + if (copy_from_user(&rs485ctrl, (struct serial_rs485 *)arg,
> + sizeof(rs485ctrl)))
> + return -EFAULT;
> +
> + spin_lock_irqsave(&up->port.lock, flags);
> + lcr = serial_inp(up, UART_LCR);
> + serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
> + fctr = serial_inp(up, UART_FCTR);
> + if (rs485ctrl.flags& SER_RS485_ENABLED)
> + fctr |= UART_FCTR_RS485;
> + else
> + fctr&= ~UART_FCTR_RS485;
> + serial_outp(up, UART_FCTR, fctr);
> + serial_outp(up, UART_LCR, lcr);
> + spin_unlock_irqrestore(&up->port.lock, flags);
> + return 0;
> + }
> +
> + case TIOCGRS485:
> + {
> + struct serial_rs485 rs485ctrl;
> + unsigned char lcr;
> +
> + if (port->type != PORT_16850)
> + return -ENOTTY;
> +
> + memset(&rs485ctrl, 0, sizeof(rs485ctrl));
> +
> + spin_lock_irqsave(&up->port.lock, flags);
> + lcr = serial_inp(up, UART_LCR);
> + serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
> + if (serial_inp(up, UART_FCTR)& UART_FCTR_RS485)
> + rs485ctrl.flags = SER_RS485_ENABLED;
> + else
> + rs485ctrl.flags = 0;
This else branch may be removed, since the structure has been already memsetted to 0.
Claudio
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 5/8] serial: 8250: reject delaying RTS with RS485
2011-11-16 16:24 ` [PATCH 5/8] serial: 8250: reject delaying RTS with RS485 Wolfram Sang
@ 2011-11-17 9:43 ` Claudio Scordino
2011-11-17 10:14 ` Wolfram Sang
0 siblings, 1 reply; 15+ messages in thread
From: Claudio Scordino @ 2011-11-17 9:43 UTC (permalink / raw)
To: Wolfram Sang
Cc: linux-serial, linux-kernel, Alan Cox, Juergen Beisert,
Matthias Fuchs
Hi Wolfram,
Il 16/11/2011 17:24, Wolfram Sang ha scritto:
> There might be chips capable of doing this, but for now nothing is implemented,
> so reject usage of this feature.
The delay must not necessarily be done by hardware. The drivers/tty/serial/crisv10.c
driver, for example, delays through a msleep.
I don't know if having a software delay in this driver can make sense in some particular
circumstance.
Best regards,
Claudio
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/8] serial: 8250: Add ioctl to enable auto rs485 mode with some Exar UARTs
2011-11-17 9:40 ` Claudio Scordino
@ 2011-11-17 10:09 ` Wolfram Sang
0 siblings, 0 replies; 15+ messages in thread
From: Wolfram Sang @ 2011-11-17 10:09 UTC (permalink / raw)
To: Claudio Scordino
Cc: linux-serial, linux-kernel, Alan Cox, Juergen Beisert,
Matthias Fuchs
[-- Attachment #1: Type: text/plain, Size: 623 bytes --]
> > + if (serial_inp(up, UART_FCTR)& UART_FCTR_RS485)
> > + rs485ctrl.flags = SER_RS485_ENABLED;
> > + else
> > + rs485ctrl.flags = 0;
>
> This else branch may be removed, since the structure has been already memsetted to 0.
Correct, yet I didn't want to change Matthias' code, so reviewers can
skip this patch if they reviewed his old code already. Flag handling
will be handled different with the next patch anyway.
Thanks,
Wolfram
--
Pengutronix e.K. | Wolfram Sang |
Industrial Linux Solutions | http://www.pengutronix.de/ |
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 5/8] serial: 8250: reject delaying RTS with RS485
2011-11-17 9:43 ` Claudio Scordino
@ 2011-11-17 10:14 ` Wolfram Sang
0 siblings, 0 replies; 15+ messages in thread
From: Wolfram Sang @ 2011-11-17 10:14 UTC (permalink / raw)
To: Claudio Scordino
Cc: linux-serial, linux-kernel, Alan Cox, Juergen Beisert,
Matthias Fuchs
[-- Attachment #1: Type: text/plain, Size: 700 bytes --]
> The delay must not necessarily be done by hardware. The drivers/tty/serial/crisv10.c
> driver, for example, delays through a msleep.
>
> I don't know if having a software delay in this driver can make sense in some particular
> circumstance.
Uuuh, I would be against software delays for the same reason why we
don't accept software based direction switching: No guarantees. msleep()
might easily delay longer than what was requested. Or are delay_rts
values to be interpreted as "delay at least"?
Regards,
Wolfram
--
Pengutronix e.K. | Wolfram Sang |
Industrial Linux Solutions | http://www.pengutronix.de/ |
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 0/8] serial: 8250: support hw-based RS485 direction control (finally!)
2011-11-16 16:24 [PATCH 0/8] serial: 8250: support hw-based RS485 direction control (finally!) Wolfram Sang
` (7 preceding siblings ...)
2011-11-16 16:24 ` [PATCH 8/8] serial: 8250: fix comment about accessing EMSR Wolfram Sang
@ 2011-11-23 15:03 ` Wolfram Sang
2011-11-24 16:05 ` Claudio Scordino
8 siblings, 1 reply; 15+ messages in thread
From: Wolfram Sang @ 2011-11-23 15:03 UTC (permalink / raw)
To: linux-serial
Cc: linux-kernel, Alan Cox, Claudio Scordino, Juergen Beisert,
Matthias Fuchs
[-- Attachment #1: Type: text/plain, Size: 910 bytes --]
On Wed, Nov 16, 2011 at 05:24:37PM +0100, Wolfram Sang wrote:
> Some 8250-variants control the direction pin for RS485 in hardware. Linux has
> RS485 support these days, so update the 8250-driver to adhere to that. There
> have been attempts for mainlining this before. So, I started with the version
> from Matthias which got no further comments, a proof-of-concept for the 16V2750
> from Jürgen, and reworked it to match the current state of RS485 in Linux. Some
> minor cleanup patches came along the way. Really looking forward to
> comments/tags, because I think it is really time to get this functionality into
> mainline once and for all ;)
Ping. Claudio? What do you think? Matthias, are you still there?
Regards,
Wolfram
--
Pengutronix e.K. | Wolfram Sang |
Industrial Linux Solutions | http://www.pengutronix.de/ |
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 0/8] serial: 8250: support hw-based RS485 direction control (finally!)
2011-11-23 15:03 ` [PATCH 0/8] serial: 8250: support hw-based RS485 direction control (finally!) Wolfram Sang
@ 2011-11-24 16:05 ` Claudio Scordino
0 siblings, 0 replies; 15+ messages in thread
From: Claudio Scordino @ 2011-11-24 16:05 UTC (permalink / raw)
To: Wolfram Sang
Cc: linux-serial, linux-kernel, Alan Cox, Juergen Beisert,
Matthias Fuchs
Il 23/11/2011 16:03, Wolfram Sang ha scritto:
> On Wed, Nov 16, 2011 at 05:24:37PM +0100, Wolfram Sang wrote:
>> Some 8250-variants control the direction pin for RS485 in hardware. Linux has
>> RS485 support these days, so update the 8250-driver to adhere to that. There
>> have been attempts for mainlining this before. So, I started with the version
>> from Matthias which got no further comments, a proof-of-concept for the 16V2750
>> from Jürgen, and reworked it to match the current state of RS485 in Linux. Some
>> minor cleanup patches came along the way. Really looking forward to
>> comments/tags, because I think it is really time to get this functionality into
>> mainline once and for all ;)
>
> Ping. Claudio? What do you think?
Hi Wolfram,
sorry for the delay, but I'm very busy these days.
I noticed that some of your patches revert the changes made by the previous patches in the
same series. So I would have preferred having only one patch with the whole changes wrt to
the mainline.
However, I've understood that some of those patches come from a previous submission that you
preferred to not touch. And I can apply the whole series to check what are the actual changes,
so its' fine.
The RS485 part looks right.
I had a superficial look also at the rest of the code, and its seems OK too. But, honestly, I couldn't
find the time to read it carefully.
Best regards,
Claudio
--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2011-11-24 16:05 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-11-16 16:24 [PATCH 0/8] serial: 8250: support hw-based RS485 direction control (finally!) Wolfram Sang
2011-11-16 16:24 ` [PATCH 1/8] serial: 8250: replace hardcoded 0xbf with #define Wolfram Sang
2011-11-16 16:24 ` [PATCH 2/8] serial: 8250: Add ioctl to enable auto rs485 mode with some Exar UARTs Wolfram Sang
2011-11-17 9:40 ` Claudio Scordino
2011-11-17 10:09 ` Wolfram Sang
2011-11-16 16:24 ` [PATCH 3/8] serial: 8250: save rs485_flags per instance Wolfram Sang
2011-11-16 16:24 ` [PATCH 4/8] serial: 8250: add RX_DURING_TX capability to RS485 mode Wolfram Sang
2011-11-16 16:24 ` [PATCH 5/8] serial: 8250: reject delaying RTS with RS485 Wolfram Sang
2011-11-17 9:43 ` Claudio Scordino
2011-11-17 10:14 ` Wolfram Sang
2011-11-16 16:24 ` [PATCH 6/8] serial: 8250: update rs485 flags with polarity settings Wolfram Sang
2011-11-16 16:24 ` [PATCH 7/8] serial: 8250: add Exar 16V2750 support Wolfram Sang
2011-11-16 16:24 ` [PATCH 8/8] serial: 8250: fix comment about accessing EMSR Wolfram Sang
2011-11-23 15:03 ` [PATCH 0/8] serial: 8250: support hw-based RS485 direction control (finally!) Wolfram Sang
2011-11-24 16:05 ` Claudio Scordino
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).