tty: 8250: Add 64byte UART support for FSL platforms
[firefly-linux-kernel-4.4.55.git] / drivers / tty / serial / 8250 / 8250_core.c
index ca5cfdc1459a61ca407f9888cbe20d50e33b71b3..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 */
@@ -541,23 +552,25 @@ void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p)
 }
 EXPORT_SYMBOL_GPL(serial8250_clear_and_reinit_fifos);
 
-static void serial8250_rpm_get(struct uart_8250_port *p)
+void serial8250_rpm_get(struct uart_8250_port *p)
 {
        if (!(p->capabilities & UART_CAP_RPM))
                return;
        pm_runtime_get_sync(p->port.dev);
 }
+EXPORT_SYMBOL_GPL(serial8250_rpm_get);
 
-static void serial8250_rpm_put(struct uart_8250_port *p)
+void serial8250_rpm_put(struct uart_8250_port *p)
 {
        if (!(p->capabilities & UART_CAP_RPM))
                return;
        pm_runtime_mark_last_busy(p->port.dev);
        pm_runtime_put_autosuspend(p->port.dev);
 }
+EXPORT_SYMBOL_GPL(serial8250_rpm_put);
 
 /*
- * This two wrapper ensure, that enable_runtime_pm_tx() can be called more than
+ * These two wrappers ensure that enable_runtime_pm_tx() can be called more than
  * once and disable_runtime_pm_tx() will still disable RPM because the fifo is
  * empty and the HW can idle again.
  */
@@ -595,6 +608,7 @@ static void serial8250_rpm_put_tx(struct uart_8250_port *p)
  */
 static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
 {
+       unsigned char lcr = 0, efr = 0;
        /*
         * Exar UARTs have a SLEEP register that enables or disables
         * each UART to enter sleep mode separately.  On the XR17V35x the
@@ -611,6 +625,8 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
 
        if (p->capabilities & UART_CAP_SLEEP) {
                if (p->capabilities & UART_CAP_EFR) {
+                       lcr = serial_in(p, UART_LCR);
+                       efr = serial_in(p, UART_EFR);
                        serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B);
                        serial_out(p, UART_EFR, UART_EFR_ECB);
                        serial_out(p, UART_LCR, 0);
@@ -618,8 +634,8 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
                serial_out(p, UART_IER, sleep ? UART_IERX_SLEEP : 0);
                if (p->capabilities & UART_CAP_EFR) {
                        serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B);
-                       serial_out(p, UART_EFR, 0);
-                       serial_out(p, UART_LCR, 0);
+                       serial_out(p, UART_EFR, efr);
+                       serial_out(p, UART_LCR, lcr);
                }
        }
 out:
@@ -951,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;
@@ -1350,7 +1376,7 @@ static void serial8250_start_tx(struct uart_port *port)
        struct uart_8250_port *up = up_to_u8250p(port);
 
        serial8250_rpm_get_tx(up);
-       if (up->dma && !serial8250_tx_dma(up)) {
+       if (up->dma && !up->dma->tx_dma(up)) {
                return;
        } else if (!(up->ier & UART_IER_THRI)) {
                up->ier |= UART_IER_THRI;
@@ -1397,6 +1423,19 @@ static void serial8250_stop_rx(struct uart_port *port)
        serial8250_rpm_put(up);
 }
 
+static void serial8250_disable_ms(struct uart_port *port)
+{
+       struct uart_8250_port *up =
+               container_of(port, struct uart_8250_port, port);
+
+       /* no MSR capabilities */
+       if (up->bugs & UART_BUG_NOMSR)
+               return;
+
+       up->ier &= ~UART_IER_MSI;
+       serial_port_out(port, UART_IER, up->ier);
+}
+
 static void serial8250_enable_ms(struct uart_port *port)
 {
        struct uart_8250_port *up = up_to_u8250p(port);
@@ -1483,7 +1522,7 @@ serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr)
 
 ignore_char:
                lsr = serial_in(up, UART_LSR);
-       } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (max_count-- > 0));
+       } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (--max_count > 0));
        spin_unlock(&port->lock);
        tty_flip_buffer_push(&port->state->port);
        spin_lock(&port->lock);
@@ -1532,7 +1571,7 @@ void serial8250_tx_chars(struct uart_8250_port *up)
        DEBUG_INTR("THRE...");
 
        /*
-        * With RPM enabled, we have to wait once the FIFO is empty before the
+        * With RPM enabled, we have to wait until the FIFO is empty before the
         * HW can go idle. So we get here once again with empty FIFO and disable
         * the interrupt and RPM in __stop_tx()
         */
@@ -1588,13 +1627,14 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
 
        if (status & (UART_LSR_DR | UART_LSR_BI)) {
                if (up->dma)
-                       dma_err = serial8250_rx_dma(up, iir);
+                       dma_err = up->dma->rx_dma(up, iir);
 
                if (!up->dma || dma_err)
                        status = serial8250_rx_chars(up, status);
        }
        serial8250_modem_status(up);
-       if (!up->dma && (status & UART_LSR_THRE))
+       if ((!up->dma || (up->dma && up->dma->tx_err)) &&
+           (status & UART_LSR_THRE))
                serial8250_tx_chars(up);
 
        spin_unlock_irqrestore(&port->lock, flags);
@@ -1905,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;
@@ -1925,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)
 {
@@ -2603,13 +2651,21 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
 }
 
 static void
-serial8250_set_ldisc(struct uart_port *port, int new)
+serial8250_set_ldisc(struct uart_port *port, struct ktermios *termios)
 {
-       if (new == N_PPS) {
+       if (termios->c_line == N_PPS) {
                port->flags |= UPF_HARDPPS_CD;
+               spin_lock_irq(&port->lock);
                serial8250_enable_ms(port);
-       } else
+               spin_unlock_irq(&port->lock);
+       } else {
                port->flags &= ~UPF_HARDPPS_CD;
+               if (!UART_ENABLE_MS(port, termios->c_cflag)) {
+                       spin_lock_irq(&port->lock);
+                       serial8250_disable_ms(port);
+                       spin_unlock_irq(&port->lock);
+               }
+       }
 }
 
 
@@ -2634,8 +2690,11 @@ serial8250_pm(struct uart_port *port, unsigned int state,
 
 static unsigned int serial8250_port_size(struct uart_8250_port *pt)
 {
-       if (pt->port.iotype == UPIO_AU)
+       if (pt->port.iotype == UPIO_AU) {
+               if (pt->port.type == PORT_RT2880)
+                       return 0x100;
                return 0x1000;
+       }
        if (is_omap1_8250(pt))
                return 0x16 << pt->port.regshift;
 
@@ -2975,42 +3034,6 @@ serial8250_verify_port(struct uart_port *port, struct serial_struct *ser)
        return 0;
 }
 
-static int serial8250_ioctl(struct uart_port *port, unsigned int cmd,
-                          unsigned long arg)
-{
-       struct uart_8250_port *up =
-               container_of(port, struct uart_8250_port, port);
-       int ret;
-       struct serial_rs485 rs485_config;
-
-       if (!up->rs485_config)
-               return -ENOIOCTLCMD;
-
-       switch (cmd) {
-       case TIOCSRS485:
-               if (copy_from_user(&rs485_config, (void __user *)arg,
-                                  sizeof(rs485_config)))
-                       return -EFAULT;
-
-               ret = up->rs485_config(up, &rs485_config);
-               if (ret)
-                       return ret;
-
-               memcpy(&up->rs485, &rs485_config, sizeof(rs485_config));
-
-               return 0;
-       case TIOCGRS485:
-               if (copy_to_user((void __user *)arg, &up->rs485,
-                                sizeof(up->rs485)))
-                       return -EFAULT;
-               return 0;
-       default:
-               break;
-       }
-
-       return -ENOIOCTLCMD;
-}
-
 static const char *
 serial8250_type(struct uart_port *port)
 {
@@ -3042,7 +3065,6 @@ static struct uart_ops serial8250_pops = {
        .request_port   = serial8250_request_port,
        .config_port    = serial8250_config_port,
        .verify_port    = serial8250_verify_port,
-       .ioctl          = serial8250_ioctl,
 #ifdef CONFIG_CONSOLE_POLL
        .poll_get_char = serial8250_get_poll_char,
        .poll_put_char = serial8250_put_poll_char,
@@ -3198,7 +3220,9 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
 
        serial8250_rpm_get(up);
 
-       if (port->sysrq || oops_in_progress)
+       if (port->sysrq)
+               locked = 0;
+       else if (oops_in_progress)
                locked = spin_trylock_irqsave(&port->lock, flags);
        else
                spin_lock_irqsave(&port->lock, flags);
@@ -3237,7 +3261,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
        serial8250_rpm_put(up);
 }
 
-static int __init serial8250_console_setup(struct console *co, char *options)
+static int serial8250_console_setup(struct console *co, char *options)
 {
        struct uart_port *port;
        int baud = 9600;
@@ -3488,7 +3512,6 @@ static struct platform_driver serial8250_isa_driver = {
        .resume         = serial8250_resume,
        .driver         = {
                .name   = "serial8250",
-               .owner  = THIS_MODULE,
        },
 };
 
@@ -3585,10 +3608,10 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
                uart->port.fifosize     = up->port.fifosize;
                uart->tx_loadsz         = up->tx_loadsz;
                uart->capabilities      = up->capabilities;
-               uart->rs485_config      = up->rs485_config;
-               uart->rs485             = up->rs485;
                uart->port.throttle     = up->port.throttle;
                uart->port.unthrottle   = up->port.unthrottle;
+               uart->port.rs485_config = up->port.rs485_config;
+               uart->port.rs485        = up->port.rs485;
 
                /* Take tx_loadsz from fifosize if it wasn't set separately */
                if (uart->port.fifosize && !uart->tx_loadsz)
@@ -3611,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)
@@ -3623,8 +3648,13 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
                        uart->dl_read = up->dl_read;
                if (up->dl_write)
                        uart->dl_write = up->dl_write;
-               if (up->dma)
+               if (up->dma) {
                        uart->dma = up->dma;
+                       if (!uart->dma->tx_dma)
+                               uart->dma->tx_dma = serial8250_tx_dma;
+                       if (!uart->dma->rx_dma)
+                               uart->dma->rx_dma = serial8250_rx_dma;
+               }
 
                if (serial8250_isa_config != NULL)
                        serial8250_isa_config(0, &uart->port,