Merge 5.18-rc5 into tty-next
[linux-2.6-microblaze.git] / drivers / tty / serial / 8250 / 8250_port.c
index 3b12bfc..9b1d47e 100644 (file)
@@ -263,7 +263,7 @@ static const struct serial8250_config uart_config[] = {
                .tx_loadsz      = 63,
                .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 |
                                  UART_FCR7_64BYTE,
-               .flags          = UART_CAP_FIFO,
+               .flags          = UART_CAP_FIFO | UART_CAP_NOTEMT,
        },
        [PORT_RT2880] = {
                .name           = "Palmchip BK-3103",
@@ -307,6 +307,14 @@ static const struct serial8250_config uart_config[] = {
                .rxtrig_bytes   = {1, 32, 64, 112},
                .flags          = UART_CAP_FIFO | UART_CAP_SLEEP,
        },
+       [PORT_ASPEED_VUART] = {
+               .name           = "ASPEED VUART",
+               .fifo_size      = 16,
+               .tx_loadsz      = 16,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00,
+               .rxtrig_bytes   = {1, 4, 8, 14},
+               .flags          = UART_CAP_FIFO,
+       },
 };
 
 /* Uart divisor latch read */
@@ -1496,18 +1504,19 @@ static void start_hrtimer_ms(struct hrtimer *hrt, unsigned long msec)
        hrtimer_start(hrt, ms_to_ktime(msec), HRTIMER_MODE_REL);
 }
 
-static void __stop_tx_rs485(struct uart_8250_port *p)
+static void __stop_tx_rs485(struct uart_8250_port *p, u64 stop_delay)
 {
        struct uart_8250_em485 *em485 = p->em485;
 
+       stop_delay += (u64)p->port.rs485.delay_rts_after_send * NSEC_PER_MSEC;
+
        /*
         * rs485_stop_tx() is going to set RTS according to config
         * AND flush RX FIFO if required.
         */
-       if (p->port.rs485.delay_rts_after_send > 0) {
+       if (stop_delay > 0) {
                em485->active_timer = &em485->stop_tx_timer;
-               start_hrtimer_ms(&em485->stop_tx_timer,
-                                  p->port.rs485.delay_rts_after_send);
+               hrtimer_start(&em485->stop_tx_timer, ns_to_ktime(stop_delay), HRTIMER_MODE_REL);
        } else {
                p->rs485_stop_tx(p);
                em485->active_timer = NULL;
@@ -1527,16 +1536,32 @@ static inline void __stop_tx(struct uart_8250_port *p)
 
        if (em485) {
                unsigned char lsr = serial_in(p, UART_LSR);
+               u64 stop_delay = 0;
+
+               if (!(lsr & UART_LSR_THRE))
+                       return;
                /*
                 * To provide required timeing and allow FIFO transfer,
                 * __stop_tx_rs485() must be called only when both FIFO and
-                * shift register are empty. It is for device driver to enable
-                * interrupt on TEMT.
+                * shift register are empty. The device driver should either
+                * enable interrupt on TEMT or set UART_CAP_NOTEMT that will
+                * enlarge stop_tx_timer by the tx time of one frame to cover
+                * for emptying of the shift register.
                 */
-               if ((lsr & BOTH_EMPTY) != BOTH_EMPTY)
-                       return;
+               if (!(lsr & UART_LSR_TEMT)) {
+                       if (!(p->capabilities & UART_CAP_NOTEMT))
+                               return;
+                       /*
+                        * RTS might get deasserted too early with the normal
+                        * frame timing formula. It seems to suggest THRE might
+                        * get asserted already during tx of the stop bit
+                        * rather than after it is fully sent.
+                        * Roughly estimate 1 extra bit here with / 7.
+                        */
+                       stop_delay = p->port.frame_time + DIV_ROUND_UP(p->port.frame_time, 7);
+               }
 
-               __stop_tx_rs485(p);
+               __stop_tx_rs485(p, stop_delay);
        }
        __do_stop_tx(p);
 }
@@ -1615,6 +1640,18 @@ static inline void start_tx_rs485(struct uart_port *port)
        struct uart_8250_port *up = up_to_u8250p(port);
        struct uart_8250_em485 *em485 = up->em485;
 
+       /*
+        * While serial8250_em485_handle_stop_tx() is a noop if
+        * em485->active_timer != &em485->stop_tx_timer, it might happen that
+        * the timer is still armed and triggers only after the current bunch of
+        * chars is send and em485->active_timer == &em485->stop_tx_timer again.
+        * So cancel the timer. There is still a theoretical race condition if
+        * the timer is already running and only comes around to check for
+        * em485->active_timer when &em485->stop_tx_timer is armed again.
+        */
+       if (em485->active_timer == &em485->stop_tx_timer)
+               hrtimer_try_to_cancel(&em485->stop_tx_timer);
+
        em485->active_timer = NULL;
 
        if (em485->tx_stopped) {
@@ -1655,6 +1692,9 @@ static void serial8250_start_tx(struct uart_port *port)
        struct uart_8250_port *up = up_to_u8250p(port);
        struct uart_8250_em485 *em485 = up->em485;
 
+       if (!port->x_char && uart_circ_empty(&port->state->xmit))
+               return;
+
        serial8250_rpm_get_tx(up);
 
        if (em485 &&
@@ -1799,9 +1839,7 @@ void serial8250_tx_chars(struct uart_8250_port *up)
        int count;
 
        if (port->x_char) {
-               serial_out(up, UART_TX, port->x_char);
-               port->icount.tx++;
-               port->x_char = 0;
+               uart_xchar_out(port, UART_TX);
                return;
        }
        if (uart_tx_stopped(port)) {
@@ -1927,9 +1965,12 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
                        status = serial8250_rx_chars(up, status);
        }
        serial8250_modem_status(up);
-       if ((!up->dma || up->dma->tx_err) && (status & UART_LSR_THRE) &&
-               (up->ier & UART_IER_THRI))
-               serial8250_tx_chars(up);
+       if ((status & UART_LSR_THRE) && (up->ier & UART_IER_THRI)) {
+               if (!up->dma || up->dma->tx_err)
+                       serial8250_tx_chars(up);
+               else
+                       __stop_tx(up);
+       }
 
        uart_unlock_and_check_sysrq_irqrestore(port, flags);
 
@@ -2056,10 +2097,7 @@ static void serial8250_break_ctl(struct uart_port *port, int break_state)
        serial8250_rpm_put(up);
 }
 
-/*
- *     Wait for transmitter & holding register to empty
- */
-static void wait_for_xmitr(struct uart_8250_port *up, int bits)
+static void wait_for_lsr(struct uart_8250_port *up, int bits)
 {
        unsigned int status, tmout = 10000;
 
@@ -2076,6 +2114,16 @@ static void wait_for_xmitr(struct uart_8250_port *up, int bits)
                udelay(1);
                touch_nmi_watchdog();
        }
+}
+
+/*
+ *     Wait for transmitter & holding register to empty
+ */
+static void wait_for_xmitr(struct uart_8250_port *up, int bits)
+{
+       unsigned int tmout;
+
+       wait_for_lsr(up, bits);
 
        /* Wait up to 1s for flow control if necessary */
        if (up->port.flags & UPF_CONS_FLOW) {
@@ -2582,21 +2630,7 @@ static unsigned char serial8250_compute_lcr(struct uart_8250_port *up,
 {
        unsigned char cval;
 
-       switch (c_cflag & CSIZE) {
-       case CS5:
-               cval = UART_LCR_WLEN5;
-               break;
-       case CS6:
-               cval = UART_LCR_WLEN6;
-               break;
-       case CS7:
-               cval = UART_LCR_WLEN7;
-               break;
-       default:
-       case CS8:
-               cval = UART_LCR_WLEN8;
-               break;
-       }
+       cval = UART_LCR_WLEN(tty_get_char_size(c_cflag));
 
        if (c_cflag & CSTOPB)
                cval |= UART_LCR_STOP;
@@ -3296,7 +3330,7 @@ EXPORT_SYMBOL_GPL(serial8250_set_defaults);
 
 #ifdef CONFIG_SERIAL_8250_CONSOLE
 
-static void serial8250_console_putchar(struct uart_port *port, int ch)
+static void serial8250_console_putchar(struct uart_port *port, unsigned char ch)
 {
        struct uart_8250_port *up = up_to_u8250p(port);
 
@@ -3322,7 +3356,36 @@ static void serial8250_console_restore(struct uart_8250_port *up)
 
        serial8250_set_divisor(port, baud, quot, frac);
        serial_port_out(port, UART_LCR, up->lcr);
-       serial8250_out_MCR(up, UART_MCR_DTR | UART_MCR_RTS);
+       serial8250_out_MCR(up, up->mcr | UART_MCR_DTR | UART_MCR_RTS);
+}
+
+/*
+ * Print a string to the serial port using the device FIFO
+ *
+ * It sends fifosize bytes and then waits for the fifo
+ * to get empty.
+ */
+static void serial8250_console_fifo_write(struct uart_8250_port *up,
+                                         const char *s, unsigned int count)
+{
+       int i;
+       const char *end = s + count;
+       unsigned int fifosize = up->tx_loadsz;
+       bool cr_sent = false;
+
+       while (s != end) {
+               wait_for_lsr(up, UART_LSR_THRE);
+
+               for (i = 0; i < fifosize && s != end; ++i) {
+                       if (*s == '\n' && !cr_sent) {
+                               serial_out(up, UART_TX, '\r');
+                               cr_sent = true;
+                       } else {
+                               serial_out(up, UART_TX, *s++);
+                               cr_sent = false;
+                       }
+               }
+       }
 }
 
 /*
@@ -3340,7 +3403,7 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s,
        struct uart_8250_em485 *em485 = up->em485;
        struct uart_port *port = &up->port;
        unsigned long flags;
-       unsigned int ier;
+       unsigned int ier, use_fifo;
        int locked = 1;
 
        touch_nmi_watchdog();
@@ -3372,7 +3435,30 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s,
                mdelay(port->rs485.delay_rts_before_send);
        }
 
-       uart_console_write(port, s, count, serial8250_console_putchar);
+       use_fifo = (up->capabilities & UART_CAP_FIFO) &&
+               /*
+                * BCM283x requires to check the fifo
+                * after each byte.
+                */
+               !(up->capabilities & UART_CAP_MINI) &&
+               /*
+                * tx_loadsz contains the transmit fifo size
+                */
+               up->tx_loadsz > 1 &&
+               (up->fcr & UART_FCR_ENABLE_FIFO) &&
+               port->state &&
+               test_bit(TTY_PORT_INITIALIZED, &port->state->port.iflags) &&
+               /*
+                * After we put a data in the fifo, the controller will send
+                * it regardless of the CTS state. Therefore, only use fifo
+                * if we don't use control flow.
+                */
+               !(up->port.flags & UPF_CONS_FLOW);
+
+       if (likely(use_fifo))
+               serial8250_console_fifo_write(up, s, count);
+       else
+               uart_console_write(port, s, count, serial8250_console_putchar);
 
        /*
         *      Finally, wait for transmitter to become empty