From 55e91575163dae33a50f26501c1022713fae3698 Mon Sep 17 00:00:00 2001 From: Harvey Hunt Date: Mon, 13 Jul 2015 10:52:21 +0100 Subject: [PATCH] serial: jz_uart: Add UART polling support In order to use kdb over serial, the UART driver needs to have polling support - this commit implements that. The code is a lightly modified version of tty/serial/8250.c Signed-off-by: Harvey Hunt --- drivers/tty/serial/jz_uart.c | 52 ++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/drivers/tty/serial/jz_uart.c b/drivers/tty/serial/jz_uart.c index 0bd1630b46dae4..0e685be7b04277 100644 --- a/drivers/tty/serial/jz_uart.c +++ b/drivers/tty/serial/jz_uart.c @@ -82,6 +82,8 @@ struct uart_jz47xx_port { static inline void check_modem_status(struct uart_jz47xx_port *up); static unsigned short *serial47xx_get_divisor(struct uart_port *port, unsigned int baud); static inline void serial_dl_write(struct uart_port *up, int value); +static int uart_jz47xx_get_poll_char(struct uart_port *port); +static void uart_jz47xx_put_poll_char(struct uart_port *port, unsigned char c); static inline unsigned int serial_in(struct uart_jz47xx_port *up, int offset) { @@ -994,6 +996,52 @@ static void serial_jz47xx_console_write(struct console *co, const char *s, unsig spin_unlock(&up->port.lock); } +#ifdef CONFIG_CONSOLE_POLL +static int uart_jz47xx_get_poll_char(struct uart_port *port) +{ + struct uart_jz47xx_port *up = + container_of(port, struct uart_jz47xx_port, port); + unsigned char lsr = serial_in(up, UART_LSR); + + if (!(lsr & UART_LSR_DR)) + return NO_POLL_CHAR; + + return serial_in(up, UART_RX); +} + +static void uart_jz47xx_put_poll_char(struct uart_port *port, + unsigned char c) +{ + unsigned int ier; + struct uart_jz47xx_port *up = + container_of(port, struct uart_jz47xx_port, port); + + /* + * First save the IER then disable the interrupts + */ + ier = serial_in(up, UART_IER); + serial_out(up, UART_IER, 0); + + wait_for_xmitr(up); + /* + * Send the character out. + * If a LF, also do CR... + */ + serial_out(up, UART_TX, c); + if (c == 10) { + wait_for_xmitr(up); + serial_out(up, UART_TX, 13); + } + + /* + * Finally, wait for transmitter to become empty + * and restore the IER + */ + wait_for_xmitr(up); + serial_out(up, UART_IER, ier); +} +#endif + static int __init serial_jz47xx_console_setup(struct console *co, char *options) { struct uart_jz47xx_port *up; @@ -1046,6 +1094,10 @@ struct uart_ops serial_jz47xx_pops = { .request_port = serial_jz47xx_request_port, .config_port = serial_jz47xx_config_port, .verify_port = serial_jz47xx_verify_port, +#ifdef CONFIG_CONSOLE_POLL + .poll_get_char = uart_jz47xx_get_poll_char, + .poll_put_char = uart_jz47xx_put_poll_char, +#endif }; static struct uart_driver serial_jz47xx_reg = {