RE: [PATCH v2] serial: imx: Fix imx_flush_buffer()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



> -----Original Message-----
> From: Fabio Estevam [mailto:fabio.estevam@xxxxxxxxxxxxx]
> Sent: Tuesday, January 13, 2015 8:00 PM
> To: gregkh@xxxxxxxxxxxxxxxxxxx
> Cc: Duan Fugang-B38611; Liu Hui-R64343; linux-serial@xxxxxxxxxxxxxxx;
> festevam@xxxxxxxxx; Estevam Fabio-R49496
> Subject: [PATCH v2] serial: imx: Fix imx_flush_buffer()
> 
> When running an userspace program that does a 'tcflush(fd, TCIOFLUSH)'
> call we still see the last received character in the URXD register
> afterwards.
> 
> Clear UCR2_SRST bit so that the UART FIFO is flushed properly.
> 
> Since UCR2_SRST also resets some UART registers, we need to save and
> restore some of them.
> 
> Signed-off-by: Fabio Estevam <fabio.estevam@xxxxxxxxxxxxx>

Looks good to me.

Acked-by: Jason Liu <r64343@xxxxxxxxxxxx>

> ---
> Changes since v1:
> - Improve the comment and explain that only 4 UART registers out of 8
> need to be saved/restored
> 
>  drivers/tty/serial/imx.c | 26 ++++++++++++++++++++++++++
>  1 file changed, 26 insertions(+)
> 
> diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index
> 59d9ef1..0eb29b1 100644
> --- a/drivers/tty/serial/imx.c
> +++ b/drivers/tty/serial/imx.c
> @@ -1320,6 +1320,7 @@ static void imx_flush_buffer(struct uart_port *port)
>  	struct imx_port *sport = (struct imx_port *)port;
>  	struct scatterlist *sgl = &sport->tx_sgl[0];
>  	unsigned long temp;
> +	int i = 100, ubir, ubmr, ubrc, uts;
> 
>  	if (!sport->dma_chan_tx)
>  		return;
> @@ -1334,6 +1335,31 @@ static void imx_flush_buffer(struct uart_port
> *port)
>  		writel(temp, sport->port.membase + UCR1);
>  		sport->dma_is_txing = false;
>  	}
> +
> +	/*
> +	 * 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]". As we don't need to restore the old values from
> +	 * USR1, USR2, URXD, UTXD, only save/restore the other four
> registers
> +	 */
> +	ubir = readl(sport->port.membase + UBIR);
> +	ubmr = readl(sport->port.membase + UBMR);
> +	ubrc = readl(sport->port.membase + UBRC);
> +	uts = readl(sport->port.membase + IMX21_UTS);
> +
> +	temp = readl(sport->port.membase + UCR2);
> +	temp &= ~UCR2_SRST;
> +	writel(temp, sport->port.membase + UCR2);
> +
> +	while (!(readl(sport->port.membase + UCR2) & UCR2_SRST) && (--i >
> 0))
> +		udelay(1);
> +
> +	/* Restore the registers */
> +	writel(ubir, sport->port.membase + UBIR);
> +	writel(ubmr, sport->port.membase + UBMR);
> +	writel(ubrc, sport->port.membase + UBRC);
> +	writel(uts, sport->port.membase + IMX21_UTS);
>  }
> 
>  static void
> --
> 1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux PPP]     [Linux FS]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Linmodem]     [Device Mapper]     [Linux Kernel for ARM]

  Powered by Linux