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; |