Re: [PATCH 5/5] atmel_serial: Add DMA support
-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
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
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
-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/