aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial/bfin_5xx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/serial/bfin_5xx.c')
-rw-r--r--drivers/serial/bfin_5xx.c77
1 files changed, 67 insertions, 10 deletions
diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c
index d86123e0339..e2f6b1bfac9 100644
--- a/drivers/serial/bfin_5xx.c
+++ b/drivers/serial/bfin_5xx.c
@@ -330,6 +330,11 @@ static void bfin_serial_tx_chars(struct bfin_serial_port *uart)
330 /* Clear TFI bit */ 330 /* Clear TFI bit */
331 UART_PUT_LSR(uart, TFI); 331 UART_PUT_LSR(uart, TFI);
332#endif 332#endif
333 /* Anomaly notes:
334 * 05000215 - we always clear ETBEI within last UART TX
335 * interrupt to end a string. It is always set
336 * when start a new tx.
337 */
333 UART_CLEAR_IER(uart, ETBEI); 338 UART_CLEAR_IER(uart, ETBEI);
334 return; 339 return;
335 } 340 }
@@ -415,6 +420,7 @@ static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart)
415 set_dma_start_addr(uart->tx_dma_channel, (unsigned long)(xmit->buf+xmit->tail)); 420 set_dma_start_addr(uart->tx_dma_channel, (unsigned long)(xmit->buf+xmit->tail));
416 set_dma_x_count(uart->tx_dma_channel, uart->tx_count); 421 set_dma_x_count(uart->tx_dma_channel, uart->tx_count);
417 set_dma_x_modify(uart->tx_dma_channel, 1); 422 set_dma_x_modify(uart->tx_dma_channel, 1);
423 SSYNC();
418 enable_dma(uart->tx_dma_channel); 424 enable_dma(uart->tx_dma_channel);
419 425
420 UART_SET_IER(uart, ETBEI); 426 UART_SET_IER(uart, ETBEI);
@@ -473,27 +479,41 @@ static void bfin_serial_dma_rx_chars(struct bfin_serial_port *uart)
473void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart) 479void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart)
474{ 480{
475 int x_pos, pos; 481 int x_pos, pos;
476 unsigned long flags;
477
478 spin_lock_irqsave(&uart->port.lock, flags);
479 482
483 dma_disable_irq(uart->rx_dma_channel);
484 spin_lock_bh(&uart->port.lock);
485
486 /* 2D DMA RX buffer ring is used. Because curr_y_count and
487 * curr_x_count can't be read as an atomic operation,
488 * curr_y_count should be read before curr_x_count. When
489 * curr_x_count is read, curr_y_count may already indicate
490 * next buffer line. But, the position calculated here is
491 * still indicate the old line. The wrong position data may
492 * be smaller than current buffer tail, which cause garbages
493 * are received if it is not prohibit.
494 */
480 uart->rx_dma_nrows = get_dma_curr_ycount(uart->rx_dma_channel); 495 uart->rx_dma_nrows = get_dma_curr_ycount(uart->rx_dma_channel);
481 x_pos = get_dma_curr_xcount(uart->rx_dma_channel); 496 x_pos = get_dma_curr_xcount(uart->rx_dma_channel);
482 uart->rx_dma_nrows = DMA_RX_YCOUNT - uart->rx_dma_nrows; 497 uart->rx_dma_nrows = DMA_RX_YCOUNT - uart->rx_dma_nrows;
483 if (uart->rx_dma_nrows == DMA_RX_YCOUNT) 498 if (uart->rx_dma_nrows == DMA_RX_YCOUNT || x_pos == 0)
484 uart->rx_dma_nrows = 0; 499 uart->rx_dma_nrows = 0;
485 x_pos = DMA_RX_XCOUNT - x_pos; 500 x_pos = DMA_RX_XCOUNT - x_pos;
486 if (x_pos == DMA_RX_XCOUNT) 501 if (x_pos == DMA_RX_XCOUNT)
487 x_pos = 0; 502 x_pos = 0;
488 503
489 pos = uart->rx_dma_nrows * DMA_RX_XCOUNT + x_pos; 504 pos = uart->rx_dma_nrows * DMA_RX_XCOUNT + x_pos;
490 if (pos != uart->rx_dma_buf.tail) { 505 /* Ignore receiving data if new position is in the same line of
506 * current buffer tail and small.
507 */
508 if (pos > uart->rx_dma_buf.tail ||
509 uart->rx_dma_nrows < (uart->rx_dma_buf.tail/DMA_RX_XCOUNT)) {
491 uart->rx_dma_buf.head = pos; 510 uart->rx_dma_buf.head = pos;
492 bfin_serial_dma_rx_chars(uart); 511 bfin_serial_dma_rx_chars(uart);
493 uart->rx_dma_buf.tail = uart->rx_dma_buf.head; 512 uart->rx_dma_buf.tail = uart->rx_dma_buf.head;
494 } 513 }
495 514
496 spin_unlock_irqrestore(&uart->port.lock, flags); 515 spin_unlock_bh(&uart->port.lock);
516 dma_enable_irq(uart->rx_dma_channel);
497 517
498 mod_timer(&(uart->rx_dma_timer), jiffies + DMA_RX_FLUSH_JIFFIES); 518 mod_timer(&(uart->rx_dma_timer), jiffies + DMA_RX_FLUSH_JIFFIES);
499} 519}
@@ -514,6 +534,11 @@ static irqreturn_t bfin_serial_dma_tx_int(int irq, void *dev_id)
514 if (!(get_dma_curr_irqstat(uart->tx_dma_channel)&DMA_RUN)) { 534 if (!(get_dma_curr_irqstat(uart->tx_dma_channel)&DMA_RUN)) {
515 disable_dma(uart->tx_dma_channel); 535 disable_dma(uart->tx_dma_channel);
516 clear_dma_irqstat(uart->tx_dma_channel); 536 clear_dma_irqstat(uart->tx_dma_channel);
537 /* Anomaly notes:
538 * 05000215 - we always clear ETBEI within last UART TX
539 * interrupt to end a string. It is always set
540 * when start a new tx.
541 */
517 UART_CLEAR_IER(uart, ETBEI); 542 UART_CLEAR_IER(uart, ETBEI);
518 xmit->tail = (xmit->tail + uart->tx_count) & (UART_XMIT_SIZE - 1); 543 xmit->tail = (xmit->tail + uart->tx_count) & (UART_XMIT_SIZE - 1);
519 uart->port.icount.tx += uart->tx_count; 544 uart->port.icount.tx += uart->tx_count;
@@ -532,11 +557,26 @@ static irqreturn_t bfin_serial_dma_rx_int(int irq, void *dev_id)
532{ 557{
533 struct bfin_serial_port *uart = dev_id; 558 struct bfin_serial_port *uart = dev_id;
534 unsigned short irqstat; 559 unsigned short irqstat;
560 int x_pos, pos;
535 561
536 spin_lock(&uart->port.lock); 562 spin_lock(&uart->port.lock);
537 irqstat = get_dma_curr_irqstat(uart->rx_dma_channel); 563 irqstat = get_dma_curr_irqstat(uart->rx_dma_channel);
538 clear_dma_irqstat(uart->rx_dma_channel); 564 clear_dma_irqstat(uart->rx_dma_channel);
539 bfin_serial_dma_rx_chars(uart); 565
566 uart->rx_dma_nrows = get_dma_curr_ycount(uart->rx_dma_channel);
567 x_pos = get_dma_curr_xcount(uart->rx_dma_channel);
568 uart->rx_dma_nrows = DMA_RX_YCOUNT - uart->rx_dma_nrows;
569 if (uart->rx_dma_nrows == DMA_RX_YCOUNT || x_pos == 0)
570 uart->rx_dma_nrows = 0;
571
572 pos = uart->rx_dma_nrows * DMA_RX_XCOUNT;
573 if (pos > uart->rx_dma_buf.tail ||
574 uart->rx_dma_nrows < (uart->rx_dma_buf.tail/DMA_RX_XCOUNT)) {
575 uart->rx_dma_buf.head = pos;
576 bfin_serial_dma_rx_chars(uart);
577 uart->rx_dma_buf.tail = uart->rx_dma_buf.head;
578 }
579
540 spin_unlock(&uart->port.lock); 580 spin_unlock(&uart->port.lock);
541 581
542 return IRQ_HANDLED; 582 return IRQ_HANDLED;
@@ -789,8 +829,16 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
789 __func__); 829 __func__);
790 } 830 }
791 831
792 if (termios->c_cflag & CSTOPB) 832 /* Anomaly notes:
793 lcr |= STB; 833 * 05000231 - STOP bit is always set to 1 whatever the user is set.
834 */
835 if (termios->c_cflag & CSTOPB) {
836 if (ANOMALY_05000231)
837 printk(KERN_WARNING "STOP bits other than 1 is not "
838 "supported in case of anomaly 05000231.\n");
839 else
840 lcr |= STB;
841 }
794 if (termios->c_cflag & PARENB) 842 if (termios->c_cflag & PARENB)
795 lcr |= PEN; 843 lcr |= PEN;
796 if (!(termios->c_cflag & PARODD)) 844 if (!(termios->c_cflag & PARODD))
@@ -940,6 +988,10 @@ static void bfin_serial_reset_irda(struct uart_port *port)
940} 988}
941 989
942#ifdef CONFIG_CONSOLE_POLL 990#ifdef CONFIG_CONSOLE_POLL
991/* Anomaly notes:
992 * 05000099 - Because we only use THRE in poll_put and DR in poll_get,
993 * losing other bits of UART_LSR is not a problem here.
994 */
943static void bfin_serial_poll_put_char(struct uart_port *port, unsigned char chr) 995static void bfin_serial_poll_put_char(struct uart_port *port, unsigned char chr)
944{ 996{
945 struct bfin_serial_port *uart = (struct bfin_serial_port *)port; 997 struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
@@ -1245,12 +1297,17 @@ static __init void early_serial_write(struct console *con, const char *s,
1245 } 1297 }
1246} 1298}
1247 1299
1300/*
1301 * This should have a .setup or .early_setup in it, but then things get called
1302 * without the command line options, and the baud rate gets messed up - so
1303 * don't let the common infrastructure play with things. (see calls to setup
1304 * & earlysetup in ./kernel/printk.c:register_console()
1305 */
1248static struct __initdata console bfin_early_serial_console = { 1306static struct __initdata console bfin_early_serial_console = {
1249 .name = "early_BFuart", 1307 .name = "early_BFuart",
1250 .write = early_serial_write, 1308 .write = early_serial_write,
1251 .device = uart_console_device, 1309 .device = uart_console_device,
1252 .flags = CON_PRINTBUFFER, 1310 .flags = CON_PRINTBUFFER,
1253 .setup = bfin_serial_console_setup,
1254 .index = -1, 1311 .index = -1,
1255 .data = &bfin_serial_reg, 1312 .data = &bfin_serial_reg,
1256}; 1313};