From patchwork Mon Aug 15 14:28:15 2011
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
X-Patchwork-Submitter: Bernhard Roth
X-Patchwork-Id: 1067882
Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134])
by demeter1.kernel.org (8.14.4/8.14.4) with ESMTP id p7FEc6LX029335
(version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO)
for ;
Mon, 15 Aug 2011 14:38:28 GMT
Received: from canuck.infradead.org ([2001:4978:20e::1])
by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux))
id 1QsyIf-0006qN-D2; Mon, 15 Aug 2011 14:37:57 +0000
Received: from localhost ([127.0.0.1] helo=canuck.infradead.org)
by canuck.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux))
id 1QsyIe-000385-U6; Mon, 15 Aug 2011 14:37:56 +0000
Received: from relay1.orceo.com ([62.245.254.100])
by canuck.infradead.org with smtp (Exim 4.76 #1 (Red Hat Linux))
id 1QsyIb-00037m-6j for linux-arm-kernel@lists.infradead.org;
Mon, 15 Aug 2011 14:37:54 +0000
Received: (qmail 30041 invoked from network); 15 Aug 2011 14:31:08 -0000
Received: from unknown (HELO ?10.2.11.13?) (br@pwrnet.de@10.2.11.13)
by mail.pub.muc1.orceo.net with SMTP; 15 Aug 2011 14:31:08 -0000
Message-ID: <4E492CFF.7040905@pwrnet.de>
Date: Mon, 15 Aug 2011 16:28:15 +0200
From: Bernhard Roth
User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US;
rv:1.9.2.18) Gecko/20110617 Thunderbird/3.1.11
MIME-Version: 1.0
To: nicolas.ferre@atmel.com
Subject: [PATCH] atmel_serial: RS485: receiving enabled when sending data
X-CRM114-Version: 20090807-BlameThorstenAndJenny ( TRE 0.7.6 (BSD) )
MR-646709E3
X-CRM114-CacheID: sfid-20110815_103753_534541_5E502C35
X-CRM114-Status: GOOD ( 14.77 )
X-Spam-Score: 0.0 (/)
X-Spam-Report: SpamAssassin version 3.3.1 on canuck.infradead.org summary:
Content analysis details: (0.0 points)
pts rule name description
---- ----------------------
--------------------------------------------------
Cc: linux-arm-kernel@lists.infradead.org, claudio@evidence.eu.com,
linux-kernel@vger.kernel.org, linux-serial@vger.kernel.org
X-BeenThere: linux-arm-kernel@lists.infradead.org
X-Mailman-Version: 2.1.12
Precedence: list
List-Id:
List-Unsubscribe:
,
List-Archive:
List-Post:
List-Help:
List-Subscribe:
,
Sender: linux-arm-kernel-bounces@lists.infradead.org
Errors-To:
linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org
X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by
milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]);
Mon, 15 Aug 2011 14:38:28 +0000 (UTC)
Hello!
By default the atmel_serial driver in RS485 mode disables receiving data
until all data in the send buffer has been sent. This flag allows to
receive data even whilst sending data. This is very useful to
- check if the data has been sent correctly over the RS485 bus
- assure that no collision happened
- check for short circuits/termination issues on the RS485 bus
Usually this functionality is realized by hardware, wether controlling
the RX-Enable pin of the RS485 transceiver with RTS (driver control
signal) or pulling it LOW permanently. The present atmel_serial driver
makes this impossible, thus requiring following patch.
Usage example:
struct serial_rs485 rs485;
memset(&rs485, 0, sizeof(rs485));
rs485.flags = SER_RS485_ENABLED | SER_RS485_RX_DURING_TX;
ioctl(fd, TIOCSRS485, &rs485);
atmel_serial: RS485: receiving enabled when sending data
By default the atmel_serial driver in RS485 mode disables receiving data
until
all data in the send buffer has been sent. This flag allows to receive data
even whilst sending data.
Signed-off-by: Bernhard Roth
Signed-off-by: Claudio Scordino
---
drivers/tty/serial/atmel_serial.c | 17 ++++++++++-------
include/linux/serial.h | 1 +
2 files changed, 11 insertions(+), 7 deletions(-)
diff --git a/drivers/tty/serial/atmel_serial.c
b/drivers/tty/serial/atmel_serial.c
index af9b781..5f6c745 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -339,8 +339,9 @@ static void atmel_stop_tx(struct uart_port *port)
/* Disable interrupts */
UART_PUT_IDR(port, atmel_port->tx_done_mask);
- if (atmel_port->rs485.flags & SER_RS485_ENABLED)
- atmel_start_rx(port);
+ if ((atmel_port->rs485.flags & SER_RS485_ENABLED) &&
+ !(atmel_port->rs485.flags & SER_RS485_RX_DURING_TX))
+ atmel_start_rx(port);
}
/*
@@ -356,8 +357,9 @@ static void atmel_start_tx(struct uart_port *port)
really need this.*/
return;
- if (atmel_port->rs485.flags & SER_RS485_ENABLED)
- atmel_stop_rx(port);
+ if ((atmel_port->rs485.flags & SER_RS485_ENABLED) &&
+ !(atmel_port->rs485.flags & SER_RS485_RX_DURING_TX))
+ atmel_stop_rx(port);
/* re-enable PDC transmit */
UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);
@@ -680,9 +682,10 @@ static void atmel_tx_dma(struct uart_port *port)
/* Enable interrupts */
UART_PUT_IER(port, atmel_port->tx_done_mask);
} else {
- if (atmel_port->rs485.flags & SER_RS485_ENABLED) {
- /* DMA done, stop TX, start RX for RS485 */
- atmel_start_rx(port);
+ if ((atmel_port->rs485.flags & SER_RS485_ENABLED) &&
+ !(atmel_port->rs485.flags & SER_RS485_RX_DURING_TX)) {
+ /* DMA done, stop TX, start RX for RS485 */
+ atmel_start_rx(port);
}
}
diff --git a/include/linux/serial.h b/include/linux/serial.h
index ef91406..97ff8e2 100644
--- a/include/linux/serial.h
+++ b/include/linux/serial.h
@@ -211,6 +211,7 @@ struct serial_rs485 {
#define SER_RS485_RTS_ON_SEND (1 << 1)
#define SER_RS485_RTS_AFTER_SEND (1 << 2)
#define SER_RS485_RTS_BEFORE_SEND (1 << 3)
+#define SER_RS485_RX_DURING_TX (1 << 4)
__u32 delay_rts_before_send; /* Milliseconds */
__u32 delay_rts_after_send; /* Milliseconds */
__u32 padding[5]; /* Memory is cheap, new structs