summaryrefslogtreecommitdiff
path: root/drivers/tty/serial/imx.c
diff options
context:
space:
mode:
authorLucas Stach <l.stach@pengutronix.de>2015-09-04 17:52:38 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-10-04 18:41:09 +0100
commit86a04ba64295e419f442866282051777ce962b8a (patch)
treec68d7afad041996ce941a57bc104b3b7e1a7e942 /drivers/tty/serial/imx.c
parentcc32382d9fd22dc8eebba4a245f50417267bda8e (diff)
serial: imx: set up aging timer interrupt as DMA trigger
The DMA transfer is only started once we are sure it will finish in a limited time, i.e. only after we received a RRDY interrupt. In order to allow the watermark level to be raised the aging timer and the corresponding interrupt need to be set up as an additional trigger, so that the transfer is also started if the incoming amount of bytes never reach the watermark. Signed-off-by: Lucas Stach <l.stach@pengutronix.de> Acked-by: Jiada Wang <jiada_wang@mentor.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/serial/imx.c')
-rw-r--r--drivers/tty/serial/imx.c31
1 files changed, 22 insertions, 9 deletions
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 0f616419213c..db1987a0f513 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -139,6 +139,7 @@
#define USR1_ESCF (1<<11) /* Escape seq interrupt flag */
#define USR1_FRAMERR (1<<10) /* Frame error interrupt flag */
#define USR1_RRDY (1<<9) /* Receiver ready interrupt/dma flag */
+#define USR1_AGTIM (1<<8) /* Ageing timer interrupt flag */
#define USR1_TIMEOUT (1<<7) /* Receive timeout interrupt status */
#define USR1_RXDS (1<<6) /* Receiver idle interrupt flag */
#define USR1_AIRINT (1<<5) /* Async IR wake interrupt flag */
@@ -728,11 +729,15 @@ static void imx_dma_rxint(struct imx_port *sport)
if ((temp & USR2_RDR) && !sport->dma_is_rxing) {
sport->dma_is_rxing = 1;
- /* disable the `Recerver Ready Interrrupt` */
+ /* disable the receiver ready and aging timer interrupts */
temp = readl(sport->port.membase + UCR1);
temp &= ~(UCR1_RRDYEN);
writel(temp, sport->port.membase + UCR1);
+ temp = readl(sport->port.membase + UCR2);
+ temp &= ~(UCR2_ATEN);
+ writel(temp, sport->port.membase + UCR2);
+
/* tell the DMA to receive the data. */
start_rx_dma(sport);
}
@@ -749,7 +754,7 @@ static irqreturn_t imx_int(int irq, void *dev_id)
sts = readl(sport->port.membase + USR1);
sts2 = readl(sport->port.membase + USR2);
- if (sts & USR1_RRDY) {
+ if (sts & (USR1_RRDY | USR1_AGTIM)) {
if (sport->dma_is_enabled)
imx_dma_rxint(sport);
else
@@ -860,11 +865,15 @@ static void imx_rx_dma_done(struct imx_port *sport)
spin_lock_irqsave(&sport->port.lock, flags);
- /* Enable this interrupt when the RXFIFO is empty. */
+ /* re-enable interrupts to get notified when new symbols are incoming */
temp = readl(sport->port.membase + UCR1);
temp |= UCR1_RRDYEN;
writel(temp, sport->port.membase + UCR1);
+ temp = readl(sport->port.membase + UCR2);
+ temp |= UCR2_ATEN;
+ writel(temp, sport->port.membase + UCR2);
+
sport->dma_is_rxing = 0;
/* Is the shutdown waiting for us? */
@@ -1068,6 +1077,10 @@ static void imx_enable_dma(struct imx_port *sport)
UCR1_ICD_REG(3);
writel(temp, sport->port.membase + UCR1);
+ temp = readl(sport->port.membase + UCR2);
+ temp |= UCR2_ATEN;
+ writel(temp, sport->port.membase + UCR2);
+
/* set UCR4 */
temp = readl(sport->port.membase + UCR4);
temp |= UCR4_IDDMAEN;
@@ -1087,7 +1100,7 @@ static void imx_disable_dma(struct imx_port *sport)
/* clear UCR2 */
temp = readl(sport->port.membase + UCR2);
- temp &= ~(UCR2_CTSC | UCR2_CTS);
+ temp &= ~(UCR2_CTSC | UCR2_CTS | UCR2_ATEN);
writel(temp, sport->port.membase + UCR2);
/* clear UCR4 */
@@ -1279,7 +1292,7 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
{
struct imx_port *sport = (struct imx_port *)port;
unsigned long flags;
- unsigned int ucr2, old_ucr1, old_txrxen, baud, quot;
+ unsigned int ucr2, old_ucr1, old_ucr2, baud, quot;
unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
unsigned int div, ufcr;
unsigned long num, denom;
@@ -1388,10 +1401,10 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
barrier();
/* then, disable everything */
- old_txrxen = readl(sport->port.membase + UCR2);
- writel(old_txrxen & ~(UCR2_TXEN | UCR2_RXEN),
+ old_ucr2 = readl(sport->port.membase + UCR2);
+ writel(old_ucr2 & ~(UCR2_TXEN | UCR2_RXEN),
sport->port.membase + UCR2);
- old_txrxen &= (UCR2_TXEN | UCR2_RXEN);
+ old_ucr2 &= (UCR2_TXEN | UCR2_RXEN | UCR2_ATEN);
/* custom-baudrate handling */
div = sport->port.uartclk / (baud * 16);
@@ -1432,7 +1445,7 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
writel(old_ucr1, sport->port.membase + UCR1);
/* set the parity, stop bits and data size */
- writel(ucr2 | old_txrxen, sport->port.membase + UCR2);
+ writel(ucr2 | old_ucr2, sport->port.membase + UCR2);
if (UART_ENABLE_MS(&sport->port, termios->c_cflag))
imx_enable_ms(&sport->port);