serial: samsung: Add poll_get_char & poll_put_char
authorJulien Pichon <pichon.jln@gmail.com>
Sat, 22 Sep 2012 06:22:31 +0000 (23:22 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 26 Sep 2012 20:40:12 +0000 (13:40 -0700)
The following patch allows users to use KGDB over serial console on
board based on Samsung SOC. It has been tested on a board using
exynos5.

[dianders: changed poll to return NO_POLL_CHAR, which appears to
fix 'help' in kgdb; also updated commit message]

Signed-off-by: Julien Pichon <pichon.jln@gmail.com>
Signed-off-by: Doug Anderson <dianders@chromium.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/tty/serial/samsung.c

index 8eef1141b81d9ac0fb0480ab3d6fc54e1e31b600..7f04717176aa42c8ba6232719903eb547e673df3 100644 (file)
@@ -876,11 +876,24 @@ s3c24xx_serial_verify_port(struct uart_port *port, struct serial_struct *ser)
 
 static struct console s3c24xx_serial_console;
 
+static int __init s3c24xx_serial_console_init(void)
+{
+       register_console(&s3c24xx_serial_console);
+       return 0;
+}
+console_initcall(s3c24xx_serial_console_init);
+
 #define S3C24XX_SERIAL_CONSOLE &s3c24xx_serial_console
 #else
 #define S3C24XX_SERIAL_CONSOLE NULL
 #endif
 
+#ifdef CONFIG_CONSOLE_POLL
+static int s3c24xx_serial_get_poll_char(struct uart_port *port);
+static void s3c24xx_serial_put_poll_char(struct uart_port *port,
+                        unsigned char c);
+#endif
+
 static struct uart_ops s3c24xx_serial_ops = {
        .pm             = s3c24xx_serial_pm,
        .tx_empty       = s3c24xx_serial_tx_empty,
@@ -899,6 +912,10 @@ static struct uart_ops s3c24xx_serial_ops = {
        .request_port   = s3c24xx_serial_request_port,
        .config_port    = s3c24xx_serial_config_port,
        .verify_port    = s3c24xx_serial_verify_port,
+#ifdef CONFIG_CONSOLE_POLL
+       .poll_get_char = s3c24xx_serial_get_poll_char,
+       .poll_put_char = s3c24xx_serial_put_poll_char,
+#endif
 };
 
 static struct uart_driver s3c24xx_uart_drv = {
@@ -1316,6 +1333,36 @@ s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon)
        return (utrstat & S3C2410_UTRSTAT_TXE) ? 1 : 0;
 }
 
+#ifdef CONFIG_CONSOLE_POLL
+/*
+ * Console polling routines for writing and reading from the uart while
+ * in an interrupt or debug context.
+ */
+
+static int s3c24xx_serial_get_poll_char(struct uart_port *port)
+{
+       struct s3c24xx_uart_port *ourport = to_ourport(port);
+       unsigned int ufstat;
+
+       ufstat = rd_regl(port, S3C2410_UFSTAT);
+       if (s3c24xx_serial_rx_fifocnt(ourport, ufstat) == 0)
+               return NO_POLL_CHAR;
+
+       return rd_regb(port, S3C2410_URXH);
+}
+
+static void s3c24xx_serial_put_poll_char(struct uart_port *port,
+               unsigned char c)
+{
+       unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON);
+
+       while (!s3c24xx_serial_console_txrdy(port, ufcon))
+               cpu_relax();
+       wr_regb(cons_uart, S3C2410_UTXH, c);
+}
+
+#endif /* CONFIG_CONSOLE_POLL */
+
 static void
 s3c24xx_serial_console_putchar(struct uart_port *port, int ch)
 {