aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty
diff options
context:
space:
mode:
authorJiada Wang <jiada_wang@mentor.com>2014-12-09 04:11:36 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-01-09 17:23:59 -0500
commit91a1a909f9217abb16c5bb3ec2ae606a9fc085e8 (patch)
tree74f335957b36148cce4e7869c860c26408cbc25d /drivers/tty
parent7e2fb5aa8d819e8cc0b6815ad627b7e911fabfd9 (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.c30
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
467static void imx_dma_tx(struct imx_port *sport);
467static inline void imx_transmit_buffer(struct imx_port *sport) 468static 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
500static void imx_dma_tx(struct imx_port *sport);
501static void dma_tx_callback(void *data) 518static 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);