aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorElen Song <elen.song@atmel.com>2013-07-22 04:30:30 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-07-29 16:05:04 -0400
commit2e68c22fde9b001e41d47185a5b7612da60d8c33 (patch)
tree758c095f1f23b3da35e0089fca62adec9ed9885b
parent055560b04a8cd063aea916fd083b7aec02c2adb8 (diff)
serial: at91: make UART support dma and pdc transfers
Because the UART lack of receive timeout register, so we use a timer to trigger data receive. The DBGU is regarded as UART. Signed-off-by: Elen Song <elen.song@atmel.com> Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/tty/serial/atmel_serial.c48
1 files changed, 42 insertions, 6 deletions
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 8dbc3e67dfa4..7e2cb31497c3 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -40,6 +40,7 @@
40#include <linux/atmel_serial.h> 40#include <linux/atmel_serial.h>
41#include <linux/uaccess.h> 41#include <linux/uaccess.h>
42#include <linux/platform_data/atmel.h> 42#include <linux/platform_data/atmel.h>
43#include <linux/timer.h>
43 44
44#include <asm/io.h> 45#include <asm/io.h>
45#include <asm/ioctls.h> 46#include <asm/ioctls.h>
@@ -168,6 +169,7 @@ struct atmel_uart_port {
168 struct serial_rs485 rs485; /* rs485 settings */ 169 struct serial_rs485 rs485; /* rs485 settings */
169 unsigned int tx_done_mask; 170 unsigned int tx_done_mask;
170 bool is_usart; /* usart or uart */ 171 bool is_usart; /* usart or uart */
172 struct timer_list uart_timer; /* uart timer */
171 int (*prepare_rx)(struct uart_port *port); 173 int (*prepare_rx)(struct uart_port *port);
172 int (*prepare_tx)(struct uart_port *port); 174 int (*prepare_tx)(struct uart_port *port);
173 void (*schedule_rx)(struct uart_port *port); 175 void (*schedule_rx)(struct uart_port *port);
@@ -822,6 +824,9 @@ static void atmel_release_rx_dma(struct uart_port *port)
822 atmel_port->desc_rx = NULL; 824 atmel_port->desc_rx = NULL;
823 atmel_port->chan_rx = NULL; 825 atmel_port->chan_rx = NULL;
824 atmel_port->cookie_rx = -EINVAL; 826 atmel_port->cookie_rx = -EINVAL;
827
828 if (!atmel_port->is_usart)
829 del_timer_sync(&atmel_port->uart_timer);
825} 830}
826 831
827static void atmel_rx_from_dma(struct uart_port *port) 832static void atmel_rx_from_dma(struct uart_port *port)
@@ -951,6 +956,15 @@ chan_err:
951 return -EINVAL; 956 return -EINVAL;
952} 957}
953 958
959static void atmel_uart_timer_callback(unsigned long data)
960{
961 struct uart_port *port = (void *)data;
962 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
963
964 tasklet_schedule(&atmel_port->tasklet);
965 mod_timer(&atmel_port->uart_timer, jiffies + uart_poll_timeout(port));
966}
967
954/* 968/*
955 * receive interrupt handler. 969 * receive interrupt handler.
956 */ 970 */
@@ -1214,6 +1228,9 @@ static void atmel_release_rx_pdc(struct uart_port *port)
1214 DMA_FROM_DEVICE); 1228 DMA_FROM_DEVICE);
1215 kfree(pdc->buf); 1229 kfree(pdc->buf);
1216 } 1230 }
1231
1232 if (!atmel_port->is_usart)
1233 del_timer_sync(&atmel_port->uart_timer);
1217} 1234}
1218 1235
1219static void atmel_rx_from_pdc(struct uart_port *port) 1236static void atmel_rx_from_pdc(struct uart_port *port)
@@ -1575,17 +1592,36 @@ static int atmel_startup(struct uart_port *port)
1575 1592
1576 if (atmel_use_pdc_rx(port)) { 1593 if (atmel_use_pdc_rx(port)) {
1577 /* set UART timeout */ 1594 /* set UART timeout */
1578 UART_PUT_RTOR(port, PDC_RX_TIMEOUT); 1595 if (!atmel_port->is_usart) {
1579 UART_PUT_CR(port, ATMEL_US_STTTO); 1596 setup_timer(&atmel_port->uart_timer,
1597 atmel_uart_timer_callback,
1598 (unsigned long)port);
1599 mod_timer(&atmel_port->uart_timer,
1600 jiffies + uart_poll_timeout(port));
1601 /* set USART timeout */
1602 } else {
1603 UART_PUT_RTOR(port, PDC_RX_TIMEOUT);
1604 UART_PUT_CR(port, ATMEL_US_STTTO);
1580 1605
1581 UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT); 1606 UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
1607 }
1582 /* enable PDC controller */ 1608 /* enable PDC controller */
1583 UART_PUT_PTCR(port, ATMEL_PDC_RXTEN); 1609 UART_PUT_PTCR(port, ATMEL_PDC_RXTEN);
1584 } else if (atmel_use_dma_rx(port)) { 1610 } else if (atmel_use_dma_rx(port)) {
1585 UART_PUT_RTOR(port, PDC_RX_TIMEOUT); 1611 /* set UART timeout */
1586 UART_PUT_CR(port, ATMEL_US_STTTO); 1612 if (!atmel_port->is_usart) {
1613 setup_timer(&atmel_port->uart_timer,
1614 atmel_uart_timer_callback,
1615 (unsigned long)port);
1616 mod_timer(&atmel_port->uart_timer,
1617 jiffies + uart_poll_timeout(port));
1618 /* set USART timeout */
1619 } else {
1620 UART_PUT_RTOR(port, PDC_RX_TIMEOUT);
1621 UART_PUT_CR(port, ATMEL_US_STTTO);
1587 1622
1588 UART_PUT_IER(port, ATMEL_US_TIMEOUT); 1623 UART_PUT_IER(port, ATMEL_US_TIMEOUT);
1624 }
1589 } else { 1625 } else {
1590 /* enable receive only */ 1626 /* enable receive only */
1591 UART_PUT_IER(port, ATMEL_US_RXRDY); 1627 UART_PUT_IER(port, ATMEL_US_RXRDY);