serial: fsl_lpuart: add loopback support
authorMichael Walle <michael@walle.cc>
Wed, 12 May 2021 14:12:54 +0000 (16:12 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 13 May 2021 14:08:26 +0000 (16:08 +0200)
The LPUART can loop the RX and TX signal. Add support for it.

Please note, this was only tested on the 32 bit version of the LPUART.

Signed-off-by: Michael Walle <michael@walle.cc>
Link: https://lore.kernel.org/r/20210512141255.18277-9-michael@walle.cc
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/tty/serial/fsl_lpuart.c

index 8957665..0d4eb02 100644 (file)
@@ -1403,22 +1403,54 @@ static int lpuart32_config_rs485(struct uart_port *port,
 
 static unsigned int lpuart_get_mctrl(struct uart_port *port)
 {
-       return 0;
+       unsigned int mctrl = 0;
+       u8 reg;
+
+       reg = readb(port->membase + UARTCR1);
+       if (reg & UARTCR1_LOOPS)
+               mctrl |= TIOCM_LOOP;
+
+       return mctrl;
 }
 
 static unsigned int lpuart32_get_mctrl(struct uart_port *port)
 {
-       return 0;
+       unsigned int mctrl = 0;
+       u32 reg;
+
+       reg = lpuart32_read(port, UARTCTRL);
+       if (reg & UARTCTRL_LOOPS)
+               mctrl |= TIOCM_LOOP;
+
+       return mctrl;
 }
 
 static void lpuart_set_mctrl(struct uart_port *port, unsigned int mctrl)
 {
+       u8 reg;
+
+       reg = readb(port->membase + UARTCR1);
+
+       /* for internal loopback we need LOOPS=1 and RSRC=0 */
+       reg &= ~(UARTCR1_LOOPS | UARTCR1_RSRC);
+       if (mctrl & TIOCM_LOOP)
+               reg |= UARTCR1_LOOPS;
 
+       writeb(reg, port->membase + UARTCR1);
 }
 
 static void lpuart32_set_mctrl(struct uart_port *port, unsigned int mctrl)
 {
+       u32 reg;
+
+       reg = lpuart32_read(port, UARTCTRL);
+
+       /* for internal loopback we need LOOPS=1 and RSRC=0 */
+       reg &= ~(UARTCTRL_LOOPS | UARTCTRL_RSRC);
+       if (mctrl & TIOCM_LOOP)
+               reg |= UARTCTRL_LOOPS;
 
+       lpuart32_write(port, reg, UARTCTRL);
 }
 
 static void lpuart_break_ctl(struct uart_port *port, int break_state)