SERIAL: omap: remove 'irq_pending' bitfield
[firefly-linux-kernel-4.4.55.git] / drivers / tty / serial / omap-serial.c
index 6ede6fd92b4cd00e939dca479e0f3e3a0a0d923e..da46be3d57b1fe31f2c64dbcb90e79d910c9896c 100644 (file)
@@ -99,7 +99,6 @@ struct uart_omap_port {
        u32                     context_loss_cnt;
        u32                     errata;
        u8                      wakeups_enabled;
-       unsigned int            irq_pending:1;
 
        int                     DTR_gpio;
        int                     DTR_inverted;
@@ -504,7 +503,7 @@ static unsigned int serial_omap_get_mctrl(struct uart_port *port)
 static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
 {
        struct uart_omap_port *up = to_uart_omap_port(port);
-       unsigned char mcr = 0;
+       unsigned char mcr = 0, old_mcr;
 
        dev_dbg(up->port.dev, "serial_omap_set_mctrl+%d\n", up->port.line);
        if (mctrl & TIOCM_RTS)
@@ -519,8 +518,10 @@ static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
                mcr |= UART_MCR_LOOP;
 
        pm_runtime_get_sync(up->dev);
-       up->mcr = serial_in(up, UART_MCR);
-       up->mcr |= mcr;
+       old_mcr = serial_in(up, UART_MCR);
+       old_mcr &= ~(UART_MCR_LOOP | UART_MCR_OUT2 | UART_MCR_OUT1 |
+                    UART_MCR_DTR | UART_MCR_RTS);
+       up->mcr = old_mcr | mcr;
        serial_out(up, UART_MCR, up->mcr);
        pm_runtime_mark_last_busy(up->dev);
        pm_runtime_put_autosuspend(up->dev);
@@ -671,19 +672,19 @@ serial_omap_configure_xonxoff
 
        /*
         * IXON Flag:
-        * Flow control for OMAP.TX
-        * OMAP.RX should listen for XON/XOFF
+        * Enable XON/XOFF flow control on output.
+        * Transmit XON1, XOFF1
         */
        if (termios->c_iflag & IXON)
-               up->efr |= OMAP_UART_SW_RX;
+               up->efr |= OMAP_UART_SW_TX;
 
        /*
         * IXOFF Flag:
-        * Flow control for OMAP.RX
-        * OMAP.TX should send XON/XOFF
+        * Enable XON/XOFF flow control on input.
+        * Receiver compares XON1, XOFF1.
         */
        if (termios->c_iflag & IXOFF)
-               up->efr |= OMAP_UART_SW_TX;
+               up->efr |= OMAP_UART_SW_RX;
 
        serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
        serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
@@ -698,18 +699,16 @@ serial_omap_configure_xonxoff
         */
        if (termios->c_iflag & IXANY)
                up->mcr |= UART_MCR_XONANY;
+       else
+               up->mcr &= ~UART_MCR_XONANY;
 
        serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
        serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
        serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_TRIG);
-       /* Enable special char function UARTi.EFR_REG[5] and
-        * load the new software flow control mode IXON or IXOFF
-        * and restore the UARTi.EFR_REG[4] ENHANCED_EN value.
-        */
-       serial_out(up, UART_EFR, up->efr | UART_EFR_SCD);
        serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
-
        serial_out(up, UART_MCR, up->mcr & ~UART_MCR_TCRTLR);
+       serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+       serial_out(up, UART_EFR, up->efr);
        serial_out(up, UART_LCR, up->lcr);
 }
 
@@ -730,7 +729,6 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
 {
        struct uart_omap_port *up = to_uart_omap_port(port);
        unsigned char cval = 0;
-       unsigned char efr = 0;
        unsigned long flags = 0;
        unsigned int baud, quot;
 
@@ -840,11 +838,12 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
 
        serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
 
-       up->efr = serial_in(up, UART_EFR);
+       up->efr = serial_in(up, UART_EFR) & ~UART_EFR_ECB;
+       up->efr &= ~UART_EFR_SCD;
        serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
 
        serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
-       up->mcr = serial_in(up, UART_MCR);
+       up->mcr = serial_in(up, UART_MCR) & ~UART_MCR_TCRTLR;
        serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
        /* FIFO ENABLE, DMA MODE */
 
@@ -863,9 +862,12 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
 
        serial_out(up, UART_OMAP_SCR, up->scr);
 
-       serial_out(up, UART_EFR, up->efr);
+       /* Reset UART_MCR_TCRTLR: this must be done with the EFR_ECB bit set */
        serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
        serial_out(up, UART_MCR, up->mcr);
+       serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+       serial_out(up, UART_EFR, up->efr);
+       serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
 
        /* Protocol, Baud Rate, and Interrupt Settings */
 
@@ -875,8 +877,6 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
                serial_out(up, UART_OMAP_MDR1, up->mdr1);
 
        serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
-
-       up->efr = serial_in(up, UART_EFR);
        serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
 
        serial_out(up, UART_LCR, 0);
@@ -905,27 +905,36 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
 
        /* Hardware Flow Control Configuration */
 
-       if (termios->c_cflag & CRTSCTS) {
-               efr |= (UART_EFR_CTS | UART_EFR_RTS);
-               serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
-
-               up->mcr = serial_in(up, UART_MCR);
-               serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
-
+       if (termios->c_cflag & CRTSCTS && up->port.flags & UPF_HARD_FLOW) {
+               /* Enable access to TCR/TLR */
                serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
-               up->efr = serial_in(up, UART_EFR);
                serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
+               serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
+               serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
 
                serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_TRIG);
-               serial_out(up, UART_EFR, efr); /* Enable AUTORTS and AUTOCTS */
-               serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
+
+               /* Enable AUTORTS and AUTOCTS */
+               up->efr |= UART_EFR_CTS | UART_EFR_RTS;
+
+               /* Disable access to TCR/TLR */
                serial_out(up, UART_MCR, up->mcr | UART_MCR_RTS);
+               serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+               serial_out(up, UART_EFR, up->efr);
+               serial_out(up, UART_LCR, cval);
+       } else {
+               /* Disable AUTORTS and AUTOCTS */
+               up->efr &= ~(UART_EFR_CTS | UART_EFR_RTS);
+
+               serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+               serial_out(up, UART_EFR, up->efr);
                serial_out(up, UART_LCR, cval);
        }
 
        serial_omap_set_mctrl(&up->port, up->port.mctrl);
        /* Software Flow Control Configuration */
-       serial_omap_configure_xonxoff(up, termios);
+       if (up->port.flags & UPF_SOFT_FLOW)
+               serial_omap_configure_xonxoff(up, termios);
 
        spin_unlock_irqrestore(&up->port.lock, flags);
        pm_runtime_mark_last_busy(up->dev);