diff options
Diffstat (limited to 'drivers/tty/serial/stm32-usart.c')
-rw-r--r-- | drivers/tty/serial/stm32-usart.c | 65 |
1 files changed, 31 insertions, 34 deletions
diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c index 58d169e5c1db03..e1e7bc04c57920 100644 --- a/drivers/tty/serial/stm32-usart.c +++ b/drivers/tty/serial/stm32-usart.c @@ -696,18 +696,23 @@ static void stm32_usart_transmit_chars_pio(struct uart_port *port) { struct stm32_port *stm32_port = to_stm32_port(port); const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; - struct circ_buf *xmit = &port->state->xmit; + struct tty_port *tport = &port->state->port; + + while (1) { + unsigned char ch; - while (!uart_circ_empty(xmit)) { /* Check that TDR is empty before filling FIFO */ if (!(readl_relaxed(port->membase + ofs->isr) & USART_SR_TXE)) break; - writel_relaxed(xmit->buf[xmit->tail], port->membase + ofs->tdr); - uart_xmit_advance(port, 1); + + if (!uart_fifo_get(port, &ch)) + break; + + writel_relaxed(ch, port->membase + ofs->tdr); } /* rely on TXE irq (mask or unmask) for sending remaining data */ - if (uart_circ_empty(xmit)) + if (kfifo_is_empty(&tport->xmit_fifo)) stm32_usart_tx_interrupt_disable(port); else stm32_usart_tx_interrupt_enable(port); @@ -716,7 +721,7 @@ static void stm32_usart_transmit_chars_pio(struct uart_port *port) static void stm32_usart_transmit_chars_dma(struct uart_port *port) { struct stm32_port *stm32port = to_stm32_port(port); - struct circ_buf *xmit = &port->state->xmit; + struct tty_port *tport = &port->state->port; struct dma_async_tx_descriptor *desc = NULL; unsigned int count; int ret; @@ -728,25 +733,8 @@ static void stm32_usart_transmit_chars_dma(struct uart_port *port) return; } - count = uart_circ_chars_pending(xmit); - - if (count > TX_BUF_L) - count = TX_BUF_L; - - if (xmit->tail < xmit->head) { - memcpy(&stm32port->tx_buf[0], &xmit->buf[xmit->tail], count); - } else { - size_t one = UART_XMIT_SIZE - xmit->tail; - size_t two; - - if (one > count) - one = count; - two = count - one; - - memcpy(&stm32port->tx_buf[0], &xmit->buf[xmit->tail], one); - if (two) - memcpy(&stm32port->tx_buf[one], &xmit->buf[0], two); - } + count = kfifo_out_peek(&tport->xmit_fifo, &stm32port->tx_buf[0], + TX_BUF_L); desc = dmaengine_prep_slave_single(stm32port->tx_ch, stm32port->tx_dma_buf, @@ -792,14 +780,14 @@ static void stm32_usart_transmit_chars(struct uart_port *port) { struct stm32_port *stm32_port = to_stm32_port(port); const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; - struct circ_buf *xmit = &port->state->xmit; + struct tty_port *tport = &port->state->port; u32 isr; int ret; if (!stm32_port->hw_flow_control && port->rs485.flags & SER_RS485_ENABLED && (port->x_char || - !(uart_circ_empty(xmit) || uart_tx_stopped(port)))) { + !(kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(port)))) { stm32_usart_tc_interrupt_disable(port); stm32_usart_rs485_rts_enable(port); } @@ -826,7 +814,7 @@ static void stm32_usart_transmit_chars(struct uart_port *port) return; } - if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { + if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(port)) { stm32_usart_tx_interrupt_disable(port); return; } @@ -841,10 +829,10 @@ static void stm32_usart_transmit_chars(struct uart_port *port) else stm32_usart_transmit_chars_pio(port); - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) uart_write_wakeup(port); - if (uart_circ_empty(xmit)) { + if (kfifo_is_empty(&tport->xmit_fifo)) { stm32_usart_tx_interrupt_disable(port); if (!stm32_port->hw_flow_control && port->rs485.flags & SER_RS485_ENABLED) { @@ -861,6 +849,7 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr) const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; u32 sr; unsigned int size; + irqreturn_t ret = IRQ_NONE; sr = readl_relaxed(port->membase + ofs->isr); @@ -869,11 +858,14 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr) (sr & USART_SR_TC)) { stm32_usart_tc_interrupt_disable(port); stm32_usart_rs485_rts_disable(port); + ret = IRQ_HANDLED; } - if ((sr & USART_SR_RTOF) && ofs->icr != UNDEF_REG) + if ((sr & USART_SR_RTOF) && ofs->icr != UNDEF_REG) { writel_relaxed(USART_ICR_RTOCF, port->membase + ofs->icr); + ret = IRQ_HANDLED; + } if ((sr & USART_SR_WUF) && ofs->icr != UNDEF_REG) { /* Clear wake up flag and disable wake up interrupt */ @@ -882,6 +874,7 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr) stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_WUFIE); if (irqd_is_wakeup_set(irq_get_irq_data(port->irq))) pm_wakeup_event(tport->tty->dev, 0); + ret = IRQ_HANDLED; } /* @@ -896,6 +889,7 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr) uart_unlock_and_check_sysrq(port); if (size) tty_flip_buffer_push(tport); + ret = IRQ_HANDLED; } } @@ -903,6 +897,7 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr) uart_port_lock(port); stm32_usart_transmit_chars(port); uart_port_unlock(port); + ret = IRQ_HANDLED; } /* Receiver timeout irq for DMA RX */ @@ -912,9 +907,10 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr) uart_unlock_and_check_sysrq(port); if (size) tty_flip_buffer_push(tport); + ret = IRQ_HANDLED; } - return IRQ_HANDLED; + return ret; } static void stm32_usart_set_mctrl(struct uart_port *port, unsigned int mctrl) @@ -967,9 +963,9 @@ static void stm32_usart_stop_tx(struct uart_port *port) /* There are probably characters waiting to be transmitted. */ static void stm32_usart_start_tx(struct uart_port *port) { - struct circ_buf *xmit = &port->state->xmit; + struct tty_port *tport = &port->state->port; - if (uart_circ_empty(xmit) && !port->x_char) { + if (kfifo_is_empty(&tport->xmit_fifo) && !port->x_char) { stm32_usart_rs485_rts_disable(port); return; } @@ -1084,6 +1080,7 @@ static int stm32_usart_startup(struct uart_port *port) val |= USART_CR2_SWAP; writel_relaxed(val, port->membase + ofs->cr2); } + stm32_port->throttled = false; /* RX FIFO Flush */ if (ofs->rqr != UNDEF_REG) |