linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 00/23] LPUART fixes and improvements
@ 2019-07-31 17:30 Andrey Smirnov
  2019-07-31 17:30 ` [PATCH v2 01/23] tty: serial: fsl_lpuart: fix framing error handling when using DMA Andrey Smirnov
                   ` (23 more replies)
  0 siblings, 24 replies; 26+ messages in thread
From: Andrey Smirnov @ 2019-07-31 17:30 UTC (permalink / raw)
  To: linux-serial
  Cc: Andrey Smirnov, Stefan Agner, Chris Healy, Cory Tusar,
	Lucas Stach, Greg Kroah-Hartman, Jiri Slaby, linux-imx,
	linux-kernel

Everyone:

This series contains fixes/improvements to LPUART dirver I came up
with recently as well as fixes picked up from Toradex and NXP Vybrid
repos.

Feedback is welcome!

Changes since [v1]:

 - Dropped "tty: serial: fsl_lpuart: Drop unnecessary sg_set_buf()
   call" due to being a duplicate of "tty: serial: fsl_lpuart: remove
   sg_set_buf() for sport->rx_sgl"
   
 - Fixed build break in "tty: serial: fsl_lpuart: Introduce
   lpuart_tx_dma_startup()"

Thanks,
Andrey Smirnov


Andrey Smirnov (21):
  tty: serial: fsl_lpuart: Flush HW FIFOs in .flush_buffer
  tty: serial: fsl_lpuart: Simplify RX/TX IRQ handlers
  tty: serial: fsl_lpuart: Fix bogus indentation
  tty: serial: fsl_lpuart: Drop unnecessary uart_write_wakeup()
  tty: serial: fsl_lpuart: Fix issue in software flow control
  tty: serial: fls_lpuart: Split shared TX IRQ handler into two
  tty: serial: fsl_lpuart: Drop no-op bit opearation
  tty: serial: fsl_lpuart: Drop unnecessary extra parenthesis
  tty: serial: fsl_lpuart: Clear CSTOPB unconditionally
  tty: serial: fsl_lpuart: Use appropriate lpuart32_* I/O funcs
  tty: serial: fsl_lpuart: Introduce lpuart_wait_bit_set()
  tty: serial: fsl_lpuart: Use cpu_relax() instead of barrier()
  tty: serial: fsl_lpuart: Introduce lpuart_stopped_or_empty()
  tty: serial: fsl_lpuart: Drop unnecessary lpuart*_stop_tx()
  tty: serial: fsl_lpuart: Introduce lpuart_dma_shutdown()
  tty: serial: fsl_lpuart: Introduce lpuart_tx_dma_startup()
  tty: serial: fsl_lpuart: Introduce lpuart_rx_dma_startup()
  tty: serial: fsl_lpuart: Introduce lpuart32_configure()
  tty: serial: fsl_lpuart: Introduce lpuart*_setup_watermark_enable()
  tty: serial: fsl_lpuart: Don't enable TIE in .startup() or .resume()
  tty: serial: fsl_lpuart: Ignore TX/RX interrupts if DMA is enabled

Stefan Agner (2):
  tty: serial: fsl_lpuart: fix framing error handling when using DMA
  tty: serial: fsl_lpuart: flush receive FIFO after overruns

 drivers/tty/serial/fsl_lpuart.c | 493 +++++++++++++++++---------------
 1 file changed, 261 insertions(+), 232 deletions(-)

-- 
2.21.0


^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH v2 01/23] tty: serial: fsl_lpuart: fix framing error handling when using DMA
  2019-07-31 17:30 [PATCH v2 00/23] LPUART fixes and improvements Andrey Smirnov
@ 2019-07-31 17:30 ` Andrey Smirnov
  2019-07-31 17:30 ` [PATCH v2 02/23] tty: serial: fsl_lpuart: flush receive FIFO after overruns Andrey Smirnov
                   ` (22 subsequent siblings)
  23 siblings, 0 replies; 26+ messages in thread
From: Andrey Smirnov @ 2019-07-31 17:30 UTC (permalink / raw)
  To: linux-serial
  Cc: Stefan Agner, Max Krummenacher, Andrey Smirnov, Stefan Agner,
	Chris Healy, Cory Tusar, Lucas Stach, Greg Kroah-Hartman,
	Jiri Slaby, linux-imx, linux-kernel

From: Stefan Agner <stefan.agner@toradex.com>

When using DMA framing error get cleared properly. However, due
to the additional read from the data register, an underflow in
the receive FIFO buffer occurs (the FIFO pointer gets out of
sync).

Clear the FIFO in case an underflow has occurred. Also disable the
receiver during this operation and when reading the data register to
minimize potential interference.

Signed-off-by: Stefan Agner <stefan.agner@toradex.com>
Acked-by: Max Krummenacher <max.krummenacher@toradex.com>
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
Cc: Stefan Agner <stefan@agner.ch>
Cc: Chris Healy <cphealy@gmail.com>
Cc: Cory Tusar <cory.tusar@zii.aero>
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: linux-imx@nxp.com
Cc: linux-serial@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/tty/serial/fsl_lpuart.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index d15e65f88214..0643fa368d35 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -983,6 +983,13 @@ static void lpuart_copy_rx_to_tty(struct lpuart_port *sport)
 		unsigned char sr = readb(sport->port.membase + UARTSR1);
 
 		if (sr & (UARTSR1_PE | UARTSR1_FE)) {
+			unsigned char cr2;
+
+			/* Disable receiver during this operation... */
+			cr2 = readb(sport->port.membase + UARTCR2);
+			cr2 &= ~UARTCR2_RE;
+			writeb(cr2, sport->port.membase + UARTCR2);
+
 			/* Read DR to clear the error flags */
 			readb(sport->port.membase + UARTDR);
 
@@ -990,6 +997,25 @@ static void lpuart_copy_rx_to_tty(struct lpuart_port *sport)
 				sport->port.icount.parity++;
 			else if (sr & UARTSR1_FE)
 				sport->port.icount.frame++;
+			/*
+			 * At this point parity/framing error is
+			 * cleared However, since the DMA already read
+			 * the data register and we had to read it
+			 * again after reading the status register to
+			 * properly clear the flags, the FIFO actually
+			 * underflowed... This requires a clearing of
+			 * the FIFO...
+			 */
+			if (readb(sport->port.membase + UARTSFIFO) &
+			    UARTSFIFO_RXUF) {
+				writeb(UARTSFIFO_RXUF,
+				       sport->port.membase + UARTSFIFO);
+				writeb(UARTCFIFO_RXFLUSH,
+				       sport->port.membase + UARTCFIFO);
+			}
+
+			cr2 |= UARTCR2_RE;
+			writeb(cr2, sport->port.membase + UARTCR2);
 		}
 	}
 
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v2 02/23] tty: serial: fsl_lpuart: flush receive FIFO after overruns
  2019-07-31 17:30 [PATCH v2 00/23] LPUART fixes and improvements Andrey Smirnov
  2019-07-31 17:30 ` [PATCH v2 01/23] tty: serial: fsl_lpuart: fix framing error handling when using DMA Andrey Smirnov
@ 2019-07-31 17:30 ` Andrey Smirnov
  2019-07-31 17:30 ` [PATCH v2 03/23] tty: serial: fsl_lpuart: Flush HW FIFOs in .flush_buffer Andrey Smirnov
                   ` (21 subsequent siblings)
  23 siblings, 0 replies; 26+ messages in thread
From: Andrey Smirnov @ 2019-07-31 17:30 UTC (permalink / raw)
  To: linux-serial
  Cc: Stefan Agner, Max Krummenacher, Stefan Agner, Chris Healy,
	Cory Tusar, Lucas Stach, Greg Kroah-Hartman, Jiri Slaby,
	linux-imx, linux-kernel

From: Stefan Agner <stefan.agner@toradex.com>

After overruns the FIFO pointers become misaligned. This
typically shows by characters still being stuck in the FIFO
despite the empty flag being asserted. After the first
assertion of the overrun flag the empty flag still seems to
indicate FIFO state correctly and all data can be read.
However, after another overrun assertion the FIFO seems to
be off by one such that the last received character is still
in the FIFO (despite the empty flag being asserted).

Flushing the receive FIFO reinitializes pointers. Hence it
is recommended to flush the FIFO after overruns, see also:
https://community.nxp.com/thread/321175

Hence, on assertion of the overrun flag read the remaining
data from the FIFO and flush buffers.

Signed-off-by: Stefan Agner <stefan.agner@toradex.com>
Acked-by: Max Krummenacher <max.krummenacher@toradex.com>
Cc: Stefan Agner <stefan@agner.ch>
Cc: Chris Healy <cphealy@gmail.com>
Cc: Cory Tusar <cory.tusar@zii.aero>
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: linux-imx@nxp.com
Cc: linux-serial@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/tty/serial/fsl_lpuart.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 0643fa368d35..317bbc1dd2b4 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -799,7 +799,7 @@ static irqreturn_t lpuart_txint(int irq, void *dev_id)
 static irqreturn_t lpuart_rxint(int irq, void *dev_id)
 {
 	struct lpuart_port *sport = dev_id;
-	unsigned int flg, ignored = 0;
+	unsigned int flg, ignored = 0, overrun = 0;
 	struct tty_port *port = &sport->port.state->port;
 	unsigned long flags;
 	unsigned char rx, sr;
@@ -826,7 +826,7 @@ static irqreturn_t lpuart_rxint(int irq, void *dev_id)
 				sport->port.icount.frame++;
 
 			if (sr & UARTSR1_OR)
-				sport->port.icount.overrun++;
+				overrun++;
 
 			if (sr & sport->port.ignore_status_mask) {
 				if (++ignored > 100)
@@ -853,6 +853,17 @@ static irqreturn_t lpuart_rxint(int irq, void *dev_id)
 	}
 
 out:
+	if (overrun) {
+		sport->port.icount.overrun += overrun;
+
+		/*
+		 * Overruns cause FIFO pointers to become missaligned.
+		 * Flushing the receive FIFO reinitializes the pointers.
+		 */
+		writeb(UARTCFIFO_RXFLUSH, sport->port.membase + UARTCFIFO);
+		writeb(UARTSFIFO_RXOF, sport->port.membase + UARTSFIFO);
+	}
+
 	spin_unlock_irqrestore(&sport->port.lock, flags);
 
 	tty_flip_buffer_push(port);
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v2 03/23] tty: serial: fsl_lpuart: Flush HW FIFOs in .flush_buffer
  2019-07-31 17:30 [PATCH v2 00/23] LPUART fixes and improvements Andrey Smirnov
  2019-07-31 17:30 ` [PATCH v2 01/23] tty: serial: fsl_lpuart: fix framing error handling when using DMA Andrey Smirnov
  2019-07-31 17:30 ` [PATCH v2 02/23] tty: serial: fsl_lpuart: flush receive FIFO after overruns Andrey Smirnov
@ 2019-07-31 17:30 ` Andrey Smirnov
  2019-07-31 17:30 ` [PATCH v2 04/23] tty: serial: fsl_lpuart: Simplify RX/TX IRQ handlers Andrey Smirnov
                   ` (20 subsequent siblings)
  23 siblings, 0 replies; 26+ messages in thread
From: Andrey Smirnov @ 2019-07-31 17:30 UTC (permalink / raw)
  To: linux-serial
  Cc: Andrey Smirnov, Fugang Duan, Stefan Agner, Chris Healy,
	Cory Tusar, Lucas Stach, Greg Kroah-Hartman, Jiri Slaby,
	linux-imx, linux-kernel

Switching baud rate might cause bogus data to appear in HW
FIFO. Add code to do a HW FIFO flush to .flush_buffer callback to
avoid that.

Signed-off-by: Fugang Duan <fugang.duan@nxp.com>
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
Cc: Stefan Agner <stefan@agner.ch>
Cc: Chris Healy <cphealy@gmail.com>
Cc: Cory Tusar <cory.tusar@zii.aero>
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: linux-imx@nxp.com
Cc: linux-serial@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/tty/serial/fsl_lpuart.c | 23 +++++++++++++++++------
 1 file changed, 17 insertions(+), 6 deletions(-)

diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 317bbc1dd2b4..12ddca608eba 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -518,9 +518,16 @@ static int lpuart_dma_tx_request(struct uart_port *port)
 	return 0;
 }
 
+static bool lpuart_is_32(struct lpuart_port *sport)
+{
+	return sport->port.iotype == UPIO_MEM32 ||
+	       sport->port.iotype ==  UPIO_MEM32BE;
+}
+
 static void lpuart_flush_buffer(struct uart_port *port)
 {
 	struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
+	u32 val;
 
 	if (sport->lpuart_dma_tx_use) {
 		if (sport->dma_tx_in_progress) {
@@ -530,6 +537,16 @@ static void lpuart_flush_buffer(struct uart_port *port)
 		}
 		dmaengine_terminate_all(sport->dma_tx_chan);
 	}
+
+	if (lpuart_is_32(sport)) {
+		val = lpuart32_read(&sport->port, UARTFIFO);
+		val |= UARTFIFO_TXFLUSH | UARTFIFO_RXFLUSH;
+		lpuart32_write(&sport->port, val, UARTFIFO);
+	} else {
+		val = readb(sport->port.membase + UARTPFIFO);
+		val |= UARTCFIFO_TXFLUSH | UARTCFIFO_RXFLUSH;
+		writeb(val, sport->port.membase + UARTCFIFO);
+	}
 }
 
 #if defined(CONFIG_CONSOLE_POLL)
@@ -754,12 +771,6 @@ static unsigned int lpuart32_tx_empty(struct uart_port *port)
 	return 0;
 }
 
-static bool lpuart_is_32(struct lpuart_port *sport)
-{
-	return sport->port.iotype == UPIO_MEM32 ||
-	       sport->port.iotype ==  UPIO_MEM32BE;
-}
-
 static irqreturn_t lpuart_txint(int irq, void *dev_id)
 {
 	struct lpuart_port *sport = dev_id;
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v2 04/23] tty: serial: fsl_lpuart: Simplify RX/TX IRQ handlers
  2019-07-31 17:30 [PATCH v2 00/23] LPUART fixes and improvements Andrey Smirnov
                   ` (2 preceding siblings ...)
  2019-07-31 17:30 ` [PATCH v2 03/23] tty: serial: fsl_lpuart: Flush HW FIFOs in .flush_buffer Andrey Smirnov
@ 2019-07-31 17:30 ` Andrey Smirnov
  2019-07-31 17:30 ` [PATCH v2 05/23] tty: serial: fsl_lpuart: Fix bogus indentation Andrey Smirnov
                   ` (19 subsequent siblings)
  23 siblings, 0 replies; 26+ messages in thread
From: Andrey Smirnov @ 2019-07-31 17:30 UTC (permalink / raw)
  To: linux-serial
  Cc: Andrey Smirnov, Stefan Agner, Chris Healy, Cory Tusar,
	Lucas Stach, Greg Kroah-Hartman, Jiri Slaby, linux-imx,
	linux-kernel

It appears that lpuart_rxint, lpuart_txint and lpuart32_rxint were
modelled after identical function found in UART driver for
i.MX. However, while said functions are used as individual IRQ
handlers in i.MX driver (in case of i.MX1), it is not the case for
LPUART. Given that, there's no need for us to restrict the prototype
of the handler to irqreturn_t foo(int, void *) and we can drop all of
uneened boilerplate code by changing it void foo(struct lpuart_port *).

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
Cc: Stefan Agner <stefan@agner.ch>
Cc: Chris Healy <cphealy@gmail.com>
Cc: Cory Tusar <cory.tusar@zii.aero>
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: linux-imx@nxp.com
Cc: linux-serial@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/tty/serial/fsl_lpuart.c | 20 +++++++-------------
 1 file changed, 7 insertions(+), 13 deletions(-)

diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 12ddca608eba..c60c5354a5b9 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -771,9 +771,8 @@ static unsigned int lpuart32_tx_empty(struct uart_port *port)
 	return 0;
 }
 
-static irqreturn_t lpuart_txint(int irq, void *dev_id)
+static void lpuart_txint(struct lpuart_port *sport)
 {
-	struct lpuart_port *sport = dev_id;
 	struct circ_buf *xmit = &sport->port.state->xmit;
 	unsigned long flags;
 
@@ -804,12 +803,10 @@ static irqreturn_t lpuart_txint(int irq, void *dev_id)
 
 out:
 	spin_unlock_irqrestore(&sport->port.lock, flags);
-	return IRQ_HANDLED;
 }
 
-static irqreturn_t lpuart_rxint(int irq, void *dev_id)
+static void lpuart_rxint(struct lpuart_port *sport)
 {
-	struct lpuart_port *sport = dev_id;
 	unsigned int flg, ignored = 0, overrun = 0;
 	struct tty_port *port = &sport->port.state->port;
 	unsigned long flags;
@@ -878,12 +875,10 @@ static irqreturn_t lpuart_rxint(int irq, void *dev_id)
 	spin_unlock_irqrestore(&sport->port.lock, flags);
 
 	tty_flip_buffer_push(port);
-	return IRQ_HANDLED;
 }
 
-static irqreturn_t lpuart32_rxint(int irq, void *dev_id)
+static void lpuart32_rxint(struct lpuart_port *sport)
 {
-	struct lpuart_port *sport = dev_id;
 	unsigned int flg, ignored = 0;
 	struct tty_port *port = &sport->port.state->port;
 	unsigned long flags;
@@ -942,7 +937,6 @@ static irqreturn_t lpuart32_rxint(int irq, void *dev_id)
 	spin_unlock_irqrestore(&sport->port.lock, flags);
 
 	tty_flip_buffer_push(port);
-	return IRQ_HANDLED;
 }
 
 static irqreturn_t lpuart_int(int irq, void *dev_id)
@@ -953,10 +947,10 @@ static irqreturn_t lpuart_int(int irq, void *dev_id)
 	sts = readb(sport->port.membase + UARTSR1);
 
 	if (sts & UARTSR1_RDRF)
-		lpuart_rxint(irq, dev_id);
+		lpuart_rxint(sport);
 
 	if (sts & UARTSR1_TDRE)
-		lpuart_txint(irq, dev_id);
+		lpuart_txint(sport);
 
 	return IRQ_HANDLED;
 }
@@ -971,10 +965,10 @@ static irqreturn_t lpuart32_int(int irq, void *dev_id)
 	rxcount = rxcount >> UARTWATER_RXCNT_OFF;
 
 	if ((sts & UARTSTAT_RDRF || rxcount > 0) && !sport->lpuart_dma_rx_use)
-		lpuart32_rxint(irq, dev_id);
+		lpuart32_rxint(sport);
 
 	if ((sts & UARTSTAT_TDRE) && !sport->lpuart_dma_tx_use)
-		lpuart_txint(irq, dev_id);
+		lpuart_txint(sport);
 
 	lpuart32_write(&sport->port, sts, UARTSTAT);
 	return IRQ_HANDLED;
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v2 05/23] tty: serial: fsl_lpuart: Fix bogus indentation
  2019-07-31 17:30 [PATCH v2 00/23] LPUART fixes and improvements Andrey Smirnov
                   ` (3 preceding siblings ...)
  2019-07-31 17:30 ` [PATCH v2 04/23] tty: serial: fsl_lpuart: Simplify RX/TX IRQ handlers Andrey Smirnov
@ 2019-07-31 17:30 ` Andrey Smirnov
  2019-07-31 17:30 ` [PATCH v2 06/23] tty: serial: fsl_lpuart: Drop unnecessary uart_write_wakeup() Andrey Smirnov
                   ` (18 subsequent siblings)
  23 siblings, 0 replies; 26+ messages in thread
From: Andrey Smirnov @ 2019-07-31 17:30 UTC (permalink / raw)
  To: linux-serial
  Cc: Andrey Smirnov, Stefan Agner, Chris Healy, Cory Tusar,
	Lucas Stach, Greg Kroah-Hartman, Jiri Slaby, linux-imx,
	linux-kernel

Fix bogus indentation in rx_dma_timer_init().

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
Cc: Stefan Agner <stefan@agner.ch>
Cc: Chris Healy <cphealy@gmail.com>
Cc: Cory Tusar <cory.tusar@zii.aero>
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: linux-imx@nxp.com
Cc: linux-serial@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/tty/serial/fsl_lpuart.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index c60c5354a5b9..57c5825f5de7 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -1409,9 +1409,9 @@ static void lpuart32_setup_watermark(struct lpuart_port *sport)
 
 static void rx_dma_timer_init(struct lpuart_port *sport)
 {
-		timer_setup(&sport->lpuart_timer, lpuart_timer_func, 0);
-		sport->lpuart_timer.expires = jiffies + sport->dma_rx_timeout;
-		add_timer(&sport->lpuart_timer);
+	timer_setup(&sport->lpuart_timer, lpuart_timer_func, 0);
+	sport->lpuart_timer.expires = jiffies + sport->dma_rx_timeout;
+	add_timer(&sport->lpuart_timer);
 }
 
 static int lpuart_startup(struct uart_port *port)
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v2 06/23] tty: serial: fsl_lpuart: Drop unnecessary uart_write_wakeup()
  2019-07-31 17:30 [PATCH v2 00/23] LPUART fixes and improvements Andrey Smirnov
                   ` (4 preceding siblings ...)
  2019-07-31 17:30 ` [PATCH v2 05/23] tty: serial: fsl_lpuart: Fix bogus indentation Andrey Smirnov
@ 2019-07-31 17:30 ` Andrey Smirnov
  2019-07-31 17:30 ` [PATCH v2 07/23] tty: serial: fsl_lpuart: Fix issue in software flow control Andrey Smirnov
                   ` (17 subsequent siblings)
  23 siblings, 0 replies; 26+ messages in thread
From: Andrey Smirnov @ 2019-07-31 17:30 UTC (permalink / raw)
  To: linux-serial
  Cc: Andrey Smirnov, Stefan Agner, Chris Healy, Cory Tusar,
	Lucas Stach, Greg Kroah-Hartman, Jiri Slaby, linux-imx,
	linux-kernel

Uart_write_wakeup() will already be called as a part of
lpuart*_transmit_buffer() call, so there doesn't seem to be a reason
to call it again right after.

It also appears that second uart_write_wakeup() might potentially
cause unwanted write wakeup when transmitting an x_char. See commit
5e42e9a30cda ("serial: imx: Fix x_char handling and tx flow control")
where this problem was fixed in a very similarly structured i.MX UART
driver.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
Cc: Stefan Agner <stefan@agner.ch>
Cc: Chris Healy <cphealy@gmail.com>
Cc: Cory Tusar <cory.tusar@zii.aero>
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: linux-imx@nxp.com
Cc: linux-serial@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/tty/serial/fsl_lpuart.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 57c5825f5de7..c35f81df0cff 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -798,9 +798,6 @@ static void lpuart_txint(struct lpuart_port *sport)
 	else
 		lpuart_transmit_buffer(sport);
 
-	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-		uart_write_wakeup(&sport->port);
-
 out:
 	spin_unlock_irqrestore(&sport->port.lock, flags);
 }
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v2 07/23] tty: serial: fsl_lpuart: Fix issue in software flow control
  2019-07-31 17:30 [PATCH v2 00/23] LPUART fixes and improvements Andrey Smirnov
                   ` (5 preceding siblings ...)
  2019-07-31 17:30 ` [PATCH v2 06/23] tty: serial: fsl_lpuart: Drop unnecessary uart_write_wakeup() Andrey Smirnov
@ 2019-07-31 17:30 ` Andrey Smirnov
  2019-07-31 17:30 ` [PATCH v2 08/23] tty: serial: fls_lpuart: Split shared TX IRQ handler into two Andrey Smirnov
                   ` (16 subsequent siblings)
  23 siblings, 0 replies; 26+ messages in thread
From: Andrey Smirnov @ 2019-07-31 17:30 UTC (permalink / raw)
  To: linux-serial
  Cc: Andrey Smirnov, Stefan Agner, Chris Healy, Cory Tusar,
	Lucas Stach, Greg Kroah-Hartman, Jiri Slaby, linux-imx,
	linux-kernel

Although I haven't observed this bug in practice, it seems that the
code for handling x_char of LPUART is pretty much identical to that of
i.MX. So the fix found in commit 7e2fb5aa8d81 ("serial: imx: Fix issue
in software flow control"):

    serial: imx: Fix issue in software flow control

    After send out x_char in UART driver, x_char needs to be cleared
    by UART driver itself, otherwise data in TXFIFO can no longer be
    sent out.
    Also tx counter needs to be increased to keep track of correct
    number of transmitted data.

    Signed-off-by: Jiada Wang <jiada_wang@mentor.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

should apply here as well.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
Cc: Stefan Agner <stefan@agner.ch>
Cc: Chris Healy <cphealy@gmail.com>
Cc: Cory Tusar <cory.tusar@zii.aero>
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: linux-imx@nxp.com
Cc: linux-serial@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/tty/serial/fsl_lpuart.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index c35f81df0cff..8657addbfd1c 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -782,6 +782,8 @@ static void lpuart_txint(struct lpuart_port *sport)
 			lpuart32_write(&sport->port, sport->port.x_char, UARTDATA);
 		else
 			writeb(sport->port.x_char, sport->port.membase + UARTDR);
+		sport->port.icount.tx++;
+		sport->port.x_char = 0;
 		goto out;
 	}
 
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v2 08/23] tty: serial: fls_lpuart: Split shared TX IRQ handler into two
  2019-07-31 17:30 [PATCH v2 00/23] LPUART fixes and improvements Andrey Smirnov
                   ` (6 preceding siblings ...)
  2019-07-31 17:30 ` [PATCH v2 07/23] tty: serial: fsl_lpuart: Fix issue in software flow control Andrey Smirnov
@ 2019-07-31 17:30 ` Andrey Smirnov
  2019-07-31 17:30 ` [PATCH v2 09/23] tty: serial: fsl_lpuart: Drop no-op bit opearation Andrey Smirnov
                   ` (15 subsequent siblings)
  23 siblings, 0 replies; 26+ messages in thread
From: Andrey Smirnov @ 2019-07-31 17:30 UTC (permalink / raw)
  To: linux-serial
  Cc: Andrey Smirnov, Stefan Agner, Chris Healy, Cory Tusar,
	Lucas Stach, Greg Kroah-Hartman, Jiri Slaby, linux-imx,
	linux-kernel

While sharing code for Tx interrupt handler between 8 and 32 bit
variant of the peripheral saves a bit of code duplication it also adds
quite a number of lpuart_is_32() checks which makes it harder to
understand. Move shared bits back into corresponding
lpuart*_transmit_buffer functions, split lpuart_txint into
lpuart_txint and lpuart32_txint so we can drop all extra
lpuart_is_32() check and make the code flow more linear.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
Cc: Stefan Agner <stefan@agner.ch>
Cc: Chris Healy <cphealy@gmail.com>
Cc: Cory Tusar <cory.tusar@zii.aero>
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: linux-imx@nxp.com
Cc: linux-serial@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/tty/serial/fsl_lpuart.c | 61 +++++++++++++++++++--------------
 1 file changed, 35 insertions(+), 26 deletions(-)

diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 8657addbfd1c..ed6d3f836c93 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -663,6 +663,18 @@ static inline void lpuart_transmit_buffer(struct lpuart_port *sport)
 {
 	struct circ_buf *xmit = &sport->port.state->xmit;
 
+	if (sport->port.x_char) {
+		writeb(sport->port.x_char, sport->port.membase + UARTDR);
+		sport->port.icount.tx++;
+		sport->port.x_char = 0;
+		return;
+	}
+
+	if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) {
+		lpuart_stop_tx(&sport->port);
+		return;
+	}
+
 	while (!uart_circ_empty(xmit) &&
 		(readb(sport->port.membase + UARTTCFIFO) < sport->txfifo_size)) {
 		writeb(xmit->buf[xmit->tail], sport->port.membase + UARTDR);
@@ -682,6 +694,18 @@ static inline void lpuart32_transmit_buffer(struct lpuart_port *sport)
 	struct circ_buf *xmit = &sport->port.state->xmit;
 	unsigned long txcnt;
 
+	if (sport->port.x_char) {
+		lpuart32_write(&sport->port, sport->port.x_char, UARTDATA);
+		sport->port.icount.tx++;
+		sport->port.x_char = 0;
+		return;
+	}
+
+	if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) {
+		lpuart32_stop_tx(&sport->port);
+		return;
+	}
+
 	txcnt = lpuart32_read(&sport->port, UARTWATER);
 	txcnt = txcnt >> UARTWATER_TXCNT_OFF;
 	txcnt &= UARTWATER_COUNT_MASK;
@@ -773,34 +797,10 @@ static unsigned int lpuart32_tx_empty(struct uart_port *port)
 
 static void lpuart_txint(struct lpuart_port *sport)
 {
-	struct circ_buf *xmit = &sport->port.state->xmit;
 	unsigned long flags;
 
 	spin_lock_irqsave(&sport->port.lock, flags);
-	if (sport->port.x_char) {
-		if (lpuart_is_32(sport))
-			lpuart32_write(&sport->port, sport->port.x_char, UARTDATA);
-		else
-			writeb(sport->port.x_char, sport->port.membase + UARTDR);
-		sport->port.icount.tx++;
-		sport->port.x_char = 0;
-		goto out;
-	}
-
-	if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) {
-		if (lpuart_is_32(sport))
-			lpuart32_stop_tx(&sport->port);
-		else
-			lpuart_stop_tx(&sport->port);
-		goto out;
-	}
-
-	if (lpuart_is_32(sport))
-		lpuart32_transmit_buffer(sport);
-	else
-		lpuart_transmit_buffer(sport);
-
-out:
+	lpuart_transmit_buffer(sport);
 	spin_unlock_irqrestore(&sport->port.lock, flags);
 }
 
@@ -876,6 +876,15 @@ static void lpuart_rxint(struct lpuart_port *sport)
 	tty_flip_buffer_push(port);
 }
 
+static void lpuart32_txint(struct lpuart_port *sport)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&sport->port.lock, flags);
+	lpuart32_transmit_buffer(sport);
+	spin_unlock_irqrestore(&sport->port.lock, flags);
+}
+
 static void lpuart32_rxint(struct lpuart_port *sport)
 {
 	unsigned int flg, ignored = 0;
@@ -967,7 +976,7 @@ static irqreturn_t lpuart32_int(int irq, void *dev_id)
 		lpuart32_rxint(sport);
 
 	if ((sts & UARTSTAT_TDRE) && !sport->lpuart_dma_tx_use)
-		lpuart_txint(sport);
+		lpuart32_txint(sport);
 
 	lpuart32_write(&sport->port, sts, UARTSTAT);
 	return IRQ_HANDLED;
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v2 09/23] tty: serial: fsl_lpuart: Drop no-op bit opearation
  2019-07-31 17:30 [PATCH v2 00/23] LPUART fixes and improvements Andrey Smirnov
                   ` (7 preceding siblings ...)
  2019-07-31 17:30 ` [PATCH v2 08/23] tty: serial: fls_lpuart: Split shared TX IRQ handler into two Andrey Smirnov
@ 2019-07-31 17:30 ` Andrey Smirnov
  2019-07-31 17:30 ` [PATCH v2 10/23] tty: serial: fsl_lpuart: Drop unnecessary extra parenthesis Andrey Smirnov
                   ` (14 subsequent siblings)
  23 siblings, 0 replies; 26+ messages in thread
From: Andrey Smirnov @ 2019-07-31 17:30 UTC (permalink / raw)
  To: linux-serial
  Cc: Andrey Smirnov, Stefan Agner, Chris Healy, Cory Tusar,
	Lucas Stach, Greg Kroah-Hartman, Jiri Slaby, linux-imx,
	linux-kernel

The check for termios->c_cflag & CRTSCTS ensure that if we reach else
branch, CRTSCTS in termios->c_cflag is already going to be
cleard. Doing so explicitly there is not necessary. Drop it.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
Cc: Stefan Agner <stefan@agner.ch>
Cc: Chris Healy <cphealy@gmail.com>
Cc: Cory Tusar <cory.tusar@zii.aero>
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: linux-imx@nxp.com
Cc: linux-serial@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/tty/serial/fsl_lpuart.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index ed6d3f836c93..b3cc44548b34 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -1650,12 +1650,10 @@ lpuart_set_termios(struct uart_port *port, struct ktermios *termios,
 	if (sport->port.rs485.flags & SER_RS485_ENABLED)
 		termios->c_cflag &= ~CRTSCTS;
 
-	if (termios->c_cflag & CRTSCTS) {
+	if (termios->c_cflag & CRTSCTS)
 		modem |= (UARTMODEM_RXRTSE | UARTMODEM_TXCTSE);
-	} else {
-		termios->c_cflag &= ~CRTSCTS;
+	else
 		modem &= ~(UARTMODEM_RXRTSE | UARTMODEM_TXCTSE);
-	}
 
 	if (termios->c_cflag & CSTOPB)
 		termios->c_cflag &= ~CSTOPB;
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v2 10/23] tty: serial: fsl_lpuart: Drop unnecessary extra parenthesis
  2019-07-31 17:30 [PATCH v2 00/23] LPUART fixes and improvements Andrey Smirnov
                   ` (8 preceding siblings ...)
  2019-07-31 17:30 ` [PATCH v2 09/23] tty: serial: fsl_lpuart: Drop no-op bit opearation Andrey Smirnov
@ 2019-07-31 17:30 ` Andrey Smirnov
  2019-07-31 17:30 ` [PATCH v2 11/23] tty: serial: fsl_lpuart: Clear CSTOPB unconditionally Andrey Smirnov
                   ` (13 subsequent siblings)
  23 siblings, 0 replies; 26+ messages in thread
From: Andrey Smirnov @ 2019-07-31 17:30 UTC (permalink / raw)
  To: linux-serial
  Cc: Andrey Smirnov, Stefan Agner, Chris Healy, Cory Tusar,
	Lucas Stach, Greg Kroah-Hartman, Jiri Slaby, linux-imx,
	linux-kernel

Drop unnecessary extra parenthesis in the driver.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
Cc: Stefan Agner <stefan@agner.ch>
Cc: Chris Healy <cphealy@gmail.com>
Cc: Cory Tusar <cory.tusar@zii.aero>
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: linux-imx@nxp.com
Cc: linux-serial@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/tty/serial/fsl_lpuart.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index b3cc44548b34..79922f179b08 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -1443,7 +1443,7 @@ static int lpuart_startup(struct uart_port *port)
 	lpuart_setup_watermark(sport);
 
 	temp = readb(sport->port.membase + UARTCR2);
-	temp |= (UARTCR2_RIE | UARTCR2_TIE | UARTCR2_RE | UARTCR2_TE);
+	temp |= UARTCR2_RIE | UARTCR2_TIE | UARTCR2_RE | UARTCR2_TE;
 	writeb(temp, sport->port.membase + UARTCR2);
 
 	if (sport->dma_rx_chan && !lpuart_start_rx_dma(sport)) {
@@ -1651,7 +1651,7 @@ lpuart_set_termios(struct uart_port *port, struct ktermios *termios,
 		termios->c_cflag &= ~CRTSCTS;
 
 	if (termios->c_cflag & CRTSCTS)
-		modem |= (UARTMODEM_RXRTSE | UARTMODEM_TXCTSE);
+		modem |= UARTMODEM_RXRTSE | UARTMODEM_TXCTSE;
 	else
 		modem &= ~(UARTMODEM_RXRTSE | UARTMODEM_TXCTSE);
 
@@ -1662,7 +1662,7 @@ lpuart_set_termios(struct uart_port *port, struct ktermios *termios,
 	if ((termios->c_cflag & CSIZE) == CS7)
 		termios->c_cflag |= PARENB;
 
-	if ((termios->c_cflag & PARENB)) {
+	if (termios->c_cflag & PARENB) {
 		if (termios->c_cflag & CMSPAR) {
 			cr1 &= ~UARTCR1_PE;
 			if (termios->c_cflag & PARODD)
@@ -1701,7 +1701,7 @@ lpuart_set_termios(struct uart_port *port, struct ktermios *termios,
 
 	sport->port.read_status_mask = 0;
 	if (termios->c_iflag & INPCK)
-		sport->port.read_status_mask |=	(UARTSR1_FE | UARTSR1_PE);
+		sport->port.read_status_mask |= UARTSR1_FE | UARTSR1_PE;
 	if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK))
 		sport->port.read_status_mask |= UARTSR1_FE;
 
@@ -1815,7 +1815,7 @@ lpuart32_serial_setbrg(struct lpuart_port *sport, unsigned int baudrate)
 		tmp |= UARTBAUD_BOTHEDGE;
 
 	tmp &= ~(UARTBAUD_OSR_MASK << UARTBAUD_OSR_SHIFT);
-	tmp |= (((osr-1) & UARTBAUD_OSR_MASK) << UARTBAUD_OSR_SHIFT);
+	tmp |= ((osr-1) & UARTBAUD_OSR_MASK) << UARTBAUD_OSR_SHIFT;
 
 	tmp &= ~UARTBAUD_SBR_MASK;
 	tmp |= sbr & UARTBAUD_SBR_MASK;
@@ -1868,7 +1868,7 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
 	}
 
 	if (termios->c_cflag & CRTSCTS) {
-		modem |= (UARTMODEM_RXRTSE | UARTMODEM_TXCTSE);
+		modem |= UARTMODEM_RXRTSE | UARTMODEM_TXCTSE;
 	} else {
 		termios->c_cflag &= ~CRTSCTS;
 		modem &= ~(UARTMODEM_RXRTSE | UARTMODEM_TXCTSE);
@@ -1917,7 +1917,7 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
 
 	sport->port.read_status_mask = 0;
 	if (termios->c_iflag & INPCK)
-		sport->port.read_status_mask |=	(UARTSTAT_FE | UARTSTAT_PE);
+		sport->port.read_status_mask |= UARTSTAT_FE | UARTSTAT_PE;
 	if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK))
 		sport->port.read_status_mask |= UARTSTAT_FE;
 
@@ -2084,7 +2084,7 @@ lpuart_console_write(struct console *co, const char *s, unsigned int count)
 
 	/* first save CR2 and then disable interrupts */
 	cr2 = old_cr2 = readb(sport->port.membase + UARTCR2);
-	cr2 |= (UARTCR2_TE |  UARTCR2_RE);
+	cr2 |= UARTCR2_TE | UARTCR2_RE;
 	cr2 &= ~(UARTCR2_TIE | UARTCR2_TCIE | UARTCR2_RIE);
 	writeb(cr2, sport->port.membase + UARTCR2);
 
@@ -2115,7 +2115,7 @@ lpuart32_console_write(struct console *co, const char *s, unsigned int count)
 
 	/* first save CR2 and then disable interrupts */
 	cr = old_cr = lpuart32_read(&sport->port, UARTCTRL);
-	cr |= (UARTCTRL_TE |  UARTCTRL_RE);
+	cr |= UARTCTRL_TE | UARTCTRL_RE;
 	cr &= ~(UARTCTRL_TIE | UARTCTRL_TCIE | UARTCTRL_RIE);
 	lpuart32_write(&sport->port, cr, UARTCTRL);
 
@@ -2572,7 +2572,7 @@ static int lpuart_resume(struct device *dev)
 	} else {
 		lpuart_setup_watermark(sport);
 		temp = readb(sport->port.membase + UARTCR2);
-		temp |= (UARTCR2_RIE | UARTCR2_TIE | UARTCR2_RE | UARTCR2_TE);
+		temp |= UARTCR2_RIE | UARTCR2_TIE | UARTCR2_RE | UARTCR2_TE;
 		writeb(temp, sport->port.membase + UARTCR2);
 	}
 
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v2 11/23] tty: serial: fsl_lpuart: Clear CSTOPB unconditionally
  2019-07-31 17:30 [PATCH v2 00/23] LPUART fixes and improvements Andrey Smirnov
                   ` (9 preceding siblings ...)
  2019-07-31 17:30 ` [PATCH v2 10/23] tty: serial: fsl_lpuart: Drop unnecessary extra parenthesis Andrey Smirnov
@ 2019-07-31 17:30 ` Andrey Smirnov
  2019-07-31 17:30 ` [PATCH v2 12/23] tty: serial: fsl_lpuart: Use appropriate lpuart32_* I/O funcs Andrey Smirnov
                   ` (12 subsequent siblings)
  23 siblings, 0 replies; 26+ messages in thread
From: Andrey Smirnov @ 2019-07-31 17:30 UTC (permalink / raw)
  To: linux-serial
  Cc: Andrey Smirnov, Stefan Agner, Chris Healy, Cory Tusar,
	Lucas Stach, Greg Kroah-Hartman, Jiri Slaby, linux-imx,
	linux-kernel

Clearing CSTOPB bit if it is set is functionally equivalent to jsut
clearing it unconditionally. Drop unnecessary check.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
Cc: Stefan Agner <stefan@agner.ch>
Cc: Chris Healy <cphealy@gmail.com>
Cc: Cory Tusar <cory.tusar@zii.aero>
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: linux-imx@nxp.com
Cc: linux-serial@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/tty/serial/fsl_lpuart.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 79922f179b08..a0f38d7caa76 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -1655,8 +1655,7 @@ lpuart_set_termios(struct uart_port *port, struct ktermios *termios,
 	else
 		modem &= ~(UARTMODEM_RXRTSE | UARTMODEM_TXCTSE);
 
-	if (termios->c_cflag & CSTOPB)
-		termios->c_cflag &= ~CSTOPB;
+	termios->c_cflag &= ~CSTOPB;
 
 	/* parity must be enabled when CS7 to match 8-bits format */
 	if ((termios->c_cflag & CSIZE) == CS7)
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v2 12/23] tty: serial: fsl_lpuart: Use appropriate lpuart32_* I/O funcs
  2019-07-31 17:30 [PATCH v2 00/23] LPUART fixes and improvements Andrey Smirnov
                   ` (10 preceding siblings ...)
  2019-07-31 17:30 ` [PATCH v2 11/23] tty: serial: fsl_lpuart: Clear CSTOPB unconditionally Andrey Smirnov
@ 2019-07-31 17:30 ` Andrey Smirnov
  2019-07-31 17:30 ` [PATCH v2 13/23] tty: serial: fsl_lpuart: Introduce lpuart_wait_bit_set() Andrey Smirnov
                   ` (11 subsequent siblings)
  23 siblings, 0 replies; 26+ messages in thread
From: Andrey Smirnov @ 2019-07-31 17:30 UTC (permalink / raw)
  To: linux-serial
  Cc: Andrey Smirnov, Stefan Agner, Chris Healy, Cory Tusar,
	Lucas Stach, Greg Kroah-Hartman, Jiri Slaby, linux-imx,
	linux-kernel

When dealing with 32-bit variant of LPUART IP block appropriate I/O
helpers have to be used to properly deal with endianness
differences. Change all of the offending code to do that.

Fixes: a5fa2660d787 ("tty/serial/fsl_lpuart: Add CONSOLE_POLL support
for lpuart32.")
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
Cc: Stefan Agner <stefan@agner.ch>
Cc: Chris Healy <cphealy@gmail.com>
Cc: Cory Tusar <cory.tusar@zii.aero>
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: linux-imx@nxp.com
Cc: linux-serial@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/tty/serial/fsl_lpuart.c | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index a0f38d7caa76..395df8c7e1d5 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -617,26 +617,26 @@ static int lpuart32_poll_init(struct uart_port *port)
 	spin_lock_irqsave(&sport->port.lock, flags);
 
 	/* Disable Rx & Tx */
-	writel(0, sport->port.membase + UARTCTRL);
+	lpuart32_write(&sport->port, UARTCTRL, 0);
 
-	temp = readl(sport->port.membase + UARTFIFO);
+	temp = lpuart32_read(&sport->port, UARTFIFO);
 
 	/* Enable Rx and Tx FIFO */
-	writel(temp | UARTFIFO_RXFE | UARTFIFO_TXFE,
-		   sport->port.membase + UARTFIFO);
+	lpuart32_write(&sport->port, UARTFIFO,
+		       temp | UARTFIFO_RXFE | UARTFIFO_TXFE);
 
 	/* flush Tx and Rx FIFO */
-	writel(UARTFIFO_TXFLUSH | UARTFIFO_RXFLUSH,
-			sport->port.membase + UARTFIFO);
+	lpuart32_write(&sport->port, UARTFIFO,
+		       UARTFIFO_TXFLUSH | UARTFIFO_RXFLUSH);
 
 	/* explicitly clear RDRF */
-	if (readl(sport->port.membase + UARTSTAT) & UARTSTAT_RDRF) {
-		readl(sport->port.membase + UARTDATA);
-		writel(UARTFIFO_RXUF, sport->port.membase + UARTFIFO);
+	if (lpuart32_read(&sport->port, UARTSTAT) & UARTSTAT_RDRF) {
+		lpuart32_read(&sport->port, UARTDATA);
+		lpuart32_write(&sport->port, UARTFIFO, UARTFIFO_RXUF);
 	}
 
 	/* Enable Rx and Tx */
-	writel(UARTCTRL_RE | UARTCTRL_TE, sport->port.membase + UARTCTRL);
+	lpuart32_write(&sport->port, UARTCTRL, UARTCTRL_RE | UARTCTRL_TE);
 	spin_unlock_irqrestore(&sport->port.lock, flags);
 
 	return 0;
@@ -644,18 +644,18 @@ static int lpuart32_poll_init(struct uart_port *port)
 
 static void lpuart32_poll_put_char(struct uart_port *port, unsigned char c)
 {
-	while (!(readl(port->membase + UARTSTAT) & UARTSTAT_TDRE))
+	while (!(lpuart32_read(port, UARTSTAT) & UARTSTAT_TDRE))
 		barrier();
 
-	writel(c, port->membase + UARTDATA);
+	lpuart32_write(port, UARTDATA, c);
 }
 
 static int lpuart32_poll_get_char(struct uart_port *port)
 {
-	if (!(readl(port->membase + UARTSTAT) & UARTSTAT_RDRF))
+	if (!(lpuart32_read(port, UARTSTAT) & UARTSTAT_RDRF))
 		return NO_POLL_CHAR;
 
-	return readl(port->membase + UARTDATA);
+	return lpuart32_read(port, UARTDATA);
 }
 #endif
 
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v2 13/23] tty: serial: fsl_lpuart: Introduce lpuart_wait_bit_set()
  2019-07-31 17:30 [PATCH v2 00/23] LPUART fixes and improvements Andrey Smirnov
                   ` (11 preceding siblings ...)
  2019-07-31 17:30 ` [PATCH v2 12/23] tty: serial: fsl_lpuart: Use appropriate lpuart32_* I/O funcs Andrey Smirnov
@ 2019-07-31 17:30 ` Andrey Smirnov
  2019-07-31 17:30 ` [PATCH v2 14/23] tty: serial: fsl_lpuart: Use cpu_relax() instead of barrier() Andrey Smirnov
                   ` (10 subsequent siblings)
  23 siblings, 0 replies; 26+ messages in thread
From: Andrey Smirnov @ 2019-07-31 17:30 UTC (permalink / raw)
  To: linux-serial
  Cc: Andrey Smirnov, Stefan Agner, Chris Healy, Cory Tusar,
	Lucas Stach, Greg Kroah-Hartman, Jiri Slaby, linux-imx,
	linux-kernel

Busy polling on a bit in a register is used in multiple places in the
driver. Move it into a shared function.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
Cc: Stefan Agner <stefan@agner.ch>
Cc: Chris Healy <cphealy@gmail.com>
Cc: Cory Tusar <cory.tusar@zii.aero>
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: linux-imx@nxp.com
Cc: linux-serial@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/tty/serial/fsl_lpuart.c | 42 +++++++++++++++++----------------
 1 file changed, 22 insertions(+), 20 deletions(-)

diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 395df8c7e1d5..eb748ef85da7 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -549,6 +549,20 @@ static void lpuart_flush_buffer(struct uart_port *port)
 	}
 }
 
+static void lpuart_wait_bit_set(struct uart_port *port, unsigned int offset,
+				u8 bit)
+{
+	while (!(readb(port->membase + offset) & bit))
+		barrier();
+}
+
+static void lpuart32_wait_bit_set(struct uart_port *port, unsigned int offset,
+				  u32 bit)
+{
+	while (!(lpuart32_read(port, offset) & bit))
+		barrier();
+}
+
 #if defined(CONFIG_CONSOLE_POLL)
 
 static int lpuart_poll_init(struct uart_port *port)
@@ -592,9 +606,7 @@ static int lpuart_poll_init(struct uart_port *port)
 static void lpuart_poll_put_char(struct uart_port *port, unsigned char c)
 {
 	/* drain */
-	while (!(readb(port->membase + UARTSR1) & UARTSR1_TDRE))
-		barrier();
-
+	lpuart_wait_bit_set(port, UARTSR1, UARTSR1_TDRE);
 	writeb(c, port->membase + UARTDR);
 }
 
@@ -644,9 +656,7 @@ static int lpuart32_poll_init(struct uart_port *port)
 
 static void lpuart32_poll_put_char(struct uart_port *port, unsigned char c)
 {
-	while (!(lpuart32_read(port, UARTSTAT) & UARTSTAT_TDRE))
-		barrier();
-
+	lpuart32_wait_bit_set(port, UARTSTAT, UARTSTAT_TDRE);
 	lpuart32_write(port, UARTDATA, c);
 }
 
@@ -1722,8 +1732,7 @@ lpuart_set_termios(struct uart_port *port, struct ktermios *termios,
 	uart_update_timeout(port, termios->c_cflag, baud);
 
 	/* wait transmit engin complete */
-	while (!(readb(sport->port.membase + UARTSR1) & UARTSR1_TC))
-		barrier();
+	lpuart_wait_bit_set(&sport->port, UARTSR1, UARTSR1_TC);
 
 	/* disable transmit and receive */
 	writeb(old_cr2 & ~(UARTCR2_TE | UARTCR2_RE),
@@ -1938,8 +1947,7 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
 	uart_update_timeout(port, termios->c_cflag, baud);
 
 	/* wait transmit engin complete */
-	while (!(lpuart32_read(&sport->port, UARTSTAT) & UARTSTAT_TC))
-		barrier();
+	lpuart32_wait_bit_set(&sport->port, UARTSTAT, UARTSTAT_TC);
 
 	/* disable transmit and receive */
 	lpuart32_write(&sport->port, old_ctrl & ~(UARTCTRL_TE | UARTCTRL_RE),
@@ -2054,17 +2062,13 @@ static struct lpuart_port *lpuart_ports[UART_NR];
 #ifdef CONFIG_SERIAL_FSL_LPUART_CONSOLE
 static void lpuart_console_putchar(struct uart_port *port, int ch)
 {
-	while (!(readb(port->membase + UARTSR1) & UARTSR1_TDRE))
-		barrier();
-
+	lpuart_wait_bit_set(port, UARTSR1, UARTSR1_TDRE);
 	writeb(ch, port->membase + UARTDR);
 }
 
 static void lpuart32_console_putchar(struct uart_port *port, int ch)
 {
-	while (!(lpuart32_read(port, UARTSTAT) & UARTSTAT_TDRE))
-		barrier();
-
+	lpuart32_wait_bit_set(port, UARTSTAT, UARTSTAT_TDRE);
 	lpuart32_write(port, ch, UARTDATA);
 }
 
@@ -2090,8 +2094,7 @@ lpuart_console_write(struct console *co, const char *s, unsigned int count)
 	uart_console_write(&sport->port, s, count, lpuart_console_putchar);
 
 	/* wait for transmitter finish complete and restore CR2 */
-	while (!(readb(sport->port.membase + UARTSR1) & UARTSR1_TC))
-		barrier();
+	lpuart_wait_bit_set(&sport->port, UARTSR1, UARTSR1_TC);
 
 	writeb(old_cr2, sport->port.membase + UARTCR2);
 
@@ -2121,8 +2124,7 @@ lpuart32_console_write(struct console *co, const char *s, unsigned int count)
 	uart_console_write(&sport->port, s, count, lpuart32_console_putchar);
 
 	/* wait for transmitter finish complete and restore CR2 */
-	while (!(lpuart32_read(&sport->port, UARTSTAT) & UARTSTAT_TC))
-		barrier();
+	lpuart32_wait_bit_set(&sport->port, UARTSTAT, UARTSTAT_TC);
 
 	lpuart32_write(&sport->port, old_cr, UARTCTRL);
 
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v2 14/23] tty: serial: fsl_lpuart: Use cpu_relax() instead of barrier()
  2019-07-31 17:30 [PATCH v2 00/23] LPUART fixes and improvements Andrey Smirnov
                   ` (12 preceding siblings ...)
  2019-07-31 17:30 ` [PATCH v2 13/23] tty: serial: fsl_lpuart: Introduce lpuart_wait_bit_set() Andrey Smirnov
@ 2019-07-31 17:30 ` Andrey Smirnov
  2019-07-31 17:30 ` [PATCH v2 15/23] tty: serial: fsl_lpuart: Introduce lpuart_stopped_or_empty() Andrey Smirnov
                   ` (9 subsequent siblings)
  23 siblings, 0 replies; 26+ messages in thread
From: Andrey Smirnov @ 2019-07-31 17:30 UTC (permalink / raw)
  To: linux-serial
  Cc: Andrey Smirnov, Stefan Agner, Chris Healy, Cory Tusar,
	Lucas Stach, Greg Kroah-Hartman, Jiri Slaby, linux-imx,
	linux-kernel

Use cpu_relax() instead of barrier() in a tight polling loops to make
them a bit more idiomatic. Should also improve things on ARM64 a bit
since cpu_relax() will expand into "yield" instruction there.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
Cc: Stefan Agner <stefan@agner.ch>
Cc: Chris Healy <cphealy@gmail.com>
Cc: Cory Tusar <cory.tusar@zii.aero>
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: linux-imx@nxp.com
Cc: linux-serial@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/tty/serial/fsl_lpuart.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index eb748ef85da7..58043e01a242 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -553,14 +553,14 @@ static void lpuart_wait_bit_set(struct uart_port *port, unsigned int offset,
 				u8 bit)
 {
 	while (!(readb(port->membase + offset) & bit))
-		barrier();
+		cpu_relax();
 }
 
 static void lpuart32_wait_bit_set(struct uart_port *port, unsigned int offset,
 				  u32 bit)
 {
 	while (!(lpuart32_read(port, offset) & bit))
-		barrier();
+		cpu_relax();
 }
 
 #if defined(CONFIG_CONSOLE_POLL)
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v2 15/23] tty: serial: fsl_lpuart: Introduce lpuart_stopped_or_empty()
  2019-07-31 17:30 [PATCH v2 00/23] LPUART fixes and improvements Andrey Smirnov
                   ` (13 preceding siblings ...)
  2019-07-31 17:30 ` [PATCH v2 14/23] tty: serial: fsl_lpuart: Use cpu_relax() instead of barrier() Andrey Smirnov
@ 2019-07-31 17:30 ` Andrey Smirnov
  2019-07-31 17:30 ` [PATCH v2 16/23] tty: serial: fsl_lpuart: Drop unnecessary lpuart*_stop_tx() Andrey Smirnov
                   ` (8 subsequent siblings)
  23 siblings, 0 replies; 26+ messages in thread
From: Andrey Smirnov @ 2019-07-31 17:30 UTC (permalink / raw)
  To: linux-serial
  Cc: Andrey Smirnov, Stefan Agner, Chris Healy, Cory Tusar,
	Lucas Stach, Greg Kroah-Hartman, Jiri Slaby, linux-imx,
	linux-kernel

The check for

    uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)

appears in multiple places in the driver. Move it into a helper
function.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
Cc: Stefan Agner <stefan@agner.ch>
Cc: Chris Healy <cphealy@gmail.com>
Cc: Cory Tusar <cory.tusar@zii.aero>
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: linux-imx@nxp.com
Cc: linux-serial@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/tty/serial/fsl_lpuart.c | 17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 58043e01a242..e59dd90fc34c 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -452,6 +452,11 @@ static void lpuart_dma_tx(struct lpuart_port *sport)
 	dma_async_issue_pending(sport->dma_tx_chan);
 }
 
+static bool lpuart_stopped_or_empty(struct uart_port *port)
+{
+	return uart_circ_empty(&port->state->xmit) || uart_tx_stopped(port);
+}
+
 static void lpuart_dma_tx_complete(void *arg)
 {
 	struct lpuart_port *sport = arg;
@@ -479,7 +484,7 @@ static void lpuart_dma_tx_complete(void *arg)
 
 	spin_lock_irqsave(&sport->port.lock, flags);
 
-	if (!uart_circ_empty(xmit) && !uart_tx_stopped(&sport->port))
+	if (!lpuart_stopped_or_empty(&sport->port))
 		lpuart_dma_tx(sport);
 
 	spin_unlock_irqrestore(&sport->port.lock, flags);
@@ -680,7 +685,7 @@ static inline void lpuart_transmit_buffer(struct lpuart_port *sport)
 		return;
 	}
 
-	if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) {
+	if (lpuart_stopped_or_empty(&sport->port)) {
 		lpuart_stop_tx(&sport->port);
 		return;
 	}
@@ -711,7 +716,7 @@ static inline void lpuart32_transmit_buffer(struct lpuart_port *sport)
 		return;
 	}
 
-	if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) {
+	if (lpuart_stopped_or_empty(&sport->port)) {
 		lpuart32_stop_tx(&sport->port);
 		return;
 	}
@@ -739,14 +744,13 @@ static void lpuart_start_tx(struct uart_port *port)
 {
 	struct lpuart_port *sport = container_of(port,
 			struct lpuart_port, port);
-	struct circ_buf *xmit = &sport->port.state->xmit;
 	unsigned char temp;
 
 	temp = readb(port->membase + UARTCR2);
 	writeb(temp | UARTCR2_TIE, port->membase + UARTCR2);
 
 	if (sport->lpuart_dma_tx_use) {
-		if (!uart_circ_empty(xmit) && !uart_tx_stopped(port))
+		if (!lpuart_stopped_or_empty(port))
 			lpuart_dma_tx(sport);
 	} else {
 		if (readb(port->membase + UARTSR1) & UARTSR1_TDRE)
@@ -757,11 +761,10 @@ static void lpuart_start_tx(struct uart_port *port)
 static void lpuart32_start_tx(struct uart_port *port)
 {
 	struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
-	struct circ_buf *xmit = &sport->port.state->xmit;
 	unsigned long temp;
 
 	if (sport->lpuart_dma_tx_use) {
-		if (!uart_circ_empty(xmit) && !uart_tx_stopped(port))
+		if (!lpuart_stopped_or_empty(port))
 			lpuart_dma_tx(sport);
 	} else {
 		temp = lpuart32_read(port, UARTCTRL);
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v2 16/23] tty: serial: fsl_lpuart: Drop unnecessary lpuart*_stop_tx()
  2019-07-31 17:30 [PATCH v2 00/23] LPUART fixes and improvements Andrey Smirnov
                   ` (14 preceding siblings ...)
  2019-07-31 17:30 ` [PATCH v2 15/23] tty: serial: fsl_lpuart: Introduce lpuart_stopped_or_empty() Andrey Smirnov
@ 2019-07-31 17:30 ` Andrey Smirnov
  2019-07-31 17:30 ` [PATCH v2 17/23] tty: serial: fsl_lpuart: Introduce lpuart_dma_shutdown() Andrey Smirnov
                   ` (7 subsequent siblings)
  23 siblings, 0 replies; 26+ messages in thread
From: Andrey Smirnov @ 2019-07-31 17:30 UTC (permalink / raw)
  To: linux-serial
  Cc: Andrey Smirnov, Stefan Agner, Chris Healy, Cory Tusar,
	Lucas Stach, Greg Kroah-Hartman, Jiri Slaby, linux-imx,
	linux-kernel

By the time lpuart_shutdown() calls lpuart_stop_tx() UARTCR2_TE and
UARTCR2_TIE (which the latter will clear) are already cleared, so that
function call should effectively be a no-op. Moreso, lpuart_stop_tx()
is expected to be executed with port spinlock held, which the caller
doesn't. Given all that, drop the call to lpuart_stop_tx() in
lpuart_shutdown().

In case of lpuart32_shutdown()/lpuart32_stop_tx(), TIE won't even be
set if lpuart_dma_tx_use is true. Drop it there as well.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
Cc: Stefan Agner <stefan@agner.ch>
Cc: Chris Healy <cphealy@gmail.com>
Cc: Cory Tusar <cory.tusar@zii.aero>
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: linux-imx@nxp.com
Cc: linux-serial@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/tty/serial/fsl_lpuart.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index e59dd90fc34c..2597a877d639 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -1574,8 +1574,6 @@ static void lpuart_shutdown(struct uart_port *port)
 			sport->dma_tx_in_progress = false;
 			dmaengine_terminate_all(sport->dma_tx_chan);
 		}
-
-		lpuart_stop_tx(port);
 	}
 }
 
@@ -1607,8 +1605,6 @@ static void lpuart32_shutdown(struct uart_port *port)
 			sport->dma_tx_in_progress = false;
 			dmaengine_terminate_all(sport->dma_tx_chan);
 		}
-
-		lpuart32_stop_tx(port);
 	}
 }
 
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v2 17/23] tty: serial: fsl_lpuart: Introduce lpuart_dma_shutdown()
  2019-07-31 17:30 [PATCH v2 00/23] LPUART fixes and improvements Andrey Smirnov
                   ` (15 preceding siblings ...)
  2019-07-31 17:30 ` [PATCH v2 16/23] tty: serial: fsl_lpuart: Drop unnecessary lpuart*_stop_tx() Andrey Smirnov
@ 2019-07-31 17:30 ` Andrey Smirnov
  2019-07-31 17:30 ` [PATCH v2 18/23] tty: serial: fsl_lpuart: Introduce lpuart_tx_dma_startup() Andrey Smirnov
                   ` (6 subsequent siblings)
  23 siblings, 0 replies; 26+ messages in thread
From: Andrey Smirnov @ 2019-07-31 17:30 UTC (permalink / raw)
  To: linux-serial
  Cc: Andrey Smirnov, Stefan Agner, Chris Healy, Cory Tusar,
	Lucas Stach, Greg Kroah-Hartman, Jiri Slaby, linux-imx,
	linux-kernel

Last steps of .shutdown() code are identical for lpuart and lpuart32
cases, so move it all into a standalone subroutine.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
Cc: Stefan Agner <stefan@agner.ch>
Cc: Chris Healy <cphealy@gmail.com>
Cc: Cory Tusar <cory.tusar@zii.aero>
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: linux-imx@nxp.com
Cc: linux-serial@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/tty/serial/fsl_lpuart.c | 42 ++++++++++++++-------------------
 1 file changed, 18 insertions(+), 24 deletions(-)

diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 2597a877d639..8cf10d12947f 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -1547,6 +1547,22 @@ static int lpuart32_startup(struct uart_port *port)
 	return 0;
 }
 
+static void lpuart_dma_shutdown(struct lpuart_port *sport)
+{
+	if (sport->lpuart_dma_rx_use) {
+		del_timer_sync(&sport->lpuart_timer);
+		lpuart_dma_rx_free(&sport->port);
+	}
+
+	if (sport->lpuart_dma_tx_use) {
+		if (wait_event_interruptible(sport->dma_wait,
+			!sport->dma_tx_in_progress) != false) {
+			sport->dma_tx_in_progress = false;
+			dmaengine_terminate_all(sport->dma_tx_chan);
+		}
+	}
+}
+
 static void lpuart_shutdown(struct uart_port *port)
 {
 	struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
@@ -1563,18 +1579,7 @@ static void lpuart_shutdown(struct uart_port *port)
 
 	spin_unlock_irqrestore(&port->lock, flags);
 
-	if (sport->lpuart_dma_rx_use) {
-		del_timer_sync(&sport->lpuart_timer);
-		lpuart_dma_rx_free(&sport->port);
-	}
-
-	if (sport->lpuart_dma_tx_use) {
-		if (wait_event_interruptible(sport->dma_wait,
-			!sport->dma_tx_in_progress) != false) {
-			sport->dma_tx_in_progress = false;
-			dmaengine_terminate_all(sport->dma_tx_chan);
-		}
-	}
+	lpuart_dma_shutdown(sport);
 }
 
 static void lpuart32_shutdown(struct uart_port *port)
@@ -1594,18 +1599,7 @@ static void lpuart32_shutdown(struct uart_port *port)
 
 	spin_unlock_irqrestore(&port->lock, flags);
 
-	if (sport->lpuart_dma_rx_use) {
-		del_timer_sync(&sport->lpuart_timer);
-		lpuart_dma_rx_free(&sport->port);
-	}
-
-	if (sport->lpuart_dma_tx_use) {
-		if (wait_event_interruptible(sport->dma_wait,
-					     !sport->dma_tx_in_progress)) {
-			sport->dma_tx_in_progress = false;
-			dmaengine_terminate_all(sport->dma_tx_chan);
-		}
-	}
+	lpuart_dma_shutdown(sport);
 }
 
 static void
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v2 18/23] tty: serial: fsl_lpuart: Introduce lpuart_tx_dma_startup()
  2019-07-31 17:30 [PATCH v2 00/23] LPUART fixes and improvements Andrey Smirnov
                   ` (16 preceding siblings ...)
  2019-07-31 17:30 ` [PATCH v2 17/23] tty: serial: fsl_lpuart: Introduce lpuart_dma_shutdown() Andrey Smirnov
@ 2019-07-31 17:30 ` Andrey Smirnov
  2019-07-31 17:30 ` [PATCH v2 19/23] tty: serial: fsl_lpuart: Introduce lpuart_rx_dma_startup() Andrey Smirnov
                   ` (5 subsequent siblings)
  23 siblings, 0 replies; 26+ messages in thread
From: Andrey Smirnov @ 2019-07-31 17:30 UTC (permalink / raw)
  To: linux-serial
  Cc: Andrey Smirnov, Stefan Agner, Chris Healy, Cory Tusar,
	Lucas Stach, Greg Kroah-Hartman, Jiri Slaby, linux-imx,
	linux-kernel

Code configure DMA TX path in lpuart_startup(), lpuart32_startup() and
lpuart_resume() is doing exactly the same thing, so move it into a
standalone subroutine.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
Cc: Stefan Agner <stefan@agner.ch>
Cc: Chris Healy <cphealy@gmail.com>
Cc: Cory Tusar <cory.tusar@zii.aero>
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: linux-imx@nxp.com
Cc: linux-serial@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/tty/serial/fsl_lpuart.c | 53 ++++++++++++++-------------------
 1 file changed, 23 insertions(+), 30 deletions(-)

diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 8cf10d12947f..5f2dc43676f7 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -1435,6 +1435,26 @@ static void rx_dma_timer_init(struct lpuart_port *sport)
 	add_timer(&sport->lpuart_timer);
 }
 
+static void lpuart_tx_dma_startup(struct lpuart_port *sport)
+{
+	u32 uartbaud;
+
+	if (sport->dma_tx_chan && !lpuart_dma_tx_request(&sport->port)) {
+		init_waitqueue_head(&sport->dma_wait);
+		sport->lpuart_dma_tx_use = true;
+		if (lpuart_is_32(sport)) {
+			uartbaud = lpuart32_read(&sport->port, UARTBAUD);
+			lpuart32_write(&sport->port,
+				       uartbaud | UARTBAUD_TDMAE, UARTBAUD);
+		} else {
+			writeb(readb(sport->port.membase + UARTCR5) |
+				UARTCR5_TDMAS, sport->port.membase + UARTCR5);
+		}
+	} else {
+		sport->lpuart_dma_tx_use = false;
+	}
+}
+
 static int lpuart_startup(struct uart_port *port)
 {
 	struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
@@ -1471,14 +1491,7 @@ static int lpuart_startup(struct uart_port *port)
 		sport->lpuart_dma_rx_use = false;
 	}
 
-	if (sport->dma_tx_chan && !lpuart_dma_tx_request(port)) {
-		init_waitqueue_head(&sport->dma_wait);
-		sport->lpuart_dma_tx_use = true;
-		temp = readb(port->membase + UARTCR5);
-		writeb(temp | UARTCR5_TDMAS, port->membase + UARTCR5);
-	} else {
-		sport->lpuart_dma_tx_use = false;
-	}
+	lpuart_tx_dma_startup(sport);
 
 	spin_unlock_irqrestore(&sport->port.lock, flags);
 
@@ -1521,14 +1534,7 @@ static int lpuart32_startup(struct uart_port *port)
 		sport->lpuart_dma_rx_use = false;
 	}
 
-	if (sport->dma_tx_chan && !lpuart_dma_tx_request(port)) {
-		init_waitqueue_head(&sport->dma_wait);
-		sport->lpuart_dma_tx_use = true;
-		temp = lpuart32_read(&sport->port, UARTBAUD);
-		lpuart32_write(&sport->port, temp | UARTBAUD_TDMAE, UARTBAUD);
-	} else {
-		sport->lpuart_dma_tx_use = false;
-	}
+	lpuart_tx_dma_startup(sport);
 
 	if (sport->lpuart_dma_rx_use) {
 		/* RXWATER must be 0 */
@@ -2579,20 +2585,7 @@ static int lpuart_resume(struct device *dev)
 		}
 	}
 
-	if (sport->dma_tx_chan && !lpuart_dma_tx_request(&sport->port)) {
-		init_waitqueue_head(&sport->dma_wait);
-		sport->lpuart_dma_tx_use = true;
-		if (lpuart_is_32(sport)) {
-			temp = lpuart32_read(&sport->port, UARTBAUD);
-			lpuart32_write(&sport->port,
-				       temp | UARTBAUD_TDMAE, UARTBAUD);
-		} else {
-			writeb(readb(sport->port.membase + UARTCR5) |
-				UARTCR5_TDMAS, sport->port.membase + UARTCR5);
-		}
-	} else {
-		sport->lpuart_dma_tx_use = false;
-	}
+	lpuart_tx_dma_startup(sport);
 
 	if (lpuart_is_32(sport)) {
 		if (sport->lpuart_dma_rx_use) {
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v2 19/23] tty: serial: fsl_lpuart: Introduce lpuart_rx_dma_startup()
  2019-07-31 17:30 [PATCH v2 00/23] LPUART fixes and improvements Andrey Smirnov
                   ` (17 preceding siblings ...)
  2019-07-31 17:30 ` [PATCH v2 18/23] tty: serial: fsl_lpuart: Introduce lpuart_tx_dma_startup() Andrey Smirnov
@ 2019-07-31 17:30 ` Andrey Smirnov
  2019-07-31 17:30 ` [PATCH v2 20/23] tty: serial: fsl_lpuart: Introduce lpuart32_configure() Andrey Smirnov
                   ` (4 subsequent siblings)
  23 siblings, 0 replies; 26+ messages in thread
From: Andrey Smirnov @ 2019-07-31 17:30 UTC (permalink / raw)
  To: linux-serial
  Cc: Andrey Smirnov, Stefan Agner, Chris Healy, Cory Tusar,
	Lucas Stach, Greg Kroah-Hartman, Jiri Slaby, linux-imx,
	linux-kernel

Code doing initial DMA RX configuration in lpuart_startup() and
lpuart32_startup() is exactly the same, so move it into a standalone
subroutine.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
Cc: Stefan Agner <stefan@agner.ch>
Cc: Chris Healy <cphealy@gmail.com>
Cc: Cory Tusar <cory.tusar@zii.aero>
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: linux-imx@nxp.com
Cc: linux-serial@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/tty/serial/fsl_lpuart.c | 40 ++++++++++++++-------------------
 1 file changed, 17 insertions(+), 23 deletions(-)

diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 5f2dc43676f7..7d67e9631623 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -1455,6 +1455,21 @@ static void lpuart_tx_dma_startup(struct lpuart_port *sport)
 	}
 }
 
+static void lpuart_rx_dma_startup(struct lpuart_port *sport)
+{
+	if (sport->dma_rx_chan && !lpuart_start_rx_dma(sport)) {
+		/* set Rx DMA timeout */
+		sport->dma_rx_timeout = msecs_to_jiffies(DMA_RX_TIMEOUT);
+		if (!sport->dma_rx_timeout)
+			sport->dma_rx_timeout = 1;
+
+		sport->lpuart_dma_rx_use = true;
+		rx_dma_timer_init(sport);
+	} else {
+		sport->lpuart_dma_rx_use = false;
+	}
+}
+
 static int lpuart_startup(struct uart_port *port)
 {
 	struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
@@ -1479,18 +1494,7 @@ static int lpuart_startup(struct uart_port *port)
 	temp |= UARTCR2_RIE | UARTCR2_TIE | UARTCR2_RE | UARTCR2_TE;
 	writeb(temp, sport->port.membase + UARTCR2);
 
-	if (sport->dma_rx_chan && !lpuart_start_rx_dma(sport)) {
-		/* set Rx DMA timeout */
-		sport->dma_rx_timeout = msecs_to_jiffies(DMA_RX_TIMEOUT);
-		if (!sport->dma_rx_timeout)
-		     sport->dma_rx_timeout = 1;
-
-		sport->lpuart_dma_rx_use = true;
-		rx_dma_timer_init(sport);
-	} else {
-		sport->lpuart_dma_rx_use = false;
-	}
-
+	lpuart_rx_dma_startup(sport);
 	lpuart_tx_dma_startup(sport);
 
 	spin_unlock_irqrestore(&sport->port.lock, flags);
@@ -1522,18 +1526,8 @@ static int lpuart32_startup(struct uart_port *port)
 	temp |= UARTCTRL_RE | UARTCTRL_TE | UARTCTRL_ILIE;
 	lpuart32_write(&sport->port, temp, UARTCTRL);
 
-	if (sport->dma_rx_chan && !lpuart_start_rx_dma(sport)) {
-		/* set Rx DMA timeout */
-		sport->dma_rx_timeout = msecs_to_jiffies(DMA_RX_TIMEOUT);
-		if (!sport->dma_rx_timeout)
-			sport->dma_rx_timeout = 1;
-
-		sport->lpuart_dma_rx_use = true;
-		rx_dma_timer_init(sport);
-	} else {
-		sport->lpuart_dma_rx_use = false;
-	}
 
+	lpuart_rx_dma_startup(sport);
 	lpuart_tx_dma_startup(sport);
 
 	if (sport->lpuart_dma_rx_use) {
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v2 20/23] tty: serial: fsl_lpuart: Introduce lpuart32_configure()
  2019-07-31 17:30 [PATCH v2 00/23] LPUART fixes and improvements Andrey Smirnov
                   ` (18 preceding siblings ...)
  2019-07-31 17:30 ` [PATCH v2 19/23] tty: serial: fsl_lpuart: Introduce lpuart_rx_dma_startup() Andrey Smirnov
@ 2019-07-31 17:30 ` Andrey Smirnov
  2019-07-31 17:30 ` [PATCH v2 21/23] tty: serial: fsl_lpuart: Introduce lpuart*_setup_watermark_enable() Andrey Smirnov
                   ` (3 subsequent siblings)
  23 siblings, 0 replies; 26+ messages in thread
From: Andrey Smirnov @ 2019-07-31 17:30 UTC (permalink / raw)
  To: linux-serial
  Cc: Andrey Smirnov, Stefan Agner, Chris Healy, Cory Tusar,
	Lucas Stach, Greg Kroah-Hartman, Jiri Slaby, linux-imx,
	linux-kernel

Code doing final steps of TX/RX configuration in lpuart32_startup()
and lpuart_resume() is identical, so move it into a standalone
subroutine.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
Cc: Stefan Agner <stefan@agner.ch>
Cc: Chris Healy <cphealy@gmail.com>
Cc: Cory Tusar <cory.tusar@zii.aero>
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: linux-imx@nxp.com
Cc: linux-serial@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/tty/serial/fsl_lpuart.c | 48 +++++++++++++++------------------
 1 file changed, 21 insertions(+), 27 deletions(-)

diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 7d67e9631623..5a6516f4bc93 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -1502,6 +1502,24 @@ static int lpuart_startup(struct uart_port *port)
 	return 0;
 }
 
+static void lpuart32_configure(struct lpuart_port *sport)
+{
+	unsigned long temp;
+
+	if (sport->lpuart_dma_rx_use) {
+		/* RXWATER must be 0 */
+		temp = lpuart32_read(&sport->port, UARTWATER);
+		temp &= ~(UARTWATER_WATER_MASK << UARTWATER_RXWATER_OFF);
+		lpuart32_write(&sport->port, temp, UARTWATER);
+	}
+	temp = lpuart32_read(&sport->port, UARTCTRL);
+	if (!sport->lpuart_dma_rx_use)
+		temp |= UARTCTRL_RIE;
+	if (!sport->lpuart_dma_tx_use)
+		temp |= UARTCTRL_TIE;
+	lpuart32_write(&sport->port, temp, UARTCTRL);
+}
+
 static int lpuart32_startup(struct uart_port *port)
 {
 	struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
@@ -1530,18 +1548,7 @@ static int lpuart32_startup(struct uart_port *port)
 	lpuart_rx_dma_startup(sport);
 	lpuart_tx_dma_startup(sport);
 
-	if (sport->lpuart_dma_rx_use) {
-		/* RXWATER must be 0 */
-		temp = lpuart32_read(&sport->port, UARTWATER);
-		temp &= ~(UARTWATER_WATER_MASK << UARTWATER_RXWATER_OFF);
-		lpuart32_write(&sport->port, temp, UARTWATER);
-	}
-	temp = lpuart32_read(&sport->port, UARTCTRL);
-	if (!sport->lpuart_dma_rx_use)
-		temp |= UARTCTRL_RIE;
-	if (!sport->lpuart_dma_tx_use)
-		temp |= UARTCTRL_TIE;
-	lpuart32_write(&sport->port, temp, UARTCTRL);
+	lpuart32_configure(sport);
 
 	spin_unlock_irqrestore(&sport->port.lock, flags);
 	return 0;
@@ -2581,21 +2588,8 @@ static int lpuart_resume(struct device *dev)
 
 	lpuart_tx_dma_startup(sport);
 
-	if (lpuart_is_32(sport)) {
-		if (sport->lpuart_dma_rx_use) {
-			/* RXWATER must be 0 */
-			temp = lpuart32_read(&sport->port, UARTWATER);
-			temp &= ~(UARTWATER_WATER_MASK <<
-				  UARTWATER_RXWATER_OFF);
-			lpuart32_write(&sport->port, temp, UARTWATER);
-		}
-		temp = lpuart32_read(&sport->port, UARTCTRL);
-		if (!sport->lpuart_dma_rx_use)
-			temp |= UARTCTRL_RIE;
-		if (!sport->lpuart_dma_tx_use)
-			temp |= UARTCTRL_TIE;
-		lpuart32_write(&sport->port, temp, UARTCTRL);
-	}
+	if (lpuart_is_32(sport))
+		lpuart32_configure(sport);
 
 	uart_resume_port(&lpuart_reg, &sport->port);
 
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v2 21/23] tty: serial: fsl_lpuart: Introduce lpuart*_setup_watermark_enable()
  2019-07-31 17:30 [PATCH v2 00/23] LPUART fixes and improvements Andrey Smirnov
                   ` (19 preceding siblings ...)
  2019-07-31 17:30 ` [PATCH v2 20/23] tty: serial: fsl_lpuart: Introduce lpuart32_configure() Andrey Smirnov
@ 2019-07-31 17:30 ` Andrey Smirnov
  2019-07-31 17:30 ` [PATCH v2 22/23] tty: serial: fsl_lpuart: Don't enable TIE in .startup() or .resume() Andrey Smirnov
                   ` (2 subsequent siblings)
  23 siblings, 0 replies; 26+ messages in thread
From: Andrey Smirnov @ 2019-07-31 17:30 UTC (permalink / raw)
  To: linux-serial
  Cc: Andrey Smirnov, Stefan Agner, Chris Healy, Cory Tusar,
	Lucas Stach, Greg Kroah-Hartman, Jiri Slaby, linux-imx,
	linux-kernel

Most users of lpuart*_setup_watermark() enable identical set of flags
right after the call, so combine those two action into a subroutine
and make use of it.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
Cc: Stefan Agner <stefan@agner.ch>
Cc: Chris Healy <cphealy@gmail.com>
Cc: Cory Tusar <cory.tusar@zii.aero>
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: linux-imx@nxp.com
Cc: linux-serial@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/tty/serial/fsl_lpuart.c | 50 ++++++++++++++++++---------------
 1 file changed, 28 insertions(+), 22 deletions(-)

diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 5a6516f4bc93..8ab5f9939597 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -1403,6 +1403,17 @@ static void lpuart_setup_watermark(struct lpuart_port *sport)
 	writeb(cr2_saved, sport->port.membase + UARTCR2);
 }
 
+static void lpuart_setup_watermark_enable(struct lpuart_port *sport)
+{
+	unsigned char cr2;
+
+	lpuart_setup_watermark(sport);
+
+	cr2 = readb(sport->port.membase + UARTCR2);
+	cr2 |= UARTCR2_RIE | UARTCR2_TIE | UARTCR2_RE | UARTCR2_TE;
+	writeb(cr2, sport->port.membase + UARTCR2);
+}
+
 static void lpuart32_setup_watermark(struct lpuart_port *sport)
 {
 	unsigned long val, ctrl;
@@ -1428,6 +1439,17 @@ static void lpuart32_setup_watermark(struct lpuart_port *sport)
 	lpuart32_write(&sport->port, ctrl_saved, UARTCTRL);
 }
 
+static void lpuart32_setup_watermark_enable(struct lpuart_port *sport)
+{
+	u32 temp;
+
+	lpuart32_setup_watermark(sport);
+
+	temp = lpuart32_read(&sport->port, UARTCTRL);
+	temp |= UARTCTRL_RE | UARTCTRL_TE | UARTCTRL_ILIE;
+	lpuart32_write(&sport->port, temp, UARTCTRL);
+}
+
 static void rx_dma_timer_init(struct lpuart_port *sport)
 {
 	timer_setup(&sport->lpuart_timer, lpuart_timer_func, 0);
@@ -1488,11 +1510,7 @@ static int lpuart_startup(struct uart_port *port)
 
 	spin_lock_irqsave(&sport->port.lock, flags);
 
-	lpuart_setup_watermark(sport);
-
-	temp = readb(sport->port.membase + UARTCR2);
-	temp |= UARTCR2_RIE | UARTCR2_TIE | UARTCR2_RE | UARTCR2_TE;
-	writeb(temp, sport->port.membase + UARTCR2);
+	lpuart_setup_watermark_enable(sport);
 
 	lpuart_rx_dma_startup(sport);
 	lpuart_tx_dma_startup(sport);
@@ -1538,11 +1556,7 @@ static int lpuart32_startup(struct uart_port *port)
 
 	spin_lock_irqsave(&sport->port.lock, flags);
 
-	lpuart32_setup_watermark(sport);
-
-	temp = lpuart32_read(&sport->port, UARTCTRL);
-	temp |= UARTCTRL_RE | UARTCTRL_TE | UARTCTRL_ILIE;
-	lpuart32_write(&sport->port, temp, UARTCTRL);
+	lpuart32_setup_watermark_enable(sport);
 
 
 	lpuart_rx_dma_startup(sport);
@@ -2560,22 +2574,14 @@ static int lpuart_resume(struct device *dev)
 {
 	struct lpuart_port *sport = dev_get_drvdata(dev);
 	bool irq_wake = irqd_is_wakeup_set(irq_get_irq_data(sport->port.irq));
-	unsigned long temp;
 
 	if (sport->port.suspended && !irq_wake)
 		lpuart_enable_clks(sport);
 
-	if (lpuart_is_32(sport)) {
-		lpuart32_setup_watermark(sport);
-		temp = lpuart32_read(&sport->port, UARTCTRL);
-		temp |= UARTCTRL_RE | UARTCTRL_TE | UARTCTRL_ILIE;
-		lpuart32_write(&sport->port, temp, UARTCTRL);
-	} else {
-		lpuart_setup_watermark(sport);
-		temp = readb(sport->port.membase + UARTCR2);
-		temp |= UARTCR2_RIE | UARTCR2_TIE | UARTCR2_RE | UARTCR2_TE;
-		writeb(temp, sport->port.membase + UARTCR2);
-	}
+	if (lpuart_is_32(sport))
+		lpuart32_setup_watermark_enable(sport);
+	else
+		lpuart_setup_watermark_enable(sport);
 
 	if (sport->lpuart_dma_rx_use) {
 		if (irq_wake) {
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v2 22/23] tty: serial: fsl_lpuart: Don't enable TIE in .startup() or .resume()
  2019-07-31 17:30 [PATCH v2 00/23] LPUART fixes and improvements Andrey Smirnov
                   ` (20 preceding siblings ...)
  2019-07-31 17:30 ` [PATCH v2 21/23] tty: serial: fsl_lpuart: Introduce lpuart*_setup_watermark_enable() Andrey Smirnov
@ 2019-07-31 17:30 ` Andrey Smirnov
  2019-07-31 17:30 ` [PATCH v2 23/23] tty: serial: fsl_lpuart: Ignore TX/RX interrupts if DMA is enabled Andrey Smirnov
  2019-07-31 17:59 ` [PATCH v2 00/23] LPUART fixes and improvements Fabio Estevam
  23 siblings, 0 replies; 26+ messages in thread
From: Andrey Smirnov @ 2019-07-31 17:30 UTC (permalink / raw)
  To: linux-serial
  Cc: Andrey Smirnov, Stefan Agner, Chris Healy, Cory Tusar,
	Lucas Stach, Greg Kroah-Hartman, Jiri Slaby, linux-imx,
	linux-kernel

Enabling TIE in .startup() callback causes the driver to start (or at
least try) to transmit data before .start_tx() is called. Which, while
harmless (since TIE handler will immediately disable it), is a no-op
and shouldn't really happen. Drop UARTCR2_TIE from list of bits set in
lpuart_startup().

This change will also not enable TIE in .resume(), but it seems that,
similart to .startup(), transmit interrupt shouldn't be enabled there
either.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
Cc: Stefan Agner <stefan@agner.ch>
Cc: Chris Healy <cphealy@gmail.com>
Cc: Cory Tusar <cory.tusar@zii.aero>
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: linux-imx@nxp.com
Cc: linux-serial@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/tty/serial/fsl_lpuart.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 8ab5f9939597..237690a6e80a 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -1410,7 +1410,7 @@ static void lpuart_setup_watermark_enable(struct lpuart_port *sport)
 	lpuart_setup_watermark(sport);
 
 	cr2 = readb(sport->port.membase + UARTCR2);
-	cr2 |= UARTCR2_RIE | UARTCR2_TIE | UARTCR2_RE | UARTCR2_TE;
+	cr2 |= UARTCR2_RIE | UARTCR2_RE | UARTCR2_TE;
 	writeb(cr2, sport->port.membase + UARTCR2);
 }
 
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v2 23/23] tty: serial: fsl_lpuart: Ignore TX/RX interrupts if DMA is enabled
  2019-07-31 17:30 [PATCH v2 00/23] LPUART fixes and improvements Andrey Smirnov
                   ` (21 preceding siblings ...)
  2019-07-31 17:30 ` [PATCH v2 22/23] tty: serial: fsl_lpuart: Don't enable TIE in .startup() or .resume() Andrey Smirnov
@ 2019-07-31 17:30 ` Andrey Smirnov
  2019-07-31 17:59 ` [PATCH v2 00/23] LPUART fixes and improvements Fabio Estevam
  23 siblings, 0 replies; 26+ messages in thread
From: Andrey Smirnov @ 2019-07-31 17:30 UTC (permalink / raw)
  To: linux-serial
  Cc: Andrey Smirnov, Stefan Agner, Chris Healy, Cory Tusar,
	Lucas Stach, Greg Kroah-Hartman, Jiri Slaby, linux-imx,
	linux-kernel

In a mixed DMA/IRQ use-case (e.g.: DMA for TX, IRQ for RX), interrupt
handler might try to handle Rx/Tx condition it shouldn't. Change the
code to only handle TX/RX event if corresponding path isn't being
handled by DMA.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
Cc: Stefan Agner <stefan@agner.ch>
Cc: Chris Healy <cphealy@gmail.com>
Cc: Cory Tusar <cory.tusar@zii.aero>
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: linux-imx@nxp.com
Cc: linux-serial@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/tty/serial/fsl_lpuart.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 237690a6e80a..e758ca57113f 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -967,10 +967,10 @@ static irqreturn_t lpuart_int(int irq, void *dev_id)
 
 	sts = readb(sport->port.membase + UARTSR1);
 
-	if (sts & UARTSR1_RDRF)
+	if (sts & UARTSR1_RDRF && !sport->lpuart_dma_rx_use)
 		lpuart_rxint(sport);
 
-	if (sts & UARTSR1_TDRE)
+	if (sts & UARTSR1_TDRE && !sport->lpuart_dma_tx_use)
 		lpuart_txint(sport);
 
 	return IRQ_HANDLED;
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [PATCH v2 00/23] LPUART fixes and improvements
  2019-07-31 17:30 [PATCH v2 00/23] LPUART fixes and improvements Andrey Smirnov
                   ` (22 preceding siblings ...)
  2019-07-31 17:30 ` [PATCH v2 23/23] tty: serial: fsl_lpuart: Ignore TX/RX interrupts if DMA is enabled Andrey Smirnov
@ 2019-07-31 17:59 ` Fabio Estevam
  2019-08-01 15:14   ` Greg Kroah-Hartman
  23 siblings, 1 reply; 26+ messages in thread
From: Fabio Estevam @ 2019-07-31 17:59 UTC (permalink / raw)
  To: Andrey Smirnov
  Cc: linux-serial, Stefan Agner, Chris Healy, Cory Tusar, Lucas Stach,
	Greg Kroah-Hartman, Jiri Slaby, NXP Linux Team, linux-kernel

Hi Andrey,

On Wed, Jul 31, 2019 at 2:53 PM Andrey Smirnov <andrew.smirnov@gmail.com> wrote:
>
> Everyone:
>
> This series contains fixes/improvements to LPUART dirver I came up
> with recently as well as fixes picked up from Toradex and NXP Vybrid
> repos.
>
> Feedback is welcome!
>
> Changes since [v1]:

Greg has already applied some of these patches:
https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git/log/?h=tty-testing

Please rebase on his tree and send the remaining ones.

Thanks

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v2 00/23] LPUART fixes and improvements
  2019-07-31 17:59 ` [PATCH v2 00/23] LPUART fixes and improvements Fabio Estevam
@ 2019-08-01 15:14   ` Greg Kroah-Hartman
  0 siblings, 0 replies; 26+ messages in thread
From: Greg Kroah-Hartman @ 2019-08-01 15:14 UTC (permalink / raw)
  To: Fabio Estevam
  Cc: Andrey Smirnov, linux-serial, Stefan Agner, Chris Healy,
	Cory Tusar, Lucas Stach, Jiri Slaby, NXP Linux Team,
	linux-kernel

On Wed, Jul 31, 2019 at 02:59:59PM -0300, Fabio Estevam wrote:
> Hi Andrey,
> 
> On Wed, Jul 31, 2019 at 2:53 PM Andrey Smirnov <andrew.smirnov@gmail.com> wrote:
> >
> > Everyone:
> >
> > This series contains fixes/improvements to LPUART dirver I came up
> > with recently as well as fixes picked up from Toradex and NXP Vybrid
> > repos.
> >
> > Feedback is welcome!
> >
> > Changes since [v1]:
> 
> Greg has already applied some of these patches:
> https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git/log/?h=tty-testing
> 
> Please rebase on his tree and send the remaining ones.

Yes, I can't drop patches I have already applied.  Andrey, just resend
the ones that I have not applied.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2019-08-01 15:14 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-07-31 17:30 [PATCH v2 00/23] LPUART fixes and improvements Andrey Smirnov
2019-07-31 17:30 ` [PATCH v2 01/23] tty: serial: fsl_lpuart: fix framing error handling when using DMA Andrey Smirnov
2019-07-31 17:30 ` [PATCH v2 02/23] tty: serial: fsl_lpuart: flush receive FIFO after overruns Andrey Smirnov
2019-07-31 17:30 ` [PATCH v2 03/23] tty: serial: fsl_lpuart: Flush HW FIFOs in .flush_buffer Andrey Smirnov
2019-07-31 17:30 ` [PATCH v2 04/23] tty: serial: fsl_lpuart: Simplify RX/TX IRQ handlers Andrey Smirnov
2019-07-31 17:30 ` [PATCH v2 05/23] tty: serial: fsl_lpuart: Fix bogus indentation Andrey Smirnov
2019-07-31 17:30 ` [PATCH v2 06/23] tty: serial: fsl_lpuart: Drop unnecessary uart_write_wakeup() Andrey Smirnov
2019-07-31 17:30 ` [PATCH v2 07/23] tty: serial: fsl_lpuart: Fix issue in software flow control Andrey Smirnov
2019-07-31 17:30 ` [PATCH v2 08/23] tty: serial: fls_lpuart: Split shared TX IRQ handler into two Andrey Smirnov
2019-07-31 17:30 ` [PATCH v2 09/23] tty: serial: fsl_lpuart: Drop no-op bit opearation Andrey Smirnov
2019-07-31 17:30 ` [PATCH v2 10/23] tty: serial: fsl_lpuart: Drop unnecessary extra parenthesis Andrey Smirnov
2019-07-31 17:30 ` [PATCH v2 11/23] tty: serial: fsl_lpuart: Clear CSTOPB unconditionally Andrey Smirnov
2019-07-31 17:30 ` [PATCH v2 12/23] tty: serial: fsl_lpuart: Use appropriate lpuart32_* I/O funcs Andrey Smirnov
2019-07-31 17:30 ` [PATCH v2 13/23] tty: serial: fsl_lpuart: Introduce lpuart_wait_bit_set() Andrey Smirnov
2019-07-31 17:30 ` [PATCH v2 14/23] tty: serial: fsl_lpuart: Use cpu_relax() instead of barrier() Andrey Smirnov
2019-07-31 17:30 ` [PATCH v2 15/23] tty: serial: fsl_lpuart: Introduce lpuart_stopped_or_empty() Andrey Smirnov
2019-07-31 17:30 ` [PATCH v2 16/23] tty: serial: fsl_lpuart: Drop unnecessary lpuart*_stop_tx() Andrey Smirnov
2019-07-31 17:30 ` [PATCH v2 17/23] tty: serial: fsl_lpuart: Introduce lpuart_dma_shutdown() Andrey Smirnov
2019-07-31 17:30 ` [PATCH v2 18/23] tty: serial: fsl_lpuart: Introduce lpuart_tx_dma_startup() Andrey Smirnov
2019-07-31 17:30 ` [PATCH v2 19/23] tty: serial: fsl_lpuart: Introduce lpuart_rx_dma_startup() Andrey Smirnov
2019-07-31 17:30 ` [PATCH v2 20/23] tty: serial: fsl_lpuart: Introduce lpuart32_configure() Andrey Smirnov
2019-07-31 17:30 ` [PATCH v2 21/23] tty: serial: fsl_lpuart: Introduce lpuart*_setup_watermark_enable() Andrey Smirnov
2019-07-31 17:30 ` [PATCH v2 22/23] tty: serial: fsl_lpuart: Don't enable TIE in .startup() or .resume() Andrey Smirnov
2019-07-31 17:30 ` [PATCH v2 23/23] tty: serial: fsl_lpuart: Ignore TX/RX interrupts if DMA is enabled Andrey Smirnov
2019-07-31 17:59 ` [PATCH v2 00/23] LPUART fixes and improvements Fabio Estevam
2019-08-01 15:14   ` Greg Kroah-Hartman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).