diff mbox series

[1/8] serial: imx: factor-out common code to imx_uart_soft_reset()

Message ID 20230113184334.287130-2-sorganov@gmail.com (mailing list archive)
State New, archived
Headers show
Series serial: imx: work-around for hardware RX flood, and then isr improvements | expand

Commit Message

Sergey Organov Jan. 13, 2023, 6:43 p.m. UTC
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@gmail.com>
---
 drivers/tty/serial/imx.c | 73 ++++++++++++++++++++--------------------
 1 file changed, 37 insertions(+), 36 deletions(-)

Comments

Ilpo Järvinen Jan. 16, 2023, 10:30 a.m. UTC | #1
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@gmail.com>
> ---
>  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().
Sergey Organov Jan. 17, 2023, 1:42 p.m. UTC | #2
Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> writes:

> 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@gmail.com>
>> ---
>>  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().

As this is just a factor-out of existing code that uses the loop, I'm not
sure if it's a good idea to change this along the way.

Do you want me to add yet another patch to the series? I'd rather not,
as I won't be able to test it on my outdated kernel anyway.

Thanks,
-- Sergey Organov
diff mbox series

Patch

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);
+
+	/* 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