linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
From: Erwan Le Ray <erwan.leray@foss.st.com>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Jiri Slaby <jslaby@suse.com>,
	Maxime Coquelin <mcoquelin.stm32@gmail.com>,
	Alexandre Torgue <alexandre.torgue@foss.st.com>
Cc: <linux-serial@vger.kernel.org>,
	<linux-stm32@st-md-mailman.stormreply.com>,
	<linux-arm-kernel@lists.infradead.org>,
	<linux-kernel@vger.kernel.org>,
	Erwan Le Ray <erwan.leray@foss.st.com>,
	Fabrice Gasnier <fabrice.gasnier@foss.st.com>,
	Valentin Caron <valentin.caron@foss.st.com>,
	Amelie Delaunay <amelie.delaunay@foss.st.com>
Subject: [PATCH 1/3] serial: stm32: rework RX dma initialization and release
Date: Mon, 25 Oct 2021 15:42:27 +0200	[thread overview]
Message-ID: <20211025134229.8456-2-erwan.leray@foss.st.com> (raw)
In-Reply-To: <20211025134229.8456-1-erwan.leray@foss.st.com>

The RX DMA channel is kept active forever (from the probe). That prevents
going to low power mode when it is used. This change moves the
DMA configuration and enabling procedures to startup routine to allow
transition to low power mode.
The DMA disabling procedure is implemented in stop_rx routine as this
ops has to stop characters reception, and DMA transation in shutdown.
Clean useless dma_async_tx_descriptor initialization to NULL value.

Signed-off-by: Valentin Caron <valentin.caron@foss.st.com>
Signed-off-by: Erwan Le Ray <erwan.leray@foss.st.com>

diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
index 7fd192e1e15d..ee3495c0abbb 100644
--- a/drivers/tty/serial/stm32-usart.c
+++ b/drivers/tty/serial/stm32-usart.c
@@ -761,6 +761,10 @@ static void stm32_usart_stop_rx(struct uart_port *port)
 	struct stm32_port *stm32_port = to_stm32_port(port);
 	const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
 
+	/* Disable DMA request line. */
+	if (stm32_port->rx_ch)
+		stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAR);
+
 	stm32_usart_clr_bits(port, ofs->cr1, stm32_port->cr1_irq);
 	if (stm32_port->cr3_irq)
 		stm32_usart_clr_bits(port, ofs->cr3, stm32_port->cr3_irq);
@@ -777,6 +781,7 @@ static int stm32_usart_startup(struct uart_port *port)
 	const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
 	const struct stm32_usart_config *cfg = &stm32_port->info->cfg;
 	const char *name = to_platform_device(port->dev)->name;
+	struct dma_async_tx_descriptor *desc;
 	u32 val;
 	int ret;
 
@@ -797,6 +802,33 @@ static int stm32_usart_startup(struct uart_port *port)
 	if (ofs->rqr != UNDEF_REG)
 		writel_relaxed(USART_RQR_RXFRQ, port->membase + ofs->rqr);
 
+	if (stm32_port->rx_ch) {
+		stm32_port->last_res = RX_BUF_L;
+		/* Prepare a DMA cyclic transaction */
+		desc = dmaengine_prep_dma_cyclic(stm32_port->rx_ch,
+						 stm32_port->rx_dma_buf,
+						 RX_BUF_L, RX_BUF_P,
+						 DMA_DEV_TO_MEM,
+						 DMA_PREP_INTERRUPT);
+		if (!desc) {
+			dev_err(port->dev, "rx dma prep cyclic failed\n");
+			ret = -ENODEV;
+			goto err;
+		}
+
+		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));
+		if (ret) {
+			dmaengine_terminate_sync(stm32_port->rx_ch);
+			goto err;
+		}
+
+		/* Issue pending DMA requests */
+		dma_async_issue_pending(stm32_port->rx_ch);
+	}
 	/*
 	 * DMA request line not re-enabled at resume when port is throttled.
 	 * It will be re-enabled by unthrottle ops.
@@ -809,6 +841,11 @@ static int stm32_usart_startup(struct uart_port *port)
 	stm32_usart_set_bits(port, ofs->cr1, val);
 
 	return 0;
+
+err:
+	free_irq(port->irq, port);
+
+	return ret;
 }
 
 static void stm32_usart_shutdown(struct uart_port *port)
@@ -836,6 +873,10 @@ static void stm32_usart_shutdown(struct uart_port *port)
 	if (ret)
 		dev_err(port->dev, "Transmission is not complete\n");
 
+	/* Disable RX DMA. */
+	if (stm32_port->rx_ch)
+		dmaengine_terminate_async(stm32_port->rx_ch);
+
 	/* flush RX & TX FIFO */
 	if (ofs->rqr != UNDEF_REG)
 		writel_relaxed(USART_RQR_TXFRQ | USART_RQR_RXFRQ,
@@ -1304,7 +1345,6 @@ static int stm32_usart_of_dma_rx_probe(struct stm32_port *stm32port,
 	struct uart_port *port = &stm32port->port;
 	struct device *dev = &pdev->dev;
 	struct dma_slave_config config;
-	struct dma_async_tx_descriptor *desc = NULL;
 	int ret;
 
 	/*
@@ -1332,32 +1372,6 @@ static int stm32_usart_of_dma_rx_probe(struct stm32_port *stm32port,
 		return ret;
 	}
 
-	/* Prepare a DMA cyclic transaction */
-	desc = dmaengine_prep_dma_cyclic(stm32port->rx_ch,
-					 stm32port->rx_dma_buf,
-					 RX_BUF_L, RX_BUF_P, DMA_DEV_TO_MEM,
-					 DMA_PREP_INTERRUPT);
-	if (!desc) {
-		dev_err(dev, "rx dma prep cyclic failed\n");
-		stm32_usart_of_dma_rx_remove(stm32port, pdev);
-		return -ENODEV;
-	}
-
-	/* 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));
-	if (ret) {
-		dmaengine_terminate_sync(stm32port->rx_ch);
-		stm32_usart_of_dma_rx_remove(stm32port, pdev);
-		return ret;
-	}
-
-	/* Issue pending DMA requests */
-	dma_async_issue_pending(stm32port->rx_ch);
-
 	return 0;
 }
 
@@ -1535,7 +1549,6 @@ static int stm32_usart_serial_remove(struct platform_device *pdev)
 	}
 
 	if (stm32_port->rx_ch) {
-		dmaengine_terminate_async(stm32_port->rx_ch);
 		stm32_usart_of_dma_rx_remove(stm32_port, pdev);
 		dma_release_channel(stm32_port->rx_ch);
 	}
-- 
2.17.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

  reply	other threads:[~2021-10-25 13:44 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-10-25 13:42 [PATCH 0/3] Power management improvements for STM32 UART DMA RX Erwan Le Ray
2021-10-25 13:42 ` Erwan Le Ray [this message]
2021-10-25 13:42 ` [PATCH 2/3] serial: stm32: terminate / restart DMA transfer at suspend / resume Erwan Le Ray
2021-10-25 13:42 ` [PATCH 3/3] serial: stm32: push DMA RX data before suspending Erwan Le Ray

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20211025134229.8456-2-erwan.leray@foss.st.com \
    --to=erwan.leray@foss.st.com \
    --cc=alexandre.torgue@foss.st.com \
    --cc=amelie.delaunay@foss.st.com \
    --cc=fabrice.gasnier@foss.st.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=jslaby@suse.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-serial@vger.kernel.org \
    --cc=linux-stm32@st-md-mailman.stormreply.com \
    --cc=mcoquelin.stm32@gmail.com \
    --cc=valentin.caron@foss.st.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).