+++ /dev/null
-From edf11620c93fc1a9a7b3dbbdb5eccb8e45608c79 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Sun, 11 Sep 2022 11:02:03 +0200
-Subject: serial: stm32: Deassert Transmit Enable on ->rs485_config()
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-From: Lukas Wunner <lukas@wunner.de>
-
-[ Upstream commit adafbbf6895eb0ce41a313c6ee68870ab9aa93cd ]
-
-The STM32 USART can control RS-485 Transmit Enable in hardware. Since
-commit 7df5081cbf5e ("serial: stm32: Add RS485 RTS GPIO control"),
-it can alternatively be controlled in software. That was done to allow
-RS-485 even if the RTS pin is unavailable because it's pinmuxed to a
-different function.
-
-However the commit neglected to deassert Transmit Enable upon invocation
-of the ->rs485_config() callback. Fix it.
-
-Avoid forward declarations by moving stm32_usart_tx_empty(),
-stm32_usart_rs485_rts_enable() and stm32_usart_rs485_rts_disable()
-further up in the driver.
-
-Fixes: 7df5081cbf5e ("serial: stm32: Add RS485 RTS GPIO control")
-Cc: stable@vger.kernel.org # v5.9+
-Cc: Marek Vasut <marex@denx.de>
-Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
-Signed-off-by: Lukas Wunner <lukas@wunner.de>
-Link: https://lore.kernel.org/r/6059eab35dba394468335ef640df8b0050fd9dbd.1662886616.git.lukas@wunner.de
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/tty/serial/stm32-usart.c | 100 ++++++++++++++++---------------
- 1 file changed, 53 insertions(+), 47 deletions(-)
-
-diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
-index 4a4108ef23e8..c2daf8c151e6 100644
---- a/drivers/tty/serial/stm32-usart.c
-+++ b/drivers/tty/serial/stm32-usart.c
-@@ -61,6 +61,53 @@ static void stm32_usart_clr_bits(struct uart_port *port, u32 reg, u32 bits)
- writel_relaxed(val, port->membase + reg);
- }
-
-+static unsigned int stm32_usart_tx_empty(struct uart_port *port)
-+{
-+ struct stm32_port *stm32_port = to_stm32_port(port);
-+ const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
-+
-+ if (readl_relaxed(port->membase + ofs->isr) & USART_SR_TC)
-+ return TIOCSER_TEMT;
-+
-+ return 0;
-+}
-+
-+static void stm32_usart_rs485_rts_enable(struct uart_port *port)
-+{
-+ struct stm32_port *stm32_port = to_stm32_port(port);
-+ struct serial_rs485 *rs485conf = &port->rs485;
-+
-+ if (stm32_port->hw_flow_control ||
-+ !(rs485conf->flags & SER_RS485_ENABLED))
-+ return;
-+
-+ if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
-+ mctrl_gpio_set(stm32_port->gpios,
-+ stm32_port->port.mctrl | TIOCM_RTS);
-+ } else {
-+ mctrl_gpio_set(stm32_port->gpios,
-+ stm32_port->port.mctrl & ~TIOCM_RTS);
-+ }
-+}
-+
-+static void stm32_usart_rs485_rts_disable(struct uart_port *port)
-+{
-+ struct stm32_port *stm32_port = to_stm32_port(port);
-+ struct serial_rs485 *rs485conf = &port->rs485;
-+
-+ if (stm32_port->hw_flow_control ||
-+ !(rs485conf->flags & SER_RS485_ENABLED))
-+ return;
-+
-+ if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
-+ mctrl_gpio_set(stm32_port->gpios,
-+ stm32_port->port.mctrl & ~TIOCM_RTS);
-+ } else {
-+ mctrl_gpio_set(stm32_port->gpios,
-+ stm32_port->port.mctrl | TIOCM_RTS);
-+ }
-+}
-+
- static void stm32_usart_config_reg_rs485(u32 *cr1, u32 *cr3, u32 delay_ADE,
- u32 delay_DDE, u32 baud)
- {
-@@ -149,6 +196,12 @@ static int stm32_usart_config_rs485(struct uart_port *port,
-
- stm32_usart_set_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit));
-
-+ /* Adjust RTS polarity in case it's driven in software */
-+ if (stm32_usart_tx_empty(port))
-+ stm32_usart_rs485_rts_disable(port);
-+ else
-+ stm32_usart_rs485_rts_enable(port);
-+
- return 0;
- }
-
-@@ -436,42 +489,6 @@ static void stm32_usart_tc_interrupt_disable(struct uart_port *port)
- stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_TCIE);
- }
-
--static void stm32_usart_rs485_rts_enable(struct uart_port *port)
--{
-- struct stm32_port *stm32_port = to_stm32_port(port);
-- struct serial_rs485 *rs485conf = &port->rs485;
--
-- if (stm32_port->hw_flow_control ||
-- !(rs485conf->flags & SER_RS485_ENABLED))
-- return;
--
-- if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
-- mctrl_gpio_set(stm32_port->gpios,
-- stm32_port->port.mctrl | TIOCM_RTS);
-- } else {
-- mctrl_gpio_set(stm32_port->gpios,
-- stm32_port->port.mctrl & ~TIOCM_RTS);
-- }
--}
--
--static void stm32_usart_rs485_rts_disable(struct uart_port *port)
--{
-- struct stm32_port *stm32_port = to_stm32_port(port);
-- struct serial_rs485 *rs485conf = &port->rs485;
--
-- if (stm32_port->hw_flow_control ||
-- !(rs485conf->flags & SER_RS485_ENABLED))
-- return;
--
-- if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
-- mctrl_gpio_set(stm32_port->gpios,
-- stm32_port->port.mctrl & ~TIOCM_RTS);
-- } else {
-- mctrl_gpio_set(stm32_port->gpios,
-- stm32_port->port.mctrl | TIOCM_RTS);
-- }
--}
--
- static void stm32_usart_transmit_chars_pio(struct uart_port *port)
- {
- struct stm32_port *stm32_port = to_stm32_port(port);
-@@ -689,17 +706,6 @@ static irqreturn_t stm32_usart_threaded_interrupt(int irq, void *ptr)
- return IRQ_HANDLED;
- }
-
--static unsigned int stm32_usart_tx_empty(struct uart_port *port)
--{
-- struct stm32_port *stm32_port = to_stm32_port(port);
-- const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
--
-- if (readl_relaxed(port->membase + ofs->isr) & USART_SR_TC)
-- return TIOCSER_TEMT;
--
-- return 0;
--}
--
- static void stm32_usart_set_mctrl(struct uart_port *port, unsigned int mctrl)
- {
- struct stm32_port *stm32_port = to_stm32_port(port);
---
-2.35.1
-
+++ /dev/null
-From dd8c5cbb18aa72a3448ed2c02910460c8e789c43 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Sat, 30 Apr 2022 18:28:44 +0200
-Subject: serial: stm32: Factor out GPIO RTS toggling into separate function
-
-From: Marek Vasut <marex@denx.de>
-
-[ Upstream commit 3bcea529b295a993b1b05db63f245ae8030c5acf ]
-
-Pull out the GPIO RTS enable and disable handling into separate function.
-Limit the scope of GPIO RTS toggling only to GPIO emulated RS485 too.
-
-Signed-off-by: Marek Vasut <marex@denx.de>
-Cc: Alexandre Torgue <alexandre.torgue@foss.st.com>
-Cc: Erwan Le Ray <erwan.leray@foss.st.com>
-Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-Cc: Jean Philippe Romain <jean-philippe.romain@foss.st.com>
-Cc: Valentin Caron <valentin.caron@foss.st.com>
-Cc: linux-arm-kernel@lists.infradead.org
-Cc: linux-stm32@st-md-mailman.stormreply.com
-To: linux-serial@vger.kernel.org
-Link: https://lore.kernel.org/r/20220430162845.244655-1-marex@denx.de
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-Stable-dep-of: adafbbf6895e ("serial: stm32: Deassert Transmit Enable on ->rs485_config()")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/tty/serial/stm32-usart.c | 59 ++++++++++++++++++++------------
- 1 file changed, 38 insertions(+), 21 deletions(-)
-
-diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
-index b4c512b138df..0e7bcbaf7268 100644
---- a/drivers/tty/serial/stm32-usart.c
-+++ b/drivers/tty/serial/stm32-usart.c
-@@ -420,6 +420,42 @@ static void stm32_usart_tx_interrupt_disable(struct uart_port *port)
- stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_TXEIE);
- }
-
-+static void stm32_usart_rs485_rts_enable(struct uart_port *port)
-+{
-+ struct stm32_port *stm32_port = to_stm32_port(port);
-+ struct serial_rs485 *rs485conf = &port->rs485;
-+
-+ if (stm32_port->hw_flow_control ||
-+ !(rs485conf->flags & SER_RS485_ENABLED))
-+ return;
-+
-+ if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
-+ mctrl_gpio_set(stm32_port->gpios,
-+ stm32_port->port.mctrl | TIOCM_RTS);
-+ } else {
-+ mctrl_gpio_set(stm32_port->gpios,
-+ stm32_port->port.mctrl & ~TIOCM_RTS);
-+ }
-+}
-+
-+static void stm32_usart_rs485_rts_disable(struct uart_port *port)
-+{
-+ struct stm32_port *stm32_port = to_stm32_port(port);
-+ struct serial_rs485 *rs485conf = &port->rs485;
-+
-+ if (stm32_port->hw_flow_control ||
-+ !(rs485conf->flags & SER_RS485_ENABLED))
-+ return;
-+
-+ if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
-+ mctrl_gpio_set(stm32_port->gpios,
-+ stm32_port->port.mctrl & ~TIOCM_RTS);
-+ } else {
-+ mctrl_gpio_set(stm32_port->gpios,
-+ stm32_port->port.mctrl | TIOCM_RTS);
-+ }
-+}
-+
- static void stm32_usart_transmit_chars_pio(struct uart_port *port)
- {
- struct stm32_port *stm32_port = to_stm32_port(port);
-@@ -666,40 +702,21 @@ static void stm32_usart_disable_ms(struct uart_port *port)
- static void stm32_usart_stop_tx(struct uart_port *port)
- {
- struct stm32_port *stm32_port = to_stm32_port(port);
-- struct serial_rs485 *rs485conf = &port->rs485;
-
- stm32_usart_tx_interrupt_disable(port);
-
-- if (rs485conf->flags & SER_RS485_ENABLED) {
-- if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
-- mctrl_gpio_set(stm32_port->gpios,
-- stm32_port->port.mctrl & ~TIOCM_RTS);
-- } else {
-- mctrl_gpio_set(stm32_port->gpios,
-- stm32_port->port.mctrl | TIOCM_RTS);
-- }
-- }
-+ stm32_usart_rs485_rts_disable(port);
- }
-
- /* There are probably characters waiting to be transmitted. */
- static void stm32_usart_start_tx(struct uart_port *port)
- {
-- struct stm32_port *stm32_port = to_stm32_port(port);
-- struct serial_rs485 *rs485conf = &port->rs485;
- struct circ_buf *xmit = &port->state->xmit;
-
- if (uart_circ_empty(xmit) && !port->x_char)
- return;
-
-- if (rs485conf->flags & SER_RS485_ENABLED) {
-- if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
-- mctrl_gpio_set(stm32_port->gpios,
-- stm32_port->port.mctrl | TIOCM_RTS);
-- } else {
-- mctrl_gpio_set(stm32_port->gpios,
-- stm32_port->port.mctrl & ~TIOCM_RTS);
-- }
-- }
-+ stm32_usart_rs485_rts_enable(port);
-
- stm32_usart_transmit_chars(port);
- }
---
-2.35.1
-
+++ /dev/null
-From 8661fb04fedaa722480ba4fb0410ea9801db0c65 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 20 Oct 2021 17:03:30 +0200
-Subject: serial: stm32: re-introduce an irq flag condition in
- usart_receive_chars
-
-From: Erwan Le Ray <erwan.leray@foss.st.com>
-
-[ Upstream commit cc58d0a3f0a4755b9c808e065d9227c6e984e7db ]
-
-Re-introduce an irq flag condition in usart_receive_chars.
-This condition has been deleted by commit 75f4e830fa9c ("serial: do not
-restore interrupt state in sysrq helper").
-This code was present to handle threaded case, and has been removed
-because it is no more needed in this case. Nevertheless an irq safe lock
-is still needed in some cases, when DMA should be stopped to receive errors
-or breaks in PIO mode.
-This patch is a precursor to the complete rework or stm32 serial driver
-DMA implementation.
-
-Signed-off-by: Erwan Le Ray <erwan.leray@foss.st.com>
-Link: https://lore.kernel.org/r/20211020150332.10214-2-erwan.leray@foss.st.com
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-Stable-dep-of: adafbbf6895e ("serial: stm32: Deassert Transmit Enable on ->rs485_config()")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/tty/serial/stm32-usart.c | 21 +++++++++++++--------
- 1 file changed, 13 insertions(+), 8 deletions(-)
-
-diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
-index fc166cc2c856..bba4facf7425 100644
---- a/drivers/tty/serial/stm32-usart.c
-+++ b/drivers/tty/serial/stm32-usart.c
-@@ -211,19 +211,22 @@ static unsigned long stm32_usart_get_char(struct uart_port *port, u32 *sr,
- return c;
- }
-
--static void stm32_usart_receive_chars(struct uart_port *port, bool threaded)
-+static void stm32_usart_receive_chars(struct uart_port *port, bool irqflag)
- {
- struct tty_port *tport = &port->state->port;
- struct stm32_port *stm32_port = to_stm32_port(port);
- const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
-- unsigned long c;
-+ unsigned long c, flags;
- u32 sr;
- char flag;
-
-- spin_lock(&port->lock);
-+ if (irqflag)
-+ spin_lock_irqsave(&port->lock, flags);
-+ else
-+ spin_lock(&port->lock);
-
- while (stm32_usart_pending_rx(port, &sr, &stm32_port->last_res,
-- threaded)) {
-+ irqflag)) {
- sr |= USART_SR_DUMMY_RX;
- flag = TTY_NORMAL;
-
-@@ -277,7 +280,10 @@ static void stm32_usart_receive_chars(struct uart_port *port, bool threaded)
- uart_insert_char(port, sr, USART_SR_ORE, c, flag);
- }
-
-- uart_unlock_and_check_sysrq(port);
-+ if (irqflag)
-+ uart_unlock_and_check_sysrq_irqrestore(port, irqflag);
-+ else
-+ uart_unlock_and_check_sysrq(port);
-
- tty_flip_buffer_push(tport);
- }
-@@ -510,10 +516,9 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
- static irqreturn_t stm32_usart_threaded_interrupt(int irq, void *ptr)
- {
- struct uart_port *port = ptr;
-- struct stm32_port *stm32_port = to_stm32_port(port);
-
-- if (stm32_port->rx_ch)
-- stm32_usart_receive_chars(port, true);
-+ /* Receiver timeout irq for DMA RX */
-+ stm32_usart_receive_chars(port, false);
-
- return IRQ_HANDLED;
- }
---
-2.35.1
-
+++ /dev/null
-From bf8b05df5e2e3aec519732bb58eab724f82aeff1 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 20 Oct 2021 17:03:31 +0200
-Subject: serial: stm32: rework RX over DMA
-
-From: Erwan Le Ray <erwan.leray@foss.st.com>
-
-[ Upstream commit 33bb2f6ac3088936b7aad3cab6f439f91af0223c ]
-
-This patch reworks RX support over DMA to improve reliability:
-- change dma buffer cyclic configuration by using 2 periods. DMA buffer
-data are handled by a flip-flop between the 2 periods in order to avoid
-risk of data loss/corruption
-- change the size of dma buffer to 4096 to limit overruns
-- add rx errors management (breaks, parity, framing and overrun).
- When an error occurs on the uart line, the dma request line is masked at
- HW level. The SW must 1st clear DMAR (dma request line enable), to
- handle the error, then re-enable DMAR to recover. So, any correct data
- is taken from the DMA buffer, before handling the error itself. Then
- errors are handled from RDR/ISR/FIFO (e.g. in PIO mode). Last, DMA
- reception is resumed.
-- add a condition on DMA request line in DMA RX routines in order to
-switch to PIO mode when no DMA request line is disabled, even if the DMA
-channel is still enabled.
- When the UART is wakeup source and is configured to use DMA for RX, any
- incoming data that wakes up the system isn't correctly received.
- At data reception, the irq_handler handles the WUF irq, and then the
- data reception over DMA.
- As the DMA transfer has been terminated at suspend, and will be restored
- by resume callback (which has no yet been called by system), the data
- can't be received.
- The wake-up data has to be handled in PIO mode while suspend callback
- has not been called.
-
-Signed-off-by: Valentin Caron <valentin.caron@foss.st.com>
-Signed-off-by: Erwan Le Ray <erwan.leray@foss.st.com>
-Link: https://lore.kernel.org/r/20211020150332.10214-3-erwan.leray@foss.st.com
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-Stable-dep-of: adafbbf6895e ("serial: stm32: Deassert Transmit Enable on ->rs485_config()")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/tty/serial/stm32-usart.c | 206 ++++++++++++++++++++++++-------
- drivers/tty/serial/stm32-usart.h | 12 +-
- 2 files changed, 165 insertions(+), 53 deletions(-)
-
-diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
-index bba4facf7425..b4c512b138df 100644
---- a/drivers/tty/serial/stm32-usart.c
-+++ b/drivers/tty/serial/stm32-usart.c
-@@ -167,66 +167,60 @@ static int stm32_usart_init_rs485(struct uart_port *port,
- return uart_get_rs485_mode(port);
- }
-
--static int stm32_usart_pending_rx(struct uart_port *port, u32 *sr,
-- int *last_res, bool threaded)
-+static bool stm32_usart_rx_dma_enabled(struct uart_port *port)
- {
- struct stm32_port *stm32_port = to_stm32_port(port);
- const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
-- enum dma_status status;
-- struct dma_tx_state state;
-
-- *sr = readl_relaxed(port->membase + ofs->isr);
-+ if (!stm32_port->rx_ch)
-+ return false;
-
-- if (threaded && stm32_port->rx_ch) {
-- status = dmaengine_tx_status(stm32_port->rx_ch,
-- stm32_port->rx_ch->cookie,
-- &state);
-- if (status == DMA_IN_PROGRESS && (*last_res != state.residue))
-- return 1;
-- else
-- return 0;
-- } else if (*sr & USART_SR_RXNE) {
-- return 1;
-+ return !!(readl_relaxed(port->membase + ofs->cr3) & USART_CR3_DMAR);
-+}
-+
-+/* Return true when data is pending (in pio mode), and false when no data is pending. */
-+static bool stm32_usart_pending_rx_pio(struct uart_port *port, u32 *sr)
-+{
-+ struct stm32_port *stm32_port = to_stm32_port(port);
-+ const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
-+
-+ *sr = readl_relaxed(port->membase + ofs->isr);
-+ /* Get pending characters in RDR or FIFO */
-+ if (*sr & USART_SR_RXNE) {
-+ /* Get all pending characters from the RDR or the FIFO when using interrupts */
-+ if (!stm32_usart_rx_dma_enabled(port))
-+ return true;
-+
-+ /* Handle only RX data errors when using DMA */
-+ if (*sr & USART_SR_ERR_MASK)
-+ return true;
- }
-- return 0;
-+
-+ return false;
- }
-
--static unsigned long stm32_usart_get_char(struct uart_port *port, u32 *sr,
-- int *last_res)
-+static unsigned long stm32_usart_get_char_pio(struct uart_port *port)
- {
- struct stm32_port *stm32_port = to_stm32_port(port);
- const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
- unsigned long c;
-
-- if (stm32_port->rx_ch) {
-- c = stm32_port->rx_buf[RX_BUF_L - (*last_res)--];
-- if ((*last_res) == 0)
-- *last_res = RX_BUF_L;
-- } else {
-- c = readl_relaxed(port->membase + ofs->rdr);
-- /* apply RDR data mask */
-- c &= stm32_port->rdr_mask;
-- }
-+ c = readl_relaxed(port->membase + ofs->rdr);
-+ /* Apply RDR data mask */
-+ c &= stm32_port->rdr_mask;
-
- return c;
- }
-
--static void stm32_usart_receive_chars(struct uart_port *port, bool irqflag)
-+static void stm32_usart_receive_chars_pio(struct uart_port *port)
- {
-- struct tty_port *tport = &port->state->port;
- struct stm32_port *stm32_port = to_stm32_port(port);
- const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
-- unsigned long c, flags;
-+ unsigned long c;
- u32 sr;
- char flag;
-
-- if (irqflag)
-- spin_lock_irqsave(&port->lock, flags);
-- else
-- spin_lock(&port->lock);
--
-- while (stm32_usart_pending_rx(port, &sr, &stm32_port->last_res,
-- irqflag)) {
-+ while (stm32_usart_pending_rx_pio(port, &sr)) {
- sr |= USART_SR_DUMMY_RX;
- flag = TTY_NORMAL;
-
-@@ -245,7 +239,7 @@ static void stm32_usart_receive_chars(struct uart_port *port, bool irqflag)
- writel_relaxed(sr & USART_SR_ERR_MASK,
- port->membase + ofs->icr);
-
-- c = stm32_usart_get_char(port, &sr, &stm32_port->last_res);
-+ c = stm32_usart_get_char_pio(port);
- port->icount.rx++;
- if (sr & USART_SR_ERR_MASK) {
- if (sr & USART_SR_ORE) {
-@@ -279,6 +273,94 @@ static void stm32_usart_receive_chars(struct uart_port *port, bool irqflag)
- continue;
- uart_insert_char(port, sr, USART_SR_ORE, c, flag);
- }
-+}
-+
-+static void stm32_usart_push_buffer_dma(struct uart_port *port, unsigned int dma_size)
-+{
-+ struct stm32_port *stm32_port = to_stm32_port(port);
-+ struct tty_port *ttyport = &stm32_port->port.state->port;
-+ unsigned char *dma_start;
-+ int dma_count, i;
-+
-+ dma_start = stm32_port->rx_buf + (RX_BUF_L - stm32_port->last_res);
-+
-+ /*
-+ * Apply rdr_mask on buffer in order to mask parity bit.
-+ * This loop is useless in cs8 mode because DMA copies only
-+ * 8 bits and already ignores parity bit.
-+ */
-+ if (!(stm32_port->rdr_mask == (BIT(8) - 1)))
-+ for (i = 0; i < dma_size; i++)
-+ *(dma_start + i) &= stm32_port->rdr_mask;
-+
-+ dma_count = tty_insert_flip_string(ttyport, dma_start, dma_size);
-+ port->icount.rx += dma_count;
-+ if (dma_count != dma_size)
-+ port->icount.buf_overrun++;
-+ stm32_port->last_res -= dma_count;
-+ if (stm32_port->last_res == 0)
-+ stm32_port->last_res = RX_BUF_L;
-+}
-+
-+static void stm32_usart_receive_chars_dma(struct uart_port *port)
-+{
-+ struct stm32_port *stm32_port = to_stm32_port(port);
-+ unsigned int dma_size;
-+
-+ /* DMA buffer is configured in cyclic mode and handles the rollback of the buffer. */
-+ if (stm32_port->rx_dma_state.residue > stm32_port->last_res) {
-+ /* Conditional first part: from last_res to end of DMA buffer */
-+ dma_size = stm32_port->last_res;
-+ stm32_usart_push_buffer_dma(port, dma_size);
-+ }
-+
-+ dma_size = stm32_port->last_res - stm32_port->rx_dma_state.residue;
-+ stm32_usart_push_buffer_dma(port, dma_size);
-+}
-+
-+static void stm32_usart_receive_chars(struct uart_port *port, bool irqflag)
-+{
-+ struct tty_port *tport = &port->state->port;
-+ struct stm32_port *stm32_port = to_stm32_port(port);
-+ const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
-+ enum dma_status rx_dma_status;
-+ unsigned long flags;
-+ u32 sr;
-+
-+ if (irqflag)
-+ spin_lock_irqsave(&port->lock, flags);
-+ else
-+ spin_lock(&port->lock);
-+
-+ if (stm32_usart_rx_dma_enabled(port)) {
-+ rx_dma_status = dmaengine_tx_status(stm32_port->rx_ch,
-+ stm32_port->rx_ch->cookie,
-+ &stm32_port->rx_dma_state);
-+ if (rx_dma_status == DMA_IN_PROGRESS) {
-+ /* Empty DMA buffer */
-+ stm32_usart_receive_chars_dma(port);
-+ sr = readl_relaxed(port->membase + ofs->isr);
-+ if (sr & USART_SR_ERR_MASK) {
-+ /* Disable DMA request line */
-+ stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAR);
-+
-+ /* Switch to PIO mode to handle the errors */
-+ stm32_usart_receive_chars_pio(port);
-+
-+ /* Switch back to DMA mode */
-+ stm32_usart_set_bits(port, ofs->cr3, USART_CR3_DMAR);
-+ }
-+ } else {
-+ /* Disable RX DMA */
-+ dmaengine_terminate_async(stm32_port->rx_ch);
-+ stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAR);
-+ /* Fall back to interrupt mode */
-+ dev_dbg(port->dev, "DMA error, fallback to irq mode\n");
-+ stm32_usart_receive_chars_pio(port);
-+ }
-+ } else {
-+ stm32_usart_receive_chars_pio(port);
-+ }
-
- if (irqflag)
- uart_unlock_and_check_sysrq_irqrestore(port, irqflag);
-@@ -320,6 +402,13 @@ static void stm32_usart_tx_interrupt_enable(struct uart_port *port)
- stm32_usart_set_bits(port, ofs->cr1, USART_CR1_TXEIE);
- }
-
-+static void stm32_usart_rx_dma_complete(void *arg)
-+{
-+ struct uart_port *port = arg;
-+
-+ stm32_usart_receive_chars(port, true);
-+}
-+
- static void stm32_usart_tx_interrupt_disable(struct uart_port *port)
- {
- struct stm32_port *stm32_port = to_stm32_port(port);
-@@ -498,7 +587,12 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
- pm_wakeup_event(tport->tty->dev, 0);
- }
-
-- if ((sr & USART_SR_RXNE) && !(stm32_port->rx_ch))
-+ /*
-+ * rx errors in dma mode has to be handled ASAP to avoid overrun as the DMA request
-+ * line has been masked by HW and rx data are stacking in FIFO.
-+ */
-+ if (((sr & USART_SR_RXNE) && !stm32_usart_rx_dma_enabled(port)) ||
-+ ((sr & USART_SR_ERR_MASK) && stm32_usart_rx_dma_enabled(port)))
- stm32_usart_receive_chars(port, false);
-
- if ((sr & USART_SR_TXE) && !(stm32_port->tx_ch)) {
-@@ -507,7 +601,7 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
- spin_unlock(&port->lock);
- }
-
-- if (stm32_port->rx_ch)
-+ if (stm32_usart_rx_dma_enabled(port))
- return IRQ_WAKE_THREAD;
- else
- return IRQ_HANDLED;
-@@ -843,9 +937,11 @@ static void stm32_usart_set_termios(struct uart_port *port,
- stm32_port->cr1_irq = USART_CR1_RTOIE;
- writel_relaxed(bits, port->membase + ofs->rtor);
- cr2 |= USART_CR2_RTOEN;
-- /* Not using dma, enable fifo threshold irq */
-- if (!stm32_port->rx_ch)
-- stm32_port->cr3_irq = USART_CR3_RXFTIE;
-+ /*
-+ * Enable fifo threshold irq in two cases, either when there is no DMA, or when
-+ * wake up over usart, from low power until the DMA gets re-enabled by resume.
-+ */
-+ stm32_port->cr3_irq = USART_CR3_RXFTIE;
- }
-
- cr1 |= stm32_port->cr1_irq;
-@@ -908,8 +1004,16 @@ static void stm32_usart_set_termios(struct uart_port *port,
- if ((termios->c_cflag & CREAD) == 0)
- port->ignore_status_mask |= USART_SR_DUMMY_RX;
-
-- if (stm32_port->rx_ch)
-+ if (stm32_port->rx_ch) {
-+ /*
-+ * Setup DMA to collect only valid data and enable error irqs.
-+ * This also enables break reception when using DMA.
-+ */
-+ cr1 |= USART_CR1_PEIE;
-+ cr3 |= USART_CR3_EIE;
- cr3 |= USART_CR3_DMAR;
-+ cr3 |= USART_CR3_DDRE;
-+ }
-
- if (rs485conf->flags & SER_RS485_ENABLED) {
- stm32_usart_config_reg_rs485(&cr1, &cr3,
-@@ -1238,9 +1342,9 @@ static int stm32_usart_of_dma_rx_probe(struct stm32_port *stm32port,
- return -ENODEV;
- }
-
-- /* No callback as dma buffer is drained on usart interrupt */
-- desc->callback = NULL;
-- desc->callback_param = NULL;
-+ /* Set DMA callback */
-+ desc->callback = stm32_usart_rx_dma_complete;
-+ desc->callback_param = port;
-
- /* Push current DMA transaction in the pending queue */
- ret = dma_submit_error(dmaengine_submit(desc));
-@@ -1405,6 +1509,7 @@ static int stm32_usart_serial_remove(struct platform_device *pdev)
- struct stm32_port *stm32_port = to_stm32_port(port);
- const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
- int err;
-+ u32 cr3;
-
- pm_runtime_get_sync(&pdev->dev);
- err = uart_remove_one_port(&stm32_usart_driver, port);
-@@ -1415,7 +1520,12 @@ static int stm32_usart_serial_remove(struct platform_device *pdev)
- pm_runtime_set_suspended(&pdev->dev);
- pm_runtime_put_noidle(&pdev->dev);
-
-- stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAR);
-+ stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_PEIE);
-+ cr3 = readl_relaxed(port->membase + ofs->cr3);
-+ cr3 &= ~USART_CR3_EIE;
-+ cr3 &= ~USART_CR3_DMAR;
-+ cr3 &= ~USART_CR3_DDRE;
-+ writel_relaxed(cr3, port->membase + ofs->cr3);
-
- if (stm32_port->tx_ch) {
- stm32_usart_of_dma_tx_remove(stm32_port, pdev);
-diff --git a/drivers/tty/serial/stm32-usart.h b/drivers/tty/serial/stm32-usart.h
-index 07ac291328cd..53bcd032fce7 100644
---- a/drivers/tty/serial/stm32-usart.h
-+++ b/drivers/tty/serial/stm32-usart.h
-@@ -109,7 +109,7 @@ struct stm32_usart_info stm32h7_info = {
- /* USART_SR (F4) / USART_ISR (F7) */
- #define USART_SR_PE BIT(0)
- #define USART_SR_FE BIT(1)
--#define USART_SR_NF BIT(2)
-+#define USART_SR_NE BIT(2) /* F7 (NF for F4) */
- #define USART_SR_ORE BIT(3)
- #define USART_SR_IDLE BIT(4)
- #define USART_SR_RXNE BIT(5)
-@@ -126,7 +126,8 @@ struct stm32_usart_info stm32h7_info = {
- #define USART_SR_SBKF BIT(18) /* F7 */
- #define USART_SR_WUF BIT(20) /* H7 */
- #define USART_SR_TEACK BIT(21) /* F7 */
--#define USART_SR_ERR_MASK (USART_SR_ORE | USART_SR_FE | USART_SR_PE)
-+#define USART_SR_ERR_MASK (USART_SR_ORE | USART_SR_NE | USART_SR_FE |\
-+ USART_SR_PE)
- /* Dummy bits */
- #define USART_SR_DUMMY_RX BIT(16)
-
-@@ -246,9 +247,9 @@ struct stm32_usart_info stm32h7_info = {
- #define STM32_SERIAL_NAME "ttySTM"
- #define STM32_MAX_PORTS 8
-
--#define RX_BUF_L 200 /* dma rx buffer length */
--#define RX_BUF_P RX_BUF_L /* dma rx buffer period */
--#define TX_BUF_L 200 /* dma tx buffer length */
-+#define RX_BUF_L 4096 /* dma rx buffer length */
-+#define RX_BUF_P (RX_BUF_L / 2) /* dma rx buffer period */
-+#define TX_BUF_L RX_BUF_L /* dma tx buffer length */
-
- struct stm32_port {
- struct uart_port port;
-@@ -272,6 +273,7 @@ struct stm32_port {
- bool wakeup_src;
- int rdr_mask; /* receive data register mask */
- struct mctrl_gpios *gpios; /* modem control gpios */
-+ struct dma_tx_state rx_dma_state;
- };
-
- static struct stm32_port stm32_ports[STM32_MAX_PORTS];
---
-2.35.1
-
+++ /dev/null
-From 6fa778f8c0f1bc1bad754c6fca14cb758de84258 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Sat, 30 Apr 2022 18:28:45 +0200
-Subject: serial: stm32: Use TC interrupt to deassert GPIO RTS in RS485 mode
-
-From: Marek Vasut <marex@denx.de>
-
-[ Upstream commit d7c76716169ddc37cf6316ff381d34ea807fbfd7 ]
-
-In case the RS485 mode is emulated using GPIO RTS, use the TC interrupt
-to deassert the GPIO RTS, otherwise the GPIO RTS stays asserted after a
-transmission ended and the RS485 cannot work.
-
-Signed-off-by: Marek Vasut <marex@denx.de>
-Cc: Alexandre Torgue <alexandre.torgue@foss.st.com>
-Cc: Erwan Le Ray <erwan.leray@foss.st.com>
-Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-Cc: Jean Philippe Romain <jean-philippe.romain@foss.st.com>
-Cc: Valentin Caron <valentin.caron@foss.st.com>
-Cc: linux-arm-kernel@lists.infradead.org
-Cc: linux-stm32@st-md-mailman.stormreply.com
-To: linux-serial@vger.kernel.org
-Link: https://lore.kernel.org/r/20220430162845.244655-2-marex@denx.de
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-Stable-dep-of: adafbbf6895e ("serial: stm32: Deassert Transmit Enable on ->rs485_config()")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/tty/serial/stm32-usart.c | 42 ++++++++++++++++++++++++++++++--
- drivers/tty/serial/stm32-usart.h | 1 +
- 2 files changed, 41 insertions(+), 2 deletions(-)
-
-diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
-index 0e7bcbaf7268..4a4108ef23e8 100644
---- a/drivers/tty/serial/stm32-usart.c
-+++ b/drivers/tty/serial/stm32-usart.c
-@@ -402,6 +402,14 @@ static void stm32_usart_tx_interrupt_enable(struct uart_port *port)
- stm32_usart_set_bits(port, ofs->cr1, USART_CR1_TXEIE);
- }
-
-+static void stm32_usart_tc_interrupt_enable(struct uart_port *port)
-+{
-+ struct stm32_port *stm32_port = to_stm32_port(port);
-+ const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
-+
-+ stm32_usart_set_bits(port, ofs->cr1, USART_CR1_TCIE);
-+}
-+
- static void stm32_usart_rx_dma_complete(void *arg)
- {
- struct uart_port *port = arg;
-@@ -420,6 +428,14 @@ static void stm32_usart_tx_interrupt_disable(struct uart_port *port)
- stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_TXEIE);
- }
-
-+static void stm32_usart_tc_interrupt_disable(struct uart_port *port)
-+{
-+ struct stm32_port *stm32_port = to_stm32_port(port);
-+ const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
-+
-+ stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_TCIE);
-+}
-+
- static void stm32_usart_rs485_rts_enable(struct uart_port *port)
- {
- struct stm32_port *stm32_port = to_stm32_port(port);
-@@ -557,6 +573,13 @@ static void stm32_usart_transmit_chars(struct uart_port *port)
- u32 isr;
- int ret;
-
-+ if (!stm32_port->hw_flow_control &&
-+ port->rs485.flags & SER_RS485_ENABLED) {
-+ stm32_port->txdone = false;
-+ stm32_usart_tc_interrupt_disable(port);
-+ stm32_usart_rs485_rts_enable(port);
-+ }
-+
- if (port->x_char) {
- if (stm32_port->tx_dma_busy)
- stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT);
-@@ -596,8 +619,14 @@ static void stm32_usart_transmit_chars(struct uart_port *port)
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(port);
-
-- if (uart_circ_empty(xmit))
-+ if (uart_circ_empty(xmit)) {
- stm32_usart_tx_interrupt_disable(port);
-+ if (!stm32_port->hw_flow_control &&
-+ port->rs485.flags & SER_RS485_ENABLED) {
-+ stm32_port->txdone = true;
-+ stm32_usart_tc_interrupt_enable(port);
-+ }
-+ }
- }
-
- static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
-@@ -610,6 +639,13 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
-
- sr = readl_relaxed(port->membase + ofs->isr);
-
-+ if (!stm32_port->hw_flow_control &&
-+ port->rs485.flags & SER_RS485_ENABLED &&
-+ (sr & USART_SR_TC)) {
-+ stm32_usart_tc_interrupt_disable(port);
-+ stm32_usart_rs485_rts_disable(port);
-+ }
-+
- if ((sr & USART_SR_RTOF) && ofs->icr != UNDEF_REG)
- writel_relaxed(USART_ICR_RTOCF,
- port->membase + ofs->icr);
-@@ -713,8 +749,10 @@ static void stm32_usart_start_tx(struct uart_port *port)
- {
- struct circ_buf *xmit = &port->state->xmit;
-
-- if (uart_circ_empty(xmit) && !port->x_char)
-+ if (uart_circ_empty(xmit) && !port->x_char) {
-+ stm32_usart_rs485_rts_disable(port);
- return;
-+ }
-
- stm32_usart_rs485_rts_enable(port);
-
-diff --git a/drivers/tty/serial/stm32-usart.h b/drivers/tty/serial/stm32-usart.h
-index 53bcd032fce7..852573e1a690 100644
---- a/drivers/tty/serial/stm32-usart.h
-+++ b/drivers/tty/serial/stm32-usart.h
-@@ -268,6 +268,7 @@ struct stm32_port {
- bool hw_flow_control;
- bool swap; /* swap RX & TX pins */
- bool fifoen;
-+ bool txdone;
- int rxftcfg; /* RX FIFO threshold CFG */
- int txftcfg; /* TX FIFO threshold CFG */
- bool wakeup_src;
---
-2.35.1
-
scsi-lpfc-adjust-bytes-received-vales-during-cmf-tim.patch
scsi-lpfc-adjust-cmf-total-bytes-and-rxmonitor.patch
scsi-lpfc-rework-mib-rx-monitor-debug-info-logic.patch
-serial-stm32-re-introduce-an-irq-flag-condition-in-u.patch
-serial-stm32-rework-rx-over-dma.patch
-serial-stm32-factor-out-gpio-rts-toggling-into-separ.patch
-serial-stm32-use-tc-interrupt-to-deassert-gpio-rts-i.patch
-serial-stm32-deassert-transmit-enable-on-rs485_confi.patch
arm64-mte-move-register-initialization-to-c.patch
btrfs-rename-root-fields-in-delayed-refs-structs.patch
btrfs-pull-up-qgroup-checks-from-delayed-ref-core-to.patch