|
|
@@ -163,6 +163,8 @@ struct atmel_uart_port {
|
|
|
unsigned int pending_status;
|
|
|
spinlock_t lock_suspended;
|
|
|
|
|
|
+ bool hd_start_rx; /* can start RX during half-duplex operation */
|
|
|
+
|
|
|
#ifdef CONFIG_PM
|
|
|
struct {
|
|
|
u32 cr;
|
|
|
@@ -805,8 +807,13 @@ static void atmel_complete_tx_dma(void *arg)
|
|
|
if (!uart_circ_empty(xmit))
|
|
|
atmel_tasklet_schedule(atmel_port, &atmel_port->tasklet_tx);
|
|
|
else if (atmel_uart_is_half_duplex(port)) {
|
|
|
- /* DMA done, stop TX, start RX for RS485 */
|
|
|
- atmel_start_rx(port);
|
|
|
+ /*
|
|
|
+ * DMA done, re-enable TXEMPTY and signal that we can stop
|
|
|
+ * TX and start RX for RS485
|
|
|
+ */
|
|
|
+ atmel_port->hd_start_rx = true;
|
|
|
+ atmel_uart_writel(port, ATMEL_US_IER,
|
|
|
+ atmel_port->tx_done_mask);
|
|
|
}
|
|
|
|
|
|
spin_unlock_irqrestore(&port->lock, flags);
|
|
|
@@ -1252,9 +1259,20 @@ atmel_handle_transmit(struct uart_port *port, unsigned int pending)
|
|
|
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
|
|
|
|
|
|
if (pending & atmel_port->tx_done_mask) {
|
|
|
- /* Either PDC or interrupt transmission */
|
|
|
atmel_uart_writel(port, ATMEL_US_IDR,
|
|
|
atmel_port->tx_done_mask);
|
|
|
+
|
|
|
+ /* Start RX if flag was set and FIFO is empty */
|
|
|
+ if (atmel_port->hd_start_rx) {
|
|
|
+ if (!(atmel_uart_readl(port, ATMEL_US_CSR)
|
|
|
+ & ATMEL_US_TXEMPTY))
|
|
|
+ dev_warn(port->dev, "Should start RX, but TX fifo is not empty\n");
|
|
|
+
|
|
|
+ atmel_port->hd_start_rx = false;
|
|
|
+ atmel_start_rx(port);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
atmel_tasklet_schedule(atmel_port, &atmel_port->tasklet_tx);
|
|
|
}
|
|
|
}
|