lkml.org 
[lkml]   [2022]   [Nov]   [23]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH AUTOSEL 5.4 04/15] serial: 8250: 8250_omap: Avoid RS485 RTS glitch on ->set_termios()
    Date
    From: Lukas Wunner <lukas@wunner.de>

    [ Upstream commit 038ee49fef18710bedd38b531d173ccd746b2d8d ]

    RS485-enabled UART ports on TI Sitara SoCs with active-low polarity
    exhibit a Transmit Enable glitch on ->set_termios():

    omap8250_restore_regs(), which is called from omap_8250_set_termios(),
    sets the TCRTLR bit in the MCR register and clears all other bits,
    including RTS. If RTS uses active-low polarity, it is now asserted
    for no reason.

    The TCRTLR bit is subsequently cleared by writing up->mcr to the MCR
    register. That variable is always zero, so the RTS bit is still cleared
    (incorrectly so if RTS is active-high).

    (up->mcr is not, as one might think, a cache of the MCR register's
    current value. Rather, it only caches a single bit of that register,
    the AFE bit. And it only does so if the UART supports the AFE bit,
    which OMAP does not. For details see serial8250_do_set_termios() and
    serial8250_do_set_mctrl().)

    Finally at the end of omap8250_restore_regs(), the MCR register is
    restored (and RTS deasserted) by a call to up->port.ops->set_mctrl()
    (which equals serial8250_set_mctrl()) and serial8250_em485_stop_tx().

    So there's an RTS glitch between setting TCRTLR and calling
    serial8250_em485_stop_tx(). Avoid by using a read-modify-write
    when setting TCRTLR.

    While at it, drop a redundant initialization of up->mcr. As explained
    above, the variable isn't used by the driver and it is already
    initialized to zero because it is part of the static struct
    serial8250_ports[] declared in 8250_core.c. (Static structs are
    initialized to zero per section 6.7.8 nr. 10 of the C99 standard.)

    Cc: Jan Kiszka <jan.kiszka@siemens.com>
    Cc: Su Bao Cheng <baocheng.su@siemens.com>
    Tested-by: Matthias Schiffer <matthias.schiffer@ew.tq-group.com>
    Signed-off-by: Lukas Wunner <lukas@wunner.de>
    Link: https://lore.kernel.org/r/6554b0241a2c7fd50f32576fdbafed96709e11e8.1664278942.git.lukas@wunner.de
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/tty/serial/8250/8250_omap.c | 7 ++++---
    1 file changed, 4 insertions(+), 3 deletions(-)

    diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
    index efe793a2fc65..f2a0ae49b143 100644
    --- a/drivers/tty/serial/8250/8250_omap.c
    +++ b/drivers/tty/serial/8250/8250_omap.c
    @@ -268,6 +268,7 @@ static void omap8250_restore_regs(struct uart_8250_port *up)
    {
    struct omap8250_priv *priv = up->port.private_data;
    struct uart_8250_dma *dma = up->dma;
    + u8 mcr = serial8250_in_MCR(up);

    if (dma && dma->tx_running) {
    /*
    @@ -284,7 +285,7 @@ static void omap8250_restore_regs(struct uart_8250_port *up)
    serial_out(up, UART_EFR, UART_EFR_ECB);

    serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
    - serial8250_out_MCR(up, UART_MCR_TCRTLR);
    + serial8250_out_MCR(up, mcr | UART_MCR_TCRTLR);
    serial_out(up, UART_FCR, up->fcr);

    omap8250_update_scr(up, priv);
    @@ -300,7 +301,8 @@ static void omap8250_restore_regs(struct uart_8250_port *up)
    serial_out(up, UART_LCR, 0);

    /* drop TCR + TLR access, we setup XON/XOFF later */
    - serial8250_out_MCR(up, up->mcr);
    + serial8250_out_MCR(up, mcr);
    +
    serial_out(up, UART_IER, up->ier);

    serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
    @@ -611,7 +613,6 @@ static int omap_8250_startup(struct uart_port *port)

    pm_runtime_get_sync(port->dev);

    - up->mcr = 0;
    serial_out(up, UART_FCR, UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);

    serial_out(up, UART_LCR, UART_LCR_WLEN8);
    --
    2.35.1
    \
     
     \ /
      Last update: 2022-11-23 13:55    [W:2.642 / U:0.024 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site