serial: meson: add Magic SysRq support
authorYixun Lan <dlan@gentoo.org>
Wed, 6 Sep 2017 13:52:39 +0000 (21:52 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 18 Sep 2017 16:31:48 +0000 (18:31 +0200)
This dirver try to implement the Magic SysRq support[1] for
Amlogic Inc's meson platfo
>From the hardware perspective, the UART IP can't detect the 'BREAK' command
clearly via the status register. Instead, we rely on the combination of
'FRAME_ERR bit && ch == 0', and it works fine.

[1] Documentation/admin-guide/sysrq.rst

Signed-off-by: Yixun Lan <dlan@gentoo.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/tty/serial/meson_uart.c

index 07c0f98..95d242a 100644 (file)
  *
  */
 
+#if defined(CONFIG_SERIAL_MESON_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
 #include <linux/clk.h>
 #include <linux/console.h>
 #include <linux/delay.h>
@@ -183,12 +187,12 @@ static void meson_receive_chars(struct uart_port *port)
 {
        struct tty_port *tport = &port->state->port;
        char flag;
-       u32 status, ch, mode;
+       u32 ostatus, status, ch, mode;
 
        do {
                flag = TTY_NORMAL;
                port->icount.rx++;
-               status = readl(port->membase + AML_UART_STATUS);
+               ostatus = status = readl(port->membase + AML_UART_STATUS);
 
                if (status & AML_UART_ERR) {
                        if (status & AML_UART_TX_FIFO_WERR)
@@ -216,6 +220,16 @@ static void meson_receive_chars(struct uart_port *port)
                ch = readl(port->membase + AML_UART_RFIFO);
                ch &= 0xff;
 
+               if ((ostatus & AML_UART_FRAME_ERR) && (ch == 0)) {
+                       port->icount.brk++;
+                       flag = TTY_BREAK;
+                       if (uart_handle_break(port))
+                               continue;
+               }
+
+               if (uart_handle_sysrq_char(port, ch))
+                       continue;
+
                if ((status & port->ignore_status_mask) == 0)
                        tty_insert_flip_char(tport, ch, flag);