tty: serial: owl: Add support for kernel debugger
authorCristian Ciocaltea <cristian.ciocaltea@gmail.com>
Tue, 12 Jan 2021 20:55:38 +0000 (22:55 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 13 Jan 2021 16:16:54 +0000 (17:16 +0100)
Implement 'poll_put_char' and 'poll_get_char' callbacks in struct
'owl_uart_ops' that enables OWL UART to be used for kernel debugging
over serial line.

Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@gmail.com>
Link: https://lore.kernel.org/r/026543195b9aeefb339d90abc5660a6ac7463c63.1610484108.git.cristian.ciocaltea@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/tty/serial/owl-uart.c

index c149f8c..abc6042 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/console.h>
 #include <linux/delay.h>
 #include <linux/io.h>
+#include <linux/iopoll.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
@@ -62,6 +63,9 @@
 #define OWL_UART_STAT_TRFL_MASK                GENMASK(16, 11)
 #define OWL_UART_STAT_UTBB             BIT(17)
 
+#define OWL_UART_POLL_USEC             5
+#define OWL_UART_TIMEOUT_USEC          10000
+
 static struct uart_driver owl_uart_driver;
 
 struct owl_uart_info {
@@ -461,6 +465,36 @@ static void owl_uart_config_port(struct uart_port *port, int flags)
        }
 }
 
+#ifdef CONFIG_CONSOLE_POLL
+
+static int owl_uart_poll_get_char(struct uart_port *port)
+{
+       if (owl_uart_read(port, OWL_UART_STAT) & OWL_UART_STAT_RFEM)
+               return NO_POLL_CHAR;
+
+       return owl_uart_read(port, OWL_UART_RXDAT);
+}
+
+static void owl_uart_poll_put_char(struct uart_port *port, unsigned char ch)
+{
+       u32 reg;
+       int ret;
+
+       /* Wait while FIFO is full or timeout */
+       ret = readl_poll_timeout_atomic(port->membase + OWL_UART_STAT, reg,
+                                       !(reg & OWL_UART_STAT_TFFU),
+                                       OWL_UART_POLL_USEC,
+                                       OWL_UART_TIMEOUT_USEC);
+       if (ret == -ETIMEDOUT) {
+               dev_err(port->dev, "Timeout waiting while UART TX FULL\n");
+               return;
+       }
+
+       owl_uart_write(port, ch, OWL_UART_TXDAT);
+}
+
+#endif /* CONFIG_CONSOLE_POLL */
+
 static const struct uart_ops owl_uart_ops = {
        .set_mctrl = owl_uart_set_mctrl,
        .get_mctrl = owl_uart_get_mctrl,
@@ -476,6 +510,10 @@ static const struct uart_ops owl_uart_ops = {
        .request_port = owl_uart_request_port,
        .release_port = owl_uart_release_port,
        .verify_port = owl_uart_verify_port,
+#ifdef CONFIG_CONSOLE_POLL
+       .poll_get_char = owl_uart_poll_get_char,
+       .poll_put_char = owl_uart_poll_put_char,
+#endif
 };
 
 #ifdef CONFIG_SERIAL_OWL_CONSOLE