I had a similar issue using the rs485 ( on the linux-fslc but I had the same issue with the linux-imx).
I saw that the ull was always in interrupt.
I solved it with the following patch (tested on)
@@ -481,6 +490,11 @@ static inline void imx_transmit_buffer(struct imx_port *sport)
writel(temp, sport->port.membase + UCR1);
schedule_work(&sport->tsk_dma_tx);
}
+
+ writel(readl(sport->port.membase + UCR4) & ~UCR4_TCEN, sport->port.membase + UCR4);
+ return;
}
if (sport->dma_is_txing)
@@ -518,8 +532,16 @@ static void dma_tx_callback(void *data)
}
sport->dma_is_txing = 0;
+ // turn off dma
+ u32 ucr1 = readl(sport->port.membase + UCR1);
+ ucr1 &= ~UCR1_TDMAEN;
+ writel(ucr1, sport->port.membase + UCR1);
+
xmit->tail = (xmit->tail + sport->tx_bytes) & (UART_XMIT_SIZE - 1);
sport->port.icount.tx += sport->tx_bytes;
spin_unlock_irqrestore(&sport->port.lock, flags);
dma_unmap_sg(sport->port.dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE);
@@ -532,6 +554,14 @@ static void dma_tx_callback(void *data)
if (!uart_circ_empty(xmit) && !uart_tx_stopped(&sport->port))
schedule_work(&sport->tsk_dma_tx);
+ else {
+ spin_lock_irqsave(&sport->port.lock, flags);
+ // Abilito interrupt di shift register vuoto
+ writel(readl(sport->port.membase + UCR4) | UCR4_TCEN, sport->port.membase + UCR4);
+ spin_unlock_irqrestore(&sport->port.lock, flags);
+ }
if (waitqueue_active(&sport->dma_wait)) {
wake_up(&sport->dma_wait);
@@ -1090,6 +1128,11 @@ static void dma_rx_callback(void *data)
return;
}
+ if( state.residue == 0 )
+ count = 0;
+ else
count = RX_BUF_SIZE - state.residue;
sport->rx_buf.buf_info[sport->rx_buf.cur_idx].filled = true;
sport->rx_buf.buf_info[sport->rx_buf.cur_idx].rx_bytes = count;
Hope it helps,
Ramon La Pietra