return stm32_port->tx_dma_busy;
}
-static bool stm32_usart_tx_dma_enabled(struct stm32_port *stm32_port)
-{
- const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
-
- return !!(readl_relaxed(stm32_port->port.membase + ofs->cr3) & USART_CR3_DMAT);
-}
-
static void stm32_usart_tx_dma_complete(void *arg)
{
struct uart_port *port = arg;
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
struct circ_buf *xmit = &port->state->xmit;
- if (stm32_usart_tx_dma_enabled(stm32_port))
- stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT);
-
while (!uart_circ_empty(xmit)) {
/* Check that TDR is empty before filling FIFO */
if (!(readl_relaxed(port->membase + ofs->isr) & USART_SR_TXE))
struct circ_buf *xmit = &port->state->xmit;
struct dma_async_tx_descriptor *desc = NULL;
unsigned int count;
+ int ret;
if (stm32_usart_tx_dma_started(stm32port)) {
- if (!stm32_usart_tx_dma_enabled(stm32port))
- stm32_usart_set_bits(port, ofs->cr3, USART_CR3_DMAT);
+ if (dmaengine_tx_status(stm32port->tx_ch,
+ stm32port->tx_ch->cookie,
+ NULL) == DMA_PAUSED) {
+ ret = dmaengine_resume(stm32port->tx_ch);
+ if (ret < 0)
+ goto dma_err;
+ }
return;
}
desc->callback_param = port;
/* Push current DMA TX transaction in the pending queue */
- if (dma_submit_error(dmaengine_submit(desc))) {
- /* dma no yet started, safe to free resources */
- stm32_usart_tx_dma_terminate(stm32port);
- goto fallback_err;
- }
+ /* DMA no yet started, safe to free resources */
+ if (dma_submit_error(dmaengine_submit(desc)))
+ goto dma_err;
/* Issue pending DMA TX requests */
dma_async_issue_pending(stm32port->tx_ch);
return;
+dma_err:
+ dev_err(port->dev, "DMA failed with error code: %d\n", ret);
+ stm32_usart_tx_dma_terminate(stm32port);
+
fallback_err:
stm32_usart_transmit_chars_pio(port);
}
if (port->x_char) {
if (stm32_usart_tx_dma_started(stm32_port) &&
- stm32_usart_tx_dma_enabled(stm32_port))
- stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT);
-
+ dmaengine_tx_status(stm32_port->tx_ch,
+ stm32_port->tx_ch->cookie,
+ NULL) == DMA_IN_PROGRESS) {
+ ret = dmaengine_pause(stm32_port->tx_ch);
+ if (ret < 0) {
+ dev_err(port->dev, "DMA failed with error code: %d\n", ret);
+ stm32_usart_tx_dma_terminate(stm32_port);
+ }
+ }
/* Check that TDR is empty before filling FIFO */
ret =
readl_relaxed_poll_timeout_atomic(port->membase + ofs->isr,
writel_relaxed(port->x_char, port->membase + ofs->tdr);
port->x_char = 0;
port->icount.tx++;
- if (stm32_usart_tx_dma_started(stm32_port))
- stm32_usart_set_bits(port, ofs->cr3, USART_CR3_DMAT);
+
+ if (stm32_usart_tx_dma_started(stm32_port)) {
+ ret = dmaengine_resume(stm32_port->tx_ch);
+ if (ret < 0) {
+ dev_err(port->dev, "DMA failed with error code: %d\n", ret);
+ stm32_usart_tx_dma_terminate(stm32_port);
+ }
+ }
return;
}
static void stm32_usart_stop_tx(struct uart_port *port)
{
struct stm32_port *stm32_port = to_stm32_port(port);
- const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
+ int ret;
stm32_usart_tx_interrupt_disable(port);
- if (stm32_usart_tx_dma_started(stm32_port) && stm32_usart_tx_dma_enabled(stm32_port))
- stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT);
+ if (stm32_usart_tx_dma_started(stm32_port)) {
+ ret = dmaengine_pause(stm32_port->tx_ch);
+ if (ret < 0) {
+ dev_err(port->dev, "DMA failed with error code: %d\n", ret);
+ stm32_usart_tx_dma_terminate(stm32_port);
+ }
+ }
stm32_usart_rs485_rts_disable(port);
}
static void stm32_usart_flush_buffer(struct uart_port *port)
{
struct stm32_port *stm32_port = to_stm32_port(port);
- const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
- if (stm32_port->tx_ch) {
+ if (stm32_port->tx_ch)
stm32_usart_tx_dma_terminate(stm32_port);
- stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT);
- }
}
/* Throttle the remote when input buffer is about to overflow. */
u32 val, isr;
int ret;
- if (stm32_usart_tx_dma_enabled(stm32_port))
- stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT);
-
if (stm32_usart_tx_dma_started(stm32_port))
stm32_usart_tx_dma_terminate(stm32_port);
+ if (stm32_port->tx_ch)
+ stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT);
+
/* Disable modem control interrupts */
stm32_usart_disable_ms(port);