aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChip Coldwell <coldwell@redhat.com>2008-02-08 07:21:06 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-08 12:22:37 -0500
commita66706158d6bc4d9eb29c37852001f78f4c8989c (patch)
treed2d593dc2902c1db1ea6d0ef417dc3426e0b3bae
parent1ecc26bd2789ddb253f61e182a61c776663fe44c (diff)
atmel_serial: add DMA support
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 and TX 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. Similarly, the two TX handlers (ENDTX and TXBUFE) have been combined into one. Since the current code only uses a single TX buffer, there's no point in handling those interrupts separately. This also fixes a DMA sync bug in the original patch. [linux@bohmer.net: rebased onto irq-splitup patch] [hskinnemoen@atmel.com: moved to tasklet, fixed dma bug, misc cleanups] [hskinnemoen@atmel.com: atmel_serial dma: Misc fixes and cleanups] Signed-off-by: Remy Bohmer <linux@bohmer.net> Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com> Cc: Andrew Victor <linux@maxim.org.za> Tested-by: Marc Pignat <marc.pignat@hevs.ch> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/serial/Kconfig15
-rw-r--r--drivers/serial/atmel_serial.c392
2 files changed, 383 insertions, 24 deletions
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 84a054d7e986..b82595cf13e8 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -380,6 +380,21 @@ config SERIAL_ATMEL_CONSOLE
380 console is the device which receives all kernel messages and 380 console is the device which receives all kernel messages and
381 warnings and which allows logins in single user mode). 381 warnings and which allows logins in single user mode).
382 382
383config SERIAL_ATMEL_PDC
384 bool "Support DMA transfers on AT91 / AT32 serial port"
385 depends on SERIAL_ATMEL
386 default y
387 help
388 Say Y here if you wish to use the PDC to do DMA transfers to
389 and from the Atmel AT91 / AT32 serial port. In order to
390 actually use DMA transfers, make sure that the use_dma_tx
391 and use_dma_rx members in the atmel_uart_data struct is set
392 appropriately for each port.
393
394 Note that break and error handling currently doesn't work
395 properly when DMA is enabled. Make sure that ports where
396 this matters don't use DMA.
397
383config SERIAL_ATMEL_TTYAT 398config SERIAL_ATMEL_TTYAT
384 bool "Install as device ttyATn instead of ttySn" 399 bool "Install as device ttyATn instead of ttySn"
385 depends on SERIAL_ATMEL=y 400 depends on SERIAL_ATMEL=y
diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c
index f0f6ea3a9eed..d15ab2243289 100644
--- a/drivers/serial/atmel_serial.c
+++ b/drivers/serial/atmel_serial.c
@@ -7,6 +7,8 @@
7 * Based on drivers/char/serial_sa1100.c, by Deep Blue Solutions Ltd. 7 * Based on drivers/char/serial_sa1100.c, by Deep Blue Solutions Ltd.
8 * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. 8 * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
9 * 9 *
10 * DMA support added by Chip Coldwell.
11 *
10 * This program is free software; you can redistribute it and/or modify 12 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by 13 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or 14 * the Free Software Foundation; either version 2 of the License, or
@@ -33,6 +35,7 @@
33#include <linux/sysrq.h> 35#include <linux/sysrq.h>
34#include <linux/tty_flip.h> 36#include <linux/tty_flip.h>
35#include <linux/platform_device.h> 37#include <linux/platform_device.h>
38#include <linux/dma-mapping.h>
36#include <linux/atmel_pdc.h> 39#include <linux/atmel_pdc.h>
37#include <linux/atmel_serial.h> 40#include <linux/atmel_serial.h>
38 41
@@ -46,6 +49,10 @@
46#include <asm/arch/gpio.h> 49#include <asm/arch/gpio.h>
47#endif 50#endif
48 51
52#define PDC_BUFFER_SIZE 512
53/* Revisit: We should calculate this based on the actual port settings */
54#define PDC_RX_TIMEOUT (3 * 10) /* 3 bytes */
55
49#if defined(CONFIG_SERIAL_ATMEL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) 56#if defined(CONFIG_SERIAL_ATMEL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
50#define SUPPORT_SYSRQ 57#define SUPPORT_SYSRQ
51#endif 58#endif
@@ -103,6 +110,13 @@
103static int (*atmel_open_hook)(struct uart_port *); 110static int (*atmel_open_hook)(struct uart_port *);
104static void (*atmel_close_hook)(struct uart_port *); 111static void (*atmel_close_hook)(struct uart_port *);
105 112
113struct atmel_dma_buffer {
114 unsigned char *buf;
115 dma_addr_t dma_addr;
116 unsigned int dma_size;
117 unsigned int ofs;
118};
119
106struct atmel_uart_char { 120struct atmel_uart_char {
107 u16 status; 121 u16 status;
108 u16 ch; 122 u16 ch;
@@ -119,6 +133,13 @@ struct atmel_uart_port {
119 unsigned short suspended; /* is port suspended? */ 133 unsigned short suspended; /* is port suspended? */
120 int break_active; /* break being received */ 134 int break_active; /* break being received */
121 135
136 short use_dma_rx; /* enable PDC receiver */
137 short pdc_rx_idx; /* current PDC RX buffer */
138 struct atmel_dma_buffer pdc_rx[2]; /* PDC receier */
139
140 short use_dma_tx; /* enable PDC transmitter */
141 struct atmel_dma_buffer pdc_tx; /* PDC transmitter */
142
122 struct tasklet_struct tasklet; 143 struct tasklet_struct tasklet;
123 unsigned int irq_status; 144 unsigned int irq_status;
124 unsigned int irq_status_prev; 145 unsigned int irq_status_prev;
@@ -132,6 +153,32 @@ static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART];
132static struct console atmel_console; 153static struct console atmel_console;
133#endif 154#endif
134 155
156#ifdef CONFIG_SERIAL_ATMEL_PDC
157static bool atmel_use_dma_rx(struct uart_port *port)
158{
159 struct atmel_uart_port *atmel_port = (struct atmel_uart_port *)port;
160
161 return atmel_port->use_dma_rx;
162}
163
164static bool atmel_use_dma_tx(struct uart_port *port)
165{
166 struct atmel_uart_port *atmel_port = (struct atmel_uart_port *)port;
167
168 return atmel_port->use_dma_tx;
169}
170#else
171static bool atmel_use_dma_rx(struct uart_port *port)
172{
173 return false;
174}
175
176static bool atmel_use_dma_tx(struct uart_port *port)
177{
178 return false;
179}
180#endif
181
135/* 182/*
136 * Return TIOCSER_TEMT when transmitter FIFO and Shift register is empty. 183 * Return TIOCSER_TEMT when transmitter FIFO and Shift register is empty.
137 */ 184 */
@@ -213,7 +260,12 @@ static u_int atmel_get_mctrl(struct uart_port *port)
213 */ 260 */
214static void atmel_stop_tx(struct uart_port *port) 261static void atmel_stop_tx(struct uart_port *port)
215{ 262{
216 UART_PUT_IDR(port, ATMEL_US_TXRDY); 263 if (atmel_use_dma_tx(port)) {
264 /* disable PDC transmit */
265 UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
266 UART_PUT_IDR(port, ATMEL_US_ENDTX | ATMEL_US_TXBUFE);
267 } else
268 UART_PUT_IDR(port, ATMEL_US_TXRDY);
217} 269}
218 270
219/* 271/*
@@ -221,7 +273,17 @@ static void atmel_stop_tx(struct uart_port *port)
221 */ 273 */
222static void atmel_start_tx(struct uart_port *port) 274static void atmel_start_tx(struct uart_port *port)
223{ 275{
224 UART_PUT_IER(port, ATMEL_US_TXRDY); 276 if (atmel_use_dma_tx(port)) {
277 if (UART_GET_PTSR(port) & ATMEL_PDC_TXTEN)
278 /* The transmitter is already running. Yes, we
279 really need this.*/
280 return;
281
282 UART_PUT_IER(port, ATMEL_US_ENDTX | ATMEL_US_TXBUFE);
283 /* re-enable PDC transmit */
284 UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);
285 } else
286 UART_PUT_IER(port, ATMEL_US_TXRDY);
225} 287}
226 288
227/* 289/*
@@ -229,7 +291,12 @@ static void atmel_start_tx(struct uart_port *port)
229 */ 291 */
230static void atmel_stop_rx(struct uart_port *port) 292static void atmel_stop_rx(struct uart_port *port)
231{ 293{
232 UART_PUT_IDR(port, ATMEL_US_RXRDY); 294 if (atmel_use_dma_rx(port)) {
295 /* disable PDC receive */
296 UART_PUT_PTCR(port, ATMEL_PDC_RXTDIS);
297 UART_PUT_IDR(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
298 } else
299 UART_PUT_IDR(port, ATMEL_US_RXRDY);
233} 300}
234 301
235/* 302/*
@@ -278,6 +345,27 @@ atmel_buffer_rx_char(struct uart_port *port, unsigned int status,
278} 345}
279 346
280/* 347/*
348 * Deal with parity, framing and overrun errors.
349 */
350static void atmel_pdc_rxerr(struct uart_port *port, unsigned int status)
351{
352 /* clear error */
353 UART_PUT_CR(port, ATMEL_US_RSTSTA);
354
355 if (status & ATMEL_US_RXBRK) {
356 /* ignore side-effect */
357 status &= ~(ATMEL_US_PARE | ATMEL_US_FRAME);
358 port->icount.brk++;
359 }
360 if (status & ATMEL_US_PARE)
361 port->icount.parity++;
362 if (status & ATMEL_US_FRAME)
363 port->icount.frame++;
364 if (status & ATMEL_US_OVRE)
365 port->icount.overrun++;
366}
367
368/*
281 * Characters received (called from interrupt handler) 369 * Characters received (called from interrupt handler)
282 */ 370 */
283static void atmel_rx_chars(struct uart_port *port) 371static void atmel_rx_chars(struct uart_port *port)
@@ -364,6 +452,25 @@ atmel_handle_receive(struct uart_port *port, unsigned int pending)
364{ 452{
365 struct atmel_uart_port *atmel_port = (struct atmel_uart_port *)port; 453 struct atmel_uart_port *atmel_port = (struct atmel_uart_port *)port;
366 454
455 if (atmel_use_dma_rx(port)) {
456 /*
457 * PDC receive. Just schedule the tasklet and let it
458 * figure out the details.
459 *
460 * TODO: We're not handling error flags correctly at
461 * the moment.
462 */
463 if (pending & (ATMEL_US_ENDRX | ATMEL_US_TIMEOUT)) {
464 UART_PUT_IDR(port, (ATMEL_US_ENDRX
465 | ATMEL_US_TIMEOUT));
466 tasklet_schedule(&atmel_port->tasklet);
467 }
468
469 if (pending & (ATMEL_US_RXBRK | ATMEL_US_OVRE |
470 ATMEL_US_FRAME | ATMEL_US_PARE))
471 atmel_pdc_rxerr(port, pending);
472 }
473
367 /* Interrupt receive */ 474 /* Interrupt receive */
368 if (pending & ATMEL_US_RXRDY) 475 if (pending & ATMEL_US_RXRDY)
369 atmel_rx_chars(port); 476 atmel_rx_chars(port);
@@ -386,10 +493,18 @@ atmel_handle_transmit(struct uart_port *port, unsigned int pending)
386{ 493{
387 struct atmel_uart_port *atmel_port = (struct atmel_uart_port *)port; 494 struct atmel_uart_port *atmel_port = (struct atmel_uart_port *)port;
388 495
389 /* Interrupt transmit */ 496 if (atmel_use_dma_tx(port)) {
390 if (pending & ATMEL_US_TXRDY) { 497 /* PDC transmit */
391 UART_PUT_IDR(port, ATMEL_US_TXRDY); 498 if (pending & (ATMEL_US_ENDTX | ATMEL_US_TXBUFE)) {
392 tasklet_schedule(&atmel_port->tasklet); 499 UART_PUT_IDR(port, ATMEL_US_ENDTX | ATMEL_US_TXBUFE);
500 tasklet_schedule(&atmel_port->tasklet);
501 }
502 } else {
503 /* Interrupt transmit */
504 if (pending & ATMEL_US_TXRDY) {
505 UART_PUT_IDR(port, ATMEL_US_TXRDY);
506 tasklet_schedule(&atmel_port->tasklet);
507 }
393 } 508 }
394} 509}
395 510
@@ -417,20 +532,63 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id)
417 struct uart_port *port = dev_id; 532 struct uart_port *port = dev_id;
418 unsigned int status, pending, pass_counter = 0; 533 unsigned int status, pending, pass_counter = 0;
419 534
420 status = UART_GET_CSR(port); 535 do {
421 pending = status & UART_GET_IMR(port); 536 status = UART_GET_CSR(port);
422 while (pending) { 537 pending = status & UART_GET_IMR(port);
538 if (!pending)
539 break;
540
423 atmel_handle_receive(port, pending); 541 atmel_handle_receive(port, pending);
424 atmel_handle_status(port, pending, status); 542 atmel_handle_status(port, pending, status);
425 atmel_handle_transmit(port, pending); 543 atmel_handle_transmit(port, pending);
544 } while (pass_counter++ < ATMEL_ISR_PASS_LIMIT);
426 545
427 if (pass_counter++ > ATMEL_ISR_PASS_LIMIT) 546 return IRQ_HANDLED;
428 break; 547}
429 548
430 status = UART_GET_CSR(port); 549/*
431 pending = status & UART_GET_IMR(port); 550 * Called from tasklet with ENDTX and TXBUFE interrupts disabled.
551 */
552static void atmel_tx_dma(struct uart_port *port)
553{
554 struct atmel_uart_port *atmel_port = (struct atmel_uart_port *)port;
555 struct circ_buf *xmit = &port->info->xmit;
556 struct atmel_dma_buffer *pdc = &atmel_port->pdc_tx;
557 int count;
558
559 xmit->tail += pdc->ofs;
560 xmit->tail &= UART_XMIT_SIZE - 1;
561
562 port->icount.tx += pdc->ofs;
563 pdc->ofs = 0;
564
565 if (!uart_circ_empty(xmit)) {
566 /* more to transmit - setup next transfer */
567
568 /* disable PDC transmit */
569 UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
570 dma_sync_single_for_device(port->dev,
571 pdc->dma_addr,
572 pdc->dma_size,
573 DMA_TO_DEVICE);
574
575 count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
576 pdc->ofs = count;
577
578 UART_PUT_TPR(port, pdc->dma_addr + xmit->tail);
579 UART_PUT_TCR(port, count);
580 /* re-enable PDC transmit and interrupts */
581 UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);
582 UART_PUT_IER(port, ATMEL_US_ENDTX | ATMEL_US_TXBUFE);
583 } else {
584 /* nothing left to transmit - disable the transmitter */
585
586 /* disable PDC transmit */
587 UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
432 } 588 }
433 return IRQ_HANDLED; 589
590 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
591 uart_write_wakeup(port);
434} 592}
435 593
436static void atmel_rx_from_ring(struct uart_port *port) 594static void atmel_rx_from_ring(struct uart_port *port)
@@ -501,6 +659,82 @@ static void atmel_rx_from_ring(struct uart_port *port)
501 spin_lock(&port->lock); 659 spin_lock(&port->lock);
502} 660}
503 661
662static void atmel_rx_from_dma(struct uart_port *port)
663{
664 struct atmel_uart_port *atmel_port = (struct atmel_uart_port *)port;
665 struct tty_struct *tty = port->info->tty;
666 struct atmel_dma_buffer *pdc;
667 int rx_idx = atmel_port->pdc_rx_idx;
668 unsigned int head;
669 unsigned int tail;
670 unsigned int count;
671
672 do {
673 /* Reset the UART timeout early so that we don't miss one */
674 UART_PUT_CR(port, ATMEL_US_STTTO);
675
676 pdc = &atmel_port->pdc_rx[rx_idx];
677 head = UART_GET_RPR(port) - pdc->dma_addr;
678 tail = pdc->ofs;
679
680 /* If the PDC has switched buffers, RPR won't contain
681 * any address within the current buffer. Since head
682 * is unsigned, we just need a one-way comparison to
683 * find out.
684 *
685 * In this case, we just need to consume the entire
686 * buffer and resubmit it for DMA. This will clear the
687 * ENDRX bit as well, so that we can safely re-enable
688 * all interrupts below.
689 */
690 head = min(head, pdc->dma_size);
691
692 if (likely(head != tail)) {
693 dma_sync_single_for_cpu(port->dev, pdc->dma_addr,
694 pdc->dma_size, DMA_FROM_DEVICE);
695
696 /*
697 * head will only wrap around when we recycle
698 * the DMA buffer, and when that happens, we
699 * explicitly set tail to 0. So head will
700 * always be greater than tail.
701 */
702 count = head - tail;
703
704 tty_insert_flip_string(tty, pdc->buf + pdc->ofs, count);
705
706 dma_sync_single_for_device(port->dev, pdc->dma_addr,
707 pdc->dma_size, DMA_FROM_DEVICE);
708
709 port->icount.rx += count;
710 pdc->ofs = head;
711 }
712
713 /*
714 * If the current buffer is full, we need to check if
715 * the next one contains any additional data.
716 */
717 if (head >= pdc->dma_size) {
718 pdc->ofs = 0;
719 UART_PUT_RNPR(port, pdc->dma_addr);
720 UART_PUT_RNCR(port, pdc->dma_size);
721
722 rx_idx = !rx_idx;
723 atmel_port->pdc_rx_idx = rx_idx;
724 }
725 } while (head >= pdc->dma_size);
726
727 /*
728 * Drop the lock here since it might end up calling
729 * uart_start(), which takes the lock.
730 */
731 spin_unlock(&port->lock);
732 tty_flip_buffer_push(tty);
733 spin_lock(&port->lock);
734
735 UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
736}
737
504/* 738/*
505 * tasklet handling tty stuff outside the interrupt handler. 739 * tasklet handling tty stuff outside the interrupt handler.
506 */ 740 */
@@ -514,7 +748,10 @@ static void atmel_tasklet_func(unsigned long data)
514 /* The interrupt handler does not take the lock */ 748 /* The interrupt handler does not take the lock */
515 spin_lock(&port->lock); 749 spin_lock(&port->lock);
516 750
517 atmel_tx_chars(port); 751 if (atmel_use_dma_tx(port))
752 atmel_tx_dma(port);
753 else
754 atmel_tx_chars(port);
518 755
519 status = atmel_port->irq_status; 756 status = atmel_port->irq_status;
520 status_change = status ^ atmel_port->irq_status_prev; 757 status_change = status ^ atmel_port->irq_status_prev;
@@ -536,7 +773,10 @@ static void atmel_tasklet_func(unsigned long data)
536 atmel_port->irq_status_prev = status; 773 atmel_port->irq_status_prev = status;
537 } 774 }
538 775
539 atmel_rx_from_ring(port); 776 if (atmel_use_dma_rx(port))
777 atmel_rx_from_dma(port);
778 else
779 atmel_rx_from_ring(port);
540 780
541 spin_unlock(&port->lock); 781 spin_unlock(&port->lock);
542} 782}
@@ -546,6 +786,7 @@ static void atmel_tasklet_func(unsigned long data)
546 */ 786 */
547static int atmel_startup(struct uart_port *port) 787static int atmel_startup(struct uart_port *port)
548{ 788{
789 struct atmel_uart_port *atmel_port = (struct atmel_uart_port *)port;
549 int retval; 790 int retval;
550 791
551 /* 792 /*
@@ -566,6 +807,56 @@ static int atmel_startup(struct uart_port *port)
566 } 807 }
567 808
568 /* 809 /*
810 * Initialize DMA (if necessary)
811 */
812 if (atmel_use_dma_rx(port)) {
813 int i;
814
815 for (i = 0; i < 2; i++) {
816 struct atmel_dma_buffer *pdc = &atmel_port->pdc_rx[i];
817
818 pdc->buf = kmalloc(PDC_BUFFER_SIZE, GFP_KERNEL);
819 if (pdc->buf == NULL) {
820 if (i != 0) {
821 dma_unmap_single(port->dev,
822 atmel_port->pdc_rx[0].dma_addr,
823 PDC_BUFFER_SIZE,
824 DMA_FROM_DEVICE);
825 kfree(atmel_port->pdc_rx[0].buf);
826 }
827 free_irq(port->irq, port);
828 return -ENOMEM;
829 }
830 pdc->dma_addr = dma_map_single(port->dev,
831 pdc->buf,
832 PDC_BUFFER_SIZE,
833 DMA_FROM_DEVICE);
834 pdc->dma_size = PDC_BUFFER_SIZE;
835 pdc->ofs = 0;
836 }
837
838 atmel_port->pdc_rx_idx = 0;
839
840 UART_PUT_RPR(port, atmel_port->pdc_rx[0].dma_addr);
841 UART_PUT_RCR(port, PDC_BUFFER_SIZE);
842
843 UART_PUT_RNPR(port, atmel_port->pdc_rx[1].dma_addr);
844 UART_PUT_RNCR(port, PDC_BUFFER_SIZE);
845 }
846 if (atmel_use_dma_tx(port)) {
847 struct atmel_dma_buffer *pdc = &atmel_port->pdc_tx;
848 struct circ_buf *xmit = &port->info->xmit;
849
850 pdc->buf = xmit->buf;
851 pdc->dma_addr = dma_map_single(port->dev,
852 pdc->buf,
853 UART_XMIT_SIZE,
854 DMA_TO_DEVICE);
855 pdc->dma_size = UART_XMIT_SIZE;
856 pdc->ofs = 0;
857 }
858
859 /*
569 * If there is a specific "open" function (to register 860 * If there is a specific "open" function (to register
570 * control line interrupts) 861 * control line interrupts)
571 */ 862 */
@@ -584,8 +875,18 @@ static int atmel_startup(struct uart_port *port)
584 /* enable xmit & rcvr */ 875 /* enable xmit & rcvr */
585 UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN); 876 UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);
586 877
587 /* enable receive only */ 878 if (atmel_use_dma_rx(port)) {
588 UART_PUT_IER(port, ATMEL_US_RXRDY); 879 /* set UART timeout */
880 UART_PUT_RTOR(port, PDC_RX_TIMEOUT);
881 UART_PUT_CR(port, ATMEL_US_STTTO);
882
883 UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
884 /* enable PDC controller */
885 UART_PUT_PTCR(port, ATMEL_PDC_RXTEN);
886 } else {
887 /* enable receive only */
888 UART_PUT_IER(port, ATMEL_US_RXRDY);
889 }
589 890
590 return 0; 891 return 0;
591} 892}
@@ -595,6 +896,38 @@ static int atmel_startup(struct uart_port *port)
595 */ 896 */
596static void atmel_shutdown(struct uart_port *port) 897static void atmel_shutdown(struct uart_port *port)
597{ 898{
899 struct atmel_uart_port *atmel_port = (struct atmel_uart_port *)port;
900 /*
901 * Ensure everything is stopped.
902 */
903 atmel_stop_rx(port);
904 atmel_stop_tx(port);
905
906 /*
907 * Shut-down the DMA.
908 */
909 if (atmel_use_dma_rx(port)) {
910 int i;
911
912 for (i = 0; i < 2; i++) {
913 struct atmel_dma_buffer *pdc = &atmel_port->pdc_rx[i];
914
915 dma_unmap_single(port->dev,
916 pdc->dma_addr,
917 pdc->dma_size,
918 DMA_FROM_DEVICE);
919 kfree(pdc->buf);
920 }
921 }
922 if (atmel_use_dma_tx(port)) {
923 struct atmel_dma_buffer *pdc = &atmel_port->pdc_tx;
924
925 dma_unmap_single(port->dev,
926 pdc->dma_addr,
927 pdc->dma_size,
928 DMA_TO_DEVICE);
929 }
930
598 /* 931 /*
599 * Disable all interrupts, port and break condition. 932 * Disable all interrupts, port and break condition.
600 */ 933 */
@@ -706,6 +1039,10 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
706 if (termios->c_iflag & (BRKINT | PARMRK)) 1039 if (termios->c_iflag & (BRKINT | PARMRK))
707 port->read_status_mask |= ATMEL_US_RXBRK; 1040 port->read_status_mask |= ATMEL_US_RXBRK;
708 1041
1042 if (atmel_use_dma_rx(port))
1043 /* need to enable error interrupts */
1044 UART_PUT_IER(port, port->read_status_mask);
1045
709 /* 1046 /*
710 * Characters to ignore 1047 * Characters to ignore
711 */ 1048 */
@@ -891,6 +1228,11 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port,
891 clk_enable(atmel_port->clk); 1228 clk_enable(atmel_port->clk);
892 port->uartclk = clk_get_rate(atmel_port->clk); 1229 port->uartclk = clk_get_rate(atmel_port->clk);
893 } 1230 }
1231
1232 atmel_port->use_dma_rx = data->use_dma_rx;
1233 atmel_port->use_dma_tx = data->use_dma_tx;
1234 if (atmel_use_dma_tx(port))
1235 port->fifosize = PDC_BUFFER_SIZE;
894} 1236}
895 1237
896/* 1238/*
@@ -1125,11 +1467,13 @@ static int __devinit atmel_serial_probe(struct platform_device *pdev)
1125 port = &atmel_ports[pdev->id]; 1467 port = &atmel_ports[pdev->id];
1126 atmel_init_port(port, pdev); 1468 atmel_init_port(port, pdev);
1127 1469
1128 ret = -ENOMEM; 1470 if (!atmel_use_dma_rx(&port->uart)) {
1129 data = kmalloc(ATMEL_SERIAL_RINGSIZE, GFP_KERNEL); 1471 ret = -ENOMEM;
1130 if (!data) 1472 data = kmalloc(ATMEL_SERIAL_RINGSIZE, GFP_KERNEL);
1131 goto err_alloc_ring; 1473 if (!data)
1132 port->rx_ring.buf = data; 1474 goto err_alloc_ring;
1475 port->rx_ring.buf = data;
1476 }
1133 1477
1134 ret = uart_add_one_port(&atmel_uart, &port->uart); 1478 ret = uart_add_one_port(&atmel_uart, &port->uart);
1135 if (ret) 1479 if (ret)