Merge 5.18-rc5 into tty-next
[linux-2.6-microblaze.git] / drivers / tty / serial / 8250 / 8250_port.c
index 1fbd5bf..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",
@@ -1504,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;
@@ -1535,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);
 }
@@ -1948,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);
 
@@ -2077,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;
 
@@ -2097,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) {
@@ -3332,6 +3359,35 @@ static void serial8250_console_restore(struct uart_8250_port *up)
        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;
+                       }
+               }
+       }
+}
+
 /*
  *     Print a string to the serial port trying not to disturb
  *     any possible real use of the port...
@@ -3347,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();
@@ -3379,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