tty: 8250: Add 64byte UART support for FSL platforms
[firefly-linux-kernel-4.4.55.git] / drivers / tty / serial / 8250 / 8250_core.c
index 9515924b7f38a431ab114e8bdf7e9db0230b5ecf..689169c11f0fc4153ad2a5e45d840a1712440faf 100644 (file)
@@ -329,6 +329,17 @@ static const struct serial8250_config uart_config[] = {
                .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
                .flags          = UART_CAP_FIFO | UART_CAP_AFE,
        },
+/* tx_loadsz is set to 63-bytes instead of 64-bytes to implement
+workaround of errata A-008006 which states that tx_loadsz should  be
+configured less than Maximum supported fifo bytes */
+       [PORT_16550A_FSL64] = {
+               .name           = "16550A_FSL64",
+               .fifo_size      = 64,
+               .tx_loadsz      = 63,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 |
+                                 UART_FCR7_64BYTE,
+               .flags          = UART_CAP_FIFO,
+       },
 };
 
 /* Uart divisor latch read */
@@ -956,7 +967,17 @@ static void autoconfig_16550a(struct uart_8250_port *up)
                        up->port.type = PORT_16650;
                        up->capabilities |= UART_CAP_EFR | UART_CAP_SLEEP;
                } else {
-                       DEBUG_AUTOCONF("Motorola 8xxx DUART ");
+                       serial_out(up, UART_LCR, 0);
+                       serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
+                                  UART_FCR7_64BYTE);
+                       status1 = serial_in(up, UART_IIR) >> 5;
+                       serial_out(up, UART_FCR, 0);
+                       serial_out(up, UART_LCR, 0);
+
+                       if (status1 == 7)
+                               up->port.type = PORT_16550A_FSL64;
+                       else
+                               DEBUG_AUTOCONF("Motorola 8xxx DUART ");
                }
                serial_out(up, UART_EFR, 0);
                return;
@@ -1924,7 +1945,7 @@ static unsigned int serial8250_get_mctrl(struct uart_port *port)
        return ret;
 }
 
-static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
+void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl)
 {
        struct uart_8250_port *up = up_to_u8250p(port);
        unsigned char mcr = 0;
@@ -1944,6 +1965,14 @@ static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
 
        serial_port_out(port, UART_MCR, mcr);
 }
+EXPORT_SYMBOL_GPL(serial8250_do_set_mctrl);
+
+static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+       if (port->set_mctrl)
+               return port->set_mctrl(port, mctrl);
+       return serial8250_do_set_mctrl(port, mctrl);
+}
 
 static void serial8250_break_ctl(struct uart_port *port, int break_state)
 {
@@ -3483,7 +3512,6 @@ static struct platform_driver serial8250_isa_driver = {
        .resume         = serial8250_resume,
        .driver         = {
                .name   = "serial8250",
-               .owner  = THIS_MODULE,
        },
 };
 
@@ -3606,6 +3634,8 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
                /*  Possibly override set_termios call */
                if (up->port.set_termios)
                        uart->port.set_termios = up->port.set_termios;
+               if (up->port.set_mctrl)
+                       uart->port.set_mctrl = up->port.set_mctrl;
                if (up->port.startup)
                        uart->port.startup = up->port.startup;
                if (up->port.shutdown)