serial: imx: Support sw flow control in DMA mode
This patch adds Software flow control support in DMA mode. Signed-off-by: Jiada Wang <jiada_wang@mentor.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
7e2fb5aa8d
commit
91a1a909f9
@ -464,9 +464,11 @@ static void imx_enable_ms(struct uart_port *port)
|
|||||||
mod_timer(&sport->timer, jiffies);
|
mod_timer(&sport->timer, jiffies);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void imx_dma_tx(struct imx_port *sport);
|
||||||
static inline void imx_transmit_buffer(struct imx_port *sport)
|
static inline void imx_transmit_buffer(struct imx_port *sport)
|
||||||
{
|
{
|
||||||
struct circ_buf *xmit = &sport->port.state->xmit;
|
struct circ_buf *xmit = &sport->port.state->xmit;
|
||||||
|
unsigned long temp;
|
||||||
|
|
||||||
if (sport->port.x_char) {
|
if (sport->port.x_char) {
|
||||||
/* Send next char */
|
/* Send next char */
|
||||||
@ -481,6 +483,22 @@ static inline void imx_transmit_buffer(struct imx_port *sport)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sport->dma_is_enabled) {
|
||||||
|
/*
|
||||||
|
* We've just sent a X-char Ensure the TX DMA is enabled
|
||||||
|
* and the TX IRQ is disabled.
|
||||||
|
**/
|
||||||
|
temp = readl(sport->port.membase + UCR1);
|
||||||
|
temp &= ~UCR1_TXMPTYEN;
|
||||||
|
if (sport->dma_is_txing) {
|
||||||
|
temp |= UCR1_TDMAEN;
|
||||||
|
writel(temp, sport->port.membase + UCR1);
|
||||||
|
} else {
|
||||||
|
writel(temp, sport->port.membase + UCR1);
|
||||||
|
imx_dma_tx(sport);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while (!uart_circ_empty(xmit) &&
|
while (!uart_circ_empty(xmit) &&
|
||||||
!(readl(sport->port.membase + uts_reg(sport)) & UTS_TXFULL)) {
|
!(readl(sport->port.membase + uts_reg(sport)) & UTS_TXFULL)) {
|
||||||
/* send xmit->buf[xmit->tail]
|
/* send xmit->buf[xmit->tail]
|
||||||
@ -497,7 +515,6 @@ static inline void imx_transmit_buffer(struct imx_port *sport)
|
|||||||
imx_stop_tx(&sport->port);
|
imx_stop_tx(&sport->port);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void imx_dma_tx(struct imx_port *sport);
|
|
||||||
static void dma_tx_callback(void *data)
|
static void dma_tx_callback(void *data)
|
||||||
{
|
{
|
||||||
struct imx_port *sport = data;
|
struct imx_port *sport = data;
|
||||||
@ -630,7 +647,16 @@ static void imx_start_tx(struct uart_port *port)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sport->dma_is_enabled) {
|
if (sport->dma_is_enabled) {
|
||||||
/* FIXME: port->x_char must be transmitted if != 0 */
|
if (sport->port.x_char) {
|
||||||
|
/* We have X-char to send, so enable TX IRQ and
|
||||||
|
* disable TX DMA to let TX interrupt to send X-char */
|
||||||
|
temp = readl(sport->port.membase + UCR1);
|
||||||
|
temp &= ~UCR1_TDMAEN;
|
||||||
|
temp |= UCR1_TXMPTYEN;
|
||||||
|
writel(temp, sport->port.membase + UCR1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!uart_circ_empty(&port->state->xmit) &&
|
if (!uart_circ_empty(&port->state->xmit) &&
|
||||||
!uart_tx_stopped(port))
|
!uart_tx_stopped(port))
|
||||||
imx_dma_tx(sport);
|
imx_dma_tx(sport);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user