[PATCH 1/2] serial: ns16550: add basic support for rs485
Pierre-Olivier Huard
pierre-olivier.huard at rtone.fr
Tue Feb 6 07:22:38 PST 2024
Add possibility to use RTS signal as a Data Enable signal on RS485
transceivers.
Signed-off-by: Pierre-Olivier Huard <pierre-olivier.huard at rtone.fr>
---
drivers/serial/serial_ns16550.c | 33 +++++++++++++++++++++++++++++++--
drivers/serial/serial_ns16550.h | 3 +++
2 files changed, 34 insertions(+), 2 deletions(-)
diff --git a/drivers/serial/serial_ns16550.c b/drivers/serial/serial_ns16550.c
index c3bc79adc2..73d8365dac 100644
--- a/drivers/serial/serial_ns16550.c
+++ b/drivers/serial/serial_ns16550.c
@@ -40,6 +40,9 @@ struct ns16550_priv {
void (*write_reg)(struct ns16550_priv *, uint8_t val, unsigned offset);
uint8_t (*read_reg)(struct ns16550_priv *, unsigned offset);
const char *access_type;
+
+ bool rs485_mode;
+ bool rs485_rts_active_low;
};
struct ns16550_drvdata {
@@ -265,9 +268,31 @@ static void rpi_init_port(struct console_device *cdev)
*/
static void ns16550_putc(struct console_device *cdev, char c)
{
- /* Loop Doing Nothing */
- while ((ns16550_read(cdev, lsr) & LSR_THRE) == 0) ;
+ struct ns16550_priv *priv = to_ns16550_priv(cdev);
+
+ /* wait until FIFO can accept at least one byte */
+ while ((ns16550_read(cdev, lsr) & (LSR_THRE)) != (LSR_THRE))
+ ;
+
+ if (priv->rs485_mode) {
+ if (priv->rs485_rts_active_low)
+ ns16550_write(cdev, MCR_RTS, mcr);
+ else
+ ns16550_write(cdev, 0, mcr);
+ }
+
ns16550_write(cdev, c, thr);
+
+ if (priv->rs485_mode) {
+ /* wait until FIFO is cleared*/
+ while ((ns16550_read(cdev, lsr) & (LSR_EMPTY)) != (LSR_EMPTY))
+ ;
+
+ if (priv->rs485_rts_active_low)
+ ns16550_write(cdev, 0, mcr);
+ else
+ ns16550_write(cdev, MCR_RTS, mcr);
+ }
}
/**
@@ -321,6 +346,10 @@ static void ns16550_probe_dt(struct device *dev, struct ns16550_priv *priv)
priv->mmiobase += offset;
of_property_read_u32(np, "reg-shift", &priv->plat.shift);
of_property_read_u32(np, "reg-io-width", &width);
+ priv->rs485_rts_active_low =
+ of_property_read_bool(np, "rs485-rts-active-low");
+ priv->rs485_mode =
+ of_property_read_bool(np, "linux,rs485-enabled-at-boot-time");
switch (width) {
case 1:
diff --git a/drivers/serial/serial_ns16550.h b/drivers/serial/serial_ns16550.h
index 56c639a134..1c5d9d551a 100644
--- a/drivers/serial/serial_ns16550.h
+++ b/drivers/serial/serial_ns16550.h
@@ -73,6 +73,9 @@
#define LSR_TEMT 0x40 /* Xmitter empty */
#define LSR_ERR 0x80 /* Error */
+/* Transmitter FIFO completely empty */
+#define LSR_EMPTY (LSR_THRE | LSR_TEMT)
+
/* useful defaults for LCR */
#define LCR_8N1 0x03
--
2.43.0
More information about the barebox
mailing list