diff options
author | Jiada Wang <jiada_wang@mentor.com> | 2014-12-09 04:11:36 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-01-09 17:23:59 -0500 |
commit | 91a1a909f9217abb16c5bb3ec2ae606a9fc085e8 (patch) | |
tree | 74f335957b36148cce4e7869c860c26408cbc25d /drivers/tty | |
parent | 7e2fb5aa8d819e8cc0b6815ad627b7e911fabfd9 (diff) |
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>
Diffstat (limited to 'drivers/tty')
-rw-r--r-- | drivers/tty/serial/imx.c | 30 |
1 files changed, 28 insertions, 2 deletions
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 5a7da019f01a..72b800b296b1 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c | |||
@@ -464,9 +464,11 @@ static void imx_enable_ms(struct uart_port *port) | |||
464 | mod_timer(&sport->timer, jiffies); | 464 | mod_timer(&sport->timer, jiffies); |
465 | } | 465 | } |
466 | 466 | ||
467 | static void imx_dma_tx(struct imx_port *sport); | ||
467 | static inline void imx_transmit_buffer(struct imx_port *sport) | 468 | static inline void imx_transmit_buffer(struct imx_port *sport) |
468 | { | 469 | { |
469 | struct circ_buf *xmit = &sport->port.state->xmit; | 470 | struct circ_buf *xmit = &sport->port.state->xmit; |
471 | unsigned long temp; | ||
470 | 472 | ||
471 | if (sport->port.x_char) { | 473 | if (sport->port.x_char) { |
472 | /* Send next char */ | 474 | /* Send next char */ |
@@ -481,6 +483,22 @@ static inline void imx_transmit_buffer(struct imx_port *sport) | |||
481 | return; | 483 | return; |
482 | } | 484 | } |
483 | 485 | ||
486 | if (sport->dma_is_enabled) { | ||
487 | /* | ||
488 | * We've just sent a X-char Ensure the TX DMA is enabled | ||
489 | * and the TX IRQ is disabled. | ||
490 | **/ | ||
491 | temp = readl(sport->port.membase + UCR1); | ||
492 | temp &= ~UCR1_TXMPTYEN; | ||
493 | if (sport->dma_is_txing) { | ||
494 | temp |= UCR1_TDMAEN; | ||
495 | writel(temp, sport->port.membase + UCR1); | ||
496 | } else { | ||
497 | writel(temp, sport->port.membase + UCR1); | ||
498 | imx_dma_tx(sport); | ||
499 | } | ||
500 | } | ||
501 | |||
484 | while (!uart_circ_empty(xmit) && | 502 | while (!uart_circ_empty(xmit) && |
485 | !(readl(sport->port.membase + uts_reg(sport)) & UTS_TXFULL)) { | 503 | !(readl(sport->port.membase + uts_reg(sport)) & UTS_TXFULL)) { |
486 | /* send xmit->buf[xmit->tail] | 504 | /* send xmit->buf[xmit->tail] |
@@ -497,7 +515,6 @@ static inline void imx_transmit_buffer(struct imx_port *sport) | |||
497 | imx_stop_tx(&sport->port); | 515 | imx_stop_tx(&sport->port); |
498 | } | 516 | } |
499 | 517 | ||
500 | static void imx_dma_tx(struct imx_port *sport); | ||
501 | static void dma_tx_callback(void *data) | 518 | static void dma_tx_callback(void *data) |
502 | { | 519 | { |
503 | struct imx_port *sport = data; | 520 | struct imx_port *sport = data; |
@@ -630,7 +647,16 @@ static void imx_start_tx(struct uart_port *port) | |||
630 | } | 647 | } |
631 | 648 | ||
632 | if (sport->dma_is_enabled) { | 649 | if (sport->dma_is_enabled) { |
633 | /* FIXME: port->x_char must be transmitted if != 0 */ | 650 | if (sport->port.x_char) { |
651 | /* We have X-char to send, so enable TX IRQ and | ||
652 | * disable TX DMA to let TX interrupt to send X-char */ | ||
653 | temp = readl(sport->port.membase + UCR1); | ||
654 | temp &= ~UCR1_TDMAEN; | ||
655 | temp |= UCR1_TXMPTYEN; | ||
656 | writel(temp, sport->port.membase + UCR1); | ||
657 | return; | ||
658 | } | ||
659 | |||
634 | if (!uart_circ_empty(&port->state->xmit) && | 660 | if (!uart_circ_empty(&port->state->xmit) && |
635 | !uart_tx_stopped(port)) | 661 | !uart_tx_stopped(port)) |
636 | imx_dma_tx(sport); | 662 | imx_dma_tx(sport); |