Re: [PATCH 5/5] atmel_serial: Add DMA support

2007-12-18 Thread Chip Coldwell
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

On Tue, 18 Dec 2007, Haavard Skinnemoen wrote:

> From: Chip Coldwell <[EMAIL PROTECTED]>
> 
> This patch is based on the DMA-patch by Chip Coldwell for the
> AT91/AT32 serial USARTS, with some tweaks to make it apply neatly on
> top of the other patches in this series.
> 
> The RX code has been moved to a tasklet and reworked a bit. Instead of
> depending on the ENDRX and TIMEOUT bits in CSR, we simply grab as much
> data as we can from the DMA buffers. I think this closes a race where
> the ENDRX bit is set after we read CSR but before we read RPR,
> although I haven't confirmed this.
> 
> This also fixes a DMA sync bug in the original patch.
> 
> [EMAIL PROTECTED]: rebased onto irq-splitup patch]
> [EMAIL PROTECTED]: moved to tasklet, fixed dma bug, misc cleanups]
> Signed-off-by: Remy Bohmer <[EMAIL PROTECTED]>
> Signed-off-by: Haavard Skinnemoen <[EMAIL PROTECTED]>
> ---
>  drivers/serial/atmel_serial.c |  386 ++--
>  1 files changed, 366 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c
> index 990d3ab..07c2734 100644
> --- a/drivers/serial/atmel_serial.c
> +++ b/drivers/serial/atmel_serial.c
> @@ -7,6 +7,8 @@
>   *  Based on drivers/char/serial_sa1100.c, by Deep Blue Solutions Ltd.
>   *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
>   *
> + *  DMA support added by Chip Coldwell.

I will ACK/Sign-off on this soon; I just want to do some tests on real
hardware first.

Chip

- -- 
Charles M. Coldwell
"Turn on, log in, tune out"
Somerville, Massachusetts, New England
-BEGIN PGP SIGNATURE-
Version: GnuPG v1.4.7 (GNU/Linux)

iD8DBQFHaA7cr6maj4UuBS8RAjMSAJsGcKoFKCP/R3aAPhW5hj+v3Qt6ZACgshsF
5NP6/9+NbhDAxBC/7jo8J0Y=
=hx4t
-END PGP SIGNATURE-
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 5/5] atmel_serial: Add DMA support

2007-12-18 Thread Haavard Skinnemoen
From: Chip Coldwell <[EMAIL PROTECTED]>

This patch is based on the DMA-patch by Chip Coldwell for the
AT91/AT32 serial USARTS, with some tweaks to make it apply neatly on
top of the other patches in this series.

The RX code has been moved to a tasklet and reworked a bit. Instead of
depending on the ENDRX and TIMEOUT bits in CSR, we simply grab as much
data as we can from the DMA buffers. I think this closes a race where
the ENDRX bit is set after we read CSR but before we read RPR,
although I haven't confirmed this.

This also fixes a DMA sync bug in the original patch.

[EMAIL PROTECTED]: rebased onto irq-splitup patch]
[EMAIL PROTECTED]: moved to tasklet, fixed dma bug, misc cleanups]
Signed-off-by: Remy Bohmer <[EMAIL PROTECTED]>
Signed-off-by: Haavard Skinnemoen <[EMAIL PROTECTED]>
---
 drivers/serial/atmel_serial.c |  386 ++--
 1 files changed, 366 insertions(+), 20 deletions(-)

diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c
index 990d3ab..07c2734 100644
--- a/drivers/serial/atmel_serial.c
+++ b/drivers/serial/atmel_serial.c
@@ -7,6 +7,8 @@
  *  Based on drivers/char/serial_sa1100.c, by Deep Blue Solutions Ltd.
  *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
  *
+ *  DMA support added by Chip Coldwell.
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -33,6 +35,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include 
@@ -47,6 +50,11 @@
 
 #include "atmel_serial.h"
 
+#define SUPPORT_PDC
+#define PDC_BUFFER_SIZE(L1_CACHE_BYTES << 3)
+#warning "Revisit"
+#define PDC_RX_TIMEOUT (3 * 10)/* 3 bytes */
+
 #if defined(CONFIG_SERIAL_ATMEL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 #define SUPPORT_SYSRQ
 #endif
@@ -111,6 +119,13 @@
 static int (*atmel_open_hook) (struct uart_port *);
 static void (*atmel_close_hook) (struct uart_port *);
 
+struct atmel_dma_buffer {
+   unsigned char   *buf;
+   dma_addr_t  dma_addr;
+   size_t  dma_size;
+   unsigned intofs;
+};
+
 struct atmel_uart_char {
u16 status;
u16 ch;
@@ -127,6 +142,13 @@ struct atmel_uart_port {
unsigned short  suspended;  /* is port suspended? */
int break_active;   /* break being received */
 
+   short   use_dma_rx; /* enable PDC receiver */
+   short   pdc_rx_idx; /* current PDC RX buffer */
+   struct atmel_dma_buffer pdc_rx[2];  /* PDC receier */
+
+   short   use_dma_tx; /* enable PDC transmitter */
+   struct atmel_dma_buffer pdc_tx; /* PDC transmitter */
+
struct tasklet_struct   tasklet;
unsigned intirq_pending;
unsigned intirq_status;
@@ -136,10 +158,39 @@ struct atmel_uart_port {
 
 static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART];
 
+#define PDC_RX_BUF(port)   &(port)->pdc_rx[(port)->pdc_rx_idx]
+#define PDC_RX_SWITCH(port)(port)->pdc_rx_idx = !(port)->pdc_rx_idx
+
 #ifdef SUPPORT_SYSRQ
 static struct console atmel_console;
 #endif
 
+#ifdef SUPPORT_PDC
+static bool atmel_use_dma_rx(struct uart_port *port)
+{
+   struct atmel_uart_port *atmel_port = (struct atmel_uart_port *)port;
+
+   return atmel_port->use_dma_rx;
+}
+
+static bool atmel_use_dma_tx(struct uart_port *port)
+{
+   struct atmel_uart_port *atmel_port = (struct atmel_uart_port *)port;
+
+   return atmel_port->use_dma_tx;
+}
+#else
+static bool atmel_use_dma_rx(struct uart_port *port)
+{
+   return false;
+}
+
+static bool atmel_use_dma_tx(struct uart_port *port)
+{
+   return false;
+}
+#endif
+
 /*
  * Return TIOCSER_TEMT when transmitter FIFO and Shift register is empty.
  */
@@ -221,7 +272,12 @@ static u_int atmel_get_mctrl(struct uart_port *port)
  */
 static void atmel_stop_tx(struct uart_port *port)
 {
-   UART_PUT_IDR(port, ATMEL_US_TXRDY);
+   if (atmel_use_dma_tx(port)) {
+   /* disable PDC transmit */
+   UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
+   UART_PUT_IDR(port, ATMEL_US_ENDTX | ATMEL_US_TXBUFE);
+   } else
+   UART_PUT_IDR(port, ATMEL_US_TXRDY);
 }
 
 /*
@@ -229,7 +285,17 @@ static void atmel_stop_tx(struct uart_port *port)
  */
 static void atmel_start_tx(struct uart_port *port)
 {
-   UART_PUT_IER(port, ATMEL_US_TXRDY);
+   if (atmel_use_dma_tx(port)) {
+   if (UART_GET_PTSR(port) & ATMEL_PDC_TXTEN)
+   /* The transmitter is already running.  Yes, we
+  really need this.*/
+   return;
+
+   UART_PUT_IER(port, ATMEL_US_ENDTX | ATMEL_US_TXBUFE);
+   /* re-enable PDC transmit */
+

[PATCH 5/5] atmel_serial: Add DMA support

2007-12-18 Thread Haavard Skinnemoen
From: Chip Coldwell [EMAIL PROTECTED]

This patch is based on the DMA-patch by Chip Coldwell for the
AT91/AT32 serial USARTS, with some tweaks to make it apply neatly on
top of the other patches in this series.

The RX code has been moved to a tasklet and reworked a bit. Instead of
depending on the ENDRX and TIMEOUT bits in CSR, we simply grab as much
data as we can from the DMA buffers. I think this closes a race where
the ENDRX bit is set after we read CSR but before we read RPR,
although I haven't confirmed this.

This also fixes a DMA sync bug in the original patch.

[EMAIL PROTECTED]: rebased onto irq-splitup patch]
[EMAIL PROTECTED]: moved to tasklet, fixed dma bug, misc cleanups]
Signed-off-by: Remy Bohmer [EMAIL PROTECTED]
Signed-off-by: Haavard Skinnemoen [EMAIL PROTECTED]
---
 drivers/serial/atmel_serial.c |  386 ++--
 1 files changed, 366 insertions(+), 20 deletions(-)

diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c
index 990d3ab..07c2734 100644
--- a/drivers/serial/atmel_serial.c
+++ b/drivers/serial/atmel_serial.c
@@ -7,6 +7,8 @@
  *  Based on drivers/char/serial_sa1100.c, by Deep Blue Solutions Ltd.
  *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
  *
+ *  DMA support added by Chip Coldwell.
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -33,6 +35,7 @@
 #include linux/sysrq.h
 #include linux/tty_flip.h
 #include linux/platform_device.h
+#include linux/dma-mapping.h
 #include linux/atmel_pdc.h
 
 #include asm/io.h
@@ -47,6 +50,11 @@
 
 #include atmel_serial.h
 
+#define SUPPORT_PDC
+#define PDC_BUFFER_SIZE(L1_CACHE_BYTES  3)
+#warning Revisit
+#define PDC_RX_TIMEOUT (3 * 10)/* 3 bytes */
+
 #if defined(CONFIG_SERIAL_ATMEL_CONSOLE)  defined(CONFIG_MAGIC_SYSRQ)
 #define SUPPORT_SYSRQ
 #endif
@@ -111,6 +119,13 @@
 static int (*atmel_open_hook) (struct uart_port *);
 static void (*atmel_close_hook) (struct uart_port *);
 
+struct atmel_dma_buffer {
+   unsigned char   *buf;
+   dma_addr_t  dma_addr;
+   size_t  dma_size;
+   unsigned intofs;
+};
+
 struct atmel_uart_char {
u16 status;
u16 ch;
@@ -127,6 +142,13 @@ struct atmel_uart_port {
unsigned short  suspended;  /* is port suspended? */
int break_active;   /* break being received */
 
+   short   use_dma_rx; /* enable PDC receiver */
+   short   pdc_rx_idx; /* current PDC RX buffer */
+   struct atmel_dma_buffer pdc_rx[2];  /* PDC receier */
+
+   short   use_dma_tx; /* enable PDC transmitter */
+   struct atmel_dma_buffer pdc_tx; /* PDC transmitter */
+
struct tasklet_struct   tasklet;
unsigned intirq_pending;
unsigned intirq_status;
@@ -136,10 +158,39 @@ struct atmel_uart_port {
 
 static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART];
 
+#define PDC_RX_BUF(port)   (port)-pdc_rx[(port)-pdc_rx_idx]
+#define PDC_RX_SWITCH(port)(port)-pdc_rx_idx = !(port)-pdc_rx_idx
+
 #ifdef SUPPORT_SYSRQ
 static struct console atmel_console;
 #endif
 
+#ifdef SUPPORT_PDC
+static bool atmel_use_dma_rx(struct uart_port *port)
+{
+   struct atmel_uart_port *atmel_port = (struct atmel_uart_port *)port;
+
+   return atmel_port-use_dma_rx;
+}
+
+static bool atmel_use_dma_tx(struct uart_port *port)
+{
+   struct atmel_uart_port *atmel_port = (struct atmel_uart_port *)port;
+
+   return atmel_port-use_dma_tx;
+}
+#else
+static bool atmel_use_dma_rx(struct uart_port *port)
+{
+   return false;
+}
+
+static bool atmel_use_dma_tx(struct uart_port *port)
+{
+   return false;
+}
+#endif
+
 /*
  * Return TIOCSER_TEMT when transmitter FIFO and Shift register is empty.
  */
@@ -221,7 +272,12 @@ static u_int atmel_get_mctrl(struct uart_port *port)
  */
 static void atmel_stop_tx(struct uart_port *port)
 {
-   UART_PUT_IDR(port, ATMEL_US_TXRDY);
+   if (atmel_use_dma_tx(port)) {
+   /* disable PDC transmit */
+   UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
+   UART_PUT_IDR(port, ATMEL_US_ENDTX | ATMEL_US_TXBUFE);
+   } else
+   UART_PUT_IDR(port, ATMEL_US_TXRDY);
 }
 
 /*
@@ -229,7 +285,17 @@ static void atmel_stop_tx(struct uart_port *port)
  */
 static void atmel_start_tx(struct uart_port *port)
 {
-   UART_PUT_IER(port, ATMEL_US_TXRDY);
+   if (atmel_use_dma_tx(port)) {
+   if (UART_GET_PTSR(port)  ATMEL_PDC_TXTEN)
+   /* The transmitter is already running.  Yes, we
+  really need this.*/
+   return;
+
+   UART_PUT_IER(port, ATMEL_US_ENDTX 

Re: [PATCH 5/5] atmel_serial: Add DMA support

2007-12-18 Thread Chip Coldwell
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

On Tue, 18 Dec 2007, Haavard Skinnemoen wrote:

 From: Chip Coldwell [EMAIL PROTECTED]
 
 This patch is based on the DMA-patch by Chip Coldwell for the
 AT91/AT32 serial USARTS, with some tweaks to make it apply neatly on
 top of the other patches in this series.
 
 The RX code has been moved to a tasklet and reworked a bit. Instead of
 depending on the ENDRX and TIMEOUT bits in CSR, we simply grab as much
 data as we can from the DMA buffers. I think this closes a race where
 the ENDRX bit is set after we read CSR but before we read RPR,
 although I haven't confirmed this.
 
 This also fixes a DMA sync bug in the original patch.
 
 [EMAIL PROTECTED]: rebased onto irq-splitup patch]
 [EMAIL PROTECTED]: moved to tasklet, fixed dma bug, misc cleanups]
 Signed-off-by: Remy Bohmer [EMAIL PROTECTED]
 Signed-off-by: Haavard Skinnemoen [EMAIL PROTECTED]
 ---
  drivers/serial/atmel_serial.c |  386 ++--
  1 files changed, 366 insertions(+), 20 deletions(-)
 
 diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c
 index 990d3ab..07c2734 100644
 --- a/drivers/serial/atmel_serial.c
 +++ b/drivers/serial/atmel_serial.c
 @@ -7,6 +7,8 @@
   *  Based on drivers/char/serial_sa1100.c, by Deep Blue Solutions Ltd.
   *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
   *
 + *  DMA support added by Chip Coldwell.

I will ACK/Sign-off on this soon; I just want to do some tests on real
hardware first.

Chip

- -- 
Charles M. Coldwell
Turn on, log in, tune out
Somerville, Massachusetts, New England
-BEGIN PGP SIGNATURE-
Version: GnuPG v1.4.7 (GNU/Linux)

iD8DBQFHaA7cr6maj4UuBS8RAjMSAJsGcKoFKCP/R3aAPhW5hj+v3Qt6ZACgshsF
5NP6/9+NbhDAxBC/7jo8J0Y=
=hx4t
-END PGP SIGNATURE-
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/