diff options
| -rw-r--r-- | drivers/serial/serial_txx9.c | 113 |
1 files changed, 92 insertions, 21 deletions
diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c index 7313c2edcb83..54dd16d66a4b 100644 --- a/drivers/serial/serial_txx9.c +++ b/drivers/serial/serial_txx9.c | |||
| @@ -461,6 +461,94 @@ static void serial_txx9_break_ctl(struct uart_port *port, int break_state) | |||
| 461 | spin_unlock_irqrestore(&up->port.lock, flags); | 461 | spin_unlock_irqrestore(&up->port.lock, flags); |
| 462 | } | 462 | } |
| 463 | 463 | ||
| 464 | #if defined(CONFIG_SERIAL_TXX9_CONSOLE) || (CONFIG_CONSOLE_POLL) | ||
| 465 | /* | ||
| 466 | * Wait for transmitter & holding register to empty | ||
| 467 | */ | ||
| 468 | static void wait_for_xmitr(struct uart_txx9_port *up) | ||
| 469 | { | ||
| 470 | unsigned int tmout = 10000; | ||
| 471 | |||
| 472 | /* Wait up to 10ms for the character(s) to be sent. */ | ||
| 473 | while (--tmout && | ||
| 474 | !(sio_in(up, TXX9_SICISR) & TXX9_SICISR_TXALS)) | ||
| 475 | udelay(1); | ||
| 476 | |||
| 477 | /* Wait up to 1s for flow control if necessary */ | ||
| 478 | if (up->port.flags & UPF_CONS_FLOW) { | ||
| 479 | tmout = 1000000; | ||
| 480 | while (--tmout && | ||
| 481 | (sio_in(up, TXX9_SICISR) & TXX9_SICISR_CTSS)) | ||
| 482 | udelay(1); | ||
| 483 | } | ||
| 484 | } | ||
| 485 | #endif | ||
| 486 | |||
| 487 | #ifdef CONFIG_CONSOLE_POLL | ||
| 488 | /* | ||
| 489 | * Console polling routines for writing and reading from the uart while | ||
| 490 | * in an interrupt or debug context. | ||
| 491 | */ | ||
| 492 | |||
| 493 | static int serial_txx9_get_poll_char(struct uart_port *port) | ||
| 494 | { | ||
| 495 | unsigned int ier; | ||
| 496 | unsigned char c; | ||
| 497 | struct uart_txx9_port *up = (struct uart_txx9_port *)port; | ||
| 498 | |||
| 499 | /* | ||
| 500 | * First save the IER then disable the interrupts | ||
| 501 | */ | ||
| 502 | ier = sio_in(up, TXX9_SIDICR); | ||
| 503 | sio_out(up, TXX9_SIDICR, 0); | ||
| 504 | |||
| 505 | while (sio_in(up, TXX9_SIDISR) & TXX9_SIDISR_UVALID) | ||
| 506 | ; | ||
| 507 | |||
| 508 | c = sio_in(up, TXX9_SIRFIFO); | ||
| 509 | |||
| 510 | /* | ||
| 511 | * Finally, clear RX interrupt status | ||
| 512 | * and restore the IER | ||
| 513 | */ | ||
| 514 | sio_mask(up, TXX9_SIDISR, TXX9_SIDISR_RDIS); | ||
| 515 | sio_out(up, TXX9_SIDICR, ier); | ||
| 516 | return c; | ||
| 517 | } | ||
| 518 | |||
| 519 | |||
| 520 | static void serial_txx9_put_poll_char(struct uart_port *port, unsigned char c) | ||
| 521 | { | ||
| 522 | unsigned int ier; | ||
| 523 | struct uart_txx9_port *up = (struct uart_txx9_port *)port; | ||
| 524 | |||
| 525 | /* | ||
| 526 | * First save the IER then disable the interrupts | ||
| 527 | */ | ||
| 528 | ier = sio_in(up, TXX9_SIDICR); | ||
| 529 | sio_out(up, TXX9_SIDICR, 0); | ||
| 530 | |||
| 531 | wait_for_xmitr(up); | ||
| 532 | /* | ||
| 533 | * Send the character out. | ||
| 534 | * If a LF, also do CR... | ||
| 535 | */ | ||
| 536 | sio_out(up, TXX9_SITFIFO, c); | ||
| 537 | if (c == 10) { | ||
| 538 | wait_for_xmitr(up); | ||
| 539 | sio_out(up, TXX9_SITFIFO, 13); | ||
| 540 | } | ||
| 541 | |||
| 542 | /* | ||
| 543 | * Finally, wait for transmitter to become empty | ||
| 544 | * and restore the IER | ||
| 545 | */ | ||
| 546 | wait_for_xmitr(up); | ||
| 547 | sio_out(up, TXX9_SIDICR, ier); | ||
| 548 | } | ||
| 549 | |||
| 550 | #endif /* CONFIG_CONSOLE_POLL */ | ||
| 551 | |||
| 464 | static int serial_txx9_startup(struct uart_port *port) | 552 | static int serial_txx9_startup(struct uart_port *port) |
| 465 | { | 553 | { |
| 466 | struct uart_txx9_port *up = (struct uart_txx9_port *)port; | 554 | struct uart_txx9_port *up = (struct uart_txx9_port *)port; |
| @@ -781,6 +869,10 @@ static struct uart_ops serial_txx9_pops = { | |||
| 781 | .release_port = serial_txx9_release_port, | 869 | .release_port = serial_txx9_release_port, |
| 782 | .request_port = serial_txx9_request_port, | 870 | .request_port = serial_txx9_request_port, |
| 783 | .config_port = serial_txx9_config_port, | 871 | .config_port = serial_txx9_config_port, |
| 872 | #ifdef CONFIG_CONSOLE_POLL | ||
| 873 | .poll_get_char = serial_txx9_get_poll_char, | ||
| 874 | .poll_put_char = serial_txx9_put_poll_char, | ||
| 875 | #endif | ||
| 784 | }; | 876 | }; |
| 785 | 877 | ||
| 786 | static struct uart_txx9_port serial_txx9_ports[UART_NR]; | 878 | static struct uart_txx9_port serial_txx9_ports[UART_NR]; |
| @@ -803,27 +895,6 @@ static void __init serial_txx9_register_ports(struct uart_driver *drv, | |||
| 803 | 895 | ||
| 804 | #ifdef CONFIG_SERIAL_TXX9_CONSOLE | 896 | #ifdef CONFIG_SERIAL_TXX9_CONSOLE |
| 805 | 897 | ||
| 806 | /* | ||
| 807 | * Wait for transmitter & holding register to empty | ||
| 808 | */ | ||
| 809 | static inline void wait_for_xmitr(struct uart_txx9_port *up) | ||
| 810 | { | ||
| 811 | unsigned int tmout = 10000; | ||
| 812 | |||
| 813 | /* Wait up to 10ms for the character(s) to be sent. */ | ||
| 814 | while (--tmout && | ||
| 815 | !(sio_in(up, TXX9_SICISR) & TXX9_SICISR_TXALS)) | ||
| 816 | udelay(1); | ||
| 817 | |||
| 818 | /* Wait up to 1s for flow control if necessary */ | ||
| 819 | if (up->port.flags & UPF_CONS_FLOW) { | ||
| 820 | tmout = 1000000; | ||
| 821 | while (--tmout && | ||
| 822 | (sio_in(up, TXX9_SICISR) & TXX9_SICISR_CTSS)) | ||
| 823 | udelay(1); | ||
| 824 | } | ||
| 825 | } | ||
| 826 | |||
| 827 | static void serial_txx9_console_putchar(struct uart_port *port, int ch) | 898 | static void serial_txx9_console_putchar(struct uart_port *port, int ch) |
| 828 | { | 899 | { |
| 829 | struct uart_txx9_port *up = (struct uart_txx9_port *)port; | 900 | struct uart_txx9_port *up = (struct uart_txx9_port *)port; |
