X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fserial%2Fatmel_serial.c;h=c065a704a93ab68cfe167d73f67edbb700a8420c;hb=dd18434ff0b7d9b9ad3d596985fc84b329d2f9a8;hp=d57bf3e708d8fffb187dcbe33e410811cdeb1f66;hpb=1ca721cdb748ba72c47e9c661d54696db3cde796;p=linux-2.6 diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c index d57bf3e708..c065a704a9 100644 --- a/drivers/serial/atmel_serial.c +++ b/drivers/serial/atmel_serial.c @@ -106,6 +106,7 @@ #define UART_PUT_TPR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_TPR) #define UART_PUT_TCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_TCR) +#define UART_GET_TCR(port) __raw_readl((port)->membase + ATMEL_PDC_TCR) static int (*atmel_open_hook)(struct uart_port *); static void (*atmel_close_hook)(struct uart_port *); @@ -562,17 +563,22 @@ static void atmel_tx_dma(struct uart_port *port) struct atmel_dma_buffer *pdc = &atmel_port->pdc_tx; int count; + /* nothing left to transmit? */ + if (UART_GET_TCR(port)) + return; + xmit->tail += pdc->ofs; xmit->tail &= UART_XMIT_SIZE - 1; port->icount.tx += pdc->ofs; pdc->ofs = 0; - if (!uart_circ_empty(xmit)) { - /* more to transmit - setup next transfer */ + /* more to transmit - setup next transfer */ - /* disable PDC transmit */ - UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS); + /* disable PDC transmit */ + UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS); + + if (!uart_circ_empty(xmit)) { dma_sync_single_for_device(port->dev, pdc->dma_addr, pdc->dma_size, @@ -586,11 +592,6 @@ static void atmel_tx_dma(struct uart_port *port) /* re-enable PDC transmit and interrupts */ UART_PUT_PTCR(port, ATMEL_PDC_TXTEN); UART_PUT_IER(port, ATMEL_US_ENDTX | ATMEL_US_TXBUFE); - } else { - /* nothing left to transmit - disable the transmitter */ - - /* disable PDC transmit */ - UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS); } if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) @@ -1274,6 +1275,7 @@ static void atmel_console_write(struct console *co, const char *s, u_int count) { struct uart_port *port = &atmel_ports[co->index].uart; unsigned int status, imr; + unsigned int pdc_tx; /* * First, save IMR and then disable interrupts @@ -1281,6 +1283,10 @@ static void atmel_console_write(struct console *co, const char *s, u_int count) imr = UART_GET_IMR(port); UART_PUT_IDR(port, ATMEL_US_RXRDY | ATMEL_US_TXRDY); + /* Store PDC transmit status and disable it */ + pdc_tx = UART_GET_PTSR(port) & ATMEL_PDC_TXTEN; + UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS); + uart_console_write(port, s, count, atmel_console_putchar); /* @@ -1290,6 +1296,11 @@ static void atmel_console_write(struct console *co, const char *s, u_int count) do { status = UART_GET_CSR(port); } while (!(status & ATMEL_US_TXRDY)); + + /* Restore PDC transmit status */ + if (pdc_tx) + UART_PUT_PTCR(port, ATMEL_PDC_TXTEN); + /* set interrupts back the way they were */ UART_PUT_IER(port, imr); } @@ -1565,3 +1576,4 @@ module_exit(atmel_serial_exit); MODULE_AUTHOR("Rick Bronson"); MODULE_DESCRIPTION("Atmel AT91 / AT32 serial port driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:atmel_usart");