> -----Original Message----- > From: Jiri Slaby <jirislaby@xxxxxxxxxx> > Sent: Tuesday, March 11, 2025 11:45 AM > To: Sherry Sun <sherry.sun@xxxxxxx>; gregkh@xxxxxxxxxxxxxxxxxxx > Cc: linux-serial@xxxxxxxxxxxxxxx; linux-kernel@xxxxxxxxxxxxxxx; > imx@xxxxxxxxxxxxxxx; Shenwei Wang <shenwei.wang@xxxxxxx>; Frank Li > <frank.li@xxxxxxx> > Subject: Re: [PATCH V2] tty: serial: fsl_lpuart: disable transmitter before > changing RS485 related registers > > On 11. 03. 25, 3:55, Sherry Sun wrote: > > According to the LPUART reference manual, TXRTSE and TXRTSPOL of > MODIR > > register only can be changed when the transmitter is disabled. > > So disable the transmitter before changing RS485 related registers and > > re-enable it after the change is done. > > > > Fixes: 67b01837861c ("tty: serial: lpuart: Add RS485 support for > > 32-bit uart flavour") > > Signed-off-by: Sherry Sun <sherry.sun@xxxxxxx> > > Reviewed-by: Frank Li <Frank.Li@xxxxxxx> > > --- > > Changes in V2: > > 1. Add TE bit polling read to ensure TE is really become 0 before proceeding. > > 2. Add Reviewed-by tag. > > --- > > drivers/tty/serial/fsl_lpuart.c | 17 +++++++++++++++++ > > 1 file changed, 17 insertions(+) > > > > diff --git a/drivers/tty/serial/fsl_lpuart.c > > b/drivers/tty/serial/fsl_lpuart.c index 91d02c55c470..6b2f3a73a367 > > 100644 > > --- a/drivers/tty/serial/fsl_lpuart.c > > +++ b/drivers/tty/serial/fsl_lpuart.c > > @@ -1484,6 +1484,19 @@ static int lpuart32_config_rs485(struct > > uart_port *port, struct ktermios *termio > > > > unsigned long modem = lpuart32_read(&sport->port, UARTMODIR) > > & ~(UARTMODIR_TXRTSPOL | > UARTMODIR_TXRTSE); > > This is unrelated, but why is the above ulong? Hi Jiri, the following lpuart cleanup patch will change all the "unsigned long" type to the correct u32. > > > + u32 ctrl; > > + > > + /* TXRTSE and TXRTSPOL only can be changed when transmitter is > disabled. */ > > + ctrl = lpuart32_read(&sport->port, UARTCTRL); > > + if (ctrl & UARTCTRL_TE) { > > + /* wait transmit engin complete */ > > wait for the transmit engine to complete Thanks, will fix. > > > + lpuart32_wait_bit_set(&sport->port, UARTSTAT, > UARTSTAT_TC); > > Both this ^^ and: > > > + lpuart32_write(&sport->port, ctrl & ~UARTCTRL_TE, > UARTCTRL); > > + > > + while (lpuart32_read(&sport->port, UARTCTRL) & > UARTCTRL_TE) > > + cpu_relax(); > > this ^^ are unbound loops in case the hardware gets mad :(. > > Anyway, IIUC, after the TE clear from CTRL by the above write, the TE bit is > really cleared by the HW from CTRL only after it is really disabled, so has to be > checked? > > > + } > > + Description of TE bit in LPUART RM: "After this field becomes 0, the field reads 1 until the transmitter has completed the current character and the TXD pin is tristated". I also tried to read back the TE bit right after write 0, actually it didn't become 0 immediately, so I added the polling read here. You can check the discussion between Shenwei and me for more details. Thanks! https://lore.kernel.org/imx/20250307021950.1000221-1-sherry.sun@xxxxxxx/T/#m14098058b083333213bd74414095aa1ef3299780 Best Regards Sherry