static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
 {
        unsigned int control = 0;
-       unsigned int mode;
+       unsigned int mode = UART_GET_MR(port);
+       unsigned int rts_paused, rts_ready;
        struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 
+       /* override mode to RS485 if needed, otherwise keep the current mode */
+       if (port->rs485.flags & SER_RS485_ENABLED) {
+               if ((port->rs485.delay_rts_after_send) > 0)
+                       UART_PUT_TTGR(port, port->rs485.delay_rts_after_send);
+               mode &= ~ATMEL_US_USMODE;
+               mode |= ATMEL_US_USMODE_RS485;
+       }
+
+       /* set the RTS line state according to the mode */
+       if ((mode & ATMEL_US_USMODE) == ATMEL_US_USMODE_HWHS) {
+               /* force RTS line to high level */
+               rts_paused = ATMEL_US_RTSEN;
+
+               /* give the control of the RTS line back to the hardware */
+               rts_ready = ATMEL_US_RTSDIS;
+       } else {
+               /* force RTS line to high level */
+               rts_paused = ATMEL_US_RTSDIS;
+
+               /* force RTS line to low level */
+               rts_ready = ATMEL_US_RTSEN;
+       }
+
        if (mctrl & TIOCM_RTS)
-               control |= ATMEL_US_RTSEN;
+               control |= rts_ready;
        else
-               control |= ATMEL_US_RTSDIS;
+               control |= rts_paused;
 
        if (mctrl & TIOCM_DTR)
                control |= ATMEL_US_DTREN;
        mctrl_gpio_set(atmel_port->gpios, mctrl);
 
        /* Local loopback mode? */
-       mode = UART_GET_MR(port) & ~ATMEL_US_CHMODE;
+       mode &= ~ATMEL_US_CHMODE;
        if (mctrl & TIOCM_LOOP)
                mode |= ATMEL_US_CHMODE_LOC_LOOP;
        else
                mode |= ATMEL_US_CHMODE_NORMAL;
 
-       /* Resetting serial mode to RS232 (0x0) */
-       mode &= ~ATMEL_US_USMODE;
-
-       if (port->rs485.flags & SER_RS485_ENABLED) {
-               dev_dbg(port->dev, "Setting UART to RS485\n");
-               if ((port->rs485.delay_rts_after_send) > 0)
-                       UART_PUT_TTGR(port, port->rs485.delay_rts_after_send);
-               mode |= ATMEL_US_USMODE_RS485;
-       } else {
-               dev_dbg(port->dev, "Setting UART to RS232\n");
-       }
        UART_PUT_MR(port, mode);
 }
 
                              struct ktermios *old)
 {
        unsigned long flags;
-       unsigned int mode, imr, quot, baud;
+       unsigned int old_mode, mode, imr, quot, baud;
+
+       /* save the current mode register */
+       mode = old_mode = UART_GET_MR(port);
 
-       /* Get current mode register */
-       mode = UART_GET_MR(port) & ~(ATMEL_US_USCLKS | ATMEL_US_CHRL
-                                       | ATMEL_US_NBSTOP | ATMEL_US_PAR
-                                       | ATMEL_US_USMODE);
+       /* reset the mode, clock divisor, parity, stop bits and data size */
+       mode &= ~(ATMEL_US_USCLKS | ATMEL_US_CHRL | ATMEL_US_NBSTOP |
+                 ATMEL_US_PAR | ATMEL_US_USMODE);
 
        baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
        quot = uart_get_divisor(port, baud);
        } else
                mode |= ATMEL_US_PAR_NONE;
 
-       /* hardware handshake (RTS/CTS) */
-       if (termios->c_cflag & CRTSCTS)
-               mode |= ATMEL_US_USMODE_HWHS;
-       else
-               mode |= ATMEL_US_USMODE_NORMAL;
-
        spin_lock_irqsave(&port->lock, flags);
 
        port->read_status_mask = ATMEL_US_OVRE;
        /* disable receiver and transmitter */
        UART_PUT_CR(port, ATMEL_US_TXDIS | ATMEL_US_RXDIS);
 
-       /* Resetting serial mode to RS232 (0x0) */
-       mode &= ~ATMEL_US_USMODE;
-
+       /* mode */
        if (port->rs485.flags & SER_RS485_ENABLED) {
                if ((port->rs485.delay_rts_after_send) > 0)
                        UART_PUT_TTGR(port, port->rs485.delay_rts_after_send);
                mode |= ATMEL_US_USMODE_RS485;
+       } else if (termios->c_cflag & CRTSCTS) {
+               /* RS232 with hardware handshake (RTS/CTS) */
+               mode |= ATMEL_US_USMODE_HWHS;
+       } else {
+               /* RS232 without hadware handshake */
+               mode |= ATMEL_US_USMODE_NORMAL;
        }
 
-       /* set the parity, stop bits and data size */
+       /* set the mode, clock divisor, parity, stop bits and data size */
        UART_PUT_MR(port, mode);
 
+       /*
+        * when switching the mode, set the RTS line state according to the
+        * new mode, otherwise keep the former state
+        */
+       if ((old_mode & ATMEL_US_USMODE) != (mode & ATMEL_US_USMODE)) {
+               unsigned int rts_state;
+
+               if ((mode & ATMEL_US_USMODE) == ATMEL_US_USMODE_HWHS) {
+                       /* let the hardware control the RTS line */
+                       rts_state = ATMEL_US_RTSDIS;
+               } else {
+                       /* force RTS line to low level */
+                       rts_state = ATMEL_US_RTSEN;
+               }
+
+               UART_PUT_CR(port, rts_state);
+       }
+
        /* set the baud rate */
        UART_PUT_BRGR(port, quot);
        UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);