On Fri, 13 Jan 2023, Sergey Organov wrote: > We perform soft reset in 2 places, slightly differently for no sufficient > reasons, so move more generic variant to a function, and re-use the code. > > Out of 2 repeat counters, 10 and 100, select 10, as the code works at > interrupts disabled, and in practice the reset happens immediately. > > Signed-off-by: Sergey Organov <sorganov@xxxxxxxxx> > --- > drivers/tty/serial/imx.c | 73 ++++++++++++++++++++-------------------- > 1 file changed, 37 insertions(+), 36 deletions(-) > > diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c > index 757825edb0cd..bf222d8568a9 100644 > --- a/drivers/tty/serial/imx.c > +++ b/drivers/tty/serial/imx.c > @@ -397,6 +397,39 @@ static void start_hrtimer_ms(struct hrtimer *hrt, unsigned long msec) > hrtimer_start(hrt, ms_to_ktime(msec), HRTIMER_MODE_REL); > } > > +/* called with port.lock taken and irqs off */ > +static void imx_uart_soft_reset(struct imx_port *sport) > +{ > + int i = 10; > + u32 ucr2, ubir, ubmr, uts; > + > + /* > + * According to the Reference Manual description of the UART SRST bit: > + * > + * "Reset the transmit and receive state machines, > + * all FIFOs and register USR1, USR2, UBIR, UBMR, UBRC, URXD, UTXD > + * and UTS[6-3]". > + * > + * We don't need to restore the old values from USR1, USR2, URXD and > + * UTXD. UBRC is read only, so only save/restore the other three > + * registers. > + */ > + ubir = imx_uart_readl(sport, UBIR); > + ubmr = imx_uart_readl(sport, UBMR); > + uts = imx_uart_readl(sport, IMX21_UTS); > + > + ucr2 = imx_uart_readl(sport, UCR2); > + imx_uart_writel(sport, ucr2 & ~UCR2_SRST, UCR2); > + > + while (!(imx_uart_readl(sport, UCR2) & UCR2_SRST) && (--i > 0)) > + udelay(1); This could use read_poll_timeout_atomic(). -- i. > + /* Restore the registers */ > + imx_uart_writel(sport, ubir, UBIR); > + imx_uart_writel(sport, ubmr, UBMR); > + imx_uart_writel(sport, uts, IMX21_UTS); > +} > + > /* called with port.lock taken and irqs off */ > static void imx_uart_start_rx(struct uart_port *port) > { > @@ -1398,7 +1431,7 @@ static void imx_uart_disable_dma(struct imx_port *sport) > static int imx_uart_startup(struct uart_port *port) > { > struct imx_port *sport = (struct imx_port *)port; > - int retval, i; > + int retval; > unsigned long flags; > int dma_is_inited = 0; > u32 ucr1, ucr2, ucr3, ucr4, uts; > @@ -1430,15 +1463,9 @@ static int imx_uart_startup(struct uart_port *port) > dma_is_inited = 1; > > spin_lock_irqsave(&sport->port.lock, flags); > + > /* Reset fifo's and state machines */ > - i = 100; > - > - ucr2 = imx_uart_readl(sport, UCR2); > - ucr2 &= ~UCR2_SRST; > - imx_uart_writel(sport, ucr2, UCR2); > - > - while (!(imx_uart_readl(sport, UCR2) & UCR2_SRST) && (--i > 0)) > - udelay(1); > + imx_uart_soft_reset(sport); > > /* > * Finally, clear and enable interrupts > @@ -1593,8 +1620,6 @@ static void imx_uart_flush_buffer(struct uart_port *port) > { > struct imx_port *sport = (struct imx_port *)port; > struct scatterlist *sgl = &sport->tx_sgl[0]; > - u32 ucr2; > - int i = 100, ubir, ubmr, uts; > > if (!sport->dma_chan_tx) > return; > @@ -1612,32 +1637,8 @@ static void imx_uart_flush_buffer(struct uart_port *port) > sport->dma_is_txing = 0; > } > > - /* > - * According to the Reference Manual description of the UART SRST bit: > - * > - * "Reset the transmit and receive state machines, > - * all FIFOs and register USR1, USR2, UBIR, UBMR, UBRC, URXD, UTXD > - * and UTS[6-3]". > - * > - * We don't need to restore the old values from USR1, USR2, URXD and > - * UTXD. UBRC is read only, so only save/restore the other three > - * registers. > - */ > - ubir = imx_uart_readl(sport, UBIR); > - ubmr = imx_uart_readl(sport, UBMR); > - uts = imx_uart_readl(sport, IMX21_UTS); > + imx_uart_soft_reset(sport); > > - ucr2 = imx_uart_readl(sport, UCR2); > - ucr2 &= ~UCR2_SRST; > - imx_uart_writel(sport, ucr2, UCR2); > - > - while (!(imx_uart_readl(sport, UCR2) & UCR2_SRST) && (--i > 0)) > - udelay(1); > - > - /* Restore the registers */ > - imx_uart_writel(sport, ubir, UBIR); > - imx_uart_writel(sport, ubmr, UBMR); > - imx_uart_writel(sport, uts, IMX21_UTS); > } > > static void >